• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <map>
8 
9 #include "base/debug/trace_event.h"
10 #include "base/logging.h"
11 #include "content/child/thread_safe_sender.h"
12 #include "content/child/webmessageportchannel_impl.h"
13 #include "content/common/service_worker/service_worker_messages.h"
14 #include "content/renderer/service_worker/embedded_worker_context_client.h"
15 #include "ipc/ipc_message.h"
16 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
17 #include "third_party/WebKit/public/platform/WebServiceWorkerRequest.h"
18 #include "third_party/WebKit/public/platform/WebString.h"
19 #include "third_party/WebKit/public/platform/WebURL.h"
20 #include "third_party/WebKit/public/web/WebServiceWorkerContextClient.h"
21 #include "third_party/WebKit/public/web/WebServiceWorkerContextProxy.h"
22 
23 namespace content {
24 
25 namespace {
26 
SendPostMessageToDocumentOnMainThread(ThreadSafeSender * sender,int routing_id,int client_id,const base::string16 & message,scoped_ptr<blink::WebMessagePortChannelArray> channels)27 void SendPostMessageToDocumentOnMainThread(
28     ThreadSafeSender* sender,
29     int routing_id,
30     int client_id,
31     const base::string16& message,
32     scoped_ptr<blink::WebMessagePortChannelArray> channels) {
33   sender->Send(new ServiceWorkerHostMsg_PostMessageToDocument(
34       routing_id, client_id, message,
35       WebMessagePortChannelImpl::ExtractMessagePortIDs(channels.release())));
36 }
37 
38 }  // namespace
39 
ServiceWorkerScriptContext(EmbeddedWorkerContextClient * embedded_context,blink::WebServiceWorkerContextProxy * proxy)40 ServiceWorkerScriptContext::ServiceWorkerScriptContext(
41     EmbeddedWorkerContextClient* embedded_context,
42     blink::WebServiceWorkerContextProxy* proxy)
43     : cache_storage_dispatcher_(new ServiceWorkerCacheStorageDispatcher(this)),
44       embedded_context_(embedded_context),
45       proxy_(proxy) {
46 }
47 
~ServiceWorkerScriptContext()48 ServiceWorkerScriptContext::~ServiceWorkerScriptContext() {}
49 
OnMessageReceived(const IPC::Message & message)50 void ServiceWorkerScriptContext::OnMessageReceived(
51     const IPC::Message& message) {
52   bool handled = true;
53   IPC_BEGIN_MESSAGE_MAP(ServiceWorkerScriptContext, message)
54     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ActivateEvent, OnActivateEvent)
55     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FetchEvent, OnFetchEvent)
56     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_InstallEvent, OnInstallEvent)
57     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SyncEvent, OnSyncEvent)
58     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_PushEvent, OnPushEvent)
59     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToWorker, OnPostMessage)
60     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetClientDocuments,
61                         OnDidGetClientDocuments)
62     IPC_MESSAGE_UNHANDLED(handled = false)
63   IPC_END_MESSAGE_MAP()
64 
65   // TODO(gavinp): Would it be preferable to put an AddListener() method to
66   // EmbeddedWorkerContextClient?
67   if (!handled)
68     handled = cache_storage_dispatcher_->OnMessageReceived(message);
69 
70   DCHECK(handled);
71 }
72 
DidHandleActivateEvent(int request_id,blink::WebServiceWorkerEventResult result)73 void ServiceWorkerScriptContext::DidHandleActivateEvent(
74     int request_id,
75     blink::WebServiceWorkerEventResult result) {
76   Send(new ServiceWorkerHostMsg_ActivateEventFinished(
77       GetRoutingID(), request_id, result));
78 }
79 
DidHandleInstallEvent(int request_id,blink::WebServiceWorkerEventResult result)80 void ServiceWorkerScriptContext::DidHandleInstallEvent(
81     int request_id,
82     blink::WebServiceWorkerEventResult result) {
83   Send(new ServiceWorkerHostMsg_InstallEventFinished(
84       GetRoutingID(), request_id, result));
85 }
86 
DidHandleFetchEvent(int request_id,ServiceWorkerFetchEventResult result,const ServiceWorkerResponse & response)87 void ServiceWorkerScriptContext::DidHandleFetchEvent(
88     int request_id,
89     ServiceWorkerFetchEventResult result,
90     const ServiceWorkerResponse& response) {
91   Send(new ServiceWorkerHostMsg_FetchEventFinished(
92       GetRoutingID(), request_id, result, response));
93 }
94 
DidHandleSyncEvent(int request_id)95 void ServiceWorkerScriptContext::DidHandleSyncEvent(int request_id) {
96   Send(new ServiceWorkerHostMsg_SyncEventFinished(
97       GetRoutingID(), request_id));
98 }
99 
GetClientDocuments(blink::WebServiceWorkerClientsCallbacks * callbacks)100 void ServiceWorkerScriptContext::GetClientDocuments(
101     blink::WebServiceWorkerClientsCallbacks* callbacks) {
102   DCHECK(callbacks);
103   int request_id = pending_clients_callbacks_.Add(callbacks);
104   Send(new ServiceWorkerHostMsg_GetClientDocuments(
105       GetRoutingID(), request_id));
106 }
107 
PostMessageToDocument(int client_id,const base::string16 & message,scoped_ptr<blink::WebMessagePortChannelArray> channels)108 void ServiceWorkerScriptContext::PostMessageToDocument(
109     int client_id,
110     const base::string16& message,
111     scoped_ptr<blink::WebMessagePortChannelArray> channels) {
112   // This may send channels for MessagePorts, and all internal book-keeping
113   // messages for MessagePort (e.g. QueueMessages) are sent from main thread
114   // (with thread hopping), so we need to do the same thread hopping here not
115   // to overtake those messages.
116   embedded_context_->main_thread_proxy()->PostTask(
117       FROM_HERE,
118       base::Bind(&SendPostMessageToDocumentOnMainThread,
119                  make_scoped_refptr(embedded_context_->thread_safe_sender()),
120                  GetRoutingID(), client_id, message, base::Passed(&channels)));
121 }
122 
Send(IPC::Message * message)123 void ServiceWorkerScriptContext::Send(IPC::Message* message) {
124   embedded_context_->Send(message);
125 }
126 
GetRoutingID() const127 int ServiceWorkerScriptContext::GetRoutingID() const {
128   return embedded_context_->embedded_worker_id();
129 }
130 
OnActivateEvent(int request_id)131 void ServiceWorkerScriptContext::OnActivateEvent(int request_id) {
132   TRACE_EVENT0("ServiceWorker",
133                "ServiceWorkerScriptContext::OnActivateEvent");
134   proxy_->dispatchActivateEvent(request_id);
135 }
136 
OnInstallEvent(int request_id,int active_version_id)137 void ServiceWorkerScriptContext::OnInstallEvent(int request_id,
138                                                 int active_version_id) {
139   TRACE_EVENT0("ServiceWorker",
140                "ServiceWorkerScriptContext::OnInstallEvent");
141   proxy_->dispatchInstallEvent(request_id);
142 }
143 
OnFetchEvent(int request_id,const ServiceWorkerFetchRequest & request)144 void ServiceWorkerScriptContext::OnFetchEvent(
145     int request_id,
146     const ServiceWorkerFetchRequest& request) {
147   blink::WebServiceWorkerRequest webRequest;
148   TRACE_EVENT0("ServiceWorker",
149                "ServiceWorkerScriptContext::OnFetchEvent");
150   webRequest.setURL(blink::WebURL(request.url));
151   webRequest.setMethod(blink::WebString::fromUTF8(request.method));
152   for (ServiceWorkerHeaderMap::const_iterator it = request.headers.begin();
153        it != request.headers.end();
154        ++it) {
155     webRequest.setHeader(blink::WebString::fromUTF8(it->first),
156                          blink::WebString::fromUTF8(it->second));
157   }
158   if (!request.blob_uuid.empty()) {
159     webRequest.setBlob(blink::WebString::fromUTF8(request.blob_uuid),
160                        request.blob_size);
161   }
162   webRequest.setReferrer(blink::WebString::fromUTF8(request.referrer.spec()),
163                          blink::WebReferrerPolicyDefault);
164   webRequest.setIsReload(request.is_reload);
165   proxy_->dispatchFetchEvent(request_id, webRequest);
166 }
167 
OnSyncEvent(int request_id)168 void ServiceWorkerScriptContext::OnSyncEvent(int request_id) {
169   TRACE_EVENT0("ServiceWorker",
170                "ServiceWorkerScriptContext::OnSyncEvent");
171   proxy_->dispatchSyncEvent(request_id);
172 }
173 
OnPushEvent(int request_id,const std::string & data)174 void ServiceWorkerScriptContext::OnPushEvent(int request_id,
175                                              const std::string& data) {
176   TRACE_EVENT0("ServiceWorker",
177                "ServiceWorkerScriptContext::OnPushEvent");
178   proxy_->dispatchPushEvent(request_id, blink::WebString::fromUTF8(data));
179   Send(new ServiceWorkerHostMsg_PushEventFinished(
180       GetRoutingID(), request_id));
181 }
182 
OnPostMessage(const base::string16 & message,const std::vector<int> & sent_message_port_ids,const std::vector<int> & new_routing_ids)183 void ServiceWorkerScriptContext::OnPostMessage(
184     const base::string16& message,
185     const std::vector<int>& sent_message_port_ids,
186     const std::vector<int>& new_routing_ids) {
187   TRACE_EVENT0("ServiceWorker",
188                "ServiceWorkerScriptContext::OnPostEvent");
189   std::vector<WebMessagePortChannelImpl*> ports;
190   if (!sent_message_port_ids.empty()) {
191     base::MessageLoopProxy* loop_proxy = embedded_context_->main_thread_proxy();
192     ports.resize(sent_message_port_ids.size());
193     for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
194       ports[i] = new WebMessagePortChannelImpl(
195           new_routing_ids[i], sent_message_port_ids[i], loop_proxy);
196     }
197   }
198 
199   proxy_->dispatchMessageEvent(message, ports);
200 }
201 
OnDidGetClientDocuments(int request_id,const std::vector<int> & client_ids)202 void ServiceWorkerScriptContext::OnDidGetClientDocuments(
203     int request_id, const std::vector<int>& client_ids) {
204   TRACE_EVENT0("ServiceWorker",
205                "ServiceWorkerScriptContext::OnDidGetClientDocuments");
206   blink::WebServiceWorkerClientsCallbacks* callbacks =
207       pending_clients_callbacks_.Lookup(request_id);
208   if (!callbacks) {
209     NOTREACHED() << "Got stray response: " << request_id;
210     return;
211   }
212   scoped_ptr<blink::WebServiceWorkerClientsInfo> info(
213       new blink::WebServiceWorkerClientsInfo);
214   info->clientIDs = client_ids;
215   callbacks->onSuccess(info.release());
216   pending_clients_callbacks_.Remove(request_id);
217 }
218 
219 }  // namespace content
220