Home | History | Annotate | Download | only in service_worker
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/renderer/service_worker/service_worker_script_context.h"
      6 
      7 #include "base/logging.h"
      8 #include "content/child/thread_safe_sender.h"
      9 #include "content/child/webmessageportchannel_impl.h"
     10 #include "content/common/service_worker/service_worker_messages.h"
     11 #include "content/renderer/service_worker/embedded_worker_context_client.h"
     12 #include "ipc/ipc_message.h"
     13 #include "third_party/WebKit/public/platform/WebServiceWorkerRequest.h"
     14 #include "third_party/WebKit/public/platform/WebString.h"
     15 #include "third_party/WebKit/public/platform/WebURL.h"
     16 #include "third_party/WebKit/public/web/WebServiceWorkerContextClient.h"
     17 #include "third_party/WebKit/public/web/WebServiceWorkerContextProxy.h"
     18 
     19 namespace content {
     20 
     21 namespace {
     22 
     23 void SendPostMessageToDocumentOnMainThread(
     24     ThreadSafeSender* sender,
     25     int routing_id,
     26     int client_id,
     27     const base::string16& message,
     28     scoped_ptr<blink::WebMessagePortChannelArray> channels) {
     29   sender->Send(new ServiceWorkerHostMsg_PostMessageToDocument(
     30       routing_id, client_id, message,
     31       WebMessagePortChannelImpl::ExtractMessagePortIDs(channels.release())));
     32 }
     33 
     34 }  // namespace
     35 
     36 ServiceWorkerScriptContext::ServiceWorkerScriptContext(
     37     EmbeddedWorkerContextClient* embedded_context,
     38     blink::WebServiceWorkerContextProxy* proxy)
     39     : embedded_context_(embedded_context),
     40       proxy_(proxy) {
     41 }
     42 
     43 ServiceWorkerScriptContext::~ServiceWorkerScriptContext() {}
     44 
     45 void ServiceWorkerScriptContext::OnMessageReceived(
     46     const IPC::Message& message) {
     47   bool handled = true;
     48   IPC_BEGIN_MESSAGE_MAP(ServiceWorkerScriptContext, message)
     49     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ActivateEvent, OnActivateEvent)
     50     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FetchEvent, OnFetchEvent)
     51     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_InstallEvent, OnInstallEvent)
     52     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SyncEvent, OnSyncEvent)
     53     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_PushEvent, OnPushEvent)
     54     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToWorker, OnPostMessage)
     55     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetClientDocuments,
     56                         OnDidGetClientDocuments)
     57     IPC_MESSAGE_UNHANDLED(handled = false)
     58   IPC_END_MESSAGE_MAP()
     59   DCHECK(handled);
     60 }
     61 
     62 void ServiceWorkerScriptContext::DidHandleActivateEvent(
     63     int request_id,
     64     blink::WebServiceWorkerEventResult result) {
     65   Send(new ServiceWorkerHostMsg_ActivateEventFinished(
     66       GetRoutingID(), request_id, result));
     67 }
     68 
     69 void ServiceWorkerScriptContext::DidHandleInstallEvent(
     70     int request_id,
     71     blink::WebServiceWorkerEventResult result) {
     72   Send(new ServiceWorkerHostMsg_InstallEventFinished(
     73       GetRoutingID(), request_id, result));
     74 }
     75 
     76 void ServiceWorkerScriptContext::DidHandleFetchEvent(
     77     int request_id,
     78     ServiceWorkerFetchEventResult result,
     79     const ServiceWorkerResponse& response) {
     80   Send(new ServiceWorkerHostMsg_FetchEventFinished(
     81       GetRoutingID(), request_id, result, response));
     82 }
     83 
     84 void ServiceWorkerScriptContext::DidHandleSyncEvent(int request_id) {
     85   Send(new ServiceWorkerHostMsg_SyncEventFinished(
     86       GetRoutingID(), request_id));
     87 }
     88 
     89 void ServiceWorkerScriptContext::GetClientDocuments(
     90     blink::WebServiceWorkerClientsCallbacks* callbacks) {
     91   DCHECK(callbacks);
     92   int request_id = pending_clients_callbacks_.Add(callbacks);
     93   Send(new ServiceWorkerHostMsg_GetClientDocuments(
     94       GetRoutingID(), request_id));
     95 }
     96 
     97 void ServiceWorkerScriptContext::PostMessageToDocument(
     98     int client_id,
     99     const base::string16& message,
    100     scoped_ptr<blink::WebMessagePortChannelArray> channels) {
    101   // This may send channels for MessagePorts, and all internal book-keeping
    102   // messages for MessagePort (e.g. QueueMessages) are sent from main thread
    103   // (with thread hopping), so we need to do the same thread hopping here not
    104   // to overtake those messages.
    105   embedded_context_->main_thread_proxy()->PostTask(
    106       FROM_HERE,
    107       base::Bind(&SendPostMessageToDocumentOnMainThread,
    108                  make_scoped_refptr(embedded_context_->thread_safe_sender()),
    109                  GetRoutingID(), client_id, message, base::Passed(&channels)));
    110 }
    111 
    112 void ServiceWorkerScriptContext::Send(IPC::Message* message) {
    113   embedded_context_->Send(message);
    114 }
    115 
    116 void ServiceWorkerScriptContext::OnActivateEvent(int request_id) {
    117   proxy_->dispatchActivateEvent(request_id);
    118 }
    119 
    120 void ServiceWorkerScriptContext::OnInstallEvent(int request_id,
    121                                                 int active_version_id) {
    122   proxy_->dispatchInstallEvent(request_id);
    123 }
    124 
    125 void ServiceWorkerScriptContext::OnFetchEvent(
    126     int request_id,
    127     const ServiceWorkerFetchRequest& request) {
    128   blink::WebServiceWorkerRequest webRequest;
    129   webRequest.setURL(blink::WebURL(request.url));
    130   webRequest.setMethod(blink::WebString::fromUTF8(request.method));
    131   for (std::map<std::string, std::string>::const_iterator it =
    132            request.headers.begin();
    133        it != request.headers.end();
    134        ++it) {
    135     webRequest.setHeader(blink::WebString::fromUTF8(it->first),
    136                          blink::WebString::fromUTF8(it->second));
    137   }
    138   proxy_->dispatchFetchEvent(request_id, webRequest);
    139 }
    140 
    141 void ServiceWorkerScriptContext::OnSyncEvent(int request_id) {
    142   proxy_->dispatchSyncEvent(request_id);
    143 }
    144 
    145 void ServiceWorkerScriptContext::OnPushEvent(int request_id,
    146                                              const std::string& data) {
    147   proxy_->dispatchPushEvent(request_id, blink::WebString::fromUTF8(data));
    148   Send(new ServiceWorkerHostMsg_PushEventFinished(
    149       GetRoutingID(), request_id));
    150 }
    151 
    152 void ServiceWorkerScriptContext::OnPostMessage(
    153     const base::string16& message,
    154     const std::vector<int>& sent_message_port_ids,
    155     const std::vector<int>& new_routing_ids) {
    156   std::vector<WebMessagePortChannelImpl*> ports;
    157   if (!sent_message_port_ids.empty()) {
    158     base::MessageLoopProxy* loop_proxy = embedded_context_->main_thread_proxy();
    159     ports.resize(sent_message_port_ids.size());
    160     for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
    161       ports[i] = new WebMessagePortChannelImpl(
    162           new_routing_ids[i], sent_message_port_ids[i], loop_proxy);
    163     }
    164   }
    165 
    166   proxy_->dispatchMessageEvent(message, ports);
    167 }
    168 
    169 void ServiceWorkerScriptContext::OnDidGetClientDocuments(
    170     int request_id, const std::vector<int>& client_ids) {
    171   blink::WebServiceWorkerClientsCallbacks* callbacks =
    172       pending_clients_callbacks_.Lookup(request_id);
    173   if (!callbacks) {
    174     NOTREACHED() << "Got stray response: " << request_id;
    175     return;
    176   }
    177   scoped_ptr<blink::WebServiceWorkerClientsInfo> info(
    178       new blink::WebServiceWorkerClientsInfo);
    179   info->clientIDs = client_ids;
    180   callbacks->onSuccess(info.release());
    181   pending_clients_callbacks_.Remove(request_id);
    182 }
    183 
    184 int ServiceWorkerScriptContext::GetRoutingID() const {
    185   return embedded_context_->embedded_worker_id();
    186 }
    187 
    188 }  // namespace content
    189