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/content_renderer_client.h"
35 #include "content/public/renderer/document_state.h"
36 #include "content/renderer/background_sync/background_sync_client_impl.h"
37 #include "content/renderer/devtools/devtools_agent.h"
38 #include "content/renderer/render_thread_impl.h"
39 #include "content/renderer/service_worker/embedded_worker_dispatcher.h"
40 #include "content/renderer/service_worker/service_worker_type_util.h"
41 #include "ipc/ipc_message.h"
42 #include "ipc/ipc_message_macros.h"
43 #include "third_party/WebKit/public/platform/WebCrossOriginServiceWorkerClient.h"
44 #include "third_party/WebKit/public/platform/WebMessagePortChannel.h"
45 #include "third_party/WebKit/public/platform/WebPassOwnPtr.h"
46 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
47 #include "third_party/WebKit/public/platform/WebString.h"
48 #include "third_party/WebKit/public/platform/modules/background_sync/WebSyncRegistration.h"
49 #include "third_party/WebKit/public/platform/modules/notifications/WebNotificationData.h"
50 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerClientQueryOptions.h"
51 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerRequest.h"
52 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponse.h"
53 #include "third_party/WebKit/public/web/WebDataSource.h"
54 #include "third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h"
55 #include "third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextProxy.h"
56 #include "third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerNetworkProvider.h"
62 // For now client must be a per-thread instance.
63 base::LazyInstance
<base::ThreadLocalPointer
<ServiceWorkerContextClient
>>::
64 Leaky g_worker_client_tls
= LAZY_INSTANCE_INITIALIZER
;
66 void CallWorkerContextDestroyedOnMainThread(int embedded_worker_id
) {
67 if (!RenderThreadImpl::current() ||
68 !RenderThreadImpl::current()->embedded_worker_dispatcher())
70 RenderThreadImpl::current()->embedded_worker_dispatcher()->
71 WorkerContextDestroyed(embedded_worker_id
);
74 // We store an instance of this class in the "extra data" of the WebDataSource
75 // and attach a ServiceWorkerNetworkProvider to it as base::UserData.
76 // (see createServiceWorkerNetworkProvider).
77 class DataSourceExtraData
78 : public blink::WebDataSource::ExtraData
,
79 public base::SupportsUserData
{
81 DataSourceExtraData() {}
82 virtual ~DataSourceExtraData() {}
85 // Called on the main thread only and blink owns it.
86 class WebServiceWorkerNetworkProviderImpl
87 : public blink::WebServiceWorkerNetworkProvider
{
89 // Blink calls this method for each request starting with the main script,
90 // we tag them with the provider id.
91 virtual void willSendRequest(
92 blink::WebDataSource
* data_source
,
93 blink::WebURLRequest
& request
) {
94 ServiceWorkerNetworkProvider
* provider
=
95 ServiceWorkerNetworkProvider::FromDocumentState(
96 static_cast<DataSourceExtraData
*>(data_source
->extraData()));
97 scoped_ptr
<RequestExtraData
> extra_data(new RequestExtraData
);
98 extra_data
->set_service_worker_provider_id(provider
->provider_id());
99 request
.setExtraData(extra_data
.release());
103 void SendPostMessageToClientOnMainThread(
104 ThreadSafeSender
* sender
,
106 const std::string
& uuid
,
107 const base::string16
& message
,
108 scoped_ptr
<blink::WebMessagePortChannelArray
> channels
) {
109 sender
->Send(new ServiceWorkerHostMsg_PostMessageToClient(
110 routing_id
, uuid
, message
,
111 WebMessagePortChannelImpl::ExtractMessagePortIDs(channels
.Pass())));
114 void SendCrossOriginMessageToClientOnMainThread(
115 ThreadSafeSender
* sender
,
117 const base::string16
& message
,
118 scoped_ptr
<blink::WebMessagePortChannelArray
> channels
) {
119 sender
->Send(new MessagePortHostMsg_PostMessage(
120 message_port_id
, MessagePortMessage(message
),
121 WebMessagePortChannelImpl::ExtractMessagePortIDs(channels
.Pass())));
124 blink::WebURLRequest::FetchRequestMode
GetBlinkFetchRequestMode(
125 FetchRequestMode mode
) {
126 return static_cast<blink::WebURLRequest::FetchRequestMode
>(mode
);
129 blink::WebURLRequest::FetchCredentialsMode
GetBlinkFetchCredentialsMode(
130 FetchCredentialsMode credentials_mode
) {
131 return static_cast<blink::WebURLRequest::FetchCredentialsMode
>(
135 blink::WebURLRequest::FetchRedirectMode
GetBlinkFetchRedirectMode(
136 FetchRedirectMode redirect_mode
) {
137 return static_cast<blink::WebURLRequest::FetchRedirectMode
>(redirect_mode
);
140 blink::WebURLRequest::RequestContext
GetBlinkRequestContext(
141 RequestContextType request_context_type
) {
142 return static_cast<blink::WebURLRequest::RequestContext
>(
143 request_context_type
);
146 blink::WebURLRequest::FrameType
GetBlinkFrameType(
147 RequestContextFrameType frame_type
) {
148 return static_cast<blink::WebURLRequest::FrameType
>(frame_type
);
151 blink::WebServiceWorkerClientInfo
152 ToWebServiceWorkerClientInfo(const ServiceWorkerClientInfo
& client_info
) {
153 DCHECK(client_info
.IsValid());
155 blink::WebServiceWorkerClientInfo web_client_info
;
157 web_client_info
.uuid
= base::UTF8ToUTF16(client_info
.client_uuid
);
158 web_client_info
.pageVisibilityState
= client_info
.page_visibility_state
;
159 web_client_info
.isFocused
= client_info
.is_focused
;
160 web_client_info
.url
= client_info
.url
;
161 web_client_info
.frameType
= GetBlinkFrameType(client_info
.frame_type
);
162 web_client_info
.clientType
= client_info
.client_type
;
164 return web_client_info
;
169 // Holding data that needs to be bound to the worker context on the
171 struct ServiceWorkerContextClient::WorkerContextData
{
172 using ClientsCallbacksMap
=
173 IDMap
<blink::WebServiceWorkerClientsCallbacks
, IDMapOwnPointer
>;
174 using ClaimClientsCallbacksMap
=
175 IDMap
<blink::WebServiceWorkerClientsClaimCallbacks
, IDMapOwnPointer
>;
176 using ClientCallbacksMap
=
177 IDMap
<blink::WebServiceWorkerClientCallbacks
, IDMapOwnPointer
>;
178 using SkipWaitingCallbacksMap
=
179 IDMap
<blink::WebServiceWorkerSkipWaitingCallbacks
, IDMapOwnPointer
>;
180 using SyncEventCallbacksMap
=
181 IDMap
<const mojo::Callback
<void(ServiceWorkerEventStatus
)>,
184 explicit WorkerContextData(ServiceWorkerContextClient
* owner
)
185 : weak_factory(owner
), proxy_weak_factory(owner
->proxy_
) {}
187 ~WorkerContextData() {
188 DCHECK(thread_checker
.CalledOnValidThread());
191 // Pending callbacks for GetClientDocuments().
192 ClientsCallbacksMap clients_callbacks
;
194 // Pending callbacks for OpenWindow() and FocusClient().
195 ClientCallbacksMap client_callbacks
;
197 // Pending callbacks for SkipWaiting().
198 SkipWaitingCallbacksMap skip_waiting_callbacks
;
200 // Pending callbacks for ClaimClients().
201 ClaimClientsCallbacksMap claim_clients_callbacks
;
203 // Pending callbacks for Background Sync Events
204 SyncEventCallbacksMap sync_event_callbacks
;
206 ServiceRegistryImpl service_registry
;
208 base::ThreadChecker thread_checker
;
209 base::WeakPtrFactory
<ServiceWorkerContextClient
> weak_factory
;
210 base::WeakPtrFactory
<blink::WebServiceWorkerContextProxy
> proxy_weak_factory
;
213 ServiceWorkerContextClient
*
214 ServiceWorkerContextClient::ThreadSpecificInstance() {
215 return g_worker_client_tls
.Pointer()->Get();
218 ServiceWorkerContextClient::ServiceWorkerContextClient(
219 int embedded_worker_id
,
220 int64 service_worker_version_id
,
221 const GURL
& service_worker_scope
,
222 const GURL
& script_url
,
223 int worker_devtools_agent_route_id
)
224 : embedded_worker_id_(embedded_worker_id
),
225 service_worker_version_id_(service_worker_version_id
),
226 service_worker_scope_(service_worker_scope
),
227 script_url_(script_url
),
228 worker_devtools_agent_route_id_(worker_devtools_agent_route_id
),
229 sender_(ChildThreadImpl::current()->thread_safe_sender()),
230 main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
232 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
233 "ServiceWorkerContextClient::StartingWorkerContext",
235 TRACE_EVENT_ASYNC_STEP_INTO0(
237 "ServiceWorkerContextClient::StartingWorkerContext",
242 ServiceWorkerContextClient::~ServiceWorkerContextClient() {}
244 void ServiceWorkerContextClient::OnMessageReceived(
246 int embedded_worker_id
,
247 const IPC::Message
& message
) {
248 CHECK_EQ(embedded_worker_id_
, embedded_worker_id
);
250 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerContextClient
, message
)
251 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ActivateEvent
, OnActivateEvent
)
252 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FetchEvent
, OnFetchEvent
)
253 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_InstallEvent
, OnInstallEvent
)
254 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_NotificationClickEvent
,
255 OnNotificationClickEvent
)
256 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_PushEvent
, OnPushEvent
)
257 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_GeofencingEvent
, OnGeofencingEvent
)
258 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToWorker
, OnPostMessage
)
259 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CrossOriginMessageToWorker
,
260 OnCrossOriginMessageToWorker
)
261 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetClients
, OnDidGetClients
)
262 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_OpenWindowResponse
,
263 OnOpenWindowResponse
)
264 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_OpenWindowError
,
266 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FocusClientResponse
,
267 OnFocusClientResponse
)
268 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_NavigateClientResponse
,
269 OnNavigateClientResponse
)
270 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_NavigateClientError
,
271 OnNavigateClientError
)
272 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidSkipWaiting
, OnDidSkipWaiting
)
273 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidClaimClients
, OnDidClaimClients
)
274 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ClaimClientsError
, OnClaimClientsError
)
275 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_Ping
, OnPing
);
276 IPC_MESSAGE_UNHANDLED(handled
= false)
277 IPC_END_MESSAGE_MAP()
281 void ServiceWorkerContextClient::BindServiceRegistry(
282 mojo::InterfaceRequest
<mojo::ServiceProvider
> services
,
283 mojo::ServiceProviderPtr exposed_services
) {
284 context_
->service_registry
.Bind(services
.Pass());
285 context_
->service_registry
.BindRemoteServiceProvider(exposed_services
.Pass());
288 blink::WebURL
ServiceWorkerContextClient::scope() const {
289 return service_worker_scope_
;
292 void ServiceWorkerContextClient::getClients(
293 const blink::WebServiceWorkerClientQueryOptions
& weboptions
,
294 blink::WebServiceWorkerClientsCallbacks
* callbacks
) {
296 int request_id
= context_
->clients_callbacks
.Add(callbacks
);
297 ServiceWorkerClientQueryOptions options
;
298 options
.client_type
= weboptions
.clientType
;
299 options
.include_uncontrolled
= weboptions
.includeUncontrolled
;
300 Send(new ServiceWorkerHostMsg_GetClients(
301 GetRoutingID(), request_id
, options
));
304 void ServiceWorkerContextClient::openWindow(
305 const blink::WebURL
& url
,
306 blink::WebServiceWorkerClientCallbacks
* callbacks
) {
308 int request_id
= context_
->client_callbacks
.Add(callbacks
);
309 Send(new ServiceWorkerHostMsg_OpenWindow(
310 GetRoutingID(), request_id
, url
));
313 void ServiceWorkerContextClient::setCachedMetadata(const blink::WebURL
& url
,
316 std::vector
<char> copy(data
, data
+ size
);
317 Send(new ServiceWorkerHostMsg_SetCachedMetadata(GetRoutingID(), url
, copy
));
320 void ServiceWorkerContextClient::clearCachedMetadata(
321 const blink::WebURL
& url
) {
322 Send(new ServiceWorkerHostMsg_ClearCachedMetadata(GetRoutingID(), url
));
325 void ServiceWorkerContextClient::workerReadyForInspection() {
326 Send(new EmbeddedWorkerHostMsg_WorkerReadyForInspection(embedded_worker_id_
));
329 void ServiceWorkerContextClient::workerContextFailedToStart() {
330 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
333 Send(new EmbeddedWorkerHostMsg_WorkerScriptLoadFailed(embedded_worker_id_
));
335 RenderThreadImpl::current()->embedded_worker_dispatcher()->
336 WorkerContextDestroyed(embedded_worker_id_
);
339 void ServiceWorkerContextClient::workerContextStarted(
340 blink::WebServiceWorkerContextProxy
* proxy
) {
341 DCHECK(!worker_task_runner_
.get());
342 DCHECK_NE(0, WorkerTaskRunner::Instance()->CurrentWorkerId());
343 worker_task_runner_
= base::ThreadTaskRunnerHandle::Get();
344 // g_worker_client_tls.Pointer()->Get() could return NULL if this context
345 // gets deleted before workerContextStarted() is called.
346 DCHECK(g_worker_client_tls
.Pointer()->Get() == NULL
);
348 g_worker_client_tls
.Pointer()->Set(this);
351 // Initialize pending callback maps. This needs to be freed on the
352 // same thread before the worker context goes away in
353 // willDestroyWorkerContext.
354 context_
.reset(new WorkerContextData(this));
356 // Register Mojo services.
357 context_
->service_registry
.ServiceRegistry::AddService(
358 base::Bind(&ServicePortDispatcherImpl::Create
,
359 context_
->proxy_weak_factory
.GetWeakPtr()));
360 context_
->service_registry
.ServiceRegistry::AddService(
361 base::Bind(&BackgroundSyncClientImpl::Create
));
363 SetRegistrationInServiceWorkerGlobalScope();
365 Send(new EmbeddedWorkerHostMsg_WorkerScriptLoaded(
367 WorkerTaskRunner::Instance()->CurrentWorkerId(),
368 provider_context_
->provider_id()));
370 TRACE_EVENT_ASYNC_STEP_INTO0(
372 "ServiceWorkerContextClient::StartingWorkerContext",
377 void ServiceWorkerContextClient::didEvaluateWorkerScript(bool success
) {
378 Send(new EmbeddedWorkerHostMsg_WorkerScriptEvaluated(
379 embedded_worker_id_
, success
));
381 // Schedule a task to send back WorkerStarted asynchronously,
382 // so that at the time we send it we can be sure that the
383 // worker run loop has been started.
384 worker_task_runner_
->PostTask(
385 FROM_HERE
, base::Bind(&ServiceWorkerContextClient::SendWorkerStarted
,
389 void ServiceWorkerContextClient::didInitializeWorkerContext(
390 v8::Local
<v8::Context
> context
,
391 const blink::WebURL
& url
) {
392 // TODO(annekao): Remove WebURL parameter from Blink (since url and script_url
393 // are equal). Also remove m_documentURL from ServiceWorkerGlobalScopeProxy.
394 DCHECK_EQ(script_url_
, GURL(url
));
397 ->DidInitializeServiceWorkerContextOnWorkerThread(context
, script_url_
);
400 void ServiceWorkerContextClient::willDestroyWorkerContext() {
401 // At this point OnWorkerRunLoopStopped is already called, so
402 // worker_task_runner_->RunsTasksOnCurrentThread() returns false
403 // (while we're still on the worker thread).
406 // We have to clear callbacks now, as they need to be freed on the
410 // This also lets the message filter stop dispatching messages to
412 g_worker_client_tls
.Pointer()->Set(NULL
);
414 GetContentClient()->renderer()->WillDestroyServiceWorkerContextOnWorkerThread(
418 void ServiceWorkerContextClient::workerContextDestroyed() {
419 DCHECK(g_worker_client_tls
.Pointer()->Get() == NULL
);
421 // Now we should be able to free the WebEmbeddedWorker container on the
423 main_thread_task_runner_
->PostTask(
425 base::Bind(&CallWorkerContextDestroyedOnMainThread
,
426 embedded_worker_id_
));
429 void ServiceWorkerContextClient::reportException(
430 const blink::WebString
& error_message
,
433 const blink::WebString
& source_url
) {
434 Send(new EmbeddedWorkerHostMsg_ReportException(
438 column_number
, GURL(source_url
)));
441 void ServiceWorkerContextClient::reportConsoleMessage(
444 const blink::WebString
& message
,
446 const blink::WebString
& source_url
) {
447 EmbeddedWorkerHostMsg_ReportConsoleMessage_Params params
;
448 params
.source_identifier
= source
;
449 params
.message_level
= level
;
450 params
.message
= message
;
451 params
.line_number
= line_number
;
452 params
.source_url
= GURL(source_url
);
454 Send(new EmbeddedWorkerHostMsg_ReportConsoleMessage(
455 embedded_worker_id_
, params
));
458 void ServiceWorkerContextClient::sendDevToolsMessage(
460 const blink::WebString
& message
,
461 const blink::WebString
& state_cookie
) {
462 DevToolsAgent::SendChunkedProtocolMessage(
463 sender_
.get(), worker_devtools_agent_route_id_
,
464 call_id
, message
.utf8(), state_cookie
.utf8());
467 void ServiceWorkerContextClient::didHandleActivateEvent(
469 blink::WebServiceWorkerEventResult result
) {
470 Send(new ServiceWorkerHostMsg_ActivateEventFinished(
471 GetRoutingID(), request_id
, result
));
474 void ServiceWorkerContextClient::didHandleInstallEvent(
476 blink::WebServiceWorkerEventResult result
) {
477 Send(new ServiceWorkerHostMsg_InstallEventFinished(
478 GetRoutingID(), request_id
, result
));
481 void ServiceWorkerContextClient::didHandleFetchEvent(int request_id
) {
482 Send(new ServiceWorkerHostMsg_FetchEventFinished(
483 GetRoutingID(), request_id
,
484 SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK
,
485 ServiceWorkerResponse()));
488 void ServiceWorkerContextClient::didHandleFetchEvent(
490 const blink::WebServiceWorkerResponse
& web_response
) {
491 ServiceWorkerHeaderMap headers
;
492 GetServiceWorkerHeaderMapFromWebResponse(web_response
, &headers
);
493 ServiceWorkerResponse
response(
494 web_response
.url(), web_response
.status(),
495 web_response
.statusText().utf8(), web_response
.responseType(), headers
,
496 web_response
.blobUUID().utf8(), web_response
.blobSize(),
497 web_response
.streamURL(), web_response
.error());
498 Send(new ServiceWorkerHostMsg_FetchEventFinished(
499 GetRoutingID(), request_id
,
500 SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE
,
504 void ServiceWorkerContextClient::didHandleNotificationClickEvent(
506 blink::WebServiceWorkerEventResult result
) {
507 Send(new ServiceWorkerHostMsg_NotificationClickEventFinished(
508 GetRoutingID(), request_id
));
511 void ServiceWorkerContextClient::didHandlePushEvent(
513 blink::WebServiceWorkerEventResult result
) {
514 Send(new ServiceWorkerHostMsg_PushEventFinished(
515 GetRoutingID(), request_id
, result
));
518 void ServiceWorkerContextClient::didHandleSyncEvent(
520 blink::WebServiceWorkerEventResult result
) {
521 const SyncCallback
* callback
=
522 context_
->sync_event_callbacks
.Lookup(request_id
);
525 if (result
== blink::WebServiceWorkerEventResultCompleted
) {
526 callback
->Run(SERVICE_WORKER_EVENT_STATUS_COMPLETED
);
528 callback
->Run(SERVICE_WORKER_EVENT_STATUS_REJECTED
);
530 context_
->sync_event_callbacks
.Remove(request_id
);
533 blink::WebServiceWorkerNetworkProvider
*
534 ServiceWorkerContextClient::createServiceWorkerNetworkProvider(
535 blink::WebDataSource
* data_source
) {
536 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
538 // Create a content::ServiceWorkerNetworkProvider for this data source so
539 // we can observe its requests.
540 scoped_ptr
<ServiceWorkerNetworkProvider
> provider(
541 new ServiceWorkerNetworkProvider(
542 MSG_ROUTING_NONE
, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER
));
543 provider_context_
= provider
->context();
545 // Tell the network provider about which version to load.
546 provider
->SetServiceWorkerVersionId(service_worker_version_id_
);
548 // The provider is kept around for the lifetime of the DataSource
549 // and ownership is transferred to the DataSource.
550 DataSourceExtraData
* extra_data
= new DataSourceExtraData();
551 data_source
->setExtraData(extra_data
);
552 ServiceWorkerNetworkProvider::AttachToDocumentState(
553 extra_data
, provider
.Pass());
555 // Blink is responsible for deleting the returned object.
556 return new WebServiceWorkerNetworkProviderImpl();
559 blink::WebServiceWorkerProvider
*
560 ServiceWorkerContextClient::createServiceWorkerProvider() {
561 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
562 DCHECK(provider_context_
);
564 // Blink is responsible for deleting the returned object.
565 return new WebServiceWorkerProviderImpl(
566 sender_
.get(), provider_context_
.get());
569 void ServiceWorkerContextClient::postMessageToClient(
570 const blink::WebString
& uuid
,
571 const blink::WebString
& message
,
572 blink::WebMessagePortChannelArray
* channels
) {
573 // This may send channels for MessagePorts, and all internal book-keeping
574 // messages for MessagePort (e.g. QueueMessages) are sent from main thread
575 // (with thread hopping), so we need to do the same thread hopping here not
576 // to overtake those messages.
577 scoped_ptr
<blink::WebMessagePortChannelArray
> channel_array(channels
);
578 main_thread_task_runner_
->PostTask(
580 base::Bind(&SendPostMessageToClientOnMainThread
,
583 base::UTF16ToUTF8(base::StringPiece16(uuid
)),
584 static_cast<base::string16
>(message
),
585 base::Passed(&channel_array
)));
588 void ServiceWorkerContextClient::postMessageToCrossOriginClient(
589 const blink::WebCrossOriginServiceWorkerClient
& client
,
590 const blink::WebString
& message
,
591 blink::WebMessagePortChannelArray
* channels
) {
592 // This may send channels for MessagePorts, and all internal book-keeping
593 // messages for MessagePort (e.g. QueueMessages) are sent from main thread
594 // (with thread hopping), so we need to do the same thread hopping here not
595 // to overtake those messages.
596 scoped_ptr
<blink::WebMessagePortChannelArray
> channel_array(channels
);
597 main_thread_task_runner_
->PostTask(
599 base::Bind(&SendCrossOriginMessageToClientOnMainThread
,
600 sender_
, client
.clientID
,
601 static_cast<base::string16
>(message
),
602 base::Passed(&channel_array
)));
605 void ServiceWorkerContextClient::focus(
606 const blink::WebString
& uuid
,
607 blink::WebServiceWorkerClientCallbacks
* callback
) {
609 int request_id
= context_
->client_callbacks
.Add(callback
);
610 Send(new ServiceWorkerHostMsg_FocusClient(
611 GetRoutingID(), request_id
,
612 base::UTF16ToUTF8(base::StringPiece16(uuid
))));
615 void ServiceWorkerContextClient::navigate(
616 const blink::WebString
& uuid
,
617 const blink::WebURL
& url
,
618 blink::WebServiceWorkerClientCallbacks
* callback
) {
620 int request_id
= context_
->client_callbacks
.Add(callback
);
621 Send(new ServiceWorkerHostMsg_NavigateClient(
622 GetRoutingID(), request_id
, base::UTF16ToUTF8(base::StringPiece16(uuid
)),
626 void ServiceWorkerContextClient::skipWaiting(
627 blink::WebServiceWorkerSkipWaitingCallbacks
* callbacks
) {
629 int request_id
= context_
->skip_waiting_callbacks
.Add(callbacks
);
630 Send(new ServiceWorkerHostMsg_SkipWaiting(GetRoutingID(), request_id
));
633 void ServiceWorkerContextClient::claim(
634 blink::WebServiceWorkerClientsClaimCallbacks
* callbacks
) {
636 int request_id
= context_
->claim_clients_callbacks
.Add(callbacks
);
637 Send(new ServiceWorkerHostMsg_ClaimClients(GetRoutingID(), request_id
));
640 void ServiceWorkerContextClient::DispatchSyncEvent(
641 const blink::WebSyncRegistration
& registration
,
642 const SyncCallback
& callback
) {
643 TRACE_EVENT0("ServiceWorker",
644 "ServiceWorkerScriptContext::DispatchSyncEvent");
646 context_
->sync_event_callbacks
.Add(new SyncCallback(callback
));
647 proxy_
->dispatchSyncEvent(request_id
, registration
);
650 void ServiceWorkerContextClient::Send(IPC::Message
* message
) {
651 sender_
->Send(message
);
654 void ServiceWorkerContextClient::SendWorkerStarted() {
655 DCHECK(worker_task_runner_
->RunsTasksOnCurrentThread());
656 TRACE_EVENT_ASYNC_END0("ServiceWorker",
657 "ServiceWorkerContextClient::StartingWorkerContext",
659 Send(new EmbeddedWorkerHostMsg_WorkerStarted(embedded_worker_id_
));
662 void ServiceWorkerContextClient::SetRegistrationInServiceWorkerGlobalScope() {
663 DCHECK(worker_task_runner_
->RunsTasksOnCurrentThread());
664 DCHECK(provider_context_
);
666 ServiceWorkerRegistrationObjectInfo info
;
667 ServiceWorkerVersionAttributes attrs
;
669 provider_context_
->GetRegistrationInfoAndVersionAttributes(&info
, &attrs
);
671 return; // Cannot be associated with a registration in some tests.
673 ServiceWorkerDispatcher
* dispatcher
=
674 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
675 sender_
.get(), main_thread_task_runner_
.get());
677 // Register a registration and its version attributes with the dispatcher
678 // living on the worker thread.
679 scoped_ptr
<WebServiceWorkerRegistrationImpl
> registration(
680 dispatcher
->CreateServiceWorkerRegistration(info
, false));
681 registration
->SetInstalling(
682 dispatcher
->GetServiceWorker(attrs
.installing
, false));
683 registration
->SetWaiting(
684 dispatcher
->GetServiceWorker(attrs
.waiting
, false));
685 registration
->SetActive(
686 dispatcher
->GetServiceWorker(attrs
.active
, false));
688 proxy_
->setRegistration(registration
.release());
691 void ServiceWorkerContextClient::OnActivateEvent(int request_id
) {
692 TRACE_EVENT0("ServiceWorker",
693 "ServiceWorkerContextClient::OnActivateEvent");
694 proxy_
->dispatchActivateEvent(request_id
);
697 void ServiceWorkerContextClient::OnInstallEvent(int request_id
) {
698 TRACE_EVENT0("ServiceWorker",
699 "ServiceWorkerContextClient::OnInstallEvent");
700 proxy_
->dispatchInstallEvent(request_id
);
703 void ServiceWorkerContextClient::OnFetchEvent(
705 const ServiceWorkerFetchRequest
& request
) {
706 blink::WebServiceWorkerRequest webRequest
;
707 TRACE_EVENT0("ServiceWorker",
708 "ServiceWorkerContextClient::OnFetchEvent");
709 webRequest
.setURL(blink::WebURL(request
.url
));
710 webRequest
.setMethod(blink::WebString::fromUTF8(request
.method
));
711 for (ServiceWorkerHeaderMap::const_iterator it
= request
.headers
.begin();
712 it
!= request
.headers
.end();
714 webRequest
.setHeader(blink::WebString::fromUTF8(it
->first
),
715 blink::WebString::fromUTF8(it
->second
));
717 if (!request
.blob_uuid
.empty()) {
718 webRequest
.setBlob(blink::WebString::fromUTF8(request
.blob_uuid
),
721 webRequest
.setReferrer(
722 blink::WebString::fromUTF8(request
.referrer
.url
.spec()),
723 request
.referrer
.policy
);
724 webRequest
.setMode(GetBlinkFetchRequestMode(request
.mode
));
725 webRequest
.setCredentialsMode(
726 GetBlinkFetchCredentialsMode(request
.credentials_mode
));
727 webRequest
.setRedirectMode(GetBlinkFetchRedirectMode(request
.redirect_mode
));
728 webRequest
.setRequestContext(
729 GetBlinkRequestContext(request
.request_context_type
));
730 webRequest
.setFrameType(GetBlinkFrameType(request
.frame_type
));
731 webRequest
.setIsReload(request
.is_reload
);
732 proxy_
->dispatchFetchEvent(request_id
, webRequest
);
735 void ServiceWorkerContextClient::OnNotificationClickEvent(
737 int64_t persistent_notification_id
,
738 const PlatformNotificationData
& notification_data
,
740 TRACE_EVENT0("ServiceWorker",
741 "ServiceWorkerContextClient::OnNotificationClickEvent");
742 proxy_
->dispatchNotificationClickEvent(
744 persistent_notification_id
,
745 ToWebNotificationData(notification_data
),
749 void ServiceWorkerContextClient::OnPushEvent(int request_id
,
750 const std::string
& data
) {
751 TRACE_EVENT0("ServiceWorker",
752 "ServiceWorkerContextClient::OnPushEvent");
753 proxy_
->dispatchPushEvent(request_id
, blink::WebString::fromUTF8(data
));
756 void ServiceWorkerContextClient::OnGeofencingEvent(
758 blink::WebGeofencingEventType event_type
,
759 const std::string
& region_id
,
760 const blink::WebCircularGeofencingRegion
& region
) {
761 TRACE_EVENT0("ServiceWorker",
762 "ServiceWorkerContextClient::OnGeofencingEvent");
763 proxy_
->dispatchGeofencingEvent(
764 request_id
, event_type
, blink::WebString::fromUTF8(region_id
), region
);
765 Send(new ServiceWorkerHostMsg_GeofencingEventFinished(GetRoutingID(),
769 void ServiceWorkerContextClient::OnPostMessage(
770 const base::string16
& message
,
771 const std::vector
<TransferredMessagePort
>& sent_message_ports
,
772 const std::vector
<int>& new_routing_ids
) {
773 TRACE_EVENT0("ServiceWorker",
774 "ServiceWorkerContextClient::OnPostEvent");
775 blink::WebMessagePortChannelArray ports
=
776 WebMessagePortChannelImpl::CreatePorts(
777 sent_message_ports
, new_routing_ids
,
778 main_thread_task_runner_
);
780 // dispatchMessageEvent is expected to execute onmessage function
782 base::TimeTicks before
= base::TimeTicks::Now();
783 proxy_
->dispatchMessageEvent(message
, ports
);
784 UMA_HISTOGRAM_MEDIUM_TIMES(
785 "ServiceWorker.MessageEvent.Time",
786 base::TimeTicks::Now() - before
);
789 void ServiceWorkerContextClient::OnCrossOriginMessageToWorker(
790 const NavigatorConnectClient
& client
,
791 const base::string16
& message
,
792 const std::vector
<TransferredMessagePort
>& sent_message_ports
,
793 const std::vector
<int>& new_routing_ids
) {
794 TRACE_EVENT0("ServiceWorker",
795 "ServiceWorkerContextClient::OnCrossOriginMessageToWorker");
796 blink::WebMessagePortChannelArray ports
=
797 WebMessagePortChannelImpl::CreatePorts(
798 sent_message_ports
, new_routing_ids
,
799 main_thread_task_runner_
);
801 blink::WebCrossOriginServiceWorkerClient web_client
;
802 web_client
.origin
= client
.origin
;
803 web_client
.targetURL
= client
.target_url
;
804 web_client
.clientID
= client
.message_port_id
;
805 proxy_
->dispatchCrossOriginMessageEvent(web_client
, message
, ports
);
808 void ServiceWorkerContextClient::OnDidGetClients(
809 int request_id
, const std::vector
<ServiceWorkerClientInfo
>& clients
) {
810 TRACE_EVENT0("ServiceWorker",
811 "ServiceWorkerContextClient::OnDidGetClients");
812 blink::WebServiceWorkerClientsCallbacks
* callbacks
=
813 context_
->clients_callbacks
.Lookup(request_id
);
815 NOTREACHED() << "Got stray response: " << request_id
;
818 blink::WebServiceWorkerClientsInfo info
;
819 blink::WebVector
<blink::WebServiceWorkerClientInfo
> convertedClients(
821 for (size_t i
= 0; i
< clients
.size(); ++i
)
822 convertedClients
[i
] = ToWebServiceWorkerClientInfo(clients
[i
]);
823 info
.clients
.swap(convertedClients
);
824 callbacks
->onSuccess(info
);
825 context_
->clients_callbacks
.Remove(request_id
);
828 void ServiceWorkerContextClient::OnOpenWindowResponse(
830 const ServiceWorkerClientInfo
& client
) {
831 TRACE_EVENT0("ServiceWorker",
832 "ServiceWorkerContextClient::OnOpenWindowResponse");
833 blink::WebServiceWorkerClientCallbacks
* callbacks
=
834 context_
->client_callbacks
.Lookup(request_id
);
836 NOTREACHED() << "Got stray response: " << request_id
;
839 scoped_ptr
<blink::WebServiceWorkerClientInfo
> web_client
;
840 if (!client
.IsEmpty()) {
841 DCHECK(client
.IsValid());
842 web_client
.reset(new blink::WebServiceWorkerClientInfo(
843 ToWebServiceWorkerClientInfo(client
)));
845 callbacks
->onSuccess(adoptWebPtr(web_client
.release()));
846 context_
->client_callbacks
.Remove(request_id
);
849 void ServiceWorkerContextClient::OnOpenWindowError(
851 const std::string
& message
) {
852 TRACE_EVENT0("ServiceWorker",
853 "ServiceWorkerContextClient::OnOpenWindowError");
854 blink::WebServiceWorkerClientCallbacks
* callbacks
=
855 context_
->client_callbacks
.Lookup(request_id
);
857 NOTREACHED() << "Got stray response: " << request_id
;
860 callbacks
->onError(blink::WebServiceWorkerError(
861 blink::WebServiceWorkerError::ErrorTypeUnknown
,
862 blink::WebString::fromUTF8(message
)));
863 context_
->client_callbacks
.Remove(request_id
);
866 void ServiceWorkerContextClient::OnFocusClientResponse(
867 int request_id
, const ServiceWorkerClientInfo
& client
) {
868 TRACE_EVENT0("ServiceWorker",
869 "ServiceWorkerContextClient::OnFocusClientResponse");
870 blink::WebServiceWorkerClientCallbacks
* callback
=
871 context_
->client_callbacks
.Lookup(request_id
);
873 NOTREACHED() << "Got stray response: " << request_id
;
876 if (!client
.IsEmpty()) {
877 DCHECK(client
.IsValid());
878 scoped_ptr
<blink::WebServiceWorkerClientInfo
> web_client (
879 new blink::WebServiceWorkerClientInfo(
880 ToWebServiceWorkerClientInfo(client
)));
881 callback
->onSuccess(adoptWebPtr(web_client
.release()));
883 callback
->onError(blink::WebServiceWorkerError(
884 blink::WebServiceWorkerError::ErrorTypeNotFound
,
885 "The WindowClient was not found."));
888 context_
->client_callbacks
.Remove(request_id
);
891 void ServiceWorkerContextClient::OnNavigateClientResponse(
893 const ServiceWorkerClientInfo
& client
) {
894 TRACE_EVENT0("ServiceWorker",
895 "ServiceWorkerContextClient::OnNavigateClientResponse");
896 blink::WebServiceWorkerClientCallbacks
* callbacks
=
897 context_
->client_callbacks
.Lookup(request_id
);
899 NOTREACHED() << "Got stray response: " << request_id
;
902 scoped_ptr
<blink::WebServiceWorkerClientInfo
> web_client
;
903 if (!client
.IsEmpty()) {
904 DCHECK(client
.IsValid());
905 web_client
.reset(new blink::WebServiceWorkerClientInfo(
906 ToWebServiceWorkerClientInfo(client
)));
908 callbacks
->onSuccess(adoptWebPtr(web_client
.release()));
909 context_
->client_callbacks
.Remove(request_id
);
912 void ServiceWorkerContextClient::OnNavigateClientError(int request_id
,
914 TRACE_EVENT0("ServiceWorker",
915 "ServiceWorkerContextClient::OnNavigateClientError");
916 blink::WebServiceWorkerClientCallbacks
* callbacks
=
917 context_
->client_callbacks
.Lookup(request_id
);
919 NOTREACHED() << "Got stray response: " << request_id
;
922 std::string message
= "Cannot navigate to URL: " + url
.spec();
923 callbacks
->onError(blink::WebServiceWorkerError(
924 blink::WebServiceWorkerError::ErrorTypeUnknown
,
925 blink::WebString::fromUTF8(message
)));
926 context_
->client_callbacks
.Remove(request_id
);
929 void ServiceWorkerContextClient::OnDidSkipWaiting(int request_id
) {
930 TRACE_EVENT0("ServiceWorker",
931 "ServiceWorkerContextClient::OnDidSkipWaiting");
932 blink::WebServiceWorkerSkipWaitingCallbacks
* callbacks
=
933 context_
->skip_waiting_callbacks
.Lookup(request_id
);
935 NOTREACHED() << "Got stray response: " << request_id
;
938 callbacks
->onSuccess();
939 context_
->skip_waiting_callbacks
.Remove(request_id
);
942 void ServiceWorkerContextClient::OnDidClaimClients(int request_id
) {
943 TRACE_EVENT0("ServiceWorker",
944 "ServiceWorkerContextClient::OnDidClaimClients");
945 blink::WebServiceWorkerClientsClaimCallbacks
* callbacks
=
946 context_
->claim_clients_callbacks
.Lookup(request_id
);
948 NOTREACHED() << "Got stray response: " << request_id
;
951 callbacks
->onSuccess();
952 context_
->claim_clients_callbacks
.Remove(request_id
);
955 void ServiceWorkerContextClient::OnClaimClientsError(
957 blink::WebServiceWorkerError::ErrorType error_type
,
958 const base::string16
& message
) {
959 TRACE_EVENT0("ServiceWorker",
960 "ServiceWorkerContextClient::OnClaimClientsError");
961 blink::WebServiceWorkerClientsClaimCallbacks
* callbacks
=
962 context_
->claim_clients_callbacks
.Lookup(request_id
);
964 NOTREACHED() << "Got stray response: " << request_id
;
967 callbacks
->onError(blink::WebServiceWorkerError(error_type
, message
));
968 context_
->claim_clients_callbacks
.Remove(request_id
);
971 void ServiceWorkerContextClient::OnPing() {
972 Send(new ServiceWorkerHostMsg_Pong(GetRoutingID()));
975 base::WeakPtr
<ServiceWorkerContextClient
>
976 ServiceWorkerContextClient::GetWeakPtr() {
977 DCHECK(worker_task_runner_
->RunsTasksOnCurrentThread());
979 return context_
->weak_factory
.GetWeakPtr();
982 } // namespace content