// 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_controllee_request_handler.h"

#include <set>
#include <utility>

#include "base/trace_event/trace_event.h"
#include "components/offline_pages/buildflags/buildflags.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_response_info.h"
#include "content/browser/service_worker/service_worker_url_job_wrapper.h"
#include "content/browser/service_worker/service_worker_url_request_job.h"
#include "content/common/navigation_subresource_loader_params.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_client.h"
#include "net/base/load_flags.h"
#include "net/base/url_util.h"
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "services/network/public/cpp/resource_response_info.h"
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "ui/base/page_transition_types.h"

#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
#include "components/offline_pages/core/request_header/offline_page_header.h"
#endif  // BUILDFLAG(ENABLE_OFFLINE_PAGES)

namespace content {

namespace {

bool MaybeForwardToServiceWorker(ServiceWorkerURLJobWrapper* job,
                                 const ServiceWorkerVersion* version) {
  DCHECK(job);
  DCHECK(version);
  DCHECK_NE(version->fetch_handler_existence(),
            ServiceWorkerVersion::FetchHandlerExistence::UNKNOWN);
  if (version->fetch_handler_existence() ==
      ServiceWorkerVersion::FetchHandlerExistence::EXISTS) {
    job->ForwardToServiceWorker();
    return true;
  }

  job->FallbackToNetworkOrRenderer();
  return false;
}

#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
// A web page, regardless of whether the service worker is used or not, could
// be downloaded with the offline snapshot captured. The user can then open
// the downloaded page which is identified by the presence of a specific
// offline header in the network request. In this case, we want to fall back
// in order for the subsequent offline page interceptor to bring up the
// offline snapshot of the page.
bool ShouldFallbackToLoadOfflinePage(
    const net::HttpRequestHeaders& extra_request_headers) {
  std::string offline_header_value;
  if (!extra_request_headers.GetHeader(offline_pages::kOfflinePageHeader,
                                       &offline_header_value)) {
    return false;
  }
  offline_pages::OfflinePageHeader offline_header(offline_header_value);
  return offline_header.reason ==
         offline_pages::OfflinePageHeader::Reason::DOWNLOAD;
}
#endif  // BUILDFLAG(ENABLE_OFFLINE_PAGES)

}  // namespace

// RAII class that disallows calling SetControllerRegistration() on a provider
// host.
class ServiceWorkerControlleeRequestHandler::
    ScopedDisallowSetControllerRegistration {
 public:
  explicit ScopedDisallowSetControllerRegistration(
      base::WeakPtr<ServiceWorkerProviderHost> provider_host)
      : provider_host_(std::move(provider_host)) {
    DCHECK(provider_host_->IsSetControllerRegistrationAllowed())
        << "The host already disallows using a registration; nested disallow "
           "is not supported.";
    provider_host_->AllowSetControllerRegistration(false);
  }

  ~ScopedDisallowSetControllerRegistration() {
    if (!provider_host_)
      return;
    DCHECK(!provider_host_->IsSetControllerRegistrationAllowed())
        << "Failed to disallow using a registration.";
    provider_host_->AllowSetControllerRegistration(true);
  }

 private:
  base::WeakPtr<ServiceWorkerProviderHost> provider_host_;

  DISALLOW_COPY_AND_ASSIGN(ScopedDisallowSetControllerRegistration);
};

class ServiceWorkerControlleeRequestHandler::MainResourceRequestTracker {
 public:
  MainResourceRequestTracker() = default;

  ~MainResourceRequestTracker() {
    if (recorded_destination_)
      return;
    RecordDestination(
        will_dispatch_fetch_
            ? ServiceWorkerMetrics::MainResourceRequestDestination::
                  kAbortedWhileDispatchingFetchEvent
            : ServiceWorkerMetrics::MainResourceRequestDestination::
                  kAbortedWithoutDispatchingFetchEvent);
  }

  void RecordDestination(
      ServiceWorkerMetrics::MainResourceRequestDestination destination) {
    CHECK(!recorded_destination_);
    recorded_destination_ = true;
    ServiceWorkerMetrics::RecordMainResourceRequestDestination(destination);
  }

  void WillDispatchFetchEvent() { will_dispatch_fetch_ = true; }

 private:
  bool recorded_destination_ = false;
  bool will_dispatch_fetch_ = false;
  DISALLOW_COPY_AND_ASSIGN(MainResourceRequestTracker);
};

ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
    base::WeakPtr<ServiceWorkerContextCore> context,
    base::WeakPtr<ServiceWorkerProviderHost> provider_host,
    base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
    network::mojom::FetchRequestMode request_mode,
    network::mojom::FetchCredentialsMode credentials_mode,
    network::mojom::FetchRedirectMode redirect_mode,
    const std::string& integrity,
    bool keepalive,
    ResourceType resource_type,
    RequestContextType request_context_type,
    network::mojom::RequestContextFrameType frame_type,
    scoped_refptr<network::ResourceRequestBody> body)
    : ServiceWorkerRequestHandler(std::move(context),
                                  std::move(provider_host),
                                  std::move(blob_storage_context),
                                  resource_type),
      resource_type_(resource_type),
      is_main_resource_load_(
          ServiceWorkerUtils::IsMainResourceType(resource_type)),
      request_mode_(request_mode),
      credentials_mode_(credentials_mode),
      redirect_mode_(redirect_mode),
      integrity_(integrity),
      keepalive_(keepalive),
      request_context_type_(request_context_type),
      frame_type_(frame_type),
      body_(std::move(body)),
      force_update_started_(false),
      use_network_(false),
      weak_factory_(this) {}

ServiceWorkerControlleeRequestHandler::
    ~ServiceWorkerControlleeRequestHandler() {
  MaybeScheduleUpdate();
}

void ServiceWorkerControlleeRequestHandler::MaybeScheduleUpdate() {
  if (!provider_host_ || !provider_host_->controller())
    return;

  if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
    // For subresources: S13nServiceWorker doesn't come here.
    DCHECK(is_main_resource_load_);

    // For navigations, the update logic is taken care of
    // during navigation and waits for the HintToUpdateServiceWorker message.
    if (IsResourceTypeFrame(resource_type_))
      return;

    // Continue to the common non-S13nServiceWorker code for triggering update
    // for shared workers. The renderer doesn't yet send a
    // HintToUpdateServiceWorker message.
    // TODO(falken): Make the renderer send the message for shared worker,
    // to simplify the code.
  }

  // If DevTools forced an update, there is no need to update again.
  if (force_update_started_)
    return;

  if (is_main_resource_load_)
    provider_host_->controller()->ScheduleUpdate();
  else
    provider_host_->controller()->DeferScheduledUpdate();
}

net::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob(
    net::URLRequest* request,
    net::NetworkDelegate* network_delegate,
    ResourceContext* resource_context) {
  ClearJob();
  ServiceWorkerResponseInfo::ResetDataForRequest(request);

  if (!context_ || !provider_host_) {
    // We can't do anything other than to fall back to network.
    return nullptr;
  }

  // This may get called multiple times for original and redirect requests:
  // A. original request case: use_network_ is false, no previous location info.
  // B. redirect or restarted request case:
  //  a) use_network_ is false if the previous location was forwarded to SW.
  //  b) use_network_ is false if the previous location was fallback.
  //  c) use_network_ is true if additional restart was required to fall back.

  // Fall back to network. (Case B-c)
  if (use_network_) {
    // Once a subresource request has fallen back to the network once, it will
    // never be handled by a service worker. This is not true of main frame
    // requests.
    if (is_main_resource_load_)
      use_network_ = false;
    return nullptr;
  }

#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
  // Fall back for the subsequent offline page interceptor to load the offline
  // snapshot of the page if required.
  if (ShouldFallbackToLoadOfflinePage(request->extra_request_headers()))
    return nullptr;
#endif  // BUILDFLAG(ENABLE_OFFLINE_PAGES)

  // It's for original request (A) or redirect case (B-a or B-b).
  auto job = std::make_unique<ServiceWorkerURLRequestJob>(
      request, network_delegate, provider_host_->client_uuid(),
      blob_storage_context_, resource_context, request_mode_, credentials_mode_,
      redirect_mode_, integrity_, keepalive_, resource_type_,
      request_context_type_, frame_type_, body_, this);
  url_job_ = std::make_unique<ServiceWorkerURLJobWrapper>(job->GetWeakPtr());

  resource_context_ = resource_context;

  if (is_main_resource_load_)
    PrepareForMainResource(request->url(), request->site_for_cookies());
  else
    PrepareForSubResource();

  if (url_job_->ShouldFallbackToNetwork()) {
    // If we know we can fallback to network at this point (in case
    // the storage lookup returned immediately), just destroy the job and return
    // NULL here to fallback to network.

    // If this is a subresource request, all subsequent requests should also use
    // the network.
    if (!is_main_resource_load_)
      use_network_ = true;

    job.reset();
    ClearJob();
  }

  return job.release();
}

void ServiceWorkerControlleeRequestHandler::MaybeCreateLoader(
    const network::ResourceRequest& tentative_resource_request,
    ResourceContext* resource_context,
    LoaderCallback callback,
    FallbackCallback fallback_callback) {
  DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
  DCHECK(is_main_resource_load_);
  ClearJob();

  if (!context_ || !provider_host_) {
    // We can't do anything other than to fall back to network.
    std::move(callback).Run({});
    return;
  }

  // In fallback cases we basically 'forward' the request, so we should
  // never see use_network_ gets true.
  DCHECK(!use_network_);

#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
  // Fall back for the subsequent offline page interceptor to load the offline
  // snapshot of the page if required.
  //
  // TODO(crbug.com/876527): Figure out how offline page interception should
  // interact with URLLoaderThrottles. It might be incorrect to use
  // |tentative_resource_request.headers| here, since throttles can rewrite
  // headers between now and when the request handler passed to
  // |loader_callback_| is invoked.
  if (ShouldFallbackToLoadOfflinePage(tentative_resource_request.headers)) {
    std::move(callback).Run({});
    return;
  }
#endif  // BUILDFLAG(ENABLE_OFFLINE_PAGES)

  url_job_ = std::make_unique<ServiceWorkerURLJobWrapper>(
      std::make_unique<ServiceWorkerNavigationLoader>(
          std::move(callback), std::move(fallback_callback), this,
          tentative_resource_request,
          base::WrapRefCounted(context_->loader_factory_getter())));

  resource_context_ = resource_context;

  PrepareForMainResource(tentative_resource_request.url,
                         tentative_resource_request.site_for_cookies);

  if (url_job_->ShouldFallbackToNetwork()) {
    // The job already fell back to network. Clear the job now.
    ClearJob();
    return;
  }

  // We will asynchronously continue on DidLookupRegistrationForMainResource.
}

base::Optional<SubresourceLoaderParams>
ServiceWorkerControlleeRequestHandler::MaybeCreateSubresourceLoaderParams() {
  DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());

  // We didn't create URLLoader for this request.
  if (!url_job_)
    return base::nullopt;

  // DidLookupRegistrationForMainResource() for the request didn't find
  // a matching service worker for this request, and
  // ServiceWorkerProviderHost::SetControllerRegistration() was not called.
  if (!provider_host_ || !provider_host_->controller())
    return base::nullopt;

  // Otherwise let's send the controller service worker information along
  // with the navigation commit.
  SubresourceLoaderParams params;
  auto controller_info = mojom::ControllerServiceWorkerInfo::New();
  controller_info->mode = provider_host_->GetControllerMode();
  // Note that |controller_info->endpoint| is null if the controller has no
  // fetch event handler. In that case the renderer frame won't get the
  // controller pointer upon the navigation commit, and subresource loading will
  // not be intercepted. (It might get intercepted later if the controller
  // changes due to skipWaiting() so SetController is sent.)
  controller_info->endpoint =
      provider_host_->GetControllerServiceWorkerPtr().PassInterface();
  controller_info->client_id = provider_host_->client_uuid();
  base::WeakPtr<ServiceWorkerObjectHost> object_host =
      provider_host_->GetOrCreateServiceWorkerObjectHost(
          provider_host_->controller());
  if (object_host) {
    params.controller_service_worker_object_host = object_host;
    controller_info->object_info = object_host->CreateIncompleteObjectInfo();
  }
  params.controller_service_worker_info = std::move(controller_info);
  return base::Optional<SubresourceLoaderParams>(std::move(params));
}

void ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
    const GURL& url,
    const GURL& site_for_cookies) {
  DCHECK(!JobWasCanceled());
  DCHECK(context_);
  DCHECK(provider_host_);
  tracker_ = std::make_unique<MainResourceRequestTracker>();

  TRACE_EVENT_ASYNC_BEGIN1(
      "ServiceWorker",
      "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
      url_job_.get(), "URL", url.spec());
  // The provider host may already have set a controller in redirect case,
  // unset it now.
  provider_host_->SetControllerRegistration(
      nullptr, false /* notify_controllerchange */);

  // Also prevent a registration from claiming this host while it's not
  // yet execution ready.
  auto disallow_controller =
      std::make_unique<ScopedDisallowSetControllerRegistration>(provider_host_);

  stripped_url_ = net::SimplifyUrlForRequest(url);
  provider_host_->SetDocumentUrl(stripped_url_);
  provider_host_->SetTopmostFrameUrl(site_for_cookies);
  context_->storage()->FindRegistrationForDocument(
      stripped_url_, base::BindOnce(&ServiceWorkerControlleeRequestHandler::
                                        DidLookupRegistrationForMainResource,
                                    weak_factory_.GetWeakPtr(),
                                    std::move(disallow_controller)));
}

void ServiceWorkerControlleeRequestHandler::
    DidLookupRegistrationForMainResource(
        std::unique_ptr<ScopedDisallowSetControllerRegistration>
            disallow_controller,
        blink::ServiceWorkerStatusCode status,
        scoped_refptr<ServiceWorkerRegistration> registration) {
  // The job may have been canceled before this was invoked.
  if (JobWasCanceled())
    return;

  if (status != blink::ServiceWorkerStatusCode::kOk) {
    tracker_->RecordDestination(
        ServiceWorkerMetrics::MainResourceRequestDestination::
            kNetworkBecauseNoRegistration);
    url_job_->FallbackToNetwork();
    TRACE_EVENT_ASYNC_END1(
        "ServiceWorker",
        "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
        url_job_.get(), "Status", blink::ServiceWorkerStatusToString(status));
    return;
  }
  DCHECK(registration);

  if (!provider_host_) {
    tracker_->RecordDestination(
        ServiceWorkerMetrics::MainResourceRequestDestination::
            kNetworkBecauseNoProvider);
    url_job_->FallbackToNetwork();
    TRACE_EVENT_ASYNC_END1(
        "ServiceWorker",
        "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
        url_job_.get(), "Info", "No Provider");
    return;
  }
  provider_host_->AddMatchingRegistration(registration.get());

  if (!context_) {
    tracker_->RecordDestination(
        ServiceWorkerMetrics::MainResourceRequestDestination::
            kNetworkBecauseNoContext);
    url_job_->FallbackToNetwork();
    TRACE_EVENT_ASYNC_END1(
        "ServiceWorker",
        "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
        url_job_.get(), "Info", "No Context");
    return;
  }

  if (!GetContentClient()->browser()->AllowServiceWorker(
          registration->pattern(), provider_host_->topmost_frame_url(),
          resource_context_, provider_host_->web_contents_getter())) {
    tracker_->RecordDestination(
        ServiceWorkerMetrics::MainResourceRequestDestination::
            kNetworkBecauseNotAllowed);
    url_job_->FallbackToNetwork();
    TRACE_EVENT_ASYNC_END1(
        "ServiceWorker",
        "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
        url_job_.get(), "Info", "ServiceWorker is blocked");
    return;
  }

  if (!provider_host_->IsContextSecureForServiceWorker()) {
    // TODO(falken): Figure out a way to surface in the page's DevTools
    // console that the service worker was blocked for security.
    tracker_->RecordDestination(
        ServiceWorkerMetrics::MainResourceRequestDestination::
            kNetworkBecauseNotSecure);
    url_job_->FallbackToNetwork();
    TRACE_EVENT_ASYNC_END1(
        "ServiceWorker",
        "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
        url_job_.get(), "Info", "Insecure context");
    return;
  }

  const bool need_to_update =
      !force_update_started_ && context_->force_update_on_page_load();
  if (need_to_update) {
    force_update_started_ = true;
    context_->UpdateServiceWorker(
        registration.get(), true /* force_bypass_cache */,
        true /* skip_script_comparison */,
        base::BindOnce(
            &ServiceWorkerControlleeRequestHandler::DidUpdateRegistration,
            weak_factory_.GetWeakPtr(), registration,
            std::move(disallow_controller)));
    return;
  }

  // Initiate activation of a waiting version. Usually a register job initiates
  // activation but that doesn't happen if the browser exits prior to activation
  // having occurred. This check handles that case.
  if (registration->waiting_version())
    registration->ActivateWaitingVersionWhenReady();

  scoped_refptr<ServiceWorkerVersion> active_version =
      registration->active_version();
  if (!active_version) {
    tracker_->RecordDestination(
        ServiceWorkerMetrics::MainResourceRequestDestination::
            kNetworkBecauseNoActiveVersion);
    url_job_->FallbackToNetwork();
    TRACE_EVENT_ASYNC_END1(
        "ServiceWorker",
        "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
        url_job_.get(), "Info",
        "No active version, so falling back to network");
    return;
  }

  DCHECK(active_version->status() == ServiceWorkerVersion::ACTIVATING ||
         active_version->status() == ServiceWorkerVersion::ACTIVATED)
      << ServiceWorkerVersion::VersionStatusToString(active_version->status());
  // Wait until it's activated before firing fetch events.
  if (active_version->status() == ServiceWorkerVersion::ACTIVATING) {
    registration->active_version()->RegisterStatusChangeCallback(
        base::BindOnce(&ServiceWorkerControlleeRequestHandler::
                           ContinueWithInScopeMainResourceRequest,
                       weak_factory_.GetWeakPtr(), registration, active_version,
                       std::move(disallow_controller)));
    TRACE_EVENT_ASYNC_END1(
        "ServiceWorker",
        "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
        url_job_.get(), "Info", "Wait until finished SW activation");
    return;
  }

  ContinueWithInScopeMainResourceRequest(std::move(registration),
                                         std::move(active_version),
                                         std::move(disallow_controller));
}

void ServiceWorkerControlleeRequestHandler::
    ContinueWithInScopeMainResourceRequest(
        scoped_refptr<ServiceWorkerRegistration> registration,
        scoped_refptr<ServiceWorkerVersion> active_version,
        std::unique_ptr<ScopedDisallowSetControllerRegistration>
            disallow_controller) {
  // The job may have been canceled before this was invoked. In that
  // case, |url_job_| can't be used, so return.
  if (JobWasCanceled()) {
    tracker_->RecordDestination(
        ServiceWorkerMetrics::MainResourceRequestDestination::kJobWasCancelled);
    TRACE_EVENT_ASYNC_END1(
        "ServiceWorker",
        "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
        url_job_.get(), "Info", "The job was canceled");
    return;
  }

  if (!provider_host_) {
    tracker_->RecordDestination(
        ServiceWorkerMetrics::MainResourceRequestDestination::
            kNetworkBecauseNoProviderAfterContinuing);
    url_job_->FallbackToNetwork();
    TRACE_EVENT_ASYNC_END1(
        "ServiceWorker",
        "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
        url_job_.get(), "Info",
        "The provider host is gone, so falling back to network");
    return;
  }

  if (active_version->status() != ServiceWorkerVersion::ACTIVATED) {
    // TODO(falken): Clean this up and clarify in what cases we come here. I
    // guess it's:
    // - strange system error cases where promoting from ACTIVATING to ACTIVATED
    //   failed (shouldn't happen)
    // - something calling Doom(), etc, making the active_version REDUNDANT
    // - a version called skipWaiting() during activation so the expected
    //   version is no longer the active one (shouldn't happen: skipWaiting()
    //   waits for the active version to finish activating).
    // In most cases, it sounds like falling back to network would not be right,
    // since it's still in-scope. We probably should do:
    //   1) If the provider host has an active version that is ACTIVATED, just
    //      use that, even if it wasn't the expected one.
    //   2) If the provider host has an active version that is not ACTIVATED,
    //      just fail the load. The correct thing is probably to re-try
    //      activating that version, but there's a risk of an infinite loop of
    //      retries.
    //   3) If the provider host does not have an active version, just fail the
    //      load.
    tracker_->RecordDestination(
        ServiceWorkerMetrics::MainResourceRequestDestination::
            kNetworkBecauseNoActiveVersionAfterContinuing);
    url_job_->FallbackToNetwork();
    TRACE_EVENT_ASYNC_END2(
        "ServiceWorker",
        "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
        url_job_.get(), "Info",
        "The expected active version is not ACTIVATED, so falling back to "
        "network",
        "Status",
        ServiceWorkerVersion::VersionStatusToString(active_version->status()));
    return;
  }

  disallow_controller.reset();
  provider_host_->SetControllerRegistration(
      registration, false /* notify_controllerchange */);

  DCHECK_EQ(active_version, registration->active_version());
  DCHECK_EQ(active_version, provider_host_->controller());
  DCHECK_NE(active_version->fetch_handler_existence(),
            ServiceWorkerVersion::FetchHandlerExistence::UNKNOWN);
  ServiceWorkerMetrics::CountControlledPageLoad(
      active_version->site_for_uma(), stripped_url_,
      resource_type_ == RESOURCE_TYPE_MAIN_FRAME);

  if (blink::ServiceWorkerUtils::IsServicificationEnabled() &&
      IsResourceTypeFrame(resource_type_)) {
    provider_host_->AddServiceWorkerToUpdate(active_version);
  }
  bool is_forwarded =
      MaybeForwardToServiceWorker(url_job_.get(), active_version.get());
  if (!is_forwarded) {
    tracker_->RecordDestination(
        ServiceWorkerMetrics::MainResourceRequestDestination::
            kNetworkBecauseNoFetchEventHandler);
  }
  TRACE_EVENT_ASYNC_END1(
      "ServiceWorker",
      "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
      url_job_.get(), "Info",
      (is_forwarded) ? "Forwarded to the ServiceWorker"
                     : "Skipped the ServiceWorker which has no fetch handler");
}

void ServiceWorkerControlleeRequestHandler::DidUpdateRegistration(
    scoped_refptr<ServiceWorkerRegistration> original_registration,
    std::unique_ptr<ScopedDisallowSetControllerRegistration>
        disallow_controller,
    blink::ServiceWorkerStatusCode status,
    const std::string& status_message,
    int64_t registration_id) {
  DCHECK(force_update_started_);

  // The job may have been canceled before this was invoked.
  if (JobWasCanceled())
    return;

  if (!context_) {
    url_job_->FallbackToNetwork();
    return;
  }
  if (status != blink::ServiceWorkerStatusCode::kOk ||
      !original_registration->installing_version()) {
    // Update failed. Look up the registration again since the original
    // registration was possibly unregistered in the meantime.
    context_->storage()->FindRegistrationForDocument(
        stripped_url_, base::BindOnce(&ServiceWorkerControlleeRequestHandler::
                                          DidLookupRegistrationForMainResource,
                                      weak_factory_.GetWeakPtr(),
                                      std::move(disallow_controller)));
    return;
  }
  DCHECK_EQ(original_registration->id(), registration_id);
  ServiceWorkerVersion* new_version =
      original_registration->installing_version();
  new_version->ReportForceUpdateToDevTools();
  new_version->set_skip_waiting(true);
  new_version->RegisterStatusChangeCallback(base::BindOnce(
      &ServiceWorkerControlleeRequestHandler::OnUpdatedVersionStatusChanged,
      weak_factory_.GetWeakPtr(), std::move(original_registration),
      base::WrapRefCounted(new_version), std::move(disallow_controller)));
}

void ServiceWorkerControlleeRequestHandler::OnUpdatedVersionStatusChanged(
    scoped_refptr<ServiceWorkerRegistration> registration,
    scoped_refptr<ServiceWorkerVersion> version,
    std::unique_ptr<ScopedDisallowSetControllerRegistration>
        disallow_controller) {
  // The job may have been canceled before this was invoked.
  if (JobWasCanceled())
    return;

  if (!context_) {
    url_job_->FallbackToNetwork();
    return;
  }
  if (version->status() == ServiceWorkerVersion::ACTIVATED ||
      version->status() == ServiceWorkerVersion::REDUNDANT) {
    // When the status is REDUNDANT, the update failed (eg: script error), we
    // continue with the incumbent version.
    // In case unregister job may have run, look up the registration again.
    context_->storage()->FindRegistrationForDocument(
        stripped_url_, base::BindOnce(&ServiceWorkerControlleeRequestHandler::
                                          DidLookupRegistrationForMainResource,
                                      weak_factory_.GetWeakPtr(),
                                      std::move(disallow_controller)));
    return;
  }
  version->RegisterStatusChangeCallback(base::BindOnce(
      &ServiceWorkerControlleeRequestHandler::OnUpdatedVersionStatusChanged,
      weak_factory_.GetWeakPtr(), std::move(registration), version,
      std::move(disallow_controller)));
}

void ServiceWorkerControlleeRequestHandler::PrepareForSubResource() {
  DCHECK(!JobWasCanceled());
  DCHECK(context_);

  // When this request handler was created, the provider host had a controller
  // and hence an active version, but by the time MaybeCreateJob() is called
  // the active version may have been lost. This happens when
  // ServiceWorkerRegistration::DeleteVersion() was called to delete the worker
  // because a permanent failure occurred when trying to start it.
  //
  // As this is an exceptional case, just error out.
  ServiceWorkerVersion* controller = provider_host_->controller();
  if (!controller) {
    url_job_->FailDueToLostController();
    return;
  }

  MaybeForwardToServiceWorker(url_job_.get(), controller);
}

void ServiceWorkerControlleeRequestHandler::OnPrepareToRestart() {
  use_network_ = true;
  ClearJob();
}

ServiceWorkerVersion*
ServiceWorkerControlleeRequestHandler::GetServiceWorkerVersion(
    ServiceWorkerMetrics::URLRequestJobResult* result) {
  if (!provider_host_) {
    *result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_NO_PROVIDER_HOST;
    return nullptr;
  }
  if (!provider_host_->controller()) {
    *result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_NO_ACTIVE_VERSION;
    return nullptr;
  }
  return provider_host_->controller();
}

bool ServiceWorkerControlleeRequestHandler::RequestStillValid(
    ServiceWorkerMetrics::URLRequestJobResult* result) {
  // A null |provider_host_| probably means the tab was closed. The null value
  // would cause problems down the line, so bail out.
  if (!provider_host_) {
    *result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_NO_PROVIDER_HOST;
    return false;
  }
  return true;
}

void ServiceWorkerControlleeRequestHandler::MainResourceLoadFailed() {
  DCHECK(provider_host_);
  // Detach the controller so subresource requests also skip the worker.
  provider_host_->NotifyControllerLost();
}

void ServiceWorkerControlleeRequestHandler::ReportDestination(
    ServiceWorkerMetrics::MainResourceRequestDestination destination) {
  DCHECK(is_main_resource_load_);
  tracker_->RecordDestination(destination);
}

void ServiceWorkerControlleeRequestHandler::
    WillDispatchFetchEventForMainResource() {
  DCHECK(is_main_resource_load_);
  tracker_->WillDispatchFetchEvent();
}

void ServiceWorkerControlleeRequestHandler::ClearJob() {
  url_job_.reset();
}

bool ServiceWorkerControlleeRequestHandler::JobWasCanceled() const {
  return !url_job_ || url_job_->WasCanceled();
}

}  // namespace content
