Introduce ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time UMA.

We can measure the effect of the speculatively launch of Service Workers on UI-events by this metric.

BUG=616502

Review-Url: https://codereview.chromium.org/2039743003
Cr-Commit-Position: refs/heads/master@{#398814}
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc
index 2d5880a0..fadb79c 100644
--- a/content/browser/background_sync/background_sync_manager.cc
+++ b/content/browser/background_sync/background_sync_manager.cc
@@ -17,6 +17,7 @@
 #include "content/browser/background_sync/background_sync_metrics.h"
 #include "content/browser/background_sync/background_sync_network_observer.h"
 #include "content/browser/background_sync/background_sync_registration_options.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_storage.h"
 #include "content/browser/storage_partition_impl.h"
@@ -755,7 +756,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(active_version);
 
-  if (active_version->running_status() != ServiceWorkerVersion::RUNNING) {
+  if (active_version->running_status() != EmbeddedWorkerStatus::RUNNING) {
     active_version->RunAfterStartWorker(
         ServiceWorkerMetrics::EventType::SYNC,
         base::Bind(&BackgroundSyncManager::DispatchSyncEvent,
diff --git a/content/browser/devtools/protocol/service_worker_handler.cc b/content/browser/devtools/protocol/service_worker_handler.cc
index 60f0241..b9f528fd 100644
--- a/content/browser/devtools/protocol/service_worker_handler.cc
+++ b/content/browser/devtools/protocol/service_worker_handler.cc
@@ -15,6 +15,7 @@
 #include "content/browser/frame_host/frame_tree.h"
 #include "content/browser/frame_host/frame_tree_node.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_context_watcher.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_version.h"
@@ -62,15 +63,15 @@
 }
 
 const std::string GetVersionRunningStatusString(
-    content::ServiceWorkerVersion::RunningStatus running_status) {
+    EmbeddedWorkerStatus running_status) {
   switch (running_status) {
-    case content::ServiceWorkerVersion::STOPPED:
+    case EmbeddedWorkerStatus::STOPPED:
       return kServiceWorkerVersionRunningStatusStopped;
-    case content::ServiceWorkerVersion::STARTING:
+    case EmbeddedWorkerStatus::STARTING:
       return kServiceWorkerVersionRunningStatusStarting;
-    case content::ServiceWorkerVersion::RUNNING:
+    case EmbeddedWorkerStatus::RUNNING:
       return kServiceWorkerVersionRunningStatusRunning;
-    case content::ServiceWorkerVersion::STOPPING:
+    case EmbeddedWorkerStatus::STOPPING:
       return kServiceWorkerVersionRunningStatusStopping;
   }
   return std::string();
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc
index f6f4638..6e26164 100644
--- a/content/browser/service_worker/embedded_worker_instance.cc
+++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -14,6 +14,7 @@
 #include "base/trace_event/trace_event.h"
 #include "content/browser/devtools/service_worker_devtools_manager.h"
 #include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/common/content_switches_internal.h"
 #include "content/common/mojo/service_registry_impl.h"
@@ -216,7 +217,7 @@
       : instance_(instance),
         state_(ProcessAllocationState::NOT_ALLOCATED),
         is_installed_(false),
-        start_situation_(ServiceWorkerMetrics::StartSituation::UNKNOWN),
+        started_during_browser_startup_(false),
         weak_factory_(this) {
     TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "EmbeddedWorkerInstance::Start",
                              this, "Script", script_url.spec());
@@ -263,7 +264,7 @@
     is_installed_ = params->is_installed;
 
     if (!GetContentClient()->browser()->IsBrowserStartupComplete())
-      start_situation_ = ServiceWorkerMetrics::StartSituation::DURING_STARTUP;
+      started_during_browser_startup_ = true;
 
     GURL scope(params->scope);
     GURL script_url(params->script_url);
@@ -288,9 +289,6 @@
   }
 
   bool is_installed() const { return is_installed_; }
-  ServiceWorkerMetrics::StartSituation start_situation() const {
-    return start_situation_;
-  }
 
  private:
   void OnProcessAllocated(
@@ -319,19 +317,22 @@
     if (is_installed_)
       ServiceWorkerMetrics::RecordProcessCreated(is_new_process);
 
-    if (start_situation_ == ServiceWorkerMetrics::StartSituation::UNKNOWN) {
-      if (is_new_process)
-        start_situation_ = ServiceWorkerMetrics::StartSituation::NEW_PROCESS;
-      else
-        start_situation_ =
-            ServiceWorkerMetrics::StartSituation::EXISTING_PROCESS;
-    }
+    ServiceWorkerMetrics::StartSituation start_situation =
+        ServiceWorkerMetrics::StartSituation::UNKNOWN;
+    if (started_during_browser_startup_)
+      start_situation = ServiceWorkerMetrics::StartSituation::DURING_STARTUP;
+    else if (is_new_process)
+      start_situation = ServiceWorkerMetrics::StartSituation::NEW_PROCESS;
+    else
+      start_situation = ServiceWorkerMetrics::StartSituation::EXISTING_PROCESS;
 
     // Notify the instance that a process is allocated.
     state_ = ProcessAllocationState::ALLOCATED;
-    instance_->OnProcessAllocated(base::WrapUnique(new WorkerProcessHandle(
-        instance_->context_, instance_->embedded_worker_id(), process_id,
-        is_new_process)));
+    instance_->OnProcessAllocated(
+        base::WrapUnique(new WorkerProcessHandle(
+            instance_->context_, instance_->embedded_worker_id(), process_id,
+            is_new_process)),
+        start_situation);
 
     // TODO(bengr): Support changes to this setting while the worker
     // is running.
@@ -399,7 +400,7 @@
 
   // Used for UMA.
   bool is_installed_;
-  ServiceWorkerMetrics::StartSituation start_situation_;
+  bool started_during_browser_startup_;
 
   base::WeakPtrFactory<StartTask> weak_factory_;
 
@@ -412,7 +413,9 @@
 }
 
 EmbeddedWorkerInstance::~EmbeddedWorkerInstance() {
-  DCHECK(status_ == STOPPING || status_ == STOPPED) << status_;
+  DCHECK(status_ == EmbeddedWorkerStatus::STOPPING ||
+         status_ == EmbeddedWorkerStatus::STOPPED)
+      << static_cast<int>(status_);
   devtools_proxy_.reset();
   if (registry_->GetWorker(embedded_worker_id_))
     registry_->RemoveWorker(process_id(), embedded_worker_id_);
@@ -427,12 +430,12 @@
     // |this| may be destroyed by the callback.
     return;
   }
-  DCHECK(status_ == STOPPED);
+  DCHECK(status_ == EmbeddedWorkerStatus::STOPPED);
 
   DCHECK(!params->pause_after_download || !params->is_installed);
   DCHECK_NE(kInvalidServiceWorkerVersionId, params->service_worker_version_id);
   step_time_ = base::TimeTicks::Now();
-  status_ = STARTING;
+  status_ = EmbeddedWorkerStatus::STARTING;
   starting_phase_ = ALLOCATING_PROCESS;
   network_accessed_for_script_ = false;
   service_registry_.reset(new ServiceRegistryImpl());
@@ -448,7 +451,9 @@
 }
 
 ServiceWorkerStatusCode EmbeddedWorkerInstance::Stop() {
-  DCHECK(status_ == STARTING || status_ == RUNNING) << status_;
+  DCHECK(status_ == EmbeddedWorkerStatus::STARTING ||
+         status_ == EmbeddedWorkerStatus::RUNNING)
+      << static_cast<int>(status_);
 
   // Abort an inflight start task.
   inflight_start_task_.reset();
@@ -464,7 +469,7 @@
     return status;
   }
 
-  status_ = STOPPING;
+  status_ = EmbeddedWorkerStatus::STOPPING;
   FOR_EACH_OBSERVER(Listener, listener_list_, OnStopping());
   return status;
 }
@@ -481,22 +486,28 @@
 ServiceWorkerStatusCode EmbeddedWorkerInstance::SendMessage(
     const IPC::Message& message) {
   DCHECK_NE(kInvalidEmbeddedWorkerThreadId, thread_id_);
-  if (status_ != RUNNING && status_ != STARTING)
+  if (status_ != EmbeddedWorkerStatus::RUNNING &&
+      status_ != EmbeddedWorkerStatus::STARTING) {
     return SERVICE_WORKER_ERROR_IPC_FAILED;
+  }
   return registry_->Send(process_id(),
                          new EmbeddedWorkerContextMsg_MessageToWorker(
                              thread_id_, embedded_worker_id_, message));
 }
 
 void EmbeddedWorkerInstance::ResumeAfterDownload() {
-  if (process_id() == ChildProcessHost::kInvalidUniqueID || status_ != STARTING)
+  if (process_id() == ChildProcessHost::kInvalidUniqueID ||
+      status_ != EmbeddedWorkerStatus::STARTING) {
     return;
+  }
   registry_->Send(process_id(), new EmbeddedWorkerMsg_ResumeAfterDownload(
                                     embedded_worker_id_));
 }
 
 ServiceRegistry* EmbeddedWorkerInstance::GetServiceRegistry() {
-  DCHECK(status_ == STARTING || status_ == RUNNING) << status_;
+  DCHECK(status_ == EmbeddedWorkerStatus::STARTING ||
+         status_ == EmbeddedWorkerStatus::RUNNING)
+      << static_cast<int>(status_);
   return service_registry_.get();
 }
 
@@ -506,7 +517,7 @@
     : context_(context),
       registry_(context->embedded_worker_registry()),
       embedded_worker_id_(embedded_worker_id),
-      status_(STOPPED),
+      status_(EmbeddedWorkerStatus::STOPPED),
       starting_phase_(NOT_STARTING),
       thread_id_(kInvalidEmbeddedWorkerThreadId),
       devtools_attached_(false),
@@ -514,12 +525,14 @@
       weak_factory_(this) {}
 
 void EmbeddedWorkerInstance::OnProcessAllocated(
-    std::unique_ptr<WorkerProcessHandle> handle) {
-  DCHECK_EQ(STARTING, status_);
+    std::unique_ptr<WorkerProcessHandle> handle,
+    ServiceWorkerMetrics::StartSituation start_situation) {
+  DCHECK_EQ(EmbeddedWorkerStatus::STARTING, status_);
   DCHECK(!process_handle_);
 
   process_handle_ = std::move(handle);
   starting_phase_ = REGISTERING_TO_DEVTOOLS;
+  start_situation_ = start_situation;
   FOR_EACH_OBSERVER(Listener, listener_list_, OnProcessAllocated());
 }
 
@@ -543,8 +556,8 @@
   if (!step_time_.is_null()) {
     base::TimeDelta duration = UpdateStepTime();
     if (inflight_start_task_->is_installed()) {
-      ServiceWorkerMetrics::RecordTimeToSendStartWorker(
-          duration, inflight_start_task_->start_situation());
+      ServiceWorkerMetrics::RecordTimeToSendStartWorker(duration,
+                                                        start_situation_);
     }
   }
 
@@ -586,8 +599,7 @@
 
   if (!step_time_.is_null()) {
     base::TimeDelta duration = UpdateStepTime();
-    ServiceWorkerMetrics::RecordTimeToLoad(
-        duration, source, inflight_start_task_->start_situation());
+    ServiceWorkerMetrics::RecordTimeToLoad(duration, source, start_situation_);
   }
 
   starting_phase_ = SCRIPT_LOADED;
@@ -603,8 +615,7 @@
   if (!step_time_.is_null()) {
     base::TimeDelta duration = UpdateStepTime();
     if (inflight_start_task_->is_installed())
-      ServiceWorkerMetrics::RecordTimeToURLJob(
-          duration, inflight_start_task_->start_situation());
+      ServiceWorkerMetrics::RecordTimeToURLJob(duration, start_situation_);
   }
 }
 
@@ -628,8 +639,7 @@
   if (!step_time_.is_null()) {
     base::TimeDelta duration = UpdateStepTime();
     if (inflight_start_task_->is_installed())
-      ServiceWorkerMetrics::RecordTimeToStartThread(
-          duration, inflight_start_task_->start_situation());
+      ServiceWorkerMetrics::RecordTimeToStartThread(duration, start_situation_);
   }
 
   thread_id_ = thread_id;
@@ -659,7 +669,7 @@
 void EmbeddedWorkerInstance::OnScriptEvaluated(bool success) {
   if (!inflight_start_task_)
     return;
-  DCHECK_EQ(STARTING, status_);
+  DCHECK_EQ(EmbeddedWorkerStatus::STARTING, status_);
 
   TRACE_EVENT_ASYNC_STEP_PAST1("ServiceWorker", "EmbeddedWorkerInstance::Start",
                                inflight_start_task_.get(), "OnScriptEvaluated",
@@ -668,8 +678,8 @@
   if (!step_time_.is_null()) {
     base::TimeDelta duration = UpdateStepTime();
     if (success && inflight_start_task_->is_installed())
-      ServiceWorkerMetrics::RecordTimeToEvaluateScript(
-          duration, inflight_start_task_->start_situation());
+      ServiceWorkerMetrics::RecordTimeToEvaluateScript(duration,
+                                                       start_situation_);
   }
 
   base::WeakPtr<EmbeddedWorkerInstance> weak_this = weak_factory_.GetWeakPtr();
@@ -682,22 +692,22 @@
 
 void EmbeddedWorkerInstance::OnStarted() {
   // Stop is requested before OnStarted is sent back from the worker.
-  if (status_ == STOPPING)
+  if (status_ == EmbeddedWorkerStatus::STOPPING)
     return;
-  DCHECK(status_ == STARTING);
-  status_ = RUNNING;
+  DCHECK(status_ == EmbeddedWorkerStatus::STARTING);
+  status_ = EmbeddedWorkerStatus::RUNNING;
   inflight_start_task_.reset();
   FOR_EACH_OBSERVER(Listener, listener_list_, OnStarted());
 }
 
 void EmbeddedWorkerInstance::OnStopped() {
-  Status old_status = status_;
+  EmbeddedWorkerStatus old_status = status_;
   ReleaseProcess();
   FOR_EACH_OBSERVER(Listener, listener_list_, OnStopped(old_status));
 }
 
 void EmbeddedWorkerInstance::OnDetached() {
-  Status old_status = status_;
+  EmbeddedWorkerStatus old_status = status_;
   ReleaseProcess();
   FOR_EACH_OBSERVER(Listener, listener_list_, OnDetached(old_status));
 }
@@ -785,18 +795,18 @@
 
   devtools_proxy_.reset();
   process_handle_.reset();
-  status_ = STOPPED;
+  status_ = EmbeddedWorkerStatus::STOPPED;
   thread_id_ = kInvalidEmbeddedWorkerThreadId;
   service_registry_.reset();
 }
 
 void EmbeddedWorkerInstance::OnStartFailed(const StatusCallback& callback,
                                            ServiceWorkerStatusCode status) {
-  Status old_status = status_;
+  EmbeddedWorkerStatus old_status = status_;
   ReleaseProcess();
   base::WeakPtr<EmbeddedWorkerInstance> weak_this = weak_factory_.GetWeakPtr();
   callback.Run(status);
-  if (weak_this && old_status != STOPPED)
+  if (weak_this && old_status != EmbeddedWorkerStatus::STOPPED)
     FOR_EACH_OBSERVER(Listener, weak_this->listener_list_,
                       OnStopped(old_status));
 }
@@ -812,25 +822,28 @@
 
 void EmbeddedWorkerInstance::AddMessageToConsole(ConsoleMessageLevel level,
                                                  const std::string& message) {
-  if (status_ != RUNNING && status_ != STARTING)
+  if (status_ != EmbeddedWorkerStatus::RUNNING &&
+      status_ != EmbeddedWorkerStatus::STARTING) {
     return;
+  }
   registry_->Send(process_id(), new EmbeddedWorkerMsg_AddMessageToConsole(
                                     embedded_worker_id_, level, message));
 }
 
 // static
-std::string EmbeddedWorkerInstance::StatusToString(Status status) {
+std::string EmbeddedWorkerInstance::StatusToString(
+    EmbeddedWorkerStatus status) {
   switch (status) {
-    case STOPPED:
+    case EmbeddedWorkerStatus::STOPPED:
       return "STOPPED";
-    case STARTING:
+    case EmbeddedWorkerStatus::STARTING:
       return "STARTING";
-    case RUNNING:
+    case EmbeddedWorkerStatus::RUNNING:
       return "RUNNING";
-    case STOPPING:
+    case EmbeddedWorkerStatus::STOPPING:
       return "STOPPING";
   }
-  NOTREACHED() << status;
+  NOTREACHED() << static_cast<int>(status);
   return std::string();
 }
 
diff --git a/content/browser/service_worker/embedded_worker_instance.h b/content/browser/service_worker/embedded_worker_instance.h
index 9356bb53..9ec684d5 100644
--- a/content/browser/service_worker/embedded_worker_instance.h
+++ b/content/browser/service_worker/embedded_worker_instance.h
@@ -20,6 +20,7 @@
 #include "base/observer_list.h"
 #include "base/strings/string16.h"
 #include "base/time/time.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_metrics.h"
 #include "content/common/content_export.h"
 #include "content/common/service_worker/service_worker_status_code.h"
@@ -51,12 +52,6 @@
 class CONTENT_EXPORT EmbeddedWorkerInstance {
  public:
   typedef base::Callback<void(ServiceWorkerStatusCode)> StatusCallback;
-  enum Status {
-    STOPPED,
-    STARTING,
-    RUNNING,
-    STOPPING,
-  };
 
   // This enum is used in UMA histograms. Append-only.
   enum StartingPhase {
@@ -88,9 +83,9 @@
 
     virtual void OnStopping() {}
     // Received ACK from renderer that the worker context terminated.
-    virtual void OnStopped(Status old_status) {}
+    virtual void OnStopped(EmbeddedWorkerStatus old_status) {}
     // The browser-side IPC endpoint for communication with the worker died.
-    virtual void OnDetached(Status old_status) {}
+    virtual void OnDetached(EmbeddedWorkerStatus old_status) {}
     virtual void OnScriptLoaded() {}
     virtual void OnScriptLoadFailed() {}
     virtual void OnReportException(const base::string16& error_message,
@@ -140,9 +135,9 @@
   ServiceRegistry* GetServiceRegistry();
 
   int embedded_worker_id() const { return embedded_worker_id_; }
-  Status status() const { return status_; }
+  EmbeddedWorkerStatus status() const { return status_; }
   StartingPhase starting_phase() const {
-    DCHECK_EQ(STARTING, status());
+    DCHECK_EQ(EmbeddedWorkerStatus::STARTING, status());
     return starting_phase_;
   }
   int process_id() const;
@@ -163,6 +158,12 @@
     return network_accessed_for_script_;
   }
 
+  ServiceWorkerMetrics::StartSituation start_situation() const {
+    DCHECK(status() == EmbeddedWorkerStatus::STARTING ||
+           status() == EmbeddedWorkerStatus::RUNNING);
+    return start_situation_;
+  }
+
   // Called when the main script load accessed the network.
   void OnNetworkAccessedForScriptLoad();
 
@@ -185,7 +186,7 @@
   void AddMessageToConsole(ConsoleMessageLevel level,
                            const std::string& message);
 
-  static std::string StatusToString(Status status);
+  static std::string StatusToString(EmbeddedWorkerStatus status);
   static std::string StartingPhaseToString(StartingPhase phase);
 
   void Detach();
@@ -208,7 +209,8 @@
                          int embedded_worker_id);
 
   // Called back from StartTask after a process is allocated on the UI thread.
-  void OnProcessAllocated(std::unique_ptr<WorkerProcessHandle> handle);
+  void OnProcessAllocated(std::unique_ptr<WorkerProcessHandle> handle,
+                          ServiceWorkerMetrics::StartSituation start_situation);
 
   // Called back from StartTask after the worker is registered to
   // WorkerDevToolsManager.
@@ -289,7 +291,7 @@
   base::WeakPtr<ServiceWorkerContextCore> context_;
   scoped_refptr<EmbeddedWorkerRegistry> registry_;
   const int embedded_worker_id_;
-  Status status_;
+  EmbeddedWorkerStatus status_;
   StartingPhase starting_phase_;
 
   // Current running information.
@@ -309,6 +311,10 @@
 
   std::unique_ptr<StartTask> inflight_start_task_;
 
+  // This is valid only after a process is allocated for the worker.
+  ServiceWorkerMetrics::StartSituation start_situation_ =
+      ServiceWorkerMetrics::StartSituation::UNKNOWN;
+
   // Used for UMA. The start time of the current start sequence step.
   base::TimeTicks step_time_;
 
diff --git a/content/browser/service_worker/embedded_worker_instance_unittest.cc b/content/browser/service_worker/embedded_worker_instance_unittest.cc
index 62e1ce6..f2df6b5 100644
--- a/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.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_context_wrapper.h"
@@ -61,12 +62,12 @@
 
   struct EventLog {
     EventType type;
-    EmbeddedWorkerInstance::Status status;
+    EmbeddedWorkerStatus status;
   };
 
   void RecordEvent(
       EventType type,
-      EmbeddedWorkerInstance::Status status = EmbeddedWorkerInstance::STOPPED) {
+      EmbeddedWorkerStatus status = EmbeddedWorkerStatus::STOPPED) {
     EventLog log = {type, status};
     events_.push_back(log);
   }
@@ -76,10 +77,10 @@
     RecordEvent(START_WORKER_MESSAGE_SENT);
   }
   void OnStarted() override { RecordEvent(STARTED); }
-  void OnStopped(EmbeddedWorkerInstance::Status old_status) override {
+  void OnStopped(EmbeddedWorkerStatus old_status) override {
     RecordEvent(STOPPED, old_status);
   }
-  void OnDetached(EmbeddedWorkerInstance::Status old_status) override {
+  void OnDetached(EmbeddedWorkerStatus old_status) override {
     RecordEvent(DETACHED, old_status);
   }
 
@@ -164,7 +165,7 @@
 TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
   std::unique_ptr<EmbeddedWorkerInstance> worker =
       embedded_worker_registry()->CreateWorker();
-  EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
 
   const int64_t service_worker_version_id = 55L;
   const GURL pattern("http://example.com/");
@@ -181,23 +182,23 @@
       CreateStartParams(service_worker_version_id, pattern, url);
   worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
                                               run_loop.QuitClosure()));
-  EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
   run_loop.Run();
   EXPECT_EQ(SERVICE_WORKER_OK, status);
 
   // The 'WorkerStarted' message should have been sent by
   // EmbeddedWorkerTestHelper.
-  EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
   EXPECT_EQ(helper_->mock_render_process_id(), worker->process_id());
 
   // Stop the worker.
   EXPECT_EQ(SERVICE_WORKER_OK, worker->Stop());
-  EXPECT_EQ(EmbeddedWorkerInstance::STOPPING, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, worker->status());
   base::RunLoop().RunUntilIdle();
 
   // The 'WorkerStopped' message should have been sent by
   // EmbeddedWorkerTestHelper.
-  EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
 
   // Verify that we've sent two messages to start and terminate the worker.
   ASSERT_TRUE(
@@ -211,7 +212,7 @@
 TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
   std::unique_ptr<EmbeddedWorkerInstance> worker =
       embedded_worker_registry()->CreateWorker();
-  EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
 
   const int64_t service_worker_version_id = 55L;
   const GURL pattern("http://example.com/");
@@ -238,7 +239,7 @@
                                                 run_loop.QuitClosure()));
     run_loop.Run();
     EXPECT_EQ(SERVICE_WORKER_OK, status);
-    EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
+    EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
     // The worker should be using the default render process.
     EXPECT_EQ(helper_->mock_render_process_id(), worker->process_id());
 
@@ -260,11 +261,11 @@
         CreateStartParams(service_worker_version_id, pattern, url));
     worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
                                                 run_loop.QuitClosure()));
-    EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status());
+    EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
     run_loop.Run();
     EXPECT_EQ(SERVICE_WORKER_OK, status);
 
-    EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
+    EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
     // The worker should be using the new render process.
     EXPECT_EQ(helper_->new_render_process_id(), worker->process_id());
     EXPECT_EQ(SERVICE_WORKER_OK, worker->Stop());
@@ -275,7 +276,7 @@
 TEST_F(EmbeddedWorkerInstanceTest, StopWhenDevToolsAttached) {
   std::unique_ptr<EmbeddedWorkerInstance> worker =
       embedded_worker_registry()->CreateWorker();
-  EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
 
   const int64_t service_worker_version_id = 55L;
   const GURL pattern("http://example.com/");
@@ -288,33 +289,33 @@
   // Start the worker and then call StopIfIdle().
   EXPECT_EQ(SERVICE_WORKER_OK,
             StartWorker(worker.get(), service_worker_version_id, pattern, url));
-  EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
   EXPECT_EQ(helper_->mock_render_process_id(), worker->process_id());
   worker->StopIfIdle();
-  EXPECT_EQ(EmbeddedWorkerInstance::STOPPING, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, worker->status());
   base::RunLoop().RunUntilIdle();
 
   // The worker must be stopped now.
-  EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
 
   // Set devtools_attached to true, and do the same.
   worker->set_devtools_attached(true);
 
   EXPECT_EQ(SERVICE_WORKER_OK,
             StartWorker(worker.get(), service_worker_version_id, pattern, url));
-  EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
   EXPECT_EQ(helper_->mock_render_process_id(), worker->process_id());
   worker->StopIfIdle();
   base::RunLoop().RunUntilIdle();
 
   // The worker must not be stopped this time.
-  EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
 
   // Calling Stop() actually stops the worker regardless of whether devtools
   // is attached or not.
   EXPECT_EQ(SERVICE_WORKER_OK, worker->Stop());
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
 }
 
 // Test that the removal of a worker from the registry doesn't remove
@@ -392,7 +393,7 @@
   worker->Detach();
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
   EXPECT_EQ(ChildProcessHost::kInvalidUniqueID, worker->process_id());
 
   // The start callback should not be aborted by detach (see a comment on the
@@ -402,7 +403,7 @@
   // "PROCESS_ALLOCATED" event should not be recorded.
   ASSERT_EQ(1u, events_.size());
   EXPECT_EQ(DETACHED, events_[0].type);
-  EXPECT_EQ(EmbeddedWorkerInstance::STARTING, events_[0].status);
+  EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
 }
 
 TEST_F(EmbeddedWorkerInstanceTest, DetachAfterSendingStartWorkerMessage) {
@@ -431,7 +432,7 @@
   worker->Detach();
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
   EXPECT_EQ(ChildProcessHost::kInvalidUniqueID, worker->process_id());
 
   // The start callback should not be aborted by detach (see a comment on the
@@ -441,7 +442,7 @@
   // "STARTED" event should not be recorded.
   ASSERT_EQ(1u, events_.size());
   EXPECT_EQ(DETACHED, events_[0].type);
-  EXPECT_EQ(EmbeddedWorkerInstance::STARTING, events_[0].status);
+  EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
 }
 
 TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
@@ -463,7 +464,7 @@
   worker->Stop();
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
   EXPECT_EQ(ChildProcessHost::kInvalidUniqueID, worker->process_id());
 
   // The start callback should not be aborted by stop (see a comment on the dtor
@@ -473,7 +474,7 @@
   // "PROCESS_ALLOCATED" event should not be recorded.
   ASSERT_EQ(1u, events_.size());
   EXPECT_EQ(DETACHED, events_[0].type);
-  EXPECT_EQ(EmbeddedWorkerInstance::STARTING, events_[0].status);
+  EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
   events_.clear();
 
   // Restart the worker.
@@ -520,7 +521,7 @@
   base::RunLoop().RunUntilIdle();
 
   // The resume after download message should not have been sent.
-  EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
   EXPECT_FALSE(ipc_sink()->GetFirstMessageMatching(
       EmbeddedWorkerMsg_ResumeAfterDownload::ID));
 }
@@ -551,7 +552,7 @@
   worker->Stop();
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
   EXPECT_EQ(ChildProcessHost::kInvalidUniqueID, worker->process_id());
 
   // The start callback should not be aborted by stop (see a comment on the dtor
@@ -561,7 +562,7 @@
   // "STARTED" event should not be recorded.
   ASSERT_EQ(1u, events_.size());
   EXPECT_EQ(STOPPED, events_[0].type);
-  EXPECT_EQ(EmbeddedWorkerInstance::STOPPING, events_[0].status);
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, events_[0].status);
   events_.clear();
 
   // Restart the worker.
@@ -608,13 +609,13 @@
   // Detach.
   int process_id = worker->process_id();
   worker->Detach();
-  EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
 
   // Send the registry a message from the detached worker. Nothing should
   // happen.
   embedded_worker_registry()->OnWorkerStarted(process_id,
                                               worker->embedded_worker_id());
-  EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
 }
 
 // Test for when sending the start IPC failed.
@@ -645,7 +646,7 @@
   ASSERT_EQ(2u, events_.size());
   EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
   EXPECT_EQ(STOPPED, events_[1].type);
-  EXPECT_EQ(EmbeddedWorkerInstance::STARTING, events_[1].status);
+  EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[1].status);
 }
 
 }  // namespace content
diff --git a/content/browser/service_worker/embedded_worker_status.h b/content/browser/service_worker/embedded_worker_status.h
new file mode 100644
index 0000000..f6bc13a
--- /dev/null
+++ b/content/browser/service_worker/embedded_worker_status.h
@@ -0,0 +1,19 @@
+// Copyright 2016 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.
+
+#ifndef CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_STATUS_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_STATUS_H_
+
+namespace content {
+
+enum class EmbeddedWorkerStatus {
+  STOPPED,
+  STARTING,
+  RUNNING,
+  STOPPING,
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_STATUS_H_
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc
index a6a7cba1..0febd11 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -15,6 +15,7 @@
 #include "content/browser/message_port_message_filter.h"
 #include "content/browser/service_worker/embedded_worker_instance.h"
 #include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/common/service_worker/embedded_worker_messages.h"
@@ -328,7 +329,7 @@
   EmbeddedWorkerInstance* worker =
       registry()->GetWorker(params.embedded_worker_id);
   ASSERT_TRUE(worker != NULL);
-  EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
       base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker,
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index 60c6b2b..ee5ecb3 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -29,6 +29,7 @@
 #include "content/browser/cache_storage/cache_storage_manager.h"
 #include "content/browser/service_worker/embedded_worker_instance.h"
 #include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_observer.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -979,7 +980,7 @@
 
   // The script has loaded but start has not completed yet.
   ASSERT_EQ(SERVICE_WORKER_ERROR_FAILED, status);
-  EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
 
   // Simulate execution timeout. Use a delay to prevent killing the worker
   // before it's started execution.
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc
index 704f821..6bb3ee1 100644
--- a/content/browser/service_worker/service_worker_context_core.cc
+++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -20,6 +20,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_context_observer.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_database_task_manager.h"
@@ -115,8 +116,8 @@
         context->GetLiveVersions();
     for (const auto& version_itr : live_versions_copy) {
       ServiceWorkerVersion* version(version_itr.second);
-      if (version->running_status() == ServiceWorkerVersion::STARTING ||
-          version->running_status() == ServiceWorkerVersion::RUNNING) {
+      if (version->running_status() == EmbeddedWorkerStatus::STARTING ||
+          version->running_status() == EmbeddedWorkerStatus::RUNNING) {
         version->StopWorker(
             base::Bind(&ClearAllServiceWorkersHelper::OnResult, this));
       }
diff --git a/content/browser/service_worker/service_worker_context_observer.h b/content/browser/service_worker/service_worker_context_observer.h
index b643153f9..ebb41cc5 100644
--- a/content/browser/service_worker/service_worker_context_observer.h
+++ b/content/browser/service_worker/service_worker_context_observer.h
@@ -14,6 +14,8 @@
 
 namespace content {
 
+enum class EmbeddedWorkerStatus;
+
 class ServiceWorkerContextObserver {
  public:
   struct ErrorInfo {
@@ -52,9 +54,8 @@
   virtual void OnNewLiveVersion(int64_t version_id,
                                 int64_t registration_id,
                                 const GURL& script_url) {}
-  virtual void OnRunningStateChanged(
-      int64_t version_id,
-      ServiceWorkerVersion::RunningStatus running_status) {}
+  virtual void OnRunningStateChanged(int64_t version_id,
+                                     EmbeddedWorkerStatus running_status) {}
   virtual void OnVersionStateChanged(int64_t version_id,
                                      ServiceWorkerVersion::Status status) {}
   virtual void OnMainScriptHttpResponseInfoSet(
diff --git a/content/browser/service_worker/service_worker_context_watcher.cc b/content/browser/service_worker/service_worker_context_watcher.cc
index d599d3d..4309b0a 100644
--- a/content/browser/service_worker/service_worker_context_watcher.cc
+++ b/content/browser/service_worker/service_worker_context_watcher.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/containers/scoped_ptr_hash_map.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_context_observer.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_version.h"
@@ -20,8 +21,7 @@
 namespace {
 
 bool IsStoppedAndRedundant(const ServiceWorkerVersionInfo& version_info) {
-  return version_info.running_status ==
-             content::ServiceWorkerVersion::STOPPED &&
+  return version_info.running_status == EmbeddedWorkerStatus::STOPPED &&
          version_info.status == content::ServiceWorkerVersion::REDUNDANT;
 }
 
@@ -186,7 +186,7 @@
 
 void ServiceWorkerContextWatcher::OnRunningStateChanged(
     int64_t version_id,
-    content::ServiceWorkerVersion::RunningStatus running_status) {
+    content::EmbeddedWorkerStatus running_status) {
   ServiceWorkerVersionInfo* version = version_info_map_.get(version_id);
   DCHECK(version);
   if (version->running_status == running_status)
diff --git a/content/browser/service_worker/service_worker_context_watcher.h b/content/browser/service_worker/service_worker_context_watcher.h
index aae387d..d7341a5 100644
--- a/content/browser/service_worker/service_worker_context_watcher.h
+++ b/content/browser/service_worker/service_worker_context_watcher.h
@@ -17,6 +17,7 @@
 namespace content {
 
 class ServiceWorkerContextWrapper;
+enum class EmbeddedWorkerStatus;
 
 // Used to monitor the status change of the ServiceWorker registrations and
 // versions in the ServiceWorkerContext from UI thread.
@@ -72,7 +73,7 @@
                         const GURL& script_url) override;
   void OnRunningStateChanged(
       int64_t version_id,
-      content::ServiceWorkerVersion::RunningStatus running_status) override;
+      content::EmbeddedWorkerStatus running_status) override;
   void OnVersionStateChanged(
       int64_t version_id,
       content::ServiceWorkerVersion::Status status) override;
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc
index 12a1dfc..e352979e9 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -17,6 +17,7 @@
 #include "content/browser/message_port_message_filter.h"
 #include "content/browser/message_port_service.h"
 #include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_client_utils.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -831,7 +832,7 @@
   // We might not be STARTING if the stop sequence was entered (STOPPING) or
   // ended up being detached (STOPPED).
   ServiceWorkerVersion* version = GetContext()->GetLiveVersion(version_id);
-  if (!version || version->running_status() != ServiceWorkerVersion::STARTING)
+  if (!version || version->running_status() != EmbeddedWorkerStatus::STARTING)
     return;
 
   if (!provider_host->SetHostedVersion(version)) {
diff --git a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
index 376ffa2..93613af 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
@@ -16,6 +16,7 @@
 #include "content/browser/message_port_service.h"
 #include "content/browser/service_worker/embedded_worker_instance.h"
 #include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.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_context_wrapper.h"
@@ -632,14 +633,14 @@
   EXPECT_EQ(SERVICE_WORKER_OK, status);
 
   EXPECT_TRUE(context()->GetProviderHost(process_id, provider_id));
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   // Simulate the render process crashing.
   dispatcher_host_->OnFilterRemoved();
 
   // The dispatcher host should clean up the state from the process.
   EXPECT_FALSE(context()->GetProviderHost(process_id, provider_id));
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
 
   // We should be able to hook up a new dispatcher host although the old object
   // is not yet destroyed. This is what the browser does when reusing a crashed
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
index dad6fba..2b9ecc9 100644
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/trace_event/trace_event.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_version.h"
 #include "content/common/service_worker/service_worker_messages.h"
 
@@ -87,7 +88,7 @@
 }
 
 void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
-  DCHECK_EQ(ServiceWorkerVersion::RUNNING, version_->running_status())
+  DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status())
       << "Worker stopped too soon after it was started.";
 
   DCHECK(!prepare_callback_.is_null());
diff --git a/content/browser/service_worker/service_worker_info.cc b/content/browser/service_worker/service_worker_info.cc
index 0f4a4c5d..47e0d13 100644
--- a/content/browser/service_worker/service_worker_info.cc
+++ b/content/browser/service_worker/service_worker_info.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/service_worker/service_worker_info.h"
 
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/common/service_worker/service_worker_types.h"
 #include "content/public/common/child_process_host.h"
 #include "ipc/ipc_message.h"
@@ -25,7 +26,7 @@
 }
 
 ServiceWorkerVersionInfo::ServiceWorkerVersionInfo()
-    : running_status(ServiceWorkerVersion::STOPPED),
+    : running_status(EmbeddedWorkerStatus::STOPPED),
       status(ServiceWorkerVersion::NEW),
       registration_id(kInvalidServiceWorkerRegistrationId),
       version_id(kInvalidServiceWorkerVersionId),
@@ -34,7 +35,7 @@
       devtools_agent_route_id(MSG_ROUTING_NONE) {}
 
 ServiceWorkerVersionInfo::ServiceWorkerVersionInfo(
-    ServiceWorkerVersion::RunningStatus running_status,
+    EmbeddedWorkerStatus running_status,
     ServiceWorkerVersion::Status status,
     const GURL& script_url,
     int64_t registration_id,
diff --git a/content/browser/service_worker/service_worker_info.h b/content/browser/service_worker/service_worker_info.h
index 8de17fea..e270878 100644
--- a/content/browser/service_worker/service_worker_info.h
+++ b/content/browser/service_worker/service_worker_info.h
@@ -16,6 +16,8 @@
 
 namespace content {
 
+enum class EmbeddedWorkerStatus;
+
 struct CONTENT_EXPORT ServiceWorkerVersionInfo {
  public:
   struct CONTENT_EXPORT ClientInfo {
@@ -29,7 +31,7 @@
   };
 
   ServiceWorkerVersionInfo();
-  ServiceWorkerVersionInfo(ServiceWorkerVersion::RunningStatus running_status,
+  ServiceWorkerVersionInfo(EmbeddedWorkerStatus running_status,
                            ServiceWorkerVersion::Status status,
                            const GURL& script_url,
                            int64_t registration_id,
@@ -40,7 +42,7 @@
   ServiceWorkerVersionInfo(const ServiceWorkerVersionInfo& other);
   ~ServiceWorkerVersionInfo();
 
-  ServiceWorkerVersion::RunningStatus running_status;
+  EmbeddedWorkerStatus running_status;
   ServiceWorkerVersion::Status status;
   GURL script_url;
   int64_t registration_id;
diff --git a/content/browser/service_worker/service_worker_internals_ui.cc b/content/browser/service_worker/service_worker_internals_ui.cc
index cabb956..c68602c 100644
--- a/content/browser/service_worker/service_worker_internals_ui.cc
+++ b/content/browser/service_worker/service_worker_internals_ui.cc
@@ -15,6 +15,7 @@
 #include "base/values.h"
 #include "content/browser/devtools/devtools_agent_host_impl.h"
 #include "content/browser/devtools/service_worker_devtools_manager.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_context_observer.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_registration.h"
@@ -113,16 +114,16 @@
 void UpdateVersionInfo(const ServiceWorkerVersionInfo& version,
                        DictionaryValue* info) {
   switch (version.running_status) {
-    case ServiceWorkerVersion::STOPPED:
+    case EmbeddedWorkerStatus::STOPPED:
       info->SetString("running_status", "STOPPED");
       break;
-    case ServiceWorkerVersion::STARTING:
+    case EmbeddedWorkerStatus::STARTING:
       info->SetString("running_status", "STARTING");
       break;
-    case ServiceWorkerVersion::RUNNING:
+    case EmbeddedWorkerStatus::RUNNING:
       info->SetString("running_status", "RUNNING");
       break;
-    case ServiceWorkerVersion::STOPPING:
+    case EmbeddedWorkerStatus::STOPPING:
       info->SetString("running_status", "STOPPING");
       break;
   }
@@ -253,7 +254,7 @@
   ~PartitionObserver() override {}
   // ServiceWorkerContextObserver overrides:
   void OnRunningStateChanged(int64_t version_id,
-                             ServiceWorkerVersion::RunningStatus) override {
+                             EmbeddedWorkerStatus) override {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     web_ui_->CallJavascriptFunctionUnsafe(
         "serviceworker.onRunningStateChanged", FundamentalValue(partition_id_),
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc
index 985da5f..233949e 100644
--- a/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/test/test_simple_task_runner.h"
 #include "content/browser/browser_thread_impl.h"
 #include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.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_context_wrapper.h"
@@ -657,15 +658,14 @@
 
   version->SetStatus(ServiceWorkerVersion::INSTALLED);
   registration->SetWaitingVersion(version);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING,
-            version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version->status());
 
   RunUnregisterJob(GURL("http://www.example.com/"));
 
   // The version should be stopped since there is no controllee after
   // unregistration.
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
 }
 
@@ -678,14 +678,14 @@
   ASSERT_TRUE(registration.get());
 
   scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
 
   RunUnregisterJob(GURL("http://www.example.com/"));
 
   // The version should be stopped since there is no controllee after
   // unregistration.
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
 }
 
@@ -702,20 +702,20 @@
   registration->active_version()->AddControllee(host.get());
 
   scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
 
   RunUnregisterJob(GURL("http://www.example.com/"));
 
   // The version should be running since there is still a controllee.
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
 
   registration->active_version()->RemoveControllee(host.get());
   base::RunLoop().RunUntilIdle();
 
   // The version should be stopped since there is no controllee.
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
 }
 
@@ -1252,7 +1252,7 @@
   // Verify the new version is installed but not activated yet.
   EXPECT_EQ(NULL, registration->installing_version());
   EXPECT_TRUE(new_version);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, new_version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::INSTALLED, new_version->status());
 
   old_version->RemoveControllee(host.get());
@@ -1269,7 +1269,7 @@
 
   runner->RunUntilIdle();
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, new_version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status());
 }
 
@@ -1304,9 +1304,9 @@
   EXPECT_TRUE(registration->is_uninstalling());
   EXPECT_EQ(old_version, registration->active_version());
 
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, old_version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, old_version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, old_version->status());
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, new_version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::INSTALLED, new_version->status());
 
   old_version->RemoveControllee(host.get());
@@ -1315,9 +1315,9 @@
   EXPECT_FALSE(registration->is_uninstalling());
   EXPECT_TRUE(registration->is_uninstalled());
 
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, old_version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, old_version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status());
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, new_version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, new_version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, new_version->status());
 }
 
@@ -1368,7 +1368,7 @@
 
   runner->RunUntilIdle();
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, new_version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status());
 }
 
@@ -1424,7 +1424,7 @@
 
   runner->RunUntilIdle();
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, third_version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, third_version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, third_version->status());
 }
 
@@ -1503,7 +1503,7 @@
   EXPECT_EQ(NULL, registration->installing_version());
   EXPECT_EQ(NULL, registration->waiting_version());
   EXPECT_EQ(new_version, registration->active_version());
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, new_version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status());
 
   EXPECT_EQ(registration, FindRegistrationForPattern(pattern));
@@ -1539,7 +1539,7 @@
   EXPECT_FALSE(registration->is_uninstalling());
   EXPECT_TRUE(registration->is_uninstalled());
 
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, old_version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, old_version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status());
 
   FindRegistrationForPattern(pattern, SERVICE_WORKER_ERROR_NOT_FOUND);
@@ -1575,7 +1575,7 @@
   EXPECT_FALSE(registration->is_uninstalling());
   EXPECT_FALSE(registration->is_uninstalled());
 
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, old_version->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, old_version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status());
 
   FindRegistrationForPattern(pattern, SERVICE_WORKER_OK);
diff --git a/content/browser/service_worker/service_worker_metrics.cc b/content/browser/service_worker/service_worker_metrics.cc
index 5095b53..eaf8071f 100644
--- a/content/browser/service_worker/service_worker_metrics.cc
+++ b/content/browser/service_worker/service_worker_metrics.cc
@@ -10,6 +10,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/sparse_histogram.h"
 #include "base/strings/string_util.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/common/service_worker/service_worker_types.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
@@ -72,6 +73,33 @@
   return "_UNKNOWN";
 }
 
+std::string GetWorkerPreparationSuffix(
+    EmbeddedWorkerStatus initial_worker_status,
+    ServiceWorkerMetrics::StartSituation start_situation) {
+  switch (initial_worker_status) {
+    case EmbeddedWorkerStatus::STOPPED: {
+      switch (start_situation) {
+        case ServiceWorkerMetrics::StartSituation::DURING_STARTUP:
+          return "_StartWorkerDuringStartup";
+        case ServiceWorkerMetrics::StartSituation::NEW_PROCESS:
+          return "_StartWorkerNewProcess";
+        case ServiceWorkerMetrics::StartSituation::EXISTING_PROCESS:
+          return "_StartWorkerExistingProcess";
+        default:
+          NOTREACHED() << static_cast<int>(start_situation);
+      }
+    }
+    case EmbeddedWorkerStatus::STARTING:
+      return "_StartingWorker";
+    case EmbeddedWorkerStatus::RUNNING:
+      return "_RunningWorker";
+    case EmbeddedWorkerStatus::STOPPING:
+      return "_StoppingWorker";
+  }
+  NOTREACHED();
+  return "_UNKNOWN";
+}
+
 // Use this for histograms with dynamically generated names, which
 // otherwise can't use the UMA_HISTOGRAM macro without code duplication.
 void RecordSuffixedTimeHistogram(const std::string& name,
@@ -288,6 +316,18 @@
   }
 }
 
+void ServiceWorkerMetrics::RecordActivatedWorkerPreparationTimeForMainFrame(
+    base::TimeDelta time,
+    EmbeddedWorkerStatus initial_worker_status,
+    StartSituation start_situation) {
+  std::string name =
+      "ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time";
+  UMA_HISTOGRAM_MEDIUM_TIMES(name, time);
+  RecordSuffixedTimeHistogram(
+      name, GetWorkerPreparationSuffix(initial_worker_status, start_situation),
+      time);
+}
+
 void ServiceWorkerMetrics::RecordWorkerStopped(StopStatus status) {
   UMA_HISTOGRAM_ENUMERATION("ServiceWorker.WorkerStopped",
                             static_cast<int>(status),
diff --git a/content/browser/service_worker/service_worker_metrics.h b/content/browser/service_worker/service_worker_metrics.h
index aca36c9..9be6cdb 100644
--- a/content/browser/service_worker/service_worker_metrics.h
+++ b/content/browser/service_worker/service_worker_metrics.h
@@ -16,6 +16,8 @@
 
 namespace content {
 
+enum class EmbeddedWorkerStatus;
+
 class ServiceWorkerMetrics {
  public:
   // Used for UMA. Append-only.
@@ -161,6 +163,13 @@
                                     StartSituation start_situation,
                                     EventType purpose);
 
+  // Records the time taken to prepare an activated Service Worker for a main
+  // frame fetch.
+  static void RecordActivatedWorkerPreparationTimeForMainFrame(
+      base::TimeDelta time,
+      EmbeddedWorkerStatus initial_worker_status,
+      StartSituation start_situation);
+
   // Records the result of trying to stop a worker.
   static void RecordWorkerStopped(StopStatus status);
 
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc
index 21e0ddf..a06b796 100644
--- a/content/browser/service_worker/service_worker_provider_host.cc
+++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -10,6 +10,7 @@
 #include "base/stl_util.h"
 #include "base/time/time.h"
 #include "content/browser/message_port_message_filter.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_request_handler.h"
 #include "content/browser/service_worker/service_worker_controllee_request_handler.h"
@@ -192,7 +193,7 @@
   if (active_version())
     return false;  // Unexpected bad message.
 
-  DCHECK_EQ(ServiceWorkerVersion::STARTING, version->running_status());
+  DCHECK_EQ(EmbeddedWorkerStatus::STARTING, version->running_status());
   if (version->embedded_worker()->process_id() != render_process_id_) {
     // If we aren't trying to start this version in our process
     // something is amiss.
diff --git a/content/browser/service_worker/service_worker_register_job.cc b/content/browser/service_worker/service_worker_register_job.cc
index d0d8b74..1eda60b 100644
--- a/content/browser/service_worker/service_worker_register_job.cc
+++ b/content/browser/service_worker/service_worker_register_job.cc
@@ -9,6 +9,7 @@
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_job_coordinator.h"
 #include "content/browser/service_worker/service_worker_metrics.h"
@@ -423,7 +424,7 @@
 void ServiceWorkerRegisterJob::DispatchInstallEvent() {
   DCHECK_EQ(ServiceWorkerVersion::INSTALLING, new_version()->status())
       << new_version()->status();
-  DCHECK_EQ(ServiceWorkerVersion::RUNNING, new_version()->running_status())
+  DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, new_version()->running_status())
       << "Worker stopped too soon after it was started.";
   int request_id = new_version()->StartRequest(
       ServiceWorkerMetrics::EventType::INSTALL,
diff --git a/content/browser/service_worker/service_worker_registration.cc b/content/browser/service_worker/service_worker_registration.cc
index f822b4c..d7fb0b1 100644
--- a/content/browser/service_worker/service_worker_registration.cc
+++ b/content/browser/service_worker/service_worker_registration.cc
@@ -6,6 +6,7 @@
 
 #include <vector>
 
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_info.h"
@@ -380,7 +381,7 @@
   }
 
   DCHECK_EQ(ServiceWorkerVersion::ACTIVATING, activating_version->status());
-  DCHECK_EQ(ServiceWorkerVersion::RUNNING, activating_version->running_status())
+  DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, activating_version->running_status())
       << "Worker stopped too soon after it was started.";
   int request_id = activating_version->StartRequest(
       ServiceWorkerMetrics::EventType::ACTIVATE,
diff --git a/content/browser/service_worker/service_worker_url_request_job.cc b/content/browser/service_worker/service_worker_url_request_job.cc
index e06e593..f21084d 100644
--- a/content/browser/service_worker/service_worker_url_request_job.cc
+++ b/content/browser/service_worker/service_worker_url_request_job.cc
@@ -22,6 +22,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "content/browser/resource_context_impl.h"
+#include "content/browser/service_worker/embedded_worker_instance.h"
 #include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
 #include "content/browser/service_worker/service_worker_provider_host.h"
 #include "content/browser/service_worker/service_worker_response_info.h"
@@ -632,9 +633,42 @@
   *blob_size = total_size;
 }
 
-void ServiceWorkerURLRequestJob::DidPrepareFetchEvent() {
+void ServiceWorkerURLRequestJob::DidPrepareFetchEvent(
+    scoped_refptr<ServiceWorkerVersion> version) {
   worker_ready_time_ = base::TimeTicks::Now();
   load_timing_info_.send_start = worker_ready_time_;
+
+  // Record the time taken for the browser to find and possibly start an active
+  // worker to which to dispatch a FetchEvent for a main frame resource request.
+  // For context, a FetchEvent can only be dispatched to an ACTIVATED worker
+  // that is running (it has been successfully started). The measurements starts
+  // when the browser process receives the request. The browser then finds the
+  // worker appropriate for this request (if there is none, this metric is not
+  // recorded). If that worker is already started, the browser process can send
+  // the request to it, so the measurement ends quickly. Otherwise the browser
+  // process has to start the worker and the measurement ends when the worker is
+  // successfully started.
+  // The metric is not recorded in the following situations:
+  // 1) The worker was in state INSTALLED or ACTIVATING, and the browser had to
+  //    wait for it to become ACTIVATED. This is to avoid including the time to
+  //    execute the activate event handlers in the worker's script.
+  // 2) The worker was started for the fetch AND DevTools was attached during
+  //    startup. This is intended to avoid including the time for debugging.
+  // 3) The request is for New Tab Page. This is because it tends to dominate
+  //    the stats and makes the results largely skewed.
+  if (resource_type_ != RESOURCE_TYPE_MAIN_FRAME)
+    return;
+  if (!worker_already_activated_)
+    return;
+  if (version->skip_recording_startup_time() &&
+      initial_worker_status_ != EmbeddedWorkerStatus::RUNNING) {
+    return;
+  }
+  if (ServiceWorkerMetrics::ShouldExcludeURLFromHistogram(request()->url()))
+    return;
+  ServiceWorkerMetrics::RecordActivatedWorkerPreparationTimeForMainFrame(
+      worker_ready_time_ - request()->creation_time(), initial_worker_status_,
+      version->embedded_worker()->start_situation());
 }
 
 void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
@@ -962,11 +996,15 @@
     return;
   }
 
+  worker_already_activated_ =
+      active_worker->status() == ServiceWorkerVersion::ACTIVATED;
+  initial_worker_status_ = active_worker->running_status();
+
   DCHECK(!fetch_dispatcher_);
   fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher(
       CreateFetchRequest(), active_worker, resource_type_,
       base::Bind(&ServiceWorkerURLRequestJob::DidPrepareFetchEvent,
-                 weak_factory_.GetWeakPtr()),
+                 weak_factory_.GetWeakPtr(), active_worker),
       base::Bind(&ServiceWorkerURLRequestJob::DidDispatchFetchEvent,
                  weak_factory_.GetWeakPtr())));
   worker_start_time_ = base::TimeTicks::Now();
diff --git a/content/browser/service_worker/service_worker_url_request_job.h b/content/browser/service_worker/service_worker_url_request_job.h
index 58ab863..1535561 100644
--- a/content/browser/service_worker/service_worker_url_request_job.h
+++ b/content/browser/service_worker/service_worker_url_request_job.h
@@ -14,6 +14,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_metrics.h"
 #include "content/browser/streams/stream_read_observer.h"
 #include "content/browser/streams/stream_register_observer.h"
@@ -179,7 +180,7 @@
   void CreateRequestBodyBlob(std::string* blob_uuid, uint64_t* blob_size);
 
   // For FORWARD_TO_SERVICE_WORKER case.
-  void DidPrepareFetchEvent();
+  void DidPrepareFetchEvent(scoped_refptr<ServiceWorkerVersion> version);
   void DidDispatchFetchEvent(
       ServiceWorkerStatusCode status,
       ServiceWorkerFetchEventResult fetch_result,
@@ -280,6 +281,9 @@
 
   std::unique_ptr<BlobConstructionWaiter> blob_construction_waiter_;
 
+  bool worker_already_activated_ = false;
+  EmbeddedWorkerStatus initial_worker_status_ = EmbeddedWorkerStatus::STOPPED;
+
   base::WeakPtrFactory<ServiceWorkerURLRequestJob> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerURLRequestJob);
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 470bc86..621f6cf 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -28,6 +28,7 @@
 #include "content/browser/message_port_service.h"
 #include "content/browser/service_worker/embedded_worker_instance.h"
 #include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_client_utils.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -103,7 +104,7 @@
       error_callback.Run(status);
     return;
   }
-  if (version->running_status() != ServiceWorkerVersion::RUNNING) {
+  if (version->running_status() != EmbeddedWorkerStatus::RUNNING) {
     // We've tried to start the worker (and it has succeeded), but
     // it looks it's not running yet.
     NOTREACHED() << "The worker's not running after successful StartWorker";
@@ -326,8 +327,10 @@
   if (context_)
     context_->RemoveLiveVersion(version_id_);
 
-  if (running_status() == STARTING || running_status() == RUNNING)
+  if (running_status() == EmbeddedWorkerStatus::STARTING ||
+      running_status() == EmbeddedWorkerStatus::RUNNING) {
     embedded_worker_->Stop();
+  }
   embedded_worker_->RemoveListener(this);
 }
 
@@ -446,7 +449,7 @@
                        TRACE_EVENT_SCOPE_THREAD, "Script", script_url_.spec(),
                        "Status", VersionStatusToString(status_));
 
-  if (running_status() == STOPPED) {
+  if (running_status() == EmbeddedWorkerStatus::STOPPED) {
     RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
     return;
   }
@@ -509,7 +512,7 @@
     const base::TimeDelta& timeout,
     TimeoutBehavior timeout_behavior) {
   OnBeginEvent();
-  DCHECK_EQ(RUNNING, running_status())
+  DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, running_status())
       << "Can only start a request with a running worker.";
   DCHECK(event_type == ServiceWorkerMetrics::EventType::INSTALL ||
          event_type == ServiceWorkerMetrics::EventType::ACTIVATE ||
@@ -556,7 +559,7 @@
     ServiceWorkerMetrics::EventType purpose,
     const base::Closure& task,
     const StatusCallback& error_callback) {
-  if (running_status() == RUNNING) {
+  if (running_status() == EmbeddedWorkerStatus::RUNNING) {
     DCHECK(start_callbacks_.empty());
     task.Run();
     return;
@@ -630,7 +633,8 @@
 void ServiceWorkerVersion::Doom() {
   DCHECK(!HasControllee());
   SetStatus(REDUNDANT);
-  if (running_status() == STARTING || running_status() == RUNNING) {
+  if (running_status() == EmbeddedWorkerStatus::STARTING ||
+      running_status() == EmbeddedWorkerStatus::RUNNING) {
     if (embedded_worker()->devtools_attached())
       stop_when_devtools_detached_ = true;
     else
@@ -647,8 +651,10 @@
   embedded_worker()->set_devtools_attached(attached);
   if (stop_when_devtools_detached_ && !attached) {
     DCHECK_EQ(REDUNDANT, status());
-    if (running_status() == STARTING || running_status() == RUNNING)
+    if (running_status() == EmbeddedWorkerStatus::STARTING ||
+        running_status() == EmbeddedWorkerStatus::RUNNING) {
       embedded_worker_->Stop();
+    }
     return;
   }
   if (attached) {
@@ -667,8 +673,9 @@
   if (!start_callbacks_.empty()) {
     // Reactivate the timer for start timeout.
     DCHECK(timeout_timer_.IsRunning());
-    DCHECK(running_status() == STARTING || running_status() == STOPPING)
-        << running_status();
+    DCHECK(running_status() == EmbeddedWorkerStatus::STARTING ||
+           running_status() == EmbeddedWorkerStatus::STOPPING)
+        << static_cast<int>(running_status());
     RestartTick(&start_time_);
   }
 
@@ -740,7 +747,7 @@
 }
 
 void ServiceWorkerVersion::OnThreadStarted() {
-  DCHECK_EQ(STARTING, running_status());
+  DCHECK_EQ(EmbeddedWorkerStatus::STARTING, running_status());
   // Activate ping/pong now that JavaScript execution will start.
   ping_controller_->Activate();
 }
@@ -750,7 +757,7 @@
 }
 
 void ServiceWorkerVersion::OnStarted() {
-  DCHECK_EQ(RUNNING, running_status());
+  DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, running_status());
   RestartTick(&idle_time_);
 
   // Fire all start callbacks.
@@ -775,8 +782,7 @@
   FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this));
 }
 
-void ServiceWorkerVersion::OnStopped(
-    EmbeddedWorkerInstance::Status old_status) {
+void ServiceWorkerVersion::OnStopped(EmbeddedWorkerStatus old_status) {
   if (IsInstalled(status())) {
     ServiceWorkerMetrics::RecordWorkerStopped(
         ServiceWorkerMetrics::StopStatus::NORMAL);
@@ -787,8 +793,7 @@
   OnStoppedInternal(old_status);
 }
 
-void ServiceWorkerVersion::OnDetached(
-    EmbeddedWorkerInstance::Status old_status) {
+void ServiceWorkerVersion::OnDetached(EmbeddedWorkerStatus old_status) {
   if (IsInstalled(status())) {
     ServiceWorkerMetrics::RecordWorkerStopped(
         ServiceWorkerMetrics::StopStatus::DETACH_BY_REGISTRY);
@@ -899,8 +904,10 @@
 
   // When Clients.get() is called on the script evaluation phase, the running
   // status can be STARTING here.
-  if (running_status() != STARTING && running_status() != RUNNING)
+  if (running_status() != EmbeddedWorkerStatus::STARTING &&
+      running_status() != EmbeddedWorkerStatus::RUNNING) {
     return;
+  }
 
   embedded_worker_->SendMessage(
       ServiceWorkerMsg_DidGetClient(request_id, client_info));
@@ -927,8 +934,10 @@
 
   // When Clients.matchAll() is called on the script evaluation phase, the
   // running status can be STARTING here.
-  if (running_status() != STARTING && running_status() != RUNNING)
+  if (running_status() != EmbeddedWorkerStatus::STARTING &&
+      running_status() != EmbeddedWorkerStatus::RUNNING) {
     return;
+  }
 
   embedded_worker_->SendMessage(
       ServiceWorkerMsg_DidGetClients(request_id, *clients));
@@ -993,7 +1002,7 @@
     const ServiceWorkerClientInfo& client_info) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (running_status() != RUNNING)
+  if (running_status() != EmbeddedWorkerStatus::RUNNING)
     return;
 
   if (status != SERVICE_WORKER_OK) {
@@ -1101,7 +1110,7 @@
     const ServiceWorkerClientInfo& client_info) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (running_status() != RUNNING)
+  if (running_status() != EmbeddedWorkerStatus::RUNNING)
     return;
 
   embedded_worker_->SendMessage(
@@ -1157,7 +1166,7 @@
     const ServiceWorkerClientInfo& client_info) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (running_status() != RUNNING)
+  if (running_status() != EmbeddedWorkerStatus::RUNNING)
     return;
 
   if (status != SERVICE_WORKER_OK) {
@@ -1187,8 +1196,10 @@
 }
 
 void ServiceWorkerVersion::DidSkipWaiting(int request_id) {
-  if (running_status() == STARTING || running_status() == RUNNING)
+  if (running_status() == EmbeddedWorkerStatus::STARTING ||
+      running_status() == EmbeddedWorkerStatus::RUNNING) {
     embedded_worker_->SendMessage(ServiceWorkerMsg_DidSkipWaiting(request_id));
+  }
 }
 
 void ServiceWorkerVersion::OnClaimClients(int request_id) {
@@ -1287,14 +1298,14 @@
   MarkIfStale();
 
   switch (running_status()) {
-    case RUNNING:
+    case EmbeddedWorkerStatus::RUNNING:
       RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
       return;
-    case STARTING:
+    case EmbeddedWorkerStatus::STARTING:
       DCHECK(!start_callbacks_.empty());
       break;
-    case STOPPING:
-    case STOPPED:
+    case EmbeddedWorkerStatus::STOPPING:
+    case EmbeddedWorkerStatus::STOPPED:
       if (start_callbacks_.empty()) {
         int trace_id = NextTraceId();
         TRACE_EVENT_ASYNC_BEGIN2(
@@ -1313,13 +1324,13 @@
   start_callbacks_.push_back(
       base::Bind(&RunStartWorkerCallback, callback, protect));
 
-  if (running_status() == STOPPED)
+  if (running_status() == EmbeddedWorkerStatus::STOPPED)
     StartWorkerInternal();
   DCHECK(timeout_timer_.IsRunning());
 }
 
 void ServiceWorkerVersion::StartWorkerInternal() {
-  DCHECK_EQ(STOPPED, running_status());
+  DCHECK_EQ(EmbeddedWorkerStatus::STOPPED, running_status());
 
   DCHECK(!metrics_);
   metrics_.reset(new Metrics(this));
@@ -1385,9 +1396,10 @@
 }
 
 void ServiceWorkerVersion::OnTimeoutTimer() {
-  DCHECK(running_status() == STARTING || running_status() == RUNNING ||
-         running_status() == STOPPING)
-      << running_status();
+  DCHECK(running_status() == EmbeddedWorkerStatus::STARTING ||
+         running_status() == EmbeddedWorkerStatus::RUNNING ||
+         running_status() == EmbeddedWorkerStatus::STOPPING)
+      << static_cast<int>(running_status());
 
   if (!context_)
     return;
@@ -1397,7 +1409,7 @@
   // Stopping the worker hasn't finished within a certain period.
   if (GetTickDuration(stop_time_) >
       base::TimeDelta::FromSeconds(kStopWorkerTimeoutSeconds)) {
-    DCHECK_EQ(STOPPING, running_status());
+    DCHECK_EQ(EmbeddedWorkerStatus::STOPPING, running_status());
     if (IsInstalled(status())) {
       ServiceWorkerMetrics::RecordWorkerStopped(
           ServiceWorkerMetrics::StopStatus::TIMEOUT);
@@ -1413,7 +1425,7 @@
     embedded_worker_->AddListener(this);
 
     // Call OnStoppedInternal to fail callbacks and possibly restart.
-    OnStoppedInternal(EmbeddedWorkerInstance::STOPPING);
+    OnStoppedInternal(EmbeddedWorkerStatus::STOPPING);
     return;
   }
 
@@ -1432,11 +1444,12 @@
           ? base::TimeDelta::FromSeconds(kStartInstalledWorkerTimeoutSeconds)
           : base::TimeDelta::FromMinutes(kStartNewWorkerTimeoutMinutes);
   if (GetTickDuration(start_time_) > start_limit) {
-    DCHECK(running_status() == STARTING || running_status() == STOPPING)
-        << running_status();
+    DCHECK(running_status() == EmbeddedWorkerStatus::STARTING ||
+           running_status() == EmbeddedWorkerStatus::STOPPING)
+        << static_cast<int>(running_status());
     scoped_refptr<ServiceWorkerVersion> protect(this);
     RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT);
-    if (running_status() == STARTING)
+    if (running_status() == EmbeddedWorkerStatus::STARTING)
       embedded_worker_->Stop();
     return;
   }
@@ -1454,12 +1467,12 @@
     }
     requests_.pop();
   }
-  if (stop_for_timeout && running_status() != STOPPING)
+  if (stop_for_timeout && running_status() != EmbeddedWorkerStatus::STOPPING)
     embedded_worker_->Stop();
 
   // For the timeouts below, there are no callbacks to timeout so there is
   // nothing more to do if the worker is already stopping.
-  if (running_status() == STOPPING)
+  if (running_status() == EmbeddedWorkerStatus::STOPPING)
     return;
 
   // The worker has been idle for longer than a certain period.
@@ -1474,12 +1487,14 @@
 }
 
 ServiceWorkerStatusCode ServiceWorkerVersion::PingWorker() {
-  DCHECK(running_status() == STARTING || running_status() == RUNNING);
+  DCHECK(running_status() == EmbeddedWorkerStatus::STARTING ||
+         running_status() == EmbeddedWorkerStatus::RUNNING);
   return embedded_worker_->SendMessage(ServiceWorkerMsg_Ping());
 }
 
 void ServiceWorkerVersion::OnPingTimeout() {
-  DCHECK(running_status() == STARTING || running_status() == RUNNING);
+  DCHECK(running_status() == EmbeddedWorkerStatus::STARTING ||
+         running_status() == EmbeddedWorkerStatus::RUNNING);
   // TODO(falken): Show a message to the developer that the SW was stopped due
   // to timeout (crbug.com/457968). Also, change the error code to
   // SERVICE_WORKER_ERROR_TIMEOUT.
@@ -1489,7 +1504,8 @@
 void ServiceWorkerVersion::StopWorkerIfIdle() {
   if (HasInflightRequests() && !ping_controller_->IsTimedOut())
     return;
-  if (running_status() == STOPPED || running_status() == STOPPING ||
+  if (running_status() == EmbeddedWorkerStatus::STOPPED ||
+      running_status() == EmbeddedWorkerStatus::STOPPING ||
       !stop_callbacks_.empty()) {
     return;
   }
@@ -1534,11 +1550,11 @@
     return;
   EmbeddedWorkerInstance::StartingPhase phase =
       EmbeddedWorkerInstance::NOT_STARTING;
-  EmbeddedWorkerInstance::Status running_status = embedded_worker_->status();
+  EmbeddedWorkerStatus running_status = embedded_worker_->status();
   // Build an artifical JavaScript exception to show in the ServiceWorker
   // log for developers; it's not user-facing so it's not a localized resource.
   std::string message = "ServiceWorker startup timed out. ";
-  if (running_status != EmbeddedWorkerInstance::STARTING) {
+  if (running_status != EmbeddedWorkerStatus::STARTING) {
     message.append("The worker had unexpected status: ");
     message.append(EmbeddedWorkerInstance::StatusToString(running_status));
   } else {
@@ -1637,9 +1653,8 @@
                                 false /* force_bypass_cache */);
 }
 
-void ServiceWorkerVersion::OnStoppedInternal(
-    EmbeddedWorkerInstance::Status old_status) {
-  DCHECK_EQ(STOPPED, running_status());
+void ServiceWorkerVersion::OnStoppedInternal(EmbeddedWorkerStatus old_status) {
+  DCHECK_EQ(EmbeddedWorkerStatus::STOPPED, running_status());
   scoped_refptr<ServiceWorkerVersion> protect;
   if (!in_dtor_)
     protect = this;
@@ -1648,7 +1663,7 @@
   metrics_.reset();
 
   bool should_restart = !is_redundant() && !start_callbacks_.empty() &&
-                        (old_status != EmbeddedWorkerInstance::STARTING) &&
+                        (old_status != EmbeddedWorkerStatus::STARTING) &&
                         !in_dtor_ && !ping_controller_->IsTimedOut();
 
   if (!stop_time_.is_null()) {
@@ -1702,7 +1717,8 @@
 }
 
 void ServiceWorkerVersion::OnBeginEvent() {
-  if (should_exclude_from_uma_ || running_status() != RUNNING ||
+  if (should_exclude_from_uma_ ||
+      running_status() != EmbeddedWorkerStatus::RUNNING ||
       idle_time_.is_null()) {
     return;
   }
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index 9b88f79..4dceb90 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -26,6 +26,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/timer/timer.h"
 #include "content/browser/service_worker/embedded_worker_instance.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_metrics.h"
 #include "content/browser/service_worker/service_worker_script_cache_map.h"
 #include "content/common/content_export.h"
@@ -67,13 +68,6 @@
  public:
   typedef base::Callback<void(ServiceWorkerStatusCode)> StatusCallback;
 
-  enum RunningStatus {
-    STOPPED = EmbeddedWorkerInstance::STOPPED,
-    STARTING = EmbeddedWorkerInstance::STARTING,
-    RUNNING = EmbeddedWorkerInstance::RUNNING,
-    STOPPING = EmbeddedWorkerInstance::STOPPING,
-  };
-
   // Current version status; some of the status (e.g. INSTALLED and ACTIVATED)
   // should be persisted unlike running status.
   enum Status {
@@ -132,8 +126,8 @@
   int64_t registration_id() const { return registration_id_; }
   const GURL& script_url() const { return script_url_; }
   const GURL& scope() const { return scope_; }
-  RunningStatus running_status() const {
-    return static_cast<RunningStatus>(embedded_worker_->status());
+  EmbeddedWorkerStatus running_status() const {
+    return embedded_worker_->status();
   }
   ServiceWorkerVersionInfo GetInfo();
   Status status() const { return status_; }
@@ -295,6 +289,10 @@
   bool skip_waiting() const { return skip_waiting_; }
   void set_skip_waiting(bool skip_waiting) { skip_waiting_ = skip_waiting; }
 
+  bool skip_recording_startup_time() const {
+    return skip_recording_startup_time_;
+  }
+
   bool force_bypass_cache_for_scripts() const {
     return force_bypass_cache_for_scripts_;
   }
@@ -478,8 +476,8 @@
   void OnStarting() override;
   void OnStarted() override;
   void OnStopping() override;
-  void OnStopped(EmbeddedWorkerInstance::Status old_status) override;
-  void OnDetached(EmbeddedWorkerInstance::Status old_status) override;
+  void OnStopped(EmbeddedWorkerStatus old_status) override;
+  void OnDetached(EmbeddedWorkerStatus old_status) override;
   void OnScriptLoaded() override;
   void OnScriptLoadFailed() override;
   void OnReportException(const base::string16& error_message,
@@ -593,7 +591,7 @@
       ServiceWorkerStatusCode status,
       const scoped_refptr<ServiceWorkerRegistration>& registration);
 
-  void OnStoppedInternal(EmbeddedWorkerInstance::Status old_status);
+  void OnStoppedInternal(EmbeddedWorkerStatus old_status);
 
   // Called when the remote side of a connection to a mojo service is lost.
   void OnMojoConnectionError(const char* service_name);
@@ -687,7 +685,7 @@
 template <typename Interface>
 base::WeakPtr<Interface> ServiceWorkerVersion::GetMojoServiceForRequest(
     int request_id) {
-  DCHECK_EQ(RUNNING, running_status());
+  DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, running_status());
   PendingRequest<StatusCallback>* request = custom_requests_.Lookup(request_id);
   DCHECK(request) << "Invalid request id";
   DCHECK(!request->mojo_service)
@@ -714,7 +712,7 @@
 void ServiceWorkerVersion::DispatchEvent(int request_id,
                                          const IPC::Message& message,
                                          const ResponseCallbackType& callback) {
-  DCHECK_EQ(RUNNING, running_status());
+  DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, running_status());
   PendingRequest<StatusCallback>* request = custom_requests_.Lookup(request_id);
   DCHECK(request) << "Invalid request id";
   DCHECK(!request->listener) << "Request already dispatched an IPC event";
diff --git a/content/browser/service_worker/service_worker_version_unittest.cc b/content/browser/service_worker/service_worker_version_unittest.cc
index 4bae9ed..3240d541 100644
--- a/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/content/browser/service_worker/service_worker_version_unittest.cc
@@ -11,6 +11,7 @@
 #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_status.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"
@@ -129,9 +130,7 @@
   ~MessageReceiverFromWorker() override { instance_->RemoveListener(this); }
 
   void OnStarted() override { NOTREACHED(); }
-  void OnStopped(EmbeddedWorkerInstance::Status old_status) override {
-    NOTREACHED();
-  }
+  void OnStopped(EmbeddedWorkerStatus old_status) override { NOTREACHED(); }
   bool OnMessageReceived(const IPC::Message& message) override {
     bool handled = true;
     IPC_BEGIN_MESSAGE_MAP(MessageReceiverFromWorker, message)
@@ -182,12 +181,12 @@
 class ServiceWorkerVersionTest : public testing::Test {
  protected:
   struct RunningStateListener : public ServiceWorkerVersion::Listener {
-    RunningStateListener() : last_status(ServiceWorkerVersion::STOPPED) {}
+    RunningStateListener() : last_status(EmbeddedWorkerStatus::STOPPED) {}
     ~RunningStateListener() override {}
     void OnRunningStateChanged(ServiceWorkerVersion* version) override {
       last_status = version->running_status();
     }
-    ServiceWorkerVersion::RunningStatus last_status;
+    EmbeddedWorkerStatus last_status;
   };
 
   ServiceWorkerVersionTest()
@@ -250,7 +249,7 @@
                                   CreateReceiverOnCurrentThread(&status));
     runner->Run();
     EXPECT_EQ(SERVICE_WORKER_ERROR_MAX_VALUE, status);
-    EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+    EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
     // Start request, as if an event is being dispatched.
     int request_id = version_->StartRequest(
@@ -386,9 +385,9 @@
   version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                         CreateReceiverOnCurrentThread(&status2));
 
-  EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   // Call StartWorker() after it's started.
   version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
@@ -406,9 +405,9 @@
   version_->StopWorker(CreateReceiverOnCurrentThread(&status1));
   version_->StopWorker(CreateReceiverOnCurrentThread(&status2));
 
-  EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, version_->running_status());
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
 
   // All StopWorker should just succeed.
   EXPECT_EQ(SERVICE_WORKER_OK, status1);
@@ -422,9 +421,9 @@
   version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                         CreateReceiverOnCurrentThread(&status1));
 
-  EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   // Call StopWorker()
   status2 = SERVICE_WORKER_ERROR_FAILED;
@@ -434,9 +433,9 @@
   version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                         CreateReceiverOnCurrentThread(&status3));
 
-  EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, version_->running_status());
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   // All should just succeed.
   EXPECT_EQ(SERVICE_WORKER_OK, status1);
@@ -445,14 +444,14 @@
 }
 
 TEST_F(ServiceWorkerVersionTest, DispatchEventToStoppedWorker) {
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::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());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   // Stop the worker, and then dispatch an event immediately after that.
   ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
@@ -461,7 +460,7 @@
   EXPECT_EQ(SERVICE_WORKER_OK, stop_status);
 
   // The worker should be now started again.
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 }
 
 TEST_F(ServiceWorkerVersionTest, StartUnregisteredButStillLiveWorker) {
@@ -470,7 +469,7 @@
   version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                         CreateReceiverOnCurrentThread(&status));
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
 
   // Delete the registration.
@@ -495,7 +494,7 @@
   SimulateDispatchEvent(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME);
 
   // The worker should be now started again.
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 }
 
 TEST_F(ServiceWorkerVersionTest, ReceiveMessageFromWorker) {
@@ -503,10 +502,10 @@
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
   version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                         CreateReceiverOnCurrentThread(&status));
-  EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_OK, status);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   MessageReceiverFromWorker receiver(version_->embedded_worker());
 
@@ -650,7 +649,7 @@
   version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                         CreateReceiverOnCurrentThread(&status));
 
-  ASSERT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
+  ASSERT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
 
   ASSERT_TRUE(version_->timeout_timer_.IsRunning());
   ASSERT_FALSE(version_->start_time_.is_null());
@@ -672,7 +671,7 @@
 
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_OK, status);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 }
 
 TEST_F(ServiceWorkerVersionTest, StoppingBeforeDestruct) {
@@ -684,11 +683,11 @@
                         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);
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, listener.last_status);
 
   version_ = nullptr;
-  EXPECT_EQ(ServiceWorkerVersion::STOPPING, listener.last_status);
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, listener.last_status);
 }
 
 // Test that update isn't triggered for a non-stale worker.
@@ -812,7 +811,7 @@
 
   // Callback has not completed yet.
   EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   // Simulate timeout.
   EXPECT_TRUE(version_->timeout_timer_.IsRunning());
@@ -820,7 +819,7 @@
   version_->timeout_timer_.user_task().Run();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
   EXPECT_FALSE(version_->FinishRequest(request_id, true));
 }
 
@@ -847,7 +846,7 @@
   EXPECT_FALSE(version_->FinishRequest(request_id, true));
 
   // CONTINUE_ON_TIMEOUT timeouts don't stop the service worker.
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 }
 
 TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeoutKill) {
@@ -873,7 +872,7 @@
   EXPECT_FALSE(version_->FinishRequest(request_id, true));
 
   // KILL_ON_TIMEOUT timeouts should stop the service worker.
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
 }
 
 TEST_F(ServiceWorkerVersionTest, MixedRequestTimeouts) {
@@ -907,7 +906,7 @@
   EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, fetch_status);
 
   // Background sync timeouts don't stop the service worker.
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   // Gracefully handle the sync event finishing after the timeout.
   EXPECT_FALSE(version_->FinishRequest(sync_request_id, true));
@@ -922,7 +921,7 @@
   EXPECT_FALSE(version_->FinishRequest(fetch_request_id, true));
 
   // Other timeouts do stop the service worker.
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
 }
 
 TEST_F(ServiceWorkerFailToStartTest, RendererCrash) {
@@ -933,7 +932,7 @@
 
   // Callback has not completed yet.
   EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
-  EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
 
   // Simulate renderer crash: do what
   // ServiceWorkerDispatcherHost::OnFilterRemoved does.
@@ -945,7 +944,7 @@
 
   // Callback completed.
   EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
 }
 
 TEST_F(ServiceWorkerFailToStartTest, Timeout) {
@@ -958,7 +957,7 @@
 
   // Callback has not completed yet.
   EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
-  EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
 
   // Simulate timeout.
   EXPECT_TRUE(version_->timeout_timer_.IsRunning());
@@ -969,7 +968,7 @@
   version_->timeout_timer_.user_task().Run();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
 }
 
 // Test that a service worker stalled in stopping will timeout and not get in a
@@ -981,12 +980,12 @@
                         CreateReceiverOnCurrentThread(&status));
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_OK, status);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::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());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, version_->running_status());
   base::RunLoop().RunUntilIdle();
 
   // Worker is now stalled in stopping. Verify a fast timeout is in place.
@@ -1003,7 +1002,7 @@
   version_->timeout_timer_.user_task().Run();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_OK, status);
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
 
   // Try to start the worker again. It should work.
   status = SERVICE_WORKER_ERROR_FAILED;
@@ -1011,7 +1010,7 @@
                         CreateReceiverOnCurrentThread(&status));
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_OK, status);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   // The timeout interval should be reset to normal.
   EXPECT_TRUE(version_->timeout_timer_.IsRunning());
@@ -1029,12 +1028,12 @@
                         CreateReceiverOnCurrentThread(&status));
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_OK, status);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::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());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, version_->running_status());
 
   // Worker is now stalled in stopping. Add a start worker requset.
   ServiceWorkerStatusCode start_status = SERVICE_WORKER_ERROR_FAILED;
@@ -1051,7 +1050,7 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_OK, status);
   EXPECT_EQ(SERVICE_WORKER_OK, start_status);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 }
 
 TEST_F(ServiceWorkerVersionTest, RegisterForeignFetchScopes) {
@@ -1062,7 +1061,7 @@
                         CreateReceiverOnCurrentThread(&status));
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_OK, status);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::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");
@@ -1138,7 +1137,7 @@
                         CreateReceiverOnCurrentThread(&status));
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_OK, status);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   int request_id =
       version_->StartRequest(ServiceWorkerMetrics::EventType::SYNC,
@@ -1158,7 +1157,7 @@
 
   // Callback completed.
   EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED, status);
-  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
 
   // Request already failed, calling finsh should return false.
   EXPECT_FALSE(version_->FinishRequest(request_id, true));
@@ -1172,7 +1171,7 @@
                         CreateReceiverOnCurrentThread(&status));
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_OK, status);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
   int request_id = version_->StartRequest(
@@ -1197,7 +1196,7 @@
                         CreateReceiverOnCurrentThread(&status));
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_OK, status);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
   int request_id = version_->StartRequest(
@@ -1223,7 +1222,7 @@
                         CreateReceiverOnCurrentThread(&status));
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_OK, status);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   // Start request and dispatch test event.
   scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
@@ -1327,7 +1326,7 @@
                         CreateReceiverOnCurrentThread(&status));
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_OK, status);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   // Start first request and dispatch test event.
   scoped_refptr<MessageLoopRunner> runner1(new MessageLoopRunner);
@@ -1405,7 +1404,7 @@
                         CreateReceiverOnCurrentThread(&status));
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_OK, status);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   // Start request and dispatch test event.
   status = SERVICE_WORKER_ERROR_MAX_VALUE;  // dummy value
@@ -1442,7 +1441,7 @@
                         CreateReceiverOnCurrentThread(&status));
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(SERVICE_WORKER_OK, status);
-  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   // Start request and dispatch test event.
   status = SERVICE_WORKER_ERROR_MAX_VALUE;  // dummy value
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 349f201..61814aa 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -1423,6 +1423,7 @@
       'browser/service_worker/embedded_worker_instance.h',
       'browser/service_worker/embedded_worker_registry.cc',
       'browser/service_worker/embedded_worker_registry.h',
+      'browser/service_worker/embedded_worker_status.h',
       'browser/service_worker/foreign_fetch_request_handler.cc',
       'browser/service_worker/foreign_fetch_request_handler.h',
       'browser/service_worker/link_header_support.cc',
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 4a26cd9..199e753 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -49682,6 +49682,30 @@
   </summary>
 </histogram>
 
+<histogram name="ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time"
+    units="ms">
+  <owner>horo@chromium.org</owner>
+  <summary>
+    The time taken for the browser to find and possibly start an active worker
+    to dispatch a FetchEvent for a main frame resource request. For context, a
+    FetchEvent can only be dispatched to an ACTIVATED worker that is running (it
+    has been successfully started). The measurements starts when the browser
+    process receives the request. The browser then finds the worker appropriate
+    for this request (if there is none, this metric is not recorded). If that
+    worker is already started, the browser process can send the request to it,
+    so the measurement ends quickly. Otherwise the browser process has to start
+    the worker and the measurement ends when the worker is successfully started
+    (we do not include in the time it takes for the worker to become ACTIVATED).
+    The metric is not recorded in the following situations: 1) The worker was in
+    state INSTALLED or ACTIVATING, and the browser had to wait for it to become
+    ACTIVATED. This is to avoid including the time to execute the activate event
+    handlers in the worker's script. 2) The worker was started for the fetch AND
+    DevTools was attached during startup. This is intended to avoid including
+    the time for debugging. 3) The request is for New Tab Page. This is because
+    it tends to dominate the stats and makes the results largely skewed.
+  </summary>
+</histogram>
+
 <histogram name="ServiceWorker.ActivateEvent.Time" units="ms">
   <owner>shimazu@chromium.org</owner>
   <summary>
@@ -97505,6 +97529,22 @@
   <affected-histogram name="ServiceWorker.StartWorker.Time"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="ServiceWorker.WorkerPreparationMode">
+  <suffix name="StartWorkerDuringStartup"
+      label="Started a worker during browser startup."/>
+  <suffix name="StartWorkerNewProcess"
+      label="Started a worker in a new process."/>
+  <suffix name="StartWorkerExistingProcess"
+      label="Started a worker in an existing process."/>
+  <suffix name="StartingWorker"
+      label="The activated worker was already starting up."/>
+  <suffix name="RunningWorker"
+      label="The activated worker was already running."/>
+  <suffix name="StoppingWorker" label="The activated worker was stopping."/>
+  <affected-histogram
+      name="ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="ServiceWorkerCache.Cache" separator=".">
   <suffix name="Batch"
       label="The time to perform the 'batch' operation on a ServiceWorker