Miscellaneous fixes for virtual/override/final specifiers to match style guide.
[chromium-blink-merge.git] / content / child / service_worker / service_worker_dispatcher.cc
blob91ddd57dfda472292b362647156db1d1fe06e561
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/debug/trace_event.h"
8 #include "base/lazy_instance.h"
9 #include "base/stl_util.h"
10 #include "base/threading/thread_local.h"
11 #include "content/child/child_thread.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/public/common/url_utils.h"
21 #include "third_party/WebKit/public/platform/WebServiceWorkerClientsInfo.h"
22 #include "third_party/WebKit/public/platform/WebServiceWorkerProviderClient.h"
23 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
25 using blink::WebServiceWorkerError;
26 using blink::WebServiceWorkerProvider;
27 using base::ThreadLocalPointer;
29 namespace content {
31 namespace {
33 base::LazyInstance<ThreadLocalPointer<ServiceWorkerDispatcher> >::Leaky
34 g_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
36 ServiceWorkerDispatcher* const kHasBeenDeleted =
37 reinterpret_cast<ServiceWorkerDispatcher*>(0x1);
39 int CurrentWorkerId() {
40 return WorkerTaskRunner::Instance()->CurrentWorkerId();
43 } // namespace
45 ServiceWorkerDispatcher::ServiceWorkerDispatcher(
46 ThreadSafeSender* thread_safe_sender)
47 : thread_safe_sender_(thread_safe_sender) {
48 g_dispatcher_tls.Pointer()->Set(this);
51 ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
52 g_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
55 void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message& msg) {
56 bool handled = true;
57 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher, msg)
58 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistration,
59 OnAssociateRegistration)
60 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DisassociateRegistration,
61 OnDisassociateRegistration)
62 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered, OnRegistered)
63 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered,
64 OnUnregistered)
65 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistration,
66 OnDidGetRegistration)
67 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError,
68 OnRegistrationError)
69 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistrationError,
70 OnUnregistrationError)
71 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationError,
72 OnGetRegistrationError)
73 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged,
74 OnServiceWorkerStateChanged)
75 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes,
76 OnSetVersionAttributes)
77 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_UpdateFound,
78 OnUpdateFound)
79 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker,
80 OnSetControllerServiceWorker)
81 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument,
82 OnPostMessage)
83 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_GetClientInfo,
84 OnGetClientInfo)
85 IPC_MESSAGE_UNHANDLED(handled = false)
86 IPC_END_MESSAGE_MAP()
87 DCHECK(handled) << "Unhandled message:" << msg.type();
90 bool ServiceWorkerDispatcher::Send(IPC::Message* msg) {
91 return thread_safe_sender_->Send(msg);
94 void ServiceWorkerDispatcher::RegisterServiceWorker(
95 int provider_id,
96 const GURL& pattern,
97 const GURL& script_url,
98 WebServiceWorkerRegistrationCallbacks* callbacks) {
99 DCHECK(callbacks);
101 if (pattern.possibly_invalid_spec().size() > GetMaxURLChars() ||
102 script_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
103 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
104 owned_callbacks(callbacks);
105 scoped_ptr<WebServiceWorkerError> error(new WebServiceWorkerError(
106 WebServiceWorkerError::ErrorTypeSecurity, "URL too long"));
107 callbacks->onError(error.release());
108 return;
111 int request_id = pending_registration_callbacks_.Add(callbacks);
112 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
113 "ServiceWorkerDispatcher::RegisterServiceWorker",
114 request_id,
115 "Scope", pattern.spec(),
116 "Script URL", script_url.spec());
117 thread_safe_sender_->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
118 CurrentWorkerId(), request_id, provider_id, pattern, script_url));
121 void ServiceWorkerDispatcher::UnregisterServiceWorker(
122 int provider_id,
123 const GURL& pattern,
124 WebServiceWorkerUnregistrationCallbacks* callbacks) {
125 DCHECK(callbacks);
127 if (pattern.possibly_invalid_spec().size() > GetMaxURLChars()) {
128 scoped_ptr<WebServiceWorkerUnregistrationCallbacks>
129 owned_callbacks(callbacks);
130 scoped_ptr<WebServiceWorkerError> error(new WebServiceWorkerError(
131 WebServiceWorkerError::ErrorTypeSecurity, "URL too long"));
132 callbacks->onError(error.release());
133 return;
136 int request_id = pending_unregistration_callbacks_.Add(callbacks);
137 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
138 "ServiceWorkerDispatcher::UnregisterServiceWorker",
139 request_id,
140 "Scope", pattern.spec());
141 thread_safe_sender_->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
142 CurrentWorkerId(), request_id, provider_id, pattern));
145 void ServiceWorkerDispatcher::GetRegistration(
146 int provider_id,
147 const GURL& document_url,
148 WebServiceWorkerRegistrationCallbacks* callbacks) {
149 DCHECK(callbacks);
151 if (document_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
152 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
153 owned_callbacks(callbacks);
154 scoped_ptr<WebServiceWorkerError> error(new WebServiceWorkerError(
155 WebServiceWorkerError::ErrorTypeSecurity, "URL too long"));
156 callbacks->onError(error.release());
157 return;
160 int request_id = pending_get_registration_callbacks_.Add(callbacks);
161 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
162 "ServiceWorkerDispatcher::GetRegistration",
163 request_id,
164 "Document URL", document_url.spec());
165 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistration(
166 CurrentWorkerId(), request_id, provider_id, document_url));
169 void ServiceWorkerDispatcher::AddProviderContext(
170 ServiceWorkerProviderContext* provider_context) {
171 DCHECK(provider_context);
172 int provider_id = provider_context->provider_id();
173 DCHECK(!ContainsKey(provider_contexts_, provider_id));
174 provider_contexts_[provider_id] = provider_context;
177 void ServiceWorkerDispatcher::RemoveProviderContext(
178 ServiceWorkerProviderContext* provider_context) {
179 DCHECK(provider_context);
180 DCHECK(ContainsKey(provider_contexts_, provider_context->provider_id()));
181 provider_contexts_.erase(provider_context->provider_id());
182 worker_to_provider_.erase(provider_context->installing_handle_id());
183 worker_to_provider_.erase(provider_context->waiting_handle_id());
184 worker_to_provider_.erase(provider_context->active_handle_id());
185 worker_to_provider_.erase(provider_context->controller_handle_id());
188 void ServiceWorkerDispatcher::AddScriptClient(
189 int provider_id,
190 blink::WebServiceWorkerProviderClient* client) {
191 DCHECK(client);
192 DCHECK(!ContainsKey(script_clients_, provider_id));
193 script_clients_[provider_id] = client;
196 void ServiceWorkerDispatcher::RemoveScriptClient(int provider_id) {
197 // This could be possibly called multiple times to ensure termination.
198 if (ContainsKey(script_clients_, provider_id))
199 script_clients_.erase(provider_id);
202 ServiceWorkerDispatcher*
203 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
204 ThreadSafeSender* thread_safe_sender) {
205 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
206 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
207 g_dispatcher_tls.Pointer()->Set(NULL);
209 if (g_dispatcher_tls.Pointer()->Get())
210 return g_dispatcher_tls.Pointer()->Get();
212 ServiceWorkerDispatcher* dispatcher =
213 new ServiceWorkerDispatcher(thread_safe_sender);
214 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
215 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
216 return dispatcher;
219 ServiceWorkerDispatcher* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
220 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted)
221 return NULL;
222 return g_dispatcher_tls.Pointer()->Get();
225 void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
226 delete this;
229 WebServiceWorkerImpl* ServiceWorkerDispatcher::GetServiceWorker(
230 const ServiceWorkerObjectInfo& info,
231 bool adopt_handle) {
232 if (info.handle_id == kInvalidServiceWorkerHandleId)
233 return NULL;
235 WorkerObjectMap::iterator existing_worker =
236 service_workers_.find(info.handle_id);
238 if (existing_worker != service_workers_.end()) {
239 if (adopt_handle) {
240 // We are instructed to adopt a handle but we already have one, so
241 // adopt and destroy a handle ref.
242 ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
244 return existing_worker->second;
247 scoped_ptr<ServiceWorkerHandleReference> handle_ref =
248 adopt_handle
249 ? ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get())
250 : ServiceWorkerHandleReference::Create(info,
251 thread_safe_sender_.get());
252 // WebServiceWorkerImpl constructor calls AddServiceWorker.
253 return new WebServiceWorkerImpl(handle_ref.Pass(), thread_safe_sender_.get());
256 WebServiceWorkerRegistrationImpl*
257 ServiceWorkerDispatcher::FindServiceWorkerRegistration(
258 const ServiceWorkerRegistrationObjectInfo& info,
259 bool adopt_handle) {
260 RegistrationObjectMap::iterator registration =
261 registrations_.find(info.handle_id);
262 if (registration == registrations_.end())
263 return NULL;
264 if (adopt_handle) {
265 // We are instructed to adopt a handle but we already have one, so
266 // adopt and destroy a handle ref.
267 ServiceWorkerRegistrationHandleReference::Adopt(
268 info, thread_safe_sender_.get());
270 return registration->second;
273 WebServiceWorkerRegistrationImpl*
274 ServiceWorkerDispatcher::CreateServiceWorkerRegistration(
275 const ServiceWorkerRegistrationObjectInfo& info,
276 bool adopt_handle) {
277 DCHECK(!FindServiceWorkerRegistration(info, adopt_handle));
278 if (info.handle_id == kInvalidServiceWorkerRegistrationHandleId)
279 return NULL;
281 scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref =
282 adopt_handle ? ServiceWorkerRegistrationHandleReference::Adopt(
283 info, thread_safe_sender_.get())
284 : ServiceWorkerRegistrationHandleReference::Create(
285 info, thread_safe_sender_.get());
287 // WebServiceWorkerRegistrationImpl constructor calls
288 // AddServiceWorkerRegistration.
289 return new WebServiceWorkerRegistrationImpl(handle_ref.Pass());
292 void ServiceWorkerDispatcher::OnAssociateRegistration(
293 int thread_id,
294 int provider_id,
295 const ServiceWorkerRegistrationObjectInfo& info,
296 const ServiceWorkerVersionAttributes& attrs) {
297 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
298 if (provider == provider_contexts_.end())
299 return;
300 provider->second->OnAssociateRegistration(info, attrs);
301 if (attrs.installing.handle_id != kInvalidServiceWorkerHandleId)
302 worker_to_provider_[attrs.installing.handle_id] = provider->second;
303 if (attrs.waiting.handle_id != kInvalidServiceWorkerHandleId)
304 worker_to_provider_[attrs.waiting.handle_id] = provider->second;
305 if (attrs.active.handle_id != kInvalidServiceWorkerHandleId)
306 worker_to_provider_[attrs.active.handle_id] = provider->second;
309 void ServiceWorkerDispatcher::OnDisassociateRegistration(
310 int thread_id,
311 int provider_id) {
312 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
313 if (provider == provider_contexts_.end())
314 return;
315 provider->second->OnDisassociateRegistration();
316 worker_to_provider_.erase(provider->second->installing_handle_id());
317 worker_to_provider_.erase(provider->second->waiting_handle_id());
318 worker_to_provider_.erase(provider->second->active_handle_id());
319 worker_to_provider_.erase(provider->second->controller_handle_id());
322 void ServiceWorkerDispatcher::OnRegistered(
323 int thread_id,
324 int request_id,
325 const ServiceWorkerRegistrationObjectInfo& info,
326 const ServiceWorkerVersionAttributes& attrs) {
327 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
328 "ServiceWorkerDispatcher::RegisterServiceWorker",
329 request_id,
330 "OnRegistered");
331 TRACE_EVENT_ASYNC_END0("ServiceWorker",
332 "ServiceWorkerDispatcher::RegisterServiceWorker",
333 request_id);
334 WebServiceWorkerRegistrationCallbacks* callbacks =
335 pending_registration_callbacks_.Lookup(request_id);
336 DCHECK(callbacks);
337 if (!callbacks)
338 return;
340 callbacks->onSuccess(FindOrCreateRegistration(info, attrs));
341 pending_registration_callbacks_.Remove(request_id);
344 void ServiceWorkerDispatcher::OnUnregistered(int thread_id,
345 int request_id,
346 bool is_success) {
347 TRACE_EVENT_ASYNC_STEP_INTO0(
348 "ServiceWorker",
349 "ServiceWorkerDispatcher::UnregisterServiceWorker",
350 request_id,
351 "OnUnregistered");
352 TRACE_EVENT_ASYNC_END0("ServiceWorker",
353 "ServiceWorkerDispatcher::UnregisterServiceWorker",
354 request_id);
355 WebServiceWorkerUnregistrationCallbacks* callbacks =
356 pending_unregistration_callbacks_.Lookup(request_id);
357 DCHECK(callbacks);
358 if (!callbacks)
359 return;
360 callbacks->onSuccess(&is_success);
361 pending_unregistration_callbacks_.Remove(request_id);
364 void ServiceWorkerDispatcher::OnDidGetRegistration(
365 int thread_id,
366 int request_id,
367 const ServiceWorkerRegistrationObjectInfo& info,
368 const ServiceWorkerVersionAttributes& attrs) {
369 TRACE_EVENT_ASYNC_STEP_INTO0(
370 "ServiceWorker",
371 "ServiceWorkerDispatcher::GetRegistration",
372 request_id,
373 "OnDidGetRegistration");
374 TRACE_EVENT_ASYNC_END0("ServiceWorker",
375 "ServiceWorkerDispatcher::GetRegistration",
376 request_id);
377 WebServiceWorkerRegistrationCallbacks* callbacks =
378 pending_get_registration_callbacks_.Lookup(request_id);
379 DCHECK(callbacks);
380 if (!callbacks)
381 return;
383 WebServiceWorkerRegistrationImpl* registration = NULL;
384 if (info.handle_id != kInvalidServiceWorkerHandleId)
385 registration = FindOrCreateRegistration(info, attrs);
387 callbacks->onSuccess(registration);
388 pending_get_registration_callbacks_.Remove(request_id);
391 void ServiceWorkerDispatcher::OnRegistrationError(
392 int thread_id,
393 int request_id,
394 WebServiceWorkerError::ErrorType error_type,
395 const base::string16& message) {
396 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
397 "ServiceWorkerDispatcher::RegisterServiceWorker",
398 request_id,
399 "OnRegistrationError");
400 TRACE_EVENT_ASYNC_END0("ServiceWorker",
401 "ServiceWorkerDispatcher::RegisterServiceWorker",
402 request_id);
403 WebServiceWorkerRegistrationCallbacks* callbacks =
404 pending_registration_callbacks_.Lookup(request_id);
405 DCHECK(callbacks);
406 if (!callbacks)
407 return;
409 scoped_ptr<WebServiceWorkerError> error(
410 new WebServiceWorkerError(error_type, message));
411 callbacks->onError(error.release());
412 pending_registration_callbacks_.Remove(request_id);
415 void ServiceWorkerDispatcher::OnUnregistrationError(
416 int thread_id,
417 int request_id,
418 WebServiceWorkerError::ErrorType error_type,
419 const base::string16& message) {
420 TRACE_EVENT_ASYNC_STEP_INTO0(
421 "ServiceWorker",
422 "ServiceWorkerDispatcher::UnregisterServiceWorker",
423 request_id,
424 "OnUnregistrationError");
425 TRACE_EVENT_ASYNC_END0("ServiceWorker",
426 "ServiceWorkerDispatcher::UnregisterServiceWorker",
427 request_id);
428 WebServiceWorkerUnregistrationCallbacks* callbacks =
429 pending_unregistration_callbacks_.Lookup(request_id);
430 DCHECK(callbacks);
431 if (!callbacks)
432 return;
434 scoped_ptr<WebServiceWorkerError> error(
435 new WebServiceWorkerError(error_type, message));
436 callbacks->onError(error.release());
437 pending_unregistration_callbacks_.Remove(request_id);
440 void ServiceWorkerDispatcher::OnGetRegistrationError(
441 int thread_id,
442 int request_id,
443 WebServiceWorkerError::ErrorType error_type,
444 const base::string16& message) {
445 TRACE_EVENT_ASYNC_STEP_INTO0(
446 "ServiceWorker",
447 "ServiceWorkerDispatcher::GetRegistration",
448 request_id,
449 "OnGetRegistrationError");
450 TRACE_EVENT_ASYNC_END0("ServiceWorker",
451 "ServiceWorkerDispatcher::GetRegistration",
452 request_id);
453 WebServiceWorkerGetRegistrationCallbacks* callbacks =
454 pending_get_registration_callbacks_.Lookup(request_id);
455 DCHECK(callbacks);
456 if (!callbacks)
457 return;
459 scoped_ptr<WebServiceWorkerError> error(
460 new WebServiceWorkerError(error_type, message));
461 callbacks->onError(error.release());
462 pending_get_registration_callbacks_.Remove(request_id);
465 void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
466 int thread_id,
467 int handle_id,
468 blink::WebServiceWorkerState state) {
469 TRACE_EVENT2("ServiceWorker",
470 "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
471 "Thread ID", thread_id,
472 "State", state);
473 WorkerObjectMap::iterator worker = service_workers_.find(handle_id);
474 if (worker != service_workers_.end())
475 worker->second->OnStateChanged(state);
477 WorkerToProviderMap::iterator provider = worker_to_provider_.find(handle_id);
478 if (provider != worker_to_provider_.end())
479 provider->second->OnServiceWorkerStateChanged(handle_id, state);
482 void ServiceWorkerDispatcher::OnSetVersionAttributes(
483 int thread_id,
484 int provider_id,
485 int registration_handle_id,
486 int changed_mask,
487 const ServiceWorkerVersionAttributes& attributes) {
488 TRACE_EVENT1("ServiceWorker",
489 "ServiceWorkerDispatcher::OnSetVersionAttributes",
490 "Thread ID", thread_id);
491 ChangedVersionAttributesMask mask(changed_mask);
492 if (mask.installing_changed()) {
493 SetInstallingServiceWorker(provider_id,
494 registration_handle_id,
495 attributes.installing);
497 if (mask.waiting_changed()) {
498 SetWaitingServiceWorker(provider_id,
499 registration_handle_id,
500 attributes.waiting);
502 if (mask.active_changed()) {
503 SetActiveServiceWorker(provider_id,
504 registration_handle_id,
505 attributes.active);
506 SetReadyRegistration(provider_id, registration_handle_id);
510 void ServiceWorkerDispatcher::OnUpdateFound(
511 int thread_id,
512 const ServiceWorkerRegistrationObjectInfo& info) {
513 TRACE_EVENT0("ServiceWorker",
514 "ServiceWorkerDispatcher::OnUpdateFound");
515 RegistrationObjectMap::iterator found = registrations_.find(info.handle_id);
516 if (found != registrations_.end())
517 found->second->OnUpdateFound();
520 void ServiceWorkerDispatcher::SetInstallingServiceWorker(
521 int provider_id,
522 int registration_handle_id,
523 const ServiceWorkerObjectInfo& info) {
524 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
525 if (provider != provider_contexts_.end() &&
526 provider->second->registration_handle_id() == registration_handle_id) {
527 int existing_installing_id = provider->second->installing_handle_id();
528 if (existing_installing_id != info.handle_id &&
529 existing_installing_id != kInvalidServiceWorkerHandleId) {
530 WorkerToProviderMap::iterator associated_provider =
531 worker_to_provider_.find(existing_installing_id);
532 DCHECK(associated_provider != worker_to_provider_.end());
533 DCHECK(associated_provider->second->provider_id() == provider_id);
534 worker_to_provider_.erase(associated_provider);
536 provider->second->OnSetInstallingServiceWorker(
537 registration_handle_id, info);
538 if (info.handle_id != kInvalidServiceWorkerHandleId)
539 worker_to_provider_[info.handle_id] = provider->second;
542 RegistrationObjectMap::iterator found =
543 registrations_.find(registration_handle_id);
544 if (found != registrations_.end()) {
545 // Populate the .installing field with the new worker object.
546 found->second->SetInstalling(GetServiceWorker(info, false));
550 void ServiceWorkerDispatcher::SetWaitingServiceWorker(
551 int provider_id,
552 int registration_handle_id,
553 const ServiceWorkerObjectInfo& info) {
554 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
555 if (provider != provider_contexts_.end() &&
556 provider->second->registration_handle_id() == registration_handle_id) {
557 int existing_waiting_id = provider->second->waiting_handle_id();
558 if (existing_waiting_id != info.handle_id &&
559 existing_waiting_id != kInvalidServiceWorkerHandleId) {
560 WorkerToProviderMap::iterator associated_provider =
561 worker_to_provider_.find(existing_waiting_id);
562 DCHECK(associated_provider != worker_to_provider_.end());
563 DCHECK(associated_provider->second->provider_id() == provider_id);
564 worker_to_provider_.erase(associated_provider);
566 provider->second->OnSetWaitingServiceWorker(registration_handle_id, info);
567 if (info.handle_id != kInvalidServiceWorkerHandleId)
568 worker_to_provider_[info.handle_id] = provider->second;
571 RegistrationObjectMap::iterator found =
572 registrations_.find(registration_handle_id);
573 if (found != registrations_.end()) {
574 // Populate the .waiting field with the new worker object.
575 found->second->SetWaiting(GetServiceWorker(info, false));
579 void ServiceWorkerDispatcher::SetActiveServiceWorker(
580 int provider_id,
581 int registration_handle_id,
582 const ServiceWorkerObjectInfo& info) {
583 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
584 if (provider != provider_contexts_.end() &&
585 provider->second->registration_handle_id() == registration_handle_id) {
586 int existing_active_id = provider->second->active_handle_id();
587 if (existing_active_id != info.handle_id &&
588 existing_active_id != kInvalidServiceWorkerHandleId) {
589 WorkerToProviderMap::iterator associated_provider =
590 worker_to_provider_.find(existing_active_id);
591 DCHECK(associated_provider != worker_to_provider_.end());
592 DCHECK(associated_provider->second->provider_id() == provider_id);
593 worker_to_provider_.erase(associated_provider);
595 provider->second->OnSetActiveServiceWorker(registration_handle_id, info);
596 if (info.handle_id != kInvalidServiceWorkerHandleId)
597 worker_to_provider_[info.handle_id] = provider->second;
600 RegistrationObjectMap::iterator found =
601 registrations_.find(registration_handle_id);
602 if (found != registrations_.end()) {
603 // Populate the .active field with the new worker object.
604 found->second->SetActive(GetServiceWorker(info, false));
608 void ServiceWorkerDispatcher::SetReadyRegistration(
609 int provider_id,
610 int registration_handle_id) {
611 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
612 if (provider == provider_contexts_.end() ||
613 provider->second->registration_handle_id() != registration_handle_id ||
614 provider->second->active_handle_id() == kInvalidServiceWorkerHandleId) {
615 return;
618 ScriptClientMap::iterator client = script_clients_.find(provider_id);
619 if (client == script_clients_.end())
620 return;
622 ServiceWorkerRegistrationObjectInfo info =
623 provider->second->registration()->info();
624 WebServiceWorkerRegistrationImpl* registration =
625 FindServiceWorkerRegistration(info, false);
626 if (!registration) {
627 registration = CreateServiceWorkerRegistration(info, false);
628 ServiceWorkerVersionAttributes attrs =
629 provider->second->GetVersionAttributes();
630 registration->SetInstalling(GetServiceWorker(attrs.installing, false));
631 registration->SetWaiting(GetServiceWorker(attrs.waiting, false));
632 registration->SetActive(GetServiceWorker(attrs.active, false));
635 // Resolve the .ready promise with the registration object.
636 client->second->setReadyRegistration(registration);
639 void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
640 int thread_id,
641 int provider_id,
642 const ServiceWorkerObjectInfo& info,
643 bool should_notify_controllerchange) {
644 TRACE_EVENT2("ServiceWorker",
645 "ServiceWorkerDispatcher::OnSetControllerServiceWorker",
646 "Thread ID", thread_id,
647 "Provider ID", provider_id);
648 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
649 if (provider != provider_contexts_.end()) {
650 provider->second->OnSetControllerServiceWorker(
651 provider->second->registration_handle_id(), info);
652 worker_to_provider_[info.handle_id] = provider->second;
655 ScriptClientMap::iterator found = script_clients_.find(provider_id);
656 if (found != script_clients_.end()) {
657 // Populate the .controller field with the new worker object.
658 found->second->setController(GetServiceWorker(info, false),
659 should_notify_controllerchange);
663 void ServiceWorkerDispatcher::OnPostMessage(
664 int thread_id,
665 int provider_id,
666 const base::string16& message,
667 const std::vector<int>& sent_message_port_ids,
668 const std::vector<int>& new_routing_ids) {
669 // Make sure we're on the main document thread. (That must be the only
670 // thread we get this message)
671 DCHECK(ChildThread::current());
672 TRACE_EVENT1("ServiceWorker",
673 "ServiceWorkerDispatcher::OnPostMessage",
674 "Thread ID", thread_id);
676 ScriptClientMap::iterator found = script_clients_.find(provider_id);
677 if (found == script_clients_.end()) {
678 // For now we do no queueing for messages sent to nonexistent / unattached
679 // client.
680 return;
683 std::vector<WebMessagePortChannelImpl*> ports;
684 if (!sent_message_port_ids.empty()) {
685 ports.resize(sent_message_port_ids.size());
686 for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
687 ports[i] = new WebMessagePortChannelImpl(
688 new_routing_ids[i], sent_message_port_ids[i],
689 base::MessageLoopProxy::current());
693 found->second->dispatchMessageEvent(message, ports);
696 void ServiceWorkerDispatcher::OnGetClientInfo(int thread_id,
697 int embedded_worker_id,
698 int request_id,
699 int provider_id) {
700 blink::WebServiceWorkerClientInfo info;
701 ScriptClientMap::iterator found = script_clients_.find(provider_id);
702 // TODO(ksakamoto): Could we track these values in the browser side? Except
703 // for |isFocused|, it would be pretty easy.
704 if (found != script_clients_.end() && found->second->getClientInfo(&info)) {
705 ServiceWorkerClientInfo result;
706 result.client_id = info.clientID;
707 result.visibility_state = info.visibilityState.utf8();
708 result.is_focused = info.isFocused;
709 result.url = info.url;
710 result.frame_type = static_cast<RequestContextFrameType>(info.frameType);
712 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetClientInfoSuccess(
713 embedded_worker_id, request_id, result));
714 } else {
715 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetClientInfoError(
716 embedded_worker_id, request_id));
720 void ServiceWorkerDispatcher::AddServiceWorker(
721 int handle_id, WebServiceWorkerImpl* worker) {
722 DCHECK(!ContainsKey(service_workers_, handle_id));
723 service_workers_[handle_id] = worker;
726 void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id) {
727 DCHECK(ContainsKey(service_workers_, handle_id));
728 service_workers_.erase(handle_id);
731 void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
732 int registration_handle_id,
733 WebServiceWorkerRegistrationImpl* registration) {
734 DCHECK(!ContainsKey(registrations_, registration_handle_id));
735 registrations_[registration_handle_id] = registration;
738 void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
739 int registration_handle_id) {
740 DCHECK(ContainsKey(registrations_, registration_handle_id));
741 registrations_.erase(registration_handle_id);
744 WebServiceWorkerRegistrationImpl*
745 ServiceWorkerDispatcher::FindOrCreateRegistration(
746 const ServiceWorkerRegistrationObjectInfo& info,
747 const ServiceWorkerVersionAttributes& attrs) {
748 WebServiceWorkerRegistrationImpl* registration =
749 FindServiceWorkerRegistration(info, true);
750 if (!registration) {
751 registration = CreateServiceWorkerRegistration(info, true);
752 registration->SetInstalling(GetServiceWorker(attrs.installing, true));
753 registration->SetWaiting(GetServiceWorker(attrs.waiting, true));
754 registration->SetActive(GetServiceWorker(attrs.active, true));
755 } else {
756 // |registration| must already have version attributes, so adopt and destroy
757 // handle refs for them.
758 ServiceWorkerHandleReference::Adopt(
759 attrs.installing, thread_safe_sender_.get());
760 ServiceWorkerHandleReference::Adopt(
761 attrs.waiting, thread_safe_sender_.get());
762 ServiceWorkerHandleReference::Adopt(
763 attrs.active, thread_safe_sender_.get());
765 return registration;
768 } // namespace content