Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / browser / service_worker / service_worker_dispatcher_host.cc
index 7bea336..8710ee9 100644 (file)
@@ -4,24 +4,64 @@
 
 #include "content/browser/service_worker/service_worker_dispatcher_host.h"
 
-#include "content/browser/service_worker/service_worker_context.h"
-#include "content/common/service_worker_messages.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/service_worker/embedded_worker_registry.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_provider_host.h"
+#include "content/common/service_worker/embedded_worker_messages.h"
+#include "content/common/service_worker/service_worker_messages.h"
 #include "ipc/ipc_message_macros.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
 #include "url/gurl.h"
 
+using blink::WebServiceWorkerError;
+
+namespace {
+
+const char kDisabledErrorMessage[] =
+    "ServiceWorker is disabled";
+const char kDomainMismatchErrorMessage[] =
+    "Scope and scripts do not have the same origin";
+
+}  // namespace
+
 namespace content {
 
 ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
-    int render_process_id,
-    ServiceWorkerContext* context) : context_(context) {}
+    int render_process_id)
+    : render_process_id_(render_process_id) {
+}
 
-ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {}
+ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
+  if (context_) {
+    context_->RemoveAllProviderHostsForProcess(render_process_id_);
+    context_->embedded_worker_registry()->RemoveChildProcessSender(
+        render_process_id_);
+  }
+}
 
-bool ServiceWorkerDispatcherHost::OnMessageReceived(const IPC::Message& message,
-                                                    bool* message_was_ok) {
-  if (IPC_MESSAGE_CLASS(message) != ServiceWorkerMsgStart)
-    return false;
+void ServiceWorkerDispatcherHost::Init(
+    ServiceWorkerContextWrapper* context_wrapper) {
+  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        base::Bind(&ServiceWorkerDispatcherHost::Init,
+                    this, make_scoped_refptr(context_wrapper)));
+      return;
+  }
+  context_ = context_wrapper->context()->AsWeakPtr();
+  context_->embedded_worker_registry()->AddChildProcessSender(
+      render_process_id_, this);
+}
 
+void ServiceWorkerDispatcherHost::OnDestruct() const {
+  BrowserThread::DeleteOnIOThread::Destruct(this);
+}
+
+bool ServiceWorkerDispatcherHost::OnMessageReceived(
+    const IPC::Message& message,
+    bool* message_was_ok) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP_EX(
     ServiceWorkerDispatcherHost, message, *message_was_ok)
@@ -29,43 +69,166 @@ bool ServiceWorkerDispatcherHost::OnMessageReceived(const IPC::Message& message,
                         OnRegisterServiceWorker)
     IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_UnregisterServiceWorker,
                         OnUnregisterServiceWorker)
+    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderCreated,
+                        OnProviderCreated)
+    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed,
+                        OnProviderDestroyed)
+    IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted,
+                        OnWorkerStarted)
+    IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped,
+                        OnWorkerStopped)
+    IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_SendMessageToBrowser,
+                        OnSendMessageToBrowser)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
 
   return handled;
 }
 
-// TODO(alecflett): Store the service_worker_id keyed by (domain+pattern,
-// script) so we don't always return a new service worker id.
-static int64 NextWorkerId() {
-  static int64 service_worker_id = 0;
-  return service_worker_id++;
-}
-
 void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
     int32 thread_id,
     int32 request_id,
-    const GURL& scope,
+    const GURL& pattern,
     const GURL& script_url) {
-  // TODO(alecflett): add a ServiceWorker-specific policy query in
+  if (!context_ || !context_->IsEnabled()) {
+    Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+        thread_id,
+        request_id,
+        WebServiceWorkerError::DisabledError,
+        base::ASCIIToUTF16(kDisabledErrorMessage)));
+    return;
+  }
+
+  // TODO(alecflett): This check is insufficient for release. Add a
+  // ServiceWorker-specific policy query in
   // ChildProcessSecurityImpl. See http://crbug.com/311631.
+  if (pattern.GetOrigin() != script_url.GetOrigin()) {
+    Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+        thread_id,
+        request_id,
+        WebServiceWorkerError::SecurityError,
+        base::ASCIIToUTF16(kDomainMismatchErrorMessage)));
+    return;
+  }
+
+  context_->RegisterServiceWorker(
+      pattern,
+      script_url,
+      render_process_id_,
+      base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete,
+                 this,
+                 thread_id,
+                 request_id));
+}
+
+void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
+    int32 thread_id,
+    int32 request_id,
+    const GURL& pattern) {
+  // TODO(alecflett): This check is insufficient for release. Add a
+  // ServiceWorker-specific policy query in
+  // ChildProcessSecurityImpl. See http://crbug.com/311631.
+  if (!context_ || !context_->IsEnabled()) {
+    Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+        thread_id,
+        request_id,
+        blink::WebServiceWorkerError::DisabledError,
+        base::ASCIIToUTF16(kDisabledErrorMessage)));
+    return;
+  }
+
+  context_->UnregisterServiceWorker(
+      pattern,
+      render_process_id_,
+      base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete,
+                 this,
+                 thread_id,
+                 request_id));
+}
+
+void ServiceWorkerDispatcherHost::OnProviderCreated(int provider_id) {
+  if (!context_)
+    return;
+  if (context_->GetProviderHost(render_process_id_, provider_id)) {
+    BadMessageReceived();
+    return;
+  }
+  scoped_ptr<ServiceWorkerProviderHost> provider_host(
+       new ServiceWorkerProviderHost(render_process_id_, provider_id));
+  context_->AddProviderHost(provider_host.Pass());
+}
 
-  // TODO(alecflett): Throw an error for origin mismatch, rather than
-  // just returning.
-  if (scope.GetOrigin() != script_url.GetOrigin())
+void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
+  if (!context_)
     return;
+  if (!context_->GetProviderHost(render_process_id_, provider_id)) {
+    BadMessageReceived();
+    return;
+  }
+  context_->RemoveProviderHost(render_process_id_, provider_id);
+}
+
+void ServiceWorkerDispatcherHost::RegistrationComplete(
+    int32 thread_id,
+    int32 request_id,
+    ServiceWorkerStatusCode status,
+    int64 registration_id) {
+  if (status != SERVICE_WORKER_OK) {
+    SendRegistrationError(thread_id, request_id, status);
+    return;
+  }
 
   Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
-      thread_id, request_id, NextWorkerId()));
+      thread_id, request_id, registration_id));
 }
 
-void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(int32 thread_id,
-                                                            int32 request_id,
-                                                            const GURL& scope) {
-  // TODO(alecflett): add a ServiceWorker-specific policy query in
-  // ChildProcessSecurityImpl. See http://crbug.com/311631.
+void ServiceWorkerDispatcherHost::OnWorkerStarted(
+    int thread_id, int embedded_worker_id) {
+  if (!context_)
+    return;
+  context_->embedded_worker_registry()->OnWorkerStarted(
+      render_process_id_, thread_id, embedded_worker_id);
+}
+
+void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) {
+  if (!context_)
+    return;
+  context_->embedded_worker_registry()->OnWorkerStopped(
+      render_process_id_, embedded_worker_id);
+}
+
+void ServiceWorkerDispatcherHost::OnSendMessageToBrowser(
+    int embedded_worker_id,
+    int request_id,
+    const IPC::Message& message) {
+  if (!context_)
+    return;
+  context_->embedded_worker_registry()->OnSendMessageToBrowser(
+      embedded_worker_id, request_id, message);
+}
+
+void ServiceWorkerDispatcherHost::UnregistrationComplete(
+    int32 thread_id,
+    int32 request_id,
+    ServiceWorkerStatusCode status) {
+  if (status != SERVICE_WORKER_OK) {
+    SendRegistrationError(thread_id, request_id, status);
+    return;
+  }
 
   Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id, request_id));
 }
 
+void ServiceWorkerDispatcherHost::SendRegistrationError(
+    int32 thread_id,
+    int32 request_id,
+    ServiceWorkerStatusCode status) {
+  base::string16 error_message;
+  blink::WebServiceWorkerError::ErrorType error_type;
+  GetServiceWorkerRegistrationStatusResponse(
+      status, &error_type, &error_message);
+  Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+      thread_id, request_id, error_type, error_message));
+}
+
 }  // namespace content