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/common/devtools_messages.h"
28 #include "content/common/message_port_messages.h"
29 #include "content/common/mojo/service_registry_impl.h"
30 #include "content/common/service_worker/embedded_worker_messages.h"
31 #include "content/common/service_worker/service_worker_messages.h"
32 #include "content/public/common/referrer.h"
33 #include "content/public/renderer/content_renderer_client.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/WebPassOwnPtr.h"
45 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
46 #include "third_party/WebKit/public/platform/WebString.h"
47 #include "third_party/WebKit/public/platform/modules/background_sync/WebSyncRegistration.h"
48 #include "third_party/WebKit/public/platform/modules/notifications/WebNotificationData.h"
49 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerClientQueryOptions.h"
50 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerRequest.h"
51 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponse.h"
52 #include "third_party/WebKit/public/web/WebDataSource.h"
53 #include "third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h"
54 #include "third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextProxy.h"
55 #include "third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerNetworkProvider.h"
61 // For now client must be a per-thread instance.
62 base::LazyInstance
<base::ThreadLocalPointer
<ServiceWorkerContextClient
>>::
63 Leaky g_worker_client_tls
= LAZY_INSTANCE_INITIALIZER
;
65 void CallWorkerContextDestroyedOnMainThread(int embedded_worker_id
) {
66 if (!RenderThreadImpl::current() ||
67 !RenderThreadImpl::current()->embedded_worker_dispatcher())
69 RenderThreadImpl::current()->embedded_worker_dispatcher()->
70 WorkerContextDestroyed(embedded_worker_id
);
73 // We store an instance of this class in the "extra data" of the WebDataSource
74 // and attach a ServiceWorkerNetworkProvider to it as base::UserData.
75 // (see createServiceWorkerNetworkProvider).
76 class DataSourceExtraData
77 : public blink::WebDataSource::ExtraData
,
78 public base::SupportsUserData
{
80 DataSourceExtraData() {}
81 virtual ~DataSourceExtraData() {}
84 // Called on the main thread only and blink owns it.
85 class WebServiceWorkerNetworkProviderImpl
86 : public blink::WebServiceWorkerNetworkProvider
{
88 // Blink calls this method for each request starting with the main script,
89 // we tag them with the provider id.
90 virtual void willSendRequest(
91 blink::WebDataSource
* data_source
,
92 blink::WebURLRequest
& request
) {
93 ServiceWorkerNetworkProvider
* provider
=
94 ServiceWorkerNetworkProvider::FromDocumentState(
95 static_cast<DataSourceExtraData
*>(data_source
->extraData()));
96 scoped_ptr
<RequestExtraData
> extra_data(new RequestExtraData
);
97 extra_data
->set_service_worker_provider_id(provider
->provider_id());
98 request
.setExtraData(extra_data
.release());
102 void SendPostMessageToClientOnMainThread(
103 ThreadSafeSender
* sender
,
105 const std::string
& uuid
,
106 const base::string16
& message
,
107 scoped_ptr
<blink::WebMessagePortChannelArray
> channels
) {
108 sender
->Send(new ServiceWorkerHostMsg_PostMessageToClient(
109 routing_id
, uuid
, message
,
110 WebMessagePortChannelImpl::ExtractMessagePortIDs(channels
.Pass())));
113 void SendCrossOriginMessageToClientOnMainThread(
114 ThreadSafeSender
* sender
,
116 const base::string16
& message
,
117 scoped_ptr
<blink::WebMessagePortChannelArray
> channels
) {
118 sender
->Send(new MessagePortHostMsg_PostMessage(
119 message_port_id
, MessagePortMessage(message
),
120 WebMessagePortChannelImpl::ExtractMessagePortIDs(channels
.Pass())));
123 blink::WebURLRequest::FetchRequestMode
GetBlinkFetchRequestMode(
124 FetchRequestMode mode
) {
125 return static_cast<blink::WebURLRequest::FetchRequestMode
>(mode
);
128 blink::WebURLRequest::FetchCredentialsMode
GetBlinkFetchCredentialsMode(
129 FetchCredentialsMode credentials_mode
) {
130 return static_cast<blink::WebURLRequest::FetchCredentialsMode
>(
134 blink::WebURLRequest::FetchRedirectMode
GetBlinkFetchRedirectMode(
135 FetchRedirectMode redirect_mode
) {
136 return static_cast<blink::WebURLRequest::FetchRedirectMode
>(redirect_mode
);
139 blink::WebURLRequest::RequestContext
GetBlinkRequestContext(
140 RequestContextType request_context_type
) {
141 return static_cast<blink::WebURLRequest::RequestContext
>(
142 request_context_type
);
145 blink::WebURLRequest::FrameType
GetBlinkFrameType(
146 RequestContextFrameType frame_type
) {
147 return static_cast<blink::WebURLRequest::FrameType
>(frame_type
);
150 blink::WebServiceWorkerClientInfo
151 ToWebServiceWorkerClientInfo(const ServiceWorkerClientInfo
& client_info
) {
152 DCHECK(client_info
.IsValid());
154 blink::WebServiceWorkerClientInfo web_client_info
;
156 web_client_info
.uuid
= base::UTF8ToUTF16(client_info
.client_uuid
);
157 web_client_info
.pageVisibilityState
= client_info
.page_visibility_state
;
158 web_client_info
.isFocused
= client_info
.is_focused
;
159 web_client_info
.url
= client_info
.url
;
160 web_client_info
.frameType
= GetBlinkFrameType(client_info
.frame_type
);
161 web_client_info
.clientType
= client_info
.client_type
;
163 return web_client_info
;
168 // Holding data that needs to be bound to the worker context on the
170 struct ServiceWorkerContextClient::WorkerContextData
{
171 using ClientsCallbacksMap
=
172 IDMap
<blink::WebServiceWorkerClientsCallbacks
, IDMapOwnPointer
>;
173 using ClaimClientsCallbacksMap
=
174 IDMap
<blink::WebServiceWorkerClientsClaimCallbacks
, IDMapOwnPointer
>;
175 using ClientCallbacksMap
=
176 IDMap
<blink::WebServiceWorkerClientCallbacks
, IDMapOwnPointer
>;
177 using SkipWaitingCallbacksMap
=
178 IDMap
<blink::WebServiceWorkerSkipWaitingCallbacks
, IDMapOwnPointer
>;
179 using SyncEventCallbacksMap
=
180 IDMap
<const mojo::Callback
<void(ServiceWorkerEventStatus
)>,
183 explicit WorkerContextData(ServiceWorkerContextClient
* owner
)
184 : weak_factory(owner
), proxy_weak_factory(owner
->proxy_
) {}
186 ~WorkerContextData() {
187 DCHECK(thread_checker
.CalledOnValidThread());
190 // Pending callbacks for GetClientDocuments().
191 ClientsCallbacksMap clients_callbacks
;
193 // Pending callbacks for OpenWindow() and FocusClient().
194 ClientCallbacksMap client_callbacks
;
196 // Pending callbacks for SkipWaiting().
197 SkipWaitingCallbacksMap skip_waiting_callbacks
;
199 // Pending callbacks for ClaimClients().
200 ClaimClientsCallbacksMap claim_clients_callbacks
;
202 // Pending callbacks for Background Sync Events
203 SyncEventCallbacksMap sync_event_callbacks
;
205 ServiceRegistryImpl service_registry
;
207 base::ThreadChecker thread_checker
;
208 base::WeakPtrFactory
<ServiceWorkerContextClient
> weak_factory
;
209 base::WeakPtrFactory
<blink::WebServiceWorkerContextProxy
> proxy_weak_factory
;
212 ServiceWorkerContextClient
*
213 ServiceWorkerContextClient::ThreadSpecificInstance() {
214 return g_worker_client_tls
.Pointer()->Get();
217 ServiceWorkerContextClient::ServiceWorkerContextClient(
218 int embedded_worker_id
,
219 int64 service_worker_version_id
,
220 const GURL
& service_worker_scope
,
221 const GURL
& script_url
,
222 int worker_devtools_agent_route_id
)
223 : embedded_worker_id_(embedded_worker_id
),
224 service_worker_version_id_(service_worker_version_id
),
225 service_worker_scope_(service_worker_scope
),
226 script_url_(script_url
),
227 worker_devtools_agent_route_id_(worker_devtools_agent_route_id
),
228 sender_(ChildThreadImpl::current()->thread_safe_sender()),
229 main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
231 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
232 "ServiceWorkerContextClient::StartingWorkerContext",
234 TRACE_EVENT_ASYNC_STEP_INTO0(
236 "ServiceWorkerContextClient::StartingWorkerContext",
241 ServiceWorkerContextClient::~ServiceWorkerContextClient() {}
243 void ServiceWorkerContextClient::OnMessageReceived(
245 int embedded_worker_id
,
246 const IPC::Message
& message
) {
247 CHECK_EQ(embedded_worker_id_
, embedded_worker_id
);
249 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerContextClient
, message
)
250 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ActivateEvent
, OnActivateEvent
)
251 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FetchEvent
, OnFetchEvent
)
252 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_InstallEvent
, OnInstallEvent
)
253 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_NotificationClickEvent
,
254 OnNotificationClickEvent
)
255 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_PushEvent
, OnPushEvent
)
256 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_GeofencingEvent
, OnGeofencingEvent
)
257 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToWorker
, OnPostMessage
)
258 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CrossOriginMessageToWorker
,
259 OnCrossOriginMessageToWorker
)
260 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetClients
, OnDidGetClients
)
261 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_OpenWindowResponse
,
262 OnOpenWindowResponse
)
263 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_OpenWindowError
,
265 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FocusClientResponse
,
266 OnFocusClientResponse
)
267 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_NavigateClientResponse
,
268 OnNavigateClientResponse
)
269 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_NavigateClientError
,
270 OnNavigateClientError
)
271 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidSkipWaiting
, OnDidSkipWaiting
)
272 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidClaimClients
, OnDidClaimClients
)
273 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ClaimClientsError
, OnClaimClientsError
)
274 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_Ping
, OnPing
);
275 IPC_MESSAGE_UNHANDLED(handled
= false)
276 IPC_END_MESSAGE_MAP()
280 void ServiceWorkerContextClient::BindServiceRegistry(
281 mojo::InterfaceRequest
<mojo::ServiceProvider
> services
,
282 mojo::ServiceProviderPtr exposed_services
) {
283 context_
->service_registry
.Bind(services
.Pass());
284 context_
->service_registry
.BindRemoteServiceProvider(exposed_services
.Pass());
287 blink::WebURL
ServiceWorkerContextClient::scope() const {
288 return service_worker_scope_
;
291 void ServiceWorkerContextClient::getClients(
292 const blink::WebServiceWorkerClientQueryOptions
& weboptions
,
293 blink::WebServiceWorkerClientsCallbacks
* callbacks
) {
295 int request_id
= context_
->clients_callbacks
.Add(callbacks
);
296 ServiceWorkerClientQueryOptions options
;
297 options
.client_type
= weboptions
.clientType
;
298 options
.include_uncontrolled
= weboptions
.includeUncontrolled
;
299 Send(new ServiceWorkerHostMsg_GetClients(
300 GetRoutingID(), request_id
, options
));
303 void ServiceWorkerContextClient::openWindow(
304 const blink::WebURL
& url
,
305 blink::WebServiceWorkerClientCallbacks
* callbacks
) {
307 int request_id
= context_
->client_callbacks
.Add(callbacks
);
308 Send(new ServiceWorkerHostMsg_OpenWindow(
309 GetRoutingID(), request_id
, url
));
312 void ServiceWorkerContextClient::setCachedMetadata(const blink::WebURL
& url
,
315 std::vector
<char> copy(data
, data
+ size
);
316 Send(new ServiceWorkerHostMsg_SetCachedMetadata(GetRoutingID(), url
, copy
));
319 void ServiceWorkerContextClient::clearCachedMetadata(
320 const blink::WebURL
& url
) {
321 Send(new ServiceWorkerHostMsg_ClearCachedMetadata(GetRoutingID(), url
));
324 void ServiceWorkerContextClient::workerReadyForInspection() {
325 Send(new EmbeddedWorkerHostMsg_WorkerReadyForInspection(embedded_worker_id_
));
328 void ServiceWorkerContextClient::workerContextFailedToStart() {
329 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
332 Send(new EmbeddedWorkerHostMsg_WorkerScriptLoadFailed(embedded_worker_id_
));
334 RenderThreadImpl::current()->embedded_worker_dispatcher()->
335 WorkerContextDestroyed(embedded_worker_id_
);
338 void ServiceWorkerContextClient::workerScriptLoaded() {
339 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
342 Send(new EmbeddedWorkerHostMsg_WorkerScriptLoaded(embedded_worker_id_
));
345 void ServiceWorkerContextClient::workerContextStarted(
346 blink::WebServiceWorkerContextProxy
* proxy
) {
347 DCHECK(!worker_task_runner_
.get());
348 DCHECK_NE(0, WorkerThread::GetCurrentId());
349 worker_task_runner_
= base::ThreadTaskRunnerHandle::Get();
350 // g_worker_client_tls.Pointer()->Get() could return NULL if this context
351 // gets deleted before workerContextStarted() is called.
352 DCHECK(g_worker_client_tls
.Pointer()->Get() == NULL
);
354 g_worker_client_tls
.Pointer()->Set(this);
357 // Initialize pending callback maps. This needs to be freed on the
358 // same thread before the worker context goes away in
359 // willDestroyWorkerContext.
360 context_
.reset(new WorkerContextData(this));
362 ServiceWorkerRegistrationObjectInfo registration_info
;
363 ServiceWorkerVersionAttributes version_attrs
;
364 provider_context_
->GetRegistrationInfoAndVersionAttributes(®istration_info
,
366 DCHECK_NE(registration_info
.registration_id
,
367 kInvalidServiceWorkerRegistrationId
);
369 // Register Mojo services.
370 context_
->service_registry
.ServiceRegistry::AddService(
371 base::Bind(&ServicePortDispatcherImpl::Create
,
372 context_
->proxy_weak_factory
.GetWeakPtr()));
373 context_
->service_registry
.ServiceRegistry::AddService(base::Bind(
374 &BackgroundSyncClientImpl::Create
, registration_info
.registration_id
));
376 SetRegistrationInServiceWorkerGlobalScope();
378 Send(new EmbeddedWorkerHostMsg_WorkerThreadStarted(
379 embedded_worker_id_
, WorkerThread::GetCurrentId(),
380 provider_context_
->provider_id()));
382 TRACE_EVENT_ASYNC_STEP_INTO0(
384 "ServiceWorkerContextClient::StartingWorkerContext",
389 void ServiceWorkerContextClient::didEvaluateWorkerScript(bool success
) {
390 Send(new EmbeddedWorkerHostMsg_WorkerScriptEvaluated(
391 embedded_worker_id_
, success
));
393 // Schedule a task to send back WorkerStarted asynchronously,
394 // so that at the time we send it we can be sure that the
395 // worker run loop has been started.
396 worker_task_runner_
->PostTask(
397 FROM_HERE
, base::Bind(&ServiceWorkerContextClient::SendWorkerStarted
,
401 void ServiceWorkerContextClient::didInitializeWorkerContext(
402 v8::Local
<v8::Context
> context
,
403 const blink::WebURL
& url
) {
404 // TODO(annekao): Remove WebURL parameter from Blink, it's at best redundant
405 // given |script_url_|, and may be empty in the future.
406 // Also remove m_documentURL from ServiceWorkerGlobalScopeProxy.
409 ->DidInitializeServiceWorkerContextOnWorkerThread(context
, script_url_
);
412 void ServiceWorkerContextClient::willDestroyWorkerContext(
413 v8::Local
<v8::Context
> context
) {
414 // At this point WillStopCurrentWorkerThread is already called, so
415 // worker_task_runner_->RunsTasksOnCurrentThread() returns false
416 // (while we're still on the worker thread).
419 // We have to clear callbacks now, as they need to be freed on the
423 // This also lets the message filter stop dispatching messages to
425 g_worker_client_tls
.Pointer()->Set(NULL
);
427 GetContentClient()->renderer()->WillDestroyServiceWorkerContextOnWorkerThread(
428 context
, script_url_
);
431 void ServiceWorkerContextClient::workerContextDestroyed() {
432 DCHECK(g_worker_client_tls
.Pointer()->Get() == NULL
);
434 // Now we should be able to free the WebEmbeddedWorker container on the
436 main_thread_task_runner_
->PostTask(
438 base::Bind(&CallWorkerContextDestroyedOnMainThread
,
439 embedded_worker_id_
));
442 void ServiceWorkerContextClient::reportException(
443 const blink::WebString
& error_message
,
446 const blink::WebString
& source_url
) {
447 Send(new EmbeddedWorkerHostMsg_ReportException(
451 column_number
, GURL(source_url
)));
454 void ServiceWorkerContextClient::reportConsoleMessage(
457 const blink::WebString
& message
,
459 const blink::WebString
& source_url
) {
460 EmbeddedWorkerHostMsg_ReportConsoleMessage_Params params
;
461 params
.source_identifier
= source
;
462 params
.message_level
= level
;
463 params
.message
= message
;
464 params
.line_number
= line_number
;
465 params
.source_url
= GURL(source_url
);
467 Send(new EmbeddedWorkerHostMsg_ReportConsoleMessage(
468 embedded_worker_id_
, params
));
471 void ServiceWorkerContextClient::sendDevToolsMessage(
473 const blink::WebString
& message
,
474 const blink::WebString
& state_cookie
) {
475 DevToolsAgent::SendChunkedProtocolMessage(
476 sender_
.get(), worker_devtools_agent_route_id_
,
477 call_id
, message
.utf8(), state_cookie
.utf8());
480 void ServiceWorkerContextClient::didHandleActivateEvent(
482 blink::WebServiceWorkerEventResult result
) {
483 Send(new ServiceWorkerHostMsg_ActivateEventFinished(
484 GetRoutingID(), request_id
, result
));
487 void ServiceWorkerContextClient::didHandleInstallEvent(
489 blink::WebServiceWorkerEventResult result
) {
490 Send(new ServiceWorkerHostMsg_InstallEventFinished(
491 GetRoutingID(), request_id
, result
));
494 void ServiceWorkerContextClient::didHandleFetchEvent(int request_id
) {
495 Send(new ServiceWorkerHostMsg_FetchEventFinished(
496 GetRoutingID(), request_id
,
497 SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK
,
498 ServiceWorkerResponse()));
501 void ServiceWorkerContextClient::didHandleFetchEvent(
503 const blink::WebServiceWorkerResponse
& web_response
) {
504 ServiceWorkerHeaderMap headers
;
505 GetServiceWorkerHeaderMapFromWebResponse(web_response
, &headers
);
506 ServiceWorkerResponse
response(
507 web_response
.url(), web_response
.status(),
508 web_response
.statusText().utf8(), web_response
.responseType(), headers
,
509 web_response
.blobUUID().utf8(), web_response
.blobSize(),
510 web_response
.streamURL(), web_response
.error());
511 Send(new ServiceWorkerHostMsg_FetchEventFinished(
512 GetRoutingID(), request_id
,
513 SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE
,
517 void ServiceWorkerContextClient::didHandleNotificationClickEvent(
519 blink::WebServiceWorkerEventResult result
) {
520 Send(new ServiceWorkerHostMsg_NotificationClickEventFinished(
521 GetRoutingID(), request_id
));
524 void ServiceWorkerContextClient::didHandlePushEvent(
526 blink::WebServiceWorkerEventResult result
) {
527 Send(new ServiceWorkerHostMsg_PushEventFinished(
528 GetRoutingID(), request_id
, result
));
531 void ServiceWorkerContextClient::didHandleSyncEvent(
533 blink::WebServiceWorkerEventResult result
) {
534 const SyncCallback
* callback
=
535 context_
->sync_event_callbacks
.Lookup(request_id
);
538 if (result
== blink::WebServiceWorkerEventResultCompleted
) {
539 callback
->Run(SERVICE_WORKER_EVENT_STATUS_COMPLETED
);
541 callback
->Run(SERVICE_WORKER_EVENT_STATUS_REJECTED
);
543 context_
->sync_event_callbacks
.Remove(request_id
);
546 blink::WebServiceWorkerNetworkProvider
*
547 ServiceWorkerContextClient::createServiceWorkerNetworkProvider(
548 blink::WebDataSource
* data_source
) {
549 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
551 // Create a content::ServiceWorkerNetworkProvider for this data source so
552 // we can observe its requests.
553 scoped_ptr
<ServiceWorkerNetworkProvider
> provider(
554 new ServiceWorkerNetworkProvider(
555 MSG_ROUTING_NONE
, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER
));
556 provider_context_
= provider
->context();
558 // Tell the network provider about which version to load.
559 provider
->SetServiceWorkerVersionId(service_worker_version_id_
);
561 // The provider is kept around for the lifetime of the DataSource
562 // and ownership is transferred to the DataSource.
563 DataSourceExtraData
* extra_data
= new DataSourceExtraData();
564 data_source
->setExtraData(extra_data
);
565 ServiceWorkerNetworkProvider::AttachToDocumentState(
566 extra_data
, provider
.Pass());
568 // Blink is responsible for deleting the returned object.
569 return new WebServiceWorkerNetworkProviderImpl();
572 blink::WebServiceWorkerProvider
*
573 ServiceWorkerContextClient::createServiceWorkerProvider() {
574 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
575 DCHECK(provider_context_
);
577 // Blink is responsible for deleting the returned object.
578 return new WebServiceWorkerProviderImpl(
579 sender_
.get(), provider_context_
.get());
582 void ServiceWorkerContextClient::postMessageToClient(
583 const blink::WebString
& uuid
,
584 const blink::WebString
& message
,
585 blink::WebMessagePortChannelArray
* channels
) {
586 // This may send channels for MessagePorts, and all internal book-keeping
587 // messages for MessagePort (e.g. QueueMessages) are sent from main thread
588 // (with thread hopping), so we need to do the same thread hopping here not
589 // to overtake those messages.
590 scoped_ptr
<blink::WebMessagePortChannelArray
> channel_array(channels
);
591 main_thread_task_runner_
->PostTask(
593 base::Bind(&SendPostMessageToClientOnMainThread
,
596 base::UTF16ToUTF8(base::StringPiece16(uuid
)),
597 static_cast<base::string16
>(message
),
598 base::Passed(&channel_array
)));
601 void ServiceWorkerContextClient::postMessageToCrossOriginClient(
602 const blink::WebCrossOriginServiceWorkerClient
& client
,
603 const blink::WebString
& message
,
604 blink::WebMessagePortChannelArray
* channels
) {
605 // This may send channels for MessagePorts, and all internal book-keeping
606 // messages for MessagePort (e.g. QueueMessages) are sent from main thread
607 // (with thread hopping), so we need to do the same thread hopping here not
608 // to overtake those messages.
609 scoped_ptr
<blink::WebMessagePortChannelArray
> channel_array(channels
);
610 main_thread_task_runner_
->PostTask(
612 base::Bind(&SendCrossOriginMessageToClientOnMainThread
,
613 sender_
, client
.clientID
,
614 static_cast<base::string16
>(message
),
615 base::Passed(&channel_array
)));
618 void ServiceWorkerContextClient::focus(
619 const blink::WebString
& uuid
,
620 blink::WebServiceWorkerClientCallbacks
* callback
) {
622 int request_id
= context_
->client_callbacks
.Add(callback
);
623 Send(new ServiceWorkerHostMsg_FocusClient(
624 GetRoutingID(), request_id
,
625 base::UTF16ToUTF8(base::StringPiece16(uuid
))));
628 void ServiceWorkerContextClient::navigate(
629 const blink::WebString
& uuid
,
630 const blink::WebURL
& url
,
631 blink::WebServiceWorkerClientCallbacks
* callback
) {
633 int request_id
= context_
->client_callbacks
.Add(callback
);
634 Send(new ServiceWorkerHostMsg_NavigateClient(
635 GetRoutingID(), request_id
, base::UTF16ToUTF8(base::StringPiece16(uuid
)),
639 void ServiceWorkerContextClient::skipWaiting(
640 blink::WebServiceWorkerSkipWaitingCallbacks
* callbacks
) {
642 int request_id
= context_
->skip_waiting_callbacks
.Add(callbacks
);
643 Send(new ServiceWorkerHostMsg_SkipWaiting(GetRoutingID(), request_id
));
646 void ServiceWorkerContextClient::claim(
647 blink::WebServiceWorkerClientsClaimCallbacks
* callbacks
) {
649 int request_id
= context_
->claim_clients_callbacks
.Add(callbacks
);
650 Send(new ServiceWorkerHostMsg_ClaimClients(GetRoutingID(), request_id
));
653 void ServiceWorkerContextClient::DispatchSyncEvent(
654 const blink::WebSyncRegistration
& registration
,
655 const SyncCallback
& callback
) {
656 TRACE_EVENT0("ServiceWorker",
657 "ServiceWorkerContextClient::DispatchSyncEvent");
659 context_
->sync_event_callbacks
.Add(new SyncCallback(callback
));
660 proxy_
->dispatchSyncEvent(request_id
, registration
);
663 void ServiceWorkerContextClient::Send(IPC::Message
* message
) {
664 sender_
->Send(message
);
667 void ServiceWorkerContextClient::SendWorkerStarted() {
668 DCHECK(worker_task_runner_
->RunsTasksOnCurrentThread());
669 TRACE_EVENT_ASYNC_END0("ServiceWorker",
670 "ServiceWorkerContextClient::StartingWorkerContext",
672 Send(new EmbeddedWorkerHostMsg_WorkerStarted(embedded_worker_id_
));
675 void ServiceWorkerContextClient::SetRegistrationInServiceWorkerGlobalScope() {
676 DCHECK(worker_task_runner_
->RunsTasksOnCurrentThread());
677 DCHECK(provider_context_
);
679 ServiceWorkerRegistrationObjectInfo info
;
680 ServiceWorkerVersionAttributes attrs
;
682 provider_context_
->GetRegistrationInfoAndVersionAttributes(&info
, &attrs
);
684 return; // Cannot be associated with a registration in some tests.
686 ServiceWorkerDispatcher
* dispatcher
=
687 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
688 sender_
.get(), main_thread_task_runner_
.get());
690 // Register a registration and its version attributes with the dispatcher
691 // living on the worker thread.
692 scoped_refptr
<WebServiceWorkerRegistrationImpl
> registration(
693 dispatcher
->CreateRegistration(info
, attrs
));
695 proxy_
->setRegistration(registration
->CreateHandle());
698 void ServiceWorkerContextClient::OnActivateEvent(int request_id
) {
699 TRACE_EVENT0("ServiceWorker",
700 "ServiceWorkerContextClient::OnActivateEvent");
701 proxy_
->dispatchActivateEvent(request_id
);
704 void ServiceWorkerContextClient::OnInstallEvent(int request_id
) {
705 TRACE_EVENT0("ServiceWorker",
706 "ServiceWorkerContextClient::OnInstallEvent");
707 proxy_
->dispatchInstallEvent(request_id
);
710 void ServiceWorkerContextClient::OnFetchEvent(
712 const ServiceWorkerFetchRequest
& request
) {
713 blink::WebServiceWorkerRequest webRequest
;
714 TRACE_EVENT0("ServiceWorker",
715 "ServiceWorkerContextClient::OnFetchEvent");
716 webRequest
.setURL(blink::WebURL(request
.url
));
717 webRequest
.setMethod(blink::WebString::fromUTF8(request
.method
));
718 for (ServiceWorkerHeaderMap::const_iterator it
= request
.headers
.begin();
719 it
!= request
.headers
.end();
721 webRequest
.setHeader(blink::WebString::fromUTF8(it
->first
),
722 blink::WebString::fromUTF8(it
->second
));
724 if (!request
.blob_uuid
.empty()) {
725 webRequest
.setBlob(blink::WebString::fromUTF8(request
.blob_uuid
),
728 webRequest
.setReferrer(
729 blink::WebString::fromUTF8(request
.referrer
.url
.spec()),
730 request
.referrer
.policy
);
731 webRequest
.setMode(GetBlinkFetchRequestMode(request
.mode
));
732 webRequest
.setCredentialsMode(
733 GetBlinkFetchCredentialsMode(request
.credentials_mode
));
734 webRequest
.setRedirectMode(GetBlinkFetchRedirectMode(request
.redirect_mode
));
735 webRequest
.setRequestContext(
736 GetBlinkRequestContext(request
.request_context_type
));
737 webRequest
.setFrameType(GetBlinkFrameType(request
.frame_type
));
738 webRequest
.setIsReload(request
.is_reload
);
739 proxy_
->dispatchFetchEvent(request_id
, webRequest
);
742 void ServiceWorkerContextClient::OnNotificationClickEvent(
744 int64_t persistent_notification_id
,
745 const PlatformNotificationData
& notification_data
,
747 TRACE_EVENT0("ServiceWorker",
748 "ServiceWorkerContextClient::OnNotificationClickEvent");
749 proxy_
->dispatchNotificationClickEvent(
751 persistent_notification_id
,
752 ToWebNotificationData(notification_data
),
756 void ServiceWorkerContextClient::OnPushEvent(int request_id
,
757 const std::string
& data
) {
758 TRACE_EVENT0("ServiceWorker",
759 "ServiceWorkerContextClient::OnPushEvent");
760 proxy_
->dispatchPushEvent(request_id
, blink::WebString::fromUTF8(data
));
763 void ServiceWorkerContextClient::OnGeofencingEvent(
765 blink::WebGeofencingEventType event_type
,
766 const std::string
& region_id
,
767 const blink::WebCircularGeofencingRegion
& region
) {
768 TRACE_EVENT0("ServiceWorker",
769 "ServiceWorkerContextClient::OnGeofencingEvent");
770 proxy_
->dispatchGeofencingEvent(
771 request_id
, event_type
, blink::WebString::fromUTF8(region_id
), region
);
772 Send(new ServiceWorkerHostMsg_GeofencingEventFinished(GetRoutingID(),
776 void ServiceWorkerContextClient::OnPostMessage(
777 const base::string16
& message
,
778 const std::vector
<TransferredMessagePort
>& sent_message_ports
,
779 const std::vector
<int>& new_routing_ids
) {
780 TRACE_EVENT0("ServiceWorker",
781 "ServiceWorkerContextClient::OnPostEvent");
782 blink::WebMessagePortChannelArray ports
=
783 WebMessagePortChannelImpl::CreatePorts(
784 sent_message_ports
, new_routing_ids
,
785 main_thread_task_runner_
);
787 // dispatchMessageEvent is expected to execute onmessage function
789 base::TimeTicks before
= base::TimeTicks::Now();
790 proxy_
->dispatchMessageEvent(message
, ports
);
791 UMA_HISTOGRAM_MEDIUM_TIMES(
792 "ServiceWorker.MessageEvent.Time",
793 base::TimeTicks::Now() - before
);
796 void ServiceWorkerContextClient::OnCrossOriginMessageToWorker(
797 const NavigatorConnectClient
& client
,
798 const base::string16
& message
,
799 const std::vector
<TransferredMessagePort
>& sent_message_ports
,
800 const std::vector
<int>& new_routing_ids
) {
801 TRACE_EVENT0("ServiceWorker",
802 "ServiceWorkerContextClient::OnCrossOriginMessageToWorker");
803 blink::WebMessagePortChannelArray ports
=
804 WebMessagePortChannelImpl::CreatePorts(
805 sent_message_ports
, new_routing_ids
,
806 main_thread_task_runner_
);
808 blink::WebCrossOriginServiceWorkerClient web_client
;
809 web_client
.origin
= client
.origin
;
810 web_client
.targetURL
= client
.target_url
;
811 web_client
.clientID
= client
.message_port_id
;
812 proxy_
->dispatchCrossOriginMessageEvent(web_client
, message
, ports
);
815 void ServiceWorkerContextClient::OnDidGetClients(
816 int request_id
, const std::vector
<ServiceWorkerClientInfo
>& clients
) {
817 TRACE_EVENT0("ServiceWorker",
818 "ServiceWorkerContextClient::OnDidGetClients");
819 blink::WebServiceWorkerClientsCallbacks
* callbacks
=
820 context_
->clients_callbacks
.Lookup(request_id
);
822 NOTREACHED() << "Got stray response: " << request_id
;
825 blink::WebServiceWorkerClientsInfo info
;
826 blink::WebVector
<blink::WebServiceWorkerClientInfo
> convertedClients(
828 for (size_t i
= 0; i
< clients
.size(); ++i
)
829 convertedClients
[i
] = ToWebServiceWorkerClientInfo(clients
[i
]);
830 info
.clients
.swap(convertedClients
);
831 callbacks
->onSuccess(info
);
832 context_
->clients_callbacks
.Remove(request_id
);
835 void ServiceWorkerContextClient::OnOpenWindowResponse(
837 const ServiceWorkerClientInfo
& client
) {
838 TRACE_EVENT0("ServiceWorker",
839 "ServiceWorkerContextClient::OnOpenWindowResponse");
840 blink::WebServiceWorkerClientCallbacks
* callbacks
=
841 context_
->client_callbacks
.Lookup(request_id
);
843 NOTREACHED() << "Got stray response: " << request_id
;
846 scoped_ptr
<blink::WebServiceWorkerClientInfo
> web_client
;
847 if (!client
.IsEmpty()) {
848 DCHECK(client
.IsValid());
849 web_client
.reset(new blink::WebServiceWorkerClientInfo(
850 ToWebServiceWorkerClientInfo(client
)));
852 callbacks
->onSuccess(adoptWebPtr(web_client
.release()));
853 context_
->client_callbacks
.Remove(request_id
);
856 void ServiceWorkerContextClient::OnOpenWindowError(
858 const std::string
& message
) {
859 TRACE_EVENT0("ServiceWorker",
860 "ServiceWorkerContextClient::OnOpenWindowError");
861 blink::WebServiceWorkerClientCallbacks
* callbacks
=
862 context_
->client_callbacks
.Lookup(request_id
);
864 NOTREACHED() << "Got stray response: " << request_id
;
867 callbacks
->onError(blink::WebServiceWorkerError(
868 blink::WebServiceWorkerError::ErrorTypeUnknown
,
869 blink::WebString::fromUTF8(message
)));
870 context_
->client_callbacks
.Remove(request_id
);
873 void ServiceWorkerContextClient::OnFocusClientResponse(
874 int request_id
, const ServiceWorkerClientInfo
& client
) {
875 TRACE_EVENT0("ServiceWorker",
876 "ServiceWorkerContextClient::OnFocusClientResponse");
877 blink::WebServiceWorkerClientCallbacks
* callback
=
878 context_
->client_callbacks
.Lookup(request_id
);
880 NOTREACHED() << "Got stray response: " << request_id
;
883 if (!client
.IsEmpty()) {
884 DCHECK(client
.IsValid());
885 scoped_ptr
<blink::WebServiceWorkerClientInfo
> web_client (
886 new blink::WebServiceWorkerClientInfo(
887 ToWebServiceWorkerClientInfo(client
)));
888 callback
->onSuccess(adoptWebPtr(web_client
.release()));
890 callback
->onError(blink::WebServiceWorkerError(
891 blink::WebServiceWorkerError::ErrorTypeNotFound
,
892 "The WindowClient was not found."));
895 context_
->client_callbacks
.Remove(request_id
);
898 void ServiceWorkerContextClient::OnNavigateClientResponse(
900 const ServiceWorkerClientInfo
& client
) {
901 TRACE_EVENT0("ServiceWorker",
902 "ServiceWorkerContextClient::OnNavigateClientResponse");
903 blink::WebServiceWorkerClientCallbacks
* callbacks
=
904 context_
->client_callbacks
.Lookup(request_id
);
906 NOTREACHED() << "Got stray response: " << request_id
;
909 scoped_ptr
<blink::WebServiceWorkerClientInfo
> web_client
;
910 if (!client
.IsEmpty()) {
911 DCHECK(client
.IsValid());
912 web_client
.reset(new blink::WebServiceWorkerClientInfo(
913 ToWebServiceWorkerClientInfo(client
)));
915 callbacks
->onSuccess(adoptWebPtr(web_client
.release()));
916 context_
->client_callbacks
.Remove(request_id
);
919 void ServiceWorkerContextClient::OnNavigateClientError(int request_id
,
921 TRACE_EVENT0("ServiceWorker",
922 "ServiceWorkerContextClient::OnNavigateClientError");
923 blink::WebServiceWorkerClientCallbacks
* callbacks
=
924 context_
->client_callbacks
.Lookup(request_id
);
926 NOTREACHED() << "Got stray response: " << request_id
;
929 std::string message
= "Cannot navigate to URL: " + url
.spec();
930 callbacks
->onError(blink::WebServiceWorkerError(
931 blink::WebServiceWorkerError::ErrorTypeUnknown
,
932 blink::WebString::fromUTF8(message
)));
933 context_
->client_callbacks
.Remove(request_id
);
936 void ServiceWorkerContextClient::OnDidSkipWaiting(int request_id
) {
937 TRACE_EVENT0("ServiceWorker",
938 "ServiceWorkerContextClient::OnDidSkipWaiting");
939 blink::WebServiceWorkerSkipWaitingCallbacks
* callbacks
=
940 context_
->skip_waiting_callbacks
.Lookup(request_id
);
942 NOTREACHED() << "Got stray response: " << request_id
;
945 callbacks
->onSuccess();
946 context_
->skip_waiting_callbacks
.Remove(request_id
);
949 void ServiceWorkerContextClient::OnDidClaimClients(int request_id
) {
950 TRACE_EVENT0("ServiceWorker",
951 "ServiceWorkerContextClient::OnDidClaimClients");
952 blink::WebServiceWorkerClientsClaimCallbacks
* callbacks
=
953 context_
->claim_clients_callbacks
.Lookup(request_id
);
955 NOTREACHED() << "Got stray response: " << request_id
;
958 callbacks
->onSuccess();
959 context_
->claim_clients_callbacks
.Remove(request_id
);
962 void ServiceWorkerContextClient::OnClaimClientsError(
964 blink::WebServiceWorkerError::ErrorType error_type
,
965 const base::string16
& message
) {
966 TRACE_EVENT0("ServiceWorker",
967 "ServiceWorkerContextClient::OnClaimClientsError");
968 blink::WebServiceWorkerClientsClaimCallbacks
* callbacks
=
969 context_
->claim_clients_callbacks
.Lookup(request_id
);
971 NOTREACHED() << "Got stray response: " << request_id
;
974 callbacks
->onError(blink::WebServiceWorkerError(error_type
, message
));
975 context_
->claim_clients_callbacks
.Remove(request_id
);
978 void ServiceWorkerContextClient::OnPing() {
979 Send(new ServiceWorkerHostMsg_Pong(GetRoutingID()));
982 base::WeakPtr
<ServiceWorkerContextClient
>
983 ServiceWorkerContextClient::GetWeakPtr() {
984 DCHECK(worker_task_runner_
->RunsTasksOnCurrentThread());
986 return context_
->weak_factory
.GetWeakPtr();
989 } // namespace content