Index: content/browser/service_worker/service_worker_version.cc |
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc |
index 03216e1a3c907fabe36195928d003b940bf39d18..7c20ba73b37a65a79712b08507b2e9a138253d76 100644 |
--- a/content/browser/service_worker/service_worker_version.cc |
+++ b/content/browser/service_worker/service_worker_version.cc |
@@ -13,6 +13,95 @@ |
namespace content { |
+namespace { |
+ |
+void RunSoon(const base::Closure& callback) { |
+ base::MessageLoop::current()->PostTask(FROM_HERE, callback); |
+} |
+ |
+} // namespace |
+ |
+//------------------------------------------------------------------- |
+class ServiceWorkerVersion::WorkerObserverBase |
+ : public EmbeddedWorkerInstance::Observer { |
+ public: |
+ virtual ~WorkerObserverBase() { |
+ version_->embedded_worker_->RemoveObserver(this); |
+ } |
+ |
+ virtual void OnStarted() OVERRIDE { NOTREACHED(); } |
+ virtual void OnStopped() OVERRIDE { NOTREACHED(); } |
+ virtual void OnMessageReceived(const IPC::Message& message) OVERRIDE { |
+ NOTREACHED(); |
+ } |
+ |
+ protected: |
+ explicit WorkerObserverBase(ServiceWorkerVersion* version) |
+ : version_(version) { |
+ version_->embedded_worker_->AddObserver(this); |
+ } |
+ |
+ ServiceWorkerVersion* version() { return version_; } |
+ |
+ private: |
+ ServiceWorkerVersion* version_; |
+}; |
+ |
+ |
+// Observer class that is attached while the worker is starting. |
+class ServiceWorkerVersion::StartObserver : public WorkerObserverBase { |
+ public: |
+ typedef ServiceWorkerVersion::StatusCallback StatusCallback; |
+ |
+ StartObserver(ServiceWorkerVersion* version, const StatusCallback& callback) |
+ : WorkerObserverBase(version), |
+ callback_(callback) {} |
+ virtual ~StartObserver() {} |
+ |
+ virtual void OnStarted() OVERRIDE { |
+ Completed(SERVICE_WORKER_OK); |
+ } |
+ |
+ virtual void OnStopped() OVERRIDE { |
+ Completed(SERVICE_WORKER_ERROR_START_WORKER_FAILED); |
+ } |
+ |
+ private: |
+ void Completed(ServiceWorkerStatusCode status) { |
+ StatusCallback callback = callback_; |
+ version()->observer_.reset(); |
+ callback.Run(status); |
+ } |
+ |
+ StatusCallback callback_; |
+ DISALLOW_COPY_AND_ASSIGN(StartObserver); |
+}; |
+ |
+// Observer class that is attached while the worker is stopping. |
+class ServiceWorkerVersion::StopObserver : public WorkerObserverBase { |
+ public: |
+ typedef ServiceWorkerVersion::StatusCallback StatusCallback; |
+ StopObserver(ServiceWorkerVersion* version, const StatusCallback& callback) |
+ : WorkerObserverBase(version), |
+ callback_(callback) {} |
+ virtual ~StopObserver() {} |
+ |
+ virtual void OnStopped() OVERRIDE { |
+ StatusCallback callback = callback_; |
+ version()->observer_.reset(); |
+ callback.Run(SERVICE_WORKER_OK); |
+ } |
+ |
+ virtual void OnMessageReceived(const IPC::Message& message) OVERRIDE { |
+ // We just ignore messages, as we're stopping. |
+ } |
+ |
+ private: |
+ StatusCallback callback_; |
+ DISALLOW_COPY_AND_ASSIGN(StopObserver); |
+}; |
+ |
+//------------------------------------------------------------------- |
ServiceWorkerVersion::ServiceWorkerVersion( |
ServiceWorkerRegistration* registration, |
EmbeddedWorkerRegistry* worker_registry, |
@@ -32,34 +121,54 @@ void ServiceWorkerVersion::Shutdown() { |
embedded_worker_.reset(); |
} |
-void ServiceWorkerVersion::StartWorker() { |
+void ServiceWorkerVersion::StartWorker(const StatusCallback& callback) { |
DCHECK(!is_shutdown_); |
DCHECK(registration_); |
- embedded_worker_->Start(version_id_, registration_->script_url()); |
+ DCHECK(!observer_); |
+ if (status() == RUNNING) { |
+ RunSoon(base::Bind(callback, SERVICE_WORKER_OK)); |
+ return; |
+ } |
+ observer_.reset(new StartObserver(this, callback)); |
+ const bool started = embedded_worker_->Start( |
+ version_id_, |
+ registration_->script_url()); |
+ if (!started) { |
+ observer_.reset(); |
+ RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED)); |
+ } |
} |
-void ServiceWorkerVersion::StopWorker() { |
+void ServiceWorkerVersion::StopWorker(const StatusCallback& callback) { |
DCHECK(!is_shutdown_); |
- embedded_worker_->Stop(); |
+ DCHECK(!observer_); |
+ if (status() == STOPPED) { |
+ RunSoon(base::Bind(callback, SERVICE_WORKER_OK)); |
+ return; |
+ } |
+ observer_.reset(new StopObserver(this, callback)); |
+ const bool stopped = embedded_worker_->Stop(); |
+ if (!stopped) { |
+ observer_.reset(); |
+ RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_FAILED)); |
+ } |
} |
bool ServiceWorkerVersion::DispatchFetchEvent( |
const ServiceWorkerFetchRequest& request) { |
- if (embedded_worker_->status() != EmbeddedWorkerInstance::RUNNING) |
+ if (status() != RUNNING) |
return false; |
return embedded_worker_->SendMessage( |
ServiceWorkerMsg_FetchEvent(request)); |
} |
-void ServiceWorkerVersion::OnAssociateProvider( |
- ServiceWorkerProviderHost* provider_host) { |
+void ServiceWorkerVersion::AddProcessToWorker(int process_id) { |
DCHECK(!is_shutdown_); |
- embedded_worker_->AddProcessReference(provider_host->process_id()); |
+ embedded_worker_->AddProcessReference(process_id); |
} |
-void ServiceWorkerVersion::OnUnassociateProvider( |
- ServiceWorkerProviderHost* provider_host) { |
- embedded_worker_->ReleaseProcessReference(provider_host->process_id()); |
+void ServiceWorkerVersion::RemoveProcessToWorker(int process_id) { |
+ embedded_worker_->ReleaseProcessReference(process_id); |
} |
} // namespace content |