Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / child / service_worker / service_worker_dispatcher.cc
index ac870ac..123f983 100644 (file)
@@ -5,10 +5,16 @@
 #include "content/child/service_worker/service_worker_dispatcher.h"
 
 #include "base/lazy_instance.h"
+#include "base/stl_util.h"
 #include "base/threading/thread_local.h"
+#include "content/child/child_thread.h"
+#include "content/child/service_worker/service_worker_handle_reference.h"
+#include "content/child/service_worker/service_worker_provider_context.h"
 #include "content/child/service_worker/web_service_worker_impl.h"
 #include "content/child/thread_safe_sender.h"
+#include "content/child/webmessageportchannel_impl.h"
 #include "content/common/service_worker/service_worker_messages.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerProviderClient.h"
 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
 
 using blink::WebServiceWorkerError;
@@ -49,6 +55,12 @@ void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message& msg) {
                         OnUnregistered)
     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError,
                         OnRegistrationError)
+    IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged,
+                        OnServiceWorkerStateChanged)
+    IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetCurrentServiceWorker,
+                        OnSetCurrentServiceWorker)
+    IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument,
+                        OnPostMessage)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   DCHECK(handled) << "Unhandled message:" << msg.type();
@@ -59,22 +71,40 @@ bool ServiceWorkerDispatcher::Send(IPC::Message* msg) {
 }
 
 void ServiceWorkerDispatcher::RegisterServiceWorker(
+    int provider_id,
     const GURL& pattern,
     const GURL& script_url,
     WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks) {
   DCHECK(callbacks);
   int request_id = pending_callbacks_.Add(callbacks);
   thread_safe_sender_->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
-      CurrentWorkerId(), request_id, pattern, script_url));
+      CurrentWorkerId(), request_id, provider_id, pattern, script_url));
 }
 
 void ServiceWorkerDispatcher::UnregisterServiceWorker(
+    int provider_id,
     const GURL& pattern,
     WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks) {
   DCHECK(callbacks);
   int request_id = pending_callbacks_.Add(callbacks);
   thread_safe_sender_->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
-      CurrentWorkerId(), request_id, pattern));
+      CurrentWorkerId(), request_id, provider_id, pattern));
+}
+
+void ServiceWorkerDispatcher::AddProviderContext(
+    ServiceWorkerProviderContext* provider_context) {
+  DCHECK(provider_context);
+  int provider_id = provider_context->provider_id();
+  DCHECK(!ContainsKey(provider_contexts_, provider_id));
+  provider_contexts_[provider_id] = provider_context;
+}
+
+void ServiceWorkerDispatcher::RemoveProviderContext(
+    ServiceWorkerProviderContext* provider_context) {
+  DCHECK(provider_context);
+  DCHECK(ContainsKey(provider_contexts_, provider_context->provider_id()));
+  provider_contexts_.erase(provider_context->provider_id());
+  worker_to_provider_.erase(provider_context->current_handle_id());
 }
 
 void ServiceWorkerDispatcher::AddScriptClient(
@@ -83,20 +113,16 @@ void ServiceWorkerDispatcher::AddScriptClient(
   DCHECK(client);
   DCHECK(!ContainsKey(script_clients_, provider_id));
   script_clients_[provider_id] = client;
-  thread_safe_sender_->Send(new ServiceWorkerHostMsg_AddScriptClient(
-      CurrentWorkerId(), provider_id));
 }
 
 void ServiceWorkerDispatcher::RemoveScriptClient(int provider_id) {
   // This could be possibly called multiple times to ensure termination.
-  if (ContainsKey(script_clients_, provider_id)) {
+  if (ContainsKey(script_clients_, provider_id))
     script_clients_.erase(provider_id);
-    thread_safe_sender_->Send(new ServiceWorkerHostMsg_RemoveScriptClient(
-        CurrentWorkerId(), provider_id));
-  }
 }
 
-ServiceWorkerDispatcher* ServiceWorkerDispatcher::ThreadSpecificInstance(
+ServiceWorkerDispatcher*
+ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
     ThreadSafeSender* thread_safe_sender) {
   if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
     NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
@@ -112,30 +138,43 @@ ServiceWorkerDispatcher* ServiceWorkerDispatcher::ThreadSpecificInstance(
   return dispatcher;
 }
 
-void ServiceWorkerDispatcher::OnRegistered(int32 thread_id,
-                                           int32 request_id,
-                                           int64 registration_id) {
+ServiceWorkerDispatcher* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
+  if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted)
+    return NULL;
+  return g_dispatcher_tls.Pointer()->Get();
+}
+
+void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
+  delete this;
+}
+
+void ServiceWorkerDispatcher::OnRegistered(
+    int thread_id,
+    int request_id,
+    const ServiceWorkerObjectInfo& info) {
   WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks =
       pending_callbacks_.Lookup(request_id);
   DCHECK(callbacks);
   if (!callbacks)
     return;
 
-  // the browser has to generate the registration_id so the same
+  // The browser has to generate the registration_id so the same
   // worker can be called from different renderer contexts. However,
   // the impl object doesn't have to be the same instance across calls
   // unless we require the DOM objects to be identical when there's a
   // duplicate registration. So for now we mint a new object each
   // time.
+  //
+  // WebServiceWorkerImpl's ctor internally calls AddServiceWorker.
   scoped_ptr<WebServiceWorkerImpl> worker(
-      new WebServiceWorkerImpl(registration_id, thread_safe_sender_));
+      new WebServiceWorkerImpl(info, thread_safe_sender_));
   callbacks->onSuccess(worker.release());
   pending_callbacks_.Remove(request_id);
 }
 
 void ServiceWorkerDispatcher::OnUnregistered(
-    int32 thread_id,
-    int32 request_id) {
+    int thread_id,
+    int request_id) {
   WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks =
       pending_callbacks_.Lookup(request_id);
   DCHECK(callbacks);
@@ -147,8 +186,8 @@ void ServiceWorkerDispatcher::OnUnregistered(
 }
 
 void ServiceWorkerDispatcher::OnRegistrationError(
-    int32 thread_id,
-    int32 request_id,
+    int thread_id,
+    int request_id,
     WebServiceWorkerError::ErrorType error_type,
     const base::string16& message) {
   WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks =
@@ -163,6 +202,78 @@ void ServiceWorkerDispatcher::OnRegistrationError(
   pending_callbacks_.Remove(request_id);
 }
 
-void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() { delete this; }
+void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
+    int thread_id,
+    int handle_id,
+    blink::WebServiceWorkerState state) {
+  WorkerObjectMap::iterator worker = service_workers_.find(handle_id);
+  if (worker != service_workers_.end())
+    worker->second->OnStateChanged(state);
+
+  WorkerToProviderMap::iterator provider = worker_to_provider_.find(handle_id);
+  if (provider != worker_to_provider_.end())
+    provider->second->OnServiceWorkerStateChanged(handle_id, state);
+}
+
+void ServiceWorkerDispatcher::OnSetCurrentServiceWorker(
+    int thread_id,
+    int provider_id,
+    const ServiceWorkerObjectInfo& info) {
+  ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
+  if (provider != provider_contexts_.end()) {
+    provider->second->OnSetCurrentServiceWorker(provider_id, info);
+    worker_to_provider_[info.handle_id] = provider->second;
+  }
+
+  ScriptClientMap::iterator found = script_clients_.find(provider_id);
+  if (found != script_clients_.end()) {
+    // Populate the .current field with the new worker object.
+    scoped_ptr<ServiceWorkerHandleReference> handle_ref(
+        ServiceWorkerHandleReference::Create(info, thread_safe_sender_));
+    found->second->setCurrentServiceWorker(
+        new WebServiceWorkerImpl(handle_ref.Pass(), thread_safe_sender_));
+  }
+}
+
+void ServiceWorkerDispatcher::OnPostMessage(
+    int thread_id,
+    int provider_id,
+    const base::string16& message,
+    const std::vector<int>& sent_message_port_ids,
+    const std::vector<int>& new_routing_ids) {
+  // Make sure we're on the main document thread. (That must be the only
+  // thread we get this message)
+  DCHECK(ChildThread::current());
+
+  ScriptClientMap::iterator found = script_clients_.find(provider_id);
+  if (found == script_clients_.end()) {
+    // For now we do no queueing for messages sent to nonexistent / unattached
+    // client.
+    return;
+  }
+
+  std::vector<WebMessagePortChannelImpl*> ports;
+  if (!sent_message_port_ids.empty()) {
+    ports.resize(sent_message_port_ids.size());
+    for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
+      ports[i] = new WebMessagePortChannelImpl(
+          new_routing_ids[i], sent_message_port_ids[i],
+          base::MessageLoopProxy::current());
+    }
+  }
+
+  found->second->dispatchMessageEvent(message, ports);
+}
+
+void ServiceWorkerDispatcher::AddServiceWorker(
+    int handle_id, WebServiceWorkerImpl* worker) {
+  DCHECK(!ContainsKey(service_workers_, handle_id));
+  service_workers_[handle_id] = worker;
+}
+
+void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id) {
+  DCHECK(ContainsKey(service_workers_, handle_id));
+  service_workers_.erase(handle_id);
+}
 
 }  // namespace content