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/stl_util.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "base/threading/thread_local.h"
11 #include "base/trace_event/trace_event.h"
12 #include "content/child/child_thread_impl.h"
13 #include "content/child/service_worker/service_worker_handle_reference.h"
14 #include "content/child/service_worker/service_worker_provider_context.h"
15 #include "content/child/service_worker/service_worker_registration_handle_reference.h"
16 #include "content/child/service_worker/web_service_worker_impl.h"
17 #include "content/child/service_worker/web_service_worker_registration_impl.h"
18 #include "content/child/thread_safe_sender.h"
19 #include "content/child/webmessageportchannel_impl.h"
20 #include "content/common/service_worker/service_worker_messages.h"
21 #include "content/common/service_worker/service_worker_types.h"
22 #include "content/public/common/url_utils.h"
23 #include "third_party/WebKit/public/platform/WebServiceWorkerClientsInfo.h"
24 #include "third_party/WebKit/public/platform/WebServiceWorkerProviderClient.h"
25 #include "third_party/WebKit/public/platform/WebString.h"
26 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
28 using blink::WebServiceWorkerError
;
29 using blink::WebServiceWorkerProvider
;
30 using base::ThreadLocalPointer
;
36 base::LazyInstance
<ThreadLocalPointer
<ServiceWorkerDispatcher
> >::Leaky
37 g_dispatcher_tls
= LAZY_INSTANCE_INITIALIZER
;
39 ServiceWorkerDispatcher
* const kHasBeenDeleted
=
40 reinterpret_cast<ServiceWorkerDispatcher
*>(0x1);
42 int CurrentWorkerId() {
43 return WorkerTaskRunner::Instance()->CurrentWorkerId();
48 ServiceWorkerDispatcher::ServiceWorkerDispatcher(
49 ThreadSafeSender
* thread_safe_sender
)
50 : thread_safe_sender_(thread_safe_sender
) {
51 g_dispatcher_tls
.Pointer()->Set(this);
54 ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
55 g_dispatcher_tls
.Pointer()->Set(kHasBeenDeleted
);
58 void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
60 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher
, msg
)
61 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistrationWithServiceWorker
,
62 OnAssociateRegistrationWithServiceWorker
)
63 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistration
,
64 OnAssociateRegistration
)
65 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DisassociateRegistration
,
66 OnDisassociateRegistration
)
67 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered
, OnRegistered
)
68 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered
,
70 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistration
,
72 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistrations
,
73 OnDidGetRegistrations
)
74 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistrationForReady
,
75 OnDidGetRegistrationForReady
)
76 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError
,
78 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistrationError
,
79 OnUnregistrationError
)
80 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationError
,
81 OnGetRegistrationError
)
82 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationsError
,
83 OnGetRegistrationsError
)
84 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged
,
85 OnServiceWorkerStateChanged
)
86 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes
,
87 OnSetVersionAttributes
)
88 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_UpdateFound
,
90 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker
,
91 OnSetControllerServiceWorker
)
92 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument
,
94 IPC_MESSAGE_UNHANDLED(handled
= false)
96 DCHECK(handled
) << "Unhandled message:" << msg
.type();
99 bool ServiceWorkerDispatcher::Send(IPC::Message
* msg
) {
100 return thread_safe_sender_
->Send(msg
);
103 void ServiceWorkerDispatcher::RegisterServiceWorker(
106 const GURL
& script_url
,
107 WebServiceWorkerRegistrationCallbacks
* callbacks
) {
110 if (pattern
.possibly_invalid_spec().size() > GetMaxURLChars() ||
111 script_url
.possibly_invalid_spec().size() > GetMaxURLChars()) {
112 scoped_ptr
<WebServiceWorkerRegistrationCallbacks
>
113 owned_callbacks(callbacks
);
114 std::string
error_message(kServiceWorkerRegisterErrorPrefix
);
115 error_message
+= "The provided scriptURL or scope is too long.";
116 scoped_ptr
<WebServiceWorkerError
> error(
117 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity
,
118 blink::WebString::fromUTF8(error_message
)));
119 callbacks
->onError(error
.release());
123 int request_id
= pending_registration_callbacks_
.Add(callbacks
);
124 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
125 "ServiceWorkerDispatcher::RegisterServiceWorker",
127 "Scope", pattern
.spec(),
128 "Script URL", script_url
.spec());
129 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
130 CurrentWorkerId(), request_id
, provider_id
, pattern
, script_url
));
133 void ServiceWorkerDispatcher::UpdateServiceWorker(int provider_id
,
134 int64 registration_id
) {
135 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_UpdateServiceWorker(
136 provider_id
, registration_id
));
139 void ServiceWorkerDispatcher::UnregisterServiceWorker(
141 int64 registration_id
,
142 WebServiceWorkerUnregistrationCallbacks
* callbacks
) {
144 int request_id
= pending_unregistration_callbacks_
.Add(callbacks
);
145 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
146 "ServiceWorkerDispatcher::UnregisterServiceWorker",
147 request_id
, "Registration ID", registration_id
);
148 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
149 CurrentWorkerId(), request_id
, provider_id
, registration_id
));
152 void ServiceWorkerDispatcher::GetRegistration(
154 const GURL
& document_url
,
155 WebServiceWorkerRegistrationCallbacks
* callbacks
) {
158 if (document_url
.possibly_invalid_spec().size() > GetMaxURLChars()) {
159 scoped_ptr
<WebServiceWorkerRegistrationCallbacks
>
160 owned_callbacks(callbacks
);
161 std::string
error_message(kServiceWorkerGetRegistrationErrorPrefix
);
162 error_message
+= "The provided documentURL is too long.";
163 scoped_ptr
<WebServiceWorkerError
> error(
164 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity
,
165 blink::WebString::fromUTF8(error_message
)));
166 callbacks
->onError(error
.release());
170 int request_id
= pending_get_registration_callbacks_
.Add(callbacks
);
171 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
172 "ServiceWorkerDispatcher::GetRegistration",
174 "Document URL", document_url
.spec());
175 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetRegistration(
176 CurrentWorkerId(), request_id
, provider_id
, document_url
));
179 void ServiceWorkerDispatcher::GetRegistrations(
181 WebServiceWorkerGetRegistrationsCallbacks
* callbacks
) {
184 int request_id
= pending_get_registrations_callbacks_
.Add(callbacks
);
185 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
186 "ServiceWorkerDispatcher::GetRegistrations",
188 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetRegistrations(
189 CurrentWorkerId(), request_id
, provider_id
));
192 void ServiceWorkerDispatcher::GetRegistrationForReady(
194 WebServiceWorkerGetRegistrationForReadyCallbacks
* callbacks
) {
195 int request_id
= get_for_ready_callbacks_
.Add(callbacks
);
196 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
197 "ServiceWorkerDispatcher::GetRegistrationForReady",
199 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetRegistrationForReady(
200 CurrentWorkerId(), request_id
, provider_id
));
203 void ServiceWorkerDispatcher::AddProviderContext(
204 ServiceWorkerProviderContext
* provider_context
) {
205 DCHECK(provider_context
);
206 int provider_id
= provider_context
->provider_id();
207 DCHECK(!ContainsKey(provider_contexts_
, provider_id
));
208 provider_contexts_
[provider_id
] = provider_context
;
211 void ServiceWorkerDispatcher::RemoveProviderContext(
212 ServiceWorkerProviderContext
* provider_context
) {
213 DCHECK(provider_context
);
214 DCHECK(ContainsKey(provider_contexts_
, provider_context
->provider_id()));
215 provider_contexts_
.erase(provider_context
->provider_id());
216 worker_to_provider_
.erase(provider_context
->installing_handle_id());
217 worker_to_provider_
.erase(provider_context
->waiting_handle_id());
218 worker_to_provider_
.erase(provider_context
->active_handle_id());
219 worker_to_provider_
.erase(provider_context
->controller_handle_id());
222 void ServiceWorkerDispatcher::AddProviderClient(
224 blink::WebServiceWorkerProviderClient
* client
) {
226 DCHECK(!ContainsKey(provider_clients_
, provider_id
));
227 provider_clients_
[provider_id
] = client
;
230 void ServiceWorkerDispatcher::RemoveProviderClient(int provider_id
) {
231 // This could be possibly called multiple times to ensure termination.
232 if (ContainsKey(provider_clients_
, provider_id
))
233 provider_clients_
.erase(provider_id
);
236 ServiceWorkerDispatcher
*
237 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
238 ThreadSafeSender
* thread_safe_sender
) {
239 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
) {
240 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
241 g_dispatcher_tls
.Pointer()->Set(NULL
);
243 if (g_dispatcher_tls
.Pointer()->Get())
244 return g_dispatcher_tls
.Pointer()->Get();
246 ServiceWorkerDispatcher
* dispatcher
=
247 new ServiceWorkerDispatcher(thread_safe_sender
);
248 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
249 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher
);
253 ServiceWorkerDispatcher
* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
254 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
)
256 return g_dispatcher_tls
.Pointer()->Get();
259 void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
263 WebServiceWorkerImpl
* ServiceWorkerDispatcher::GetServiceWorker(
264 const ServiceWorkerObjectInfo
& info
,
266 if (info
.handle_id
== kInvalidServiceWorkerHandleId
)
269 WorkerObjectMap::iterator existing_worker
=
270 service_workers_
.find(info
.handle_id
);
272 if (existing_worker
!= service_workers_
.end()) {
274 // We are instructed to adopt a handle but we already have one, so
275 // adopt and destroy a handle ref.
276 ServiceWorkerHandleReference::Adopt(info
, thread_safe_sender_
.get());
278 return existing_worker
->second
;
281 scoped_ptr
<ServiceWorkerHandleReference
> handle_ref
=
283 ? ServiceWorkerHandleReference::Adopt(info
, thread_safe_sender_
.get())
284 : ServiceWorkerHandleReference::Create(info
,
285 thread_safe_sender_
.get());
286 // WebServiceWorkerImpl constructor calls AddServiceWorker.
287 return new WebServiceWorkerImpl(handle_ref
.Pass(), thread_safe_sender_
.get());
290 WebServiceWorkerRegistrationImpl
*
291 ServiceWorkerDispatcher::CreateServiceWorkerRegistration(
292 const ServiceWorkerRegistrationObjectInfo
& info
,
294 DCHECK(!ContainsKey(registrations_
, info
.handle_id
));
295 if (info
.handle_id
== kInvalidServiceWorkerRegistrationHandleId
)
298 scoped_ptr
<ServiceWorkerRegistrationHandleReference
> handle_ref
=
299 adopt_handle
? ServiceWorkerRegistrationHandleReference::Adopt(
300 info
, thread_safe_sender_
.get())
301 : ServiceWorkerRegistrationHandleReference::Create(
302 info
, thread_safe_sender_
.get());
304 // WebServiceWorkerRegistrationImpl constructor calls
305 // AddServiceWorkerRegistration.
306 return new WebServiceWorkerRegistrationImpl(handle_ref
.Pass());
309 // We can assume that this message handler is called before the worker context
310 // starts because script loading happens after this association.
311 // TODO(nhiroki): This association information could be pushed into
312 // EmbeddedWorkerMsg_StartWorker message and handed over to the worker thread
313 // without a lock in ServiceWorkerProviderContext.
314 void ServiceWorkerDispatcher::OnAssociateRegistrationWithServiceWorker(
317 const ServiceWorkerRegistrationObjectInfo
& info
,
318 const ServiceWorkerVersionAttributes
& attrs
) {
319 DCHECK_EQ(kDocumentMainThreadId
, thread_id
);
321 ProviderContextMap::iterator context
= provider_contexts_
.find(provider_id
);
322 if (context
== provider_contexts_
.end())
324 context
->second
->OnAssociateRegistration(info
, attrs
);
326 // We don't have to add entries into |worker_to_provider_| because state
327 // change events for the workers will be notified on the worker thread.
330 void ServiceWorkerDispatcher::OnAssociateRegistration(
333 const ServiceWorkerRegistrationObjectInfo
& info
,
334 const ServiceWorkerVersionAttributes
& attrs
) {
335 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
336 if (provider
== provider_contexts_
.end())
338 provider
->second
->OnAssociateRegistration(info
, attrs
);
339 if (attrs
.installing
.handle_id
!= kInvalidServiceWorkerHandleId
)
340 worker_to_provider_
[attrs
.installing
.handle_id
] = provider
->second
;
341 if (attrs
.waiting
.handle_id
!= kInvalidServiceWorkerHandleId
)
342 worker_to_provider_
[attrs
.waiting
.handle_id
] = provider
->second
;
343 if (attrs
.active
.handle_id
!= kInvalidServiceWorkerHandleId
)
344 worker_to_provider_
[attrs
.active
.handle_id
] = provider
->second
;
347 void ServiceWorkerDispatcher::OnDisassociateRegistration(
350 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
351 if (provider
== provider_contexts_
.end())
353 worker_to_provider_
.erase(provider
->second
->installing_handle_id());
354 worker_to_provider_
.erase(provider
->second
->waiting_handle_id());
355 worker_to_provider_
.erase(provider
->second
->active_handle_id());
356 worker_to_provider_
.erase(provider
->second
->controller_handle_id());
357 provider
->second
->OnDisassociateRegistration();
360 void ServiceWorkerDispatcher::OnRegistered(
363 const ServiceWorkerRegistrationObjectInfo
& info
,
364 const ServiceWorkerVersionAttributes
& attrs
) {
365 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
366 "ServiceWorkerDispatcher::RegisterServiceWorker",
369 TRACE_EVENT_ASYNC_END0("ServiceWorker",
370 "ServiceWorkerDispatcher::RegisterServiceWorker",
372 WebServiceWorkerRegistrationCallbacks
* callbacks
=
373 pending_registration_callbacks_
.Lookup(request_id
);
378 callbacks
->onSuccess(FindOrCreateRegistration(info
, attrs
));
379 pending_registration_callbacks_
.Remove(request_id
);
382 void ServiceWorkerDispatcher::OnUnregistered(int thread_id
,
385 TRACE_EVENT_ASYNC_STEP_INTO0(
387 "ServiceWorkerDispatcher::UnregisterServiceWorker",
390 TRACE_EVENT_ASYNC_END0("ServiceWorker",
391 "ServiceWorkerDispatcher::UnregisterServiceWorker",
393 WebServiceWorkerUnregistrationCallbacks
* callbacks
=
394 pending_unregistration_callbacks_
.Lookup(request_id
);
398 callbacks
->onSuccess(&is_success
);
399 pending_unregistration_callbacks_
.Remove(request_id
);
402 void ServiceWorkerDispatcher::OnDidGetRegistration(
405 const ServiceWorkerRegistrationObjectInfo
& info
,
406 const ServiceWorkerVersionAttributes
& attrs
) {
407 TRACE_EVENT_ASYNC_STEP_INTO0(
409 "ServiceWorkerDispatcher::GetRegistration",
411 "OnDidGetRegistration");
412 TRACE_EVENT_ASYNC_END0("ServiceWorker",
413 "ServiceWorkerDispatcher::GetRegistration",
415 WebServiceWorkerRegistrationCallbacks
* callbacks
=
416 pending_get_registration_callbacks_
.Lookup(request_id
);
421 WebServiceWorkerRegistrationImpl
* registration
= NULL
;
422 if (info
.handle_id
!= kInvalidServiceWorkerHandleId
)
423 registration
= FindOrCreateRegistration(info
, attrs
);
425 callbacks
->onSuccess(registration
);
426 pending_get_registration_callbacks_
.Remove(request_id
);
429 void ServiceWorkerDispatcher::OnDidGetRegistrations(
432 const std::vector
<ServiceWorkerRegistrationObjectInfo
>& infos
,
433 const std::vector
<ServiceWorkerVersionAttributes
>& attrs
) {
434 TRACE_EVENT_ASYNC_STEP_INTO0(
436 "ServiceWorkerDispatcher::GetRegistrations",
438 "OnDidGetRegistrations");
439 TRACE_EVENT_ASYNC_END0("ServiceWorker",
440 "ServiceWorkerDispatcher::GetRegistrations",
443 WebServiceWorkerGetRegistrationsCallbacks
* callbacks
=
444 pending_get_registrations_callbacks_
.Lookup(request_id
);
449 typedef blink::WebVector
<blink::WebServiceWorkerRegistration
*>
450 WebServiceWorkerRegistrationArray
;
451 scoped_ptr
<WebServiceWorkerRegistrationArray
>
452 registrations(new WebServiceWorkerRegistrationArray(infos
.size()));
453 for (size_t i
= 0; i
< infos
.size(); ++i
) {
454 if (infos
[i
].handle_id
!= kInvalidServiceWorkerHandleId
) {
455 ServiceWorkerRegistrationObjectInfo
info(infos
[i
]);
456 ServiceWorkerVersionAttributes
attr(attrs
[i
]);
457 (*registrations
)[i
] = FindOrCreateRegistration(info
, attr
);
461 callbacks
->onSuccess(registrations
.release());
462 pending_get_registrations_callbacks_
.Remove(request_id
);
465 void ServiceWorkerDispatcher::OnDidGetRegistrationForReady(
468 const ServiceWorkerRegistrationObjectInfo
& info
,
469 const ServiceWorkerVersionAttributes
& attrs
) {
470 TRACE_EVENT_ASYNC_STEP_INTO0(
472 "ServiceWorkerDispatcher::GetRegistrationForReady",
474 "OnDidGetRegistrationForReady");
475 TRACE_EVENT_ASYNC_END0("ServiceWorker",
476 "ServiceWorkerDispatcher::GetRegistrationForReady",
478 WebServiceWorkerGetRegistrationForReadyCallbacks
* callbacks
=
479 get_for_ready_callbacks_
.Lookup(request_id
);
484 WebServiceWorkerRegistrationImpl
* registration
= NULL
;
485 DCHECK(info
.handle_id
!= kInvalidServiceWorkerHandleId
);
486 registration
= FindOrCreateRegistration(info
, attrs
);
487 callbacks
->onSuccess(registration
);
488 get_for_ready_callbacks_
.Remove(request_id
);
491 void ServiceWorkerDispatcher::OnRegistrationError(
494 WebServiceWorkerError::ErrorType error_type
,
495 const base::string16
& message
) {
496 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
497 "ServiceWorkerDispatcher::RegisterServiceWorker",
499 "OnRegistrationError");
500 TRACE_EVENT_ASYNC_END0("ServiceWorker",
501 "ServiceWorkerDispatcher::RegisterServiceWorker",
503 WebServiceWorkerRegistrationCallbacks
* callbacks
=
504 pending_registration_callbacks_
.Lookup(request_id
);
509 scoped_ptr
<WebServiceWorkerError
> error(
510 new WebServiceWorkerError(error_type
, message
));
511 callbacks
->onError(error
.release());
512 pending_registration_callbacks_
.Remove(request_id
);
515 void ServiceWorkerDispatcher::OnUnregistrationError(
518 WebServiceWorkerError::ErrorType error_type
,
519 const base::string16
& message
) {
520 TRACE_EVENT_ASYNC_STEP_INTO0(
522 "ServiceWorkerDispatcher::UnregisterServiceWorker",
524 "OnUnregistrationError");
525 TRACE_EVENT_ASYNC_END0("ServiceWorker",
526 "ServiceWorkerDispatcher::UnregisterServiceWorker",
528 WebServiceWorkerUnregistrationCallbacks
* callbacks
=
529 pending_unregistration_callbacks_
.Lookup(request_id
);
534 scoped_ptr
<WebServiceWorkerError
> error(
535 new WebServiceWorkerError(error_type
, message
));
536 callbacks
->onError(error
.release());
537 pending_unregistration_callbacks_
.Remove(request_id
);
540 void ServiceWorkerDispatcher::OnGetRegistrationError(
543 WebServiceWorkerError::ErrorType error_type
,
544 const base::string16
& message
) {
545 TRACE_EVENT_ASYNC_STEP_INTO0(
547 "ServiceWorkerDispatcher::GetRegistration",
549 "OnGetRegistrationError");
550 TRACE_EVENT_ASYNC_END0("ServiceWorker",
551 "ServiceWorkerDispatcher::GetRegistration",
553 WebServiceWorkerGetRegistrationCallbacks
* callbacks
=
554 pending_get_registration_callbacks_
.Lookup(request_id
);
559 scoped_ptr
<WebServiceWorkerError
> error(
560 new WebServiceWorkerError(error_type
, message
));
561 callbacks
->onError(error
.release());
562 pending_get_registration_callbacks_
.Remove(request_id
);
565 void ServiceWorkerDispatcher::OnGetRegistrationsError(
568 WebServiceWorkerError::ErrorType error_type
,
569 const base::string16
& message
) {
570 TRACE_EVENT_ASYNC_STEP_INTO0(
572 "ServiceWorkerDispatcher::GetRegistrations",
574 "OnGetRegistrationsError");
575 TRACE_EVENT_ASYNC_END0("ServiceWorker",
576 "ServiceWorkerDispatcher::GetRegistrations",
578 WebServiceWorkerGetRegistrationsCallbacks
* callbacks
=
579 pending_get_registrations_callbacks_
.Lookup(request_id
);
584 scoped_ptr
<WebServiceWorkerError
> error(
585 new WebServiceWorkerError(error_type
, message
));
586 callbacks
->onError(error
.release());
587 pending_get_registrations_callbacks_
.Remove(request_id
);
590 void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
593 blink::WebServiceWorkerState state
) {
594 TRACE_EVENT2("ServiceWorker",
595 "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
596 "Thread ID", thread_id
,
598 WorkerObjectMap::iterator worker
= service_workers_
.find(handle_id
);
599 if (worker
!= service_workers_
.end())
600 worker
->second
->OnStateChanged(state
);
602 WorkerToProviderMap::iterator provider
= worker_to_provider_
.find(handle_id
);
603 if (provider
!= worker_to_provider_
.end())
604 provider
->second
->OnServiceWorkerStateChanged(handle_id
, state
);
607 void ServiceWorkerDispatcher::OnSetVersionAttributes(
610 int registration_handle_id
,
612 const ServiceWorkerVersionAttributes
& attrs
) {
613 TRACE_EVENT1("ServiceWorker",
614 "ServiceWorkerDispatcher::OnSetVersionAttributes",
615 "Thread ID", thread_id
);
617 ChangedVersionAttributesMask
mask(changed_mask
);
618 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
619 if (provider
!= provider_contexts_
.end() &&
620 provider
->second
->registration_handle_id() == registration_handle_id
) {
621 if (mask
.installing_changed()) {
622 worker_to_provider_
.erase(provider
->second
->installing_handle_id());
623 if (attrs
.installing
.handle_id
!= kInvalidServiceWorkerHandleId
)
624 worker_to_provider_
[attrs
.installing
.handle_id
] = provider
->second
;
626 if (mask
.waiting_changed()) {
627 worker_to_provider_
.erase(provider
->second
->waiting_handle_id());
628 if (attrs
.waiting
.handle_id
!= kInvalidServiceWorkerHandleId
)
629 worker_to_provider_
[attrs
.waiting
.handle_id
] = provider
->second
;
631 if (mask
.active_changed()) {
632 worker_to_provider_
.erase(provider
->second
->active_handle_id());
633 if (attrs
.active
.handle_id
!= kInvalidServiceWorkerHandleId
)
634 worker_to_provider_
[attrs
.active
.handle_id
] = provider
->second
;
636 provider
->second
->SetVersionAttributes(mask
, attrs
);
639 RegistrationObjectMap::iterator found
=
640 registrations_
.find(registration_handle_id
);
641 if (found
!= registrations_
.end()) {
642 // Populate the version fields (eg. .installing) with new worker objects.
643 if (mask
.installing_changed())
644 found
->second
->SetInstalling(GetServiceWorker(attrs
.installing
, false));
645 if (mask
.waiting_changed())
646 found
->second
->SetWaiting(GetServiceWorker(attrs
.waiting
, false));
647 if (mask
.active_changed())
648 found
->second
->SetActive(GetServiceWorker(attrs
.active
, false));
652 void ServiceWorkerDispatcher::OnUpdateFound(
654 int registration_handle_id
) {
655 TRACE_EVENT0("ServiceWorker",
656 "ServiceWorkerDispatcher::OnUpdateFound");
657 RegistrationObjectMap::iterator found
=
658 registrations_
.find(registration_handle_id
);
659 if (found
!= registrations_
.end())
660 found
->second
->OnUpdateFound();
663 void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
666 const ServiceWorkerObjectInfo
& info
,
667 bool should_notify_controllerchange
) {
668 TRACE_EVENT2("ServiceWorker",
669 "ServiceWorkerDispatcher::OnSetControllerServiceWorker",
670 "Thread ID", thread_id
,
671 "Provider ID", provider_id
);
673 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
674 if (provider
!= provider_contexts_
.end()) {
675 worker_to_provider_
.erase(provider
->second
->controller_handle_id());
676 if (info
.handle_id
!= kInvalidServiceWorkerHandleId
)
677 worker_to_provider_
[info
.handle_id
] = provider
->second
;
678 provider
->second
->OnSetControllerServiceWorker(info
);
681 ProviderClientMap::iterator found
= provider_clients_
.find(provider_id
);
682 if (found
!= provider_clients_
.end()) {
683 // Populate the .controller field with the new worker object.
684 found
->second
->setController(GetServiceWorker(info
, false),
685 should_notify_controllerchange
);
689 void ServiceWorkerDispatcher::OnPostMessage(
692 const base::string16
& message
,
693 const std::vector
<TransferredMessagePort
>& sent_message_ports
,
694 const std::vector
<int>& new_routing_ids
) {
695 // Make sure we're on the main document thread. (That must be the only
696 // thread we get this message)
697 DCHECK(ChildThreadImpl::current());
698 TRACE_EVENT1("ServiceWorker",
699 "ServiceWorkerDispatcher::OnPostMessage",
700 "Thread ID", thread_id
);
702 ProviderClientMap::iterator found
= provider_clients_
.find(provider_id
);
703 if (found
== provider_clients_
.end()) {
704 // For now we do no queueing for messages sent to nonexistent / unattached
709 blink::WebMessagePortChannelArray ports
=
710 WebMessagePortChannelImpl::CreatePorts(
711 sent_message_ports
, new_routing_ids
,
712 base::ThreadTaskRunnerHandle::Get());
714 found
->second
->dispatchMessageEvent(message
, ports
);
717 void ServiceWorkerDispatcher::AddServiceWorker(
718 int handle_id
, WebServiceWorkerImpl
* worker
) {
719 DCHECK(!ContainsKey(service_workers_
, handle_id
));
720 service_workers_
[handle_id
] = worker
;
723 void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id
) {
724 DCHECK(ContainsKey(service_workers_
, handle_id
));
725 service_workers_
.erase(handle_id
);
728 void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
729 int registration_handle_id
,
730 WebServiceWorkerRegistrationImpl
* registration
) {
731 DCHECK(!ContainsKey(registrations_
, registration_handle_id
));
732 registrations_
[registration_handle_id
] = registration
;
735 void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
736 int registration_handle_id
) {
737 DCHECK(ContainsKey(registrations_
, registration_handle_id
));
738 registrations_
.erase(registration_handle_id
);
741 WebServiceWorkerRegistrationImpl
*
742 ServiceWorkerDispatcher::FindOrCreateRegistration(
743 const ServiceWorkerRegistrationObjectInfo
& info
,
744 const ServiceWorkerVersionAttributes
& attrs
) {
745 RegistrationObjectMap::iterator found
= registrations_
.find(info
.handle_id
);
746 if (found
!= registrations_
.end()) {
747 ServiceWorkerRegistrationHandleReference::Adopt(info
,
748 thread_safe_sender_
.get());
749 ServiceWorkerHandleReference::Adopt(attrs
.installing
,
750 thread_safe_sender_
.get());
751 ServiceWorkerHandleReference::Adopt(attrs
.waiting
,
752 thread_safe_sender_
.get());
753 ServiceWorkerHandleReference::Adopt(attrs
.active
,
754 thread_safe_sender_
.get());
755 return found
->second
;
758 bool adopt_handle
= true;
759 WebServiceWorkerRegistrationImpl
* registration
=
760 CreateServiceWorkerRegistration(info
, adopt_handle
);
761 registration
->SetInstalling(GetServiceWorker(attrs
.installing
, adopt_handle
));
762 registration
->SetWaiting(GetServiceWorker(attrs
.waiting
, adopt_handle
));
763 registration
->SetActive(GetServiceWorker(attrs
.active
, adopt_handle
));
767 } // namespace content