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/WebString.h"
25 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerClientsInfo.h"
26 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerProviderClient.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
<void>>::Leaky g_dispatcher_tls
=
38 LAZY_INSTANCE_INITIALIZER
;
40 void* const kHasBeenDeleted
= reinterpret_cast<void*>(0x1);
42 int CurrentWorkerId() {
43 return WorkerTaskRunner::Instance()->CurrentWorkerId();
48 ServiceWorkerDispatcher::ServiceWorkerDispatcher(
49 ThreadSafeSender
* thread_safe_sender
,
50 base::SingleThreadTaskRunner
* main_thread_task_runner
)
51 : thread_safe_sender_(thread_safe_sender
),
52 main_thread_task_runner_(main_thread_task_runner
) {
53 g_dispatcher_tls
.Pointer()->Set(static_cast<void*>(this));
56 ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
57 g_dispatcher_tls
.Pointer()->Set(kHasBeenDeleted
);
60 void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
62 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher
, msg
)
63 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistrationWithServiceWorker
,
64 OnAssociateRegistrationWithServiceWorker
)
65 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistration
,
66 OnAssociateRegistration
)
67 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DisassociateRegistration
,
68 OnDisassociateRegistration
)
69 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered
, OnRegistered
)
70 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUpdated
, OnUpdated
)
71 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered
,
73 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistration
,
75 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistrations
,
76 OnDidGetRegistrations
)
77 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistrationForReady
,
78 OnDidGetRegistrationForReady
)
79 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError
,
81 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUpdateError
,
83 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistrationError
,
84 OnUnregistrationError
)
85 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationError
,
86 OnGetRegistrationError
)
87 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationsError
,
88 OnGetRegistrationsError
)
89 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged
,
90 OnServiceWorkerStateChanged
)
91 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes
,
92 OnSetVersionAttributes
)
93 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_UpdateFound
,
95 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker
,
96 OnSetControllerServiceWorker
)
97 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument
,
99 IPC_MESSAGE_UNHANDLED(handled
= false)
100 IPC_END_MESSAGE_MAP()
101 DCHECK(handled
) << "Unhandled message:" << msg
.type();
104 bool ServiceWorkerDispatcher::Send(IPC::Message
* msg
) {
105 return thread_safe_sender_
->Send(msg
);
108 void ServiceWorkerDispatcher::RegisterServiceWorker(
111 const GURL
& script_url
,
112 WebServiceWorkerRegistrationCallbacks
* callbacks
) {
115 if (pattern
.possibly_invalid_spec().size() > GetMaxURLChars() ||
116 script_url
.possibly_invalid_spec().size() > GetMaxURLChars()) {
117 scoped_ptr
<WebServiceWorkerRegistrationCallbacks
>
118 owned_callbacks(callbacks
);
119 std::string
error_message(kServiceWorkerRegisterErrorPrefix
);
120 error_message
+= "The provided scriptURL or scope is too long.";
122 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity
,
123 blink::WebString::fromUTF8(error_message
)));
127 int request_id
= pending_registration_callbacks_
.Add(callbacks
);
128 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
129 "ServiceWorkerDispatcher::RegisterServiceWorker",
131 "Scope", pattern
.spec(),
132 "Script URL", script_url
.spec());
133 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
134 CurrentWorkerId(), request_id
, provider_id
, pattern
, script_url
));
137 void ServiceWorkerDispatcher::UpdateServiceWorker(
139 int64 registration_id
,
140 WebServiceWorkerUpdateCallbacks
* callbacks
) {
142 int request_id
= pending_update_callbacks_
.Add(callbacks
);
143 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_UpdateServiceWorker(
144 CurrentWorkerId(), request_id
, provider_id
, registration_id
));
147 void ServiceWorkerDispatcher::UnregisterServiceWorker(
149 int64 registration_id
,
150 WebServiceWorkerUnregistrationCallbacks
* callbacks
) {
152 int request_id
= pending_unregistration_callbacks_
.Add(callbacks
);
153 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
154 "ServiceWorkerDispatcher::UnregisterServiceWorker",
155 request_id
, "Registration ID", registration_id
);
156 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
157 CurrentWorkerId(), request_id
, provider_id
, registration_id
));
160 void ServiceWorkerDispatcher::GetRegistration(
162 const GURL
& document_url
,
163 WebServiceWorkerRegistrationCallbacks
* callbacks
) {
166 if (document_url
.possibly_invalid_spec().size() > GetMaxURLChars()) {
167 scoped_ptr
<WebServiceWorkerRegistrationCallbacks
>
168 owned_callbacks(callbacks
);
169 std::string
error_message(kServiceWorkerGetRegistrationErrorPrefix
);
170 error_message
+= "The provided documentURL is too long.";
172 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity
,
173 blink::WebString::fromUTF8(error_message
)));
177 int request_id
= pending_get_registration_callbacks_
.Add(callbacks
);
178 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
179 "ServiceWorkerDispatcher::GetRegistration",
181 "Document URL", document_url
.spec());
182 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetRegistration(
183 CurrentWorkerId(), request_id
, provider_id
, document_url
));
186 void ServiceWorkerDispatcher::GetRegistrations(
188 WebServiceWorkerGetRegistrationsCallbacks
* callbacks
) {
191 int request_id
= pending_get_registrations_callbacks_
.Add(callbacks
);
192 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
193 "ServiceWorkerDispatcher::GetRegistrations",
195 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetRegistrations(
196 CurrentWorkerId(), request_id
, provider_id
));
199 void ServiceWorkerDispatcher::GetRegistrationForReady(
201 WebServiceWorkerGetRegistrationForReadyCallbacks
* callbacks
) {
202 int request_id
= get_for_ready_callbacks_
.Add(callbacks
);
203 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
204 "ServiceWorkerDispatcher::GetRegistrationForReady",
206 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetRegistrationForReady(
207 CurrentWorkerId(), request_id
, provider_id
));
210 void ServiceWorkerDispatcher::AddProviderContext(
211 ServiceWorkerProviderContext
* provider_context
) {
212 DCHECK(provider_context
);
213 int provider_id
= provider_context
->provider_id();
214 DCHECK(!ContainsKey(provider_contexts_
, provider_id
));
215 provider_contexts_
[provider_id
] = provider_context
;
218 void ServiceWorkerDispatcher::RemoveProviderContext(
219 ServiceWorkerProviderContext
* provider_context
) {
220 DCHECK(provider_context
);
221 DCHECK(ContainsKey(provider_contexts_
, provider_context
->provider_id()));
222 provider_contexts_
.erase(provider_context
->provider_id());
223 worker_to_provider_
.erase(provider_context
->installing_handle_id());
224 worker_to_provider_
.erase(provider_context
->waiting_handle_id());
225 worker_to_provider_
.erase(provider_context
->active_handle_id());
226 worker_to_provider_
.erase(provider_context
->controller_handle_id());
229 void ServiceWorkerDispatcher::AddProviderClient(
231 blink::WebServiceWorkerProviderClient
* client
) {
233 DCHECK(!ContainsKey(provider_clients_
, provider_id
));
234 provider_clients_
[provider_id
] = client
;
237 void ServiceWorkerDispatcher::RemoveProviderClient(int provider_id
) {
238 // This could be possibly called multiple times to ensure termination.
239 if (ContainsKey(provider_clients_
, provider_id
))
240 provider_clients_
.erase(provider_id
);
243 ServiceWorkerDispatcher
*
244 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
245 ThreadSafeSender
* thread_safe_sender
,
246 base::SingleThreadTaskRunner
* main_thread_task_runner
) {
247 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
) {
248 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
249 g_dispatcher_tls
.Pointer()->Set(NULL
);
251 if (g_dispatcher_tls
.Pointer()->Get())
252 return static_cast<ServiceWorkerDispatcher
*>(
253 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 static_cast<ServiceWorkerDispatcher
*>(
266 g_dispatcher_tls
.Pointer()->Get());
269 void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
273 WebServiceWorkerImpl
* ServiceWorkerDispatcher::GetServiceWorker(
274 const ServiceWorkerObjectInfo
& info
,
276 if (info
.handle_id
== kInvalidServiceWorkerHandleId
)
279 WorkerObjectMap::iterator existing_worker
=
280 service_workers_
.find(info
.handle_id
);
282 if (existing_worker
!= service_workers_
.end()) {
284 // We are instructed to adopt a handle but we already have one, so
285 // adopt and destroy a handle ref.
286 ServiceWorkerHandleReference::Adopt(info
, thread_safe_sender_
.get());
288 return existing_worker
->second
;
291 scoped_ptr
<ServiceWorkerHandleReference
> handle_ref
=
293 ? ServiceWorkerHandleReference::Adopt(info
, thread_safe_sender_
.get())
294 : ServiceWorkerHandleReference::Create(info
,
295 thread_safe_sender_
.get());
296 // WebServiceWorkerImpl constructor calls AddServiceWorker.
297 return new WebServiceWorkerImpl(handle_ref
.Pass(), thread_safe_sender_
.get());
300 WebServiceWorkerRegistrationImpl
*
301 ServiceWorkerDispatcher::CreateServiceWorkerRegistration(
302 const ServiceWorkerRegistrationObjectInfo
& info
,
304 DCHECK(!ContainsKey(registrations_
, info
.handle_id
));
305 if (info
.handle_id
== kInvalidServiceWorkerRegistrationHandleId
)
308 scoped_ptr
<ServiceWorkerRegistrationHandleReference
> handle_ref
=
309 adopt_handle
? ServiceWorkerRegistrationHandleReference::Adopt(
310 info
, thread_safe_sender_
.get())
311 : ServiceWorkerRegistrationHandleReference::Create(
312 info
, thread_safe_sender_
.get());
314 // WebServiceWorkerRegistrationImpl constructor calls
315 // AddServiceWorkerRegistration.
316 return new WebServiceWorkerRegistrationImpl(handle_ref
.Pass());
319 // We can assume that this message handler is called before the worker context
320 // starts because script loading happens after this association.
321 // TODO(nhiroki): This association information could be pushed into
322 // EmbeddedWorkerMsg_StartWorker message and handed over to the worker thread
323 // without a lock in ServiceWorkerProviderContext.
324 void ServiceWorkerDispatcher::OnAssociateRegistrationWithServiceWorker(
327 const ServiceWorkerRegistrationObjectInfo
& info
,
328 const ServiceWorkerVersionAttributes
& attrs
) {
329 DCHECK_EQ(kDocumentMainThreadId
, thread_id
);
331 ProviderContextMap::iterator context
= provider_contexts_
.find(provider_id
);
332 if (context
== provider_contexts_
.end())
334 context
->second
->OnAssociateRegistration(info
, attrs
);
336 // We don't have to add entries into |worker_to_provider_| because state
337 // change events for the workers will be notified on the worker thread.
340 void ServiceWorkerDispatcher::OnAssociateRegistration(
343 const ServiceWorkerRegistrationObjectInfo
& info
,
344 const ServiceWorkerVersionAttributes
& attrs
) {
345 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
346 if (provider
== provider_contexts_
.end())
348 provider
->second
->OnAssociateRegistration(info
, attrs
);
349 if (attrs
.installing
.handle_id
!= kInvalidServiceWorkerHandleId
)
350 worker_to_provider_
[attrs
.installing
.handle_id
] = provider
->second
;
351 if (attrs
.waiting
.handle_id
!= kInvalidServiceWorkerHandleId
)
352 worker_to_provider_
[attrs
.waiting
.handle_id
] = provider
->second
;
353 if (attrs
.active
.handle_id
!= kInvalidServiceWorkerHandleId
)
354 worker_to_provider_
[attrs
.active
.handle_id
] = provider
->second
;
357 void ServiceWorkerDispatcher::OnDisassociateRegistration(
360 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
361 if (provider
== provider_contexts_
.end())
363 worker_to_provider_
.erase(provider
->second
->installing_handle_id());
364 worker_to_provider_
.erase(provider
->second
->waiting_handle_id());
365 worker_to_provider_
.erase(provider
->second
->active_handle_id());
366 worker_to_provider_
.erase(provider
->second
->controller_handle_id());
367 provider
->second
->OnDisassociateRegistration();
370 void ServiceWorkerDispatcher::OnRegistered(
373 const ServiceWorkerRegistrationObjectInfo
& info
,
374 const ServiceWorkerVersionAttributes
& attrs
) {
375 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
376 "ServiceWorkerDispatcher::RegisterServiceWorker",
379 TRACE_EVENT_ASYNC_END0("ServiceWorker",
380 "ServiceWorkerDispatcher::RegisterServiceWorker",
382 WebServiceWorkerRegistrationCallbacks
* callbacks
=
383 pending_registration_callbacks_
.Lookup(request_id
);
388 callbacks
->onSuccess(FindOrCreateRegistration(info
, attrs
));
389 pending_registration_callbacks_
.Remove(request_id
);
392 void ServiceWorkerDispatcher::OnUpdated(int thread_id
, int request_id
) {
393 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
394 "ServiceWorkerDispatcher::UpdateServiceWorker",
395 request_id
, "OnUpdated");
396 TRACE_EVENT_ASYNC_END0("ServiceWorker",
397 "ServiceWorkerDispatcher::UpdateServiceWorker",
399 WebServiceWorkerUpdateCallbacks
* callbacks
=
400 pending_update_callbacks_
.Lookup(request_id
);
405 callbacks
->onSuccess();
406 pending_update_callbacks_
.Remove(request_id
);
409 void ServiceWorkerDispatcher::OnUnregistered(int thread_id
,
412 TRACE_EVENT_ASYNC_STEP_INTO0(
414 "ServiceWorkerDispatcher::UnregisterServiceWorker",
417 TRACE_EVENT_ASYNC_END0("ServiceWorker",
418 "ServiceWorkerDispatcher::UnregisterServiceWorker",
420 WebServiceWorkerUnregistrationCallbacks
* callbacks
=
421 pending_unregistration_callbacks_
.Lookup(request_id
);
425 callbacks
->onSuccess(is_success
);
426 pending_unregistration_callbacks_
.Remove(request_id
);
429 void ServiceWorkerDispatcher::OnDidGetRegistration(
432 const ServiceWorkerRegistrationObjectInfo
& info
,
433 const ServiceWorkerVersionAttributes
& attrs
) {
434 TRACE_EVENT_ASYNC_STEP_INTO0(
436 "ServiceWorkerDispatcher::GetRegistration",
438 "OnDidGetRegistration");
439 TRACE_EVENT_ASYNC_END0("ServiceWorker",
440 "ServiceWorkerDispatcher::GetRegistration",
442 WebServiceWorkerRegistrationCallbacks
* callbacks
=
443 pending_get_registration_callbacks_
.Lookup(request_id
);
448 WebServiceWorkerRegistrationImpl
* registration
= NULL
;
449 if (info
.handle_id
!= kInvalidServiceWorkerHandleId
)
450 registration
= FindOrCreateRegistration(info
, attrs
);
452 callbacks
->onSuccess(registration
);
453 pending_get_registration_callbacks_
.Remove(request_id
);
456 void ServiceWorkerDispatcher::OnDidGetRegistrations(
459 const std::vector
<ServiceWorkerRegistrationObjectInfo
>& infos
,
460 const std::vector
<ServiceWorkerVersionAttributes
>& attrs
) {
461 TRACE_EVENT_ASYNC_STEP_INTO0(
463 "ServiceWorkerDispatcher::GetRegistrations",
465 "OnDidGetRegistrations");
466 TRACE_EVENT_ASYNC_END0("ServiceWorker",
467 "ServiceWorkerDispatcher::GetRegistrations",
470 WebServiceWorkerGetRegistrationsCallbacks
* callbacks
=
471 pending_get_registrations_callbacks_
.Lookup(request_id
);
476 typedef blink::WebVector
<blink::WebServiceWorkerRegistration
*>
477 WebServiceWorkerRegistrationArray
;
478 WebServiceWorkerRegistrationArray
* registrations
=
479 new WebServiceWorkerRegistrationArray(infos
.size());
480 for (size_t i
= 0; i
< infos
.size(); ++i
) {
481 if (infos
[i
].handle_id
!= kInvalidServiceWorkerHandleId
) {
482 ServiceWorkerRegistrationObjectInfo
info(infos
[i
]);
483 ServiceWorkerVersionAttributes
attr(attrs
[i
]);
484 (*registrations
)[i
] = FindOrCreateRegistration(info
, attr
);
488 callbacks
->onSuccess(registrations
);
489 pending_get_registrations_callbacks_
.Remove(request_id
);
492 void ServiceWorkerDispatcher::OnDidGetRegistrationForReady(
495 const ServiceWorkerRegistrationObjectInfo
& info
,
496 const ServiceWorkerVersionAttributes
& attrs
) {
497 TRACE_EVENT_ASYNC_STEP_INTO0(
499 "ServiceWorkerDispatcher::GetRegistrationForReady",
501 "OnDidGetRegistrationForReady");
502 TRACE_EVENT_ASYNC_END0("ServiceWorker",
503 "ServiceWorkerDispatcher::GetRegistrationForReady",
505 WebServiceWorkerGetRegistrationForReadyCallbacks
* callbacks
=
506 get_for_ready_callbacks_
.Lookup(request_id
);
511 WebServiceWorkerRegistrationImpl
* registration
= NULL
;
512 DCHECK(info
.handle_id
!= kInvalidServiceWorkerHandleId
);
513 registration
= FindOrCreateRegistration(info
, attrs
);
514 callbacks
->onSuccess(registration
);
515 get_for_ready_callbacks_
.Remove(request_id
);
518 void ServiceWorkerDispatcher::OnRegistrationError(
521 WebServiceWorkerError::ErrorType error_type
,
522 const base::string16
& message
) {
523 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
524 "ServiceWorkerDispatcher::RegisterServiceWorker",
526 "OnRegistrationError");
527 TRACE_EVENT_ASYNC_END0("ServiceWorker",
528 "ServiceWorkerDispatcher::RegisterServiceWorker",
530 WebServiceWorkerRegistrationCallbacks
* callbacks
=
531 pending_registration_callbacks_
.Lookup(request_id
);
536 callbacks
->onError(new WebServiceWorkerError(error_type
, message
));
537 pending_registration_callbacks_
.Remove(request_id
);
540 void ServiceWorkerDispatcher::OnUpdateError(
543 WebServiceWorkerError::ErrorType error_type
,
544 const base::string16
& message
) {
545 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
546 "ServiceWorkerDispatcher::UpdateServiceWorker",
547 request_id
, "OnUpdateError");
548 TRACE_EVENT_ASYNC_END0("ServiceWorker",
549 "ServiceWorkerDispatcher::UpdateServiceWorker",
551 WebServiceWorkerUpdateCallbacks
* callbacks
=
552 pending_update_callbacks_
.Lookup(request_id
);
557 callbacks
->onError(WebServiceWorkerError(error_type
, message
));
558 pending_update_callbacks_
.Remove(request_id
);
561 void ServiceWorkerDispatcher::OnUnregistrationError(
564 WebServiceWorkerError::ErrorType error_type
,
565 const base::string16
& message
) {
566 TRACE_EVENT_ASYNC_STEP_INTO0(
568 "ServiceWorkerDispatcher::UnregisterServiceWorker",
570 "OnUnregistrationError");
571 TRACE_EVENT_ASYNC_END0("ServiceWorker",
572 "ServiceWorkerDispatcher::UnregisterServiceWorker",
574 WebServiceWorkerUnregistrationCallbacks
* callbacks
=
575 pending_unregistration_callbacks_
.Lookup(request_id
);
580 callbacks
->onError(WebServiceWorkerError(error_type
, message
));
581 pending_unregistration_callbacks_
.Remove(request_id
);
584 void ServiceWorkerDispatcher::OnGetRegistrationError(
587 WebServiceWorkerError::ErrorType error_type
,
588 const base::string16
& message
) {
589 TRACE_EVENT_ASYNC_STEP_INTO0(
591 "ServiceWorkerDispatcher::GetRegistration",
593 "OnGetRegistrationError");
594 TRACE_EVENT_ASYNC_END0("ServiceWorker",
595 "ServiceWorkerDispatcher::GetRegistration",
597 WebServiceWorkerGetRegistrationCallbacks
* callbacks
=
598 pending_get_registration_callbacks_
.Lookup(request_id
);
603 callbacks
->onError(new WebServiceWorkerError(error_type
, message
));
604 pending_get_registration_callbacks_
.Remove(request_id
);
607 void ServiceWorkerDispatcher::OnGetRegistrationsError(
610 WebServiceWorkerError::ErrorType error_type
,
611 const base::string16
& message
) {
612 TRACE_EVENT_ASYNC_STEP_INTO0(
614 "ServiceWorkerDispatcher::GetRegistrations",
616 "OnGetRegistrationsError");
617 TRACE_EVENT_ASYNC_END0("ServiceWorker",
618 "ServiceWorkerDispatcher::GetRegistrations",
620 WebServiceWorkerGetRegistrationsCallbacks
* callbacks
=
621 pending_get_registrations_callbacks_
.Lookup(request_id
);
626 callbacks
->onError(new WebServiceWorkerError(error_type
, message
));
627 pending_get_registrations_callbacks_
.Remove(request_id
);
630 void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
633 blink::WebServiceWorkerState state
) {
634 TRACE_EVENT2("ServiceWorker",
635 "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
636 "Thread ID", thread_id
,
638 WorkerObjectMap::iterator worker
= service_workers_
.find(handle_id
);
639 if (worker
!= service_workers_
.end())
640 worker
->second
->OnStateChanged(state
);
642 WorkerToProviderMap::iterator provider
= worker_to_provider_
.find(handle_id
);
643 if (provider
!= worker_to_provider_
.end())
644 provider
->second
->OnServiceWorkerStateChanged(handle_id
, state
);
647 void ServiceWorkerDispatcher::OnSetVersionAttributes(
650 int registration_handle_id
,
652 const ServiceWorkerVersionAttributes
& attrs
) {
653 TRACE_EVENT1("ServiceWorker",
654 "ServiceWorkerDispatcher::OnSetVersionAttributes",
655 "Thread ID", thread_id
);
657 ChangedVersionAttributesMask
mask(changed_mask
);
658 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
659 if (provider
!= provider_contexts_
.end() &&
660 provider
->second
->registration_handle_id() == registration_handle_id
) {
661 if (mask
.installing_changed()) {
662 worker_to_provider_
.erase(provider
->second
->installing_handle_id());
663 if (attrs
.installing
.handle_id
!= kInvalidServiceWorkerHandleId
)
664 worker_to_provider_
[attrs
.installing
.handle_id
] = provider
->second
;
666 if (mask
.waiting_changed()) {
667 worker_to_provider_
.erase(provider
->second
->waiting_handle_id());
668 if (attrs
.waiting
.handle_id
!= kInvalidServiceWorkerHandleId
)
669 worker_to_provider_
[attrs
.waiting
.handle_id
] = provider
->second
;
671 if (mask
.active_changed()) {
672 worker_to_provider_
.erase(provider
->second
->active_handle_id());
673 if (attrs
.active
.handle_id
!= kInvalidServiceWorkerHandleId
)
674 worker_to_provider_
[attrs
.active
.handle_id
] = provider
->second
;
676 provider
->second
->SetVersionAttributes(mask
, attrs
);
679 RegistrationObjectMap::iterator found
=
680 registrations_
.find(registration_handle_id
);
681 if (found
!= registrations_
.end()) {
682 // Populate the version fields (eg. .installing) with new worker objects.
683 if (mask
.installing_changed())
684 found
->second
->SetInstalling(GetServiceWorker(attrs
.installing
, false));
685 if (mask
.waiting_changed())
686 found
->second
->SetWaiting(GetServiceWorker(attrs
.waiting
, false));
687 if (mask
.active_changed())
688 found
->second
->SetActive(GetServiceWorker(attrs
.active
, false));
692 void ServiceWorkerDispatcher::OnUpdateFound(
694 int registration_handle_id
) {
695 TRACE_EVENT0("ServiceWorker",
696 "ServiceWorkerDispatcher::OnUpdateFound");
697 RegistrationObjectMap::iterator found
=
698 registrations_
.find(registration_handle_id
);
699 if (found
!= registrations_
.end())
700 found
->second
->OnUpdateFound();
703 void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
706 const ServiceWorkerObjectInfo
& info
,
707 bool should_notify_controllerchange
) {
708 TRACE_EVENT2("ServiceWorker",
709 "ServiceWorkerDispatcher::OnSetControllerServiceWorker",
710 "Thread ID", thread_id
,
711 "Provider ID", provider_id
);
713 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
714 if (provider
!= provider_contexts_
.end()) {
715 worker_to_provider_
.erase(provider
->second
->controller_handle_id());
716 if (info
.handle_id
!= kInvalidServiceWorkerHandleId
)
717 worker_to_provider_
[info
.handle_id
] = provider
->second
;
718 provider
->second
->OnSetControllerServiceWorker(info
);
721 ProviderClientMap::iterator found
= provider_clients_
.find(provider_id
);
722 if (found
!= provider_clients_
.end()) {
723 // Populate the .controller field with the new worker object.
724 found
->second
->setController(GetServiceWorker(info
, false),
725 should_notify_controllerchange
);
729 void ServiceWorkerDispatcher::OnPostMessage(
730 const ServiceWorkerMsg_MessageToDocument_Params
& params
) {
731 // Make sure we're on the main document thread. (That must be the only
732 // thread we get this message)
733 DCHECK(ChildThreadImpl::current());
734 TRACE_EVENT1("ServiceWorker", "ServiceWorkerDispatcher::OnPostMessage",
735 "Thread ID", params
.thread_id
);
737 ProviderClientMap::iterator found
=
738 provider_clients_
.find(params
.provider_id
);
739 if (found
== provider_clients_
.end()) {
740 // For now we do no queueing for messages sent to nonexistent / unattached
745 blink::WebMessagePortChannelArray ports
=
746 WebMessagePortChannelImpl::CreatePorts(
747 params
.message_ports
, params
.new_routing_ids
,
748 base::ThreadTaskRunnerHandle::Get());
750 found
->second
->dispatchMessageEvent(
751 GetServiceWorker(params
.service_worker_info
, false /* adopt_handle */),
752 params
.message
, ports
);
755 void ServiceWorkerDispatcher::AddServiceWorker(
756 int handle_id
, WebServiceWorkerImpl
* worker
) {
757 DCHECK(!ContainsKey(service_workers_
, handle_id
));
758 service_workers_
[handle_id
] = worker
;
761 void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id
) {
762 DCHECK(ContainsKey(service_workers_
, handle_id
));
763 service_workers_
.erase(handle_id
);
766 void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
767 int registration_handle_id
,
768 WebServiceWorkerRegistrationImpl
* registration
) {
769 DCHECK(!ContainsKey(registrations_
, registration_handle_id
));
770 registrations_
[registration_handle_id
] = registration
;
773 void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
774 int registration_handle_id
) {
775 DCHECK(ContainsKey(registrations_
, registration_handle_id
));
776 registrations_
.erase(registration_handle_id
);
779 WebServiceWorkerRegistrationImpl
*
780 ServiceWorkerDispatcher::FindOrCreateRegistration(
781 const ServiceWorkerRegistrationObjectInfo
& info
,
782 const ServiceWorkerVersionAttributes
& attrs
) {
783 RegistrationObjectMap::iterator found
= registrations_
.find(info
.handle_id
);
784 if (found
!= registrations_
.end()) {
785 ServiceWorkerRegistrationHandleReference::Adopt(info
,
786 thread_safe_sender_
.get());
787 ServiceWorkerHandleReference::Adopt(attrs
.installing
,
788 thread_safe_sender_
.get());
789 ServiceWorkerHandleReference::Adopt(attrs
.waiting
,
790 thread_safe_sender_
.get());
791 ServiceWorkerHandleReference::Adopt(attrs
.active
,
792 thread_safe_sender_
.get());
793 return found
->second
;
796 bool adopt_handle
= true;
797 WebServiceWorkerRegistrationImpl
* registration
=
798 CreateServiceWorkerRegistration(info
, adopt_handle
);
799 registration
->SetInstalling(GetServiceWorker(attrs
.installing
, adopt_handle
));
800 registration
->SetWaiting(GetServiceWorker(attrs
.waiting
, adopt_handle
));
801 registration
->SetActive(GetServiceWorker(attrs
.active
, adopt_handle
));
805 } // namespace content