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/lazy_instance.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/stl_util.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/threading/thread_local.h"
12 #include "base/trace_event/trace_event.h"
13 #include "content/child/child_thread_impl.h"
14 #include "content/child/service_worker/service_worker_handle_reference.h"
15 #include "content/child/service_worker/service_worker_provider_context.h"
16 #include "content/child/service_worker/service_worker_registration_handle_reference.h"
17 #include "content/child/service_worker/web_service_worker_impl.h"
18 #include "content/child/service_worker/web_service_worker_registration_impl.h"
19 #include "content/child/thread_safe_sender.h"
20 #include "content/child/webmessageportchannel_impl.h"
21 #include "content/common/service_worker/service_worker_messages.h"
22 #include "content/common/service_worker/service_worker_types.h"
23 #include "content/public/common/url_utils.h"
24 #include "third_party/WebKit/public/platform/WebServiceWorkerClientsInfo.h"
25 #include "third_party/WebKit/public/platform/WebServiceWorkerProviderClient.h"
26 #include "third_party/WebKit/public/platform/WebString.h"
27 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
29 using blink::WebServiceWorkerError
;
30 using blink::WebServiceWorkerProvider
;
31 using base::ThreadLocalPointer
;
37 base::LazyInstance
<ThreadLocalPointer
<ServiceWorkerDispatcher
> >::Leaky
38 g_dispatcher_tls
= LAZY_INSTANCE_INITIALIZER
;
40 ServiceWorkerDispatcher
* const kHasBeenDeleted
=
41 reinterpret_cast<ServiceWorkerDispatcher
*>(0x1);
43 int CurrentWorkerId() {
44 return WorkerTaskRunner::Instance()->CurrentWorkerId();
49 ServiceWorkerDispatcher::ServiceWorkerDispatcher(
50 ThreadSafeSender
* thread_safe_sender
,
51 base::SingleThreadTaskRunner
* main_thread_task_runner
)
52 : thread_safe_sender_(thread_safe_sender
),
53 main_thread_task_runner_(main_thread_task_runner
) {
54 g_dispatcher_tls
.Pointer()->Set(this);
57 ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
58 g_dispatcher_tls
.Pointer()->Set(kHasBeenDeleted
);
61 void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
63 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher
, msg
)
64 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistrationWithServiceWorker
,
65 OnAssociateRegistrationWithServiceWorker
)
66 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistration
,
67 OnAssociateRegistration
)
68 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DisassociateRegistration
,
69 OnDisassociateRegistration
)
70 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered
, OnRegistered
)
71 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUpdated
, OnUpdated
)
72 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered
,
74 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistration
,
76 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistrations
,
77 OnDidGetRegistrations
)
78 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistrationForReady
,
79 OnDidGetRegistrationForReady
)
80 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError
,
82 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUpdateError
,
84 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistrationError
,
85 OnUnregistrationError
)
86 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationError
,
87 OnGetRegistrationError
)
88 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationsError
,
89 OnGetRegistrationsError
)
90 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged
,
91 OnServiceWorkerStateChanged
)
92 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes
,
93 OnSetVersionAttributes
)
94 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_UpdateFound
,
96 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker
,
97 OnSetControllerServiceWorker
)
98 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument
,
100 IPC_MESSAGE_UNHANDLED(handled
= false)
101 IPC_END_MESSAGE_MAP()
102 DCHECK(handled
) << "Unhandled message:" << msg
.type();
105 bool ServiceWorkerDispatcher::Send(IPC::Message
* msg
) {
106 return thread_safe_sender_
->Send(msg
);
109 void ServiceWorkerDispatcher::RegisterServiceWorker(
112 const GURL
& script_url
,
113 WebServiceWorkerRegistrationCallbacks
* callbacks
) {
116 if (pattern
.possibly_invalid_spec().size() > GetMaxURLChars() ||
117 script_url
.possibly_invalid_spec().size() > GetMaxURLChars()) {
118 scoped_ptr
<WebServiceWorkerRegistrationCallbacks
>
119 owned_callbacks(callbacks
);
120 std::string
error_message(kServiceWorkerRegisterErrorPrefix
);
121 error_message
+= "The provided scriptURL or scope is too long.";
123 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity
,
124 blink::WebString::fromUTF8(error_message
)));
128 int request_id
= pending_registration_callbacks_
.Add(callbacks
);
129 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
130 "ServiceWorkerDispatcher::RegisterServiceWorker",
132 "Scope", pattern
.spec(),
133 "Script URL", script_url
.spec());
134 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
135 CurrentWorkerId(), request_id
, provider_id
, pattern
, script_url
));
138 void ServiceWorkerDispatcher::UpdateServiceWorker(
140 int64 registration_id
,
141 WebServiceWorkerUpdateCallbacks
* callbacks
) {
143 int request_id
= pending_update_callbacks_
.Add(callbacks
);
144 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_UpdateServiceWorker(
145 CurrentWorkerId(), request_id
, provider_id
, registration_id
));
148 void ServiceWorkerDispatcher::UnregisterServiceWorker(
150 int64 registration_id
,
151 WebServiceWorkerUnregistrationCallbacks
* callbacks
) {
153 int request_id
= pending_unregistration_callbacks_
.Add(callbacks
);
154 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
155 "ServiceWorkerDispatcher::UnregisterServiceWorker",
156 request_id
, "Registration ID", registration_id
);
157 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
158 CurrentWorkerId(), request_id
, provider_id
, registration_id
));
161 void ServiceWorkerDispatcher::GetRegistration(
163 const GURL
& document_url
,
164 WebServiceWorkerRegistrationCallbacks
* callbacks
) {
167 if (document_url
.possibly_invalid_spec().size() > GetMaxURLChars()) {
168 scoped_ptr
<WebServiceWorkerRegistrationCallbacks
>
169 owned_callbacks(callbacks
);
170 std::string
error_message(kServiceWorkerGetRegistrationErrorPrefix
);
171 error_message
+= "The provided documentURL is too long.";
173 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity
,
174 blink::WebString::fromUTF8(error_message
)));
178 int request_id
= pending_get_registration_callbacks_
.Add(callbacks
);
179 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
180 "ServiceWorkerDispatcher::GetRegistration",
182 "Document URL", document_url
.spec());
183 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetRegistration(
184 CurrentWorkerId(), request_id
, provider_id
, document_url
));
187 void ServiceWorkerDispatcher::GetRegistrations(
189 WebServiceWorkerGetRegistrationsCallbacks
* callbacks
) {
192 int request_id
= pending_get_registrations_callbacks_
.Add(callbacks
);
193 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
194 "ServiceWorkerDispatcher::GetRegistrations",
196 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetRegistrations(
197 CurrentWorkerId(), request_id
, provider_id
));
200 void ServiceWorkerDispatcher::GetRegistrationForReady(
202 WebServiceWorkerGetRegistrationForReadyCallbacks
* callbacks
) {
203 int request_id
= get_for_ready_callbacks_
.Add(callbacks
);
204 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
205 "ServiceWorkerDispatcher::GetRegistrationForReady",
207 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetRegistrationForReady(
208 CurrentWorkerId(), request_id
, provider_id
));
211 void ServiceWorkerDispatcher::AddProviderContext(
212 ServiceWorkerProviderContext
* provider_context
) {
213 DCHECK(provider_context
);
214 int provider_id
= provider_context
->provider_id();
215 DCHECK(!ContainsKey(provider_contexts_
, provider_id
));
216 provider_contexts_
[provider_id
] = provider_context
;
219 void ServiceWorkerDispatcher::RemoveProviderContext(
220 ServiceWorkerProviderContext
* provider_context
) {
221 DCHECK(provider_context
);
222 DCHECK(ContainsKey(provider_contexts_
, provider_context
->provider_id()));
223 provider_contexts_
.erase(provider_context
->provider_id());
224 worker_to_provider_
.erase(provider_context
->installing_handle_id());
225 worker_to_provider_
.erase(provider_context
->waiting_handle_id());
226 worker_to_provider_
.erase(provider_context
->active_handle_id());
227 worker_to_provider_
.erase(provider_context
->controller_handle_id());
230 void ServiceWorkerDispatcher::AddProviderClient(
232 blink::WebServiceWorkerProviderClient
* client
) {
234 DCHECK(!ContainsKey(provider_clients_
, provider_id
));
235 provider_clients_
[provider_id
] = client
;
238 void ServiceWorkerDispatcher::RemoveProviderClient(int provider_id
) {
239 // This could be possibly called multiple times to ensure termination.
240 if (ContainsKey(provider_clients_
, provider_id
))
241 provider_clients_
.erase(provider_id
);
244 ServiceWorkerDispatcher
*
245 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
246 ThreadSafeSender
* thread_safe_sender
,
247 base::SingleThreadTaskRunner
* main_thread_task_runner
) {
248 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
) {
249 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
250 g_dispatcher_tls
.Pointer()->Set(NULL
);
252 if (g_dispatcher_tls
.Pointer()->Get())
253 return g_dispatcher_tls
.Pointer()->Get();
255 ServiceWorkerDispatcher
* dispatcher
=
256 new ServiceWorkerDispatcher(thread_safe_sender
, main_thread_task_runner
);
257 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
258 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher
);
262 ServiceWorkerDispatcher
* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
263 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
)
265 return g_dispatcher_tls
.Pointer()->Get();
268 void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
272 WebServiceWorkerImpl
* ServiceWorkerDispatcher::GetServiceWorker(
273 const ServiceWorkerObjectInfo
& info
,
275 if (info
.handle_id
== kInvalidServiceWorkerHandleId
)
278 WorkerObjectMap::iterator existing_worker
=
279 service_workers_
.find(info
.handle_id
);
281 if (existing_worker
!= service_workers_
.end()) {
283 // We are instructed to adopt a handle but we already have one, so
284 // adopt and destroy a handle ref.
285 ServiceWorkerHandleReference::Adopt(info
, thread_safe_sender_
.get());
287 return existing_worker
->second
;
290 scoped_ptr
<ServiceWorkerHandleReference
> handle_ref
=
292 ? ServiceWorkerHandleReference::Adopt(info
, thread_safe_sender_
.get())
293 : ServiceWorkerHandleReference::Create(info
,
294 thread_safe_sender_
.get());
295 // WebServiceWorkerImpl constructor calls AddServiceWorker.
296 return new WebServiceWorkerImpl(handle_ref
.Pass(), thread_safe_sender_
.get());
299 WebServiceWorkerRegistrationImpl
*
300 ServiceWorkerDispatcher::CreateServiceWorkerRegistration(
301 const ServiceWorkerRegistrationObjectInfo
& info
,
303 DCHECK(!ContainsKey(registrations_
, info
.handle_id
));
304 if (info
.handle_id
== kInvalidServiceWorkerRegistrationHandleId
)
307 scoped_ptr
<ServiceWorkerRegistrationHandleReference
> handle_ref
=
308 adopt_handle
? ServiceWorkerRegistrationHandleReference::Adopt(
309 info
, thread_safe_sender_
.get())
310 : ServiceWorkerRegistrationHandleReference::Create(
311 info
, thread_safe_sender_
.get());
313 // WebServiceWorkerRegistrationImpl constructor calls
314 // AddServiceWorkerRegistration.
315 return new WebServiceWorkerRegistrationImpl(handle_ref
.Pass());
318 // We can assume that this message handler is called before the worker context
319 // starts because script loading happens after this association.
320 // TODO(nhiroki): This association information could be pushed into
321 // EmbeddedWorkerMsg_StartWorker message and handed over to the worker thread
322 // without a lock in ServiceWorkerProviderContext.
323 void ServiceWorkerDispatcher::OnAssociateRegistrationWithServiceWorker(
326 const ServiceWorkerRegistrationObjectInfo
& info
,
327 const ServiceWorkerVersionAttributes
& attrs
) {
328 DCHECK_EQ(kDocumentMainThreadId
, thread_id
);
330 ProviderContextMap::iterator context
= provider_contexts_
.find(provider_id
);
331 if (context
== provider_contexts_
.end())
333 context
->second
->OnAssociateRegistration(info
, attrs
);
335 // We don't have to add entries into |worker_to_provider_| because state
336 // change events for the workers will be notified on the worker thread.
339 void ServiceWorkerDispatcher::OnAssociateRegistration(
342 const ServiceWorkerRegistrationObjectInfo
& info
,
343 const ServiceWorkerVersionAttributes
& attrs
) {
344 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
345 if (provider
== provider_contexts_
.end())
347 provider
->second
->OnAssociateRegistration(info
, attrs
);
348 if (attrs
.installing
.handle_id
!= kInvalidServiceWorkerHandleId
)
349 worker_to_provider_
[attrs
.installing
.handle_id
] = provider
->second
;
350 if (attrs
.waiting
.handle_id
!= kInvalidServiceWorkerHandleId
)
351 worker_to_provider_
[attrs
.waiting
.handle_id
] = provider
->second
;
352 if (attrs
.active
.handle_id
!= kInvalidServiceWorkerHandleId
)
353 worker_to_provider_
[attrs
.active
.handle_id
] = provider
->second
;
356 void ServiceWorkerDispatcher::OnDisassociateRegistration(
359 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
360 if (provider
== provider_contexts_
.end())
362 worker_to_provider_
.erase(provider
->second
->installing_handle_id());
363 worker_to_provider_
.erase(provider
->second
->waiting_handle_id());
364 worker_to_provider_
.erase(provider
->second
->active_handle_id());
365 worker_to_provider_
.erase(provider
->second
->controller_handle_id());
366 provider
->second
->OnDisassociateRegistration();
369 void ServiceWorkerDispatcher::OnRegistered(
372 const ServiceWorkerRegistrationObjectInfo
& info
,
373 const ServiceWorkerVersionAttributes
& attrs
) {
374 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
375 "ServiceWorkerDispatcher::RegisterServiceWorker",
378 TRACE_EVENT_ASYNC_END0("ServiceWorker",
379 "ServiceWorkerDispatcher::RegisterServiceWorker",
381 WebServiceWorkerRegistrationCallbacks
* callbacks
=
382 pending_registration_callbacks_
.Lookup(request_id
);
387 callbacks
->onSuccess(FindOrCreateRegistration(info
, attrs
));
388 pending_registration_callbacks_
.Remove(request_id
);
391 void ServiceWorkerDispatcher::OnUpdated(int thread_id
, int request_id
) {
392 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
393 "ServiceWorkerDispatcher::UpdateServiceWorker",
394 request_id
, "OnUpdated");
395 TRACE_EVENT_ASYNC_END0("ServiceWorker",
396 "ServiceWorkerDispatcher::UpdateServiceWorker",
398 WebServiceWorkerUpdateCallbacks
* callbacks
=
399 pending_update_callbacks_
.Lookup(request_id
);
404 callbacks
->onSuccess();
405 pending_update_callbacks_
.Remove(request_id
);
408 void ServiceWorkerDispatcher::OnUnregistered(int thread_id
,
411 TRACE_EVENT_ASYNC_STEP_INTO0(
413 "ServiceWorkerDispatcher::UnregisterServiceWorker",
416 TRACE_EVENT_ASYNC_END0("ServiceWorker",
417 "ServiceWorkerDispatcher::UnregisterServiceWorker",
419 WebServiceWorkerUnregistrationCallbacks
* callbacks
=
420 pending_unregistration_callbacks_
.Lookup(request_id
);
424 callbacks
->onSuccess(is_success
);
425 pending_unregistration_callbacks_
.Remove(request_id
);
428 void ServiceWorkerDispatcher::OnDidGetRegistration(
431 const ServiceWorkerRegistrationObjectInfo
& info
,
432 const ServiceWorkerVersionAttributes
& attrs
) {
433 TRACE_EVENT_ASYNC_STEP_INTO0(
435 "ServiceWorkerDispatcher::GetRegistration",
437 "OnDidGetRegistration");
438 TRACE_EVENT_ASYNC_END0("ServiceWorker",
439 "ServiceWorkerDispatcher::GetRegistration",
441 WebServiceWorkerRegistrationCallbacks
* callbacks
=
442 pending_get_registration_callbacks_
.Lookup(request_id
);
447 WebServiceWorkerRegistrationImpl
* registration
= NULL
;
448 if (info
.handle_id
!= kInvalidServiceWorkerHandleId
)
449 registration
= FindOrCreateRegistration(info
, attrs
);
451 callbacks
->onSuccess(registration
);
452 pending_get_registration_callbacks_
.Remove(request_id
);
455 void ServiceWorkerDispatcher::OnDidGetRegistrations(
458 const std::vector
<ServiceWorkerRegistrationObjectInfo
>& infos
,
459 const std::vector
<ServiceWorkerVersionAttributes
>& attrs
) {
460 TRACE_EVENT_ASYNC_STEP_INTO0(
462 "ServiceWorkerDispatcher::GetRegistrations",
464 "OnDidGetRegistrations");
465 TRACE_EVENT_ASYNC_END0("ServiceWorker",
466 "ServiceWorkerDispatcher::GetRegistrations",
469 WebServiceWorkerGetRegistrationsCallbacks
* callbacks
=
470 pending_get_registrations_callbacks_
.Lookup(request_id
);
475 typedef blink::WebVector
<blink::WebServiceWorkerRegistration
*>
476 WebServiceWorkerRegistrationArray
;
477 WebServiceWorkerRegistrationArray
* registrations
=
478 new WebServiceWorkerRegistrationArray(infos
.size());
479 for (size_t i
= 0; i
< infos
.size(); ++i
) {
480 if (infos
[i
].handle_id
!= kInvalidServiceWorkerHandleId
) {
481 ServiceWorkerRegistrationObjectInfo
info(infos
[i
]);
482 ServiceWorkerVersionAttributes
attr(attrs
[i
]);
483 (*registrations
)[i
] = FindOrCreateRegistration(info
, attr
);
487 callbacks
->onSuccess(registrations
);
488 pending_get_registrations_callbacks_
.Remove(request_id
);
491 void ServiceWorkerDispatcher::OnDidGetRegistrationForReady(
494 const ServiceWorkerRegistrationObjectInfo
& info
,
495 const ServiceWorkerVersionAttributes
& attrs
) {
496 TRACE_EVENT_ASYNC_STEP_INTO0(
498 "ServiceWorkerDispatcher::GetRegistrationForReady",
500 "OnDidGetRegistrationForReady");
501 TRACE_EVENT_ASYNC_END0("ServiceWorker",
502 "ServiceWorkerDispatcher::GetRegistrationForReady",
504 WebServiceWorkerGetRegistrationForReadyCallbacks
* callbacks
=
505 get_for_ready_callbacks_
.Lookup(request_id
);
510 WebServiceWorkerRegistrationImpl
* registration
= NULL
;
511 DCHECK(info
.handle_id
!= kInvalidServiceWorkerHandleId
);
512 registration
= FindOrCreateRegistration(info
, attrs
);
513 callbacks
->onSuccess(registration
);
514 get_for_ready_callbacks_
.Remove(request_id
);
517 void ServiceWorkerDispatcher::OnRegistrationError(
520 WebServiceWorkerError::ErrorType error_type
,
521 const base::string16
& message
) {
522 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
523 "ServiceWorkerDispatcher::RegisterServiceWorker",
525 "OnRegistrationError");
526 TRACE_EVENT_ASYNC_END0("ServiceWorker",
527 "ServiceWorkerDispatcher::RegisterServiceWorker",
529 WebServiceWorkerRegistrationCallbacks
* callbacks
=
530 pending_registration_callbacks_
.Lookup(request_id
);
535 callbacks
->onError(new WebServiceWorkerError(error_type
, message
));
536 pending_registration_callbacks_
.Remove(request_id
);
539 void ServiceWorkerDispatcher::OnUpdateError(
542 WebServiceWorkerError::ErrorType error_type
,
543 const base::string16
& message
) {
544 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
545 "ServiceWorkerDispatcher::UpdateServiceWorker",
546 request_id
, "OnUpdateError");
547 TRACE_EVENT_ASYNC_END0("ServiceWorker",
548 "ServiceWorkerDispatcher::UpdateServiceWorker",
550 WebServiceWorkerUpdateCallbacks
* callbacks
=
551 pending_update_callbacks_
.Lookup(request_id
);
556 callbacks
->onError(WebServiceWorkerError(error_type
, message
));
557 pending_update_callbacks_
.Remove(request_id
);
560 void ServiceWorkerDispatcher::OnUnregistrationError(
563 WebServiceWorkerError::ErrorType error_type
,
564 const base::string16
& message
) {
565 TRACE_EVENT_ASYNC_STEP_INTO0(
567 "ServiceWorkerDispatcher::UnregisterServiceWorker",
569 "OnUnregistrationError");
570 TRACE_EVENT_ASYNC_END0("ServiceWorker",
571 "ServiceWorkerDispatcher::UnregisterServiceWorker",
573 WebServiceWorkerUnregistrationCallbacks
* callbacks
=
574 pending_unregistration_callbacks_
.Lookup(request_id
);
579 callbacks
->onError(WebServiceWorkerError(error_type
, message
));
580 pending_unregistration_callbacks_
.Remove(request_id
);
583 void ServiceWorkerDispatcher::OnGetRegistrationError(
586 WebServiceWorkerError::ErrorType error_type
,
587 const base::string16
& message
) {
588 TRACE_EVENT_ASYNC_STEP_INTO0(
590 "ServiceWorkerDispatcher::GetRegistration",
592 "OnGetRegistrationError");
593 TRACE_EVENT_ASYNC_END0("ServiceWorker",
594 "ServiceWorkerDispatcher::GetRegistration",
596 WebServiceWorkerGetRegistrationCallbacks
* callbacks
=
597 pending_get_registration_callbacks_
.Lookup(request_id
);
602 callbacks
->onError(new WebServiceWorkerError(error_type
, message
));
603 pending_get_registration_callbacks_
.Remove(request_id
);
606 void ServiceWorkerDispatcher::OnGetRegistrationsError(
609 WebServiceWorkerError::ErrorType error_type
,
610 const base::string16
& message
) {
611 TRACE_EVENT_ASYNC_STEP_INTO0(
613 "ServiceWorkerDispatcher::GetRegistrations",
615 "OnGetRegistrationsError");
616 TRACE_EVENT_ASYNC_END0("ServiceWorker",
617 "ServiceWorkerDispatcher::GetRegistrations",
619 WebServiceWorkerGetRegistrationsCallbacks
* callbacks
=
620 pending_get_registrations_callbacks_
.Lookup(request_id
);
625 callbacks
->onError(new WebServiceWorkerError(error_type
, message
));
626 pending_get_registrations_callbacks_
.Remove(request_id
);
629 void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
632 blink::WebServiceWorkerState state
) {
633 TRACE_EVENT2("ServiceWorker",
634 "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
635 "Thread ID", thread_id
,
637 WorkerObjectMap::iterator worker
= service_workers_
.find(handle_id
);
638 if (worker
!= service_workers_
.end())
639 worker
->second
->OnStateChanged(state
);
641 WorkerToProviderMap::iterator provider
= worker_to_provider_
.find(handle_id
);
642 if (provider
!= worker_to_provider_
.end())
643 provider
->second
->OnServiceWorkerStateChanged(handle_id
, state
);
646 void ServiceWorkerDispatcher::OnSetVersionAttributes(
649 int registration_handle_id
,
651 const ServiceWorkerVersionAttributes
& attrs
) {
652 TRACE_EVENT1("ServiceWorker",
653 "ServiceWorkerDispatcher::OnSetVersionAttributes",
654 "Thread ID", thread_id
);
656 ChangedVersionAttributesMask
mask(changed_mask
);
657 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
658 if (provider
!= provider_contexts_
.end() &&
659 provider
->second
->registration_handle_id() == registration_handle_id
) {
660 if (mask
.installing_changed()) {
661 worker_to_provider_
.erase(provider
->second
->installing_handle_id());
662 if (attrs
.installing
.handle_id
!= kInvalidServiceWorkerHandleId
)
663 worker_to_provider_
[attrs
.installing
.handle_id
] = provider
->second
;
665 if (mask
.waiting_changed()) {
666 worker_to_provider_
.erase(provider
->second
->waiting_handle_id());
667 if (attrs
.waiting
.handle_id
!= kInvalidServiceWorkerHandleId
)
668 worker_to_provider_
[attrs
.waiting
.handle_id
] = provider
->second
;
670 if (mask
.active_changed()) {
671 worker_to_provider_
.erase(provider
->second
->active_handle_id());
672 if (attrs
.active
.handle_id
!= kInvalidServiceWorkerHandleId
)
673 worker_to_provider_
[attrs
.active
.handle_id
] = provider
->second
;
675 provider
->second
->SetVersionAttributes(mask
, attrs
);
678 RegistrationObjectMap::iterator found
=
679 registrations_
.find(registration_handle_id
);
680 if (found
!= registrations_
.end()) {
681 // Populate the version fields (eg. .installing) with new worker objects.
682 if (mask
.installing_changed())
683 found
->second
->SetInstalling(GetServiceWorker(attrs
.installing
, false));
684 if (mask
.waiting_changed())
685 found
->second
->SetWaiting(GetServiceWorker(attrs
.waiting
, false));
686 if (mask
.active_changed())
687 found
->second
->SetActive(GetServiceWorker(attrs
.active
, false));
691 void ServiceWorkerDispatcher::OnUpdateFound(
693 int registration_handle_id
) {
694 TRACE_EVENT0("ServiceWorker",
695 "ServiceWorkerDispatcher::OnUpdateFound");
696 RegistrationObjectMap::iterator found
=
697 registrations_
.find(registration_handle_id
);
698 if (found
!= registrations_
.end())
699 found
->second
->OnUpdateFound();
702 void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
705 const ServiceWorkerObjectInfo
& info
,
706 bool should_notify_controllerchange
) {
707 TRACE_EVENT2("ServiceWorker",
708 "ServiceWorkerDispatcher::OnSetControllerServiceWorker",
709 "Thread ID", thread_id
,
710 "Provider ID", provider_id
);
712 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
713 if (provider
!= provider_contexts_
.end()) {
714 worker_to_provider_
.erase(provider
->second
->controller_handle_id());
715 if (info
.handle_id
!= kInvalidServiceWorkerHandleId
)
716 worker_to_provider_
[info
.handle_id
] = provider
->second
;
717 provider
->second
->OnSetControllerServiceWorker(info
);
720 ProviderClientMap::iterator found
= provider_clients_
.find(provider_id
);
721 if (found
!= provider_clients_
.end()) {
722 // Populate the .controller field with the new worker object.
723 found
->second
->setController(GetServiceWorker(info
, false),
724 should_notify_controllerchange
);
728 void ServiceWorkerDispatcher::OnPostMessage(
729 const ServiceWorkerMsg_MessageToDocument_Params
& params
) {
730 // Make sure we're on the main document thread. (That must be the only
731 // thread we get this message)
732 DCHECK(ChildThreadImpl::current());
733 TRACE_EVENT1("ServiceWorker", "ServiceWorkerDispatcher::OnPostMessage",
734 "Thread ID", params
.thread_id
);
736 ProviderClientMap::iterator found
=
737 provider_clients_
.find(params
.provider_id
);
738 if (found
== provider_clients_
.end()) {
739 // For now we do no queueing for messages sent to nonexistent / unattached
744 blink::WebMessagePortChannelArray ports
=
745 WebMessagePortChannelImpl::CreatePorts(
746 params
.message_ports
, params
.new_routing_ids
,
747 base::ThreadTaskRunnerHandle::Get());
749 found
->second
->dispatchMessageEvent(
750 GetServiceWorker(params
.service_worker_info
, false /* adopt_handle */),
751 params
.message
, ports
);
754 void ServiceWorkerDispatcher::AddServiceWorker(
755 int handle_id
, WebServiceWorkerImpl
* worker
) {
756 DCHECK(!ContainsKey(service_workers_
, handle_id
));
757 service_workers_
[handle_id
] = worker
;
760 void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id
) {
761 DCHECK(ContainsKey(service_workers_
, handle_id
));
762 service_workers_
.erase(handle_id
);
765 void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
766 int registration_handle_id
,
767 WebServiceWorkerRegistrationImpl
* registration
) {
768 DCHECK(!ContainsKey(registrations_
, registration_handle_id
));
769 registrations_
[registration_handle_id
] = registration
;
772 void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
773 int registration_handle_id
) {
774 DCHECK(ContainsKey(registrations_
, registration_handle_id
));
775 registrations_
.erase(registration_handle_id
);
778 WebServiceWorkerRegistrationImpl
*
779 ServiceWorkerDispatcher::FindOrCreateRegistration(
780 const ServiceWorkerRegistrationObjectInfo
& info
,
781 const ServiceWorkerVersionAttributes
& attrs
) {
782 RegistrationObjectMap::iterator found
= registrations_
.find(info
.handle_id
);
783 if (found
!= registrations_
.end()) {
784 ServiceWorkerRegistrationHandleReference::Adopt(info
,
785 thread_safe_sender_
.get());
786 ServiceWorkerHandleReference::Adopt(attrs
.installing
,
787 thread_safe_sender_
.get());
788 ServiceWorkerHandleReference::Adopt(attrs
.waiting
,
789 thread_safe_sender_
.get());
790 ServiceWorkerHandleReference::Adopt(attrs
.active
,
791 thread_safe_sender_
.get());
792 return found
->second
;
795 bool adopt_handle
= true;
796 WebServiceWorkerRegistrationImpl
* registration
=
797 CreateServiceWorkerRegistration(info
, adopt_handle
);
798 registration
->SetInstalling(GetServiceWorker(attrs
.installing
, adopt_handle
));
799 registration
->SetWaiting(GetServiceWorker(attrs
.waiting
, adopt_handle
));
800 registration
->SetActive(GetServiceWorker(attrs
.active
, adopt_handle
));
804 } // namespace content