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