Roll src/third_party/WebKit a452221:9ff6d11 (svn 202117:202119)
[chromium-blink-merge.git] / content / renderer / service_worker / service_worker_context_client.cc
blob4da72ab0ef783042bacce2972031a03e946970d9
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"
57 namespace content {
59 namespace {
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())
68 return;
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 {
79 public:
80 DataSourceExtraData() {}
81 virtual ~DataSourceExtraData() {}
84 // Called on the main thread only and blink owns it.
85 class WebServiceWorkerNetworkProviderImpl
86 : public blink::WebServiceWorkerNetworkProvider {
87 public:
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,
104 int routing_id,
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,
115 int message_port_id,
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>(
131 credentials_mode);
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;
166 } // namespace
168 // Holding data that needs to be bound to the worker context on the
169 // worker thread.
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)>,
181 IDMapOwnPointer>;
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()),
230 proxy_(nullptr) {
231 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
232 "ServiceWorkerContextClient::StartingWorkerContext",
233 this);
234 TRACE_EVENT_ASYNC_STEP_INTO0(
235 "ServiceWorker",
236 "ServiceWorkerContextClient::StartingWorkerContext",
237 this,
238 "PrepareWorker");
241 ServiceWorkerContextClient::~ServiceWorkerContextClient() {}
243 void ServiceWorkerContextClient::OnMessageReceived(
244 int thread_id,
245 int embedded_worker_id,
246 const IPC::Message& message) {
247 CHECK_EQ(embedded_worker_id_, embedded_worker_id);
248 bool handled = true;
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,
264 OnOpenWindowError)
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()
277 DCHECK(handled);
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) {
294 DCHECK(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) {
306 DCHECK(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,
313 const char* data,
314 size_t size) {
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());
330 DCHECK(!proxy_);
332 Send(new EmbeddedWorkerHostMsg_WorkerScriptLoadFailed(embedded_worker_id_));
334 RenderThreadImpl::current()->embedded_worker_dispatcher()->
335 WorkerContextDestroyed(embedded_worker_id_);
338 void ServiceWorkerContextClient::workerContextStarted(
339 blink::WebServiceWorkerContextProxy* proxy) {
340 DCHECK(!worker_task_runner_.get());
341 DCHECK_NE(0, WorkerThread::GetCurrentId());
342 worker_task_runner_ = base::ThreadTaskRunnerHandle::Get();
343 // g_worker_client_tls.Pointer()->Get() could return NULL if this context
344 // gets deleted before workerContextStarted() is called.
345 DCHECK(g_worker_client_tls.Pointer()->Get() == NULL);
346 DCHECK(!proxy_);
347 g_worker_client_tls.Pointer()->Set(this);
348 proxy_ = proxy;
350 // Initialize pending callback maps. This needs to be freed on the
351 // same thread before the worker context goes away in
352 // willDestroyWorkerContext.
353 context_.reset(new WorkerContextData(this));
355 ServiceWorkerRegistrationObjectInfo registration_info;
356 ServiceWorkerVersionAttributes version_attrs;
357 provider_context_->GetRegistrationInfoAndVersionAttributes(&registration_info,
358 &version_attrs);
359 DCHECK_NE(registration_info.registration_id,
360 kInvalidServiceWorkerRegistrationId);
362 // Register Mojo services.
363 context_->service_registry.ServiceRegistry::AddService(
364 base::Bind(&ServicePortDispatcherImpl::Create,
365 context_->proxy_weak_factory.GetWeakPtr()));
366 context_->service_registry.ServiceRegistry::AddService(base::Bind(
367 &BackgroundSyncClientImpl::Create, registration_info.registration_id));
369 SetRegistrationInServiceWorkerGlobalScope();
371 Send(new EmbeddedWorkerHostMsg_WorkerScriptLoaded(
372 embedded_worker_id_, WorkerThread::GetCurrentId(),
373 provider_context_->provider_id()));
375 TRACE_EVENT_ASYNC_STEP_INTO0(
376 "ServiceWorker",
377 "ServiceWorkerContextClient::StartingWorkerContext",
378 this,
379 "ExecuteScript");
382 void ServiceWorkerContextClient::didEvaluateWorkerScript(bool success) {
383 Send(new EmbeddedWorkerHostMsg_WorkerScriptEvaluated(
384 embedded_worker_id_, success));
386 // Schedule a task to send back WorkerStarted asynchronously,
387 // so that at the time we send it we can be sure that the
388 // worker run loop has been started.
389 worker_task_runner_->PostTask(
390 FROM_HERE, base::Bind(&ServiceWorkerContextClient::SendWorkerStarted,
391 GetWeakPtr()));
394 void ServiceWorkerContextClient::didInitializeWorkerContext(
395 v8::Local<v8::Context> context,
396 const blink::WebURL& url) {
397 // TODO(annekao): Remove WebURL parameter from Blink, it's at best redundant
398 // given |script_url_|, and may be empty in the future.
399 // Also remove m_documentURL from ServiceWorkerGlobalScopeProxy.
400 GetContentClient()
401 ->renderer()
402 ->DidInitializeServiceWorkerContextOnWorkerThread(context, script_url_);
405 void ServiceWorkerContextClient::willDestroyWorkerContext(
406 v8::Local<v8::Context> context) {
407 // At this point WillStopCurrentWorkerThread is already called, so
408 // worker_task_runner_->RunsTasksOnCurrentThread() returns false
409 // (while we're still on the worker thread).
410 proxy_ = NULL;
412 // We have to clear callbacks now, as they need to be freed on the
413 // same thread.
414 context_.reset();
416 // This also lets the message filter stop dispatching messages to
417 // this client.
418 g_worker_client_tls.Pointer()->Set(NULL);
420 GetContentClient()->renderer()->WillDestroyServiceWorkerContextOnWorkerThread(
421 script_url_);
424 void ServiceWorkerContextClient::workerContextDestroyed() {
425 DCHECK(g_worker_client_tls.Pointer()->Get() == NULL);
427 // Now we should be able to free the WebEmbeddedWorker container on the
428 // main thread.
429 main_thread_task_runner_->PostTask(
430 FROM_HERE,
431 base::Bind(&CallWorkerContextDestroyedOnMainThread,
432 embedded_worker_id_));
435 void ServiceWorkerContextClient::reportException(
436 const blink::WebString& error_message,
437 int line_number,
438 int column_number,
439 const blink::WebString& source_url) {
440 Send(new EmbeddedWorkerHostMsg_ReportException(
441 embedded_worker_id_,
442 error_message,
443 line_number,
444 column_number, GURL(source_url)));
447 void ServiceWorkerContextClient::reportConsoleMessage(
448 int source,
449 int level,
450 const blink::WebString& message,
451 int line_number,
452 const blink::WebString& source_url) {
453 EmbeddedWorkerHostMsg_ReportConsoleMessage_Params params;
454 params.source_identifier = source;
455 params.message_level = level;
456 params.message = message;
457 params.line_number = line_number;
458 params.source_url = GURL(source_url);
460 Send(new EmbeddedWorkerHostMsg_ReportConsoleMessage(
461 embedded_worker_id_, params));
464 void ServiceWorkerContextClient::sendDevToolsMessage(
465 int call_id,
466 const blink::WebString& message,
467 const blink::WebString& state_cookie) {
468 DevToolsAgent::SendChunkedProtocolMessage(
469 sender_.get(), worker_devtools_agent_route_id_,
470 call_id, message.utf8(), state_cookie.utf8());
473 void ServiceWorkerContextClient::didHandleActivateEvent(
474 int request_id,
475 blink::WebServiceWorkerEventResult result) {
476 Send(new ServiceWorkerHostMsg_ActivateEventFinished(
477 GetRoutingID(), request_id, result));
480 void ServiceWorkerContextClient::didHandleInstallEvent(
481 int request_id,
482 blink::WebServiceWorkerEventResult result) {
483 Send(new ServiceWorkerHostMsg_InstallEventFinished(
484 GetRoutingID(), request_id, result));
487 void ServiceWorkerContextClient::didHandleFetchEvent(int request_id) {
488 Send(new ServiceWorkerHostMsg_FetchEventFinished(
489 GetRoutingID(), request_id,
490 SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
491 ServiceWorkerResponse()));
494 void ServiceWorkerContextClient::didHandleFetchEvent(
495 int request_id,
496 const blink::WebServiceWorkerResponse& web_response) {
497 ServiceWorkerHeaderMap headers;
498 GetServiceWorkerHeaderMapFromWebResponse(web_response, &headers);
499 ServiceWorkerResponse response(
500 web_response.url(), web_response.status(),
501 web_response.statusText().utf8(), web_response.responseType(), headers,
502 web_response.blobUUID().utf8(), web_response.blobSize(),
503 web_response.streamURL(), web_response.error());
504 Send(new ServiceWorkerHostMsg_FetchEventFinished(
505 GetRoutingID(), request_id,
506 SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
507 response));
510 void ServiceWorkerContextClient::didHandleNotificationClickEvent(
511 int request_id,
512 blink::WebServiceWorkerEventResult result) {
513 Send(new ServiceWorkerHostMsg_NotificationClickEventFinished(
514 GetRoutingID(), request_id));
517 void ServiceWorkerContextClient::didHandlePushEvent(
518 int request_id,
519 blink::WebServiceWorkerEventResult result) {
520 Send(new ServiceWorkerHostMsg_PushEventFinished(
521 GetRoutingID(), request_id, result));
524 void ServiceWorkerContextClient::didHandleSyncEvent(
525 int request_id,
526 blink::WebServiceWorkerEventResult result) {
527 const SyncCallback* callback =
528 context_->sync_event_callbacks.Lookup(request_id);
529 if (!callback)
530 return;
531 if (result == blink::WebServiceWorkerEventResultCompleted) {
532 callback->Run(SERVICE_WORKER_EVENT_STATUS_COMPLETED);
533 } else {
534 callback->Run(SERVICE_WORKER_EVENT_STATUS_REJECTED);
536 context_->sync_event_callbacks.Remove(request_id);
539 blink::WebServiceWorkerNetworkProvider*
540 ServiceWorkerContextClient::createServiceWorkerNetworkProvider(
541 blink::WebDataSource* data_source) {
542 DCHECK(main_thread_task_runner_->RunsTasksOnCurrentThread());
544 // Create a content::ServiceWorkerNetworkProvider for this data source so
545 // we can observe its requests.
546 scoped_ptr<ServiceWorkerNetworkProvider> provider(
547 new ServiceWorkerNetworkProvider(
548 MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER));
549 provider_context_ = provider->context();
551 // Tell the network provider about which version to load.
552 provider->SetServiceWorkerVersionId(service_worker_version_id_);
554 // The provider is kept around for the lifetime of the DataSource
555 // and ownership is transferred to the DataSource.
556 DataSourceExtraData* extra_data = new DataSourceExtraData();
557 data_source->setExtraData(extra_data);
558 ServiceWorkerNetworkProvider::AttachToDocumentState(
559 extra_data, provider.Pass());
561 // Blink is responsible for deleting the returned object.
562 return new WebServiceWorkerNetworkProviderImpl();
565 blink::WebServiceWorkerProvider*
566 ServiceWorkerContextClient::createServiceWorkerProvider() {
567 DCHECK(main_thread_task_runner_->RunsTasksOnCurrentThread());
568 DCHECK(provider_context_);
570 // Blink is responsible for deleting the returned object.
571 return new WebServiceWorkerProviderImpl(
572 sender_.get(), provider_context_.get());
575 void ServiceWorkerContextClient::postMessageToClient(
576 const blink::WebString& uuid,
577 const blink::WebString& message,
578 blink::WebMessagePortChannelArray* channels) {
579 // This may send channels for MessagePorts, and all internal book-keeping
580 // messages for MessagePort (e.g. QueueMessages) are sent from main thread
581 // (with thread hopping), so we need to do the same thread hopping here not
582 // to overtake those messages.
583 scoped_ptr<blink::WebMessagePortChannelArray> channel_array(channels);
584 main_thread_task_runner_->PostTask(
585 FROM_HERE,
586 base::Bind(&SendPostMessageToClientOnMainThread,
587 sender_,
588 GetRoutingID(),
589 base::UTF16ToUTF8(base::StringPiece16(uuid)),
590 static_cast<base::string16>(message),
591 base::Passed(&channel_array)));
594 void ServiceWorkerContextClient::postMessageToCrossOriginClient(
595 const blink::WebCrossOriginServiceWorkerClient& client,
596 const blink::WebString& message,
597 blink::WebMessagePortChannelArray* channels) {
598 // This may send channels for MessagePorts, and all internal book-keeping
599 // messages for MessagePort (e.g. QueueMessages) are sent from main thread
600 // (with thread hopping), so we need to do the same thread hopping here not
601 // to overtake those messages.
602 scoped_ptr<blink::WebMessagePortChannelArray> channel_array(channels);
603 main_thread_task_runner_->PostTask(
604 FROM_HERE,
605 base::Bind(&SendCrossOriginMessageToClientOnMainThread,
606 sender_, client.clientID,
607 static_cast<base::string16>(message),
608 base::Passed(&channel_array)));
611 void ServiceWorkerContextClient::focus(
612 const blink::WebString& uuid,
613 blink::WebServiceWorkerClientCallbacks* callback) {
614 DCHECK(callback);
615 int request_id = context_->client_callbacks.Add(callback);
616 Send(new ServiceWorkerHostMsg_FocusClient(
617 GetRoutingID(), request_id,
618 base::UTF16ToUTF8(base::StringPiece16(uuid))));
621 void ServiceWorkerContextClient::navigate(
622 const blink::WebString& uuid,
623 const blink::WebURL& url,
624 blink::WebServiceWorkerClientCallbacks* callback) {
625 DCHECK(callback);
626 int request_id = context_->client_callbacks.Add(callback);
627 Send(new ServiceWorkerHostMsg_NavigateClient(
628 GetRoutingID(), request_id, base::UTF16ToUTF8(base::StringPiece16(uuid)),
629 url));
632 void ServiceWorkerContextClient::skipWaiting(
633 blink::WebServiceWorkerSkipWaitingCallbacks* callbacks) {
634 DCHECK(callbacks);
635 int request_id = context_->skip_waiting_callbacks.Add(callbacks);
636 Send(new ServiceWorkerHostMsg_SkipWaiting(GetRoutingID(), request_id));
639 void ServiceWorkerContextClient::claim(
640 blink::WebServiceWorkerClientsClaimCallbacks* callbacks) {
641 DCHECK(callbacks);
642 int request_id = context_->claim_clients_callbacks.Add(callbacks);
643 Send(new ServiceWorkerHostMsg_ClaimClients(GetRoutingID(), request_id));
646 void ServiceWorkerContextClient::DispatchSyncEvent(
647 const blink::WebSyncRegistration& registration,
648 const SyncCallback& callback) {
649 TRACE_EVENT0("ServiceWorker",
650 "ServiceWorkerContextClient::DispatchSyncEvent");
651 int request_id =
652 context_->sync_event_callbacks.Add(new SyncCallback(callback));
653 proxy_->dispatchSyncEvent(request_id, registration);
656 void ServiceWorkerContextClient::Send(IPC::Message* message) {
657 sender_->Send(message);
660 void ServiceWorkerContextClient::SendWorkerStarted() {
661 DCHECK(worker_task_runner_->RunsTasksOnCurrentThread());
662 TRACE_EVENT_ASYNC_END0("ServiceWorker",
663 "ServiceWorkerContextClient::StartingWorkerContext",
664 this);
665 Send(new EmbeddedWorkerHostMsg_WorkerStarted(embedded_worker_id_));
668 void ServiceWorkerContextClient::SetRegistrationInServiceWorkerGlobalScope() {
669 DCHECK(worker_task_runner_->RunsTasksOnCurrentThread());
670 DCHECK(provider_context_);
672 ServiceWorkerRegistrationObjectInfo info;
673 ServiceWorkerVersionAttributes attrs;
674 bool found =
675 provider_context_->GetRegistrationInfoAndVersionAttributes(&info, &attrs);
676 if (!found)
677 return; // Cannot be associated with a registration in some tests.
679 ServiceWorkerDispatcher* dispatcher =
680 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
681 sender_.get(), main_thread_task_runner_.get());
683 // Register a registration and its version attributes with the dispatcher
684 // living on the worker thread.
685 scoped_refptr<WebServiceWorkerRegistrationImpl> registration(
686 dispatcher->CreateRegistration(info, attrs));
688 // WebServiceWorkerContextProxy::setRegistration cannot receive
689 // WebPassOwnPtr<WebServiceWorkerRegistrationImpl> yet, so pass a leaky handle
690 // for now.
691 // TODO(nhiroki): Make WebServiceWorkerContextProxy::setRegistration receive
692 // WebPassOwnPtr.
693 proxy_->setRegistration(registration->CreateLeakyHandle());
696 void ServiceWorkerContextClient::OnActivateEvent(int request_id) {
697 TRACE_EVENT0("ServiceWorker",
698 "ServiceWorkerContextClient::OnActivateEvent");
699 proxy_->dispatchActivateEvent(request_id);
702 void ServiceWorkerContextClient::OnInstallEvent(int request_id) {
703 TRACE_EVENT0("ServiceWorker",
704 "ServiceWorkerContextClient::OnInstallEvent");
705 proxy_->dispatchInstallEvent(request_id);
708 void ServiceWorkerContextClient::OnFetchEvent(
709 int request_id,
710 const ServiceWorkerFetchRequest& request) {
711 blink::WebServiceWorkerRequest webRequest;
712 TRACE_EVENT0("ServiceWorker",
713 "ServiceWorkerContextClient::OnFetchEvent");
714 webRequest.setURL(blink::WebURL(request.url));
715 webRequest.setMethod(blink::WebString::fromUTF8(request.method));
716 for (ServiceWorkerHeaderMap::const_iterator it = request.headers.begin();
717 it != request.headers.end();
718 ++it) {
719 webRequest.setHeader(blink::WebString::fromUTF8(it->first),
720 blink::WebString::fromUTF8(it->second));
722 if (!request.blob_uuid.empty()) {
723 webRequest.setBlob(blink::WebString::fromUTF8(request.blob_uuid),
724 request.blob_size);
726 webRequest.setReferrer(
727 blink::WebString::fromUTF8(request.referrer.url.spec()),
728 request.referrer.policy);
729 webRequest.setMode(GetBlinkFetchRequestMode(request.mode));
730 webRequest.setCredentialsMode(
731 GetBlinkFetchCredentialsMode(request.credentials_mode));
732 webRequest.setRedirectMode(GetBlinkFetchRedirectMode(request.redirect_mode));
733 webRequest.setRequestContext(
734 GetBlinkRequestContext(request.request_context_type));
735 webRequest.setFrameType(GetBlinkFrameType(request.frame_type));
736 webRequest.setIsReload(request.is_reload);
737 proxy_->dispatchFetchEvent(request_id, webRequest);
740 void ServiceWorkerContextClient::OnNotificationClickEvent(
741 int request_id,
742 int64_t persistent_notification_id,
743 const PlatformNotificationData& notification_data,
744 int action_index) {
745 TRACE_EVENT0("ServiceWorker",
746 "ServiceWorkerContextClient::OnNotificationClickEvent");
747 proxy_->dispatchNotificationClickEvent(
748 request_id,
749 persistent_notification_id,
750 ToWebNotificationData(notification_data),
751 action_index);
754 void ServiceWorkerContextClient::OnPushEvent(int request_id,
755 const std::string& data) {
756 TRACE_EVENT0("ServiceWorker",
757 "ServiceWorkerContextClient::OnPushEvent");
758 proxy_->dispatchPushEvent(request_id, blink::WebString::fromUTF8(data));
761 void ServiceWorkerContextClient::OnGeofencingEvent(
762 int request_id,
763 blink::WebGeofencingEventType event_type,
764 const std::string& region_id,
765 const blink::WebCircularGeofencingRegion& region) {
766 TRACE_EVENT0("ServiceWorker",
767 "ServiceWorkerContextClient::OnGeofencingEvent");
768 proxy_->dispatchGeofencingEvent(
769 request_id, event_type, blink::WebString::fromUTF8(region_id), region);
770 Send(new ServiceWorkerHostMsg_GeofencingEventFinished(GetRoutingID(),
771 request_id));
774 void ServiceWorkerContextClient::OnPostMessage(
775 const base::string16& message,
776 const std::vector<TransferredMessagePort>& sent_message_ports,
777 const std::vector<int>& new_routing_ids) {
778 TRACE_EVENT0("ServiceWorker",
779 "ServiceWorkerContextClient::OnPostEvent");
780 blink::WebMessagePortChannelArray ports =
781 WebMessagePortChannelImpl::CreatePorts(
782 sent_message_ports, new_routing_ids,
783 main_thread_task_runner_);
785 // dispatchMessageEvent is expected to execute onmessage function
786 // synchronously.
787 base::TimeTicks before = base::TimeTicks::Now();
788 proxy_->dispatchMessageEvent(message, ports);
789 UMA_HISTOGRAM_MEDIUM_TIMES(
790 "ServiceWorker.MessageEvent.Time",
791 base::TimeTicks::Now() - before);
794 void ServiceWorkerContextClient::OnCrossOriginMessageToWorker(
795 const NavigatorConnectClient& client,
796 const base::string16& message,
797 const std::vector<TransferredMessagePort>& sent_message_ports,
798 const std::vector<int>& new_routing_ids) {
799 TRACE_EVENT0("ServiceWorker",
800 "ServiceWorkerContextClient::OnCrossOriginMessageToWorker");
801 blink::WebMessagePortChannelArray ports =
802 WebMessagePortChannelImpl::CreatePorts(
803 sent_message_ports, new_routing_ids,
804 main_thread_task_runner_);
806 blink::WebCrossOriginServiceWorkerClient web_client;
807 web_client.origin = client.origin;
808 web_client.targetURL = client.target_url;
809 web_client.clientID = client.message_port_id;
810 proxy_->dispatchCrossOriginMessageEvent(web_client, message, ports);
813 void ServiceWorkerContextClient::OnDidGetClients(
814 int request_id, const std::vector<ServiceWorkerClientInfo>& clients) {
815 TRACE_EVENT0("ServiceWorker",
816 "ServiceWorkerContextClient::OnDidGetClients");
817 blink::WebServiceWorkerClientsCallbacks* callbacks =
818 context_->clients_callbacks.Lookup(request_id);
819 if (!callbacks) {
820 NOTREACHED() << "Got stray response: " << request_id;
821 return;
823 blink::WebServiceWorkerClientsInfo info;
824 blink::WebVector<blink::WebServiceWorkerClientInfo> convertedClients(
825 clients.size());
826 for (size_t i = 0; i < clients.size(); ++i)
827 convertedClients[i] = ToWebServiceWorkerClientInfo(clients[i]);
828 info.clients.swap(convertedClients);
829 callbacks->onSuccess(info);
830 context_->clients_callbacks.Remove(request_id);
833 void ServiceWorkerContextClient::OnOpenWindowResponse(
834 int request_id,
835 const ServiceWorkerClientInfo& client) {
836 TRACE_EVENT0("ServiceWorker",
837 "ServiceWorkerContextClient::OnOpenWindowResponse");
838 blink::WebServiceWorkerClientCallbacks* callbacks =
839 context_->client_callbacks.Lookup(request_id);
840 if (!callbacks) {
841 NOTREACHED() << "Got stray response: " << request_id;
842 return;
844 scoped_ptr<blink::WebServiceWorkerClientInfo> web_client;
845 if (!client.IsEmpty()) {
846 DCHECK(client.IsValid());
847 web_client.reset(new blink::WebServiceWorkerClientInfo(
848 ToWebServiceWorkerClientInfo(client)));
850 callbacks->onSuccess(adoptWebPtr(web_client.release()));
851 context_->client_callbacks.Remove(request_id);
854 void ServiceWorkerContextClient::OnOpenWindowError(
855 int request_id,
856 const std::string& message) {
857 TRACE_EVENT0("ServiceWorker",
858 "ServiceWorkerContextClient::OnOpenWindowError");
859 blink::WebServiceWorkerClientCallbacks* callbacks =
860 context_->client_callbacks.Lookup(request_id);
861 if (!callbacks) {
862 NOTREACHED() << "Got stray response: " << request_id;
863 return;
865 callbacks->onError(blink::WebServiceWorkerError(
866 blink::WebServiceWorkerError::ErrorTypeUnknown,
867 blink::WebString::fromUTF8(message)));
868 context_->client_callbacks.Remove(request_id);
871 void ServiceWorkerContextClient::OnFocusClientResponse(
872 int request_id, const ServiceWorkerClientInfo& client) {
873 TRACE_EVENT0("ServiceWorker",
874 "ServiceWorkerContextClient::OnFocusClientResponse");
875 blink::WebServiceWorkerClientCallbacks* callback =
876 context_->client_callbacks.Lookup(request_id);
877 if (!callback) {
878 NOTREACHED() << "Got stray response: " << request_id;
879 return;
881 if (!client.IsEmpty()) {
882 DCHECK(client.IsValid());
883 scoped_ptr<blink::WebServiceWorkerClientInfo> web_client (
884 new blink::WebServiceWorkerClientInfo(
885 ToWebServiceWorkerClientInfo(client)));
886 callback->onSuccess(adoptWebPtr(web_client.release()));
887 } else {
888 callback->onError(blink::WebServiceWorkerError(
889 blink::WebServiceWorkerError::ErrorTypeNotFound,
890 "The WindowClient was not found."));
893 context_->client_callbacks.Remove(request_id);
896 void ServiceWorkerContextClient::OnNavigateClientResponse(
897 int request_id,
898 const ServiceWorkerClientInfo& client) {
899 TRACE_EVENT0("ServiceWorker",
900 "ServiceWorkerContextClient::OnNavigateClientResponse");
901 blink::WebServiceWorkerClientCallbacks* callbacks =
902 context_->client_callbacks.Lookup(request_id);
903 if (!callbacks) {
904 NOTREACHED() << "Got stray response: " << request_id;
905 return;
907 scoped_ptr<blink::WebServiceWorkerClientInfo> web_client;
908 if (!client.IsEmpty()) {
909 DCHECK(client.IsValid());
910 web_client.reset(new blink::WebServiceWorkerClientInfo(
911 ToWebServiceWorkerClientInfo(client)));
913 callbacks->onSuccess(adoptWebPtr(web_client.release()));
914 context_->client_callbacks.Remove(request_id);
917 void ServiceWorkerContextClient::OnNavigateClientError(int request_id,
918 const GURL& url) {
919 TRACE_EVENT0("ServiceWorker",
920 "ServiceWorkerContextClient::OnNavigateClientError");
921 blink::WebServiceWorkerClientCallbacks* callbacks =
922 context_->client_callbacks.Lookup(request_id);
923 if (!callbacks) {
924 NOTREACHED() << "Got stray response: " << request_id;
925 return;
927 std::string message = "Cannot navigate to URL: " + url.spec();
928 callbacks->onError(blink::WebServiceWorkerError(
929 blink::WebServiceWorkerError::ErrorTypeUnknown,
930 blink::WebString::fromUTF8(message)));
931 context_->client_callbacks.Remove(request_id);
934 void ServiceWorkerContextClient::OnDidSkipWaiting(int request_id) {
935 TRACE_EVENT0("ServiceWorker",
936 "ServiceWorkerContextClient::OnDidSkipWaiting");
937 blink::WebServiceWorkerSkipWaitingCallbacks* callbacks =
938 context_->skip_waiting_callbacks.Lookup(request_id);
939 if (!callbacks) {
940 NOTREACHED() << "Got stray response: " << request_id;
941 return;
943 callbacks->onSuccess();
944 context_->skip_waiting_callbacks.Remove(request_id);
947 void ServiceWorkerContextClient::OnDidClaimClients(int request_id) {
948 TRACE_EVENT0("ServiceWorker",
949 "ServiceWorkerContextClient::OnDidClaimClients");
950 blink::WebServiceWorkerClientsClaimCallbacks* callbacks =
951 context_->claim_clients_callbacks.Lookup(request_id);
952 if (!callbacks) {
953 NOTREACHED() << "Got stray response: " << request_id;
954 return;
956 callbacks->onSuccess();
957 context_->claim_clients_callbacks.Remove(request_id);
960 void ServiceWorkerContextClient::OnClaimClientsError(
961 int request_id,
962 blink::WebServiceWorkerError::ErrorType error_type,
963 const base::string16& message) {
964 TRACE_EVENT0("ServiceWorker",
965 "ServiceWorkerContextClient::OnClaimClientsError");
966 blink::WebServiceWorkerClientsClaimCallbacks* callbacks =
967 context_->claim_clients_callbacks.Lookup(request_id);
968 if (!callbacks) {
969 NOTREACHED() << "Got stray response: " << request_id;
970 return;
972 callbacks->onError(blink::WebServiceWorkerError(error_type, message));
973 context_->claim_clients_callbacks.Remove(request_id);
976 void ServiceWorkerContextClient::OnPing() {
977 Send(new ServiceWorkerHostMsg_Pong(GetRoutingID()));
980 base::WeakPtr<ServiceWorkerContextClient>
981 ServiceWorkerContextClient::GetWeakPtr() {
982 DCHECK(worker_task_runner_->RunsTasksOnCurrentThread());
983 DCHECK(context_);
984 return context_->weak_factory.GetWeakPtr();
987 } // namespace content