[Android] Implement 3-way sensor fallback for Device Orientation.
[chromium-blink-merge.git] / content / renderer / service_worker / service_worker_context_client.cc
blob55cf381ce034c50eb5c4d170f7a106005cfd49cb
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"
58 namespace content {
60 namespace {
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())
69 return;
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 {
80 public:
81 DataSourceExtraData() {}
82 virtual ~DataSourceExtraData() {}
85 // Called on the main thread only and blink owns it.
86 class WebServiceWorkerNetworkProviderImpl
87 : public blink::WebServiceWorkerNetworkProvider {
88 public:
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,
105 int routing_id,
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,
116 int message_port_id,
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>(
132 credentials_mode);
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;
167 } // namespace
169 // Holding data that needs to be bound to the worker context on the
170 // worker thread.
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)>,
182 IDMapOwnPointer>;
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()),
231 proxy_(nullptr) {
232 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
233 "ServiceWorkerContextClient::StartingWorkerContext",
234 this);
235 TRACE_EVENT_ASYNC_STEP_INTO0(
236 "ServiceWorker",
237 "ServiceWorkerContextClient::StartingWorkerContext",
238 this,
239 "PrepareWorker");
242 ServiceWorkerContextClient::~ServiceWorkerContextClient() {}
244 void ServiceWorkerContextClient::OnMessageReceived(
245 int thread_id,
246 int embedded_worker_id,
247 const IPC::Message& message) {
248 CHECK_EQ(embedded_worker_id_, embedded_worker_id);
249 bool handled = true;
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,
265 OnOpenWindowError)
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()
278 DCHECK(handled);
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) {
295 DCHECK(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) {
307 DCHECK(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,
314 const char* data,
315 size_t size) {
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());
331 DCHECK(!proxy_);
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);
347 DCHECK(!proxy_);
348 g_worker_client_tls.Pointer()->Set(this);
349 proxy_ = proxy;
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(
366 embedded_worker_id_,
367 WorkerTaskRunner::Instance()->CurrentWorkerId(),
368 provider_context_->provider_id()));
370 TRACE_EVENT_ASYNC_STEP_INTO0(
371 "ServiceWorker",
372 "ServiceWorkerContextClient::StartingWorkerContext",
373 this,
374 "ExecuteScript");
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,
386 GetWeakPtr()));
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));
395 GetContentClient()
396 ->renderer()
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).
404 proxy_ = NULL;
406 // We have to clear callbacks now, as they need to be freed on the
407 // same thread.
408 context_.reset();
410 // This also lets the message filter stop dispatching messages to
411 // this client.
412 g_worker_client_tls.Pointer()->Set(NULL);
414 GetContentClient()->renderer()->WillDestroyServiceWorkerContextOnWorkerThread(
415 script_url_);
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
422 // main thread.
423 main_thread_task_runner_->PostTask(
424 FROM_HERE,
425 base::Bind(&CallWorkerContextDestroyedOnMainThread,
426 embedded_worker_id_));
429 void ServiceWorkerContextClient::reportException(
430 const blink::WebString& error_message,
431 int line_number,
432 int column_number,
433 const blink::WebString& source_url) {
434 Send(new EmbeddedWorkerHostMsg_ReportException(
435 embedded_worker_id_,
436 error_message,
437 line_number,
438 column_number, GURL(source_url)));
441 void ServiceWorkerContextClient::reportConsoleMessage(
442 int source,
443 int level,
444 const blink::WebString& message,
445 int line_number,
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(
459 int call_id,
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(
468 int request_id,
469 blink::WebServiceWorkerEventResult result) {
470 Send(new ServiceWorkerHostMsg_ActivateEventFinished(
471 GetRoutingID(), request_id, result));
474 void ServiceWorkerContextClient::didHandleInstallEvent(
475 int request_id,
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(
489 int request_id,
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,
501 response));
504 void ServiceWorkerContextClient::didHandleNotificationClickEvent(
505 int request_id,
506 blink::WebServiceWorkerEventResult result) {
507 Send(new ServiceWorkerHostMsg_NotificationClickEventFinished(
508 GetRoutingID(), request_id));
511 void ServiceWorkerContextClient::didHandlePushEvent(
512 int request_id,
513 blink::WebServiceWorkerEventResult result) {
514 Send(new ServiceWorkerHostMsg_PushEventFinished(
515 GetRoutingID(), request_id, result));
518 void ServiceWorkerContextClient::didHandleSyncEvent(
519 int request_id,
520 blink::WebServiceWorkerEventResult result) {
521 const SyncCallback* callback =
522 context_->sync_event_callbacks.Lookup(request_id);
523 if (!callback)
524 return;
525 if (result == blink::WebServiceWorkerEventResultCompleted) {
526 callback->Run(SERVICE_WORKER_EVENT_STATUS_COMPLETED);
527 } else {
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(
579 FROM_HERE,
580 base::Bind(&SendPostMessageToClientOnMainThread,
581 sender_,
582 GetRoutingID(),
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(
598 FROM_HERE,
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) {
608 DCHECK(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) {
619 DCHECK(callback);
620 int request_id = context_->client_callbacks.Add(callback);
621 Send(new ServiceWorkerHostMsg_NavigateClient(
622 GetRoutingID(), request_id, base::UTF16ToUTF8(base::StringPiece16(uuid)),
623 url));
626 void ServiceWorkerContextClient::skipWaiting(
627 blink::WebServiceWorkerSkipWaitingCallbacks* callbacks) {
628 DCHECK(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) {
635 DCHECK(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");
645 int request_id =
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",
658 this);
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;
668 bool found =
669 provider_context_->GetRegistrationInfoAndVersionAttributes(&info, &attrs);
670 if (!found)
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(
704 int request_id,
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();
713 ++it) {
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),
719 request.blob_size);
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(
736 int request_id,
737 int64_t persistent_notification_id,
738 const PlatformNotificationData& notification_data,
739 int action_index) {
740 TRACE_EVENT0("ServiceWorker",
741 "ServiceWorkerContextClient::OnNotificationClickEvent");
742 proxy_->dispatchNotificationClickEvent(
743 request_id,
744 persistent_notification_id,
745 ToWebNotificationData(notification_data),
746 action_index);
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(
757 int request_id,
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(),
766 request_id));
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
781 // synchronously.
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);
814 if (!callbacks) {
815 NOTREACHED() << "Got stray response: " << request_id;
816 return;
818 blink::WebServiceWorkerClientsInfo info;
819 blink::WebVector<blink::WebServiceWorkerClientInfo> convertedClients(
820 clients.size());
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(
829 int request_id,
830 const ServiceWorkerClientInfo& client) {
831 TRACE_EVENT0("ServiceWorker",
832 "ServiceWorkerContextClient::OnOpenWindowResponse");
833 blink::WebServiceWorkerClientCallbacks* callbacks =
834 context_->client_callbacks.Lookup(request_id);
835 if (!callbacks) {
836 NOTREACHED() << "Got stray response: " << request_id;
837 return;
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(
850 int request_id,
851 const std::string& message) {
852 TRACE_EVENT0("ServiceWorker",
853 "ServiceWorkerContextClient::OnOpenWindowError");
854 blink::WebServiceWorkerClientCallbacks* callbacks =
855 context_->client_callbacks.Lookup(request_id);
856 if (!callbacks) {
857 NOTREACHED() << "Got stray response: " << request_id;
858 return;
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);
872 if (!callback) {
873 NOTREACHED() << "Got stray response: " << request_id;
874 return;
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()));
882 } else {
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(
892 int request_id,
893 const ServiceWorkerClientInfo& client) {
894 TRACE_EVENT0("ServiceWorker",
895 "ServiceWorkerContextClient::OnNavigateClientResponse");
896 blink::WebServiceWorkerClientCallbacks* callbacks =
897 context_->client_callbacks.Lookup(request_id);
898 if (!callbacks) {
899 NOTREACHED() << "Got stray response: " << request_id;
900 return;
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,
913 const GURL& url) {
914 TRACE_EVENT0("ServiceWorker",
915 "ServiceWorkerContextClient::OnNavigateClientError");
916 blink::WebServiceWorkerClientCallbacks* callbacks =
917 context_->client_callbacks.Lookup(request_id);
918 if (!callbacks) {
919 NOTREACHED() << "Got stray response: " << request_id;
920 return;
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);
934 if (!callbacks) {
935 NOTREACHED() << "Got stray response: " << request_id;
936 return;
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);
947 if (!callbacks) {
948 NOTREACHED() << "Got stray response: " << request_id;
949 return;
951 callbacks->onSuccess();
952 context_->claim_clients_callbacks.Remove(request_id);
955 void ServiceWorkerContextClient::OnClaimClientsError(
956 int request_id,
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);
963 if (!callbacks) {
964 NOTREACHED() << "Got stray response: " << request_id;
965 return;
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());
978 DCHECK(context_);
979 return context_->weak_factory.GetWeakPtr();
982 } // namespace content