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.
5 #include "content/renderer/service_worker/service_worker_script_context.h"
9 #include "base/logging.h"
10 #include "content/child/thread_safe_sender.h"
11 #include "content/child/webmessageportchannel_impl.h"
12 #include "content/common/service_worker/service_worker_messages.h"
13 #include "content/renderer/service_worker/embedded_worker_context_client.h"
14 #include "ipc/ipc_message.h"
15 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
16 #include "third_party/WebKit/public/platform/WebServiceWorkerRequest.h"
17 #include "third_party/WebKit/public/platform/WebString.h"
18 #include "third_party/WebKit/public/platform/WebURL.h"
19 #include "third_party/WebKit/public/web/WebServiceWorkerContextClient.h"
20 #include "third_party/WebKit/public/web/WebServiceWorkerContextProxy.h"
26 void SendPostMessageToDocumentOnMainThread(
27 ThreadSafeSender
* sender
,
30 const base::string16
& message
,
31 scoped_ptr
<blink::WebMessagePortChannelArray
> channels
) {
32 sender
->Send(new ServiceWorkerHostMsg_PostMessageToDocument(
33 routing_id
, client_id
, message
,
34 WebMessagePortChannelImpl::ExtractMessagePortIDs(channels
.release())));
39 ServiceWorkerScriptContext::ServiceWorkerScriptContext(
40 EmbeddedWorkerContextClient
* embedded_context
,
41 blink::WebServiceWorkerContextProxy
* proxy
)
42 : cache_storage_dispatcher_(new ServiceWorkerCacheStorageDispatcher(this)),
43 embedded_context_(embedded_context
),
47 ServiceWorkerScriptContext::~ServiceWorkerScriptContext() {}
49 void ServiceWorkerScriptContext::OnMessageReceived(
50 const IPC::Message
& message
) {
52 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerScriptContext
, message
)
53 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ActivateEvent
, OnActivateEvent
)
54 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FetchEvent
, OnFetchEvent
)
55 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_InstallEvent
, OnInstallEvent
)
56 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SyncEvent
, OnSyncEvent
)
57 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_PushEvent
, OnPushEvent
)
58 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToWorker
, OnPostMessage
)
59 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetClientDocuments
,
60 OnDidGetClientDocuments
)
61 IPC_MESSAGE_UNHANDLED(handled
= false)
64 // TODO(gavinp): Would it be preferable to put an AddListener() method to
65 // EmbeddedWorkerContextClient?
67 handled
= cache_storage_dispatcher_
->OnMessageReceived(message
);
72 void ServiceWorkerScriptContext::DidHandleActivateEvent(
74 blink::WebServiceWorkerEventResult result
) {
75 Send(new ServiceWorkerHostMsg_ActivateEventFinished(
76 GetRoutingID(), request_id
, result
));
79 void ServiceWorkerScriptContext::DidHandleInstallEvent(
81 blink::WebServiceWorkerEventResult result
) {
82 Send(new ServiceWorkerHostMsg_InstallEventFinished(
83 GetRoutingID(), request_id
, result
));
86 void ServiceWorkerScriptContext::DidHandleFetchEvent(
88 ServiceWorkerFetchEventResult result
,
89 const ServiceWorkerResponse
& response
) {
90 Send(new ServiceWorkerHostMsg_FetchEventFinished(
91 GetRoutingID(), request_id
, result
, response
));
94 void ServiceWorkerScriptContext::DidHandleSyncEvent(int request_id
) {
95 Send(new ServiceWorkerHostMsg_SyncEventFinished(
96 GetRoutingID(), request_id
));
99 void ServiceWorkerScriptContext::GetClientDocuments(
100 blink::WebServiceWorkerClientsCallbacks
* callbacks
) {
102 int request_id
= pending_clients_callbacks_
.Add(callbacks
);
103 Send(new ServiceWorkerHostMsg_GetClientDocuments(
104 GetRoutingID(), request_id
));
107 void ServiceWorkerScriptContext::PostMessageToDocument(
109 const base::string16
& message
,
110 scoped_ptr
<blink::WebMessagePortChannelArray
> channels
) {
111 // This may send channels for MessagePorts, and all internal book-keeping
112 // messages for MessagePort (e.g. QueueMessages) are sent from main thread
113 // (with thread hopping), so we need to do the same thread hopping here not
114 // to overtake those messages.
115 embedded_context_
->main_thread_proxy()->PostTask(
117 base::Bind(&SendPostMessageToDocumentOnMainThread
,
118 make_scoped_refptr(embedded_context_
->thread_safe_sender()),
119 GetRoutingID(), client_id
, message
, base::Passed(&channels
)));
122 void ServiceWorkerScriptContext::Send(IPC::Message
* message
) {
123 embedded_context_
->Send(message
);
126 int ServiceWorkerScriptContext::GetRoutingID() const {
127 return embedded_context_
->embedded_worker_id();
130 void ServiceWorkerScriptContext::OnActivateEvent(int request_id
) {
131 proxy_
->dispatchActivateEvent(request_id
);
134 void ServiceWorkerScriptContext::OnInstallEvent(int request_id
,
135 int active_version_id
) {
136 proxy_
->dispatchInstallEvent(request_id
);
139 void ServiceWorkerScriptContext::OnFetchEvent(
141 const ServiceWorkerFetchRequest
& request
) {
142 blink::WebServiceWorkerRequest webRequest
;
143 webRequest
.setURL(blink::WebURL(request
.url
));
144 webRequest
.setMethod(blink::WebString::fromUTF8(request
.method
));
145 for (std::map
<std::string
, std::string
>::const_iterator it
=
146 request
.headers
.begin();
147 it
!= request
.headers
.end();
149 webRequest
.setHeader(blink::WebString::fromUTF8(it
->first
),
150 blink::WebString::fromUTF8(it
->second
));
152 if (!request
.blob_uuid
.empty()) {
153 webRequest
.setBlob(blink::WebString::fromUTF8(request
.blob_uuid
),
156 webRequest
.setReferrer(blink::WebString::fromUTF8(request
.referrer
.spec()),
157 blink::WebReferrerPolicyDefault
);
158 webRequest
.setIsReload(request
.is_reload
);
159 proxy_
->dispatchFetchEvent(request_id
, webRequest
);
162 void ServiceWorkerScriptContext::OnSyncEvent(int request_id
) {
163 proxy_
->dispatchSyncEvent(request_id
);
166 void ServiceWorkerScriptContext::OnPushEvent(int request_id
,
167 const std::string
& data
) {
168 proxy_
->dispatchPushEvent(request_id
, blink::WebString::fromUTF8(data
));
169 Send(new ServiceWorkerHostMsg_PushEventFinished(
170 GetRoutingID(), request_id
));
173 void ServiceWorkerScriptContext::OnPostMessage(
174 const base::string16
& message
,
175 const std::vector
<int>& sent_message_port_ids
,
176 const std::vector
<int>& new_routing_ids
) {
177 std::vector
<WebMessagePortChannelImpl
*> ports
;
178 if (!sent_message_port_ids
.empty()) {
179 base::MessageLoopProxy
* loop_proxy
= embedded_context_
->main_thread_proxy();
180 ports
.resize(sent_message_port_ids
.size());
181 for (size_t i
= 0; i
< sent_message_port_ids
.size(); ++i
) {
182 ports
[i
] = new WebMessagePortChannelImpl(
183 new_routing_ids
[i
], sent_message_port_ids
[i
], loop_proxy
);
187 proxy_
->dispatchMessageEvent(message
, ports
);
190 void ServiceWorkerScriptContext::OnDidGetClientDocuments(
191 int request_id
, const std::vector
<int>& client_ids
) {
192 blink::WebServiceWorkerClientsCallbacks
* callbacks
=
193 pending_clients_callbacks_
.Lookup(request_id
);
195 NOTREACHED() << "Got stray response: " << request_id
;
198 scoped_ptr
<blink::WebServiceWorkerClientsInfo
> info(
199 new blink::WebServiceWorkerClientsInfo
);
200 info
->clientIDs
= client_ids
;
201 callbacks
->onSuccess(info
.release());
202 pending_clients_callbacks_
.Remove(request_id
);
205 } // namespace content