Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / content / child / service_worker / service_worker_dispatcher.cc
blobdfbcfc18f6c06fb4e2e20fd6796f1fa9e81b3b64
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;
31 namespace content {
33 namespace {
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();
45 } // namespace
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) {
58 bool handled = true;
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,
68 OnUnregistered)
69 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistration,
70 OnDidGetRegistration)
71 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistrationForReady,
72 OnDidGetRegistrationForReady)
73 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError,
74 OnRegistrationError)
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,
84 OnUpdateFound)
85 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker,
86 OnSetControllerServiceWorker)
87 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument,
88 OnPostMessage)
89 IPC_MESSAGE_UNHANDLED(handled = false)
90 IPC_END_MESSAGE_MAP()
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(
99 int provider_id,
100 const GURL& pattern,
101 const GURL& script_url,
102 WebServiceWorkerRegistrationCallbacks* callbacks) {
103 DCHECK(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());
115 return;
118 int request_id = pending_registration_callbacks_.Add(callbacks);
119 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
120 "ServiceWorkerDispatcher::RegisterServiceWorker",
121 request_id,
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(
129 int provider_id,
130 const GURL& pattern,
131 WebServiceWorkerUnregistrationCallbacks* callbacks) {
132 DCHECK(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());
143 return;
146 int request_id = pending_unregistration_callbacks_.Add(callbacks);
147 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
148 "ServiceWorkerDispatcher::UnregisterServiceWorker",
149 request_id,
150 "Scope", pattern.spec());
151 thread_safe_sender_->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
152 CurrentWorkerId(), request_id, provider_id, pattern));
155 void ServiceWorkerDispatcher::GetRegistration(
156 int provider_id,
157 const GURL& document_url,
158 WebServiceWorkerRegistrationCallbacks* callbacks) {
159 DCHECK(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());
170 return;
173 int request_id = pending_get_registration_callbacks_.Add(callbacks);
174 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
175 "ServiceWorkerDispatcher::GetRegistration",
176 request_id,
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(
183 int provider_id,
184 WebServiceWorkerGetRegistrationForReadyCallbacks* callbacks) {
185 int request_id = get_for_ready_callbacks_.Add(callbacks);
186 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
187 "ServiceWorkerDispatcher::GetRegistrationForReady",
188 request_id);
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(
213 int provider_id,
214 blink::WebServiceWorkerProviderClient* client) {
215 DCHECK(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);
240 return dispatcher;
243 ServiceWorkerDispatcher* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
244 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted)
245 return NULL;
246 return g_dispatcher_tls.Pointer()->Get();
249 void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
250 delete this;
253 WebServiceWorkerImpl* ServiceWorkerDispatcher::GetServiceWorker(
254 const ServiceWorkerObjectInfo& info,
255 bool adopt_handle) {
256 if (info.handle_id == kInvalidServiceWorkerHandleId)
257 return NULL;
259 WorkerObjectMap::iterator existing_worker =
260 service_workers_.find(info.handle_id);
262 if (existing_worker != service_workers_.end()) {
263 if (adopt_handle) {
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 =
272 adopt_handle
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,
283 bool adopt_handle) {
284 DCHECK(!ContainsKey(registrations_, info.handle_id));
285 if (info.handle_id == kInvalidServiceWorkerRegistrationHandleId)
286 return NULL;
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(
305 int thread_id,
306 int provider_id,
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())
313 return;
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(
321 int thread_id,
322 int provider_id,
323 const ServiceWorkerRegistrationObjectInfo& info,
324 const ServiceWorkerVersionAttributes& attrs) {
325 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
326 if (provider == provider_contexts_.end())
327 return;
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(
338 int thread_id,
339 int provider_id) {
340 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
341 if (provider == provider_contexts_.end())
342 return;
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(
351 int thread_id,
352 int request_id,
353 const ServiceWorkerRegistrationObjectInfo& info,
354 const ServiceWorkerVersionAttributes& attrs) {
355 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
356 "ServiceWorkerDispatcher::RegisterServiceWorker",
357 request_id,
358 "OnRegistered");
359 TRACE_EVENT_ASYNC_END0("ServiceWorker",
360 "ServiceWorkerDispatcher::RegisterServiceWorker",
361 request_id);
362 WebServiceWorkerRegistrationCallbacks* callbacks =
363 pending_registration_callbacks_.Lookup(request_id);
364 DCHECK(callbacks);
365 if (!callbacks)
366 return;
368 callbacks->onSuccess(FindOrCreateRegistration(info, attrs));
369 pending_registration_callbacks_.Remove(request_id);
372 void ServiceWorkerDispatcher::OnUnregistered(int thread_id,
373 int request_id,
374 bool is_success) {
375 TRACE_EVENT_ASYNC_STEP_INTO0(
376 "ServiceWorker",
377 "ServiceWorkerDispatcher::UnregisterServiceWorker",
378 request_id,
379 "OnUnregistered");
380 TRACE_EVENT_ASYNC_END0("ServiceWorker",
381 "ServiceWorkerDispatcher::UnregisterServiceWorker",
382 request_id);
383 WebServiceWorkerUnregistrationCallbacks* callbacks =
384 pending_unregistration_callbacks_.Lookup(request_id);
385 DCHECK(callbacks);
386 if (!callbacks)
387 return;
388 callbacks->onSuccess(&is_success);
389 pending_unregistration_callbacks_.Remove(request_id);
392 void ServiceWorkerDispatcher::OnDidGetRegistration(
393 int thread_id,
394 int request_id,
395 const ServiceWorkerRegistrationObjectInfo& info,
396 const ServiceWorkerVersionAttributes& attrs) {
397 TRACE_EVENT_ASYNC_STEP_INTO0(
398 "ServiceWorker",
399 "ServiceWorkerDispatcher::GetRegistration",
400 request_id,
401 "OnDidGetRegistration");
402 TRACE_EVENT_ASYNC_END0("ServiceWorker",
403 "ServiceWorkerDispatcher::GetRegistration",
404 request_id);
405 WebServiceWorkerRegistrationCallbacks* callbacks =
406 pending_get_registration_callbacks_.Lookup(request_id);
407 DCHECK(callbacks);
408 if (!callbacks)
409 return;
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(
420 int thread_id,
421 int request_id,
422 const ServiceWorkerRegistrationObjectInfo& info,
423 const ServiceWorkerVersionAttributes& attrs) {
424 TRACE_EVENT_ASYNC_STEP_INTO0(
425 "ServiceWorker",
426 "ServiceWorkerDispatcher::GetRegistrationForReady",
427 request_id,
428 "OnDidGetRegistrationForReady");
429 TRACE_EVENT_ASYNC_END0("ServiceWorker",
430 "ServiceWorkerDispatcher::GetRegistrationForReady",
431 request_id);
432 WebServiceWorkerGetRegistrationForReadyCallbacks* callbacks =
433 get_for_ready_callbacks_.Lookup(request_id);
434 DCHECK(callbacks);
435 if (!callbacks)
436 return;
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(
446 int thread_id,
447 int request_id,
448 WebServiceWorkerError::ErrorType error_type,
449 const base::string16& message) {
450 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
451 "ServiceWorkerDispatcher::RegisterServiceWorker",
452 request_id,
453 "OnRegistrationError");
454 TRACE_EVENT_ASYNC_END0("ServiceWorker",
455 "ServiceWorkerDispatcher::RegisterServiceWorker",
456 request_id);
457 WebServiceWorkerRegistrationCallbacks* callbacks =
458 pending_registration_callbacks_.Lookup(request_id);
459 DCHECK(callbacks);
460 if (!callbacks)
461 return;
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(
470 int thread_id,
471 int request_id,
472 WebServiceWorkerError::ErrorType error_type,
473 const base::string16& message) {
474 TRACE_EVENT_ASYNC_STEP_INTO0(
475 "ServiceWorker",
476 "ServiceWorkerDispatcher::UnregisterServiceWorker",
477 request_id,
478 "OnUnregistrationError");
479 TRACE_EVENT_ASYNC_END0("ServiceWorker",
480 "ServiceWorkerDispatcher::UnregisterServiceWorker",
481 request_id);
482 WebServiceWorkerUnregistrationCallbacks* callbacks =
483 pending_unregistration_callbacks_.Lookup(request_id);
484 DCHECK(callbacks);
485 if (!callbacks)
486 return;
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(
495 int thread_id,
496 int request_id,
497 WebServiceWorkerError::ErrorType error_type,
498 const base::string16& message) {
499 TRACE_EVENT_ASYNC_STEP_INTO0(
500 "ServiceWorker",
501 "ServiceWorkerDispatcher::GetRegistration",
502 request_id,
503 "OnGetRegistrationError");
504 TRACE_EVENT_ASYNC_END0("ServiceWorker",
505 "ServiceWorkerDispatcher::GetRegistration",
506 request_id);
507 WebServiceWorkerGetRegistrationCallbacks* callbacks =
508 pending_get_registration_callbacks_.Lookup(request_id);
509 DCHECK(callbacks);
510 if (!callbacks)
511 return;
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(
520 int thread_id,
521 int handle_id,
522 blink::WebServiceWorkerState state) {
523 TRACE_EVENT2("ServiceWorker",
524 "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
525 "Thread ID", thread_id,
526 "State", state);
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(
537 int thread_id,
538 int provider_id,
539 int registration_handle_id,
540 int changed_mask,
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(
582 int thread_id,
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(
593 int thread_id,
594 int provider_id,
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(
619 int thread_id,
620 int provider_id,
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
634 // client.
635 return;
638 blink::WebMessagePortChannelArray ports =
639 WebMessagePortChannelImpl::CreatePorts(sent_message_ports,
640 new_routing_ids,
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));
693 return registration;
696 } // namespace content