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

#include <utility>
#include <vector>

#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
#include "content/child/thread_safe_sender.h"
#include "content/renderer/service_worker/embedded_worker_instance_client_impl.h"
#include "content/renderer/service_worker/service_worker_timeout_timer.h"
#include "content/renderer/service_worker/web_service_worker_impl.h"
#include "content/renderer/worker_thread_registry.h"
#include "mojo/public/cpp/bindings/associated_binding_set.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/resource_request.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/message_port/message_port_channel.h"
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
#include "third_party/blink/public/platform/modules/background_fetch/web_background_fetch_settled_fetch.h"
#include "third_party/blink/public/platform/modules/notifications/web_notification_data.h"
#include "third_party/blink/public/platform/modules/payments/web_payment_request_event_data.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_clients_info.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/platform/web_data_consumer_handle.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url_response.h"
#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h"

namespace content {

namespace {

// Pipes connected to the context client.
struct ContextClientPipes {
  // From the browser to ServiceWorkerContextClient.
  mojom::ServiceWorkerEventDispatcherPtr event_dispatcher;
  mojom::ControllerServiceWorkerPtr controller;
  blink::mojom::ServiceWorkerRegistrationObjectAssociatedPtr registration;

  // From ServiceWorkerContextClient to the browser.
  blink::mojom::ServiceWorkerHostAssociatedRequest service_worker_host_request;
  mojom::EmbeddedWorkerInstanceHostAssociatedRequest
      embedded_worker_host_request;
  blink::mojom::ServiceWorkerRegistrationObjectHostAssociatedRequest
      registration_host_request;
};

class MockWebServiceWorkerContextProxy
    : public blink::WebServiceWorkerContextProxy {
 public:
  ~MockWebServiceWorkerContextProxy() override = default;

  void ReadyToEvaluateScript() override {}
  void SetRegistration(
      std::unique_ptr<blink::WebServiceWorkerRegistration::Handle> handle)
      override {
    registration_handle_ = std::move(handle);
  }
  bool HasFetchEventHandler() override { return false; }
  void DispatchFetchEvent(int fetch_event_id,
                          const blink::WebServiceWorkerRequest& web_request,
                          bool navigation_preload_sent) override {
    fetch_events_.emplace_back(fetch_event_id, web_request);
  }

  void DispatchActivateEvent(int event_id) override { NOTREACHED(); }
  void DispatchBackgroundFetchAbortEvent(
      int event_id,
      const blink::WebString& developer_id,
      const blink::WebString& unique_id,
      const blink::WebVector<blink::WebBackgroundFetchSettledFetch>& fetches)
      override {
    NOTREACHED();
  }
  void DispatchBackgroundFetchClickEvent(int event_id,
                                         const blink::WebString& developer_id,
                                         BackgroundFetchState status) override {
    NOTREACHED();
  }
  void DispatchBackgroundFetchFailEvent(
      int event_id,
      const blink::WebString& developer_id,
      const blink::WebString& unique_id,
      const blink::WebVector<blink::WebBackgroundFetchSettledFetch>& fetches)
      override {
    NOTREACHED();
  }
  void DispatchBackgroundFetchedEvent(
      int event_id,
      const blink::WebString& developer_id,
      const blink::WebString& unique_id,
      const blink::WebVector<blink::WebBackgroundFetchSettledFetch>& fetches)
      override {
    NOTREACHED();
  }
  void DispatchCookieChangeEvent(
      int event_id,
      const blink::WebCanonicalCookie& cookie,
      ::network::mojom::CookieChangeCause change_cause) override {
    NOTREACHED();
  }
  void DispatchExtendableMessageEvent(
      int event_id,
      blink::TransferableMessage message,
      const blink::WebSecurityOrigin& source_origin,
      const blink::WebServiceWorkerClientInfo&) override {
    NOTREACHED();
  }
  void DispatchExtendableMessageEvent(
      int event_id,
      blink::TransferableMessage message,
      const blink::WebSecurityOrigin& source_origin,
      std::unique_ptr<blink::WebServiceWorker::Handle>) override {
    NOTREACHED();
  }
  void DispatchInstallEvent(int event_id) override { NOTREACHED(); }
  void DispatchNotificationClickEvent(int event_id,
                                      const blink::WebString& notification_id,
                                      const blink::WebNotificationData&,
                                      int action_index,
                                      const blink::WebString& reply) override {
    NOTREACHED();
  }
  void DispatchNotificationCloseEvent(
      int event_id,
      const blink::WebString& notification_id,
      const blink::WebNotificationData&) override {
    NOTREACHED();
  }
  void DispatchPushEvent(int event_id, const blink::WebString& data) override {
    NOTREACHED();
  }
  void DispatchSyncEvent(int sync_event_id,
                         const blink::WebString& tag,
                         bool last_chance) override {
    NOTREACHED();
  }
  void DispatchAbortPaymentEvent(int event_id) override { NOTREACHED(); }
  void DispatchCanMakePaymentEvent(
      int event_id,
      const blink::WebCanMakePaymentEventData&) override {
    NOTREACHED();
  }
  void DispatchPaymentRequestEvent(
      int event_id,
      const blink::WebPaymentRequestEventData&) override {
    NOTREACHED();
  }
  void OnNavigationPreloadResponse(
      int fetch_event_id,
      std::unique_ptr<blink::WebURLResponse>,
      std::unique_ptr<blink::WebDataConsumerHandle>) override {
    NOTREACHED();
  }
  void OnNavigationPreloadError(
      int fetch_event_id,
      std::unique_ptr<blink::WebServiceWorkerError>) override {
    NOTREACHED();
  }
  void OnNavigationPreloadComplete(int fetch_event_id,
                                   base::TimeTicks completion_time,
                                   int64_t encoded_data_length,
                                   int64_t encoded_body_length,
                                   int64_t decoded_body_length) override {
    NOTREACHED();
  }

  const std::vector<
      std::pair<int /* event_id */, blink::WebServiceWorkerRequest>>&
  fetch_events() const {
    return fetch_events_;
  }

 private:
  std::unique_ptr<blink::WebServiceWorkerRegistration::Handle>
      registration_handle_;
  std::vector<std::pair<int /* event_id */, blink::WebServiceWorkerRequest>>
      fetch_events_;
};

base::RepeatingClosure CreateCallbackWithCalledFlag(bool* out_is_called) {
  return base::BindRepeating([](bool* out_is_called) { *out_is_called = true; },
                             out_is_called);
}

class MockServiceWorkerObjectHost
    : public blink::mojom::ServiceWorkerObjectHost {
 public:
  explicit MockServiceWorkerObjectHost(int64_t version_id)
      : version_id_(version_id) {}
  ~MockServiceWorkerObjectHost() override = default;

  blink::mojom::ServiceWorkerObjectInfoPtr CreateObjectInfo() {
    auto info = blink::mojom::ServiceWorkerObjectInfo::New();
    info->version_id = version_id_;
    bindings_.AddBinding(this, mojo::MakeRequest(&info->host_ptr_info));
    info->request = mojo::MakeRequest(&remote_object_);
    return info;
  }

  int GetBindingCount() const { return bindings_.size(); }

 private:
  // Implements blink::mojom::ServiceWorkerObjectHost.
  void PostMessageToServiceWorker(
      ::blink::TransferableMessage message) override {
    NOTREACHED();
  }
  void TerminateForTesting(TerminateForTestingCallback callback) override {
    NOTREACHED();
  }

  const int64_t version_id_;
  mojo::AssociatedBindingSet<blink::mojom::ServiceWorkerObjectHost> bindings_;
  blink::mojom::ServiceWorkerObjectAssociatedPtr remote_object_;
};

}  // namespace

class ServiceWorkerContextClientTest : public testing::Test {
 public:
  ServiceWorkerContextClientTest() = default;

 protected:
  void SetUp() override {
    task_runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
    message_loop_.SetTaskRunner(task_runner_);
    // Use this thread as the worker thread.
    WorkerThreadRegistry::Instance()->DidStartCurrentWorkerThread();
  }

  void TearDown() override {
    ServiceWorkerContextClient::ResetThreadSpecificInstanceForTesting();
    // Unregister this thread from worker threads.
    WorkerThreadRegistry::Instance()->WillStopCurrentWorkerThread();
    task_runner_->RunUntilIdle();
  }

  void EnableServicification() {
    feature_list_.InitWithFeatures({network::features::kNetworkService}, {});
    ASSERT_TRUE(blink::ServiceWorkerUtils::IsServicificationEnabled());
  }

  // Creates an empty struct to initialize ServiceWorkerProviderContext.
  mojom::ServiceWorkerProviderInfoForStartWorkerPtr CreateProviderInfo() {
    auto info = mojom::ServiceWorkerProviderInfoForStartWorker::New();
    info->provider_id = 10;  // dummy
    return info;
  }

  // Creates an ContextClient, whose pipes are connected to |out_pipes|, then
  // simulates that the service worker thread has started with |proxy|.
  std::unique_ptr<ServiceWorkerContextClient> CreateContextClient(
      ContextClientPipes* out_pipes,
      blink::WebServiceWorkerContextProxy* proxy) {
    auto event_dispatcher_request =
        mojo::MakeRequest(&out_pipes->event_dispatcher);
    auto controller_request = mojo::MakeRequest(&out_pipes->controller);
    mojom::EmbeddedWorkerInstanceHostAssociatedPtr embedded_worker_host_ptr;
    out_pipes->embedded_worker_host_request =
        mojo::MakeRequestAssociatedWithDedicatedPipe(&embedded_worker_host_ptr);
    const GURL kScope("https://example.com");
    const GURL kScript("https://example.com/SW.js");
    std::unique_ptr<ServiceWorkerContextClient> context_client =
        std::make_unique<ServiceWorkerContextClient>(
            1 /* embedded_worker_id */, 1 /* service_worker_version_id */,
            kScope, kScript, false /* is_script_streaming */,
            std::move(event_dispatcher_request), std::move(controller_request),
            embedded_worker_host_ptr.PassInterface(), CreateProviderInfo(),
            nullptr /* embedded_worker_client */,
            mojom::EmbeddedWorkerStartTiming::New(),
            blink::scheduler::GetSingleThreadTaskRunnerForTesting());

    context_client->WorkerContextStarted(proxy);

    blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host;
    out_pipes->service_worker_host_request =
        mojo::MakeRequest(&service_worker_host);
    auto registration_info =
        blink::mojom::ServiceWorkerRegistrationObjectInfo::New();
    registration_info->registration_id = 100;  // dummy
    registration_info->options =
        blink::mojom::ServiceWorkerRegistrationOptions::New(
            kScope, blink::mojom::ServiceWorkerUpdateViaCache::kAll);
    out_pipes->registration_host_request =
        mojo::MakeRequest(&registration_info->host_ptr_info);
    registration_info->request = mojo::MakeRequest(&out_pipes->registration);
    out_pipes->event_dispatcher->InitializeGlobalScope(
        std::move(service_worker_host), std::move(registration_info));
    task_runner()->RunUntilIdle();
    return context_client;
  }

  bool ContainsServiceWorkerObject(ServiceWorkerContextClient* context_client,
                                   int64_t version_id) {
    return context_client->ContainsServiceWorkerObjectForTesting(version_id);
  }

  scoped_refptr<base::TestMockTimeTaskRunner> task_runner() const {
    return task_runner_;
  }

 private:
  base::MessageLoop message_loop_;
  scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
  base::test::ScopedFeatureList feature_list_;
};

TEST_F(ServiceWorkerContextClientTest, Ping) {
  ContextClientPipes pipes;
  MockWebServiceWorkerContextProxy mock_proxy;
  std::unique_ptr<ServiceWorkerContextClient> context_client =
      CreateContextClient(&pipes, &mock_proxy);

  bool is_called = false;
  pipes.event_dispatcher->Ping(CreateCallbackWithCalledFlag(&is_called));
  task_runner()->RunUntilIdle();
  EXPECT_TRUE(is_called);
}

TEST_F(ServiceWorkerContextClientTest, DispatchFetchEvent) {
  ContextClientPipes pipes;
  MockWebServiceWorkerContextProxy mock_proxy;
  std::unique_ptr<ServiceWorkerContextClient> context_client =
      CreateContextClient(&pipes, &mock_proxy);
  context_client->DidEvaluateClassicScript(true /* success */);
  task_runner()->RunUntilIdle();
  EXPECT_TRUE(mock_proxy.fetch_events().empty());

  const GURL expected_url("https://example.com/expected");
  mojom::ServiceWorkerFetchResponseCallbackRequest fetch_callback_request;
  auto request = std::make_unique<network::ResourceRequest>();
  request->url = expected_url;
  mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
  fetch_callback_request = mojo::MakeRequest(&fetch_callback_ptr);
  auto params = blink::mojom::DispatchFetchEventParams::New();
  params->request = *request;
  pipes.event_dispatcher->DispatchFetchEvent(
      std::move(params), std::move(fetch_callback_ptr),
      base::BindOnce(
          [](blink::mojom::ServiceWorkerEventStatus, base::Time) {}));
  task_runner()->RunUntilIdle();

  ASSERT_EQ(1u, mock_proxy.fetch_events().size());
  EXPECT_EQ(request->url,
            static_cast<GURL>(mock_proxy.fetch_events()[0].second.Url()));
}

TEST_F(ServiceWorkerContextClientTest,
       DispatchOrQueueFetchEvent_NotRequestedTermination) {
  EnableServicification();
  ContextClientPipes pipes;
  MockWebServiceWorkerContextProxy mock_proxy;
  std::unique_ptr<ServiceWorkerContextClient> context_client =
      CreateContextClient(&pipes, &mock_proxy);
  context_client->DidEvaluateClassicScript(true /* success */);
  task_runner()->RunUntilIdle();
  EXPECT_TRUE(mock_proxy.fetch_events().empty());

  bool is_idle = false;
  auto timer = std::make_unique<ServiceWorkerTimeoutTimer>(
      CreateCallbackWithCalledFlag(&is_idle),
      task_runner()->GetMockTickClock());
  context_client->SetTimeoutTimerForTesting(std::move(timer));

  // The dispatched fetch event should be recorded by |mock_proxy|.
  const GURL expected_url("https://example.com/expected");
  mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
  mojom::ServiceWorkerFetchResponseCallbackRequest fetch_callback_request =
      mojo::MakeRequest(&fetch_callback_ptr);
  auto request = std::make_unique<network::ResourceRequest>();
  request->url = expected_url;
  auto params = blink::mojom::DispatchFetchEventParams::New();
  params->request = *request;
  context_client->DispatchOrQueueFetchEvent(
      std::move(params), std::move(fetch_callback_ptr),
      base::BindOnce(
          [](blink::mojom::ServiceWorkerEventStatus, base::Time) {}));
  task_runner()->RunUntilIdle();

  EXPECT_FALSE(context_client->RequestedTermination());
  ASSERT_EQ(1u, mock_proxy.fetch_events().size());
  EXPECT_EQ(expected_url,
            static_cast<GURL>(mock_proxy.fetch_events()[0].second.Url()));
}

TEST_F(ServiceWorkerContextClientTest,
       DispatchOrQueueFetchEvent_RequestedTerminationAndDie) {
  EnableServicification();
  ContextClientPipes pipes;
  MockWebServiceWorkerContextProxy mock_proxy;
  std::unique_ptr<ServiceWorkerContextClient> context_client =
      CreateContextClient(&pipes, &mock_proxy);
  context_client->DidEvaluateClassicScript(true /* success */);
  task_runner()->RunUntilIdle();
  EXPECT_TRUE(mock_proxy.fetch_events().empty());

  bool is_idle = false;
  auto timer = std::make_unique<ServiceWorkerTimeoutTimer>(
      CreateCallbackWithCalledFlag(&is_idle),
      task_runner()->GetMockTickClock());
  context_client->SetTimeoutTimerForTesting(std::move(timer));

  // Ensure the idle state.
  EXPECT_FALSE(context_client->RequestedTermination());
  task_runner()->FastForwardBy(ServiceWorkerTimeoutTimer::kIdleDelay +
                               ServiceWorkerTimeoutTimer::kUpdateInterval +
                               base::TimeDelta::FromSeconds(1));
  EXPECT_TRUE(context_client->RequestedTermination());

  const GURL expected_url("https://example.com/expected");
  mojom::ServiceWorkerFetchResponseCallbackRequest fetch_callback_request;

  // FetchEvent dispatched directly from the controlled clients through
  // mojom::ControllerServiceWorker should be queued in the idle state.
  {
    mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
    fetch_callback_request = mojo::MakeRequest(&fetch_callback_ptr);
    auto request = std::make_unique<network::ResourceRequest>();
    request->url = expected_url;
    auto params = blink::mojom::DispatchFetchEventParams::New();
    params->request = *request;
    pipes.controller->DispatchFetchEvent(
        std::move(params), std::move(fetch_callback_ptr),
        base::BindOnce(
            [](blink::mojom::ServiceWorkerEventStatus, base::Time) {}));
    task_runner()->RunUntilIdle();
  }
  EXPECT_TRUE(mock_proxy.fetch_events().empty());

  // Destruction of |context_client| should not hit any DCHECKs.
  context_client.reset();
}

TEST_F(ServiceWorkerContextClientTest,
       DispatchOrQueueFetchEvent_RequestedTerminationAndWakeUp) {
  EnableServicification();
  ContextClientPipes pipes;
  MockWebServiceWorkerContextProxy mock_proxy;
  std::unique_ptr<ServiceWorkerContextClient> context_client =
      CreateContextClient(&pipes, &mock_proxy);
  context_client->DidEvaluateClassicScript(true /* success */);
  task_runner()->RunUntilIdle();
  EXPECT_TRUE(mock_proxy.fetch_events().empty());
  bool is_idle = false;
  auto timer = std::make_unique<ServiceWorkerTimeoutTimer>(
      CreateCallbackWithCalledFlag(&is_idle),
      task_runner()->GetMockTickClock());
  context_client->SetTimeoutTimerForTesting(std::move(timer));

  // Ensure the idle state.
  EXPECT_FALSE(context_client->RequestedTermination());
  task_runner()->FastForwardBy(ServiceWorkerTimeoutTimer::kIdleDelay +
                               ServiceWorkerTimeoutTimer::kUpdateInterval +
                               base::TimeDelta::FromSeconds(1));
  EXPECT_TRUE(context_client->RequestedTermination());

  const GURL expected_url_1("https://example.com/expected_1");
  const GURL expected_url_2("https://example.com/expected_2");
  mojom::ServiceWorkerFetchResponseCallbackRequest fetch_callback_request_1;
  mojom::ServiceWorkerFetchResponseCallbackRequest fetch_callback_request_2;

  // FetchEvent dispatched directly from the controlled clients through
  // mojom::ControllerServiceWorker should be queued in the idle state.
  {
    mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
    fetch_callback_request_1 = mojo::MakeRequest(&fetch_callback_ptr);
    auto request = std::make_unique<network::ResourceRequest>();
    request->url = expected_url_1;
    auto params = blink::mojom::DispatchFetchEventParams::New();
    params->request = *request;
    pipes.controller->DispatchFetchEvent(
        std::move(params), std::move(fetch_callback_ptr),
        base::BindOnce(
            [](blink::mojom::ServiceWorkerEventStatus, base::Time) {}));
    task_runner()->RunUntilIdle();
  }
  EXPECT_TRUE(mock_proxy.fetch_events().empty());

  // Another event dispatched to mojom::ServiceWorkerEventDispatcher wakes up
  // the context client.
  {
    mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
    fetch_callback_request_2 = mojo::MakeRequest(&fetch_callback_ptr);
    auto request = std::make_unique<network::ResourceRequest>();
    request->url = expected_url_2;
    auto params = blink::mojom::DispatchFetchEventParams::New();
    params->request = *request;
    pipes.event_dispatcher->DispatchFetchEvent(
        std::move(params), std::move(fetch_callback_ptr),
        base::BindOnce(
            [](blink::mojom::ServiceWorkerEventStatus, base::Time) {}));
    task_runner()->RunUntilIdle();
  }
  EXPECT_FALSE(context_client->RequestedTermination());

  // All events should fire. The order of events should be kept.
  ASSERT_EQ(2u, mock_proxy.fetch_events().size());
  EXPECT_EQ(expected_url_1,
            static_cast<GURL>(mock_proxy.fetch_events()[0].second.Url()));
  EXPECT_EQ(expected_url_2,
            static_cast<GURL>(mock_proxy.fetch_events()[1].second.Url()));
}

TEST_F(ServiceWorkerContextClientTest, GetOrCreateServiceWorkerObject) {
  ContextClientPipes pipes;
  MockWebServiceWorkerContextProxy mock_proxy;
  std::unique_ptr<ServiceWorkerContextClient> context_client =
      CreateContextClient(&pipes, &mock_proxy);
  scoped_refptr<WebServiceWorkerImpl> worker1;
  scoped_refptr<WebServiceWorkerImpl> worker2;
  const int64_t version_id = 200;
  auto mock_service_worker_object_host =
      std::make_unique<MockServiceWorkerObjectHost>(version_id);
  ASSERT_EQ(0, mock_service_worker_object_host->GetBindingCount());

  // Should return a worker object newly created with the 1st given |info|.
  {
    blink::mojom::ServiceWorkerObjectInfoPtr info =
        mock_service_worker_object_host->CreateObjectInfo();
    // ServiceWorkerObjectHost Mojo connection has been added.
    EXPECT_EQ(1, mock_service_worker_object_host->GetBindingCount());
    EXPECT_FALSE(ContainsServiceWorkerObject(context_client.get(), version_id));
    worker1 = context_client->GetOrCreateServiceWorkerObject(std::move(info));
    EXPECT_TRUE(worker1);
    EXPECT_TRUE(ContainsServiceWorkerObject(context_client.get(), version_id));
    // |worker1| is holding the 1st blink::mojom::ServiceWorkerObjectHost Mojo
    // connection to |mock_service_worker_object_host|.
    EXPECT_EQ(1, mock_service_worker_object_host->GetBindingCount());
  }

  // Should return the same worker object and release the 2nd given |info|.
  {
    blink::mojom::ServiceWorkerObjectInfoPtr info =
        mock_service_worker_object_host->CreateObjectInfo();
    EXPECT_EQ(2, mock_service_worker_object_host->GetBindingCount());
    worker2 = context_client->GetOrCreateServiceWorkerObject(std::move(info));
    EXPECT_EQ(worker1, worker2);
    task_runner()->RunUntilIdle();
    // The 2nd ServiceWorkerObjectHost Mojo connection in |info| has been
    // dropped.
    EXPECT_EQ(1, mock_service_worker_object_host->GetBindingCount());
  }

  // The dtor decrements the refcounts.
  worker1 = nullptr;
  worker2 = nullptr;
  task_runner()->RunUntilIdle();
  EXPECT_FALSE(ContainsServiceWorkerObject(context_client.get(), version_id));
  // The 1st ServiceWorkerObjectHost Mojo connection got broken.
  EXPECT_EQ(0, mock_service_worker_object_host->GetBindingCount());

  // Should return nullptr when given nullptr.
  scoped_refptr<WebServiceWorkerImpl> invalid_worker =
      context_client->GetOrCreateServiceWorkerObject(nullptr);
  EXPECT_FALSE(invalid_worker);
}

}  // namespace content
