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/public/common/url_utils.h"
21 #include "third_party/WebKit/public/platform/WebServiceWorkerProviderClient.h"
22 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
24 using blink::WebServiceWorkerError
;
25 using blink::WebServiceWorkerProvider
;
26 using base::ThreadLocalPointer
;
32 base::LazyInstance
<ThreadLocalPointer
<ServiceWorkerDispatcher
> >::Leaky
33 g_dispatcher_tls
= LAZY_INSTANCE_INITIALIZER
;
35 ServiceWorkerDispatcher
* const kHasBeenDeleted
=
36 reinterpret_cast<ServiceWorkerDispatcher
*>(0x1);
38 int CurrentWorkerId() {
39 return WorkerTaskRunner::Instance()->CurrentWorkerId();
44 ServiceWorkerDispatcher::ServiceWorkerDispatcher(
45 ThreadSafeSender
* thread_safe_sender
)
46 : thread_safe_sender_(thread_safe_sender
) {
47 g_dispatcher_tls
.Pointer()->Set(this);
50 ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
51 g_dispatcher_tls
.Pointer()->Set(kHasBeenDeleted
);
54 void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
56 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher
, msg
)
57 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistration
,
58 OnAssociateRegistration
)
59 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DisassociateRegistration
,
60 OnDisassociateRegistration
)
61 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered
, OnRegistered
)
62 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered
,
64 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistration
,
66 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError
,
68 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistrationError
,
69 OnUnregistrationError
)
70 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationError
,
71 OnGetRegistrationError
)
72 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged
,
73 OnServiceWorkerStateChanged
)
74 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes
,
75 OnSetVersionAttributes
)
76 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_UpdateFound
,
78 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker
,
79 OnSetControllerServiceWorker
)
80 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument
,
82 IPC_MESSAGE_UNHANDLED(handled
= false)
84 DCHECK(handled
) << "Unhandled message:" << msg
.type();
87 bool ServiceWorkerDispatcher::Send(IPC::Message
* msg
) {
88 return thread_safe_sender_
->Send(msg
);
91 void ServiceWorkerDispatcher::RegisterServiceWorker(
94 const GURL
& script_url
,
95 WebServiceWorkerRegistrationCallbacks
* callbacks
) {
98 if (pattern
.possibly_invalid_spec().size() > GetMaxURLChars() ||
99 script_url
.possibly_invalid_spec().size() > GetMaxURLChars()) {
100 scoped_ptr
<WebServiceWorkerRegistrationCallbacks
>
101 owned_callbacks(callbacks
);
102 scoped_ptr
<WebServiceWorkerError
> error(new WebServiceWorkerError(
103 WebServiceWorkerError::ErrorTypeSecurity
, "URL too long"));
104 callbacks
->onError(error
.release());
108 int request_id
= pending_registration_callbacks_
.Add(callbacks
);
109 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
110 "ServiceWorkerDispatcher::RegisterServiceWorker",
112 "Pettern", pattern
.spec(),
113 "Script URL", script_url
.spec());
114 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
115 CurrentWorkerId(), request_id
, provider_id
, pattern
, script_url
));
118 void ServiceWorkerDispatcher::UnregisterServiceWorker(
121 WebServiceWorkerUnregistrationCallbacks
* callbacks
) {
124 if (pattern
.possibly_invalid_spec().size() > GetMaxURLChars()) {
125 scoped_ptr
<WebServiceWorkerUnregistrationCallbacks
>
126 owned_callbacks(callbacks
);
127 scoped_ptr
<WebServiceWorkerError
> error(new WebServiceWorkerError(
128 WebServiceWorkerError::ErrorTypeSecurity
, "URL too long"));
129 callbacks
->onError(error
.release());
133 int request_id
= pending_unregistration_callbacks_
.Add(callbacks
);
134 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
135 "ServiceWorkerDispatcher::UnregisterServiceWorker",
137 "Pettern", pattern
.spec());
138 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
139 CurrentWorkerId(), request_id
, provider_id
, pattern
));
142 void ServiceWorkerDispatcher::GetRegistration(
144 const GURL
& document_url
,
145 WebServiceWorkerRegistrationCallbacks
* callbacks
) {
148 if (document_url
.possibly_invalid_spec().size() > GetMaxURLChars()) {
149 scoped_ptr
<WebServiceWorkerRegistrationCallbacks
>
150 owned_callbacks(callbacks
);
151 scoped_ptr
<WebServiceWorkerError
> error(new WebServiceWorkerError(
152 WebServiceWorkerError::ErrorTypeSecurity
, "URL too long"));
153 callbacks
->onError(error
.release());
157 int request_id
= pending_get_registration_callbacks_
.Add(callbacks
);
158 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
159 "ServiceWorkerDispatcher::GetRegistration",
161 "Document URL", document_url
.spec());
162 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetRegistration(
163 CurrentWorkerId(), request_id
, provider_id
, document_url
));
166 void ServiceWorkerDispatcher::AddProviderContext(
167 ServiceWorkerProviderContext
* provider_context
) {
168 DCHECK(provider_context
);
169 int provider_id
= provider_context
->provider_id();
170 DCHECK(!ContainsKey(provider_contexts_
, provider_id
));
171 provider_contexts_
[provider_id
] = provider_context
;
174 void ServiceWorkerDispatcher::RemoveProviderContext(
175 ServiceWorkerProviderContext
* provider_context
) {
176 DCHECK(provider_context
);
177 DCHECK(ContainsKey(provider_contexts_
, provider_context
->provider_id()));
178 provider_contexts_
.erase(provider_context
->provider_id());
179 worker_to_provider_
.erase(provider_context
->installing_handle_id());
180 worker_to_provider_
.erase(provider_context
->waiting_handle_id());
181 worker_to_provider_
.erase(provider_context
->active_handle_id());
182 worker_to_provider_
.erase(provider_context
->controller_handle_id());
185 void ServiceWorkerDispatcher::AddScriptClient(
187 blink::WebServiceWorkerProviderClient
* client
) {
189 DCHECK(!ContainsKey(script_clients_
, provider_id
));
190 script_clients_
[provider_id
] = client
;
193 void ServiceWorkerDispatcher::RemoveScriptClient(int provider_id
) {
194 // This could be possibly called multiple times to ensure termination.
195 if (ContainsKey(script_clients_
, provider_id
))
196 script_clients_
.erase(provider_id
);
199 ServiceWorkerDispatcher
*
200 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
201 ThreadSafeSender
* thread_safe_sender
) {
202 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
) {
203 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
204 g_dispatcher_tls
.Pointer()->Set(NULL
);
206 if (g_dispatcher_tls
.Pointer()->Get())
207 return g_dispatcher_tls
.Pointer()->Get();
209 ServiceWorkerDispatcher
* dispatcher
=
210 new ServiceWorkerDispatcher(thread_safe_sender
);
211 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
212 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher
);
216 ServiceWorkerDispatcher
* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
217 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
)
219 return g_dispatcher_tls
.Pointer()->Get();
222 void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
226 WebServiceWorkerImpl
* ServiceWorkerDispatcher::GetServiceWorker(
227 const ServiceWorkerObjectInfo
& info
,
229 if (info
.handle_id
== kInvalidServiceWorkerHandleId
)
232 WorkerObjectMap::iterator existing_worker
=
233 service_workers_
.find(info
.handle_id
);
235 if (existing_worker
!= service_workers_
.end()) {
237 // We are instructed to adopt a handle but we already have one, so
238 // adopt and destroy a handle ref.
239 ServiceWorkerHandleReference::Adopt(info
, thread_safe_sender_
.get());
241 return existing_worker
->second
;
244 scoped_ptr
<ServiceWorkerHandleReference
> handle_ref
=
246 ? ServiceWorkerHandleReference::Adopt(info
, thread_safe_sender_
.get())
247 : ServiceWorkerHandleReference::Create(info
,
248 thread_safe_sender_
.get());
249 // WebServiceWorkerImpl constructor calls AddServiceWorker.
250 return new WebServiceWorkerImpl(handle_ref
.Pass(), thread_safe_sender_
.get());
253 WebServiceWorkerRegistrationImpl
*
254 ServiceWorkerDispatcher::FindServiceWorkerRegistration(
255 const ServiceWorkerRegistrationObjectInfo
& info
,
257 RegistrationObjectMap::iterator registration
=
258 registrations_
.find(info
.handle_id
);
259 if (registration
== registrations_
.end())
262 // We are instructed to adopt a handle but we already have one, so
263 // adopt and destroy a handle ref.
264 ServiceWorkerRegistrationHandleReference::Adopt(
265 info
, thread_safe_sender_
.get());
267 return registration
->second
;
270 WebServiceWorkerRegistrationImpl
*
271 ServiceWorkerDispatcher::CreateServiceWorkerRegistration(
272 const ServiceWorkerRegistrationObjectInfo
& info
,
274 DCHECK(!FindServiceWorkerRegistration(info
, adopt_handle
));
275 if (info
.handle_id
== kInvalidServiceWorkerRegistrationHandleId
)
278 scoped_ptr
<ServiceWorkerRegistrationHandleReference
> handle_ref
=
279 adopt_handle
? ServiceWorkerRegistrationHandleReference::Adopt(
280 info
, thread_safe_sender_
.get())
281 : ServiceWorkerRegistrationHandleReference::Create(
282 info
, thread_safe_sender_
.get());
284 // WebServiceWorkerRegistrationImpl constructor calls
285 // AddServiceWorkerRegistration.
286 return new WebServiceWorkerRegistrationImpl(handle_ref
.Pass());
289 void ServiceWorkerDispatcher::OnAssociateRegistration(
292 const ServiceWorkerRegistrationObjectInfo
& info
,
293 const ServiceWorkerVersionAttributes
& attrs
) {
294 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
295 if (provider
== provider_contexts_
.end())
297 provider
->second
->OnAssociateRegistration(info
, attrs
);
298 if (attrs
.installing
.handle_id
!= kInvalidServiceWorkerHandleId
)
299 worker_to_provider_
[attrs
.installing
.handle_id
] = provider
->second
;
300 if (attrs
.waiting
.handle_id
!= kInvalidServiceWorkerHandleId
)
301 worker_to_provider_
[attrs
.waiting
.handle_id
] = provider
->second
;
302 if (attrs
.active
.handle_id
!= kInvalidServiceWorkerHandleId
)
303 worker_to_provider_
[attrs
.active
.handle_id
] = provider
->second
;
306 void ServiceWorkerDispatcher::OnDisassociateRegistration(
309 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
310 if (provider
== provider_contexts_
.end())
312 provider
->second
->OnDisassociateRegistration();
313 worker_to_provider_
.erase(provider
->second
->installing_handle_id());
314 worker_to_provider_
.erase(provider
->second
->waiting_handle_id());
315 worker_to_provider_
.erase(provider
->second
->active_handle_id());
316 worker_to_provider_
.erase(provider
->second
->controller_handle_id());
319 void ServiceWorkerDispatcher::OnRegistered(
322 const ServiceWorkerRegistrationObjectInfo
& info
,
323 const ServiceWorkerVersionAttributes
& attrs
) {
324 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
325 "ServiceWorkerDispatcher::RegisterServiceWorker",
328 WebServiceWorkerRegistrationCallbacks
* callbacks
=
329 pending_registration_callbacks_
.Lookup(request_id
);
334 callbacks
->onSuccess(FindOrCreateRegistration(info
, attrs
));
335 pending_registration_callbacks_
.Remove(request_id
);
336 TRACE_EVENT_ASYNC_END0("ServiceWorker",
337 "ServiceWorkerDispatcher::RegisterServiceWorker",
341 void ServiceWorkerDispatcher::OnUnregistered(int thread_id
,
344 WebServiceWorkerUnregistrationCallbacks
* callbacks
=
345 pending_unregistration_callbacks_
.Lookup(request_id
);
346 TRACE_EVENT_ASYNC_STEP_INTO0(
348 "ServiceWorkerDispatcher::UnregisterServiceWorker",
354 callbacks
->onSuccess(&is_success
);
355 pending_unregistration_callbacks_
.Remove(request_id
);
356 TRACE_EVENT_ASYNC_END0("ServiceWorker",
357 "ServiceWorkerDispatcher::UnregisterServiceWorker",
361 void ServiceWorkerDispatcher::OnDidGetRegistration(
364 const ServiceWorkerRegistrationObjectInfo
& info
,
365 const ServiceWorkerVersionAttributes
& attrs
) {
366 WebServiceWorkerRegistrationCallbacks
* callbacks
=
367 pending_get_registration_callbacks_
.Lookup(request_id
);
368 TRACE_EVENT_ASYNC_STEP_INTO0(
370 "ServiceWorkerDispatcher::GetRegistration",
372 "OnDidGetRegistration");
377 WebServiceWorkerRegistrationImpl
* registration
= NULL
;
378 if (info
.handle_id
!= kInvalidServiceWorkerHandleId
)
379 registration
= FindOrCreateRegistration(info
, attrs
);
381 callbacks
->onSuccess(registration
);
382 pending_get_registration_callbacks_
.Remove(request_id
);
383 TRACE_EVENT_ASYNC_END0("ServiceWorker",
384 "ServiceWorkerDispatcher::GetRegistration",
388 void ServiceWorkerDispatcher::OnRegistrationError(
391 WebServiceWorkerError::ErrorType error_type
,
392 const base::string16
& message
) {
393 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
394 "ServiceWorkerDispatcher::RegisterServiceWorker",
396 "OnRegistrationError");
397 WebServiceWorkerRegistrationCallbacks
* callbacks
=
398 pending_registration_callbacks_
.Lookup(request_id
);
403 scoped_ptr
<WebServiceWorkerError
> error(
404 new WebServiceWorkerError(error_type
, message
));
405 callbacks
->onError(error
.release());
406 pending_registration_callbacks_
.Remove(request_id
);
407 TRACE_EVENT_ASYNC_END0("ServiceWorker",
408 "ServiceWorkerDispatcher::RegisterServiceWorker",
412 void ServiceWorkerDispatcher::OnUnregistrationError(
415 WebServiceWorkerError::ErrorType error_type
,
416 const base::string16
& message
) {
417 TRACE_EVENT_ASYNC_STEP_INTO0(
419 "ServiceWorkerDispatcher::UnregisterServiceWorker",
421 "OnUnregistrationError");
422 WebServiceWorkerUnregistrationCallbacks
* callbacks
=
423 pending_unregistration_callbacks_
.Lookup(request_id
);
428 scoped_ptr
<WebServiceWorkerError
> error(
429 new WebServiceWorkerError(error_type
, message
));
430 callbacks
->onError(error
.release());
431 pending_unregistration_callbacks_
.Remove(request_id
);
432 TRACE_EVENT_ASYNC_END0("ServiceWorker",
433 "ServiceWorkerDispatcher::UnregisterServiceWorker",
437 void ServiceWorkerDispatcher::OnGetRegistrationError(
440 WebServiceWorkerError::ErrorType error_type
,
441 const base::string16
& message
) {
442 TRACE_EVENT_ASYNC_STEP_INTO0(
444 "ServiceWorkerDispatcher::GetRegistration",
446 "OnGetRegistrationError");
447 WebServiceWorkerGetRegistrationCallbacks
* callbacks
=
448 pending_get_registration_callbacks_
.Lookup(request_id
);
453 scoped_ptr
<WebServiceWorkerError
> error(
454 new WebServiceWorkerError(error_type
, message
));
455 callbacks
->onError(error
.release());
456 pending_get_registration_callbacks_
.Remove(request_id
);
457 TRACE_EVENT_ASYNC_END0("ServiceWorker",
458 "ServiceWorkerDispatcher::GetRegistration",
462 void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
465 blink::WebServiceWorkerState state
) {
466 TRACE_EVENT2("ServiceWorker",
467 "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
468 "Thread ID", thread_id
,
470 WorkerObjectMap::iterator worker
= service_workers_
.find(handle_id
);
471 if (worker
!= service_workers_
.end())
472 worker
->second
->OnStateChanged(state
);
474 WorkerToProviderMap::iterator provider
= worker_to_provider_
.find(handle_id
);
475 if (provider
!= worker_to_provider_
.end())
476 provider
->second
->OnServiceWorkerStateChanged(handle_id
, state
);
479 void ServiceWorkerDispatcher::OnSetVersionAttributes(
482 int registration_handle_id
,
484 const ServiceWorkerVersionAttributes
& attributes
) {
485 TRACE_EVENT1("ServiceWorker",
486 "ServiceWorkerDispatcher::OnSetVersionAttributes",
487 "Thread ID", thread_id
);
488 ChangedVersionAttributesMask
mask(changed_mask
);
489 if (mask
.installing_changed()) {
490 SetInstallingServiceWorker(provider_id
,
491 registration_handle_id
,
492 attributes
.installing
);
494 if (mask
.waiting_changed()) {
495 SetWaitingServiceWorker(provider_id
,
496 registration_handle_id
,
499 if (mask
.active_changed()) {
500 SetActiveServiceWorker(provider_id
,
501 registration_handle_id
,
503 SetReadyRegistration(provider_id
, registration_handle_id
);
507 void ServiceWorkerDispatcher::OnUpdateFound(
509 const ServiceWorkerRegistrationObjectInfo
& info
) {
510 TRACE_EVENT0("ServiceWorker",
511 "ServiceWorkerDispatcher::OnUpdateFound");
512 RegistrationObjectMap::iterator found
= registrations_
.find(info
.handle_id
);
513 if (found
!= registrations_
.end())
514 found
->second
->OnUpdateFound();
517 void ServiceWorkerDispatcher::SetInstallingServiceWorker(
519 int registration_handle_id
,
520 const ServiceWorkerObjectInfo
& info
) {
521 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
522 if (provider
!= provider_contexts_
.end() &&
523 provider
->second
->registration_handle_id() == registration_handle_id
) {
524 int existing_installing_id
= provider
->second
->installing_handle_id();
525 if (existing_installing_id
!= info
.handle_id
&&
526 existing_installing_id
!= kInvalidServiceWorkerHandleId
) {
527 WorkerToProviderMap::iterator associated_provider
=
528 worker_to_provider_
.find(existing_installing_id
);
529 DCHECK(associated_provider
!= worker_to_provider_
.end());
530 DCHECK(associated_provider
->second
->provider_id() == provider_id
);
531 worker_to_provider_
.erase(associated_provider
);
533 provider
->second
->OnSetInstallingServiceWorker(
534 registration_handle_id
, info
);
535 if (info
.handle_id
!= kInvalidServiceWorkerHandleId
)
536 worker_to_provider_
[info
.handle_id
] = provider
->second
;
539 RegistrationObjectMap::iterator found
=
540 registrations_
.find(registration_handle_id
);
541 if (found
!= registrations_
.end()) {
542 // Populate the .installing field with the new worker object.
543 found
->second
->SetInstalling(GetServiceWorker(info
, false));
547 void ServiceWorkerDispatcher::SetWaitingServiceWorker(
549 int registration_handle_id
,
550 const ServiceWorkerObjectInfo
& info
) {
551 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
552 if (provider
!= provider_contexts_
.end() &&
553 provider
->second
->registration_handle_id() == registration_handle_id
) {
554 int existing_waiting_id
= provider
->second
->waiting_handle_id();
555 if (existing_waiting_id
!= info
.handle_id
&&
556 existing_waiting_id
!= kInvalidServiceWorkerHandleId
) {
557 WorkerToProviderMap::iterator associated_provider
=
558 worker_to_provider_
.find(existing_waiting_id
);
559 DCHECK(associated_provider
!= worker_to_provider_
.end());
560 DCHECK(associated_provider
->second
->provider_id() == provider_id
);
561 worker_to_provider_
.erase(associated_provider
);
563 provider
->second
->OnSetWaitingServiceWorker(registration_handle_id
, info
);
564 if (info
.handle_id
!= kInvalidServiceWorkerHandleId
)
565 worker_to_provider_
[info
.handle_id
] = provider
->second
;
568 RegistrationObjectMap::iterator found
=
569 registrations_
.find(registration_handle_id
);
570 if (found
!= registrations_
.end()) {
571 // Populate the .waiting field with the new worker object.
572 found
->second
->SetWaiting(GetServiceWorker(info
, false));
576 void ServiceWorkerDispatcher::SetActiveServiceWorker(
578 int registration_handle_id
,
579 const ServiceWorkerObjectInfo
& info
) {
580 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
581 if (provider
!= provider_contexts_
.end() &&
582 provider
->second
->registration_handle_id() == registration_handle_id
) {
583 int existing_active_id
= provider
->second
->active_handle_id();
584 if (existing_active_id
!= info
.handle_id
&&
585 existing_active_id
!= kInvalidServiceWorkerHandleId
) {
586 WorkerToProviderMap::iterator associated_provider
=
587 worker_to_provider_
.find(existing_active_id
);
588 DCHECK(associated_provider
!= worker_to_provider_
.end());
589 DCHECK(associated_provider
->second
->provider_id() == provider_id
);
590 worker_to_provider_
.erase(associated_provider
);
592 provider
->second
->OnSetActiveServiceWorker(registration_handle_id
, info
);
593 if (info
.handle_id
!= kInvalidServiceWorkerHandleId
)
594 worker_to_provider_
[info
.handle_id
] = provider
->second
;
597 RegistrationObjectMap::iterator found
=
598 registrations_
.find(registration_handle_id
);
599 if (found
!= registrations_
.end()) {
600 // Populate the .active field with the new worker object.
601 found
->second
->SetActive(GetServiceWorker(info
, false));
605 void ServiceWorkerDispatcher::SetReadyRegistration(
607 int registration_handle_id
) {
608 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
609 if (provider
== provider_contexts_
.end() ||
610 provider
->second
->registration_handle_id() != registration_handle_id
||
611 provider
->second
->active_handle_id() == kInvalidServiceWorkerHandleId
) {
615 ScriptClientMap::iterator client
= script_clients_
.find(provider_id
);
616 if (client
== script_clients_
.end())
619 ServiceWorkerRegistrationObjectInfo info
=
620 provider
->second
->registration()->info();
621 WebServiceWorkerRegistrationImpl
* registration
=
622 FindServiceWorkerRegistration(info
, false);
624 registration
= CreateServiceWorkerRegistration(info
, false);
625 ServiceWorkerVersionAttributes attrs
=
626 provider
->second
->GetVersionAttributes();
627 registration
->SetInstalling(GetServiceWorker(attrs
.installing
, false));
628 registration
->SetWaiting(GetServiceWorker(attrs
.waiting
, false));
629 registration
->SetActive(GetServiceWorker(attrs
.active
, false));
632 // Resolve the .ready promise with the registration object.
633 client
->second
->setReadyRegistration(registration
);
636 void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
639 const ServiceWorkerObjectInfo
& info
) {
640 TRACE_EVENT2("ServiceWorker",
641 "ServiceWorkerDispatcher::OnSetControllerServiceWorker",
642 "Thread ID", thread_id
,
643 "Provider ID", provider_id
);
644 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
645 if (provider
!= provider_contexts_
.end()) {
646 provider
->second
->OnSetControllerServiceWorker(
647 provider
->second
->registration_handle_id(), info
);
648 worker_to_provider_
[info
.handle_id
] = provider
->second
;
651 ScriptClientMap::iterator found
= script_clients_
.find(provider_id
);
652 if (found
!= script_clients_
.end()) {
653 // Populate the .controller field with the new worker object.
654 found
->second
->setController(GetServiceWorker(info
, false));
658 void ServiceWorkerDispatcher::OnPostMessage(
661 const base::string16
& message
,
662 const std::vector
<int>& sent_message_port_ids
,
663 const std::vector
<int>& new_routing_ids
) {
664 // Make sure we're on the main document thread. (That must be the only
665 // thread we get this message)
666 DCHECK(ChildThread::current());
667 TRACE_EVENT1("ServiceWorker",
668 "ServiceWorkerDispatcher::OnPostMessage",
669 "Thread ID", thread_id
);
671 ScriptClientMap::iterator found
= script_clients_
.find(provider_id
);
672 if (found
== script_clients_
.end()) {
673 // For now we do no queueing for messages sent to nonexistent / unattached
678 std::vector
<WebMessagePortChannelImpl
*> ports
;
679 if (!sent_message_port_ids
.empty()) {
680 ports
.resize(sent_message_port_ids
.size());
681 for (size_t i
= 0; i
< sent_message_port_ids
.size(); ++i
) {
682 ports
[i
] = new WebMessagePortChannelImpl(
683 new_routing_ids
[i
], sent_message_port_ids
[i
],
684 base::MessageLoopProxy::current());
688 found
->second
->dispatchMessageEvent(message
, ports
);
691 void ServiceWorkerDispatcher::AddServiceWorker(
692 int handle_id
, WebServiceWorkerImpl
* worker
) {
693 DCHECK(!ContainsKey(service_workers_
, handle_id
));
694 service_workers_
[handle_id
] = worker
;
697 void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id
) {
698 DCHECK(ContainsKey(service_workers_
, handle_id
));
699 service_workers_
.erase(handle_id
);
702 void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
703 int registration_handle_id
,
704 WebServiceWorkerRegistrationImpl
* registration
) {
705 DCHECK(!ContainsKey(registrations_
, registration_handle_id
));
706 registrations_
[registration_handle_id
] = registration
;
709 void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
710 int registration_handle_id
) {
711 DCHECK(ContainsKey(registrations_
, registration_handle_id
));
712 registrations_
.erase(registration_handle_id
);
715 WebServiceWorkerRegistrationImpl
*
716 ServiceWorkerDispatcher::FindOrCreateRegistration(
717 const ServiceWorkerRegistrationObjectInfo
& info
,
718 const ServiceWorkerVersionAttributes
& attrs
) {
719 WebServiceWorkerRegistrationImpl
* registration
=
720 FindServiceWorkerRegistration(info
, true);
722 registration
= CreateServiceWorkerRegistration(info
, true);
723 registration
->SetInstalling(GetServiceWorker(attrs
.installing
, true));
724 registration
->SetWaiting(GetServiceWorker(attrs
.waiting
, true));
725 registration
->SetActive(GetServiceWorker(attrs
.active
, true));
727 // |registration| must already have version attributes, so adopt and destroy
728 // handle refs for them.
729 ServiceWorkerHandleReference::Adopt(
730 attrs
.installing
, thread_safe_sender_
.get());
731 ServiceWorkerHandleReference::Adopt(
732 attrs
.waiting
, thread_safe_sender_
.get());
733 ServiceWorkerHandleReference::Adopt(
734 attrs
.active
, thread_safe_sender_
.get());
739 } // namespace content