// Copyright 2014 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 "content/browser/service_worker/service_worker_fetch_dispatcher.h"

#include <string>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/containers/queue.h"
#include "base/feature_list.h"
#include "base/task/post_task.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/service_worker_devtools_agent_host.h"
#include "content/browser/devtools/service_worker_devtools_manager.h"
#include "content/browser/loader/navigation_url_loader_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/loader/resource_requester_info.h"
#include "content/browser/loader/url_loader_factory_impl.h"
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/url_loader_factory_getter.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/navigation_policy.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/base/request_priority.h"
#include "net/http/http_util.h"
#include "net/log/net_log.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "services/network/throttling/throttling_controller.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"

namespace content {

namespace {

void NotifyNavigationPreloadRequestSentOnUI(
    const network::ResourceRequest& request,
    const std::pair<int, int>& worker_id,
    const std::string& request_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  ServiceWorkerDevToolsManager::GetInstance()->NavigationPreloadRequestSent(
      worker_id.first, worker_id.second, request_id, request);
}

void NotifyNavigationPreloadResponseReceivedOnUI(
    const GURL& url,
    scoped_refptr<network::ResourceResponse> response,
    const std::pair<int, int>& worker_id,
    const std::string& request_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  ServiceWorkerDevToolsManager::GetInstance()
      ->NavigationPreloadResponseReceived(worker_id.first, worker_id.second,
                                          request_id, url, response->head);
}

void NotifyNavigationPreloadCompletedOnUI(
    const network::URLLoaderCompletionStatus& status,
    const std::pair<int, int>& worker_id,
    const std::string& request_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  ServiceWorkerDevToolsManager::GetInstance()->NavigationPreloadCompleted(
      worker_id.first, worker_id.second, request_id, status);
}

// DelegatingURLLoaderClient is the URLLoaderClient for the navigation preload
// network request. It watches as the response comes in, and pipes the response
// back to the service worker while also doing extra processing like notifying
// DevTools.
class DelegatingURLLoaderClient final : public network::mojom::URLLoaderClient {
 public:
  using WorkerId = std::pair<int, int>;
  explicit DelegatingURLLoaderClient(network::mojom::URLLoaderClientPtr client,
                                     base::OnceClosure on_response,
                                     const network::ResourceRequest& request)
      : binding_(this),
        client_(std::move(client)),
        on_response_(std::move(on_response)),
        url_(request.url),
        devtools_enabled_(request.report_raw_headers) {
    if (!devtools_enabled_)
      return;
    AddDevToolsCallback(
        base::BindOnce(&NotifyNavigationPreloadRequestSentOnUI, request));
  }
  ~DelegatingURLLoaderClient() override {
    if (!completed_) {
      // Let the service worker know that the request has been canceled.
      network::URLLoaderCompletionStatus status;
      status.error_code = net::ERR_ABORTED;
      client_->OnComplete(status);
      if (!devtools_enabled_)
        return;
      AddDevToolsCallback(
          base::BindOnce(&NotifyNavigationPreloadCompletedOnUI, status));
    }
  }

  void MaybeReportToDevTools(WorkerId worker_id, int fetch_event_id) {
    worker_id_ = worker_id;
    devtools_request_id_ = base::StringPrintf("preload-%d", fetch_event_id);
    MaybeRunDevToolsCallbacks();
  }

  void OnUploadProgress(int64_t current_position,
                        int64_t total_size,
                        OnUploadProgressCallback ack_callback) override {
    client_->OnUploadProgress(current_position, total_size,
                              std::move(ack_callback));
  }
  void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {
    client_->OnReceiveCachedMetadata(data);
  }
  void OnTransferSizeUpdated(int32_t transfer_size_diff) override {
    client_->OnTransferSizeUpdated(transfer_size_diff);
  }
  void OnReceiveResponse(const network::ResourceResponseHead& head) override {
    client_->OnReceiveResponse(head);
    DCHECK(on_response_);
    std::move(on_response_).Run();
    if (!devtools_enabled_)
      return;
    // Make a deep copy of ResourceResponseHead before passing it cross-thread.
    auto resource_response = base::MakeRefCounted<network::ResourceResponse>();
    resource_response->head = head;
    AddDevToolsCallback(
        base::BindOnce(&NotifyNavigationPreloadResponseReceivedOnUI, url_,
                       resource_response->DeepCopy()));
  }
  void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
                         const network::ResourceResponseHead& head) override {
    completed_ = true;
    // When the server returns a redirect response, we only send
    // OnReceiveRedirect IPC and don't send OnComplete IPC. The service worker
    // will clean up the preload request when OnReceiveRedirect() is called.
    client_->OnReceiveRedirect(redirect_info, head);

    if (!devtools_enabled_)
      return;
    // Make a deep copy of ResourceResponseHead before passing it cross-thread.
    auto resource_response = base::MakeRefCounted<network::ResourceResponse>();
    resource_response->head = head;
    AddDevToolsCallback(
        base::BindOnce(&NotifyNavigationPreloadResponseReceivedOnUI, url_,
                       resource_response->DeepCopy()));
    network::URLLoaderCompletionStatus status;
    AddDevToolsCallback(
        base::BindOnce(&NotifyNavigationPreloadCompletedOnUI, status));
  }
  void OnStartLoadingResponseBody(
      mojo::ScopedDataPipeConsumerHandle body) override {
    client_->OnStartLoadingResponseBody(std::move(body));
  }
  void OnComplete(const network::URLLoaderCompletionStatus& status) override {
    if (completed_)
      return;
    completed_ = true;
    client_->OnComplete(status);
    if (!devtools_enabled_)
      return;
    AddDevToolsCallback(
        base::BindOnce(&NotifyNavigationPreloadCompletedOnUI, status));
  }

  void Bind(network::mojom::URLLoaderClientPtr* ptr_info) {
    binding_.Bind(mojo::MakeRequest(ptr_info));
  }

 private:
  void MaybeRunDevToolsCallbacks() {
    if (!worker_id_ || !devtools_enabled_)
      return;
    while (!devtools_callbacks.empty()) {
      base::PostTaskWithTraits(
          FROM_HERE, {BrowserThread::UI},
          base::BindOnce(std::move(devtools_callbacks.front()), *worker_id_,
                         devtools_request_id_));
      devtools_callbacks.pop();
    }
  }
  void AddDevToolsCallback(
      base::OnceCallback<void(const WorkerId&, const std::string&)> callback) {
    devtools_callbacks.push(std::move(callback));
    MaybeRunDevToolsCallbacks();
  }

  mojo::Binding<network::mojom::URLLoaderClient> binding_;
  network::mojom::URLLoaderClientPtr client_;
  base::OnceClosure on_response_;
  bool completed_ = false;
  const GURL url_;
  const bool devtools_enabled_;

  base::Optional<std::pair<int, int>> worker_id_;
  std::string devtools_request_id_;
  base::queue<base::OnceCallback<void(const WorkerId&, const std::string&)>>
      devtools_callbacks;
  DISALLOW_COPY_AND_ASSIGN(DelegatingURLLoaderClient);
};

using EventType = ServiceWorkerMetrics::EventType;
EventType ResourceTypeToEventType(ResourceType resource_type) {
  switch (resource_type) {
    case RESOURCE_TYPE_MAIN_FRAME:
      return EventType::FETCH_MAIN_FRAME;
    case RESOURCE_TYPE_SUB_FRAME:
      return EventType::FETCH_SUB_FRAME;
    case RESOURCE_TYPE_SHARED_WORKER:
      return EventType::FETCH_SHARED_WORKER;
    case RESOURCE_TYPE_SERVICE_WORKER:
    case RESOURCE_TYPE_LAST_TYPE:
      NOTREACHED() << resource_type;
      return EventType::FETCH_SUB_RESOURCE;
    default:
      return EventType::FETCH_SUB_RESOURCE;
  }
}

const net::NetworkTrafficAnnotationTag kNavigationPreloadTrafficAnnotation =
    net::DefineNetworkTrafficAnnotation("service_worker_navigation_preload",
                                        R"(
    semantics {
      sender: "Service Worker Navigation Preload"
      description:
        "This request is issued by a navigation to fetch the content of the "
        "page that is being navigated to, in the case where a service worker "
        "has been registered for the page and is using the Navigation Preload "
        "API."
      trigger:
        "Navigating Chrome (by clicking on a link, bookmark, history item, "
        "using session restore, etc)."
      data:
        "Arbitrary site-controlled data can be included in the URL, HTTP "
        "headers, and request body. Requests may include cookies and "
        "site-specific credentials."
      destination: WEBSITE
    }
    policy {
      cookies_allowed: YES
      cookies_store: "user"
      setting:
        "This request can be prevented by disabling service workers, which can "
        "be done by disabling cookie and site data under Settings, Content "
        "Settings, Cookies."
      chrome_policy {
        URLBlacklist {
          URLBlacklist: { entries: '*' }
        }
      }
      chrome_policy {
        URLWhitelist {
          URLWhitelist { }
        }
      }
    }
    comments:
      "Chrome would be unable to use service workers if this feature were "
      "disabled, which could result in a degraded experience for websites that "
      "register a service worker. Using either URLBlacklist or URLWhitelist "
      "policies (or a combination of both) limits the scope of these requests."
)");

// A copy of RenderFrameHostImpl's GrantFileAccess since there's not a great
// central place to put this.
//
// Abuse is prevented, because the files listed in ResourceRequestBody are
// validated earlier by navigation or ResourceDispatcherHost machinery before
// ServiceWorkerFetchDispatcher is used to send the request to a service worker.
void GrantFileAccessToProcess(int process_id,
                              const std::vector<base::FilePath>& file_paths) {
  ChildProcessSecurityPolicyImpl* policy =
      ChildProcessSecurityPolicyImpl::GetInstance();

  for (const auto& file : file_paths) {
    if (!policy->CanReadFile(process_id, file))
      policy->GrantReadFile(process_id, file);
  }
}

// Creates the network URLLoaderFactory for the navigation preload request.
void CreateNetworkFactoryForNavigationPreloadOnUI(
    const ServiceWorkerFetchDispatcher::WebContentsGetter& web_contents_getter,
    scoped_refptr<ServiceWorkerContextWrapper> context_wrapper,
    network::mojom::URLLoaderFactoryRequest request) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));

  WebContents* web_contents = web_contents_getter.Run();
  StoragePartitionImpl* partition = context_wrapper->storage_partition();
  if (!web_contents || !partition) {
    // The navigation was cancelled or we are in shutdown. Just drop the
    // request. Otherwise, we might go to network without consulting the
    // embedder first, which would break guarantees.
    return;
  }

  // Follow what NavigationURLLoaderImpl does for the initiator passed to
  // WillCreateURLLoaderFactory():
  // Navigation requests are not associated with any particular
  // |network::ResourceRequest::request_initiator| origin - using an opaque
  // origin instead.
  url::Origin initiator = url::Origin();

  // We ignore the value of |bypass_redirect_checks_unused| since a redirects is
  // just relayed to the service worker where preloadResponse is resolved as
  // redirect.
  bool bypass_redirect_checks_unused;

  // Consult the embedder.
  network::mojom::TrustedURLLoaderHeaderClientPtrInfo header_client;
  GetContentClient()->browser()->WillCreateURLLoaderFactory(
      web_contents->GetBrowserContext(), web_contents->GetMainFrame(),
      web_contents->GetMainFrame()->GetProcess()->GetID(),
      true /* is_navigation */, false /* is_download */, initiator, &request,
      &header_client, &bypass_redirect_checks_unused);

  // Make the network factory.
  NavigationURLLoaderImpl::CreateURLLoaderFactoryWithHeaderClient(
      std::move(header_client), std::move(request), partition);
}

}  // namespace

// ResponseCallback is owned by the callback that is passed to
// ServiceWorkerVersion::StartRequest*(), and held in pending_requests_
// until FinishRequest() is called.
class ServiceWorkerFetchDispatcher::ResponseCallback
    : public blink::mojom::ServiceWorkerFetchResponseCallback {
 public:
  ResponseCallback(
      blink::mojom::ServiceWorkerFetchResponseCallbackRequest request,
      base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher,
      ServiceWorkerVersion* version)
      : binding_(this, std::move(request)),
        fetch_dispatcher_(fetch_dispatcher),
        version_(version) {}

  ~ResponseCallback() override { DCHECK(fetch_event_id_.has_value()); }

  void set_fetch_event_id(int id) {
    DCHECK(!fetch_event_id_);
    fetch_event_id_ = id;
  }

  // Implements blink::mojom::ServiceWorkerFetchResponseCallback.
  void OnResponse(
      blink::mojom::FetchAPIResponsePtr response,
      blink::mojom::ServiceWorkerFetchEventTimingPtr timing) override {
    HandleResponse(fetch_dispatcher_, version_, fetch_event_id_,
                   std::move(response), nullptr /* body_as_stream */,
                   FetchEventResult::kGotResponse, std::move(timing));
  }
  void OnResponseStream(
      blink::mojom::FetchAPIResponsePtr response,
      blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
      blink::mojom::ServiceWorkerFetchEventTimingPtr timing) override {
    HandleResponse(fetch_dispatcher_, version_, fetch_event_id_,
                   std::move(response), std::move(body_as_stream),
                   FetchEventResult::kGotResponse, std::move(timing));
  }
  void OnFallback(
      blink::mojom::ServiceWorkerFetchEventTimingPtr timing) override {
    HandleResponse(fetch_dispatcher_, version_, fetch_event_id_,
                   blink::mojom::FetchAPIResponse::New(),
                   nullptr /* body_as_stream */,
                   FetchEventResult::kShouldFallback, std::move(timing));
  }

 private:
  // static as version->FinishRequest will remove the calling ResponseCallback
  // instance.
  static void HandleResponse(
      base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher,
      ServiceWorkerVersion* version,
      base::Optional<int> fetch_event_id,
      blink::mojom::FetchAPIResponsePtr response,
      blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
      FetchEventResult fetch_result,
      blink::mojom::ServiceWorkerFetchEventTimingPtr timing) {
    if (!version->FinishRequest(fetch_event_id.value(),
                                fetch_result == FetchEventResult::kGotResponse))
      NOTREACHED() << "Should only receive one reply per event";
    // |fetch_dispatcher| is null if the URLRequest was killed.
    if (!fetch_dispatcher)
      return;
    fetch_dispatcher->DidFinish(fetch_event_id.value(), fetch_result,
                                std::move(response), std::move(body_as_stream),
                                std::move(timing));
  }

  mojo::Binding<blink::mojom::ServiceWorkerFetchResponseCallback> binding_;
  base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
  // Owns |this| via pending_requests_.
  ServiceWorkerVersion* version_;
  // Must be set to a non-nullopt value before the corresponding mojo
  // handle is passed to the other end (i.e. before any of OnResponse*
  // is called).
  base::Optional<int> fetch_event_id_;

  DISALLOW_COPY_AND_ASSIGN(ResponseCallback);
};

// This class keeps the URL loader related assets alive while the FetchEvent is
// ongoing in the service worker.
class ServiceWorkerFetchDispatcher::URLLoaderAssets
    : public base::RefCounted<ServiceWorkerFetchDispatcher::URLLoaderAssets> {
 public:
  // Non-NetworkService.
  URLLoaderAssets(
      std::unique_ptr<network::mojom::URLLoaderFactory> url_loader_factory,
      std::unique_ptr<DelegatingURLLoaderClient> url_loader_client)
      : url_loader_factory_(std::move(url_loader_factory)),
        url_loader_client_(std::move(url_loader_client)) {}
  // NetworkService.
  URLLoaderAssets(
      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
      std::unique_ptr<DelegatingURLLoaderClient> url_loader_client)
      : shared_url_loader_factory_(std::move(shared_url_loader_factory)),
        url_loader_client_(std::move(url_loader_client)) {}

  void MaybeReportToDevTools(std::pair<int, int> worker_id,
                             int fetch_event_id) {
    url_loader_client_->MaybeReportToDevTools(worker_id, fetch_event_id);
  }

 private:
  friend class base::RefCounted<URLLoaderAssets>;
  virtual ~URLLoaderAssets() {}

  // Non-NetworkService:
  std::unique_ptr<network::mojom::URLLoaderFactory> url_loader_factory_;

  // NetworkService:
  scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;

  // Both:
  std::unique_ptr<DelegatingURLLoaderClient> url_loader_client_;

  DISALLOW_COPY_AND_ASSIGN(URLLoaderAssets);
};

ServiceWorkerFetchDispatcher::ServiceWorkerFetchDispatcher(
    blink::mojom::FetchAPIRequestPtr request,
    ResourceType resource_type,
    const std::string& client_id,
    scoped_refptr<ServiceWorkerVersion> version,
    base::OnceClosure prepare_callback,
    FetchCallback fetch_callback)
    : request_(std::move(request)),
      client_id_(client_id),
      version_(std::move(version)),
      resource_type_(resource_type),
      prepare_callback_(std::move(prepare_callback)),
      fetch_callback_(std::move(fetch_callback)),
      did_complete_(false),
      weak_factory_(this) {
#if DCHECK_IS_ON()
  if (blink::ServiceWorkerUtils::IsServicificationEnabled())
    DCHECK(!request_->blob);
#endif  // DCHECK_IS_ON()
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
      "ServiceWorker", "ServiceWorkerFetchDispatcher::DispatchFetchEvent", this,
      "event_type", ServiceWorkerMetrics::EventTypeToString(GetEventType()));
}

ServiceWorkerFetchDispatcher::~ServiceWorkerFetchDispatcher() {
  if (!did_complete_) {
    TRACE_EVENT_NESTABLE_ASYNC_END0(
        "ServiceWorker", "ServiceWorkerFetchDispatcher::DispatchFetchEvent",
        this);
  }
}

void ServiceWorkerFetchDispatcher::Run() {
  DCHECK(version_->status() == ServiceWorkerVersion::ACTIVATING ||
         version_->status() == ServiceWorkerVersion::ACTIVATED)
      << version_->status();

  if (version_->status() == ServiceWorkerVersion::ACTIVATING) {
    TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
        "ServiceWorker", "ServiceWorkerFetchDispatcher::WaitForActivation",
        this);
    version_->RegisterStatusChangeCallback(
        base::BindOnce(&ServiceWorkerFetchDispatcher::DidWaitForActivation,
                       weak_factory_.GetWeakPtr()));
    return;
  }
  StartWorker();
}

void ServiceWorkerFetchDispatcher::DidWaitForActivation() {
  TRACE_EVENT_NESTABLE_ASYNC_END0(
      "ServiceWorker", "ServiceWorkerFetchDispatcher::WaitForActivation", this);
  StartWorker();
}

void ServiceWorkerFetchDispatcher::StartWorker() {
  // We might be REDUNDANT if a new worker started activating and kicked us out
  // before we could finish activation.
  if (version_->status() != ServiceWorkerVersion::ACTIVATED) {
    DCHECK_EQ(ServiceWorkerVersion::REDUNDANT, version_->status());
    DidFail(blink::ServiceWorkerStatusCode::kErrorActivateWorkerFailed);
    return;
  }

  if (version_->running_status() == EmbeddedWorkerStatus::RUNNING) {
    DispatchFetchEvent();
    return;
  }

  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
      "ServiceWorker", "ServiceWorkerFetchDispatcher::StartWorker", this);
  version_->RunAfterStartWorker(
      GetEventType(),
      base::BindOnce(&ServiceWorkerFetchDispatcher::DidStartWorker,
                     weak_factory_.GetWeakPtr()));
}

void ServiceWorkerFetchDispatcher::DidStartWorker(
    blink::ServiceWorkerStatusCode status) {
  TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker",
                                  "ServiceWorkerFetchDispatcher::StartWorker",
                                  this, "status", status);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    DidFail(status);
    return;
  }
  DispatchFetchEvent();
}

void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
  DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status())
      << "Worker stopped too soon after it was started.";

  // Grant the service worker's process access to files in the request body.
  if (request_->body) {
    GrantFileAccessToProcess(version_->embedded_worker()->process_id(),
                             request_->body->GetReferencedFiles());
  }

  // Run callback to say that the fetch event will be dispatched.
  DCHECK(prepare_callback_);
  std::move(prepare_callback_).Run();
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
      "ServiceWorker", "ServiceWorkerFetchDispatcher::FetchEvent", this);

  // Set up for receiving the response.
  blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback_ptr;
  auto response_callback = std::make_unique<ResponseCallback>(
      mojo::MakeRequest(&response_callback_ptr), weak_factory_.GetWeakPtr(),
      version_.get());
  ResponseCallback* response_callback_rawptr = response_callback.get();

  // Set up the fetch event.
  int fetch_event_id = version_->StartRequest(
      GetEventType(),
      base::BindOnce(&ServiceWorkerFetchDispatcher::DidFailToDispatch,
                     weak_factory_.GetWeakPtr(), std::move(response_callback)));
  int event_finish_id = version_->StartRequest(
      ServiceWorkerMetrics::EventType::FETCH_WAITUNTIL, base::DoNothing());
  response_callback_rawptr->set_fetch_event_id(fetch_event_id);

  // Report navigation preload to DevTools if needed.
  if (url_loader_assets_) {
    url_loader_assets_->MaybeReportToDevTools(
        std::make_pair(
            version_->embedded_worker()->process_id(),
            version_->embedded_worker()->worker_devtools_agent_route_id()),
        fetch_event_id);
  }

  // Dispatch the fetch event.
  auto params = blink::mojom::DispatchFetchEventParams::New();
  params->request = std::move(request_);
  params->client_id = client_id_;
  params->preload_handle = std::move(preload_handle_);
  // |endpoint()| is owned by |version_|. So it is safe to pass the
  // unretained raw pointer of |version_| to OnFetchEventFinished callback.
  // Pass |url_loader_assets_| to the callback to keep the URL loader related
  // assets alive while the FetchEvent is ongoing in the service worker.
  version_->endpoint()->DispatchFetchEvent(
      std::move(params), std::move(response_callback_ptr),
      base::BindOnce(&ServiceWorkerFetchDispatcher::OnFetchEventFinished,
                     base::Unretained(version_.get()), event_finish_id,
                     url_loader_assets_));
}

void ServiceWorkerFetchDispatcher::DidFailToDispatch(
    std::unique_ptr<ResponseCallback> response_callback,
    blink::ServiceWorkerStatusCode status) {
  TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker",
                                  "ServiceWorkerFetchDispatcher::FetchEvent",
                                  this, "status", status);
  DidFail(status);
}

void ServiceWorkerFetchDispatcher::DidFail(
    blink::ServiceWorkerStatusCode status) {
  DCHECK_NE(blink::ServiceWorkerStatusCode::kOk, status);
  Complete(status, FetchEventResult::kShouldFallback,
           blink::mojom::FetchAPIResponse::New(), nullptr /* body_as_stream */,
           nullptr /* timing */);
}

void ServiceWorkerFetchDispatcher::DidFinish(
    int request_id,
    FetchEventResult fetch_result,
    blink::mojom::FetchAPIResponsePtr response,
    blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
    blink::mojom::ServiceWorkerFetchEventTimingPtr timing) {
  TRACE_EVENT_NESTABLE_ASYNC_END0(
      "ServiceWorker", "ServiceWorkerFetchDispatcher::FetchEvent", this);
  Complete(blink::ServiceWorkerStatusCode::kOk, fetch_result,
           std::move(response), std::move(body_as_stream), std::move(timing));
}

void ServiceWorkerFetchDispatcher::Complete(
    blink::ServiceWorkerStatusCode status,
    FetchEventResult fetch_result,
    blink::mojom::FetchAPIResponsePtr response,
    blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
    blink::mojom::ServiceWorkerFetchEventTimingPtr timing) {
  DCHECK(fetch_callback_);

  did_complete_ = true;
  TRACE_EVENT_NESTABLE_ASYNC_END1(
      "ServiceWorker", "ServiceWorkerFetchDispatcher::DispatchFetchEvent", this,
      "result", fetch_result);
  std::move(fetch_callback_)
      .Run(status, fetch_result, std::move(response), std::move(body_as_stream),
           std::move(timing), version_);
}

// Non-S13nServiceWorker
bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
    net::URLRequest* original_request,
    base::OnceClosure on_response) {
  if (resource_type_ != RESOURCE_TYPE_MAIN_FRAME &&
      resource_type_ != RESOURCE_TYPE_SUB_FRAME) {
    return false;
  }
  if (!version_->navigation_preload_state().enabled)
    return false;
  // TODO(horo): Currently NavigationPreload doesn't support request body.
  if (request_->blob)
    return false;

  ResourceRequestInfoImpl* original_info =
      ResourceRequestInfoImpl::ForRequest(original_request);
  ResourceRequesterInfo* requester_info = original_info->requester_info();
  DCHECK(requester_info->IsBrowserSideNavigation());
  auto url_loader_factory = std::make_unique<URLLoaderFactoryImpl>(
      ResourceRequesterInfo::CreateForNavigationPreload(
          requester_info,
          const_cast<net::URLRequestContext*>(original_request->context())));

  network::ResourceRequest request;
  request.method = original_request->method();
  request.url = original_request->url();
  request.site_for_cookies = original_request->site_for_cookies();
  request.request_initiator =
      original_request->initiator().has_value()
          ? original_request->initiator()
          : url::Origin::Create(original_request->url());
  request.referrer = GURL(original_request->referrer());
  request.referrer_policy =
      Referrer::ReferrerPolicyForUrlRequest(original_info->GetReferrerPolicy());
  request.is_prerendering = original_info->IsPrerendering();
  request.load_flags = original_request->load_flags();
  request.resource_type = RESOURCE_TYPE_NAVIGATION_PRELOAD;
  request.priority = original_request->priority();
  request.skip_service_worker = true;
  request.do_not_prompt_for_login = true;
  request.render_frame_id = original_info->GetRenderFrameID();
  request.is_main_frame = original_info->IsMainFrame();
  request.enable_load_timing = original_info->is_load_timing_enabled();
  request.report_raw_headers = original_info->ShouldReportRawHeaders();
  request.throttling_profile_id =
      network::ThrottlingController::GetProfileIDForNetLogSource(
          original_request->net_log().source().id);

  DCHECK(net::HttpUtil::IsValidHeaderValue(
      version_->navigation_preload_state().header));
  ServiceWorkerMetrics::RecordNavigationPreloadRequestHeaderSize(
      version_->navigation_preload_state().header.length());
  request.headers.CopyFrom(original_request->extra_request_headers());
  request.headers.SetHeader("Service-Worker-Navigation-Preload",
                            version_->navigation_preload_state().header);

  const int request_id = ResourceDispatcherHostImpl::Get()->MakeRequestID();
  DCHECK_LT(request_id, -1);

  preload_handle_ = blink::mojom::FetchEventPreloadHandle::New();
  network::mojom::URLLoaderClientPtr inner_url_loader_client;
  preload_handle_->url_loader_client_request =
      mojo::MakeRequest(&inner_url_loader_client);
  auto url_loader_client = std::make_unique<DelegatingURLLoaderClient>(
      std::move(inner_url_loader_client), std::move(on_response), request);
  network::mojom::URLLoaderClientPtr url_loader_client_to_pass;
  url_loader_client->Bind(&url_loader_client_to_pass);
  network::mojom::URLLoaderPtr url_loader;

  url_loader_factory->CreateLoaderAndStart(
      mojo::MakeRequest(&url_loader), original_info->GetRouteID(), request_id,
      network::mojom::kURLLoadOptionNone, request,
      std::move(url_loader_client_to_pass),
      net::MutableNetworkTrafficAnnotationTag(
          original_request->traffic_annotation()));

  preload_handle_->url_loader = url_loader.PassInterface();

  DCHECK(!url_loader_assets_);
  url_loader_assets_ = base::MakeRefCounted<URLLoaderAssets>(
      std::move(url_loader_factory), std::move(url_loader_client));
  return true;
}

// S13nServiceWorker
bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreloadWithURLLoader(
    const network::ResourceRequest& original_request,
    URLLoaderFactoryGetter* url_loader_factory_getter,
    scoped_refptr<ServiceWorkerContextWrapper> context_wrapper,
    const WebContentsGetter& web_contents_getter,
    base::OnceClosure on_response) {
  if (resource_type_ != RESOURCE_TYPE_MAIN_FRAME &&
      resource_type_ != RESOURCE_TYPE_SUB_FRAME) {
    return false;
  }
  if (!version_->navigation_preload_state().enabled)
    return false;
  // TODO(horo): Currently NavigationPreload doesn't support request body.
  if (request_->body)
    return false;

  network::ResourceRequest resource_request(original_request);
  resource_request.resource_type = RESOURCE_TYPE_NAVIGATION_PRELOAD;
  resource_request.skip_service_worker = true;
  resource_request.do_not_prompt_for_login = true;

  DCHECK(net::HttpUtil::IsValidHeaderValue(
      version_->navigation_preload_state().header));
  ServiceWorkerMetrics::RecordNavigationPreloadRequestHeaderSize(
      version_->navigation_preload_state().header.length());
  resource_request.headers.SetHeader(
      "Service-Worker-Navigation-Preload",
      version_->navigation_preload_state().header);

  // Create the network factory.
  scoped_refptr<network::SharedURLLoaderFactory> factory;
  if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
    // In the network service case, create the factory on the UI thread.
    network::mojom::URLLoaderFactoryPtr network_factory;
    auto factory_request = mojo::MakeRequest(&network_factory);

    base::PostTaskWithTraits(
        FROM_HERE, {BrowserThread::UI},
        base::BindOnce(&CreateNetworkFactoryForNavigationPreloadOnUI,
                       web_contents_getter, std::move(context_wrapper),
                       mojo::MakeRequest(&network_factory)));
    factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
        std::move(network_factory));
  } else {
    // In the non-network-service case, use |url_loader_factory_getter|. Unlike
    // the network service case, we don't need to go to the UI thread to tell
    // the embedder about the factory since the request will go to
    // ResourceDispatcherHost which talks to the embedder then.
    factory = url_loader_factory_getter->GetNetworkFactory();
  }

  preload_handle_ = blink::mojom::FetchEventPreloadHandle::New();

  // Create the DelegatingURLLoaderClient, which becomes the
  // URLLoaderClient for the navigation preload network request.
  network::mojom::URLLoaderClientPtr inner_url_loader_client;
  preload_handle_->url_loader_client_request =
      mojo::MakeRequest(&inner_url_loader_client);
  auto url_loader_client = std::make_unique<DelegatingURLLoaderClient>(
      std::move(inner_url_loader_client), std::move(on_response),
      resource_request);

  // Use NavigationURLLoaderImpl to get a unique request id across
  // browser-initiated navigations and navigation preloads.
  int request_id = NavigationURLLoaderImpl::MakeGlobalRequestID().request_id;

  // Start the network request for the URL using the network factory.
  // TODO(falken): What to do about routing_id.
  network::mojom::URLLoaderClientPtr url_loader_client_to_pass;
  url_loader_client->Bind(&url_loader_client_to_pass);
  network::mojom::URLLoaderPtr url_loader;

  factory->CreateLoaderAndStart(
      mojo::MakeRequest(&url_loader), -1 /* routing_id? */, request_id,
      network::mojom::kURLLoadOptionNone, resource_request,
      std::move(url_loader_client_to_pass),
      net::MutableNetworkTrafficAnnotationTag(
          kNavigationPreloadTrafficAnnotation));

  preload_handle_->url_loader = url_loader.PassInterface();

  DCHECK(!url_loader_assets_);
  url_loader_assets_ = base::MakeRefCounted<URLLoaderAssets>(
      std::move(factory), std::move(url_loader_client));
  return true;
}

ServiceWorkerMetrics::EventType ServiceWorkerFetchDispatcher::GetEventType()
    const {
  return ResourceTypeToEventType(resource_type_);
}

// static
void ServiceWorkerFetchDispatcher::OnFetchEventFinished(
    ServiceWorkerVersion* version,
    int event_finish_id,
    scoped_refptr<URLLoaderAssets> url_loader_assets,
    blink::mojom::ServiceWorkerEventStatus status) {
  version->FinishRequest(
      event_finish_id,
      status != blink::mojom::ServiceWorkerEventStatus::ABORTED);
}

}  // namespace content
