// 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/renderer/service_worker/service_worker_subresource_loader.h"

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

#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/content_features.h"
#include "content/public/common/resource_type.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/renderer/service_worker/controller_service_worker_connector.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
#include "net/http/http_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_data_pipe_getter.h"
#include "services/network/test/test_url_loader_client.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_container.mojom.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "url/origin.h"

namespace content {
namespace service_worker_subresource_loader_unittest {

// A simple blob implementation for serving data stored in a vector.
class FakeBlob final : public blink::mojom::Blob {
 public:
  FakeBlob(base::Optional<std::vector<uint8_t>> side_data, std::string body)
      : side_data_(std::move(side_data)), body_(std::move(body)) {}

 private:
  // Implements blink::mojom::Blob.
  void Clone(blink::mojom::BlobRequest) override { NOTREACHED(); }
  void AsDataPipeGetter(network::mojom::DataPipeGetterRequest) override {
    NOTREACHED();
  }
  void ReadRange(uint64_t offset,
                 uint64_t length,
                 mojo::ScopedDataPipeProducerHandle handle,
                 blink::mojom::BlobReaderClientPtr client) override {
    NOTREACHED();
  }
  void ReadAll(mojo::ScopedDataPipeProducerHandle handle,
               blink::mojom::BlobReaderClientPtr client) override {
    EXPECT_TRUE(mojo::BlockingCopyFromString(body_, handle));
    if (client) {
      client->OnCalculatedSize(body_.size(), body_.size());
      client->OnComplete(net::OK, body_.size());
    }
  }
  void ReadSideData(ReadSideDataCallback callback) override {
    std::move(callback).Run(side_data_);
  }
  void GetInternalUUID(GetInternalUUIDCallback callback) override {
    NOTREACHED();
  }

  base::Optional<std::vector<uint8_t>> side_data_;
  std::string body_;
};

// A simple URLLoaderFactory that responds with status 200 to every request.
// This is the default network loader factory for
// ServiceWorkerSubresourceLoaderTest.
class FakeNetworkURLLoaderFactory final
    : public network::mojom::URLLoaderFactory {
 public:
  FakeNetworkURLLoaderFactory() = default;

  // network::mojom::URLLoaderFactory implementation.
  void CreateLoaderAndStart(network::mojom::URLLoaderRequest request,
                            int32_t routing_id,
                            int32_t request_id,
                            uint32_t options,
                            const network::ResourceRequest& url_request,
                            network::mojom::URLLoaderClientPtr client,
                            const net::MutableNetworkTrafficAnnotationTag&
                                traffic_annotation) override {
    std::string headers = "HTTP/1.1 200 OK\n\n";
    net::HttpResponseInfo info;
    info.headers = new net::HttpResponseHeaders(
        net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.length()));
    network::ResourceResponseHead response;
    response.headers = info.headers;
    response.headers->GetMimeType(&response.mime_type);
    client->OnReceiveResponse(response);

    std::string body = "this body came from the network";
    uint32_t bytes_written = body.size();
    mojo::DataPipe data_pipe;
    data_pipe.producer_handle->WriteData(body.data(), &bytes_written,
                                         MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
    client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));

    network::URLLoaderCompletionStatus status;
    status.error_code = net::OK;
    client->OnComplete(status);
  }

  void Clone(network::mojom::URLLoaderFactoryRequest factory) override {
    NOTREACHED();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(FakeNetworkURLLoaderFactory);
};

class FakeControllerServiceWorker
    : public blink::mojom::ControllerServiceWorker {
 public:
  FakeControllerServiceWorker() = default;
  ~FakeControllerServiceWorker() override = default;

  static blink::mojom::FetchAPIResponsePtr OkResponse(
      blink::mojom::SerializedBlobPtr blob_body,
      network::mojom::FetchResponseSource response_source) {
    auto response = blink::mojom::FetchAPIResponse::New();
    response->status_code = 200;
    response->status_text = "OK";
    response->response_type = network::mojom::FetchResponseType::kDefault;
    response->response_source = response_source;
    response->blob = std::move(blob_body);
    if (response->blob) {
      response->headers.emplace("Content-Length",
                                base::NumberToString(response->blob->size));
    }
    return response;
  }

  static blink::mojom::FetchAPIResponsePtr ErrorResponse() {
    auto response = blink::mojom::FetchAPIResponse::New();
    response->status_code = 0;
    response->response_type = network::mojom::FetchResponseType::kDefault;
    response->error =
        blink::mojom::ServiceWorkerResponseError::kPromiseRejected;
    return response;
  }

  static blink::mojom::FetchAPIResponsePtr RedirectResponse(
      const std::string& redirect_location_header) {
    auto response = blink::mojom::FetchAPIResponse::New();
    response->status_code = 302;
    response->status_text = "Found";
    response->response_type = network::mojom::FetchResponseType::kDefault;
    response->headers["Location"] = redirect_location_header;
    return response;
  }

  void CloseAllBindings() { bindings_.CloseAllBindings(); }

  // Tells this controller to abort the fetch event without a response.
  // i.e., simulate the service worker failing to handle the fetch event.
  void AbortEventWithNoResponse() { response_mode_ = ResponseMode::kAbort; }

  // Tells this controller to respond to fetch events with network fallback.
  // i.e., simulate the service worker not calling respondWith().
  void RespondWithFallback() {
    response_mode_ = ResponseMode::kFallbackResponse;
  }

  // Tells this controller to respond to fetch events with the specified stream.
  void RespondWithStream(
      blink::mojom::ServiceWorkerStreamCallbackRequest callback_request,
      mojo::ScopedDataPipeConsumerHandle consumer_handle) {
    response_mode_ = ResponseMode::kStream;
    stream_handle_ = blink::mojom::ServiceWorkerStreamHandle::New();
    stream_handle_->callback_request = std::move(callback_request);
    stream_handle_->stream = std::move(consumer_handle);
  }

  // Tells this controller to respond to fetch events with a error response.
  void RespondWithError() { response_mode_ = ResponseMode::kErrorResponse; }

  // Tells this controller to respond to fetch events with a redirect response.
  void RespondWithRedirect(const std::string& redirect_location_header) {
    response_mode_ = ResponseMode::kRedirectResponse;
    redirect_location_header_ = redirect_location_header;
  }

  // Tells this controller to respond to fetch events with a blob response body.
  void RespondWithBlob(base::Optional<std::vector<uint8_t>> metadata,
                       std::string body) {
    response_mode_ = ResponseMode::kBlob;
    blob_body_ = blink::mojom::SerializedBlob::New();
    blob_body_->uuid = "dummy-blob-uuid";
    blob_body_->size = body.size();
    mojo::MakeStrongBinding(
        std::make_unique<FakeBlob>(std::move(metadata), std::move(body)),
        mojo::MakeRequest(&blob_body_->blob));
  }

  // Tells this controller to respond to fetch events with a 206 partial
  // response, returning a blob composed of the requested bytes of |body|
  // according to the request headers.
  void RespondWithBlobRange(std::string body) {
    response_mode_ = ResponseMode::kBlobRange;
    blob_range_body_ = body;
  }

  void ReadRequestBody(std::string* out_string) {
    ASSERT_TRUE(request_body_);
    std::vector<network::DataElement>* elements =
        request_body_->elements_mutable();
    // So far this test expects a single element (bytes or data pipe).
    ASSERT_EQ(1u, elements->size());
    network::DataElement& element = elements->front();
    if (element.type() == network::DataElement::TYPE_BYTES) {
      *out_string = std::string(element.bytes(), element.length());
    } else if (element.type() == network::DataElement::TYPE_DATA_PIPE) {
      // Read the content into |data_pipe|.
      mojo::DataPipe data_pipe;
      network::mojom::DataPipeGetterPtr ptr(element.ReleaseDataPipeGetter());
      base::RunLoop run_loop;
      ptr->Read(
          std::move(data_pipe.producer_handle),
          base::BindOnce([](const base::Closure& quit_closure, int32_t status,
                            uint64_t size) { quit_closure.Run(); },
                         run_loop.QuitClosure()));
      run_loop.Run();
      // Copy the content to |out_string|.
      mojo::BlockingCopyToString(std::move(data_pipe.consumer_handle),
                                 out_string);
    } else {
      NOTREACHED();
    }
  }

  void SetResponseSource(network::mojom::FetchResponseSource source) {
    response_source_ = source;
  }

  // blink::mojom::ControllerServiceWorker:
  void DispatchFetchEvent(
      blink::mojom::DispatchFetchEventParamsPtr params,
      blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
      DispatchFetchEventCallback callback) override {
    EXPECT_FALSE(params->request->is_main_resource_load);
    if (params->request->body)
      request_body_ = params->request->body.value();

    fetch_event_count_++;
    fetch_event_request_ = std::move(params->request);

    auto timing = blink::mojom::ServiceWorkerFetchEventTiming::New();
    timing->dispatch_event_time = base::TimeTicks::Now();

    switch (response_mode_) {
      case ResponseMode::kDefault:
        response_callback->OnResponse(
            OkResponse(nullptr /* blob_body */, response_source_),
            std::move(timing));
        std::move(callback).Run(
            blink::mojom::ServiceWorkerEventStatus::COMPLETED);
        break;
      case ResponseMode::kAbort:
        std::move(callback).Run(
            blink::mojom::ServiceWorkerEventStatus::ABORTED);
        break;
      case ResponseMode::kStream:
        response_callback->OnResponseStream(
            OkResponse(nullptr /* blob_body */, response_source_),
            std::move(stream_handle_), std::move(timing));
        std::move(callback).Run(
            blink::mojom::ServiceWorkerEventStatus::COMPLETED);
        break;
      case ResponseMode::kBlob:
        response_callback->OnResponse(
            OkResponse(std::move(blob_body_), response_source_),
            std::move(timing));
        std::move(callback).Run(
            blink::mojom::ServiceWorkerEventStatus::COMPLETED);
        break;

      case ResponseMode::kBlobRange: {
        // Parse the Range header.
        std::string range_header;
        std::vector<net::HttpByteRange> ranges;
        ASSERT_TRUE(fetch_event_request_->headers.contains(
            std::string(net::HttpRequestHeaders::kRange)));
        ASSERT_TRUE(net::HttpUtil::ParseRangeHeader(
            fetch_event_request_->headers[net::HttpRequestHeaders::kRange],
            &ranges));
        ASSERT_EQ(1u, ranges.size());
        ASSERT_TRUE(ranges[0].ComputeBounds(blob_range_body_.size()));
        const net::HttpByteRange& range = ranges[0];

        // Build a Blob composed of the requested bytes from |blob_range_body_|.
        size_t start = static_cast<size_t>(range.first_byte_position());
        size_t end = static_cast<size_t>(range.last_byte_position());
        size_t size = end - start + 1;
        std::string body = blob_range_body_.substr(start, size);
        auto blob = blink::mojom::SerializedBlob::New();
        blob->uuid = "dummy-blob-uuid";
        blob->size = size;
        mojo::MakeStrongBinding(std::make_unique<FakeBlob>(base::nullopt, body),
                                mojo::MakeRequest(&blob->blob));

        // Respond with a 206 response.
        auto response = OkResponse(std::move(blob), response_source_);
        response->status_code = 206;
        response->headers.emplace(
            "Content-Range", base::StringPrintf("bytes %zu-%zu/%zu", start, end,
                                                blob_range_body_.size()));
        response_callback->OnResponse(std::move(response), std::move(timing));
        std::move(callback).Run(
            blink::mojom::ServiceWorkerEventStatus::COMPLETED);
        break;
      }

      case ResponseMode::kFallbackResponse:
        response_callback->OnFallback(std::move(timing));
        std::move(callback).Run(
            blink::mojom::ServiceWorkerEventStatus::COMPLETED);
        break;
      case ResponseMode::kErrorResponse:
        response_callback->OnResponse(ErrorResponse(), std::move(timing));
        std::move(callback).Run(
            blink::mojom::ServiceWorkerEventStatus::REJECTED);
        break;
      case ResponseMode::kRedirectResponse: {
        response_callback->OnResponse(
            RedirectResponse(redirect_location_header_), std::move(timing));
        std::move(callback).Run(
            blink::mojom::ServiceWorkerEventStatus::COMPLETED);
        break;
      }
    }
    if (fetch_event_callback_)
      std::move(fetch_event_callback_).Run();
  }

  void Clone(blink::mojom::ControllerServiceWorkerRequest request) override {
    bindings_.AddBinding(this, std::move(request));
  }

  void RunUntilFetchEvent() {
    base::RunLoop loop;
    fetch_event_callback_ = loop.QuitClosure();
    loop.Run();
  }

  int fetch_event_count() const { return fetch_event_count_; }
  const blink::mojom::FetchAPIRequest& fetch_event_request() const {
    return *fetch_event_request_;
  }

 private:
  enum class ResponseMode {
    kDefault,
    kAbort,
    kStream,
    kBlob,
    kBlobRange,
    kFallbackResponse,
    kErrorResponse,
    kRedirectResponse
  };

  ResponseMode response_mode_ = ResponseMode::kDefault;
  scoped_refptr<network::ResourceRequestBody> request_body_;

  int fetch_event_count_ = 0;
  blink::mojom::FetchAPIRequestPtr fetch_event_request_;
  base::OnceClosure fetch_event_callback_;
  mojo::BindingSet<blink::mojom::ControllerServiceWorker> bindings_;

  // For ResponseMode::kStream.
  blink::mojom::ServiceWorkerStreamHandlePtr stream_handle_;

  // For ResponseMode::kBlob.
  blink::mojom::SerializedBlobPtr blob_body_;

  // For ResponseMode::kBlobRange.
  std::string blob_range_body_;

  // For ResponseMode::kRedirectResponse
  std::string redirect_location_header_;

  network::mojom::FetchResponseSource response_source_ =
      network::mojom::FetchResponseSource::kUnspecified;

  DISALLOW_COPY_AND_ASSIGN(FakeControllerServiceWorker);
};

class FakeServiceWorkerContainerHost
    : public blink::mojom::ServiceWorkerContainerHost {
 public:
  explicit FakeServiceWorkerContainerHost(
      FakeControllerServiceWorker* fake_controller)
      : fake_controller_(fake_controller) {}

  ~FakeServiceWorkerContainerHost() override = default;

  void set_fake_controller(FakeControllerServiceWorker* new_fake_controller) {
    fake_controller_ = new_fake_controller;
  }

  int get_controller_service_worker_count() const {
    return get_controller_service_worker_count_;
  }

  // Implements blink::mojom::ServiceWorkerContainerHost.
  void Register(const GURL& script_url,
                blink::mojom::ServiceWorkerRegistrationOptionsPtr options,
                RegisterCallback callback) override {
    NOTIMPLEMENTED();
  }
  void GetRegistration(const GURL& client_url,
                       GetRegistrationCallback callback) override {
    NOTIMPLEMENTED();
  }
  void GetRegistrations(GetRegistrationsCallback callback) override {
    NOTIMPLEMENTED();
  }
  void GetRegistrationForReady(
      GetRegistrationForReadyCallback callback) override {
    NOTIMPLEMENTED();
  }
  void EnsureControllerServiceWorker(
      blink::mojom::ControllerServiceWorkerRequest request,
      blink::mojom::ControllerServiceWorkerPurpose purpose) override {
    get_controller_service_worker_count_++;
    if (!fake_controller_)
      return;
    fake_controller_->Clone(std::move(request));
  }
  void CloneContainerHost(
      blink::mojom::ServiceWorkerContainerHostRequest request) override {
    bindings_.AddBinding(this, std::move(request));
  }
  void Ping(PingCallback callback) override { NOTIMPLEMENTED(); }
  void HintToUpdateServiceWorker() override { NOTIMPLEMENTED(); }

 private:
  int get_controller_service_worker_count_ = 0;
  FakeControllerServiceWorker* fake_controller_;
  mojo::BindingSet<blink::mojom::ServiceWorkerContainerHost> bindings_;
  DISALLOW_COPY_AND_ASSIGN(FakeServiceWorkerContainerHost);
};

// Returns an expected ResourceResponseHead which is used by stream response
// related tests.
std::unique_ptr<network::ResourceResponseHead>
CreateResponseInfoFromServiceWorker() {
  auto head = std::make_unique<network::ResourceResponseHead>();
  std::string headers = "HTTP/1.1 200 OK\n\n";
  head->headers = new net::HttpResponseHeaders(
      net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.length()));
  head->was_fetched_via_service_worker = true;
  head->was_fallback_required_by_service_worker = false;
  head->url_list_via_service_worker = std::vector<GURL>();
  head->response_type = network::mojom::FetchResponseType::kDefault;
  head->is_in_cache_storage = false;
  head->cache_storage_cache_name = std::string();
  head->did_service_worker_navigation_preload = false;
  return head;
}

const char kHistogramSubresourceFetchEvent[] =
    "ServiceWorker.FetchEvent.Subresource.Status";

class ServiceWorkerSubresourceLoaderTest : public ::testing::Test {
 protected:
  ServiceWorkerSubresourceLoaderTest()
      : fake_container_host_(&fake_controller_) {}
  ~ServiceWorkerSubresourceLoaderTest() override = default;

  void SetUp() override {
    feature_list_.InitAndEnableFeature(network::features::kNetworkService);

    network::mojom::URLLoaderFactoryPtr fake_loader_factory;
    mojo::MakeStrongBinding(std::make_unique<FakeNetworkURLLoaderFactory>(),
                            MakeRequest(&fake_loader_factory));
    loader_factory_ =
        base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
            std::move(fake_loader_factory));
  }

  network::mojom::URLLoaderFactoryPtr CreateSubresourceLoaderFactory() {
    if (!connector_) {
      blink::mojom::ServiceWorkerContainerHostPtrInfo host_ptr_info;
      fake_container_host_.CloneContainerHost(
          mojo::MakeRequest(&host_ptr_info));
      connector_ = base::MakeRefCounted<ControllerServiceWorkerConnector>(
          std::move(host_ptr_info), nullptr /*controller_ptr*/,
          "" /*client_id*/);
    }
    network::mojom::URLLoaderFactoryPtr service_worker_url_loader_factory;
    ServiceWorkerSubresourceLoaderFactory::Create(
        connector_, loader_factory_,
        mojo::MakeRequest(&service_worker_url_loader_factory),
        blink::scheduler::GetSequencedTaskRunnerForTesting());
    return service_worker_url_loader_factory;
  }

  // Starts |request| using |loader_factory| and sets |out_loader| and
  // |out_loader_client| to the resulting URLLoader and its URLLoaderClient. The
  // caller can then use functions like client.RunUntilComplete() to wait for
  // completion. Calling fake_controller_->RunUntilFetchEvent() also advances
  // the load to until |fake_controller_| receives the fetch event.
  void StartRequest(
      const network::mojom::URLLoaderFactoryPtr& loader_factory,
      const network::ResourceRequest& request,
      network::mojom::URLLoaderPtr* out_loader,
      std::unique_ptr<network::TestURLLoaderClient>* out_loader_client) {
    *out_loader_client = std::make_unique<network::TestURLLoaderClient>();
    loader_factory->CreateLoaderAndStart(
        mojo::MakeRequest(out_loader), 0, 0, network::mojom::kURLLoadOptionNone,
        request, (*out_loader_client)->CreateInterfacePtr(),
        net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
  }

  void ExpectResponseInfo(const network::ResourceResponseHead& info,
                          const network::ResourceResponseHead& expected_info) {
    EXPECT_EQ(expected_info.headers->response_code(),
              info.headers->response_code());
    EXPECT_EQ(expected_info.was_fetched_via_service_worker,
              info.was_fetched_via_service_worker);
    EXPECT_EQ(expected_info.was_fallback_required_by_service_worker,
              info.was_fallback_required_by_service_worker);
    EXPECT_EQ(expected_info.url_list_via_service_worker,
              info.url_list_via_service_worker);
    EXPECT_EQ(expected_info.response_type, info.response_type);
    EXPECT_EQ(expected_info.is_in_cache_storage, info.is_in_cache_storage);
    EXPECT_EQ(expected_info.cache_storage_cache_name,
              info.cache_storage_cache_name);
    EXPECT_EQ(expected_info.did_service_worker_navigation_preload,
              info.did_service_worker_navigation_preload);
    EXPECT_NE(expected_info.service_worker_start_time,
              info.service_worker_start_time);
    EXPECT_NE(expected_info.service_worker_ready_time,
              info.service_worker_ready_time);
  }

  network::ResourceRequest CreateRequest(const GURL& url) {
    network::ResourceRequest request;
    request.url = url;
    request.method = "GET";
    request.resource_type = RESOURCE_TYPE_SUB_RESOURCE;
    return request;
  }

  // Performs a request with the given |request_body|, and checks that the body
  // is passed to the fetch event.
  void RunFallbackWithRequestBodyTest(
      scoped_refptr<network::ResourceRequestBody> request_body,
      const std::string& expected_body) {
    network::mojom::URLLoaderFactoryPtr factory =
        CreateSubresourceLoaderFactory();

    // Create a request with the body.
    network::ResourceRequest request =
        CreateRequest(GURL("https://www.example.com/upload"));
    request.method = "POST";
    request.request_body = std::move(request_body);

    // Set the service worker to do network fallback as it exercises a tricky
    // code path to ensure the body makes it to network.
    fake_controller_.RespondWithFallback();

    // Perform the request.
    network::mojom::URLLoaderPtr loader;
    std::unique_ptr<network::TestURLLoaderClient> client;
    StartRequest(factory, request, &loader, &client);
    client->RunUntilComplete();

    // Verify that the request body was passed to the fetch event.
    std::string fetch_event_body;
    fake_controller_.ReadRequestBody(&fetch_event_body);
    EXPECT_EQ(expected_body, fetch_event_body);

    // TODO(falken): It'd be nicer to also check the request body was sent to
    // network but it requires more complicated network mocking and it was hard
    // getting EmbeddedTestServer working with these tests (probably
    // CorsFallbackResponse is too heavy). We also have Web Platform Tests that
    // cover this case in fetch-event.https.html.
  }

  // Performs a range request using |range_header| and returns the resulting
  // client after completion.
  std::unique_ptr<network::TestURLLoaderClient> DoRangeRequest(
      const std::string& range_header) {
    network::mojom::URLLoaderFactoryPtr factory =
        CreateSubresourceLoaderFactory();
    network::ResourceRequest request =
        CreateRequest(GURL("https://www.example.com/big-file"));
    request.headers.SetHeader("Range", range_header);
    network::mojom::URLLoaderPtr loader;
    std::unique_ptr<network::TestURLLoaderClient> client;
    StartRequest(factory, request, &loader, &client);
    client->RunUntilComplete();
    return client;
  }

  std::string TakeResponseBody(network::TestURLLoaderClient* client) {
    std::string body;
    EXPECT_TRUE(client->response_body().is_valid());
    EXPECT_TRUE(
        mojo::BlockingCopyToString(client->response_body_release(), &body));
    return body;
  }

  TestBrowserThreadBundle thread_bundle_;
  scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
  scoped_refptr<ControllerServiceWorkerConnector> connector_;
  FakeServiceWorkerContainerHost fake_container_host_;
  FakeControllerServiceWorker fake_controller_;
  base::test::ScopedFeatureList feature_list_;

  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerSubresourceLoaderTest);
};

TEST_F(ServiceWorkerSubresourceLoaderTest, Basic) {
  base::HistogramTester histogram_tester;

  network::mojom::URLLoaderFactoryPtr factory =
      CreateSubresourceLoaderFactory();
  network::ResourceRequest request =
      CreateRequest(GURL("https://www.example.com/foo.png"));
  network::mojom::URLLoaderPtr loader;
  std::unique_ptr<network::TestURLLoaderClient> client;
  StartRequest(factory, request, &loader, &client);
  fake_controller_.RunUntilFetchEvent();

  EXPECT_EQ(request.url, fake_controller_.fetch_event_request().url);
  EXPECT_EQ(request.method, fake_controller_.fetch_event_request().method);
  EXPECT_EQ(1, fake_controller_.fetch_event_count());
  EXPECT_EQ(1, fake_container_host_.get_controller_service_worker_count());

  client->RunUntilComplete();

  net::LoadTimingInfo load_timing_info = client->response_head().load_timing;
  EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
  EXPECT_FALSE(load_timing_info.receive_headers_end.is_null());
  EXPECT_LE(load_timing_info.receive_headers_start,
            load_timing_info.receive_headers_end);

  histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent,
                                      blink::ServiceWorkerStatusCode::kOk, 1);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ForwardServiceWorkerToWorkerReady",
      1);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted2", 1);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted2."
      "Unspecified",
      1);
}

TEST_F(ServiceWorkerSubresourceLoaderTest, Abort) {
  fake_controller_.AbortEventWithNoResponse();
  base::HistogramTester histogram_tester;

  network::mojom::URLLoaderFactoryPtr factory =
      CreateSubresourceLoaderFactory();

  // Perform the request.
  network::ResourceRequest request =
      CreateRequest(GURL("https://www.example.com/foo.png"));
  network::mojom::URLLoaderPtr loader;
  std::unique_ptr<network::TestURLLoaderClient> client;
  StartRequest(factory, request, &loader, &client);
  client->RunUntilComplete();

  EXPECT_EQ(net::ERR_FAILED, client->completion_status().error_code);
  histogram_tester.ExpectUniqueSample(
      kHistogramSubresourceFetchEvent,
      blink::ServiceWorkerStatusCode::kErrorAbort, 1);

  // Timing histograms shouldn't be recorded on abort.
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ForwardServiceWorkerToWorkerReady",
      0);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted2", 0);
}

TEST_F(ServiceWorkerSubresourceLoaderTest, DropController) {
  network::mojom::URLLoaderFactoryPtr factory =
      CreateSubresourceLoaderFactory();
  {
    network::ResourceRequest request =
        CreateRequest(GURL("https://www.example.com/foo.png"));
    network::mojom::URLLoaderPtr loader;
    std::unique_ptr<network::TestURLLoaderClient> client;
    StartRequest(factory, request, &loader, &client);
    fake_controller_.RunUntilFetchEvent();

    EXPECT_EQ(request.url, fake_controller_.fetch_event_request().url);
    EXPECT_EQ(request.method, fake_controller_.fetch_event_request().method);
    EXPECT_EQ(1, fake_controller_.fetch_event_count());
    EXPECT_EQ(1, fake_container_host_.get_controller_service_worker_count());
  }

  // Loading another resource reuses the existing connection to the
  // ControllerServiceWorker (i.e. it doesn't increase the get controller
  // service worker count).
  {
    network::ResourceRequest request =
        CreateRequest(GURL("https://www.example.com/foo2.png"));
    network::mojom::URLLoaderPtr loader;
    std::unique_ptr<network::TestURLLoaderClient> client;
    StartRequest(factory, request, &loader, &client);
    fake_controller_.RunUntilFetchEvent();

    EXPECT_EQ(request.url, fake_controller_.fetch_event_request().url);
    EXPECT_EQ(request.method, fake_controller_.fetch_event_request().method);
    EXPECT_EQ(2, fake_controller_.fetch_event_count());
    EXPECT_EQ(1, fake_container_host_.get_controller_service_worker_count());
  }

  // Drop the connection to the ControllerServiceWorker.
  fake_controller_.CloseAllBindings();
  base::RunLoop().RunUntilIdle();

  {
    // This should re-obtain the ControllerServiceWorker.
    network::ResourceRequest request =
        CreateRequest(GURL("https://www.example.com/foo3.png"));
    network::mojom::URLLoaderPtr loader;
    std::unique_ptr<network::TestURLLoaderClient> client;
    StartRequest(factory, request, &loader, &client);
    fake_controller_.RunUntilFetchEvent();

    EXPECT_EQ(request.url, fake_controller_.fetch_event_request().url);
    EXPECT_EQ(request.method, fake_controller_.fetch_event_request().method);
    EXPECT_EQ(3, fake_controller_.fetch_event_count());
    EXPECT_EQ(2, fake_container_host_.get_controller_service_worker_count());
  }
}

TEST_F(ServiceWorkerSubresourceLoaderTest, NoController) {
  network::mojom::URLLoaderFactoryPtr factory =
      CreateSubresourceLoaderFactory();
  {
    network::ResourceRequest request =
        CreateRequest(GURL("https://www.example.com/foo.png"));
    network::mojom::URLLoaderPtr loader;
    std::unique_ptr<network::TestURLLoaderClient> client;
    StartRequest(factory, request, &loader, &client);
    fake_controller_.RunUntilFetchEvent();

    EXPECT_EQ(request.url, fake_controller_.fetch_event_request().url);
    EXPECT_EQ(request.method, fake_controller_.fetch_event_request().method);
    EXPECT_EQ(1, fake_controller_.fetch_event_count());
    EXPECT_EQ(1, fake_container_host_.get_controller_service_worker_count());
  }

  // Make the connector have no controller.
  connector_->UpdateController(nullptr);
  base::RunLoop().RunUntilIdle();

  base::HistogramTester histogram_tester;
  {
    // This should fallback to the network.
    network::ResourceRequest request =
        CreateRequest(GURL("https://www.example.com/foo2.png"));
    network::mojom::URLLoaderPtr loader;
    std::unique_ptr<network::TestURLLoaderClient> client;
    StartRequest(factory, request, &loader, &client);
    client->RunUntilComplete();

    EXPECT_TRUE(client->has_received_completion());
    EXPECT_FALSE(client->response_head().was_fetched_via_service_worker);

    EXPECT_EQ(1, fake_controller_.fetch_event_count());
    EXPECT_EQ(1, fake_container_host_.get_controller_service_worker_count());
  }

  // No fetch event was dispatched, so no sample should be recorded.
  histogram_tester.ExpectTotalCount(kHistogramSubresourceFetchEvent, 0);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ForwardServiceWorkerToWorkerReady",
      0);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted2", 0);
}

TEST_F(ServiceWorkerSubresourceLoaderTest, DropController_RestartFetchEvent) {
  network::mojom::URLLoaderFactoryPtr factory =
      CreateSubresourceLoaderFactory();

  {
    network::ResourceRequest request =
        CreateRequest(GURL("https://www.example.com/foo.png"));
    network::mojom::URLLoaderPtr loader;
    std::unique_ptr<network::TestURLLoaderClient> client;
    StartRequest(factory, request, &loader, &client);
    fake_controller_.RunUntilFetchEvent();

    EXPECT_EQ(request.url, fake_controller_.fetch_event_request().url);
    EXPECT_EQ(request.method, fake_controller_.fetch_event_request().method);
    EXPECT_EQ(1, fake_controller_.fetch_event_count());
    EXPECT_EQ(1, fake_container_host_.get_controller_service_worker_count());
  }

  // Loading another resource reuses the existing connection to the
  // ControllerServiceWorker (i.e. it doesn't increase the get controller
  // service worker count).
  {
    network::ResourceRequest request =
        CreateRequest(GURL("https://www.example.com/foo2.png"));
    network::mojom::URLLoaderPtr loader;
    std::unique_ptr<network::TestURLLoaderClient> client;
    StartRequest(factory, request, &loader, &client);
    fake_controller_.RunUntilFetchEvent();

    EXPECT_EQ(request.url, fake_controller_.fetch_event_request().url);
    EXPECT_EQ(request.method, fake_controller_.fetch_event_request().method);
    EXPECT_EQ(2, fake_controller_.fetch_event_count());
    EXPECT_EQ(1, fake_container_host_.get_controller_service_worker_count());
    client->RunUntilComplete();
  }

  base::HistogramTester histogram_tester;

  network::ResourceRequest request =
      CreateRequest(GURL("https://www.example.com/foo3.png"));
  network::mojom::URLLoaderPtr loader;
  std::unique_ptr<network::TestURLLoaderClient> client;
  StartRequest(factory, request, &loader, &client);

  // Drop the connection to the ControllerServiceWorker.
  fake_controller_.CloseAllBindings();
  base::RunLoop().RunUntilIdle();

  // If connection is closed during fetch event, it's restarted and successfully
  // finishes.
  EXPECT_EQ(request.url, fake_controller_.fetch_event_request().url);
  EXPECT_EQ(request.method, fake_controller_.fetch_event_request().method);
  EXPECT_EQ(3, fake_controller_.fetch_event_count());
  EXPECT_EQ(2, fake_container_host_.get_controller_service_worker_count());
  histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent,
                                      blink::ServiceWorkerStatusCode::kOk, 1);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ForwardServiceWorkerToWorkerReady",
      1);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted2", 1);
}

TEST_F(ServiceWorkerSubresourceLoaderTest, DropController_TooManyRestart) {
  base::HistogramTester histogram_tester;
  // Simulate the container host fails to start a service worker.
  fake_container_host_.set_fake_controller(nullptr);

  network::mojom::URLLoaderFactoryPtr factory =
      CreateSubresourceLoaderFactory();
  network::ResourceRequest request =
      CreateRequest(GURL("https://www.example.com/foo.png"));
  network::mojom::URLLoaderPtr loader;
  std::unique_ptr<network::TestURLLoaderClient> client;
  StartRequest(factory, request, &loader, &client);

  // Try to dispatch fetch event to the bad worker.
  base::RunLoop().RunUntilIdle();

  // The request should be failed instead of infinite loop to restart the
  // inflight fetch event.
  EXPECT_EQ(2, fake_container_host_.get_controller_service_worker_count());
  EXPECT_TRUE(client->has_received_completion());
  EXPECT_EQ(net::ERR_FAILED, client->completion_status().error_code);

  histogram_tester.ExpectUniqueSample(
      kHistogramSubresourceFetchEvent,
      blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed, 1);

  // Timing histograms shouldn't be recorded on failure.
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ForwardServiceWorkerToWorkerReady",
      0);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted2", 0);
}

TEST_F(ServiceWorkerSubresourceLoaderTest, StreamResponse) {
  base::HistogramTester histogram_tester;

  // Construct the Stream to respond with.
  const char kResponseBody[] = "Here is sample text for the Stream.";
  blink::mojom::ServiceWorkerStreamCallbackPtr stream_callback;
  mojo::DataPipe data_pipe;
  fake_controller_.RespondWithStream(mojo::MakeRequest(&stream_callback),
                                     std::move(data_pipe.consumer_handle));
  fake_controller_.SetResponseSource(
      network::mojom::FetchResponseSource::kNetwork);

  network::mojom::URLLoaderFactoryPtr factory =
      CreateSubresourceLoaderFactory();

  // Perform the request.
  network::ResourceRequest request =
      CreateRequest(GURL("https://www.example.com/foo.png"));
  network::mojom::URLLoaderPtr loader;
  std::unique_ptr<network::TestURLLoaderClient> client;
  StartRequest(factory, request, &loader, &client);
  client->RunUntilResponseReceived();

  const network::ResourceResponseHead& info = client->response_head();
  ExpectResponseInfo(info, *CreateResponseInfoFromServiceWorker());

  // Write the body stream.
  uint32_t written_bytes = sizeof(kResponseBody) - 1;
  MojoResult mojo_result = data_pipe.producer_handle->WriteData(
      kResponseBody, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
  ASSERT_EQ(MOJO_RESULT_OK, mojo_result);
  EXPECT_EQ(sizeof(kResponseBody) - 1, written_bytes);
  stream_callback->OnCompleted();
  data_pipe.producer_handle.reset();

  client->RunUntilComplete();
  EXPECT_EQ(net::OK, client->completion_status().error_code);

  // Test the body.
  std::string response;
  EXPECT_TRUE(client->response_body().is_valid());
  EXPECT_TRUE(
      mojo::BlockingCopyToString(client->response_body_release(), &response));
  EXPECT_EQ(kResponseBody, response);

  histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent,
                                      blink::ServiceWorkerStatusCode::kOk, 1);

  // Test timing histograms of reading body.
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ForwardServiceWorkerToWorkerReady",
      1);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted2", 1);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted2."
      "Network",
      1);
}

TEST_F(ServiceWorkerSubresourceLoaderTest, StreamResponse_Abort) {
  base::HistogramTester histogram_tester;

  // Construct the Stream to respond with.
  const char kResponseBody[] = "Here is sample text for the Stream.";
  blink::mojom::ServiceWorkerStreamCallbackPtr stream_callback;
  mojo::DataPipe data_pipe;
  fake_controller_.RespondWithStream(mojo::MakeRequest(&stream_callback),
                                     std::move(data_pipe.consumer_handle));

  network::mojom::URLLoaderFactoryPtr factory =
      CreateSubresourceLoaderFactory();

  // Perform the request.
  network::ResourceRequest request =
      CreateRequest(GURL("https://www.example.com/foo.txt"));
  network::mojom::URLLoaderPtr loader;
  std::unique_ptr<network::TestURLLoaderClient> client;
  StartRequest(factory, request, &loader, &client);
  client->RunUntilResponseReceived();

  const network::ResourceResponseHead& info = client->response_head();
  ExpectResponseInfo(info, *CreateResponseInfoFromServiceWorker());

  // Start writing the body stream, then abort before finishing.
  uint32_t written_bytes = sizeof(kResponseBody) - 1;
  MojoResult mojo_result = data_pipe.producer_handle->WriteData(
      kResponseBody, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
  ASSERT_EQ(MOJO_RESULT_OK, mojo_result);
  EXPECT_EQ(sizeof(kResponseBody) - 1, written_bytes);
  stream_callback->OnAborted();
  data_pipe.producer_handle.reset();

  client->RunUntilComplete();
  EXPECT_EQ(net::ERR_ABORTED, client->completion_status().error_code);

  // Test the body.
  std::string response;
  EXPECT_TRUE(client->response_body().is_valid());
  EXPECT_TRUE(
      mojo::BlockingCopyToString(client->response_body_release(), &response));
  EXPECT_EQ(kResponseBody, response);

  histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent,
                                      blink::ServiceWorkerStatusCode::kOk, 1);

  // Timing histograms shouldn't be recorded on abort.
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ForwardServiceWorkerToWorkerReady",
      0);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted2", 0);
}

TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponse) {
  base::HistogramTester histogram_tester;

  // Construct the Blob to respond with.
  const std::string kResponseBody = "Here is sample text for the Blob.";
  const std::vector<uint8_t> kMetadata = {0xE3, 0x81, 0x8F, 0xE3, 0x82,
                                          0x8D, 0xE3, 0x81, 0xBF, 0xE3,
                                          0x81, 0x86, 0xE3, 0x82, 0x80};
  fake_controller_.RespondWithBlob(kMetadata, kResponseBody);
  fake_controller_.SetResponseSource(
      network::mojom::FetchResponseSource::kCacheStorage);

  network::mojom::URLLoaderFactoryPtr factory =
      CreateSubresourceLoaderFactory();

  // Perform the request.
  network::ResourceRequest request =
      CreateRequest(GURL("https://www.example.com/foo.png"));
  network::mojom::URLLoaderPtr loader;
  std::unique_ptr<network::TestURLLoaderClient> client;
  StartRequest(factory, request, &loader, &client);
  client->RunUntilResponseReceived();

  const network::ResourceResponseHead& info = client->response_head();
  ExpectResponseInfo(info, *CreateResponseInfoFromServiceWorker());
  EXPECT_EQ(33, info.content_length);

  // Test the cached metadata.
  client->RunUntilCachedMetadataReceived();
  EXPECT_EQ(client->cached_metadata(),
            std::string(kMetadata.begin(), kMetadata.end()));

  client->RunUntilComplete();
  EXPECT_EQ(net::OK, client->completion_status().error_code);

  // Test the body.
  std::string response;
  EXPECT_TRUE(client->response_body().is_valid());
  EXPECT_TRUE(
      mojo::BlockingCopyToString(client->response_body_release(), &response));
  EXPECT_EQ(kResponseBody, response);

  histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent,
                                      blink::ServiceWorkerStatusCode::kOk, 1);

  // Test timing histograms of reading body.
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ForwardServiceWorkerToWorkerReady",
      1);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted2", 1);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted2."
      "CacheStorage",
      1);
}

TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponseWithoutMetadata) {
  base::HistogramTester histogram_tester;

  // Construct the Blob to respond with.
  const std::string kResponseBody = "Here is sample text for the Blob.";
  fake_controller_.RespondWithBlob(base::nullopt, kResponseBody);

  network::mojom::URLLoaderFactoryPtr factory =
      CreateSubresourceLoaderFactory();

  // Perform the request.
  network::ResourceRequest request =
      CreateRequest(GURL("https://www.example.com/foo.png"));
  network::mojom::URLLoaderPtr loader;
  std::unique_ptr<network::TestURLLoaderClient> client;
  StartRequest(factory, request, &loader, &client);
  client->RunUntilResponseReceived();

  const network::ResourceResponseHead& info = client->response_head();
  ExpectResponseInfo(info, *CreateResponseInfoFromServiceWorker());

  client->RunUntilComplete();
  EXPECT_EQ(net::OK, client->completion_status().error_code);

  // Test the body.
  std::string response;
  EXPECT_TRUE(client->response_body().is_valid());
  EXPECT_TRUE(
      mojo::BlockingCopyToString(client->response_body_release(), &response));
  EXPECT_EQ(kResponseBody, response);
  EXPECT_FALSE(client->has_received_cached_metadata());

  histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent,
                                      blink::ServiceWorkerStatusCode::kOk, 1);

  // Test timing histograms of reading body.
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ForwardServiceWorkerToWorkerReady",
      1);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted2", 1);
}

// Test when the service worker responds with network fallback.
// i.e., does not call respondWith().
TEST_F(ServiceWorkerSubresourceLoaderTest, FallbackResponse) {
  base::HistogramTester histogram_tester;
  fake_controller_.RespondWithFallback();

  network::mojom::URLLoaderFactoryPtr factory =
      CreateSubresourceLoaderFactory();

  // Perform the request.
  network::ResourceRequest request =
      CreateRequest(GURL("https://www.example.com/foo.png"));
  network::mojom::URLLoaderPtr loader;
  std::unique_ptr<network::TestURLLoaderClient> client;
  StartRequest(factory, request, &loader, &client);
  client->RunUntilComplete();

  // OnFallback() should complete the network request using network loader.
  EXPECT_TRUE(client->has_received_completion());
  EXPECT_FALSE(client->response_head().was_fetched_via_service_worker);

  histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent,
                                      blink::ServiceWorkerStatusCode::kOk, 1);

  // Test timing histograms of network fallback.
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ForwardServiceWorkerToWorkerReady",
      1);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.FetchHandlerEndToFallbackNetwork",
      1);
}

TEST_F(ServiceWorkerSubresourceLoaderTest, ErrorResponse) {
  base::HistogramTester histogram_tester;
  fake_controller_.RespondWithError();

  network::mojom::URLLoaderFactoryPtr factory =
      CreateSubresourceLoaderFactory();

  // Perform the request.
  network::ResourceRequest request =
      CreateRequest(GURL("https://www.example.com/foo.png"));
  network::mojom::URLLoaderPtr loader;
  std::unique_ptr<network::TestURLLoaderClient> client;
  StartRequest(factory, request, &loader, &client);
  client->RunUntilComplete();

  EXPECT_EQ(net::ERR_FAILED, client->completion_status().error_code);
  histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent,
                                      blink::ServiceWorkerStatusCode::kOk, 1);

  // Timing histograms shouldn't be recorded when we receive an error response.
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ForwardServiceWorkerToWorkerReady",
      0);
  histogram_tester.ExpectTotalCount(
      "ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted2", 0);
}

TEST_F(ServiceWorkerSubresourceLoaderTest, RedirectResponse) {
  base::HistogramTester histogram_tester;
  fake_controller_.RespondWithRedirect("https://www.example.com/bar.png");

  network::mojom::URLLoaderFactoryPtr factory =
      CreateSubresourceLoaderFactory();

  // Perform the request.
  network::ResourceRequest request =
      CreateRequest(GURL("https://www.example.com/foo.png"));
  network::mojom::URLLoaderPtr loader;
  std::unique_ptr<network::TestURLLoaderClient> client;
  StartRequest(factory, request, &loader, &client);
  client->RunUntilRedirectReceived();

  EXPECT_EQ(net::OK, client->completion_status().error_code);
  EXPECT_TRUE(client->has_received_redirect());
  {
    const net::RedirectInfo& redirect_info = client->redirect_info();
    EXPECT_EQ(302, redirect_info.status_code);
    EXPECT_EQ("GET", redirect_info.new_method);
    EXPECT_EQ(GURL("https://www.example.com/bar.png"), redirect_info.new_url);
  }
  client->ClearHasReceivedRedirect();

  // Redirect once more.
  fake_controller_.RespondWithRedirect("https://other.example.com/baz.png");
  loader->FollowRedirect({}, {}, base::nullopt);
  client->RunUntilRedirectReceived();

  EXPECT_EQ(net::OK, client->completion_status().error_code);
  EXPECT_TRUE(client->has_received_redirect());
  {
    const net::RedirectInfo& redirect_info = client->redirect_info();
    EXPECT_EQ(302, redirect_info.status_code);
    EXPECT_EQ("GET", redirect_info.new_method);
    EXPECT_EQ(GURL("https://other.example.com/baz.png"), redirect_info.new_url);
  }
  client->ClearHasReceivedRedirect();

  // Give the final response.
  const char kResponseBody[] = "Here is sample text for the Stream.";
  blink::mojom::ServiceWorkerStreamCallbackPtr stream_callback;
  mojo::DataPipe data_pipe;
  fake_controller_.RespondWithStream(mojo::MakeRequest(&stream_callback),
                                     std::move(data_pipe.consumer_handle));
  loader->FollowRedirect({}, {}, base::nullopt);
  client->RunUntilResponseReceived();

  const network::ResourceResponseHead& info = client->response_head();
  EXPECT_EQ(200, info.headers->response_code());
  EXPECT_EQ(network::mojom::FetchResponseType::kDefault, info.response_type);

  // Write the body stream.
  uint32_t written_bytes = sizeof(kResponseBody) - 1;
  MojoResult mojo_result = data_pipe.producer_handle->WriteData(
      kResponseBody, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
  ASSERT_EQ(MOJO_RESULT_OK, mojo_result);
  EXPECT_EQ(sizeof(kResponseBody) - 1, written_bytes);
  stream_callback->OnCompleted();
  data_pipe.producer_handle.reset();

  client->RunUntilComplete();
  EXPECT_EQ(net::OK, client->completion_status().error_code);

  // Test the body.
  std::string response;
  EXPECT_TRUE(client->response_body().is_valid());
  EXPECT_TRUE(
      mojo::BlockingCopyToString(client->response_body_release(), &response));
  EXPECT_EQ(kResponseBody, response);

  // There were 3 fetch events, so expect a count of 3.
  histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent,
                                      blink::ServiceWorkerStatusCode::kOk, 3);
}

TEST_F(ServiceWorkerSubresourceLoaderTest, TooManyRedirects) {
  base::HistogramTester histogram_tester;

  int count = 1;
  std::string redirect_location =
      std::string("https://www.example.com/redirect_") +
      base::IntToString(count);
  fake_controller_.RespondWithRedirect(redirect_location);
  network::mojom::URLLoaderFactoryPtr factory =
      CreateSubresourceLoaderFactory();

  // Perform the request.
  network::ResourceRequest request =
      CreateRequest(GURL("https://www.example.com/foo.png"));
  network::mojom::URLLoaderPtr loader;
  std::unique_ptr<network::TestURLLoaderClient> client;
  StartRequest(factory, request, &loader, &client);

  // The Fetch spec says: "If request’s redirect count is twenty, return a
  // network error." https://fetch.spec.whatwg.org/#http-redirect-fetch
  // So fetch can follow the redirect response until 20 times.
  static_assert(net::URLRequest::kMaxRedirects == 20,
                "The Fetch spec requires kMaxRedirects to be 20");
  for (; count < net::URLRequest::kMaxRedirects + 1; ++count) {
    client->RunUntilRedirectReceived();

    EXPECT_TRUE(client->has_received_redirect());
    EXPECT_EQ(net::OK, client->completion_status().error_code);
    const net::RedirectInfo& redirect_info = client->redirect_info();
    EXPECT_EQ(302, redirect_info.status_code);
    EXPECT_EQ("GET", redirect_info.new_method);
    EXPECT_EQ(GURL(redirect_location), redirect_info.new_url);

    client->ClearHasReceivedRedirect();

    // Redirect more.
    redirect_location = std::string("https://www.example.com/redirect_") +
                        base::IntToString(count);
    fake_controller_.RespondWithRedirect(redirect_location);
    loader->FollowRedirect({}, {}, base::nullopt);
  }
  client->RunUntilComplete();

  // Fetch can't follow the redirect response 21 times.
  EXPECT_FALSE(client->has_received_redirect());
  EXPECT_EQ(net::ERR_TOO_MANY_REDIRECTS,
            client->completion_status().error_code);

  // Expect a sample for each fetch event (kMaxRedirects + 1).
  histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent,
                                      blink::ServiceWorkerStatusCode::kOk,
                                      net::URLRequest::kMaxRedirects + 1);
}

// Test when the service worker responds with network fallback to CORS request.
TEST_F(ServiceWorkerSubresourceLoaderTest, CorsFallbackResponse) {
  fake_controller_.RespondWithFallback();

  network::mojom::URLLoaderFactoryPtr factory =
      CreateSubresourceLoaderFactory();

  struct TestCase {
    network::mojom::FetchRequestMode fetch_request_mode;
    base::Optional<url::Origin> request_initiator;
    bool expected_was_fallback_required_by_service_worker;
  };
  const TestCase kTests[] = {
      {network::mojom::FetchRequestMode::kSameOrigin,
       base::Optional<url::Origin>(), false},
      {network::mojom::FetchRequestMode::kNoCors, base::Optional<url::Origin>(),
       false},
      {network::mojom::FetchRequestMode::kCors, base::Optional<url::Origin>(),
       true},
      {network::mojom::FetchRequestMode::kCorsWithForcedPreflight,
       base::Optional<url::Origin>(), true},
      {network::mojom::FetchRequestMode::kNavigate,
       base::Optional<url::Origin>(), false},
      {network::mojom::FetchRequestMode::kSameOrigin,
       url::Origin::Create(GURL("https://www.example.com/")), false},
      {network::mojom::FetchRequestMode::kNoCors,
       url::Origin::Create(GURL("https://www.example.com/")), false},
      {network::mojom::FetchRequestMode::kCors,
       url::Origin::Create(GURL("https://www.example.com/")), false},
      {network::mojom::FetchRequestMode::kCorsWithForcedPreflight,
       url::Origin::Create(GURL("https://www.example.com/")), false},
      {network::mojom::FetchRequestMode::kNavigate,
       url::Origin::Create(GURL("https://other.example.com/")), false},
      {network::mojom::FetchRequestMode::kSameOrigin,
       url::Origin::Create(GURL("https://other.example.com/")), false},
      {network::mojom::FetchRequestMode::kNoCors,
       url::Origin::Create(GURL("https://other.example.com/")), false},
      {network::mojom::FetchRequestMode::kCors,
       url::Origin::Create(GURL("https://other.example.com/")), true},
      {network::mojom::FetchRequestMode::kCorsWithForcedPreflight,
       url::Origin::Create(GURL("https://other.example.com/")), true},
      {network::mojom::FetchRequestMode::kNavigate,
       url::Origin::Create(GURL("https://other.example.com/")), false}};

  for (const auto& test : kTests) {
    base::HistogramTester histogram_tester;

    SCOPED_TRACE(
        ::testing::Message()
        << "fetch_request_mode: " << static_cast<int>(test.fetch_request_mode)
        << " request_initiator: "
        << (test.request_initiator ? test.request_initiator->Serialize()
                                   : std::string("null")));
    // Perform the request.
    network::ResourceRequest request =
        CreateRequest(GURL("https://www.example.com/foo.png"));
    request.fetch_request_mode = test.fetch_request_mode;
    request.request_initiator = test.request_initiator;
    network::mojom::URLLoaderPtr loader;
    std::unique_ptr<network::TestURLLoaderClient> client;
    StartRequest(factory, request, &loader, &client);
    client->RunUntilComplete();

    const network::ResourceResponseHead& info = client->response_head();
    EXPECT_EQ(test.expected_was_fallback_required_by_service_worker,
              info.was_fetched_via_service_worker);
    EXPECT_EQ(test.expected_was_fallback_required_by_service_worker,
              info.was_fallback_required_by_service_worker);
    if (info.was_fallback_required_by_service_worker) {
      EXPECT_EQ("HTTP/1.1 400 Service Worker Fallback Required",
                info.headers->GetStatusLine());
    }
    histogram_tester.ExpectTotalCount(
        "ServiceWorker.LoadTiming.Subresource."
        "FetchHandlerEndToFallbackNetwork",
        1);
  }
}

TEST_F(ServiceWorkerSubresourceLoaderTest, FallbackWithRequestBody_String) {
  const std::string kData = "Hi, this is the request body (string)";
  auto request_body = base::MakeRefCounted<network::ResourceRequestBody>();
  network::mojom::DataPipeGetterPtr data_pipe_getter_ptr;
  request_body->AppendBytes(kData.c_str(), kData.length());

  RunFallbackWithRequestBodyTest(std::move(request_body), kData);
}

TEST_F(ServiceWorkerSubresourceLoaderTest, FallbackWithRequestBody_DataPipe) {
  const std::string kData = "Hi, this is the request body (data pipe)";
  auto request_body = base::MakeRefCounted<network::ResourceRequestBody>();
  network::mojom::DataPipeGetterPtr data_pipe_getter_ptr;
  auto data_pipe_getter = std::make_unique<network::TestDataPipeGetter>(
      kData, mojo::MakeRequest(&data_pipe_getter_ptr));
  request_body->AppendDataPipe(std::move(data_pipe_getter_ptr));

  RunFallbackWithRequestBodyTest(std::move(request_body), kData);
}

// Test a range request that the service worker responds to with a 200
// (non-ranged) response. The client should get the entire response as-is from
// the service worker.
TEST_F(ServiceWorkerSubresourceLoaderTest, RangeRequest_200Response) {
  // Construct the Blob to respond with.
  const std::string kResponseBody = "Here is sample text for the Blob.";
  fake_controller_.RespondWithBlob(base::nullopt, kResponseBody);

  // Perform the request.
  std::unique_ptr<network::TestURLLoaderClient> client =
      DoRangeRequest("bytes=5-13");
  EXPECT_EQ(net::OK, client->completion_status().error_code);

  // Test the response.
  const network::ResourceResponseHead& info = client->response_head();
  ExpectResponseInfo(info, *CreateResponseInfoFromServiceWorker());
  EXPECT_EQ(33, info.content_length);
  EXPECT_FALSE(info.headers->HasHeader("Content-Range"));
  EXPECT_EQ(kResponseBody, TakeResponseBody(client.get()));
}

// Test a range request that the service worker responds to with a 206 ranged
// response. The client should get the partial response as-is from the service
// worker.
TEST_F(ServiceWorkerSubresourceLoaderTest, RangeRequest_206Response) {
  // Tell the controller to respond with a 206 response.
  const std::string kResponseBody = "Here is sample text for the Blob.";
  fake_controller_.RespondWithBlobRange(kResponseBody);

  // Perform the request.
  std::unique_ptr<network::TestURLLoaderClient> client =
      DoRangeRequest("bytes=5-13");
  EXPECT_EQ(net::OK, client->completion_status().error_code);

  // Test the response.
  const network::ResourceResponseHead& info = client->response_head();
  EXPECT_EQ(206, info.headers->response_code());
  std::string range;
  ASSERT_TRUE(info.headers->GetNormalizedHeader("Content-Range", &range));
  EXPECT_EQ("bytes 5-13/33", range);
  EXPECT_EQ(9, info.content_length);
  EXPECT_EQ("is sample", TakeResponseBody(client.get()));
}

// Test a range request that the service worker responds to with a 206 ranged
// response. The requested range has an unbounded end. The client should get the
// partial response as-is from the service worker.
TEST_F(ServiceWorkerSubresourceLoaderTest,
       RangeRequest_UnboundedRight_206Response) {
  // Tell the controller to respond with a 206 response.
  const std::string kResponseBody = "Here is sample text for the Blob.";
  fake_controller_.RespondWithBlobRange(kResponseBody);

  // Perform the request.
  std::unique_ptr<network::TestURLLoaderClient> client =
      DoRangeRequest("bytes=5-");
  EXPECT_EQ(net::OK, client->completion_status().error_code);

  // Test the response.
  const network::ResourceResponseHead& info = client->response_head();
  EXPECT_EQ(206, info.headers->response_code());
  std::string range;
  ASSERT_TRUE(info.headers->GetNormalizedHeader("Content-Range", &range));
  EXPECT_EQ("bytes 5-32/33", range);
  EXPECT_EQ(28, info.content_length);
  EXPECT_EQ("is sample text for the Blob.", TakeResponseBody(client.get()));
}

}  // namespace service_worker_subresource_loader_unittest
}  // namespace content
