1 // Copyright 2013 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/child/service_worker/service_worker_dispatcher.h"
7 #include "base/debug/trace_event.h"
8 #include "base/lazy_instance.h"
9 #include "base/stl_util.h"
10 #include "base/threading/thread_local.h"
11 #include "content/child/child_thread.h"
12 #include "content/child/service_worker/service_worker_handle_reference.h"
13 #include "content/child/service_worker/service_worker_provider_context.h"
14 #include "content/child/service_worker/service_worker_registration_handle_reference.h"
15 #include "content/child/service_worker/web_service_worker_impl.h"
16 #include "content/child/service_worker/web_service_worker_registration_impl.h"
17 #include "content/child/thread_safe_sender.h"
18 #include "content/child/webmessageportchannel_impl.h"
19 #include "content/common/service_worker/service_worker_messages.h"
20 #include "content/common/service_worker/service_worker_types.h"
21 #include "content/public/common/url_utils.h"
22 #include "third_party/WebKit/public/platform/WebServiceWorkerClientsInfo.h"
23 #include "third_party/WebKit/public/platform/WebServiceWorkerProviderClient.h"
24 #include "third_party/WebKit/public/platform/WebString.h"
25 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
27 using blink::WebServiceWorkerError
;
28 using blink::WebServiceWorkerProvider
;
29 using base::ThreadLocalPointer
;
35 base::LazyInstance
<ThreadLocalPointer
<ServiceWorkerDispatcher
> >::Leaky
36 g_dispatcher_tls
= LAZY_INSTANCE_INITIALIZER
;
38 ServiceWorkerDispatcher
* const kHasBeenDeleted
=
39 reinterpret_cast<ServiceWorkerDispatcher
*>(0x1);
41 int CurrentWorkerId() {
42 return WorkerTaskRunner::Instance()->CurrentWorkerId();
47 ServiceWorkerDispatcher::ServiceWorkerDispatcher(
48 ThreadSafeSender
* thread_safe_sender
)
49 : thread_safe_sender_(thread_safe_sender
) {
50 g_dispatcher_tls
.Pointer()->Set(this);
53 ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
54 g_dispatcher_tls
.Pointer()->Set(kHasBeenDeleted
);
57 void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
59 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher
, msg
)
60 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistration
,
61 OnAssociateRegistration
)
62 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DisassociateRegistration
,
63 OnDisassociateRegistration
)
64 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered
, OnRegistered
)
65 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered
,
67 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistration
,
69 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError
,
71 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistrationError
,
72 OnUnregistrationError
)
73 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationError
,
74 OnGetRegistrationError
)
75 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged
,
76 OnServiceWorkerStateChanged
)
77 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes
,
78 OnSetVersionAttributes
)
79 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_UpdateFound
,
81 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker
,
82 OnSetControllerServiceWorker
)
83 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument
,
85 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_GetClientInfo
,
87 IPC_MESSAGE_UNHANDLED(handled
= false)
89 DCHECK(handled
) << "Unhandled message:" << msg
.type();
92 bool ServiceWorkerDispatcher::Send(IPC::Message
* msg
) {
93 return thread_safe_sender_
->Send(msg
);
96 void ServiceWorkerDispatcher::RegisterServiceWorker(
99 const GURL
& script_url
,
100 WebServiceWorkerRegistrationCallbacks
* callbacks
) {
103 if (pattern
.possibly_invalid_spec().size() > GetMaxURLChars() ||
104 script_url
.possibly_invalid_spec().size() > GetMaxURLChars()) {
105 scoped_ptr
<WebServiceWorkerRegistrationCallbacks
>
106 owned_callbacks(callbacks
);
107 std::string
error_message(kServiceWorkerRegisterErrorPrefix
);
108 error_message
+= "The provided scriptURL or scope is too long.";
109 scoped_ptr
<WebServiceWorkerError
> error(
110 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity
,
111 blink::WebString::fromUTF8(error_message
)));
112 callbacks
->onError(error
.release());
116 int request_id
= pending_registration_callbacks_
.Add(callbacks
);
117 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
118 "ServiceWorkerDispatcher::RegisterServiceWorker",
120 "Scope", pattern
.spec(),
121 "Script URL", script_url
.spec());
122 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
123 CurrentWorkerId(), request_id
, provider_id
, pattern
, script_url
));
126 void ServiceWorkerDispatcher::UnregisterServiceWorker(
129 WebServiceWorkerUnregistrationCallbacks
* callbacks
) {
132 if (pattern
.possibly_invalid_spec().size() > GetMaxURLChars()) {
133 scoped_ptr
<WebServiceWorkerUnregistrationCallbacks
>
134 owned_callbacks(callbacks
);
135 std::string
error_message(kServiceWorkerUnregisterErrorPrefix
);
136 error_message
+= "The provided scope is too long.";
137 scoped_ptr
<WebServiceWorkerError
> error(
138 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity
,
139 blink::WebString::fromUTF8(error_message
)));
140 callbacks
->onError(error
.release());
144 int request_id
= pending_unregistration_callbacks_
.Add(callbacks
);
145 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
146 "ServiceWorkerDispatcher::UnregisterServiceWorker",
148 "Scope", pattern
.spec());
149 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
150 CurrentWorkerId(), request_id
, provider_id
, pattern
));
153 void ServiceWorkerDispatcher::GetRegistration(
155 const GURL
& document_url
,
156 WebServiceWorkerRegistrationCallbacks
* callbacks
) {
159 if (document_url
.possibly_invalid_spec().size() > GetMaxURLChars()) {
160 scoped_ptr
<WebServiceWorkerRegistrationCallbacks
>
161 owned_callbacks(callbacks
);
162 std::string
error_message(kServiceWorkerGetRegistrationErrorPrefix
);
163 error_message
+= "The provided documentURL is too long.";
164 scoped_ptr
<WebServiceWorkerError
> error(
165 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity
,
166 blink::WebString::fromUTF8(error_message
)));
167 callbacks
->onError(error
.release());
171 int request_id
= pending_get_registration_callbacks_
.Add(callbacks
);
172 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
173 "ServiceWorkerDispatcher::GetRegistration",
175 "Document URL", document_url
.spec());
176 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetRegistration(
177 CurrentWorkerId(), request_id
, provider_id
, document_url
));
180 void ServiceWorkerDispatcher::AddProviderContext(
181 ServiceWorkerProviderContext
* provider_context
) {
182 DCHECK(provider_context
);
183 int provider_id
= provider_context
->provider_id();
184 DCHECK(!ContainsKey(provider_contexts_
, provider_id
));
185 provider_contexts_
[provider_id
] = provider_context
;
188 void ServiceWorkerDispatcher::RemoveProviderContext(
189 ServiceWorkerProviderContext
* provider_context
) {
190 DCHECK(provider_context
);
191 DCHECK(ContainsKey(provider_contexts_
, provider_context
->provider_id()));
192 provider_contexts_
.erase(provider_context
->provider_id());
193 worker_to_provider_
.erase(provider_context
->installing_handle_id());
194 worker_to_provider_
.erase(provider_context
->waiting_handle_id());
195 worker_to_provider_
.erase(provider_context
->active_handle_id());
196 worker_to_provider_
.erase(provider_context
->controller_handle_id());
199 void ServiceWorkerDispatcher::AddProviderClient(
201 blink::WebServiceWorkerProviderClient
* client
) {
203 DCHECK(!ContainsKey(provider_clients_
, provider_id
));
204 provider_clients_
[provider_id
] = client
;
207 void ServiceWorkerDispatcher::RemoveProviderClient(int provider_id
) {
208 // This could be possibly called multiple times to ensure termination.
209 if (ContainsKey(provider_clients_
, provider_id
))
210 provider_clients_
.erase(provider_id
);
213 ServiceWorkerDispatcher
*
214 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
215 ThreadSafeSender
* thread_safe_sender
) {
216 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
) {
217 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
218 g_dispatcher_tls
.Pointer()->Set(NULL
);
220 if (g_dispatcher_tls
.Pointer()->Get())
221 return g_dispatcher_tls
.Pointer()->Get();
223 ServiceWorkerDispatcher
* dispatcher
=
224 new ServiceWorkerDispatcher(thread_safe_sender
);
225 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
226 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher
);
230 ServiceWorkerDispatcher
* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
231 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
)
233 return g_dispatcher_tls
.Pointer()->Get();
236 void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
240 WebServiceWorkerImpl
* ServiceWorkerDispatcher::GetServiceWorker(
241 const ServiceWorkerObjectInfo
& info
,
243 if (info
.handle_id
== kInvalidServiceWorkerHandleId
)
246 WorkerObjectMap::iterator existing_worker
=
247 service_workers_
.find(info
.handle_id
);
249 if (existing_worker
!= service_workers_
.end()) {
251 // We are instructed to adopt a handle but we already have one, so
252 // adopt and destroy a handle ref.
253 ServiceWorkerHandleReference::Adopt(info
, thread_safe_sender_
.get());
255 return existing_worker
->second
;
258 scoped_ptr
<ServiceWorkerHandleReference
> handle_ref
=
260 ? ServiceWorkerHandleReference::Adopt(info
, thread_safe_sender_
.get())
261 : ServiceWorkerHandleReference::Create(info
,
262 thread_safe_sender_
.get());
263 // WebServiceWorkerImpl constructor calls AddServiceWorker.
264 return new WebServiceWorkerImpl(handle_ref
.Pass(), thread_safe_sender_
.get());
267 WebServiceWorkerRegistrationImpl
*
268 ServiceWorkerDispatcher::FindServiceWorkerRegistration(
269 const ServiceWorkerRegistrationObjectInfo
& info
,
271 RegistrationObjectMap::iterator registration
=
272 registrations_
.find(info
.handle_id
);
273 if (registration
== registrations_
.end())
276 // We are instructed to adopt a handle but we already have one, so
277 // adopt and destroy a handle ref.
278 ServiceWorkerRegistrationHandleReference::Adopt(
279 info
, thread_safe_sender_
.get());
281 return registration
->second
;
284 WebServiceWorkerRegistrationImpl
*
285 ServiceWorkerDispatcher::CreateServiceWorkerRegistration(
286 const ServiceWorkerRegistrationObjectInfo
& info
,
288 DCHECK(!FindServiceWorkerRegistration(info
, adopt_handle
));
289 if (info
.handle_id
== kInvalidServiceWorkerRegistrationHandleId
)
292 scoped_ptr
<ServiceWorkerRegistrationHandleReference
> handle_ref
=
293 adopt_handle
? ServiceWorkerRegistrationHandleReference::Adopt(
294 info
, thread_safe_sender_
.get())
295 : ServiceWorkerRegistrationHandleReference::Create(
296 info
, thread_safe_sender_
.get());
298 // WebServiceWorkerRegistrationImpl constructor calls
299 // AddServiceWorkerRegistration.
300 return new WebServiceWorkerRegistrationImpl(handle_ref
.Pass());
303 void ServiceWorkerDispatcher::OnAssociateRegistration(
306 const ServiceWorkerRegistrationObjectInfo
& info
,
307 const ServiceWorkerVersionAttributes
& attrs
) {
308 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
309 if (provider
== provider_contexts_
.end())
311 provider
->second
->OnAssociateRegistration(info
, attrs
);
312 if (attrs
.installing
.handle_id
!= kInvalidServiceWorkerHandleId
)
313 worker_to_provider_
[attrs
.installing
.handle_id
] = provider
->second
;
314 if (attrs
.waiting
.handle_id
!= kInvalidServiceWorkerHandleId
)
315 worker_to_provider_
[attrs
.waiting
.handle_id
] = provider
->second
;
316 if (attrs
.active
.handle_id
!= kInvalidServiceWorkerHandleId
)
317 worker_to_provider_
[attrs
.active
.handle_id
] = provider
->second
;
320 void ServiceWorkerDispatcher::OnDisassociateRegistration(
323 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
324 if (provider
== provider_contexts_
.end())
326 provider
->second
->OnDisassociateRegistration();
327 worker_to_provider_
.erase(provider
->second
->installing_handle_id());
328 worker_to_provider_
.erase(provider
->second
->waiting_handle_id());
329 worker_to_provider_
.erase(provider
->second
->active_handle_id());
330 worker_to_provider_
.erase(provider
->second
->controller_handle_id());
333 void ServiceWorkerDispatcher::OnRegistered(
336 const ServiceWorkerRegistrationObjectInfo
& info
,
337 const ServiceWorkerVersionAttributes
& attrs
) {
338 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
339 "ServiceWorkerDispatcher::RegisterServiceWorker",
342 TRACE_EVENT_ASYNC_END0("ServiceWorker",
343 "ServiceWorkerDispatcher::RegisterServiceWorker",
345 WebServiceWorkerRegistrationCallbacks
* callbacks
=
346 pending_registration_callbacks_
.Lookup(request_id
);
351 callbacks
->onSuccess(FindOrCreateRegistration(info
, attrs
));
352 pending_registration_callbacks_
.Remove(request_id
);
355 void ServiceWorkerDispatcher::OnUnregistered(int thread_id
,
358 TRACE_EVENT_ASYNC_STEP_INTO0(
360 "ServiceWorkerDispatcher::UnregisterServiceWorker",
363 TRACE_EVENT_ASYNC_END0("ServiceWorker",
364 "ServiceWorkerDispatcher::UnregisterServiceWorker",
366 WebServiceWorkerUnregistrationCallbacks
* callbacks
=
367 pending_unregistration_callbacks_
.Lookup(request_id
);
371 callbacks
->onSuccess(&is_success
);
372 pending_unregistration_callbacks_
.Remove(request_id
);
375 void ServiceWorkerDispatcher::OnDidGetRegistration(
378 const ServiceWorkerRegistrationObjectInfo
& info
,
379 const ServiceWorkerVersionAttributes
& attrs
) {
380 TRACE_EVENT_ASYNC_STEP_INTO0(
382 "ServiceWorkerDispatcher::GetRegistration",
384 "OnDidGetRegistration");
385 TRACE_EVENT_ASYNC_END0("ServiceWorker",
386 "ServiceWorkerDispatcher::GetRegistration",
388 WebServiceWorkerRegistrationCallbacks
* callbacks
=
389 pending_get_registration_callbacks_
.Lookup(request_id
);
394 WebServiceWorkerRegistrationImpl
* registration
= NULL
;
395 if (info
.handle_id
!= kInvalidServiceWorkerHandleId
)
396 registration
= FindOrCreateRegistration(info
, attrs
);
398 callbacks
->onSuccess(registration
);
399 pending_get_registration_callbacks_
.Remove(request_id
);
402 void ServiceWorkerDispatcher::OnRegistrationError(
405 WebServiceWorkerError::ErrorType error_type
,
406 const base::string16
& message
) {
407 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
408 "ServiceWorkerDispatcher::RegisterServiceWorker",
410 "OnRegistrationError");
411 TRACE_EVENT_ASYNC_END0("ServiceWorker",
412 "ServiceWorkerDispatcher::RegisterServiceWorker",
414 WebServiceWorkerRegistrationCallbacks
* callbacks
=
415 pending_registration_callbacks_
.Lookup(request_id
);
420 scoped_ptr
<WebServiceWorkerError
> error(
421 new WebServiceWorkerError(error_type
, message
));
422 callbacks
->onError(error
.release());
423 pending_registration_callbacks_
.Remove(request_id
);
426 void ServiceWorkerDispatcher::OnUnregistrationError(
429 WebServiceWorkerError::ErrorType error_type
,
430 const base::string16
& message
) {
431 TRACE_EVENT_ASYNC_STEP_INTO0(
433 "ServiceWorkerDispatcher::UnregisterServiceWorker",
435 "OnUnregistrationError");
436 TRACE_EVENT_ASYNC_END0("ServiceWorker",
437 "ServiceWorkerDispatcher::UnregisterServiceWorker",
439 WebServiceWorkerUnregistrationCallbacks
* callbacks
=
440 pending_unregistration_callbacks_
.Lookup(request_id
);
445 scoped_ptr
<WebServiceWorkerError
> error(
446 new WebServiceWorkerError(error_type
, message
));
447 callbacks
->onError(error
.release());
448 pending_unregistration_callbacks_
.Remove(request_id
);
451 void ServiceWorkerDispatcher::OnGetRegistrationError(
454 WebServiceWorkerError::ErrorType error_type
,
455 const base::string16
& message
) {
456 TRACE_EVENT_ASYNC_STEP_INTO0(
458 "ServiceWorkerDispatcher::GetRegistration",
460 "OnGetRegistrationError");
461 TRACE_EVENT_ASYNC_END0("ServiceWorker",
462 "ServiceWorkerDispatcher::GetRegistration",
464 WebServiceWorkerGetRegistrationCallbacks
* callbacks
=
465 pending_get_registration_callbacks_
.Lookup(request_id
);
470 scoped_ptr
<WebServiceWorkerError
> error(
471 new WebServiceWorkerError(error_type
, message
));
472 callbacks
->onError(error
.release());
473 pending_get_registration_callbacks_
.Remove(request_id
);
476 void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
479 blink::WebServiceWorkerState state
) {
480 TRACE_EVENT2("ServiceWorker",
481 "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
482 "Thread ID", thread_id
,
484 WorkerObjectMap::iterator worker
= service_workers_
.find(handle_id
);
485 if (worker
!= service_workers_
.end())
486 worker
->second
->OnStateChanged(state
);
488 WorkerToProviderMap::iterator provider
= worker_to_provider_
.find(handle_id
);
489 if (provider
!= worker_to_provider_
.end())
490 provider
->second
->OnServiceWorkerStateChanged(handle_id
, state
);
493 void ServiceWorkerDispatcher::OnSetVersionAttributes(
496 int registration_handle_id
,
498 const ServiceWorkerVersionAttributes
& attrs
) {
499 TRACE_EVENT1("ServiceWorker",
500 "ServiceWorkerDispatcher::OnSetVersionAttributes",
501 "Thread ID", thread_id
);
503 ChangedVersionAttributesMask
mask(changed_mask
);
504 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
505 if (provider
!= provider_contexts_
.end() &&
506 provider
->second
->registration_handle_id() == registration_handle_id
) {
507 if (mask
.installing_changed()) {
508 worker_to_provider_
.erase(provider
->second
->installing_handle_id());
509 if (attrs
.installing
.handle_id
!= kInvalidServiceWorkerHandleId
)
510 worker_to_provider_
[attrs
.installing
.handle_id
] = provider
->second
;
512 if (mask
.waiting_changed()) {
513 worker_to_provider_
.erase(provider
->second
->waiting_handle_id());
514 if (attrs
.waiting
.handle_id
!= kInvalidServiceWorkerHandleId
)
515 worker_to_provider_
[attrs
.waiting
.handle_id
] = provider
->second
;
517 if (mask
.active_changed()) {
518 worker_to_provider_
.erase(provider
->second
->active_handle_id());
519 if (attrs
.active
.handle_id
!= kInvalidServiceWorkerHandleId
)
520 worker_to_provider_
[attrs
.active
.handle_id
] = provider
->second
;
522 provider
->second
->SetVersionAttributes(mask
, attrs
);
525 RegistrationObjectMap::iterator found
=
526 registrations_
.find(registration_handle_id
);
527 if (found
!= registrations_
.end()) {
528 // Populate the version fields (eg. .installing) with new worker objects.
529 if (mask
.installing_changed())
530 found
->second
->SetInstalling(GetServiceWorker(attrs
.installing
, false));
531 if (mask
.waiting_changed())
532 found
->second
->SetWaiting(GetServiceWorker(attrs
.waiting
, false));
533 if (mask
.active_changed())
534 found
->second
->SetActive(GetServiceWorker(attrs
.active
, false));
537 if (mask
.active_changed())
538 SetReadyRegistration(provider_id
, registration_handle_id
);
541 void ServiceWorkerDispatcher::OnUpdateFound(
543 const ServiceWorkerRegistrationObjectInfo
& info
) {
544 TRACE_EVENT0("ServiceWorker",
545 "ServiceWorkerDispatcher::OnUpdateFound");
546 RegistrationObjectMap::iterator found
= registrations_
.find(info
.handle_id
);
547 if (found
!= registrations_
.end())
548 found
->second
->OnUpdateFound();
551 void ServiceWorkerDispatcher::SetReadyRegistration(
553 int registration_handle_id
) {
554 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
555 if (provider
== provider_contexts_
.end() ||
556 provider
->second
->registration_handle_id() != registration_handle_id
||
557 provider
->second
->active_handle_id() == kInvalidServiceWorkerHandleId
) {
561 ProviderClientMap::iterator client
= provider_clients_
.find(provider_id
);
562 if (client
== provider_clients_
.end())
565 ServiceWorkerRegistrationObjectInfo info
=
566 provider
->second
->registration()->info();
567 WebServiceWorkerRegistrationImpl
* registration
=
568 FindServiceWorkerRegistration(info
, false);
570 registration
= CreateServiceWorkerRegistration(info
, false);
571 ServiceWorkerVersionAttributes attrs
=
572 provider
->second
->GetVersionAttributes();
573 registration
->SetInstalling(GetServiceWorker(attrs
.installing
, false));
574 registration
->SetWaiting(GetServiceWorker(attrs
.waiting
, false));
575 registration
->SetActive(GetServiceWorker(attrs
.active
, false));
578 // Resolve the .ready promise with the registration object.
579 client
->second
->setReadyRegistration(registration
);
582 void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
585 const ServiceWorkerObjectInfo
& info
,
586 bool should_notify_controllerchange
) {
587 TRACE_EVENT2("ServiceWorker",
588 "ServiceWorkerDispatcher::OnSetControllerServiceWorker",
589 "Thread ID", thread_id
,
590 "Provider ID", provider_id
);
592 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
593 if (provider
!= provider_contexts_
.end()) {
594 worker_to_provider_
.erase(provider
->second
->controller_handle_id());
595 if (info
.handle_id
!= kInvalidServiceWorkerHandleId
)
596 worker_to_provider_
[info
.handle_id
] = provider
->second
;
597 provider
->second
->OnSetControllerServiceWorker(info
);
600 ProviderClientMap::iterator found
= provider_clients_
.find(provider_id
);
601 if (found
!= provider_clients_
.end()) {
602 // Populate the .controller field with the new worker object.
603 found
->second
->setController(GetServiceWorker(info
, false),
604 should_notify_controllerchange
);
608 void ServiceWorkerDispatcher::OnPostMessage(
611 const base::string16
& message
,
612 const std::vector
<int>& sent_message_port_ids
,
613 const std::vector
<int>& new_routing_ids
) {
614 // Make sure we're on the main document thread. (That must be the only
615 // thread we get this message)
616 DCHECK(ChildThread::current());
617 TRACE_EVENT1("ServiceWorker",
618 "ServiceWorkerDispatcher::OnPostMessage",
619 "Thread ID", thread_id
);
621 ProviderClientMap::iterator found
= provider_clients_
.find(provider_id
);
622 if (found
== provider_clients_
.end()) {
623 // For now we do no queueing for messages sent to nonexistent / unattached
628 std::vector
<WebMessagePortChannelImpl
*> ports
;
629 if (!sent_message_port_ids
.empty()) {
630 ports
.resize(sent_message_port_ids
.size());
631 for (size_t i
= 0; i
< sent_message_port_ids
.size(); ++i
) {
632 ports
[i
] = new WebMessagePortChannelImpl(
633 new_routing_ids
[i
], sent_message_port_ids
[i
],
634 base::MessageLoopProxy::current());
638 found
->second
->dispatchMessageEvent(message
, ports
);
641 void ServiceWorkerDispatcher::OnGetClientInfo(int thread_id
,
642 int embedded_worker_id
,
645 blink::WebServiceWorkerClientInfo info
;
646 ProviderClientMap::iterator found
= provider_clients_
.find(provider_id
);
647 // TODO(ksakamoto): Could we track these values in the browser side? Except
648 // for |isFocused|, it would be pretty easy.
649 if (found
!= provider_clients_
.end() && found
->second
->getClientInfo(&info
)) {
650 ServiceWorkerClientInfo result
;
651 result
.client_id
= info
.clientID
;
652 result
.page_visibility_state
= info
.pageVisibilityState
;
653 result
.is_focused
= info
.isFocused
;
654 result
.url
= info
.url
;
655 result
.frame_type
= static_cast<RequestContextFrameType
>(info
.frameType
);
657 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetClientInfoSuccess(
658 embedded_worker_id
, request_id
, result
));
660 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetClientInfoError(
661 embedded_worker_id
, request_id
));
665 void ServiceWorkerDispatcher::AddServiceWorker(
666 int handle_id
, WebServiceWorkerImpl
* worker
) {
667 DCHECK(!ContainsKey(service_workers_
, handle_id
));
668 service_workers_
[handle_id
] = worker
;
671 void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id
) {
672 DCHECK(ContainsKey(service_workers_
, handle_id
));
673 service_workers_
.erase(handle_id
);
676 void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
677 int registration_handle_id
,
678 WebServiceWorkerRegistrationImpl
* registration
) {
679 DCHECK(!ContainsKey(registrations_
, registration_handle_id
));
680 registrations_
[registration_handle_id
] = registration
;
683 void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
684 int registration_handle_id
) {
685 DCHECK(ContainsKey(registrations_
, registration_handle_id
));
686 registrations_
.erase(registration_handle_id
);
689 WebServiceWorkerRegistrationImpl
*
690 ServiceWorkerDispatcher::FindOrCreateRegistration(
691 const ServiceWorkerRegistrationObjectInfo
& info
,
692 const ServiceWorkerVersionAttributes
& attrs
) {
693 WebServiceWorkerRegistrationImpl
* registration
=
694 FindServiceWorkerRegistration(info
, true);
696 registration
= CreateServiceWorkerRegistration(info
, true);
697 registration
->SetInstalling(GetServiceWorker(attrs
.installing
, true));
698 registration
->SetWaiting(GetServiceWorker(attrs
.waiting
, true));
699 registration
->SetActive(GetServiceWorker(attrs
.active
, true));
701 // |registration| must already have version attributes, so adopt and destroy
702 // handle refs for them.
703 ServiceWorkerHandleReference::Adopt(
704 attrs
.installing
, thread_safe_sender_
.get());
705 ServiceWorkerHandleReference::Adopt(
706 attrs
.waiting
, thread_safe_sender_
.get());
707 ServiceWorkerHandleReference::Adopt(
708 attrs
.active
, thread_safe_sender_
.get());
713 } // namespace content