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/threading/thread_local.h"
10 #include "base/trace_event/trace_event.h"
11 #include "content/child/child_thread_impl.h"
12 #include "content/child/service_worker/service_worker_handle_reference.h"
13 #include "content/child/service_worker/service_worker_provider_context.h"
14 #include "content/child/service_worker/service_worker_registration_handle_reference.h"
15 #include "content/child/service_worker/web_service_worker_impl.h"
16 #include "content/child/service_worker/web_service_worker_registration_impl.h"
17 #include "content/child/thread_safe_sender.h"
18 #include "content/child/webmessageportchannel_impl.h"
19 #include "content/common/service_worker/service_worker_messages.h"
20 #include "content/common/service_worker/service_worker_types.h"
21 #include "content/public/common/url_utils.h"
22 #include "third_party/WebKit/public/platform/WebServiceWorkerClientsInfo.h"
23 #include "third_party/WebKit/public/platform/WebServiceWorkerProviderClient.h"
24 #include "third_party/WebKit/public/platform/WebString.h"
25 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
27 using blink::WebServiceWorkerError
;
28 using blink::WebServiceWorkerProvider
;
29 using base::ThreadLocalPointer
;
35 base::LazyInstance
<ThreadLocalPointer
<ServiceWorkerDispatcher
> >::Leaky
36 g_dispatcher_tls
= LAZY_INSTANCE_INITIALIZER
;
38 ServiceWorkerDispatcher
* const kHasBeenDeleted
=
39 reinterpret_cast<ServiceWorkerDispatcher
*>(0x1);
41 int CurrentWorkerId() {
42 return WorkerTaskRunner::Instance()->CurrentWorkerId();
47 ServiceWorkerDispatcher::ServiceWorkerDispatcher(
48 ThreadSafeSender
* thread_safe_sender
)
49 : thread_safe_sender_(thread_safe_sender
) {
50 g_dispatcher_tls
.Pointer()->Set(this);
53 ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
54 g_dispatcher_tls
.Pointer()->Set(kHasBeenDeleted
);
57 void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
59 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher
, msg
)
60 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistrationWithServiceWorker
,
61 OnAssociateRegistrationWithServiceWorker
)
62 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistration
,
63 OnAssociateRegistration
)
64 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DisassociateRegistration
,
65 OnDisassociateRegistration
)
66 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered
, OnRegistered
)
67 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered
,
69 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistration
,
71 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistrationForReady
,
72 OnDidGetRegistrationForReady
)
73 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError
,
75 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistrationError
,
76 OnUnregistrationError
)
77 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationError
,
78 OnGetRegistrationError
)
79 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged
,
80 OnServiceWorkerStateChanged
)
81 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes
,
82 OnSetVersionAttributes
)
83 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_UpdateFound
,
85 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker
,
86 OnSetControllerServiceWorker
)
87 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument
,
89 IPC_MESSAGE_UNHANDLED(handled
= false)
91 DCHECK(handled
) << "Unhandled message:" << msg
.type();
94 bool ServiceWorkerDispatcher::Send(IPC::Message
* msg
) {
95 return thread_safe_sender_
->Send(msg
);
98 void ServiceWorkerDispatcher::RegisterServiceWorker(
101 const GURL
& script_url
,
102 WebServiceWorkerRegistrationCallbacks
* callbacks
) {
105 if (pattern
.possibly_invalid_spec().size() > GetMaxURLChars() ||
106 script_url
.possibly_invalid_spec().size() > GetMaxURLChars()) {
107 scoped_ptr
<WebServiceWorkerRegistrationCallbacks
>
108 owned_callbacks(callbacks
);
109 std::string
error_message(kServiceWorkerRegisterErrorPrefix
);
110 error_message
+= "The provided scriptURL or scope is too long.";
111 scoped_ptr
<WebServiceWorkerError
> error(
112 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity
,
113 blink::WebString::fromUTF8(error_message
)));
114 callbacks
->onError(error
.release());
118 int request_id
= pending_registration_callbacks_
.Add(callbacks
);
119 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
120 "ServiceWorkerDispatcher::RegisterServiceWorker",
122 "Scope", pattern
.spec(),
123 "Script URL", script_url
.spec());
124 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
125 CurrentWorkerId(), request_id
, provider_id
, pattern
, script_url
));
128 void ServiceWorkerDispatcher::UnregisterServiceWorker(
131 WebServiceWorkerUnregistrationCallbacks
* callbacks
) {
134 if (pattern
.possibly_invalid_spec().size() > GetMaxURLChars()) {
135 scoped_ptr
<WebServiceWorkerUnregistrationCallbacks
>
136 owned_callbacks(callbacks
);
137 std::string
error_message(kServiceWorkerUnregisterErrorPrefix
);
138 error_message
+= "The provided scope is too long.";
139 scoped_ptr
<WebServiceWorkerError
> error(
140 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity
,
141 blink::WebString::fromUTF8(error_message
)));
142 callbacks
->onError(error
.release());
146 int request_id
= pending_unregistration_callbacks_
.Add(callbacks
);
147 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
148 "ServiceWorkerDispatcher::UnregisterServiceWorker",
150 "Scope", pattern
.spec());
151 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
152 CurrentWorkerId(), request_id
, provider_id
, pattern
));
155 void ServiceWorkerDispatcher::GetRegistration(
157 const GURL
& document_url
,
158 WebServiceWorkerRegistrationCallbacks
* callbacks
) {
161 if (document_url
.possibly_invalid_spec().size() > GetMaxURLChars()) {
162 scoped_ptr
<WebServiceWorkerRegistrationCallbacks
>
163 owned_callbacks(callbacks
);
164 std::string
error_message(kServiceWorkerGetRegistrationErrorPrefix
);
165 error_message
+= "The provided documentURL is too long.";
166 scoped_ptr
<WebServiceWorkerError
> error(
167 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity
,
168 blink::WebString::fromUTF8(error_message
)));
169 callbacks
->onError(error
.release());
173 int request_id
= pending_get_registration_callbacks_
.Add(callbacks
);
174 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
175 "ServiceWorkerDispatcher::GetRegistration",
177 "Document URL", document_url
.spec());
178 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetRegistration(
179 CurrentWorkerId(), request_id
, provider_id
, document_url
));
182 void ServiceWorkerDispatcher::GetRegistrationForReady(
184 WebServiceWorkerGetRegistrationForReadyCallbacks
* callbacks
) {
185 int request_id
= get_for_ready_callbacks_
.Add(callbacks
);
186 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
187 "ServiceWorkerDispatcher::GetRegistrationForReady",
189 thread_safe_sender_
->Send(new ServiceWorkerHostMsg_GetRegistrationForReady(
190 CurrentWorkerId(), request_id
, provider_id
));
193 void ServiceWorkerDispatcher::AddProviderContext(
194 ServiceWorkerProviderContext
* provider_context
) {
195 DCHECK(provider_context
);
196 int provider_id
= provider_context
->provider_id();
197 DCHECK(!ContainsKey(provider_contexts_
, provider_id
));
198 provider_contexts_
[provider_id
] = provider_context
;
201 void ServiceWorkerDispatcher::RemoveProviderContext(
202 ServiceWorkerProviderContext
* provider_context
) {
203 DCHECK(provider_context
);
204 DCHECK(ContainsKey(provider_contexts_
, provider_context
->provider_id()));
205 provider_contexts_
.erase(provider_context
->provider_id());
206 worker_to_provider_
.erase(provider_context
->installing_handle_id());
207 worker_to_provider_
.erase(provider_context
->waiting_handle_id());
208 worker_to_provider_
.erase(provider_context
->active_handle_id());
209 worker_to_provider_
.erase(provider_context
->controller_handle_id());
212 void ServiceWorkerDispatcher::AddProviderClient(
214 blink::WebServiceWorkerProviderClient
* client
) {
216 DCHECK(!ContainsKey(provider_clients_
, provider_id
));
217 provider_clients_
[provider_id
] = client
;
220 void ServiceWorkerDispatcher::RemoveProviderClient(int provider_id
) {
221 // This could be possibly called multiple times to ensure termination.
222 if (ContainsKey(provider_clients_
, provider_id
))
223 provider_clients_
.erase(provider_id
);
226 ServiceWorkerDispatcher
*
227 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
228 ThreadSafeSender
* thread_safe_sender
) {
229 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
) {
230 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
231 g_dispatcher_tls
.Pointer()->Set(NULL
);
233 if (g_dispatcher_tls
.Pointer()->Get())
234 return g_dispatcher_tls
.Pointer()->Get();
236 ServiceWorkerDispatcher
* dispatcher
=
237 new ServiceWorkerDispatcher(thread_safe_sender
);
238 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
239 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher
);
243 ServiceWorkerDispatcher
* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
244 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
)
246 return g_dispatcher_tls
.Pointer()->Get();
249 void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
253 WebServiceWorkerImpl
* ServiceWorkerDispatcher::GetServiceWorker(
254 const ServiceWorkerObjectInfo
& info
,
256 if (info
.handle_id
== kInvalidServiceWorkerHandleId
)
259 WorkerObjectMap::iterator existing_worker
=
260 service_workers_
.find(info
.handle_id
);
262 if (existing_worker
!= service_workers_
.end()) {
264 // We are instructed to adopt a handle but we already have one, so
265 // adopt and destroy a handle ref.
266 ServiceWorkerHandleReference::Adopt(info
, thread_safe_sender_
.get());
268 return existing_worker
->second
;
271 scoped_ptr
<ServiceWorkerHandleReference
> handle_ref
=
273 ? ServiceWorkerHandleReference::Adopt(info
, thread_safe_sender_
.get())
274 : ServiceWorkerHandleReference::Create(info
,
275 thread_safe_sender_
.get());
276 // WebServiceWorkerImpl constructor calls AddServiceWorker.
277 return new WebServiceWorkerImpl(handle_ref
.Pass(), thread_safe_sender_
.get());
280 WebServiceWorkerRegistrationImpl
*
281 ServiceWorkerDispatcher::CreateServiceWorkerRegistration(
282 const ServiceWorkerRegistrationObjectInfo
& info
,
284 DCHECK(!ContainsKey(registrations_
, info
.handle_id
));
285 if (info
.handle_id
== kInvalidServiceWorkerRegistrationHandleId
)
288 scoped_ptr
<ServiceWorkerRegistrationHandleReference
> handle_ref
=
289 adopt_handle
? ServiceWorkerRegistrationHandleReference::Adopt(
290 info
, thread_safe_sender_
.get())
291 : ServiceWorkerRegistrationHandleReference::Create(
292 info
, thread_safe_sender_
.get());
294 // WebServiceWorkerRegistrationImpl constructor calls
295 // AddServiceWorkerRegistration.
296 return new WebServiceWorkerRegistrationImpl(handle_ref
.Pass());
299 // We can assume that this message handler is called before the worker context
300 // starts because script loading happens after this association.
301 // TODO(nhiroki): This association information could be pushed into
302 // EmbeddedWorkerMsg_StartWorker message and handed over to the worker thread
303 // without a lock in ServiceWorkerProviderContext.
304 void ServiceWorkerDispatcher::OnAssociateRegistrationWithServiceWorker(
307 const ServiceWorkerRegistrationObjectInfo
& info
,
308 const ServiceWorkerVersionAttributes
& attrs
) {
309 DCHECK_EQ(kDocumentMainThreadId
, thread_id
);
311 ProviderContextMap::iterator context
= provider_contexts_
.find(provider_id
);
312 if (context
== provider_contexts_
.end())
314 context
->second
->OnAssociateRegistration(info
, attrs
);
316 // We don't have to add entries into |worker_to_provider_| because state
317 // change events for the workers will be notified on the worker thread.
320 void ServiceWorkerDispatcher::OnAssociateRegistration(
323 const ServiceWorkerRegistrationObjectInfo
& info
,
324 const ServiceWorkerVersionAttributes
& attrs
) {
325 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
326 if (provider
== provider_contexts_
.end())
328 provider
->second
->OnAssociateRegistration(info
, attrs
);
329 if (attrs
.installing
.handle_id
!= kInvalidServiceWorkerHandleId
)
330 worker_to_provider_
[attrs
.installing
.handle_id
] = provider
->second
;
331 if (attrs
.waiting
.handle_id
!= kInvalidServiceWorkerHandleId
)
332 worker_to_provider_
[attrs
.waiting
.handle_id
] = provider
->second
;
333 if (attrs
.active
.handle_id
!= kInvalidServiceWorkerHandleId
)
334 worker_to_provider_
[attrs
.active
.handle_id
] = provider
->second
;
337 void ServiceWorkerDispatcher::OnDisassociateRegistration(
340 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
341 if (provider
== provider_contexts_
.end())
343 worker_to_provider_
.erase(provider
->second
->installing_handle_id());
344 worker_to_provider_
.erase(provider
->second
->waiting_handle_id());
345 worker_to_provider_
.erase(provider
->second
->active_handle_id());
346 worker_to_provider_
.erase(provider
->second
->controller_handle_id());
347 provider
->second
->OnDisassociateRegistration();
350 void ServiceWorkerDispatcher::OnRegistered(
353 const ServiceWorkerRegistrationObjectInfo
& info
,
354 const ServiceWorkerVersionAttributes
& attrs
) {
355 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
356 "ServiceWorkerDispatcher::RegisterServiceWorker",
359 TRACE_EVENT_ASYNC_END0("ServiceWorker",
360 "ServiceWorkerDispatcher::RegisterServiceWorker",
362 WebServiceWorkerRegistrationCallbacks
* callbacks
=
363 pending_registration_callbacks_
.Lookup(request_id
);
368 callbacks
->onSuccess(FindOrCreateRegistration(info
, attrs
));
369 pending_registration_callbacks_
.Remove(request_id
);
372 void ServiceWorkerDispatcher::OnUnregistered(int thread_id
,
375 TRACE_EVENT_ASYNC_STEP_INTO0(
377 "ServiceWorkerDispatcher::UnregisterServiceWorker",
380 TRACE_EVENT_ASYNC_END0("ServiceWorker",
381 "ServiceWorkerDispatcher::UnregisterServiceWorker",
383 WebServiceWorkerUnregistrationCallbacks
* callbacks
=
384 pending_unregistration_callbacks_
.Lookup(request_id
);
388 callbacks
->onSuccess(&is_success
);
389 pending_unregistration_callbacks_
.Remove(request_id
);
392 void ServiceWorkerDispatcher::OnDidGetRegistration(
395 const ServiceWorkerRegistrationObjectInfo
& info
,
396 const ServiceWorkerVersionAttributes
& attrs
) {
397 TRACE_EVENT_ASYNC_STEP_INTO0(
399 "ServiceWorkerDispatcher::GetRegistration",
401 "OnDidGetRegistration");
402 TRACE_EVENT_ASYNC_END0("ServiceWorker",
403 "ServiceWorkerDispatcher::GetRegistration",
405 WebServiceWorkerRegistrationCallbacks
* callbacks
=
406 pending_get_registration_callbacks_
.Lookup(request_id
);
411 WebServiceWorkerRegistrationImpl
* registration
= NULL
;
412 if (info
.handle_id
!= kInvalidServiceWorkerHandleId
)
413 registration
= FindOrCreateRegistration(info
, attrs
);
415 callbacks
->onSuccess(registration
);
416 pending_get_registration_callbacks_
.Remove(request_id
);
419 void ServiceWorkerDispatcher::OnDidGetRegistrationForReady(
422 const ServiceWorkerRegistrationObjectInfo
& info
,
423 const ServiceWorkerVersionAttributes
& attrs
) {
424 TRACE_EVENT_ASYNC_STEP_INTO0(
426 "ServiceWorkerDispatcher::GetRegistrationForReady",
428 "OnDidGetRegistrationForReady");
429 TRACE_EVENT_ASYNC_END0("ServiceWorker",
430 "ServiceWorkerDispatcher::GetRegistrationForReady",
432 WebServiceWorkerGetRegistrationForReadyCallbacks
* callbacks
=
433 get_for_ready_callbacks_
.Lookup(request_id
);
438 WebServiceWorkerRegistrationImpl
* registration
= NULL
;
439 DCHECK(info
.handle_id
!= kInvalidServiceWorkerHandleId
);
440 registration
= FindOrCreateRegistration(info
, attrs
);
441 callbacks
->onSuccess(registration
);
442 get_for_ready_callbacks_
.Remove(request_id
);
445 void ServiceWorkerDispatcher::OnRegistrationError(
448 WebServiceWorkerError::ErrorType error_type
,
449 const base::string16
& message
) {
450 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
451 "ServiceWorkerDispatcher::RegisterServiceWorker",
453 "OnRegistrationError");
454 TRACE_EVENT_ASYNC_END0("ServiceWorker",
455 "ServiceWorkerDispatcher::RegisterServiceWorker",
457 WebServiceWorkerRegistrationCallbacks
* callbacks
=
458 pending_registration_callbacks_
.Lookup(request_id
);
463 scoped_ptr
<WebServiceWorkerError
> error(
464 new WebServiceWorkerError(error_type
, message
));
465 callbacks
->onError(error
.release());
466 pending_registration_callbacks_
.Remove(request_id
);
469 void ServiceWorkerDispatcher::OnUnregistrationError(
472 WebServiceWorkerError::ErrorType error_type
,
473 const base::string16
& message
) {
474 TRACE_EVENT_ASYNC_STEP_INTO0(
476 "ServiceWorkerDispatcher::UnregisterServiceWorker",
478 "OnUnregistrationError");
479 TRACE_EVENT_ASYNC_END0("ServiceWorker",
480 "ServiceWorkerDispatcher::UnregisterServiceWorker",
482 WebServiceWorkerUnregistrationCallbacks
* callbacks
=
483 pending_unregistration_callbacks_
.Lookup(request_id
);
488 scoped_ptr
<WebServiceWorkerError
> error(
489 new WebServiceWorkerError(error_type
, message
));
490 callbacks
->onError(error
.release());
491 pending_unregistration_callbacks_
.Remove(request_id
);
494 void ServiceWorkerDispatcher::OnGetRegistrationError(
497 WebServiceWorkerError::ErrorType error_type
,
498 const base::string16
& message
) {
499 TRACE_EVENT_ASYNC_STEP_INTO0(
501 "ServiceWorkerDispatcher::GetRegistration",
503 "OnGetRegistrationError");
504 TRACE_EVENT_ASYNC_END0("ServiceWorker",
505 "ServiceWorkerDispatcher::GetRegistration",
507 WebServiceWorkerGetRegistrationCallbacks
* callbacks
=
508 pending_get_registration_callbacks_
.Lookup(request_id
);
513 scoped_ptr
<WebServiceWorkerError
> error(
514 new WebServiceWorkerError(error_type
, message
));
515 callbacks
->onError(error
.release());
516 pending_get_registration_callbacks_
.Remove(request_id
);
519 void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
522 blink::WebServiceWorkerState state
) {
523 TRACE_EVENT2("ServiceWorker",
524 "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
525 "Thread ID", thread_id
,
527 WorkerObjectMap::iterator worker
= service_workers_
.find(handle_id
);
528 if (worker
!= service_workers_
.end())
529 worker
->second
->OnStateChanged(state
);
531 WorkerToProviderMap::iterator provider
= worker_to_provider_
.find(handle_id
);
532 if (provider
!= worker_to_provider_
.end())
533 provider
->second
->OnServiceWorkerStateChanged(handle_id
, state
);
536 void ServiceWorkerDispatcher::OnSetVersionAttributes(
539 int registration_handle_id
,
541 const ServiceWorkerVersionAttributes
& attrs
) {
542 TRACE_EVENT1("ServiceWorker",
543 "ServiceWorkerDispatcher::OnSetVersionAttributes",
544 "Thread ID", thread_id
);
546 ChangedVersionAttributesMask
mask(changed_mask
);
547 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
548 if (provider
!= provider_contexts_
.end() &&
549 provider
->second
->registration_handle_id() == registration_handle_id
) {
550 if (mask
.installing_changed()) {
551 worker_to_provider_
.erase(provider
->second
->installing_handle_id());
552 if (attrs
.installing
.handle_id
!= kInvalidServiceWorkerHandleId
)
553 worker_to_provider_
[attrs
.installing
.handle_id
] = provider
->second
;
555 if (mask
.waiting_changed()) {
556 worker_to_provider_
.erase(provider
->second
->waiting_handle_id());
557 if (attrs
.waiting
.handle_id
!= kInvalidServiceWorkerHandleId
)
558 worker_to_provider_
[attrs
.waiting
.handle_id
] = provider
->second
;
560 if (mask
.active_changed()) {
561 worker_to_provider_
.erase(provider
->second
->active_handle_id());
562 if (attrs
.active
.handle_id
!= kInvalidServiceWorkerHandleId
)
563 worker_to_provider_
[attrs
.active
.handle_id
] = provider
->second
;
565 provider
->second
->SetVersionAttributes(mask
, attrs
);
568 RegistrationObjectMap::iterator found
=
569 registrations_
.find(registration_handle_id
);
570 if (found
!= registrations_
.end()) {
571 // Populate the version fields (eg. .installing) with new worker objects.
572 if (mask
.installing_changed())
573 found
->second
->SetInstalling(GetServiceWorker(attrs
.installing
, false));
574 if (mask
.waiting_changed())
575 found
->second
->SetWaiting(GetServiceWorker(attrs
.waiting
, false));
576 if (mask
.active_changed())
577 found
->second
->SetActive(GetServiceWorker(attrs
.active
, false));
581 void ServiceWorkerDispatcher::OnUpdateFound(
583 int registration_handle_id
) {
584 TRACE_EVENT0("ServiceWorker",
585 "ServiceWorkerDispatcher::OnUpdateFound");
586 RegistrationObjectMap::iterator found
=
587 registrations_
.find(registration_handle_id
);
588 if (found
!= registrations_
.end())
589 found
->second
->OnUpdateFound();
592 void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
595 const ServiceWorkerObjectInfo
& info
,
596 bool should_notify_controllerchange
) {
597 TRACE_EVENT2("ServiceWorker",
598 "ServiceWorkerDispatcher::OnSetControllerServiceWorker",
599 "Thread ID", thread_id
,
600 "Provider ID", provider_id
);
602 ProviderContextMap::iterator provider
= provider_contexts_
.find(provider_id
);
603 if (provider
!= provider_contexts_
.end()) {
604 worker_to_provider_
.erase(provider
->second
->controller_handle_id());
605 if (info
.handle_id
!= kInvalidServiceWorkerHandleId
)
606 worker_to_provider_
[info
.handle_id
] = provider
->second
;
607 provider
->second
->OnSetControllerServiceWorker(info
);
610 ProviderClientMap::iterator found
= provider_clients_
.find(provider_id
);
611 if (found
!= provider_clients_
.end()) {
612 // Populate the .controller field with the new worker object.
613 found
->second
->setController(GetServiceWorker(info
, false),
614 should_notify_controllerchange
);
618 void ServiceWorkerDispatcher::OnPostMessage(
621 const base::string16
& message
,
622 const std::vector
<TransferredMessagePort
>& sent_message_ports
,
623 const std::vector
<int>& new_routing_ids
) {
624 // Make sure we're on the main document thread. (That must be the only
625 // thread we get this message)
626 DCHECK(ChildThreadImpl::current());
627 TRACE_EVENT1("ServiceWorker",
628 "ServiceWorkerDispatcher::OnPostMessage",
629 "Thread ID", thread_id
);
631 ProviderClientMap::iterator found
= provider_clients_
.find(provider_id
);
632 if (found
== provider_clients_
.end()) {
633 // For now we do no queueing for messages sent to nonexistent / unattached
638 blink::WebMessagePortChannelArray ports
=
639 WebMessagePortChannelImpl::CreatePorts(sent_message_ports
,
641 base::MessageLoopProxy::current());
643 found
->second
->dispatchMessageEvent(message
, ports
);
646 void ServiceWorkerDispatcher::AddServiceWorker(
647 int handle_id
, WebServiceWorkerImpl
* worker
) {
648 DCHECK(!ContainsKey(service_workers_
, handle_id
));
649 service_workers_
[handle_id
] = worker
;
652 void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id
) {
653 DCHECK(ContainsKey(service_workers_
, handle_id
));
654 service_workers_
.erase(handle_id
);
657 void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
658 int registration_handle_id
,
659 WebServiceWorkerRegistrationImpl
* registration
) {
660 DCHECK(!ContainsKey(registrations_
, registration_handle_id
));
661 registrations_
[registration_handle_id
] = registration
;
664 void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
665 int registration_handle_id
) {
666 DCHECK(ContainsKey(registrations_
, registration_handle_id
));
667 registrations_
.erase(registration_handle_id
);
670 WebServiceWorkerRegistrationImpl
*
671 ServiceWorkerDispatcher::FindOrCreateRegistration(
672 const ServiceWorkerRegistrationObjectInfo
& info
,
673 const ServiceWorkerVersionAttributes
& attrs
) {
674 RegistrationObjectMap::iterator found
= registrations_
.find(info
.handle_id
);
675 if (found
!= registrations_
.end()) {
676 ServiceWorkerRegistrationHandleReference::Adopt(info
,
677 thread_safe_sender_
.get());
678 ServiceWorkerHandleReference::Adopt(attrs
.installing
,
679 thread_safe_sender_
.get());
680 ServiceWorkerHandleReference::Adopt(attrs
.waiting
,
681 thread_safe_sender_
.get());
682 ServiceWorkerHandleReference::Adopt(attrs
.active
,
683 thread_safe_sender_
.get());
684 return found
->second
;
687 bool adopt_handle
= true;
688 WebServiceWorkerRegistrationImpl
* registration
=
689 CreateServiceWorkerRegistration(info
, adopt_handle
);
690 registration
->SetInstalling(GetServiceWorker(attrs
.installing
, adopt_handle
));
691 registration
->SetWaiting(GetServiceWorker(attrs
.waiting
, adopt_handle
));
692 registration
->SetActive(GetServiceWorker(attrs
.active
, adopt_handle
));
696 } // namespace content