1 // Copyright 2015 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_context_client.h"
7 #include "base/lazy_instance.h"
8 #include "base/logging.h"
9 #include "base/metrics/histogram.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "base/threading/thread_checker.h"
13 #include "base/threading/thread_local.h"
14 #include "base/trace_event/trace_event.h"
15 #include "content/child/navigator_connect/service_port_dispatcher_impl.h"
16 #include "content/child/notifications/notification_data_conversions.h"
17 #include "content/child/request_extra_data.h"
18 #include "content/child/service_worker/service_worker_dispatcher.h"
19 #include "content/child/service_worker/service_worker_network_provider.h"
20 #include "content/child/service_worker/service_worker_provider_context.h"
21 #include "content/child/service_worker/service_worker_registration_handle_reference.h"
22 #include "content/child/service_worker/web_service_worker_impl.h"
23 #include "content/child/service_worker/web_service_worker_provider_impl.h"
24 #include "content/child/service_worker/web_service_worker_registration_impl.h"
25 #include "content/child/thread_safe_sender.h"
26 #include "content/child/webmessageportchannel_impl.h"
27 #include "content/child/worker_task_runner.h"
28 #include "content/common/devtools_messages.h"
29 #include "content/common/message_port_messages.h"
30 #include "content/common/mojo/service_registry_impl.h"
31 #include "content/common/service_worker/embedded_worker_messages.h"
32 #include "content/common/service_worker/service_worker_messages.h"
33 #include "content/public/common/referrer.h"
34 #include "content/public/renderer/document_state.h"
35 #include "content/renderer/background_sync/background_sync_client_impl.h"
36 #include "content/renderer/devtools/devtools_agent.h"
37 #include "content/renderer/render_thread_impl.h"
38 #include "content/renderer/service_worker/embedded_worker_dispatcher.h"
39 #include "content/renderer/service_worker/service_worker_type_util.h"
40 #include "ipc/ipc_message.h"
41 #include "ipc/ipc_message_macros.h"
42 #include "third_party/WebKit/public/platform/WebCrossOriginServiceWorkerClient.h"
43 #include "third_party/WebKit/public/platform/WebMessagePortChannel.h"
44 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
45 #include "third_party/WebKit/public/platform/WebServiceWorkerClientQueryOptions.h"
46 #include "third_party/WebKit/public/platform/WebServiceWorkerRequest.h"
47 #include "third_party/WebKit/public/platform/WebServiceWorkerResponse.h"
48 #include "third_party/WebKit/public/platform/WebString.h"
49 #include "third_party/WebKit/public/platform/modules/background_sync/WebSyncRegistration.h"
50 #include "third_party/WebKit/public/platform/modules/notifications/WebNotificationData.h"
51 #include "third_party/WebKit/public/web/WebDataSource.h"
52 #include "third_party/WebKit/public/web/WebServiceWorkerContextClient.h"
53 #include "third_party/WebKit/public/web/WebServiceWorkerContextProxy.h"
54 #include "third_party/WebKit/public/web/WebServiceWorkerNetworkProvider.h"
60 // For now client must be a per-thread instance.
61 base::LazyInstance
<base::ThreadLocalPointer
<ServiceWorkerContextClient
>>::
62 Leaky g_worker_client_tls
= LAZY_INSTANCE_INITIALIZER
;
64 void CallWorkerContextDestroyedOnMainThread(int embedded_worker_id
) {
65 if (!RenderThreadImpl::current() ||
66 !RenderThreadImpl::current()->embedded_worker_dispatcher())
68 RenderThreadImpl::current()->embedded_worker_dispatcher()->
69 WorkerContextDestroyed(embedded_worker_id
);
72 // We store an instance of this class in the "extra data" of the WebDataSource
73 // and attach a ServiceWorkerNetworkProvider to it as base::UserData.
74 // (see createServiceWorkerNetworkProvider).
75 class DataSourceExtraData
76 : public blink::WebDataSource::ExtraData
,
77 public base::SupportsUserData
{
79 DataSourceExtraData() {}
80 virtual ~DataSourceExtraData() {}
83 // Called on the main thread only and blink owns it.
84 class WebServiceWorkerNetworkProviderImpl
85 : public blink::WebServiceWorkerNetworkProvider
{
87 // Blink calls this method for each request starting with the main script,
88 // we tag them with the provider id.
89 virtual void willSendRequest(
90 blink::WebDataSource
* data_source
,
91 blink::WebURLRequest
& request
) {
92 ServiceWorkerNetworkProvider
* provider
=
93 ServiceWorkerNetworkProvider::FromDocumentState(
94 static_cast<DataSourceExtraData
*>(data_source
->extraData()));
95 scoped_ptr
<RequestExtraData
> extra_data(new RequestExtraData
);
96 extra_data
->set_service_worker_provider_id(provider
->provider_id());
97 request
.setExtraData(extra_data
.release());
101 void SendPostMessageToClientOnMainThread(
102 ThreadSafeSender
* sender
,
104 const std::string
& uuid
,
105 const base::string16
& message
,
106 scoped_ptr
<blink::WebMessagePortChannelArray
> channels
) {
107 sender
->Send(new ServiceWorkerHostMsg_PostMessageToClient(
108 routing_id
, uuid
, message
,
109 WebMessagePortChannelImpl::ExtractMessagePortIDs(channels
.Pass())));
112 void SendCrossOriginMessageToClientOnMainThread(
113 ThreadSafeSender
* sender
,
115 const base::string16
& message
,
116 scoped_ptr
<blink::WebMessagePortChannelArray
> channels
) {
117 sender
->Send(new MessagePortHostMsg_PostMessage(
118 message_port_id
, MessagePortMessage(message
),
119 WebMessagePortChannelImpl::ExtractMessagePortIDs(channels
.Pass())));
122 blink::WebURLRequest::FetchRequestMode
GetBlinkFetchRequestMode(
123 FetchRequestMode mode
) {
124 return static_cast<blink::WebURLRequest::FetchRequestMode
>(mode
);
127 blink::WebURLRequest::FetchCredentialsMode
GetBlinkFetchCredentialsMode(
128 FetchCredentialsMode credentials_mode
) {
129 return static_cast<blink::WebURLRequest::FetchCredentialsMode
>(
133 blink::WebURLRequest::RequestContext
GetBlinkRequestContext(
134 RequestContextType request_context_type
) {
135 return static_cast<blink::WebURLRequest::RequestContext
>(
136 request_context_type
);
139 blink::WebURLRequest::FrameType
GetBlinkFrameType(
140 RequestContextFrameType frame_type
) {
141 return static_cast<blink::WebURLRequest::FrameType
>(frame_type
);
144 blink::WebServiceWorkerClientInfo
145 ToWebServiceWorkerClientInfo(const ServiceWorkerClientInfo
& client_info
) {
146 DCHECK(client_info
.IsValid());
148 blink::WebServiceWorkerClientInfo web_client_info
;
150 web_client_info
.uuid
= base::UTF8ToUTF16(client_info
.client_uuid
);
151 web_client_info
.pageVisibilityState
= client_info
.page_visibility_state
;
152 web_client_info
.isFocused
= client_info
.is_focused
;
153 web_client_info
.url
= client_info
.url
;
154 web_client_info
.frameType
= GetBlinkFrameType(client_info
.frame_type
);
155 web_client_info
.clientType
= client_info
.client_type
;
157 return web_client_info
;
162 // Holding data that needs to be bound to the worker context on the
164 struct ServiceWorkerContextClient::WorkerContextData
{
165 using ClientsCallbacksMap
=
166 IDMap
<blink::WebServiceWorkerClientsCallbacks
, IDMapOwnPointer
>;
167 using ClaimClientsCallbacksMap
=
168 IDMap
<blink::WebServiceWorkerClientsClaimCallbacks
, IDMapOwnPointer
>;
169 using ClientCallbacksMap
=
170 IDMap
<blink::WebServiceWorkerClientCallbacks
, IDMapOwnPointer
>;
171 using SkipWaitingCallbacksMap
=
172 IDMap
<blink::WebServiceWorkerSkipWaitingCallbacks
, IDMapOwnPointer
>;
173 using SyncEventCallbacksMap
=
174 IDMap
<const mojo::Callback
<void(ServiceWorkerEventStatus
)>,
177 explicit WorkerContextData(ServiceWorkerContextClient
* owner
)
178 : weak_factory(owner
), proxy_weak_factory(owner
->proxy_
) {}
180 ~WorkerContextData() {
181 DCHECK(thread_checker
.CalledOnValidThread());
184 // Pending callbacks for GetClientDocuments().
185 ClientsCallbacksMap clients_callbacks
;
187 // Pending callbacks for OpenWindow() and FocusClient().
188 ClientCallbacksMap client_callbacks
;
190 // Pending callbacks for SkipWaiting().
191 SkipWaitingCallbacksMap skip_waiting_callbacks
;
193 // Pending callbacks for ClaimClients().
194 ClaimClientsCallbacksMap claim_clients_callbacks
;
196 // Pending callbacks for Background Sync Events
197 SyncEventCallbacksMap sync_event_callbacks
;
199 ServiceRegistryImpl service_registry
;
201 base::ThreadChecker thread_checker
;
202 base::WeakPtrFactory
<ServiceWorkerContextClient
> weak_factory
;
203 base::WeakPtrFactory
<blink::WebServiceWorkerContextProxy
> proxy_weak_factory
;
206 ServiceWorkerContextClient
*
207 ServiceWorkerContextClient::ThreadSpecificInstance() {
208 return g_worker_client_tls
.Pointer()->Get();
211 ServiceWorkerContextClient::ServiceWorkerContextClient(
212 int embedded_worker_id
,
213 int64 service_worker_version_id
,
214 const GURL
& service_worker_scope
,
215 const GURL
& script_url
,
216 int worker_devtools_agent_route_id
)
217 : embedded_worker_id_(embedded_worker_id
),
218 service_worker_version_id_(service_worker_version_id
),
219 service_worker_scope_(service_worker_scope
),
220 script_url_(script_url
),
221 worker_devtools_agent_route_id_(worker_devtools_agent_route_id
),
222 sender_(ChildThreadImpl::current()->thread_safe_sender()),
223 main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
225 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
226 "ServiceWorkerContextClient::StartingWorkerContext",
228 TRACE_EVENT_ASYNC_STEP_INTO0(
230 "ServiceWorkerContextClient::StartingWorkerContext",
235 ServiceWorkerContextClient::~ServiceWorkerContextClient() {}
237 void ServiceWorkerContextClient::OnMessageReceived(
239 int embedded_worker_id
,
240 const IPC::Message
& message
) {
241 CHECK_EQ(embedded_worker_id_
, embedded_worker_id
);
243 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerContextClient
, message
)
244 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ActivateEvent
, OnActivateEvent
)
245 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FetchEvent
, OnFetchEvent
)
246 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_InstallEvent
, OnInstallEvent
)
247 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_NotificationClickEvent
,
248 OnNotificationClickEvent
)
249 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_PushEvent
, OnPushEvent
)
250 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_GeofencingEvent
, OnGeofencingEvent
)
251 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToWorker
, OnPostMessage
)
252 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CrossOriginMessageToWorker
,
253 OnCrossOriginMessageToWorker
)
254 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetClients
, OnDidGetClients
)
255 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_OpenWindowResponse
,
256 OnOpenWindowResponse
)
257 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_OpenWindowError
,
259 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FocusClientResponse
,
260 OnFocusClientResponse
)
261 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_NavigateClientResponse
,
262 OnNavigateClientResponse
)
263 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_NavigateClientError
,
264 OnNavigateClientError
)
265 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidSkipWaiting
, OnDidSkipWaiting
)
266 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidClaimClients
, OnDidClaimClients
)
267 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ClaimClientsError
, OnClaimClientsError
)
268 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_Ping
, OnPing
);
269 IPC_MESSAGE_UNHANDLED(handled
= false)
270 IPC_END_MESSAGE_MAP()
274 void ServiceWorkerContextClient::BindServiceRegistry(
275 mojo::InterfaceRequest
<mojo::ServiceProvider
> services
,
276 mojo::ServiceProviderPtr exposed_services
) {
277 context_
->service_registry
.Bind(services
.Pass());
278 context_
->service_registry
.BindRemoteServiceProvider(exposed_services
.Pass());
281 blink::WebURL
ServiceWorkerContextClient::scope() const {
282 return service_worker_scope_
;
285 void ServiceWorkerContextClient::getClients(
286 const blink::WebServiceWorkerClientQueryOptions
& weboptions
,
287 blink::WebServiceWorkerClientsCallbacks
* callbacks
) {
289 int request_id
= context_
->clients_callbacks
.Add(callbacks
);
290 ServiceWorkerClientQueryOptions options
;
291 options
.client_type
= weboptions
.clientType
;
292 options
.include_uncontrolled
= weboptions
.includeUncontrolled
;
293 Send(new ServiceWorkerHostMsg_GetClients(
294 GetRoutingID(), request_id
, options
));
297 void ServiceWorkerContextClient::openWindow(
298 const blink::WebURL
& url
,
299 blink::WebServiceWorkerClientCallbacks
* callbacks
) {
301 int request_id
= context_
->client_callbacks
.Add(callbacks
);
302 Send(new ServiceWorkerHostMsg_OpenWindow(
303 GetRoutingID(), request_id
, url
));
306 void ServiceWorkerContextClient::setCachedMetadata(const blink::WebURL
& url
,
309 std::vector
<char> copy(data
, data
+ size
);
310 Send(new ServiceWorkerHostMsg_SetCachedMetadata(GetRoutingID(), url
, copy
));
313 void ServiceWorkerContextClient::clearCachedMetadata(
314 const blink::WebURL
& url
) {
315 Send(new ServiceWorkerHostMsg_ClearCachedMetadata(GetRoutingID(), url
));
318 void ServiceWorkerContextClient::workerReadyForInspection() {
319 Send(new EmbeddedWorkerHostMsg_WorkerReadyForInspection(embedded_worker_id_
));
322 void ServiceWorkerContextClient::workerContextFailedToStart() {
323 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
326 Send(new EmbeddedWorkerHostMsg_WorkerScriptLoadFailed(embedded_worker_id_
));
328 RenderThreadImpl::current()->embedded_worker_dispatcher()->
329 WorkerContextDestroyed(embedded_worker_id_
);
332 void ServiceWorkerContextClient::workerContextStarted(
333 blink::WebServiceWorkerContextProxy
* proxy
) {
334 DCHECK(!worker_task_runner_
.get());
335 DCHECK_NE(0, WorkerTaskRunner::Instance()->CurrentWorkerId());
336 worker_task_runner_
= base::ThreadTaskRunnerHandle::Get();
337 // g_worker_client_tls.Pointer()->Get() could return NULL if this context
338 // gets deleted before workerContextStarted() is called.
339 DCHECK(g_worker_client_tls
.Pointer()->Get() == NULL
);
341 g_worker_client_tls
.Pointer()->Set(this);
344 // Initialize pending callback maps. This needs to be freed on the
345 // same thread before the worker context goes away in
346 // willDestroyWorkerContext.
347 context_
.reset(new WorkerContextData(this));
349 // Register Mojo services.
350 context_
->service_registry
.ServiceRegistry::AddService(
351 base::Bind(&ServicePortDispatcherImpl::Create
,
352 context_
->proxy_weak_factory
.GetWeakPtr()));
353 context_
->service_registry
.ServiceRegistry::AddService(
354 base::Bind(&BackgroundSyncClientImpl::Create
));
356 SetRegistrationInServiceWorkerGlobalScope();
358 Send(new EmbeddedWorkerHostMsg_WorkerScriptLoaded(
360 WorkerTaskRunner::Instance()->CurrentWorkerId(),
361 provider_context_
->provider_id()));
363 TRACE_EVENT_ASYNC_STEP_INTO0(
365 "ServiceWorkerContextClient::StartingWorkerContext",
370 void ServiceWorkerContextClient::didEvaluateWorkerScript(bool success
) {
371 Send(new EmbeddedWorkerHostMsg_WorkerScriptEvaluated(
372 embedded_worker_id_
, success
));
374 // Schedule a task to send back WorkerStarted asynchronously,
375 // so that at the time we send it we can be sure that the
376 // worker run loop has been started.
377 worker_task_runner_
->PostTask(
378 FROM_HERE
, base::Bind(&ServiceWorkerContextClient::SendWorkerStarted
,
382 void ServiceWorkerContextClient::willDestroyWorkerContext() {
383 // At this point OnWorkerRunLoopStopped is already called, so
384 // worker_task_runner_->RunsTasksOnCurrentThread() returns false
385 // (while we're still on the worker thread).
388 // We have to clear callbacks now, as they need to be freed on the
392 // This also lets the message filter stop dispatching messages to
394 g_worker_client_tls
.Pointer()->Set(NULL
);
397 void ServiceWorkerContextClient::workerContextDestroyed() {
398 DCHECK(g_worker_client_tls
.Pointer()->Get() == NULL
);
400 // Now we should be able to free the WebEmbeddedWorker container on the
402 main_thread_task_runner_
->PostTask(
404 base::Bind(&CallWorkerContextDestroyedOnMainThread
,
405 embedded_worker_id_
));
408 void ServiceWorkerContextClient::reportException(
409 const blink::WebString
& error_message
,
412 const blink::WebString
& source_url
) {
413 Send(new EmbeddedWorkerHostMsg_ReportException(
417 column_number
, GURL(source_url
)));
420 void ServiceWorkerContextClient::reportConsoleMessage(
423 const blink::WebString
& message
,
425 const blink::WebString
& source_url
) {
426 EmbeddedWorkerHostMsg_ReportConsoleMessage_Params params
;
427 params
.source_identifier
= source
;
428 params
.message_level
= level
;
429 params
.message
= message
;
430 params
.line_number
= line_number
;
431 params
.source_url
= GURL(source_url
);
433 Send(new EmbeddedWorkerHostMsg_ReportConsoleMessage(
434 embedded_worker_id_
, params
));
437 void ServiceWorkerContextClient::sendDevToolsMessage(
439 const blink::WebString
& message
,
440 const blink::WebString
& state_cookie
) {
441 DevToolsAgent::SendChunkedProtocolMessage(
442 sender_
.get(), worker_devtools_agent_route_id_
,
443 call_id
, message
.utf8(), state_cookie
.utf8());
446 void ServiceWorkerContextClient::didHandleActivateEvent(
448 blink::WebServiceWorkerEventResult result
) {
449 Send(new ServiceWorkerHostMsg_ActivateEventFinished(
450 GetRoutingID(), request_id
, result
));
453 void ServiceWorkerContextClient::didHandleInstallEvent(
455 blink::WebServiceWorkerEventResult result
) {
456 Send(new ServiceWorkerHostMsg_InstallEventFinished(
457 GetRoutingID(), request_id
, result
));
460 void ServiceWorkerContextClient::didHandleFetchEvent(int request_id
) {
461 Send(new ServiceWorkerHostMsg_FetchEventFinished(
462 GetRoutingID(), request_id
,
463 SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK
,
464 ServiceWorkerResponse()));
467 void ServiceWorkerContextClient::didHandleFetchEvent(
469 const blink::WebServiceWorkerResponse
& web_response
) {
470 ServiceWorkerHeaderMap headers
;
471 GetServiceWorkerHeaderMapFromWebResponse(web_response
, &headers
);
472 ServiceWorkerResponse
response(
473 web_response
.url(), web_response
.status(),
474 web_response
.statusText().utf8(), web_response
.responseType(), headers
,
475 web_response
.blobUUID().utf8(), web_response
.blobSize(),
476 web_response
.streamURL(), web_response
.error());
477 Send(new ServiceWorkerHostMsg_FetchEventFinished(
478 GetRoutingID(), request_id
,
479 SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE
,
483 void ServiceWorkerContextClient::didHandleNotificationClickEvent(
485 blink::WebServiceWorkerEventResult result
) {
486 Send(new ServiceWorkerHostMsg_NotificationClickEventFinished(
487 GetRoutingID(), request_id
));
490 void ServiceWorkerContextClient::didHandlePushEvent(
492 blink::WebServiceWorkerEventResult result
) {
493 Send(new ServiceWorkerHostMsg_PushEventFinished(
494 GetRoutingID(), request_id
, result
));
497 void ServiceWorkerContextClient::didHandleSyncEvent(
499 blink::WebServiceWorkerEventResult result
) {
500 const SyncCallback
* callback
=
501 context_
->sync_event_callbacks
.Lookup(request_id
);
504 if (result
== blink::WebServiceWorkerEventResultCompleted
) {
505 callback
->Run(SERVICE_WORKER_EVENT_STATUS_COMPLETED
);
507 callback
->Run(SERVICE_WORKER_EVENT_STATUS_REJECTED
);
509 context_
->sync_event_callbacks
.Remove(request_id
);
512 blink::WebServiceWorkerNetworkProvider
*
513 ServiceWorkerContextClient::createServiceWorkerNetworkProvider(
514 blink::WebDataSource
* data_source
) {
515 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
517 // Create a content::ServiceWorkerNetworkProvider for this data source so
518 // we can observe its requests.
519 scoped_ptr
<ServiceWorkerNetworkProvider
> provider(
520 new ServiceWorkerNetworkProvider(
521 MSG_ROUTING_NONE
, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER
));
522 provider_context_
= provider
->context();
524 // Tell the network provider about which version to load.
525 provider
->SetServiceWorkerVersionId(service_worker_version_id_
);
527 // The provider is kept around for the lifetime of the DataSource
528 // and ownership is transferred to the DataSource.
529 DataSourceExtraData
* extra_data
= new DataSourceExtraData();
530 data_source
->setExtraData(extra_data
);
531 ServiceWorkerNetworkProvider::AttachToDocumentState(
532 extra_data
, provider
.Pass());
534 // Blink is responsible for deleting the returned object.
535 return new WebServiceWorkerNetworkProviderImpl();
538 blink::WebServiceWorkerProvider
*
539 ServiceWorkerContextClient::createServiceWorkerProvider() {
540 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
541 DCHECK(provider_context_
);
543 // Blink is responsible for deleting the returned object.
544 return new WebServiceWorkerProviderImpl(
545 sender_
.get(), provider_context_
.get());
548 void ServiceWorkerContextClient::postMessageToClient(
549 const blink::WebString
& uuid
,
550 const blink::WebString
& message
,
551 blink::WebMessagePortChannelArray
* channels
) {
552 // This may send channels for MessagePorts, and all internal book-keeping
553 // messages for MessagePort (e.g. QueueMessages) are sent from main thread
554 // (with thread hopping), so we need to do the same thread hopping here not
555 // to overtake those messages.
556 scoped_ptr
<blink::WebMessagePortChannelArray
> channel_array(channels
);
557 main_thread_task_runner_
->PostTask(
559 base::Bind(&SendPostMessageToClientOnMainThread
,
562 base::UTF16ToUTF8(base::StringPiece16(uuid
)),
563 static_cast<base::string16
>(message
),
564 base::Passed(&channel_array
)));
567 void ServiceWorkerContextClient::postMessageToCrossOriginClient(
568 const blink::WebCrossOriginServiceWorkerClient
& client
,
569 const blink::WebString
& message
,
570 blink::WebMessagePortChannelArray
* channels
) {
571 // This may send channels for MessagePorts, and all internal book-keeping
572 // messages for MessagePort (e.g. QueueMessages) are sent from main thread
573 // (with thread hopping), so we need to do the same thread hopping here not
574 // to overtake those messages.
575 scoped_ptr
<blink::WebMessagePortChannelArray
> channel_array(channels
);
576 main_thread_task_runner_
->PostTask(
578 base::Bind(&SendCrossOriginMessageToClientOnMainThread
,
579 sender_
, client
.clientID
,
580 static_cast<base::string16
>(message
),
581 base::Passed(&channel_array
)));
584 void ServiceWorkerContextClient::focus(
585 const blink::WebString
& uuid
,
586 blink::WebServiceWorkerClientCallbacks
* callback
) {
588 int request_id
= context_
->client_callbacks
.Add(callback
);
589 Send(new ServiceWorkerHostMsg_FocusClient(
590 GetRoutingID(), request_id
,
591 base::UTF16ToUTF8(base::StringPiece16(uuid
))));
594 void ServiceWorkerContextClient::navigate(
595 const blink::WebString
& uuid
,
596 const blink::WebURL
& url
,
597 blink::WebServiceWorkerClientCallbacks
* callback
) {
599 int request_id
= context_
->client_callbacks
.Add(callback
);
600 Send(new ServiceWorkerHostMsg_NavigateClient(
601 GetRoutingID(), request_id
, base::UTF16ToUTF8(base::StringPiece16(uuid
)),
605 void ServiceWorkerContextClient::skipWaiting(
606 blink::WebServiceWorkerSkipWaitingCallbacks
* callbacks
) {
608 int request_id
= context_
->skip_waiting_callbacks
.Add(callbacks
);
609 Send(new ServiceWorkerHostMsg_SkipWaiting(GetRoutingID(), request_id
));
612 void ServiceWorkerContextClient::claim(
613 blink::WebServiceWorkerClientsClaimCallbacks
* callbacks
) {
615 int request_id
= context_
->claim_clients_callbacks
.Add(callbacks
);
616 Send(new ServiceWorkerHostMsg_ClaimClients(GetRoutingID(), request_id
));
619 void ServiceWorkerContextClient::DispatchSyncEvent(
620 const blink::WebSyncRegistration
& registration
,
621 const SyncCallback
& callback
) {
622 TRACE_EVENT0("ServiceWorker",
623 "ServiceWorkerScriptContext::DispatchSyncEvent");
625 context_
->sync_event_callbacks
.Add(new SyncCallback(callback
));
626 proxy_
->dispatchSyncEvent(request_id
, registration
);
629 void ServiceWorkerContextClient::Send(IPC::Message
* message
) {
630 sender_
->Send(message
);
633 void ServiceWorkerContextClient::SendWorkerStarted() {
634 DCHECK(worker_task_runner_
->RunsTasksOnCurrentThread());
635 TRACE_EVENT_ASYNC_END0("ServiceWorker",
636 "ServiceWorkerContextClient::StartingWorkerContext",
638 Send(new EmbeddedWorkerHostMsg_WorkerStarted(embedded_worker_id_
));
641 void ServiceWorkerContextClient::SetRegistrationInServiceWorkerGlobalScope() {
642 DCHECK(worker_task_runner_
->RunsTasksOnCurrentThread());
643 DCHECK(provider_context_
);
645 ServiceWorkerRegistrationObjectInfo info
;
646 ServiceWorkerVersionAttributes attrs
;
648 provider_context_
->GetRegistrationInfoAndVersionAttributes(&info
, &attrs
);
650 return; // Cannot be associated with a registration in some tests.
652 ServiceWorkerDispatcher
* dispatcher
=
653 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
654 sender_
.get(), main_thread_task_runner_
.get());
656 // Register a registration and its version attributes with the dispatcher
657 // living on the worker thread.
658 scoped_ptr
<WebServiceWorkerRegistrationImpl
> registration(
659 dispatcher
->CreateServiceWorkerRegistration(info
, false));
660 registration
->SetInstalling(
661 dispatcher
->GetServiceWorker(attrs
.installing
, false));
662 registration
->SetWaiting(
663 dispatcher
->GetServiceWorker(attrs
.waiting
, false));
664 registration
->SetActive(
665 dispatcher
->GetServiceWorker(attrs
.active
, false));
667 proxy_
->setRegistration(registration
.release());
670 void ServiceWorkerContextClient::OnActivateEvent(int request_id
) {
671 TRACE_EVENT0("ServiceWorker",
672 "ServiceWorkerContextClient::OnActivateEvent");
673 proxy_
->dispatchActivateEvent(request_id
);
676 void ServiceWorkerContextClient::OnInstallEvent(int request_id
) {
677 TRACE_EVENT0("ServiceWorker",
678 "ServiceWorkerContextClient::OnInstallEvent");
679 proxy_
->dispatchInstallEvent(request_id
);
682 void ServiceWorkerContextClient::OnFetchEvent(
684 const ServiceWorkerFetchRequest
& request
) {
685 blink::WebServiceWorkerRequest webRequest
;
686 TRACE_EVENT0("ServiceWorker",
687 "ServiceWorkerContextClient::OnFetchEvent");
688 webRequest
.setURL(blink::WebURL(request
.url
));
689 webRequest
.setMethod(blink::WebString::fromUTF8(request
.method
));
690 for (ServiceWorkerHeaderMap::const_iterator it
= request
.headers
.begin();
691 it
!= request
.headers
.end();
693 webRequest
.setHeader(blink::WebString::fromUTF8(it
->first
),
694 blink::WebString::fromUTF8(it
->second
));
696 if (!request
.blob_uuid
.empty()) {
697 webRequest
.setBlob(blink::WebString::fromUTF8(request
.blob_uuid
),
700 webRequest
.setReferrer(
701 blink::WebString::fromUTF8(request
.referrer
.url
.spec()),
702 request
.referrer
.policy
);
703 webRequest
.setMode(GetBlinkFetchRequestMode(request
.mode
));
704 webRequest
.setCredentialsMode(
705 GetBlinkFetchCredentialsMode(request
.credentials_mode
));
706 webRequest
.setRequestContext(
707 GetBlinkRequestContext(request
.request_context_type
));
708 webRequest
.setFrameType(GetBlinkFrameType(request
.frame_type
));
709 webRequest
.setIsReload(request
.is_reload
);
710 proxy_
->dispatchFetchEvent(request_id
, webRequest
);
713 void ServiceWorkerContextClient::OnNotificationClickEvent(
715 int64_t persistent_notification_id
,
716 const PlatformNotificationData
& notification_data
) {
717 TRACE_EVENT0("ServiceWorker",
718 "ServiceWorkerContextClient::OnNotificationClickEvent");
719 proxy_
->dispatchNotificationClickEvent(
721 persistent_notification_id
,
722 ToWebNotificationData(notification_data
));
725 void ServiceWorkerContextClient::OnPushEvent(int request_id
,
726 const std::string
& data
) {
727 TRACE_EVENT0("ServiceWorker",
728 "ServiceWorkerContextClient::OnPushEvent");
729 proxy_
->dispatchPushEvent(request_id
, blink::WebString::fromUTF8(data
));
732 void ServiceWorkerContextClient::OnGeofencingEvent(
734 blink::WebGeofencingEventType event_type
,
735 const std::string
& region_id
,
736 const blink::WebCircularGeofencingRegion
& region
) {
737 TRACE_EVENT0("ServiceWorker",
738 "ServiceWorkerContextClient::OnGeofencingEvent");
739 proxy_
->dispatchGeofencingEvent(
740 request_id
, event_type
, blink::WebString::fromUTF8(region_id
), region
);
741 Send(new ServiceWorkerHostMsg_GeofencingEventFinished(GetRoutingID(),
745 void ServiceWorkerContextClient::OnPostMessage(
746 const base::string16
& message
,
747 const std::vector
<TransferredMessagePort
>& sent_message_ports
,
748 const std::vector
<int>& new_routing_ids
) {
749 TRACE_EVENT0("ServiceWorker",
750 "ServiceWorkerContextClient::OnPostEvent");
751 blink::WebMessagePortChannelArray ports
=
752 WebMessagePortChannelImpl::CreatePorts(
753 sent_message_ports
, new_routing_ids
,
754 main_thread_task_runner_
);
756 // dispatchMessageEvent is expected to execute onmessage function
758 base::TimeTicks before
= base::TimeTicks::Now();
759 proxy_
->dispatchMessageEvent(message
, ports
);
760 UMA_HISTOGRAM_MEDIUM_TIMES(
761 "ServiceWorker.MessageEvent.Time",
762 base::TimeTicks::Now() - before
);
765 void ServiceWorkerContextClient::OnCrossOriginMessageToWorker(
766 const NavigatorConnectClient
& client
,
767 const base::string16
& message
,
768 const std::vector
<TransferredMessagePort
>& sent_message_ports
,
769 const std::vector
<int>& new_routing_ids
) {
770 TRACE_EVENT0("ServiceWorker",
771 "ServiceWorkerContextClient::OnCrossOriginMessageToWorker");
772 blink::WebMessagePortChannelArray ports
=
773 WebMessagePortChannelImpl::CreatePorts(
774 sent_message_ports
, new_routing_ids
,
775 main_thread_task_runner_
);
777 blink::WebCrossOriginServiceWorkerClient web_client
;
778 web_client
.origin
= client
.origin
;
779 web_client
.targetURL
= client
.target_url
;
780 web_client
.clientID
= client
.message_port_id
;
781 proxy_
->dispatchCrossOriginMessageEvent(web_client
, message
, ports
);
784 void ServiceWorkerContextClient::OnDidGetClients(
785 int request_id
, const std::vector
<ServiceWorkerClientInfo
>& clients
) {
786 TRACE_EVENT0("ServiceWorker",
787 "ServiceWorkerContextClient::OnDidGetClients");
788 blink::WebServiceWorkerClientsCallbacks
* callbacks
=
789 context_
->clients_callbacks
.Lookup(request_id
);
791 NOTREACHED() << "Got stray response: " << request_id
;
794 scoped_ptr
<blink::WebServiceWorkerClientsInfo
> info(
795 new blink::WebServiceWorkerClientsInfo
);
796 blink::WebVector
<blink::WebServiceWorkerClientInfo
> convertedClients(
798 for (size_t i
= 0; i
< clients
.size(); ++i
)
799 convertedClients
[i
] = ToWebServiceWorkerClientInfo(clients
[i
]);
800 info
->clients
.swap(convertedClients
);
801 callbacks
->onSuccess(info
.release());
802 context_
->clients_callbacks
.Remove(request_id
);
805 void ServiceWorkerContextClient::OnOpenWindowResponse(
807 const ServiceWorkerClientInfo
& client
) {
808 TRACE_EVENT0("ServiceWorker",
809 "ServiceWorkerContextClient::OnOpenWindowResponse");
810 blink::WebServiceWorkerClientCallbacks
* callbacks
=
811 context_
->client_callbacks
.Lookup(request_id
);
813 NOTREACHED() << "Got stray response: " << request_id
;
816 scoped_ptr
<blink::WebServiceWorkerClientInfo
> web_client
;
817 if (!client
.IsEmpty()) {
818 DCHECK(client
.IsValid());
819 web_client
.reset(new blink::WebServiceWorkerClientInfo(
820 ToWebServiceWorkerClientInfo(client
)));
822 callbacks
->onSuccess(web_client
.release());
823 context_
->client_callbacks
.Remove(request_id
);
826 void ServiceWorkerContextClient::OnOpenWindowError(
828 const std::string
& message
) {
829 TRACE_EVENT0("ServiceWorker",
830 "ServiceWorkerContextClient::OnOpenWindowError");
831 blink::WebServiceWorkerClientCallbacks
* callbacks
=
832 context_
->client_callbacks
.Lookup(request_id
);
834 NOTREACHED() << "Got stray response: " << request_id
;
837 scoped_ptr
<blink::WebServiceWorkerError
> error(
838 new blink::WebServiceWorkerError(
839 blink::WebServiceWorkerError::ErrorTypeUnknown
,
840 blink::WebString::fromUTF8(message
)));
841 callbacks
->onError(error
.release());
842 context_
->client_callbacks
.Remove(request_id
);
845 void ServiceWorkerContextClient::OnFocusClientResponse(
846 int request_id
, const ServiceWorkerClientInfo
& client
) {
847 TRACE_EVENT0("ServiceWorker",
848 "ServiceWorkerContextClient::OnFocusClientResponse");
849 blink::WebServiceWorkerClientCallbacks
* callback
=
850 context_
->client_callbacks
.Lookup(request_id
);
852 NOTREACHED() << "Got stray response: " << request_id
;
855 if (!client
.IsEmpty()) {
856 DCHECK(client
.IsValid());
857 scoped_ptr
<blink::WebServiceWorkerClientInfo
> web_client (
858 new blink::WebServiceWorkerClientInfo(
859 ToWebServiceWorkerClientInfo(client
)));
860 callback
->onSuccess(web_client
.release());
862 scoped_ptr
<blink::WebServiceWorkerError
> error(
863 new blink::WebServiceWorkerError(
864 blink::WebServiceWorkerError::ErrorTypeNotFound
,
865 "The WindowClient was not found."));
866 callback
->onError(error
.release());
869 context_
->client_callbacks
.Remove(request_id
);
872 void ServiceWorkerContextClient::OnNavigateClientResponse(
874 const ServiceWorkerClientInfo
& client
) {
875 TRACE_EVENT0("ServiceWorker",
876 "ServiceWorkerContextClient::OnNavigateClientResponse");
877 blink::WebServiceWorkerClientCallbacks
* callbacks
=
878 context_
->client_callbacks
.Lookup(request_id
);
880 NOTREACHED() << "Got stray response: " << request_id
;
883 scoped_ptr
<blink::WebServiceWorkerClientInfo
> web_client
;
884 if (!client
.IsEmpty()) {
885 DCHECK(client
.IsValid());
886 web_client
.reset(new blink::WebServiceWorkerClientInfo(
887 ToWebServiceWorkerClientInfo(client
)));
889 callbacks
->onSuccess(web_client
.release());
890 context_
->client_callbacks
.Remove(request_id
);
893 void ServiceWorkerContextClient::OnNavigateClientError(int request_id
,
895 TRACE_EVENT0("ServiceWorker",
896 "ServiceWorkerContextClient::OnNavigateClientError");
897 blink::WebServiceWorkerClientCallbacks
* callbacks
=
898 context_
->client_callbacks
.Lookup(request_id
);
900 NOTREACHED() << "Got stray response: " << request_id
;
903 std::string message
= "Cannot navigate to URL: " + url
.spec();
904 scoped_ptr
<blink::WebServiceWorkerError
> error(
905 new blink::WebServiceWorkerError(
906 blink::WebServiceWorkerError::ErrorTypeUnknown
,
907 blink::WebString::fromUTF8(message
)));
908 callbacks
->onError(error
.release());
909 context_
->client_callbacks
.Remove(request_id
);
912 void ServiceWorkerContextClient::OnDidSkipWaiting(int request_id
) {
913 TRACE_EVENT0("ServiceWorker",
914 "ServiceWorkerContextClient::OnDidSkipWaiting");
915 blink::WebServiceWorkerSkipWaitingCallbacks
* callbacks
=
916 context_
->skip_waiting_callbacks
.Lookup(request_id
);
918 NOTREACHED() << "Got stray response: " << request_id
;
921 callbacks
->onSuccess();
922 context_
->skip_waiting_callbacks
.Remove(request_id
);
925 void ServiceWorkerContextClient::OnDidClaimClients(int request_id
) {
926 TRACE_EVENT0("ServiceWorker",
927 "ServiceWorkerContextClient::OnDidClaimClients");
928 blink::WebServiceWorkerClientsClaimCallbacks
* callbacks
=
929 context_
->claim_clients_callbacks
.Lookup(request_id
);
931 NOTREACHED() << "Got stray response: " << request_id
;
934 callbacks
->onSuccess();
935 context_
->claim_clients_callbacks
.Remove(request_id
);
938 void ServiceWorkerContextClient::OnClaimClientsError(
940 blink::WebServiceWorkerError::ErrorType error_type
,
941 const base::string16
& message
) {
942 TRACE_EVENT0("ServiceWorker",
943 "ServiceWorkerContextClient::OnClaimClientsError");
944 blink::WebServiceWorkerClientsClaimCallbacks
* callbacks
=
945 context_
->claim_clients_callbacks
.Lookup(request_id
);
947 NOTREACHED() << "Got stray response: " << request_id
;
950 scoped_ptr
<blink::WebServiceWorkerError
> error(
951 new blink::WebServiceWorkerError(error_type
, message
));
952 callbacks
->onError(error
.release());
953 context_
->claim_clients_callbacks
.Remove(request_id
);
956 void ServiceWorkerContextClient::OnPing() {
957 Send(new ServiceWorkerHostMsg_Pong(GetRoutingID()));
960 base::WeakPtr
<ServiceWorkerContextClient
>
961 ServiceWorkerContextClient::GetWeakPtr() {
962 DCHECK(worker_task_runner_
->RunsTasksOnCurrentThread());
964 return context_
->weak_factory
.GetWeakPtr();
967 } // namespace content