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.";
122 scoped_ptr
<WebServiceWorkerError
> error(
123 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity
,
124 blink::WebString::fromUTF8(error_message
)));
125 callbacks
->onError(error
.release());
129 int request_id
= pending_registration_callbacks_
.Add(callbacks
);
130 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
131 "ServiceWorkerDispatcher::RegisterServiceWorker",
133 "Scope", pattern
.spec(),
134 "Script URL", script_url
.spec());
135 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
136 CurrentWorkerId(), request_id
, provider_id
, pattern
, script_url
));
139 void ServiceWorkerDispatcher::UpdateServiceWorker(
141 int64 registration_id
,
142 WebServiceWorkerUpdateCallbacks
* callbacks
) {
144 int request_id
= pending_update_callbacks_
.Add(callbacks
);
145 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_UpdateServiceWorker(
146 CurrentWorkerId(), request_id
, provider_id
, registration_id
));
149 void ServiceWorkerDispatcher::UnregisterServiceWorker(
151 int64 registration_id
,
152 WebServiceWorkerUnregistrationCallbacks
* callbacks
) {
154 int request_id
= pending_unregistration_callbacks_
.Add(callbacks
);
155 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
156 "ServiceWorkerDispatcher::UnregisterServiceWorker",
157 request_id
, "Registration ID", registration_id
);
158 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
159 CurrentWorkerId(), request_id
, provider_id
, registration_id
));
162 void ServiceWorkerDispatcher::GetRegistration(
164 const GURL
& document_url
,
165 WebServiceWorkerRegistrationCallbacks
* callbacks
) {
168 if (document_url
.possibly_invalid_spec().size() > GetMaxURLChars()) {
169 scoped_ptr
<WebServiceWorkerRegistrationCallbacks
>
170 owned_callbacks(callbacks
);
171 std::string
error_message(kServiceWorkerGetRegistrationErrorPrefix
);
172 error_message
+= "The provided documentURL is too long.";
173 scoped_ptr
<WebServiceWorkerError
> error(
174 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity
,
175 blink::WebString::fromUTF8(error_message
)));
176 callbacks
->onError(error
.release());
180 int request_id
= pending_get_registration_callbacks_
.Add(callbacks
);
181 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
182 "ServiceWorkerDispatcher::GetRegistration",
184 "Document URL", document_url
.spec());
185 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetRegistration(
186 CurrentWorkerId(), request_id
, provider_id
, document_url
));
189 void ServiceWorkerDispatcher::GetRegistrations(
191 WebServiceWorkerGetRegistrationsCallbacks
* callbacks
) {
194 int request_id
= pending_get_registrations_callbacks_
.Add(callbacks
);
195 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
196 "ServiceWorkerDispatcher::GetRegistrations",
198 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetRegistrations(
199 CurrentWorkerId(), request_id
, provider_id
));
202 void ServiceWorkerDispatcher::GetRegistrationForReady(
204 WebServiceWorkerGetRegistrationForReadyCallbacks
* callbacks
) {
205 int request_id
= get_for_ready_callbacks_
.Add(callbacks
);
206 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
207 "ServiceWorkerDispatcher::GetRegistrationForReady",
209 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetRegistrationForReady(
210 CurrentWorkerId(), request_id
, provider_id
));
213 void ServiceWorkerDispatcher::AddProviderContext(
214 ServiceWorkerProviderContext
* provider_context
) {
215 DCHECK(provider_context
);
216 int provider_id
= provider_context
->provider_id();
217 DCHECK(!ContainsKey(provider_contexts_
, provider_id
));
218 provider_contexts_
[provider_id
] = provider_context
;
221 void ServiceWorkerDispatcher::RemoveProviderContext(
222 ServiceWorkerProviderContext
* provider_context
) {
223 DCHECK(provider_context
);
224 DCHECK(ContainsKey(provider_contexts_
, provider_context
->provider_id()));
225 provider_contexts_
.erase(provider_context
->provider_id());
226 worker_to_provider_
.erase(provider_context
->installing_handle_id());
227 worker_to_provider_
.erase(provider_context
->waiting_handle_id());
228 worker_to_provider_
.erase(provider_context
->active_handle_id());
229 worker_to_provider_
.erase(provider_context
->controller_handle_id());
232 void ServiceWorkerDispatcher::AddProviderClient(
234 blink::WebServiceWorkerProviderClient
* client
) {
236 DCHECK(!ContainsKey(provider_clients_
, provider_id
));
237 provider_clients_
[provider_id
] = client
;
240 void ServiceWorkerDispatcher::RemoveProviderClient(int provider_id
) {
241 // This could be possibly called multiple times to ensure termination.
242 if (ContainsKey(provider_clients_
, provider_id
))
243 provider_clients_
.erase(provider_id
);
246 ServiceWorkerDispatcher
*
247 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
248 ThreadSafeSender
* thread_safe_sender
,
249 base::SingleThreadTaskRunner
* main_thread_task_runner
) {
250 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
) {
251 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
252 g_dispatcher_tls
.Pointer()->Set(NULL
);
254 if (g_dispatcher_tls
.Pointer()->Get())
255 return g_dispatcher_tls
.Pointer()->Get();
257 ServiceWorkerDispatcher
* dispatcher
=
258 new ServiceWorkerDispatcher(thread_safe_sender
, main_thread_task_runner
);
259 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
260 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher
);
264 ServiceWorkerDispatcher
* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
265 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
)
267 return g_dispatcher_tls
.Pointer()->Get();
270 void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
274 WebServiceWorkerImpl
* ServiceWorkerDispatcher::GetServiceWorker(
275 const ServiceWorkerObjectInfo
& info
,
277 if (info
.handle_id
== kInvalidServiceWorkerHandleId
)
280 WorkerObjectMap::iterator existing_worker
=
281 service_workers_
.find(info
.handle_id
);
283 if (existing_worker
!= service_workers_
.end()) {
285 // We are instructed to adopt a handle but we already have one, so
286 // adopt and destroy a handle ref.
287 ServiceWorkerHandleReference::Adopt(info
, thread_safe_sender_
.get());
289 return existing_worker
->second
;
292 scoped_ptr
<ServiceWorkerHandleReference
> handle_ref
=
294 ? ServiceWorkerHandleReference::Adopt(info
, thread_safe_sender_
.get())
295 : ServiceWorkerHandleReference::Create(info
,
296 thread_safe_sender_
.get());
297 // WebServiceWorkerImpl constructor calls AddServiceWorker.
298 return new WebServiceWorkerImpl(handle_ref
.Pass(), thread_safe_sender_
.get());
301 WebServiceWorkerRegistrationImpl
*
302 ServiceWorkerDispatcher::CreateServiceWorkerRegistration(
303 const ServiceWorkerRegistrationObjectInfo
& info
,
305 DCHECK(!ContainsKey(registrations_
, info
.handle_id
));
306 if (info
.handle_id
== kInvalidServiceWorkerRegistrationHandleId
)
309 scoped_ptr
<ServiceWorkerRegistrationHandleReference
> handle_ref
=
310 adopt_handle
? ServiceWorkerRegistrationHandleReference::Adopt(
311 info
, thread_safe_sender_
.get())
312 : ServiceWorkerRegistrationHandleReference::Create(
313 info
, thread_safe_sender_
.get());
315 // WebServiceWorkerRegistrationImpl constructor calls
316 // AddServiceWorkerRegistration.
317 return new WebServiceWorkerRegistrationImpl(handle_ref
.Pass());
320 // We can assume that this message handler is called before the worker context
321 // starts because script loading happens after this association.
322 // TODO(nhiroki): This association information could be pushed into
323 // EmbeddedWorkerMsg_StartWorker message and handed over to the worker thread
324 // without a lock in ServiceWorkerProviderContext.
325 void ServiceWorkerDispatcher::OnAssociateRegistrationWithServiceWorker(
328 const ServiceWorkerRegistrationObjectInfo
& info
,
329 const ServiceWorkerVersionAttributes
& attrs
) {
330 DCHECK_EQ(kDocumentMainThreadId
, thread_id
);
332 ProviderContextMap::iterator context
= provider_contexts_
.find(provider_id
);
333 if (context
== provider_contexts_
.end())
335 context
->second
->OnAssociateRegistration(info
, attrs
);
337 // We don't have to add entries into |worker_to_provider_| because state
338 // change events for the workers will be notified on the worker thread.
341 void ServiceWorkerDispatcher::OnAssociateRegistration(
344 const ServiceWorkerRegistrationObjectInfo
& info
,
345 const ServiceWorkerVersionAttributes
& attrs
) {
346 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
347 if (provider
== provider_contexts_
.end())
349 provider
->second
->OnAssociateRegistration(info
, attrs
);
350 if (attrs
.installing
.handle_id
!= kInvalidServiceWorkerHandleId
)
351 worker_to_provider_
[attrs
.installing
.handle_id
] = provider
->second
;
352 if (attrs
.waiting
.handle_id
!= kInvalidServiceWorkerHandleId
)
353 worker_to_provider_
[attrs
.waiting
.handle_id
] = provider
->second
;
354 if (attrs
.active
.handle_id
!= kInvalidServiceWorkerHandleId
)
355 worker_to_provider_
[attrs
.active
.handle_id
] = provider
->second
;
358 void ServiceWorkerDispatcher::OnDisassociateRegistration(
361 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
362 if (provider
== provider_contexts_
.end())
364 worker_to_provider_
.erase(provider
->second
->installing_handle_id());
365 worker_to_provider_
.erase(provider
->second
->waiting_handle_id());
366 worker_to_provider_
.erase(provider
->second
->active_handle_id());
367 worker_to_provider_
.erase(provider
->second
->controller_handle_id());
368 provider
->second
->OnDisassociateRegistration();
371 void ServiceWorkerDispatcher::OnRegistered(
374 const ServiceWorkerRegistrationObjectInfo
& info
,
375 const ServiceWorkerVersionAttributes
& attrs
) {
376 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
377 "ServiceWorkerDispatcher::RegisterServiceWorker",
380 TRACE_EVENT_ASYNC_END0("ServiceWorker",
381 "ServiceWorkerDispatcher::RegisterServiceWorker",
383 WebServiceWorkerRegistrationCallbacks
* callbacks
=
384 pending_registration_callbacks_
.Lookup(request_id
);
389 callbacks
->onSuccess(FindOrCreateRegistration(info
, attrs
));
390 pending_registration_callbacks_
.Remove(request_id
);
393 void ServiceWorkerDispatcher::OnUpdated(int thread_id
, int request_id
) {
394 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
395 "ServiceWorkerDispatcher::UpdateServiceWorker",
396 request_id
, "OnUpdated");
397 TRACE_EVENT_ASYNC_END0("ServiceWorker",
398 "ServiceWorkerDispatcher::UpdateServiceWorker",
400 WebServiceWorkerUpdateCallbacks
* callbacks
=
401 pending_update_callbacks_
.Lookup(request_id
);
406 callbacks
->onSuccess();
407 pending_update_callbacks_
.Remove(request_id
);
410 void ServiceWorkerDispatcher::OnUnregistered(int thread_id
,
413 TRACE_EVENT_ASYNC_STEP_INTO0(
415 "ServiceWorkerDispatcher::UnregisterServiceWorker",
418 TRACE_EVENT_ASYNC_END0("ServiceWorker",
419 "ServiceWorkerDispatcher::UnregisterServiceWorker",
421 WebServiceWorkerUnregistrationCallbacks
* callbacks
=
422 pending_unregistration_callbacks_
.Lookup(request_id
);
426 callbacks
->onSuccess(&is_success
);
427 pending_unregistration_callbacks_
.Remove(request_id
);
430 void ServiceWorkerDispatcher::OnDidGetRegistration(
433 const ServiceWorkerRegistrationObjectInfo
& info
,
434 const ServiceWorkerVersionAttributes
& attrs
) {
435 TRACE_EVENT_ASYNC_STEP_INTO0(
437 "ServiceWorkerDispatcher::GetRegistration",
439 "OnDidGetRegistration");
440 TRACE_EVENT_ASYNC_END0("ServiceWorker",
441 "ServiceWorkerDispatcher::GetRegistration",
443 WebServiceWorkerRegistrationCallbacks
* callbacks
=
444 pending_get_registration_callbacks_
.Lookup(request_id
);
449 WebServiceWorkerRegistrationImpl
* registration
= NULL
;
450 if (info
.handle_id
!= kInvalidServiceWorkerHandleId
)
451 registration
= FindOrCreateRegistration(info
, attrs
);
453 callbacks
->onSuccess(registration
);
454 pending_get_registration_callbacks_
.Remove(request_id
);
457 void ServiceWorkerDispatcher::OnDidGetRegistrations(
460 const std::vector
<ServiceWorkerRegistrationObjectInfo
>& infos
,
461 const std::vector
<ServiceWorkerVersionAttributes
>& attrs
) {
462 TRACE_EVENT_ASYNC_STEP_INTO0(
464 "ServiceWorkerDispatcher::GetRegistrations",
466 "OnDidGetRegistrations");
467 TRACE_EVENT_ASYNC_END0("ServiceWorker",
468 "ServiceWorkerDispatcher::GetRegistrations",
471 WebServiceWorkerGetRegistrationsCallbacks
* callbacks
=
472 pending_get_registrations_callbacks_
.Lookup(request_id
);
477 typedef blink::WebVector
<blink::WebServiceWorkerRegistration
*>
478 WebServiceWorkerRegistrationArray
;
479 scoped_ptr
<WebServiceWorkerRegistrationArray
>
480 registrations(new WebServiceWorkerRegistrationArray(infos
.size()));
481 for (size_t i
= 0; i
< infos
.size(); ++i
) {
482 if (infos
[i
].handle_id
!= kInvalidServiceWorkerHandleId
) {
483 ServiceWorkerRegistrationObjectInfo
info(infos
[i
]);
484 ServiceWorkerVersionAttributes
attr(attrs
[i
]);
485 (*registrations
)[i
] = FindOrCreateRegistration(info
, attr
);
489 callbacks
->onSuccess(registrations
.release());
490 pending_get_registrations_callbacks_
.Remove(request_id
);
493 void ServiceWorkerDispatcher::OnDidGetRegistrationForReady(
496 const ServiceWorkerRegistrationObjectInfo
& info
,
497 const ServiceWorkerVersionAttributes
& attrs
) {
498 TRACE_EVENT_ASYNC_STEP_INTO0(
500 "ServiceWorkerDispatcher::GetRegistrationForReady",
502 "OnDidGetRegistrationForReady");
503 TRACE_EVENT_ASYNC_END0("ServiceWorker",
504 "ServiceWorkerDispatcher::GetRegistrationForReady",
506 WebServiceWorkerGetRegistrationForReadyCallbacks
* callbacks
=
507 get_for_ready_callbacks_
.Lookup(request_id
);
512 WebServiceWorkerRegistrationImpl
* registration
= NULL
;
513 DCHECK(info
.handle_id
!= kInvalidServiceWorkerHandleId
);
514 registration
= FindOrCreateRegistration(info
, attrs
);
515 callbacks
->onSuccess(registration
);
516 get_for_ready_callbacks_
.Remove(request_id
);
519 void ServiceWorkerDispatcher::OnRegistrationError(
522 WebServiceWorkerError::ErrorType error_type
,
523 const base::string16
& message
) {
524 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
525 "ServiceWorkerDispatcher::RegisterServiceWorker",
527 "OnRegistrationError");
528 TRACE_EVENT_ASYNC_END0("ServiceWorker",
529 "ServiceWorkerDispatcher::RegisterServiceWorker",
531 WebServiceWorkerRegistrationCallbacks
* callbacks
=
532 pending_registration_callbacks_
.Lookup(request_id
);
537 scoped_ptr
<WebServiceWorkerError
> error(
538 new WebServiceWorkerError(error_type
, message
));
539 callbacks
->onError(error
.release());
540 pending_registration_callbacks_
.Remove(request_id
);
543 void ServiceWorkerDispatcher::OnUpdateError(
546 WebServiceWorkerError::ErrorType error_type
,
547 const base::string16
& message
) {
548 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
549 "ServiceWorkerDispatcher::UpdateServiceWorker",
550 request_id
, "OnUpdateError");
551 TRACE_EVENT_ASYNC_END0("ServiceWorker",
552 "ServiceWorkerDispatcher::UpdateServiceWorker",
554 WebServiceWorkerUpdateCallbacks
* callbacks
=
555 pending_update_callbacks_
.Lookup(request_id
);
560 callbacks
->onError(new WebServiceWorkerError(error_type
, message
));
561 pending_update_callbacks_
.Remove(request_id
);
564 void ServiceWorkerDispatcher::OnUnregistrationError(
567 WebServiceWorkerError::ErrorType error_type
,
568 const base::string16
& message
) {
569 TRACE_EVENT_ASYNC_STEP_INTO0(
571 "ServiceWorkerDispatcher::UnregisterServiceWorker",
573 "OnUnregistrationError");
574 TRACE_EVENT_ASYNC_END0("ServiceWorker",
575 "ServiceWorkerDispatcher::UnregisterServiceWorker",
577 WebServiceWorkerUnregistrationCallbacks
* callbacks
=
578 pending_unregistration_callbacks_
.Lookup(request_id
);
583 scoped_ptr
<WebServiceWorkerError
> error(
584 new WebServiceWorkerError(error_type
, message
));
585 callbacks
->onError(error
.release());
586 pending_unregistration_callbacks_
.Remove(request_id
);
589 void ServiceWorkerDispatcher::OnGetRegistrationError(
592 WebServiceWorkerError::ErrorType error_type
,
593 const base::string16
& message
) {
594 TRACE_EVENT_ASYNC_STEP_INTO0(
596 "ServiceWorkerDispatcher::GetRegistration",
598 "OnGetRegistrationError");
599 TRACE_EVENT_ASYNC_END0("ServiceWorker",
600 "ServiceWorkerDispatcher::GetRegistration",
602 WebServiceWorkerGetRegistrationCallbacks
* callbacks
=
603 pending_get_registration_callbacks_
.Lookup(request_id
);
608 scoped_ptr
<WebServiceWorkerError
> error(
609 new WebServiceWorkerError(error_type
, message
));
610 callbacks
->onError(error
.release());
611 pending_get_registration_callbacks_
.Remove(request_id
);
614 void ServiceWorkerDispatcher::OnGetRegistrationsError(
617 WebServiceWorkerError::ErrorType error_type
,
618 const base::string16
& message
) {
619 TRACE_EVENT_ASYNC_STEP_INTO0(
621 "ServiceWorkerDispatcher::GetRegistrations",
623 "OnGetRegistrationsError");
624 TRACE_EVENT_ASYNC_END0("ServiceWorker",
625 "ServiceWorkerDispatcher::GetRegistrations",
627 WebServiceWorkerGetRegistrationsCallbacks
* callbacks
=
628 pending_get_registrations_callbacks_
.Lookup(request_id
);
633 scoped_ptr
<WebServiceWorkerError
> error(
634 new WebServiceWorkerError(error_type
, message
));
635 callbacks
->onError(error
.release());
636 pending_get_registrations_callbacks_
.Remove(request_id
);
639 void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
642 blink::WebServiceWorkerState state
) {
643 TRACE_EVENT2("ServiceWorker",
644 "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
645 "Thread ID", thread_id
,
647 WorkerObjectMap::iterator worker
= service_workers_
.find(handle_id
);
648 if (worker
!= service_workers_
.end())
649 worker
->second
->OnStateChanged(state
);
651 WorkerToProviderMap::iterator provider
= worker_to_provider_
.find(handle_id
);
652 if (provider
!= worker_to_provider_
.end())
653 provider
->second
->OnServiceWorkerStateChanged(handle_id
, state
);
656 void ServiceWorkerDispatcher::OnSetVersionAttributes(
659 int registration_handle_id
,
661 const ServiceWorkerVersionAttributes
& attrs
) {
662 TRACE_EVENT1("ServiceWorker",
663 "ServiceWorkerDispatcher::OnSetVersionAttributes",
664 "Thread ID", thread_id
);
666 ChangedVersionAttributesMask
mask(changed_mask
);
667 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
668 if (provider
!= provider_contexts_
.end() &&
669 provider
->second
->registration_handle_id() == registration_handle_id
) {
670 if (mask
.installing_changed()) {
671 worker_to_provider_
.erase(provider
->second
->installing_handle_id());
672 if (attrs
.installing
.handle_id
!= kInvalidServiceWorkerHandleId
)
673 worker_to_provider_
[attrs
.installing
.handle_id
] = provider
->second
;
675 if (mask
.waiting_changed()) {
676 worker_to_provider_
.erase(provider
->second
->waiting_handle_id());
677 if (attrs
.waiting
.handle_id
!= kInvalidServiceWorkerHandleId
)
678 worker_to_provider_
[attrs
.waiting
.handle_id
] = provider
->second
;
680 if (mask
.active_changed()) {
681 worker_to_provider_
.erase(provider
->second
->active_handle_id());
682 if (attrs
.active
.handle_id
!= kInvalidServiceWorkerHandleId
)
683 worker_to_provider_
[attrs
.active
.handle_id
] = provider
->second
;
685 provider
->second
->SetVersionAttributes(mask
, attrs
);
688 RegistrationObjectMap::iterator found
=
689 registrations_
.find(registration_handle_id
);
690 if (found
!= registrations_
.end()) {
691 // Populate the version fields (eg. .installing) with new worker objects.
692 if (mask
.installing_changed())
693 found
->second
->SetInstalling(GetServiceWorker(attrs
.installing
, false));
694 if (mask
.waiting_changed())
695 found
->second
->SetWaiting(GetServiceWorker(attrs
.waiting
, false));
696 if (mask
.active_changed())
697 found
->second
->SetActive(GetServiceWorker(attrs
.active
, false));
701 void ServiceWorkerDispatcher::OnUpdateFound(
703 int registration_handle_id
) {
704 TRACE_EVENT0("ServiceWorker",
705 "ServiceWorkerDispatcher::OnUpdateFound");
706 RegistrationObjectMap::iterator found
=
707 registrations_
.find(registration_handle_id
);
708 if (found
!= registrations_
.end())
709 found
->second
->OnUpdateFound();
712 void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
715 const ServiceWorkerObjectInfo
& info
,
716 bool should_notify_controllerchange
) {
717 TRACE_EVENT2("ServiceWorker",
718 "ServiceWorkerDispatcher::OnSetControllerServiceWorker",
719 "Thread ID", thread_id
,
720 "Provider ID", provider_id
);
722 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
723 if (provider
!= provider_contexts_
.end()) {
724 worker_to_provider_
.erase(provider
->second
->controller_handle_id());
725 if (info
.handle_id
!= kInvalidServiceWorkerHandleId
)
726 worker_to_provider_
[info
.handle_id
] = provider
->second
;
727 provider
->second
->OnSetControllerServiceWorker(info
);
730 ProviderClientMap::iterator found
= provider_clients_
.find(provider_id
);
731 if (found
!= provider_clients_
.end()) {
732 // Populate the .controller field with the new worker object.
733 found
->second
->setController(GetServiceWorker(info
, false),
734 should_notify_controllerchange
);
738 void ServiceWorkerDispatcher::OnPostMessage(
739 const ServiceWorkerMsg_MessageToDocument_Params
& params
) {
740 // Make sure we're on the main document thread. (That must be the only
741 // thread we get this message)
742 DCHECK(ChildThreadImpl::current());
743 TRACE_EVENT1("ServiceWorker", "ServiceWorkerDispatcher::OnPostMessage",
744 "Thread ID", params
.thread_id
);
746 ProviderClientMap::iterator found
=
747 provider_clients_
.find(params
.provider_id
);
748 if (found
== provider_clients_
.end()) {
749 // For now we do no queueing for messages sent to nonexistent / unattached
754 blink::WebMessagePortChannelArray ports
=
755 WebMessagePortChannelImpl::CreatePorts(
756 params
.message_ports
, params
.new_routing_ids
,
757 base::ThreadTaskRunnerHandle::Get());
759 found
->second
->dispatchMessageEvent(
760 GetServiceWorker(params
.service_worker_info
, false /* adopt_handle */),
761 params
.message
, ports
);
764 void ServiceWorkerDispatcher::AddServiceWorker(
765 int handle_id
, WebServiceWorkerImpl
* worker
) {
766 DCHECK(!ContainsKey(service_workers_
, handle_id
));
767 service_workers_
[handle_id
] = worker
;
770 void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id
) {
771 DCHECK(ContainsKey(service_workers_
, handle_id
));
772 service_workers_
.erase(handle_id
);
775 void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
776 int registration_handle_id
,
777 WebServiceWorkerRegistrationImpl
* registration
) {
778 DCHECK(!ContainsKey(registrations_
, registration_handle_id
));
779 registrations_
[registration_handle_id
] = registration
;
782 void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
783 int registration_handle_id
) {
784 DCHECK(ContainsKey(registrations_
, registration_handle_id
));
785 registrations_
.erase(registration_handle_id
);
788 WebServiceWorkerRegistrationImpl
*
789 ServiceWorkerDispatcher::FindOrCreateRegistration(
790 const ServiceWorkerRegistrationObjectInfo
& info
,
791 const ServiceWorkerVersionAttributes
& attrs
) {
792 RegistrationObjectMap::iterator found
= registrations_
.find(info
.handle_id
);
793 if (found
!= registrations_
.end()) {
794 ServiceWorkerRegistrationHandleReference::Adopt(info
,
795 thread_safe_sender_
.get());
796 ServiceWorkerHandleReference::Adopt(attrs
.installing
,
797 thread_safe_sender_
.get());
798 ServiceWorkerHandleReference::Adopt(attrs
.waiting
,
799 thread_safe_sender_
.get());
800 ServiceWorkerHandleReference::Adopt(attrs
.active
,
801 thread_safe_sender_
.get());
802 return found
->second
;
805 bool adopt_handle
= true;
806 WebServiceWorkerRegistrationImpl
* registration
=
807 CreateServiceWorkerRegistration(info
, adopt_handle
);
808 registration
->SetInstalling(GetServiceWorker(attrs
.installing
, adopt_handle
));
809 registration
->SetWaiting(GetServiceWorker(attrs
.waiting
, adopt_handle
));
810 registration
->SetActive(GetServiceWorker(attrs
.active
, adopt_handle
));
814 } // namespace content