// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/service_worker/service_worker_version.h"

#include <stdint.h>

#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_mojo_service.mojom.h"
#include "content/public/test/test_utils.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "testing/gtest/include/gtest/gtest.h"

// IPC messages for testing ---------------------------------------------------

#define IPC_MESSAGE_IMPL
#include "ipc/ipc_message_macros.h"

#define IPC_MESSAGE_START TestMsgStart

IPC_MESSAGE_CONTROL0(TestMsg_Message)
IPC_MESSAGE_ROUTED1(TestMsg_MessageFromWorker, int)

IPC_MESSAGE_CONTROL1(TestMsg_TestEvent, int)
IPC_MESSAGE_ROUTED2(TestMsg_TestEventResult, int, std::string)
IPC_MESSAGE_ROUTED2(TestMsg_TestSimpleEventResult,
                    int,
                    blink::WebServiceWorkerEventResult)

IPC_ENUM_TRAITS_MAX_VALUE(blink::WebServiceWorkerEventResult,
                          blink::WebServiceWorkerEventResultLast)

// ---------------------------------------------------------------------------

namespace content {

namespace {

class MessageReceiver : public EmbeddedWorkerTestHelper {
 public:
  MessageReceiver()
      : EmbeddedWorkerTestHelper(base::FilePath()),
        current_embedded_worker_id_(0) {}
  ~MessageReceiver() override {}

  bool OnMessageToWorker(int thread_id,
                         int embedded_worker_id,
                         const IPC::Message& message) override {
    if (EmbeddedWorkerTestHelper::OnMessageToWorker(
            thread_id, embedded_worker_id, message)) {
      return true;
    }
    current_embedded_worker_id_ = embedded_worker_id;
    bool handled = true;
    IPC_BEGIN_MESSAGE_MAP(MessageReceiver, message)
      IPC_MESSAGE_HANDLER(TestMsg_Message, OnMessage)
      IPC_MESSAGE_UNHANDLED(handled = false)
    IPC_END_MESSAGE_MAP()
    return handled;
  }

  void SimulateSendValueToBrowser(int embedded_worker_id, int value) {
    SimulateSend(new TestMsg_MessageFromWorker(embedded_worker_id, value));
  }

  void SimulateSendEventResult(int embedded_worker_id,
                               int request_id,
                               const std::string& reply) {
    SimulateSend(
        new TestMsg_TestEventResult(embedded_worker_id, request_id, reply));
  }

  void SimulateSendSimpleEventResult(int embedded_worker_id,
                                     int request_id,
                                     blink::WebServiceWorkerEventResult reply) {
    SimulateSend(new TestMsg_TestSimpleEventResult(embedded_worker_id,
                                                   request_id, reply));
  }

 private:
  void OnMessage() {
    // Do nothing.
  }

  int current_embedded_worker_id_;
  DISALLOW_COPY_AND_ASSIGN(MessageReceiver);
};

void VerifyCalled(bool* called) {
  *called = true;
}

void ObserveStatusChanges(ServiceWorkerVersion* version,
                          std::vector<ServiceWorkerVersion::Status>* statuses) {
  statuses->push_back(version->status());
  version->RegisterStatusChangeCallback(
      base::Bind(&ObserveStatusChanges, base::Unretained(version), statuses));
}

void ReceiveTestEventResult(int* request_id,
                            std::string* data,
                            const base::Closure& callback,
                            int actual_request_id,
                            const std::string& actual_data) {
  *request_id = actual_request_id;
  *data = actual_data;
  callback.Run();
}

// A specialized listener class to receive test messages from a worker.
class MessageReceiverFromWorker : public EmbeddedWorkerInstance::Listener {
 public:
  explicit MessageReceiverFromWorker(EmbeddedWorkerInstance* instance)
      : instance_(instance) {
    instance_->AddListener(this);
  }
  ~MessageReceiverFromWorker() override { instance_->RemoveListener(this); }

  void OnStarted() override { NOTREACHED(); }
  void OnStopped(EmbeddedWorkerInstance::Status old_status) override {
    NOTREACHED();
  }
  bool OnMessageReceived(const IPC::Message& message) override {
    bool handled = true;
    IPC_BEGIN_MESSAGE_MAP(MessageReceiverFromWorker, message)
      IPC_MESSAGE_HANDLER(TestMsg_MessageFromWorker, OnMessageFromWorker)
      IPC_MESSAGE_UNHANDLED(handled = false)
    IPC_END_MESSAGE_MAP()
    return handled;
  }

  void OnMessageFromWorker(int value) { received_values_.push_back(value); }
  const std::vector<int>& received_values() const { return received_values_; }

 private:
  EmbeddedWorkerInstance* instance_;
  std::vector<int> received_values_;
  DISALLOW_COPY_AND_ASSIGN(MessageReceiverFromWorker);
};

base::Time GetYesterday() {
  return base::Time::Now() - base::TimeDelta::FromDays(1) -
         base::TimeDelta::FromSeconds(1);
}

class TestMojoServiceImpl : public mojom::TestMojoService {
 public:
  static void Create(mojo::InterfaceRequest<mojom::TestMojoService> request) {
    new TestMojoServiceImpl(std::move(request));
  }

  void DoSomething(const DoSomethingCallback& callback) override {
    callback.Run();
  }

  void GetRequestorName(const GetRequestorNameCallback& callback) override {
    callback.Run(mojo::String(""));
  }

 private:
  explicit TestMojoServiceImpl(
      mojo::InterfaceRequest<mojom::TestMojoService> request)
      : binding_(this, std::move(request)) {}

  mojo::StrongBinding<mojom::TestMojoService> binding_;
};

}  // namespace

class ServiceWorkerVersionTest : public testing::Test {
 protected:
  struct RunningStateListener : public ServiceWorkerVersion::Listener {
    RunningStateListener() : last_status(ServiceWorkerVersion::STOPPED) {}
    ~RunningStateListener() override {}
    void OnRunningStateChanged(ServiceWorkerVersion* version) override {
      last_status = version->running_status();
    }
    ServiceWorkerVersion::RunningStatus last_status;
  };

  ServiceWorkerVersionTest()
      : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}

  void SetUp() override {
    helper_ = GetMessageReceiver();

    helper_->context()->storage()->LazyInitialize(base::Bind(&base::DoNothing));
    base::RunLoop().RunUntilIdle();

    pattern_ = GURL("http://www.example.com/test/");
    registration_ = new ServiceWorkerRegistration(
        pattern_,
        1L,
        helper_->context()->AsWeakPtr());
    version_ = new ServiceWorkerVersion(
        registration_.get(),
        GURL("http://www.example.com/test/service_worker.js"),
        helper_->context()->storage()->NewVersionId(),
        helper_->context()->AsWeakPtr());
    std::vector<ServiceWorkerDatabase::ResourceRecord> records;
    records.push_back(
        ServiceWorkerDatabase::ResourceRecord(10, version_->script_url(), 100));
    version_->script_cache_map()->SetResources(records);

    // Make the registration findable via storage functions.
    ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
    helper_->context()->storage()->StoreRegistration(
        registration_.get(),
        version_.get(),
        CreateReceiverOnCurrentThread(&status));
    base::RunLoop().RunUntilIdle();
    ASSERT_EQ(SERVICE_WORKER_OK, status);

    // Simulate adding one process to the pattern.
    helper_->SimulateAddProcessToPattern(pattern_,
                                         helper_->mock_render_process_id());
    ASSERT_TRUE(helper_->context()->process_manager()
        ->PatternHasProcessToRun(pattern_));
  }

  virtual std::unique_ptr<MessageReceiver> GetMessageReceiver() {
    return base::WrapUnique(new MessageReceiver());
  }

  void TearDown() override {
    version_ = 0;
    registration_ = 0;
    helper_.reset();
  }

  void SimulateDispatchEvent(ServiceWorkerMetrics::EventType event_type) {
    ServiceWorkerStatusCode status =
        SERVICE_WORKER_ERROR_MAX_VALUE;  // dummy value

    // Make sure worker is running.
    scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
    version_->RunAfterStartWorker(event_type, runner->QuitClosure(),
                                  CreateReceiverOnCurrentThread(&status));
    runner->Run();
    EXPECT_EQ(SERVICE_WORKER_ERROR_MAX_VALUE, status);
    EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

    // Start request, as if an event is being dispatched.
    int request_id = version_->StartRequest(
        event_type, CreateReceiverOnCurrentThread(&status));
    base::RunLoop().RunUntilIdle();

    // And finish request, as if a response to the event was received.
    EXPECT_TRUE(version_->FinishRequest(request_id, true));
    base::RunLoop().RunUntilIdle();
    EXPECT_EQ(SERVICE_WORKER_ERROR_MAX_VALUE, status);
  }

  TestBrowserThreadBundle thread_bundle_;
  std::unique_ptr<MessageReceiver> helper_;
  scoped_refptr<ServiceWorkerRegistration> registration_;
  scoped_refptr<ServiceWorkerVersion> version_;
  GURL pattern_;

 private:
  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersionTest);
};

class MessageReceiverDisallowStart : public MessageReceiver {
 public:
  MessageReceiverDisallowStart()
      : MessageReceiver() {}
  ~MessageReceiverDisallowStart() override {}

  enum class StartMode { STALL, FAIL, SUCCEED };

  void OnStartWorker(int embedded_worker_id,
                     int64_t service_worker_version_id,
                     const GURL& scope,
                     const GURL& script_url,
                     bool pause_after_download) override {
    switch (mode_) {
      case StartMode::STALL:
        break;  // Do nothing.
      case StartMode::FAIL:
        OnStopWorker(embedded_worker_id);
        break;
      case StartMode::SUCCEED:
        MessageReceiver::OnStartWorker(embedded_worker_id,
                                       service_worker_version_id, scope,
                                       script_url, pause_after_download);
        break;
    }
  }

  void set_start_mode(StartMode mode) { mode_ = mode; }

 private:
  StartMode mode_ = StartMode::STALL;
  DISALLOW_COPY_AND_ASSIGN(MessageReceiverDisallowStart);
};

class ServiceWorkerFailToStartTest : public ServiceWorkerVersionTest {
 protected:
  ServiceWorkerFailToStartTest()
      : ServiceWorkerVersionTest() {}

  void set_start_mode(MessageReceiverDisallowStart::StartMode mode) {
    MessageReceiverDisallowStart* helper =
        static_cast<MessageReceiverDisallowStart*>(helper_.get());
    helper->set_start_mode(mode);
  }

  std::unique_ptr<MessageReceiver> GetMessageReceiver() override {
    return base::WrapUnique(new MessageReceiverDisallowStart());
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerFailToStartTest);
};

class MessageReceiverDisallowStop : public MessageReceiver {
 public:
  MessageReceiverDisallowStop() : MessageReceiver() {}
  ~MessageReceiverDisallowStop() override {}

  void OnStopWorker(int embedded_worker_id) override {
    // Do nothing.
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(MessageReceiverDisallowStop);
};

class ServiceWorkerStallInStoppingTest : public ServiceWorkerVersionTest {
 protected:
  ServiceWorkerStallInStoppingTest() : ServiceWorkerVersionTest() {}

  std::unique_ptr<MessageReceiver> GetMessageReceiver() override {
    return base::WrapUnique(new MessageReceiverDisallowStop());
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerStallInStoppingTest);
};

class MessageReceiverMojoTestService : public MessageReceiver {
 public:
  MessageReceiverMojoTestService() : MessageReceiver() {}
  ~MessageReceiverMojoTestService() override {}

  void OnSetupMojo(ServiceRegistry* service_registry) override {
    service_registry->AddService(base::Bind(&TestMojoServiceImpl::Create));
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(MessageReceiverMojoTestService);
};

class ServiceWorkerVersionWithMojoTest : public ServiceWorkerVersionTest {
 protected:
  ServiceWorkerVersionWithMojoTest() : ServiceWorkerVersionTest() {}

  std::unique_ptr<MessageReceiver> GetMessageReceiver() override {
    return base::WrapUnique(new MessageReceiverMojoTestService());
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersionWithMojoTest);
};

TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
  // Call StartWorker() multiple times.
  ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED;
  ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED;
  ServiceWorkerStatusCode status3 = SERVICE_WORKER_ERROR_FAILED;
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status1));
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status2));

  EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Call StartWorker() after it's started.
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status3));
  base::RunLoop().RunUntilIdle();

  // All should just succeed.
  EXPECT_EQ(SERVICE_WORKER_OK, status1);
  EXPECT_EQ(SERVICE_WORKER_OK, status2);
  EXPECT_EQ(SERVICE_WORKER_OK, status3);

  // Call StopWorker() multiple times.
  status1 = SERVICE_WORKER_ERROR_FAILED;
  status2 = SERVICE_WORKER_ERROR_FAILED;
  version_->StopWorker(CreateReceiverOnCurrentThread(&status1));
  version_->StopWorker(CreateReceiverOnCurrentThread(&status2));

  EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());

  // All StopWorker should just succeed.
  EXPECT_EQ(SERVICE_WORKER_OK, status1);
  EXPECT_EQ(SERVICE_WORKER_OK, status2);

  // Start worker again.
  status1 = SERVICE_WORKER_ERROR_FAILED;
  status2 = SERVICE_WORKER_ERROR_FAILED;
  status3 = SERVICE_WORKER_ERROR_FAILED;

  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status1));

  EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Call StopWorker()
  status2 = SERVICE_WORKER_ERROR_FAILED;
  version_->StopWorker(CreateReceiverOnCurrentThread(&status2));

  // And try calling StartWorker while StopWorker is in queue.
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status3));

  EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // All should just succeed.
  EXPECT_EQ(SERVICE_WORKER_OK, status1);
  EXPECT_EQ(SERVICE_WORKER_OK, status2);
  EXPECT_EQ(SERVICE_WORKER_OK, status3);
}

TEST_F(ServiceWorkerVersionTest, DispatchEventToStoppedWorker) {
  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());

  // Dispatch an event without starting the worker.
  version_->SetStatus(ServiceWorkerVersion::INSTALLING);
  SimulateDispatchEvent(ServiceWorkerMetrics::EventType::INSTALL);

  // The worker should be now started.
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Stop the worker, and then dispatch an event immediately after that.
  ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
  version_->StopWorker(CreateReceiverOnCurrentThread(&stop_status));
  SimulateDispatchEvent(ServiceWorkerMetrics::EventType::INSTALL);
  EXPECT_EQ(SERVICE_WORKER_OK, stop_status);

  // The worker should be now started again.
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
}

TEST_F(ServiceWorkerVersionTest, StartUnregisteredButStillLiveWorker) {
  // Start the worker.
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);

  // Delete the registration.
  status = SERVICE_WORKER_ERROR_FAILED;
  helper_->context()->storage()->DeleteRegistration(
      registration_->id(), registration_->pattern().GetOrigin(),
      CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  ASSERT_EQ(SERVICE_WORKER_OK, status);

  // The live registration is marked as deleted, but still exists.
  ASSERT_TRUE(registration_->is_deleted());

  // Stop the worker.
  ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
  version_->StopWorker(CreateReceiverOnCurrentThread(&stop_status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, stop_status);

  // Dispatch an event on the unregistered and stopped but still live worker.
  status = SERVICE_WORKER_ERROR_FAILED;
  SimulateDispatchEvent(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME);

  // The worker should be now started again.
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
}

TEST_F(ServiceWorkerVersionTest, ReceiveMessageFromWorker) {
  // Start worker.
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));
  EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  MessageReceiverFromWorker receiver(version_->embedded_worker());

  // Simulate sending some dummy values from the worker.
  helper_->SimulateSendValueToBrowser(
      version_->embedded_worker()->embedded_worker_id(), 555);
  helper_->SimulateSendValueToBrowser(
      version_->embedded_worker()->embedded_worker_id(), 777);

  // Verify the receiver received the values.
  ASSERT_EQ(2U, receiver.received_values().size());
  EXPECT_EQ(555, receiver.received_values()[0]);
  EXPECT_EQ(777, receiver.received_values()[1]);
}

TEST_F(ServiceWorkerVersionTest, InstallAndWaitCompletion) {
  version_->SetStatus(ServiceWorkerVersion::INSTALLING);

  // Wait for the completion.
  bool status_change_called = false;
  version_->RegisterStatusChangeCallback(
      base::Bind(&VerifyCalled, &status_change_called));

  // Dispatch an install event.
  SimulateDispatchEvent(ServiceWorkerMetrics::EventType::INSTALL);

  // Version's status must not have changed during installation.
  EXPECT_FALSE(status_change_called);
  EXPECT_EQ(ServiceWorkerVersion::INSTALLING, version_->status());
}

TEST_F(ServiceWorkerVersionTest, ActivateAndWaitCompletion) {
  // TODO(mek): This test (and the one above for the install event) made more
  // sense back when ServiceWorkerVersion was responsible for updating the
  // status. Now a better version of this test should probably be added to
  // ServiceWorkerRegistrationTest instead.

  version_->SetStatus(ServiceWorkerVersion::ACTIVATING);

  // Wait for the completion.
  bool status_change_called = false;
  version_->RegisterStatusChangeCallback(
      base::Bind(&VerifyCalled, &status_change_called));

  // Dispatch an activate event.
  SimulateDispatchEvent(ServiceWorkerMetrics::EventType::ACTIVATE);

  // Version's status must not have changed during activation.
  EXPECT_FALSE(status_change_called);
  EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
}

TEST_F(ServiceWorkerVersionTest, RepeatedlyObserveStatusChanges) {
  EXPECT_EQ(ServiceWorkerVersion::NEW, version_->status());

  // Repeatedly observe status changes (the callback re-registers itself).
  std::vector<ServiceWorkerVersion::Status> statuses;
  version_->RegisterStatusChangeCallback(base::Bind(
      &ObserveStatusChanges, base::RetainedRef(version_), &statuses));

  version_->SetStatus(ServiceWorkerVersion::INSTALLING);
  version_->SetStatus(ServiceWorkerVersion::INSTALLED);
  version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
  version_->SetStatus(ServiceWorkerVersion::REDUNDANT);

  // Verify that we could successfully observe repeated status changes.
  ASSERT_EQ(5U, statuses.size());
  ASSERT_EQ(ServiceWorkerVersion::INSTALLING, statuses[0]);
  ASSERT_EQ(ServiceWorkerVersion::INSTALLED, statuses[1]);
  ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, statuses[2]);
  ASSERT_EQ(ServiceWorkerVersion::ACTIVATED, statuses[3]);
  ASSERT_EQ(ServiceWorkerVersion::REDUNDANT, statuses[4]);
}

TEST_F(ServiceWorkerVersionTest, IdleTimeout) {
  // Used to reliably test when the idle time gets reset regardless of clock
  // granularity.
  const base::TimeDelta kOneSecond = base::TimeDelta::FromSeconds(1);

  // Verify the timer is not running when version initializes its status.
  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
  EXPECT_FALSE(version_->timeout_timer_.IsRunning());

  // Verify the timer is running after the worker is started.
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_TRUE(version_->timeout_timer_.IsRunning());
  EXPECT_FALSE(version_->idle_time_.is_null());

  // The idle time should be reset if the worker is restarted without
  // controllee.
  status = SERVICE_WORKER_ERROR_FAILED;
  version_->idle_time_ -= kOneSecond;
  base::TimeTicks idle_time = version_->idle_time_;
  version_->StopWorker(CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  status = SERVICE_WORKER_ERROR_FAILED;
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_TRUE(version_->timeout_timer_.IsRunning());
  EXPECT_LT(idle_time, version_->idle_time_);

  // Adding a controllee resets the idle time.
  version_->idle_time_ -= kOneSecond;
  idle_time = version_->idle_time_;
  std::unique_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
      33 /* dummy render process id */, MSG_ROUTING_NONE /* render_frame_id */,
      1 /* dummy provider_id */, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
      ServiceWorkerProviderHost::FrameSecurityLevel::SECURE,
      helper_->context()->AsWeakPtr(), NULL));
  version_->AddControllee(host.get());
  EXPECT_TRUE(version_->timeout_timer_.IsRunning());
  EXPECT_LT(idle_time, version_->idle_time_);

  // Completing an event resets the idle time.
  version_->idle_time_ -= kOneSecond;
  idle_time = version_->idle_time_;
  SimulateDispatchEvent(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME);
  EXPECT_LT(idle_time, version_->idle_time_);

  // Starting and finishing a request resets the idle time.
  version_->idle_time_ -= kOneSecond;
  idle_time = version_->idle_time_;
  int request_id =
      version_->StartRequest(ServiceWorkerMetrics::EventType::SYNC,
                             CreateReceiverOnCurrentThread(&status));
  EXPECT_TRUE(version_->FinishRequest(request_id, true));

  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_LT(idle_time, version_->idle_time_);
}

TEST_F(ServiceWorkerVersionTest, SetDevToolsAttached) {
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));

  ASSERT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());

  ASSERT_TRUE(version_->timeout_timer_.IsRunning());
  ASSERT_FALSE(version_->start_time_.is_null());
  ASSERT_FALSE(version_->skip_recording_startup_time_);

  // Simulate DevTools is attached. This should deactivate the timer for start
  // timeout, but not stop the timer itself.
  version_->SetDevToolsAttached(true);
  EXPECT_TRUE(version_->timeout_timer_.IsRunning());
  EXPECT_TRUE(version_->start_time_.is_null());
  EXPECT_TRUE(version_->skip_recording_startup_time_);

  // Simulate DevTools is detached. This should reactivate the timer for start
  // timeout.
  version_->SetDevToolsAttached(false);
  EXPECT_TRUE(version_->timeout_timer_.IsRunning());
  EXPECT_FALSE(version_->start_time_.is_null());
  EXPECT_TRUE(version_->skip_recording_startup_time_);

  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
}

TEST_F(ServiceWorkerVersionTest, StoppingBeforeDestruct) {
  RunningStateListener listener;
  version_->AddListener(&listener);

  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, listener.last_status);

  version_ = nullptr;
  EXPECT_EQ(ServiceWorkerVersion::STOPPING, listener.last_status);
}

// Test that update isn't triggered for a non-stale worker.
TEST_F(ServiceWorkerVersionTest, StaleUpdate_FreshWorker) {
  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
  registration_->SetActiveVersion(version_);
  registration_->set_last_update_check(base::Time::Now());
  SimulateDispatchEvent(ServiceWorkerMetrics::EventType::PUSH);

  EXPECT_TRUE(version_->stale_time_.is_null());
  EXPECT_FALSE(version_->update_timer_.IsRunning());
}

// Test that update isn't triggered for a non-active worker.
TEST_F(ServiceWorkerVersionTest, StaleUpdate_NonActiveWorker) {
  version_->SetStatus(ServiceWorkerVersion::INSTALLING);
  registration_->SetInstallingVersion(version_);
  registration_->set_last_update_check(GetYesterday());
  SimulateDispatchEvent(ServiceWorkerMetrics::EventType::INSTALL);

  EXPECT_TRUE(version_->stale_time_.is_null());
  EXPECT_FALSE(version_->update_timer_.IsRunning());
}

// Test that staleness is detected when starting a worker.
TEST_F(ServiceWorkerVersionTest, StaleUpdate_StartWorker) {
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;

  // Starting the worker marks it as stale.
  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
  registration_->SetActiveVersion(version_);
  registration_->set_last_update_check(GetYesterday());
  SimulateDispatchEvent(ServiceWorkerMetrics::EventType::PUSH);
  EXPECT_FALSE(version_->stale_time_.is_null());
  EXPECT_FALSE(version_->update_timer_.IsRunning());

  // Update is actually scheduled after the worker stops.
  version_->StopWorker(CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_TRUE(version_->stale_time_.is_null());
  EXPECT_TRUE(version_->update_timer_.IsRunning());
}

// Test that staleness is detected on a running worker.
TEST_F(ServiceWorkerVersionTest, StaleUpdate_RunningWorker) {
  // Start a fresh worker.
  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
  registration_->SetActiveVersion(version_);
  registration_->set_last_update_check(base::Time::Now());
  SimulateDispatchEvent(ServiceWorkerMetrics::EventType::PUSH);
  EXPECT_TRUE(version_->stale_time_.is_null());

  // Simulate it running for a day. It will be marked stale.
  registration_->set_last_update_check(GetYesterday());
  version_->OnTimeoutTimer();
  EXPECT_FALSE(version_->stale_time_.is_null());
  EXPECT_FALSE(version_->update_timer_.IsRunning());

  // Simulate it running for past the wait threshold. The update will be
  // scheduled.
  version_->stale_time_ =
      base::TimeTicks::Now() -
      base::TimeDelta::FromMinutes(
          ServiceWorkerVersion::kStartNewWorkerTimeoutMinutes + 1);
  version_->OnTimeoutTimer();
  EXPECT_TRUE(version_->stale_time_.is_null());
  EXPECT_TRUE(version_->update_timer_.IsRunning());
}

// Test that a stream of events doesn't restart the timer.
TEST_F(ServiceWorkerVersionTest, StaleUpdate_DoNotDeferTimer) {
  // Make a stale worker.
  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
  registration_->SetActiveVersion(version_);
  registration_->set_last_update_check(GetYesterday());
  base::TimeTicks stale_time =
      base::TimeTicks::Now() -
      base::TimeDelta::FromMinutes(
          ServiceWorkerVersion::kStartNewWorkerTimeoutMinutes + 1);
  version_->stale_time_ = stale_time;

  // Stale time is not deferred.
  version_->RunAfterStartWorker(
      ServiceWorkerMetrics::EventType::UNKNOWN, base::Bind(&base::DoNothing),
      base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
  version_->RunAfterStartWorker(
      ServiceWorkerMetrics::EventType::UNKNOWN, base::Bind(&base::DoNothing),
      base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(stale_time, version_->stale_time_);

  // Timeout triggers the update.
  version_->OnTimeoutTimer();
  EXPECT_TRUE(version_->stale_time_.is_null());
  EXPECT_TRUE(version_->update_timer_.IsRunning());

  // Update timer is not deferred.
  base::TimeTicks run_time = version_->update_timer_.desired_run_time();
  SimulateDispatchEvent(ServiceWorkerMetrics::EventType::PUSH);
  SimulateDispatchEvent(ServiceWorkerMetrics::EventType::PUSH);
  SimulateDispatchEvent(ServiceWorkerMetrics::EventType::PUSH);
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(version_->stale_time_.is_null());
  EXPECT_EQ(run_time, version_->update_timer_.desired_run_time());
}

TEST_F(ServiceWorkerVersionTest, RequestTimeout) {
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value
  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);

  version_->StartWorker(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
                        base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
  base::RunLoop().RunUntilIdle();

  // Create a request.
  int request_id =
      version_->StartRequest(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
                             CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();

  // Callback has not completed yet.
  EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Simulate timeout.
  EXPECT_TRUE(version_->timeout_timer_.IsRunning());
  version_->SetAllRequestExpirations(base::TimeTicks::Now());
  version_->timeout_timer_.user_task().Run();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
  EXPECT_FALSE(version_->FinishRequest(request_id, true));
}

TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeout) {
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value
  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);

  version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
                        base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
  base::RunLoop().RunUntilIdle();

  // Create a request that should expire Now().
  int request_id = version_->StartRequestWithCustomTimeout(
      ServiceWorkerMetrics::EventType::SYNC,
      CreateReceiverOnCurrentThread(&status), base::TimeDelta(),
      ServiceWorkerVersion::CONTINUE_ON_TIMEOUT);

  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(version_->timeout_timer_.IsRunning());
  version_->timeout_timer_.user_task().Run();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);

  EXPECT_FALSE(version_->FinishRequest(request_id, true));

  // CONTINUE_ON_TIMEOUT timeouts don't stop the service worker.
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
}

TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeoutKill) {
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value
  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);

  version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
                        base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
  base::RunLoop().RunUntilIdle();

  // Create a request that should expire Now().
  int request_id = version_->StartRequestWithCustomTimeout(
      ServiceWorkerMetrics::EventType::SYNC,
      CreateReceiverOnCurrentThread(&status), base::TimeDelta(),
      ServiceWorkerVersion::KILL_ON_TIMEOUT);

  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(version_->timeout_timer_.IsRunning());
  version_->timeout_timer_.user_task().Run();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);

  EXPECT_FALSE(version_->FinishRequest(request_id, true));

  // KILL_ON_TIMEOUT timeouts should stop the service worker.
  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
}

TEST_F(ServiceWorkerVersionTest, MixedRequestTimeouts) {
  ServiceWorkerStatusCode sync_status =
      SERVICE_WORKER_ERROR_NETWORK;  // dummy value
  ServiceWorkerStatusCode fetch_status =
      SERVICE_WORKER_ERROR_NETWORK;  // dummy value
  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);

  version_->StartWorker(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
                        base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
  base::RunLoop().RunUntilIdle();

  // Create a fetch request that should expire sometime later.
  int fetch_request_id =
      version_->StartRequest(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
                             CreateReceiverOnCurrentThread(&fetch_status));
  // Create a request that should expire Now().
  int sync_request_id = version_->StartRequestWithCustomTimeout(
      ServiceWorkerMetrics::EventType::SYNC,
      CreateReceiverOnCurrentThread(&sync_status), base::TimeDelta(),
      ServiceWorkerVersion::CONTINUE_ON_TIMEOUT);
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, sync_status);

  // Verify the sync has timed out but not the fetch.
  EXPECT_TRUE(version_->timeout_timer_.IsRunning());
  version_->timeout_timer_.user_task().Run();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, sync_status);
  EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, fetch_status);

  // Background sync timeouts don't stop the service worker.
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Gracefully handle the sync event finishing after the timeout.
  EXPECT_FALSE(version_->FinishRequest(sync_request_id, true));

  // Verify that the fetch times out later.
  version_->SetAllRequestExpirations(base::TimeTicks::Now());
  version_->timeout_timer_.user_task().Run();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, fetch_status);

  // Fetch request should no longer exist.
  EXPECT_FALSE(version_->FinishRequest(fetch_request_id, true));

  // Other timeouts do stop the service worker.
  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
}

TEST_F(ServiceWorkerFailToStartTest, RendererCrash) {
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();

  // Callback has not completed yet.
  EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
  EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());

  // Simulate renderer crash: do what
  // ServiceWorkerDispatcherHost::OnFilterRemoved does.
  int process_id = helper_->mock_render_process_id();
  helper_->context()->RemoveAllProviderHostsForProcess(process_id);
  helper_->context()->embedded_worker_registry()->RemoveChildProcessSender(
      process_id);
  base::RunLoop().RunUntilIdle();

  // Callback completed.
  EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
}

TEST_F(ServiceWorkerFailToStartTest, Timeout) {
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value

  // Start starting the worker.
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();

  // Callback has not completed yet.
  EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
  EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());

  // Simulate timeout.
  EXPECT_TRUE(version_->timeout_timer_.IsRunning());
  version_->start_time_ =
      base::TimeTicks::Now() -
      base::TimeDelta::FromMinutes(
          ServiceWorkerVersion::kStartNewWorkerTimeoutMinutes + 1);
  version_->timeout_timer_.user_task().Run();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
}

// Test that a service worker stalled in stopping will timeout and not get in a
// sticky error state.
TEST_F(ServiceWorkerStallInStoppingTest, DetachThenStart) {
  // Start a worker.
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Try to stop the worker.
  status = SERVICE_WORKER_ERROR_FAILED;
  version_->StopWorker(CreateReceiverOnCurrentThread(&status));
  EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());
  base::RunLoop().RunUntilIdle();

  // Worker is now stalled in stopping. Verify a fast timeout is in place.
  EXPECT_TRUE(version_->timeout_timer_.IsRunning());
  EXPECT_EQ(base::TimeDelta::FromSeconds(
                ServiceWorkerVersion::kStopWorkerTimeoutSeconds),
            version_->timeout_timer_.GetCurrentDelay());

  // Simulate timeout.
  version_->stop_time_ =
      base::TimeTicks::Now() -
      base::TimeDelta::FromSeconds(
          ServiceWorkerVersion::kStopWorkerTimeoutSeconds + 1);
  version_->timeout_timer_.user_task().Run();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());

  // Try to start the worker again. It should work.
  status = SERVICE_WORKER_ERROR_FAILED;
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // The timeout interval should be reset to normal.
  EXPECT_TRUE(version_->timeout_timer_.IsRunning());
  EXPECT_EQ(base::TimeDelta::FromSeconds(
                ServiceWorkerVersion::kTimeoutTimerDelaySeconds),
            version_->timeout_timer_.GetCurrentDelay());
}

// Test that a service worker stalled in stopping with a start worker
// request queued up will timeout and restart.
TEST_F(ServiceWorkerStallInStoppingTest, DetachThenRestart) {
  // Start a worker.
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Try to stop the worker.
  status = SERVICE_WORKER_ERROR_FAILED;
  version_->StopWorker(CreateReceiverOnCurrentThread(&status));
  EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());

  // Worker is now stalled in stopping. Add a start worker requset.
  ServiceWorkerStatusCode start_status = SERVICE_WORKER_ERROR_FAILED;
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&start_status));

  // Simulate timeout. The worker should stop and get restarted.
  EXPECT_TRUE(version_->timeout_timer_.IsRunning());
  version_->stop_time_ =
      base::TimeTicks::Now() -
      base::TimeDelta::FromSeconds(
          ServiceWorkerVersion::kStopWorkerTimeoutSeconds + 1);
  version_->timeout_timer_.user_task().Run();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(SERVICE_WORKER_OK, start_status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
}

TEST_F(ServiceWorkerVersionTest, RegisterForeignFetchScopes) {
  version_->SetStatus(ServiceWorkerVersion::INSTALLING);
  // Start a worker.
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
  EXPECT_EQ(0, helper_->mock_render_process_host()->bad_msg_count());

  GURL valid_scope_1("http://www.example.com/test/subscope");
  GURL valid_scope_2("http://www.example.com/test/othersubscope");
  std::vector<GURL> valid_scopes;
  valid_scopes.push_back(valid_scope_1);
  valid_scopes.push_back(valid_scope_2);

  std::vector<url::Origin> all_origins;
  url::Origin valid_origin(GURL("https://chromium.org/"));
  std::vector<url::Origin> valid_origin_list(1, valid_origin);

  // Invalid subscope, should kill worker (but in tests will only increase bad
  // message count).
  version_->OnRegisterForeignFetchScopes(std::vector<GURL>(1, GURL()),
                                         valid_origin_list);
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(1, helper_->mock_render_process_host()->bad_msg_count());
  EXPECT_EQ(0u, version_->foreign_fetch_scopes_.size());
  EXPECT_EQ(0u, version_->foreign_fetch_origins_.size());

  // Subscope outside the scope of the worker.
  version_->OnRegisterForeignFetchScopes(
      std::vector<GURL>(1, GURL("http://www.example.com/wrong")),
      valid_origin_list);
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(2, helper_->mock_render_process_host()->bad_msg_count());
  EXPECT_EQ(0u, version_->foreign_fetch_scopes_.size());
  EXPECT_EQ(0u, version_->foreign_fetch_origins_.size());

  // Subscope on wrong origin.
  version_->OnRegisterForeignFetchScopes(
      std::vector<GURL>(1, GURL("http://example.com/test/")),
      valid_origin_list);
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(3, helper_->mock_render_process_host()->bad_msg_count());
  EXPECT_EQ(0u, version_->foreign_fetch_scopes_.size());
  EXPECT_EQ(0u, version_->foreign_fetch_origins_.size());

  // Invalid origin.
  version_->OnRegisterForeignFetchScopes(
      valid_scopes, std::vector<url::Origin>(1, url::Origin()));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(4, helper_->mock_render_process_host()->bad_msg_count());
  EXPECT_EQ(0u, version_->foreign_fetch_scopes_.size());
  EXPECT_EQ(0u, version_->foreign_fetch_origins_.size());

  // Valid subscope, no origins.
  version_->OnRegisterForeignFetchScopes(std::vector<GURL>(1, valid_scope_1),
                                         all_origins);
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(4, helper_->mock_render_process_host()->bad_msg_count());
  EXPECT_EQ(1u, version_->foreign_fetch_scopes_.size());
  EXPECT_EQ(valid_scope_1, version_->foreign_fetch_scopes_[0]);
  EXPECT_EQ(0u, version_->foreign_fetch_origins_.size());

  // Valid subscope, explicit origins.
  version_->OnRegisterForeignFetchScopes(valid_scopes, valid_origin_list);
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(4, helper_->mock_render_process_host()->bad_msg_count());
  EXPECT_EQ(2u, version_->foreign_fetch_scopes_.size());
  EXPECT_EQ(valid_scope_1, version_->foreign_fetch_scopes_[0]);
  EXPECT_EQ(valid_scope_2, version_->foreign_fetch_scopes_[1]);
  EXPECT_EQ(1u, version_->foreign_fetch_origins_.size());
  EXPECT_EQ(valid_origin, version_->foreign_fetch_origins_[0]);
}

TEST_F(ServiceWorkerVersionTest, RendererCrashDuringEvent) {
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value

  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
  version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  int request_id =
      version_->StartRequest(ServiceWorkerMetrics::EventType::SYNC,
                             CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();

  // Callback has not completed yet.
  EXPECT_EQ(SERVICE_WORKER_OK, status);

  // Simulate renderer crash: do what
  // ServiceWorkerDispatcherHost::OnFilterRemoved does.
  int process_id = helper_->mock_render_process_id();
  helper_->context()->RemoveAllProviderHostsForProcess(process_id);
  helper_->context()->embedded_worker_registry()->RemoveChildProcessSender(
      process_id);
  base::RunLoop().RunUntilIdle();

  // Callback completed.
  EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED, status);
  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());

  // Request already failed, calling finsh should return false.
  EXPECT_FALSE(version_->FinishRequest(request_id, true));
}

TEST_F(ServiceWorkerVersionWithMojoTest, MojoService) {
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value

  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
  version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
  int request_id = version_->StartRequest(
      ServiceWorkerMetrics::EventType::SYNC,
      CreateReceiverOnCurrentThread(&status, runner->QuitClosure()));
  base::WeakPtr<mojom::TestMojoService> service =
      version_->GetMojoServiceForRequest<mojom::TestMojoService>(request_id);
  service->DoSomething(runner->QuitClosure());
  runner->Run();

  // Mojo service does exist in worker, so error callback should not have been
  // called and FinishRequest should return true.
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_TRUE(version_->FinishRequest(request_id, true));
}

TEST_F(ServiceWorkerVersionTest, NonExistentMojoService) {
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value

  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
  version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
  int request_id = version_->StartRequest(
      ServiceWorkerMetrics::EventType::SYNC,
      CreateReceiverOnCurrentThread(&status, runner->QuitClosure()));
  base::WeakPtr<mojom::TestMojoService> service =
      version_->GetMojoServiceForRequest<mojom::TestMojoService>(request_id);
  service->DoSomething(runner->QuitClosure());
  runner->Run();

  // Mojo service doesn't exist in worker, so error callback should have been
  // called and FinishRequest should return false.
  EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED, status);
  EXPECT_FALSE(version_->FinishRequest(request_id, true));
}

TEST_F(ServiceWorkerVersionTest, DispatchEvent) {
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value

  // Activate and start worker.
  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
  version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Start request and dispatch test event.
  scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
  int request_id = version_->StartRequest(
      ServiceWorkerMetrics::EventType::SYNC,
      CreateReceiverOnCurrentThread(&status, runner->QuitClosure()));
  int received_request_id = 0;
  std::string received_data;
  version_->DispatchEvent<TestMsg_TestEventResult>(
      request_id, TestMsg_TestEvent(request_id),
      base::Bind(&ReceiveTestEventResult, &received_request_id, &received_data,
                 runner->QuitClosure()));

  // Verify event got dispatched to worker.
  base::RunLoop().RunUntilIdle();
  ASSERT_EQ(1u, helper_->inner_ipc_sink()->message_count());
  const IPC::Message* msg = helper_->inner_ipc_sink()->GetMessageAt(0);
  EXPECT_EQ(TestMsg_TestEvent::ID, msg->type());

  // Simulate sending reply to event.
  std::string reply("foobar");
  helper_->SimulateSendEventResult(
      version_->embedded_worker()->embedded_worker_id(), request_id, reply);
  runner->Run();

  // Verify message callback got called with correct reply.
  EXPECT_EQ(request_id, received_request_id);
  EXPECT_EQ(reply, received_data);

  // Should not have timed out, so error callback should not have been
  // called and FinishRequest should return true.
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_TRUE(version_->FinishRequest(request_id, true));
}

TEST_F(ServiceWorkerFailToStartTest, FailingWorkerUsesNewRendererProcess) {
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;

  helper_->SimulateAddProcessToPattern(pattern_,
                                       helper_->new_render_process_id());
  ServiceWorkerContextCore* context = helper_->context();
  int64_t id = version_->version_id();
  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);

  // Start once. It should choose the "existing process".
  set_start_mode(MessageReceiverDisallowStart::StartMode::SUCCEED);
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(helper_->mock_render_process_id(),
            version_->embedded_worker()->process_id());
  version_->StopWorker(CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();

  // Fail once.
  set_start_mode(MessageReceiverDisallowStart::StartMode::FAIL);
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
  EXPECT_EQ(1, context->GetVersionFailureCount(id));

  // Fail again.
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
  EXPECT_EQ(2, context->GetVersionFailureCount(id));

  // Succeed. It should choose the "new process".
  set_start_mode(MessageReceiverDisallowStart::StartMode::SUCCEED);
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(helper_->new_render_process_id(),
            version_->embedded_worker()->process_id());
  EXPECT_EQ(0, context->GetVersionFailureCount(id));
  version_->StopWorker(CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();

  // Start again. It should choose the "existing process" again as we no longer
  // force creation of a new process.
  version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(helper_->mock_render_process_id(),
            version_->embedded_worker()->process_id());
  version_->StopWorker(CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
}

TEST_F(ServiceWorkerVersionTest, DispatchConcurrentEvent) {
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value

  // Activate and start worker.
  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
  version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Start first request and dispatch test event.
  scoped_refptr<MessageLoopRunner> runner1(new MessageLoopRunner);
  ServiceWorkerStatusCode status1 = SERVICE_WORKER_OK;  // dummy value
  int request_id1 = version_->StartRequest(
      ServiceWorkerMetrics::EventType::SYNC,
      CreateReceiverOnCurrentThread(&status1, runner1->QuitClosure()));
  int received_request_id1 = 0;
  std::string received_data1;
  version_->DispatchEvent<TestMsg_TestEventResult>(
      request_id1, TestMsg_TestEvent(request_id1),
      base::Bind(&ReceiveTestEventResult, &received_request_id1,
                 &received_data1, runner1->QuitClosure()));

  // Start second request and dispatch test event.
  scoped_refptr<MessageLoopRunner> runner2(new MessageLoopRunner);
  ServiceWorkerStatusCode status2 = SERVICE_WORKER_OK;  // dummy value
  int request_id2 = version_->StartRequest(
      ServiceWorkerMetrics::EventType::SYNC,
      CreateReceiverOnCurrentThread(&status2, runner2->QuitClosure()));
  int received_request_id2 = 0;
  std::string received_data2;
  version_->DispatchEvent<TestMsg_TestEventResult>(
      request_id2, TestMsg_TestEvent(request_id2),
      base::Bind(&ReceiveTestEventResult, &received_request_id2,
                 &received_data2, runner2->QuitClosure()));

  // Make sure events got dispatched in same order.
  base::RunLoop().RunUntilIdle();
  ASSERT_EQ(2u, helper_->inner_ipc_sink()->message_count());
  const IPC::Message* msg = helper_->inner_ipc_sink()->GetMessageAt(0);
  ASSERT_EQ(TestMsg_TestEvent::ID, msg->type());
  TestMsg_TestEvent::Param params;
  TestMsg_TestEvent::Read(msg, &params);
  EXPECT_EQ(request_id1, base::get<0>(params));
  msg = helper_->inner_ipc_sink()->GetMessageAt(1);
  ASSERT_EQ(TestMsg_TestEvent::ID, msg->type());
  TestMsg_TestEvent::Read(msg, &params);
  EXPECT_EQ(request_id2, base::get<0>(params));

  // Reply to second event.
  std::string reply2("foobar");
  helper_->SimulateSendEventResult(
      version_->embedded_worker()->embedded_worker_id(), request_id2, reply2);
  runner2->Run();

  // Verify correct message callback got called with correct reply.
  EXPECT_EQ(0, received_request_id1);
  EXPECT_EQ(request_id2, received_request_id2);
  EXPECT_EQ(reply2, received_data2);
  EXPECT_EQ(SERVICE_WORKER_OK, status2);
  EXPECT_TRUE(version_->FinishRequest(request_id2, true));

  // Reply to first event.
  std::string reply1("hello world");
  helper_->SimulateSendEventResult(
      version_->embedded_worker()->embedded_worker_id(), request_id1, reply1);
  runner1->Run();

  // Verify correct response was received.
  EXPECT_EQ(request_id1, received_request_id1);
  EXPECT_EQ(request_id2, received_request_id2);
  EXPECT_EQ(reply1, received_data1);
  EXPECT_EQ(SERVICE_WORKER_OK, status1);
  EXPECT_TRUE(version_->FinishRequest(request_id1, true));
}

TEST_F(ServiceWorkerVersionTest, DispatchSimpleEvent_Completed) {
  ServiceWorkerStatusCode status =
      SERVICE_WORKER_ERROR_MAX_VALUE;  // dummy value

  // Activate and start worker.
  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
  version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Start request and dispatch test event.
  status = SERVICE_WORKER_ERROR_MAX_VALUE;  // dummy value
  scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
  int request_id = version_->StartRequest(
      ServiceWorkerMetrics::EventType::SYNC,
      CreateReceiverOnCurrentThread(&status, runner->QuitClosure()));
  version_->DispatchSimpleEvent<TestMsg_TestSimpleEventResult>(
      request_id, TestMsg_TestEvent(request_id));

  // Verify event got dispatched to worker.
  base::RunLoop().RunUntilIdle();
  ASSERT_EQ(1u, helper_->inner_ipc_sink()->message_count());
  const IPC::Message* msg = helper_->inner_ipc_sink()->GetMessageAt(0);
  EXPECT_EQ(TestMsg_TestEvent::ID, msg->type());

  // Simulate sending reply to event.
  helper_->SimulateSendSimpleEventResult(
      version_->embedded_worker()->embedded_worker_id(), request_id,
      blink::WebServiceWorkerEventResultCompleted);
  runner->Run();

  // Verify callback was called with correct status.
  EXPECT_EQ(SERVICE_WORKER_OK, status);
}

TEST_F(ServiceWorkerVersionTest, DispatchSimpleEvent_Rejected) {
  ServiceWorkerStatusCode status =
      SERVICE_WORKER_ERROR_MAX_VALUE;  // dummy value

  // Activate and start worker.
  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
  version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Start request and dispatch test event.
  status = SERVICE_WORKER_ERROR_MAX_VALUE;  // dummy value
  scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
  int request_id = version_->StartRequest(
      ServiceWorkerMetrics::EventType::SYNC,
      CreateReceiverOnCurrentThread(&status, runner->QuitClosure()));
  version_->DispatchSimpleEvent<TestMsg_TestSimpleEventResult>(
      request_id, TestMsg_TestEvent(request_id));

  // Verify event got dispatched to worker.
  base::RunLoop().RunUntilIdle();
  ASSERT_EQ(1u, helper_->inner_ipc_sink()->message_count());
  const IPC::Message* msg = helper_->inner_ipc_sink()->GetMessageAt(0);
  EXPECT_EQ(TestMsg_TestEvent::ID, msg->type());

  // Simulate sending reply to event.
  helper_->SimulateSendSimpleEventResult(
      version_->embedded_worker()->embedded_worker_id(), request_id,
      blink::WebServiceWorkerEventResultRejected);
  runner->Run();

  // Verify callback was called with correct status.
  EXPECT_EQ(SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED, status);
}

}  // namespace content
