// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "services/network/cors/preflight_controller.h"

#include <algorithm>
#include <vector>

#include "base/bind.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
#include "services/network/public/cpp/cors/cors.h"
#include "services/network/public/cpp/cors/cors_error_status.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "url/gurl.h"

namespace network {

namespace cors {

namespace {

base::Optional<std::string> GetHeaderString(
    const scoped_refptr<net::HttpResponseHeaders>& headers,
    const std::string& header_name) {
  std::string header_value;
  if (!headers->GetNormalizedHeader(header_name, &header_value))
    return base::nullopt;
  return header_value;
}

// Algorithm step 3 of the CORS-preflight fetch,
// https://fetch.spec.whatwg.org/#cors-preflight-fetch-0, that requires
//  - CORS-safelisted request-headers excluded
//  - duplicates excluded
//  - sorted lexicographically
//  - byte-lowercased
std::string CreateAccessControlRequestHeadersHeader(
    const net::HttpRequestHeaders& headers) {
  std::vector<std::string> filtered_headers;
  for (const auto& header : headers.GetHeaderVector()) {
    // Exclude CORS-safelisted headers.
    if (cors::IsCORSSafelistedHeader(header.key, header.value))
      continue;
    // Exclude the forbidden headers because they may be added by the user
    // agent. They must be checked separately and rejected for
    // JavaScript-initiated requests.
    if (cors::IsForbiddenHeader(header.key))
      continue;
    filtered_headers.push_back(base::ToLowerASCII(header.key));
  }
  if (filtered_headers.empty())
    return std::string();

  // Sort header names lexicographically.
  std::sort(filtered_headers.begin(), filtered_headers.end());

  return base::JoinString(filtered_headers, ",");
}

std::unique_ptr<ResourceRequest> CreatePreflightRequest(
    const ResourceRequest& request,
    bool tainted) {
  DCHECK(!request.url.has_username());
  DCHECK(!request.url.has_password());

  std::unique_ptr<ResourceRequest> preflight_request =
      std::make_unique<ResourceRequest>();

  // Algorithm step 1 through 4 of the CORS-preflight fetch,
  // https://fetch.spec.whatwg.org/#cors-preflight-fetch-0.
  preflight_request->url = request.url;
  preflight_request->method = "OPTIONS";
  preflight_request->priority = request.priority;
  preflight_request->fetch_request_context_type =
      request.fetch_request_context_type;
  preflight_request->referrer = request.referrer;
  preflight_request->referrer_policy = request.referrer_policy;

  preflight_request->fetch_credentials_mode =
      mojom::FetchCredentialsMode::kOmit;
  preflight_request->load_flags |= net::LOAD_DO_NOT_SAVE_COOKIES;
  preflight_request->load_flags |= net::LOAD_DO_NOT_SEND_COOKIES;
  preflight_request->load_flags |= net::LOAD_DO_NOT_SEND_AUTH_DATA;

  preflight_request->headers.SetHeader(
      cors::header_names::kAccessControlRequestMethod, request.method);

  std::string request_headers =
      CreateAccessControlRequestHeadersHeader(request.headers);
  if (!request_headers.empty()) {
    preflight_request->headers.SetHeader(
        cors::header_names::kAccessControlRequestHeaders, request_headers);
  }

  if (request.is_external_request) {
    preflight_request->headers.SetHeader(
        cors::header_names::kAccessControlRequestExternal, "true");
  }

  DCHECK(request.request_initiator);
  preflight_request->request_initiator = request.request_initiator;
  preflight_request->headers.SetHeader(
      net::HttpRequestHeaders::kOrigin,
      (tainted ? url::Origin() : *request.request_initiator).Serialize());

  // TODO(toyoshim): Remove the following line once the network service is
  // enabled by default.
  preflight_request->skip_service_worker = true;

  // TODO(toyoshim): Should not matter, but at this moment, it hits a sanity
  // check in ResourceDispatcherHostImpl if |resource_type| isn't set.
  preflight_request->resource_type = request.resource_type;

  return preflight_request;
}

std::unique_ptr<PreflightResult> CreatePreflightResult(
    const GURL& final_url,
    const ResourceResponseHead& head,
    const ResourceRequest& original_request,
    bool tainted,
    base::Optional<CORSErrorStatus>* detected_error_status) {
  DCHECK(detected_error_status);

  // TODO(toyoshim): Reflect --allow-file-access-from-files flag.
  *detected_error_status = CheckPreflightAccess(
      final_url, head.headers->response_code(),
      GetHeaderString(head.headers,
                      cors::header_names::kAccessControlAllowOrigin),
      GetHeaderString(head.headers,
                      cors::header_names::kAccessControlAllowCredentials),
      original_request.fetch_credentials_mode,
      tainted ? url::Origin() : *original_request.request_initiator,
      false /* allow_file_origin */);
  if (*detected_error_status)
    return nullptr;

  base::Optional<mojom::CORSError> error;
  error = CheckPreflight(head.headers->response_code());
  if (error) {
    *detected_error_status = CORSErrorStatus(*error);
    return nullptr;
  }

  if (original_request.is_external_request) {
    *detected_error_status = CheckExternalPreflight(GetHeaderString(
        head.headers, header_names::kAccessControlAllowExternal));
    if (*detected_error_status)
      return nullptr;
  }

  auto result = PreflightResult::Create(
      original_request.fetch_credentials_mode,
      GetHeaderString(head.headers, header_names::kAccessControlAllowMethods),
      GetHeaderString(head.headers, header_names::kAccessControlAllowHeaders),
      GetHeaderString(head.headers, header_names::kAccessControlMaxAge),
      &error);

  if (error)
    *detected_error_status = CORSErrorStatus(*error);
  return result;
}

base::Optional<CORSErrorStatus> CheckPreflightResult(
    PreflightResult* result,
    const ResourceRequest& original_request) {
  base::Optional<mojom::CORSError> error =
      result->EnsureAllowedCrossOriginMethod(original_request.method);
  if (error)
    return CORSErrorStatus(*error, original_request.method);

  std::string detected_error_header;
  error = result->EnsureAllowedCrossOriginHeaders(original_request.headers,
                                                  &detected_error_header);
  if (error)
    return CORSErrorStatus(*error, detected_error_header);

  return base::nullopt;
}

// TODO(toyoshim): Remove this class once the Network Service is enabled.
// This wrapper class is used to tell the actual request's |request_id| to call
// CreateLoaderAndStart() for the legacy implementation that requires the ID
// to be unique while SimpleURLLoader always set it to 0.
class WrappedLegacyURLLoaderFactory final : public mojom::URLLoaderFactory {
 public:
  static WrappedLegacyURLLoaderFactory* GetSharedInstance() {
    static WrappedLegacyURLLoaderFactory factory;
    return &factory;
  }

  ~WrappedLegacyURLLoaderFactory() override = default;

  void SetFactoryAndRequestId(mojom::URLLoaderFactory* factory,
                              int32_t request_id) {
    factory_ = factory;
    request_id_ = request_id;
  }

  void CheckIdle() {
    DCHECK(!factory_);
    DCHECK_EQ(0, request_id_);
  }

  // mojom::URLLoaderFactory:
  void CreateLoaderAndStart(::network::mojom::URLLoaderRequest loader,
                            int32_t routing_id,
                            int32_t request_id,
                            uint32_t options,
                            const network::ResourceRequest& request,
                            ::network::mojom::URLLoaderClientPtr client,
                            const net::MutableNetworkTrafficAnnotationTag&
                                traffic_annotation) override {
    factory_->CreateLoaderAndStart(std::move(loader), routing_id, request_id_,
                                   options, request, std::move(client),
                                   traffic_annotation);
    factory_ = nullptr;
    request_id_ = 0;
  }

  void Clone(mojom::URLLoaderFactoryRequest factory) override {
    // Should not be called because retry logic is disabled to use
    // SimpleURLLoader. Could not work correctly by design.
    NOTREACHED();
  }

 private:
  mojom::URLLoaderFactory* factory_ = nullptr;
  int32_t request_id_ = 0;
};

}  // namespace

class PreflightController::PreflightLoader final {
 public:
  PreflightLoader(PreflightController* controller,
                  CompletionCallback completion_callback,
                  const ResourceRequest& request,
                  bool tainted,
                  const net::NetworkTrafficAnnotationTag& annotation_tag,
                  base::OnceCallback<void()> preflight_finalizer)
      : controller_(controller),
        completion_callback_(std::move(completion_callback)),
        original_request_(request),
        tainted_(tainted),
        preflight_finalizer_(std::move(preflight_finalizer)) {
    loader_ = SimpleURLLoader::Create(CreatePreflightRequest(request, tainted),
                                      annotation_tag);
  }

  void Request(mojom::URLLoaderFactory* loader_factory, int32_t request_id) {
    DCHECK(loader_);

    loader_->SetOnRedirectCallback(base::BindRepeating(
        &PreflightLoader::HandleRedirect, base::Unretained(this)));
    loader_->SetOnResponseStartedCallback(base::BindRepeating(
        &PreflightLoader::HandleResponseHeader, base::Unretained(this)));

    // TODO(toyoshim): Stop using WrappedLegacyURLLoaderFactory once the Network
    // Service is enabled by default. This is a workaround to use an allowed
    // request_id in the legacy URLLoaderFactory.
    WrappedLegacyURLLoaderFactory::GetSharedInstance()->SetFactoryAndRequestId(
        loader_factory, request_id);
    loader_->DownloadToString(
        WrappedLegacyURLLoaderFactory::GetSharedInstance(),
        base::BindOnce(&PreflightLoader::HandleResponseBody,
                       base::Unretained(this)),
        0);
    WrappedLegacyURLLoaderFactory::GetSharedInstance()->CheckIdle();
  }

 private:
  void HandleRedirect(const net::RedirectInfo& redirect_info,
                      const network::ResourceResponseHead& response_head,
                      std::vector<std::string>* to_be_removed_headers) {
    // Preflight should not allow any redirect.
    FinalizeLoader();

    std::move(completion_callback_)
        .Run(net::ERR_FAILED,
             CORSErrorStatus(mojom::CORSError::kPreflightDisallowedRedirect));

    RemoveFromController();
    // |this| is deleted here.
  }

  void HandleResponseHeader(const GURL& final_url,
                            const ResourceResponseHead& head) {
    FinalizeLoader();

    base::Optional<CORSErrorStatus> detected_error_status;
    std::unique_ptr<PreflightResult> result = CreatePreflightResult(
        final_url, head, original_request_, tainted_, &detected_error_status);

    if (result) {
      // Preflight succeeded. Check |original_request_| with |result|.
      DCHECK(!detected_error_status);
      detected_error_status =
          CheckPreflightResult(result.get(), original_request_);
    }

    // TODO(toyoshim): Check the spec if we cache |result| regardless of
    // following checks.
    if (!detected_error_status) {
      controller_->AppendToCache(*original_request_.request_initiator,
                                 original_request_.url, std::move(result));
    }

    std::move(completion_callback_)
        .Run(detected_error_status ? net::ERR_FAILED : net::OK,
             detected_error_status);

    RemoveFromController();
    // |this| is deleted here.
  }

  void HandleResponseBody(std::unique_ptr<std::string> response_body) {
    // Reached only when the request fails without receiving headers, e.g.
    // unknown hosts, unreachable remote, reset by peer, and so on.
    // See https://crbug.com/826868 for related discussion.
    DCHECK(!response_body);
    const int error = loader_->NetError();
    DCHECK_NE(error, net::OK);
    FinalizeLoader();
    std::move(completion_callback_).Run(error, base::nullopt);
    RemoveFromController();
    // |this| is deleted here.
  }

  void FinalizeLoader() {
    DCHECK(loader_);
    if (preflight_finalizer_)
      std::move(preflight_finalizer_).Run();
    loader_.reset();
  }

  // Removes |this| instance from |controller_|. Once the method returns, |this|
  // is already removed.
  void RemoveFromController() { controller_->RemoveLoader(this); }

  // PreflightController owns all PreflightLoader instances, and should outlive.
  PreflightController* const controller_;

  // Holds SimpleURLLoader instance for the CORS-preflight request.
  std::unique_ptr<SimpleURLLoader> loader_;

  // Holds caller's information.
  PreflightController::CompletionCallback completion_callback_;
  const ResourceRequest original_request_;

  const bool tainted_;

  // This is needed because we sometimes need to cancel the preflight loader
  // synchronously.
  // TODO(yhirano): Remove this when the network service is fully enabled.
  base::OnceCallback<void()> preflight_finalizer_;

  DISALLOW_COPY_AND_ASSIGN(PreflightLoader);
};

// static
std::unique_ptr<ResourceRequest>
PreflightController::CreatePreflightRequestForTesting(
    const ResourceRequest& request,
    bool tainted) {
  return CreatePreflightRequest(request, tainted);
}

// static
PreflightController* PreflightController::GetDefaultController() {
  static PreflightController controller;
  return &controller;
}

PreflightController::PreflightController() = default;

PreflightController::~PreflightController() = default;

void PreflightController::PerformPreflightCheck(
    CompletionCallback callback,
    int32_t request_id,
    const ResourceRequest& request,
    bool tainted,
    const net::NetworkTrafficAnnotationTag& annotation_tag,
    mojom::URLLoaderFactory* loader_factory,
    base::OnceCallback<void()> preflight_finalizer) {
  DCHECK(request.request_initiator);

  if (!request.is_external_request &&
      cache_.CheckIfRequestCanSkipPreflight(
          request.request_initiator->Serialize(), request.url,
          request.fetch_credentials_mode, request.method, request.headers)) {
    std::move(callback).Run(net::OK, base::nullopt);
    return;
  }

  auto emplaced_pair = loaders_.emplace(std::make_unique<PreflightLoader>(
      this, std::move(callback), request, tainted, annotation_tag,
      std::move(preflight_finalizer)));
  (*emplaced_pair.first)->Request(loader_factory, request_id);
}

void PreflightController::RemoveLoader(PreflightLoader* loader) {
  auto it = loaders_.find(loader);
  DCHECK(it != loaders_.end());
  loaders_.erase(it);
}

void PreflightController::AppendToCache(
    const url::Origin& origin,
    const GURL& url,
    std::unique_ptr<PreflightResult> result) {
  cache_.AppendEntry(origin.Serialize(), url, std::move(result));
}

}  // namespace cors

}  // namespace network
