// Copyright 2017 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_navigation_loader.h"

#include <sstream>
#include <utility>

#include "base/metrics/histogram_macros.h"
#include "base/optional.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/url_loader_factory_getter.h"
#include "content/common/service_worker/service_worker_loader_helpers.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_request_info.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/fetch_api.mojom.h"

namespace content {

namespace {

std::string ComposeFetchEventResultString(
    ServiceWorkerFetchDispatcher::FetchEventResult result,
    const blink::mojom::FetchAPIResponse& response) {
  if (result == ServiceWorkerFetchDispatcher::FetchEventResult::kShouldFallback)
    return "Fallback to network";
  std::stringstream stream;
  stream << "Got response (status_code: " << response.status_code
         << " status_text: '" << response.status_text << "')";
  return stream.str();
}

bool BodyHasNoDataPipeGetters(const network::ResourceRequestBody* body) {
  if (!body)
    return true;
  for (const auto& elem : *body->elements()) {
    if (elem.type() == network::DataElement::TYPE_DATA_PIPE)
      return false;
  }
  return true;
}

}  // namespace

// This class waits for completion of a stream response from the service worker.
// It calls ServiceWorkerNavigationLoader::CommitCompleted() upon completion of
// the response.
class ServiceWorkerNavigationLoader::StreamWaiter
    : public blink::mojom::ServiceWorkerStreamCallback {
 public:
  StreamWaiter(
      ServiceWorkerNavigationLoader* owner,
      scoped_refptr<ServiceWorkerVersion> streaming_version,
      blink::mojom::ServiceWorkerStreamCallbackRequest callback_request)
      : owner_(owner),
        streaming_version_(streaming_version),
        binding_(this, std::move(callback_request)) {
    streaming_version_->OnStreamResponseStarted();
    binding_.set_connection_error_handler(
        base::BindOnce(&StreamWaiter::OnAborted, base::Unretained(this)));
  }
  ~StreamWaiter() override { streaming_version_->OnStreamResponseFinished(); }

  // Implements mojom::ServiceWorkerStreamCallback.
  void OnCompleted() override {
    // Destroys |this|.
    owner_->CommitCompleted(net::OK, "Stream has completed.");
  }
  void OnAborted() override {
    // Destroys |this|.
    owner_->CommitCompleted(net::ERR_ABORTED, "Stream has aborted.");
  }

 private:
  ServiceWorkerNavigationLoader* owner_;
  scoped_refptr<ServiceWorkerVersion> streaming_version_;
  mojo::Binding<blink::mojom::ServiceWorkerStreamCallback> binding_;

  DISALLOW_COPY_AND_ASSIGN(StreamWaiter);
};

ServiceWorkerNavigationLoader::ServiceWorkerNavigationLoader(
    NavigationLoaderInterceptor::LoaderCallback callback,
    NavigationLoaderInterceptor::FallbackCallback fallback_callback,
    Delegate* delegate,
    const network::ResourceRequest& tentative_resource_request,
    base::WeakPtr<ServiceWorkerProviderHost> provider_host,
    scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter)
    : loader_callback_(std::move(callback)),
      fallback_callback_(std::move(fallback_callback)),
      delegate_(delegate),
      provider_host_(std::move(provider_host)),
      url_loader_factory_getter_(std::move(url_loader_factory_getter)),
      binding_(this),
      weak_factory_(this) {
  TRACE_EVENT_WITH_FLOW1(
      "ServiceWorker",
      "ServiceWorkerNavigationLoader::ServiceWorkerNavigationloader", this,
      TRACE_EVENT_FLAG_FLOW_OUT, "url", tentative_resource_request.url.spec());

  DCHECK(delegate_);
  DCHECK(ServiceWorkerUtils::IsMainResourceType(
      static_cast<ResourceType>(tentative_resource_request.resource_type)));

  response_head_.load_timing.request_start = base::TimeTicks::Now();
  response_head_.load_timing.request_start_time = base::Time::Now();

  // Beware that the final resource request may change due to throttles, so
  // don't save |tentative_resource_request| here. We'll get the real one in
  // StartRequest.
}

ServiceWorkerNavigationLoader::~ServiceWorkerNavigationLoader() {
  TRACE_EVENT_WITH_FLOW0(
      "ServiceWorker",
      "ServiceWorkerNavigationLoader::~ServiceWorkerNavigationloader", this,
      TRACE_EVENT_FLAG_FLOW_IN);
};

void ServiceWorkerNavigationLoader::FallbackToNetwork() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  TRACE_EVENT_WITH_FLOW0(
      "ServiceWorker", "ServiceWorkerNavigationLoader::FallbackToNetwork", this,
      TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  // The URLJobWrapper only calls this if this loader never intercepted the
  // request. Fallback to network after interception uses |fallback_callback_|
  // instead.
  DCHECK_EQ(response_type_, ResponseType::NOT_DETERMINED);
  response_type_ = ResponseType::FALLBACK_TO_NETWORK;

  TransitionToStatus(Status::kCompleted);

  std::move(loader_callback_).Run({});
}

void ServiceWorkerNavigationLoader::ForwardToServiceWorker() {
  TRACE_EVENT_WITH_FLOW0(
      "ServiceWorker", "ServiceWorkerNavigationLoader::ForwardToServiceWorker",
      this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  DCHECK_EQ(status_, Status::kNotStarted);
  DCHECK_EQ(response_type_, ResponseType::NOT_DETERMINED);

  response_type_ = ResponseType::FORWARD_TO_SERVICE_WORKER;

  std::move(loader_callback_)
      .Run(base::BindOnce(&ServiceWorkerNavigationLoader::StartRequest,
                          weak_factory_.GetWeakPtr()));
}

bool ServiceWorkerNavigationLoader::ShouldFallbackToNetwork() {
  return response_type_ == ResponseType::FALLBACK_TO_NETWORK;
}

bool ServiceWorkerNavigationLoader::ShouldForwardToServiceWorker() {
  return response_type_ == ResponseType::FORWARD_TO_SERVICE_WORKER;
}

void ServiceWorkerNavigationLoader::DetachedFromRequest() {
  delegate_ = nullptr;
  DeleteIfNeeded();
}

base::WeakPtr<ServiceWorkerNavigationLoader>
ServiceWorkerNavigationLoader::AsWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

void ServiceWorkerNavigationLoader::StartRequest(
    const network::ResourceRequest& resource_request,
    network::mojom::URLLoaderRequest request,
    network::mojom::URLLoaderClientPtr client) {
  resource_request_ = resource_request;
  if (provider_host_ && provider_host_->fetch_request_window_id()) {
    resource_request_.fetch_window_id =
        base::make_optional(provider_host_->fetch_request_window_id());
  }

  DCHECK(delegate_);
  DCHECK(!binding_.is_bound());
  DCHECK(!url_loader_client_.is_bound());
  binding_.Bind(std::move(request));
  binding_.set_connection_error_handler(
      base::BindOnce(&ServiceWorkerNavigationLoader::OnConnectionClosed,
                     base::Unretained(this)));
  url_loader_client_ = std::move(client);

  DCHECK_EQ(ResponseType::FORWARD_TO_SERVICE_WORKER, response_type_);
  TransitionToStatus(Status::kStarted);

  TRACE_EVENT_WITH_FLOW0("ServiceWorker",
                         "ServiceWorkerNavigationLoader::StartRequest", this,
                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);

  ServiceWorkerMetrics::URLRequestJobResult result =
      ServiceWorkerMetrics::REQUEST_JOB_ERROR_BAD_DELEGATE;
  ServiceWorkerVersion* active_worker =
      delegate_->GetServiceWorkerVersion(&result);
  if (!active_worker) {
    CommitCompleted(net::ERR_FAILED, "No active worker");
    return;
  }

  // ServiceWorkerFetchDispatcher requires a std::unique_ptr<ResourceRequest>
  // so make one here.
  // TODO(crbug.com/803125): Try to eliminate unnecessary copying?
  auto resource_request_to_pass =
      std::make_unique<network::ResourceRequest>(resource_request_);

  // Passing the request body over Mojo moves out the DataPipeGetter elements,
  // which would mean we should clone the body like
  // ServiceWorkerSubresourceLoader does. But we don't expect DataPipeGetters
  // here yet: they are only created by the renderer when converting from a
  // Blob, which doesn't happen for navigations. In interest of speed, just
  // don't clone until proven necessary.
  DCHECK(BodyHasNoDataPipeGetters(resource_request_to_pass->request_body.get()))
      << "We assumed there would be no data pipe getter elements here, but "
         "there are. Add code here to clone the body before proceeding.";

  if (!provider_host_) {
    // We lost |provider_host_| (for the client) somehow before dispatching
    // FetchEvent.
    CommitCompleted(net::ERR_ABORTED, "No provider host");
    return;
  }

  // Dispatch the fetch event.
  fetch_dispatcher_ = std::make_unique<ServiceWorkerFetchDispatcher>(
      std::move(resource_request_to_pass),
      std::string() /* request_body_blob_uuid */,
      0 /* request_body_blob_size */, nullptr /* request_body_blob */,
      provider_host_->client_uuid(), active_worker,
      net::NetLogWithSource() /* TODO(scottmg): net log? */,
      base::BindOnce(&ServiceWorkerNavigationLoader::DidPrepareFetchEvent,
                     weak_factory_.GetWeakPtr(),
                     base::WrapRefCounted(active_worker),
                     active_worker->running_status()),
      base::BindOnce(&ServiceWorkerNavigationLoader::DidDispatchFetchEvent,
                     weak_factory_.GetWeakPtr()));
  did_navigation_preload_ =
      fetch_dispatcher_->MaybeStartNavigationPreloadWithURLLoader(
          resource_request_, url_loader_factory_getter_.get(),
          base::DoNothing(/* TODO(crbug/762357): metrics? */));

  // Record worker start time here as |fetch_dispatcher_| will start a service
  // worker if there is no running service worker.
  response_head_.service_worker_start_time = base::TimeTicks::Now();
  fetch_dispatcher_->Run();
}

void ServiceWorkerNavigationLoader::CommitResponseHeaders() {
  DCHECK(url_loader_client_.is_bound());
  TRACE_EVENT_WITH_FLOW2(
      "ServiceWorker", "ServiceWorkerNavigationLoader::CommitResponseHeaders",
      this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
      "response_code", response_head_.headers->response_code(), "status_text",
      response_head_.headers->GetStatusText());
  TransitionToStatus(Status::kSentHeader);
  url_loader_client_->OnReceiveResponse(response_head_);
}

void ServiceWorkerNavigationLoader::CommitResponseBody(
    mojo::ScopedDataPipeConsumerHandle response_body) {
  TransitionToStatus(Status::kSentBody);
  url_loader_client_->OnStartLoadingResponseBody(std::move(response_body));
}

void ServiceWorkerNavigationLoader::CommitResponseBodyEmpty() {
  TransitionToStatus(Status::kSentBody);
  mojo::DataPipe pipe;
  url_loader_client_->OnStartLoadingResponseBody(
      std::move(pipe.consumer_handle));
  // pipe.producer_handle is closed here.
}

void ServiceWorkerNavigationLoader::CommitCompleted(int error_code,
                                                    const char* reason) {
  TRACE_EVENT_WITH_FLOW2(
      "ServiceWorker", "ServiceWorkerNavigationLoader::CommitCompleted", this,
      TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "error_code",
      net::ErrorToString(error_code), "reason", TRACE_STR_COPY(reason));

  DCHECK(url_loader_client_.is_bound());
  TransitionToStatus(Status::kCompleted);
  if (error_code == net::OK)
    RecordTimingMetrics(true);

  // |stream_waiter_| calls this when done.
  stream_waiter_.reset();

  url_loader_client_->OnComplete(
      network::URLLoaderCompletionStatus(error_code));
}

void ServiceWorkerNavigationLoader::DidPrepareFetchEvent(
    scoped_refptr<ServiceWorkerVersion> version,
    EmbeddedWorkerStatus initial_worker_status) {
  TRACE_EVENT_WITH_FLOW1(
      "ServiceWorker", "ServiceWorkerNavigationLoader::DidPrepareFetchEvent",
      this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
      "initial_worker_status",
      EmbeddedWorkerInstance::StatusToString(initial_worker_status));

  // At this point a service worker is running and the fetch event is about
  // to dispatch. Record some load timings.
  base::TimeTicks now = base::TimeTicks::Now();
  response_head_.service_worker_ready_time = now;
  response_head_.load_timing.send_start = now;
  response_head_.load_timing.send_end = now;

  devtools_attached_ = version->embedded_worker()->devtools_attached();

  // Note that we don't record worker preparation time in S13nServiceWorker
  // path for now. If we want to measure worker preparation time we can
  // calculate it from response_head_.service_worker_ready_time and
  // response_head_.load_timing.request_start.
  // https://crbug.com/852664
  ServiceWorkerMetrics::RecordActivatedWorkerPreparationForMainFrame(
      base::TimeDelta(), initial_worker_status,
      version->embedded_worker()->start_situation(), did_navigation_preload_,
      resource_request_.url);
}

void ServiceWorkerNavigationLoader::DidDispatchFetchEvent(
    blink::ServiceWorkerStatusCode status,
    ServiceWorkerFetchDispatcher::FetchEventResult fetch_result,
    blink::mojom::FetchAPIResponsePtr response,
    blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
    blink::mojom::ServiceWorkerFetchEventTimingPtr timing,
    scoped_refptr<ServiceWorkerVersion> version) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK_EQ(status_, Status::kStarted);

  TRACE_EVENT_WITH_FLOW2(
      "ServiceWorker", "ServiceWorkerNavigationLoader::DidDispatchFetchEvent",
      this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "status",
      blink::ServiceWorkerStatusToString(status), "result",
      ComposeFetchEventResultString(fetch_result, *response));

  ServiceWorkerMetrics::RecordFetchEventStatus(true /* is_main_resource */,
                                               status);
  ServiceWorkerMetrics::URLRequestJobResult result =
      ServiceWorkerMetrics::REQUEST_JOB_ERROR_BAD_DELEGATE;
  if (!delegate_ || !delegate_->RequestStillValid(&result)) {
    // The navigation or shared worker startup is cancelled. Just abort.
    CommitCompleted(net::ERR_ABORTED, "No delegate");
    return;
  }

  fetch_event_timing_ = std::move(timing);

  if (status != blink::ServiceWorkerStatusCode::kOk) {
    // Dispatching the event to the service worker failed. Do a last resort
    // attempt to load the page via network as if there was no service worker.
    // It'd be more correct and simpler to remove this path and show an error
    // page, but the risk is that the user will be stuck if there's a persistent
    // failure.
    delegate_->MainResourceLoadFailed();
    std::move(fallback_callback_)
        .Run(true /* reset_subresource_loader_params */);
    return;
  }

  if (fetch_result ==
      ServiceWorkerFetchDispatcher::FetchEventResult::kShouldFallback) {
    TransitionToStatus(Status::kCompleted);
    RecordTimingMetrics(false);
    // TODO(falken): Propagate the timing info to the renderer somehow, or else
    // Navigation Timing etc APIs won't know about service worker.
    std::move(fallback_callback_)
        .Run(false /* reset_subresource_loader_params */);
    return;
  }

  DCHECK_EQ(fetch_result,
            ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse);

  // A response with status code 0 is Blink telling us to respond with
  // network error.
  if (response->status_code == 0) {
    // TODO(falken): Use more specific errors. Or just add ERR_SERVICE_WORKER?
    CommitCompleted(net::ERR_FAILED, "Zero response status");
    return;
  }

  StartResponse(std::move(response), std::move(version),
                std::move(body_as_stream));
}

void ServiceWorkerNavigationLoader::StartResponse(
    blink::mojom::FetchAPIResponsePtr response,
    scoped_refptr<ServiceWorkerVersion> version,
    blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK_EQ(status_, Status::kStarted);

  ServiceWorkerLoaderHelpers::SaveResponseInfo(*response, &response_head_);
  ServiceWorkerLoaderHelpers::SaveResponseHeaders(
      response->status_code, response->status_text, response->headers,
      &response_head_);

  response_head_.did_service_worker_navigation_preload =
      did_navigation_preload_;
  response_head_.load_timing.receive_headers_end = base::TimeTicks::Now();

  // Make the navigated page inherit the SSLInfo from its controller service
  // worker's script. This affects the HTTPS padlock, etc, shown by the
  // browser. See https://crbug.com/392409 for details about this design.
  // TODO(horo): When we support mixed-content (HTTP) no-cors requests from a
  // ServiceWorker, we have to check the security level of the responses.
  response_head_.ssl_info = version->GetMainScriptHttpResponseInfo()->ssl_info;

  // Handle a redirect response. ComputeRedirectInfo returns non-null redirect
  // info if the given response is a redirect.
  base::Optional<net::RedirectInfo> redirect_info =
      ServiceWorkerLoaderHelpers::ComputeRedirectInfo(resource_request_,
                                                      response_head_);
  if (redirect_info) {
    TRACE_EVENT_WITH_FLOW2(
        "ServiceWorker", "ServiceWorkerNavigationLoader::StartResponse", this,
        TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "result",
        "redirect", "redirect url", redirect_info->new_url.spec());

    response_head_.encoded_data_length = 0;
    url_loader_client_->OnReceiveRedirect(*redirect_info, response_head_);
    // Our client is the navigation loader, which will start a new URLLoader for
    // the redirect rather than calling FollowRedirect(), so we're done here.
    TransitionToStatus(Status::kCompleted);
    return;
  }

  // We have a non-redirect response. Send the headers to the client.
  CommitResponseHeaders();

  // Handle a stream response body.
  if (!body_as_stream.is_null() && body_as_stream->stream.is_valid()) {
    TRACE_EVENT_WITH_FLOW1("ServiceWorker",
                           "ServiceWorkerNavigationLoader::StartResponse", this,
                           TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
                           "result", "stream response");
    stream_waiter_ = std::make_unique<StreamWaiter>(
        this, std::move(version), std::move(body_as_stream->callback_request));
    CommitResponseBody(std::move(body_as_stream->stream));
    // StreamWaiter will call CommitCompleted() when done.
    return;
  }

  // Handle a blob response body.
  if (response->blob) {
    DCHECK(response->blob->blob.is_valid());
    body_as_blob_.Bind(std::move(response->blob->blob));
    mojo::ScopedDataPipeConsumerHandle data_pipe;
    int error = ServiceWorkerLoaderHelpers::ReadBlobResponseBody(
        &body_as_blob_, response->blob->size,
        base::BindOnce(&ServiceWorkerNavigationLoader::OnBlobReadingComplete,
                       weak_factory_.GetWeakPtr()),
        &data_pipe);
    if (error != net::OK) {
      CommitResponseBodyEmpty();
      CommitCompleted(error, "Failed to read blob body");
      return;
    }
    TRACE_EVENT_WITH_FLOW1("ServiceWorker",
                           "ServiceWorkerNavigationLoader::StartResponse", this,
                           TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
                           "result", "blob response");

    CommitResponseBody(std::move(data_pipe));
    // We continue in OnBlobReadingComplete().
    return;
  }

  TRACE_EVENT_WITH_FLOW1("ServiceWorker",
                         "ServiceWorkerNavigationLoader::StartResponse", this,
                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
                         "result", "no body");

  CommitResponseBodyEmpty();
  CommitCompleted(net::OK, "No body exists.");
}

// URLLoader implementation----------------------------------------

void ServiceWorkerNavigationLoader::FollowRedirect(
    const base::Optional<std::vector<std::string>>&
        to_be_removed_request_headers,
    const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
  NOTIMPLEMENTED();
}

void ServiceWorkerNavigationLoader::ProceedWithResponse() {
  // ServiceWorkerNavigationLoader doesn't need to wait for
  // ProceedWithResponse() since it doesn't use MojoAsyncResourceHandler to load
  // the resource request.
}

void ServiceWorkerNavigationLoader::SetPriority(net::RequestPriority priority,
                                                int32_t intra_priority_value) {
  NOTIMPLEMENTED();
}

void ServiceWorkerNavigationLoader::PauseReadingBodyFromNet() {}

void ServiceWorkerNavigationLoader::ResumeReadingBodyFromNet() {}

void ServiceWorkerNavigationLoader::OnBlobReadingComplete(int net_error) {
  CommitCompleted(net_error, "Blob has been read.");
  body_as_blob_.reset();
}

void ServiceWorkerNavigationLoader::OnConnectionClosed() {
  TRACE_EVENT_WITH_FLOW0(
      "ServiceWorker", "ServiceWorkerNavigationLoader::OnConnectionClosed",
      this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);

  // The fetch dispatcher or stream waiter may still be running. Don't let them
  // do callbacks back to this loader, since it is now done with the request.
  // TODO(falken): Try to move this to CommitCompleted(), since the same
  // justification applies there too.
  weak_factory_.InvalidateWeakPtrs();
  fetch_dispatcher_.reset();
  stream_waiter_.reset();
  binding_.Close();

  // Respond to the request if it's not yet responded to.
  if (status_ != Status::kCompleted)
    CommitCompleted(net::ERR_ABORTED, "Disconnected pipe before completed");

  url_loader_client_.reset();
  DeleteIfNeeded();
}

void ServiceWorkerNavigationLoader::DeleteIfNeeded() {
  if (!binding_.is_bound() && !delegate_)
    delete this;
}

void ServiceWorkerNavigationLoader::RecordTimingMetrics(bool handled) {
  DCHECK(fetch_event_timing_);
  DCHECK(!completion_time_.is_null());

  // We only record these metrics for top-level navigation.
  if (resource_request_.resource_type != RESOURCE_TYPE_MAIN_FRAME)
    return;

  // |fetch_event_timing_| is recorded in renderer so we can get reasonable
  // metrics only when TimeTicks are consistent across processes.
  if (!base::TimeTicks::IsHighResolution() ||
      !base::TimeTicks::IsConsistentAcrossProcesses())
    return;

  // Don't record metrics when DevTools is attached to reduce noise.
  if (devtools_attached_)
    return;

  // Time between the request is made and the request is routed to this loader.
  UMA_HISTOGRAM_TIMES(
      "ServiceWorker.LoadTiming.MainFrame.MainResource."
      "StartToForwardServiceWorker",
      response_head_.service_worker_start_time -
          response_head_.load_timing.request_start);

  // Time spent for service worker startup.
  UMA_HISTOGRAM_TIMES(
      "ServiceWorker.LoadTiming.MainFrame.MainResource."
      "ForwardServiceWorkerToWorkerReady",
      response_head_.service_worker_ready_time -
          response_head_.service_worker_start_time);

  // Browser -> Renderer IPC delay.
  UMA_HISTOGRAM_TIMES(
      "ServiceWorker.LoadTiming.MainFrame.MainResource."
      "WorkerReadyToFetchHandlerStart",
      fetch_event_timing_->dispatch_event_time -
          response_head_.service_worker_ready_time);

  // Time spent by fetch handlers.
  UMA_HISTOGRAM_TIMES(
      "ServiceWorker.LoadTiming.MainFrame.MainResource."
      "FetchHandlerStartToFetchHandlerEnd",
      fetch_event_timing_->respond_with_settled_time -
          fetch_event_timing_->dispatch_event_time);

  if (handled) {
    // Renderer -> Browser IPC delay.
    UMA_HISTOGRAM_TIMES(
        "ServiceWorker.LoadTiming.MainFrame.MainResource."
        "FetchHandlerEndToResponseReceived",
        response_head_.load_timing.receive_headers_end -
            fetch_event_timing_->respond_with_settled_time);

    // Time spent reading response body.
    UMA_HISTOGRAM_TIMES(
        "ServiceWorker.LoadTiming.MainFrame.MainResource."
        "ResponseReceivedToCompleted",
        completion_time_ - response_head_.load_timing.receive_headers_end);
  } else {
    // Renderer -> Browser IPC delay (network fallback case).
    UMA_HISTOGRAM_TIMES(
        "ServiceWorker.LoadTiming.MainFrame.MainResource."
        "FetchHandlerEndToFallbackNetwork",
        completion_time_ - fetch_event_timing_->respond_with_settled_time);
  }
}

void ServiceWorkerNavigationLoader::TransitionToStatus(Status new_status) {
#if DCHECK_IS_ON()
  switch (new_status) {
    case Status::kNotStarted:
      NOTREACHED();
      break;
    case Status::kStarted:
      DCHECK_EQ(status_, Status::kNotStarted);
      break;
    case Status::kSentHeader:
      DCHECK_EQ(status_, Status::kStarted);
      break;
    case Status::kSentBody:
      DCHECK_EQ(status_, Status::kSentHeader);
      break;
    case Status::kCompleted:
      DCHECK(
          // Network fallback before interception.
          status_ == Status::kNotStarted ||
          // Network fallback after interception.
          status_ == Status::kStarted ||
          // Success case or error while sending the response's body.
          status_ == Status::kSentBody);
      break;
  }
#endif  // DCHECK_IS_ON()

  status_ = new_status;
  if (new_status == Status::kCompleted)
    completion_time_ = base::TimeTicks::Now();
}

}  // namespace content
