Delete chrome.mediaGalleriesPrivate because the functionality unique to it has since...
[chromium-blink-merge.git] / content / child / service_worker / service_worker_dispatcher.cc
blob0a30cfbb25c612454d851c7cfcfe20f34762a9f7
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/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_AssociateRegistration,
61 OnAssociateRegistration)
62 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DisassociateRegistration,
63 OnDisassociateRegistration)
64 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered, OnRegistered)
65 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered,
66 OnUnregistered)
67 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistration,
68 OnDidGetRegistration)
69 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError,
70 OnRegistrationError)
71 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistrationError,
72 OnUnregistrationError)
73 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationError,
74 OnGetRegistrationError)
75 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged,
76 OnServiceWorkerStateChanged)
77 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes,
78 OnSetVersionAttributes)
79 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_UpdateFound,
80 OnUpdateFound)
81 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker,
82 OnSetControllerServiceWorker)
83 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument,
84 OnPostMessage)
85 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_GetClientInfo,
86 OnGetClientInfo)
87 IPC_MESSAGE_UNHANDLED(handled = false)
88 IPC_END_MESSAGE_MAP()
89 DCHECK(handled) << "Unhandled message:" << msg.type();
92 bool ServiceWorkerDispatcher::Send(IPC::Message* msg) {
93 return thread_safe_sender_->Send(msg);
96 void ServiceWorkerDispatcher::RegisterServiceWorker(
97 int provider_id,
98 const GURL& pattern,
99 const GURL& script_url,
100 WebServiceWorkerRegistrationCallbacks* callbacks) {
101 DCHECK(callbacks);
103 if (pattern.possibly_invalid_spec().size() > GetMaxURLChars() ||
104 script_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
105 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
106 owned_callbacks(callbacks);
107 std::string error_message(kServiceWorkerRegisterErrorPrefix);
108 error_message += "The provided scriptURL or scope is too long.";
109 scoped_ptr<WebServiceWorkerError> error(
110 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity,
111 blink::WebString::fromUTF8(error_message)));
112 callbacks->onError(error.release());
113 return;
116 int request_id = pending_registration_callbacks_.Add(callbacks);
117 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
118 "ServiceWorkerDispatcher::RegisterServiceWorker",
119 request_id,
120 "Scope", pattern.spec(),
121 "Script URL", script_url.spec());
122 thread_safe_sender_->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
123 CurrentWorkerId(), request_id, provider_id, pattern, script_url));
126 void ServiceWorkerDispatcher::UnregisterServiceWorker(
127 int provider_id,
128 const GURL& pattern,
129 WebServiceWorkerUnregistrationCallbacks* callbacks) {
130 DCHECK(callbacks);
132 if (pattern.possibly_invalid_spec().size() > GetMaxURLChars()) {
133 scoped_ptr<WebServiceWorkerUnregistrationCallbacks>
134 owned_callbacks(callbacks);
135 std::string error_message(kServiceWorkerUnregisterErrorPrefix);
136 error_message += "The provided scope is too long.";
137 scoped_ptr<WebServiceWorkerError> error(
138 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity,
139 blink::WebString::fromUTF8(error_message)));
140 callbacks->onError(error.release());
141 return;
144 int request_id = pending_unregistration_callbacks_.Add(callbacks);
145 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
146 "ServiceWorkerDispatcher::UnregisterServiceWorker",
147 request_id,
148 "Scope", pattern.spec());
149 thread_safe_sender_->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
150 CurrentWorkerId(), request_id, provider_id, pattern));
153 void ServiceWorkerDispatcher::GetRegistration(
154 int provider_id,
155 const GURL& document_url,
156 WebServiceWorkerRegistrationCallbacks* callbacks) {
157 DCHECK(callbacks);
159 if (document_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
160 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
161 owned_callbacks(callbacks);
162 std::string error_message(kServiceWorkerGetRegistrationErrorPrefix);
163 error_message += "The provided documentURL is too long.";
164 scoped_ptr<WebServiceWorkerError> error(
165 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity,
166 blink::WebString::fromUTF8(error_message)));
167 callbacks->onError(error.release());
168 return;
171 int request_id = pending_get_registration_callbacks_.Add(callbacks);
172 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
173 "ServiceWorkerDispatcher::GetRegistration",
174 request_id,
175 "Document URL", document_url.spec());
176 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistration(
177 CurrentWorkerId(), request_id, provider_id, document_url));
180 void ServiceWorkerDispatcher::AddProviderContext(
181 ServiceWorkerProviderContext* provider_context) {
182 DCHECK(provider_context);
183 int provider_id = provider_context->provider_id();
184 DCHECK(!ContainsKey(provider_contexts_, provider_id));
185 provider_contexts_[provider_id] = provider_context;
188 void ServiceWorkerDispatcher::RemoveProviderContext(
189 ServiceWorkerProviderContext* provider_context) {
190 DCHECK(provider_context);
191 DCHECK(ContainsKey(provider_contexts_, provider_context->provider_id()));
192 provider_contexts_.erase(provider_context->provider_id());
193 worker_to_provider_.erase(provider_context->installing_handle_id());
194 worker_to_provider_.erase(provider_context->waiting_handle_id());
195 worker_to_provider_.erase(provider_context->active_handle_id());
196 worker_to_provider_.erase(provider_context->controller_handle_id());
199 void ServiceWorkerDispatcher::AddProviderClient(
200 int provider_id,
201 blink::WebServiceWorkerProviderClient* client) {
202 DCHECK(client);
203 DCHECK(!ContainsKey(provider_clients_, provider_id));
204 provider_clients_[provider_id] = client;
207 void ServiceWorkerDispatcher::RemoveProviderClient(int provider_id) {
208 // This could be possibly called multiple times to ensure termination.
209 if (ContainsKey(provider_clients_, provider_id))
210 provider_clients_.erase(provider_id);
213 ServiceWorkerDispatcher*
214 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
215 ThreadSafeSender* thread_safe_sender) {
216 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
217 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
218 g_dispatcher_tls.Pointer()->Set(NULL);
220 if (g_dispatcher_tls.Pointer()->Get())
221 return g_dispatcher_tls.Pointer()->Get();
223 ServiceWorkerDispatcher* dispatcher =
224 new ServiceWorkerDispatcher(thread_safe_sender);
225 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
226 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
227 return dispatcher;
230 ServiceWorkerDispatcher* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
231 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted)
232 return NULL;
233 return g_dispatcher_tls.Pointer()->Get();
236 void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
237 delete this;
240 WebServiceWorkerImpl* ServiceWorkerDispatcher::GetServiceWorker(
241 const ServiceWorkerObjectInfo& info,
242 bool adopt_handle) {
243 if (info.handle_id == kInvalidServiceWorkerHandleId)
244 return NULL;
246 WorkerObjectMap::iterator existing_worker =
247 service_workers_.find(info.handle_id);
249 if (existing_worker != service_workers_.end()) {
250 if (adopt_handle) {
251 // We are instructed to adopt a handle but we already have one, so
252 // adopt and destroy a handle ref.
253 ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
255 return existing_worker->second;
258 scoped_ptr<ServiceWorkerHandleReference> handle_ref =
259 adopt_handle
260 ? ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get())
261 : ServiceWorkerHandleReference::Create(info,
262 thread_safe_sender_.get());
263 // WebServiceWorkerImpl constructor calls AddServiceWorker.
264 return new WebServiceWorkerImpl(handle_ref.Pass(), thread_safe_sender_.get());
267 WebServiceWorkerRegistrationImpl*
268 ServiceWorkerDispatcher::FindServiceWorkerRegistration(
269 const ServiceWorkerRegistrationObjectInfo& info,
270 bool adopt_handle) {
271 RegistrationObjectMap::iterator registration =
272 registrations_.find(info.handle_id);
273 if (registration == registrations_.end())
274 return NULL;
275 if (adopt_handle) {
276 // We are instructed to adopt a handle but we already have one, so
277 // adopt and destroy a handle ref.
278 ServiceWorkerRegistrationHandleReference::Adopt(
279 info, thread_safe_sender_.get());
281 return registration->second;
284 WebServiceWorkerRegistrationImpl*
285 ServiceWorkerDispatcher::CreateServiceWorkerRegistration(
286 const ServiceWorkerRegistrationObjectInfo& info,
287 bool adopt_handle) {
288 DCHECK(!FindServiceWorkerRegistration(info, adopt_handle));
289 if (info.handle_id == kInvalidServiceWorkerRegistrationHandleId)
290 return NULL;
292 scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref =
293 adopt_handle ? ServiceWorkerRegistrationHandleReference::Adopt(
294 info, thread_safe_sender_.get())
295 : ServiceWorkerRegistrationHandleReference::Create(
296 info, thread_safe_sender_.get());
298 // WebServiceWorkerRegistrationImpl constructor calls
299 // AddServiceWorkerRegistration.
300 return new WebServiceWorkerRegistrationImpl(handle_ref.Pass());
303 void ServiceWorkerDispatcher::OnAssociateRegistration(
304 int thread_id,
305 int provider_id,
306 const ServiceWorkerRegistrationObjectInfo& info,
307 const ServiceWorkerVersionAttributes& attrs) {
308 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
309 if (provider == provider_contexts_.end())
310 return;
311 provider->second->OnAssociateRegistration(info, attrs);
312 if (attrs.installing.handle_id != kInvalidServiceWorkerHandleId)
313 worker_to_provider_[attrs.installing.handle_id] = provider->second;
314 if (attrs.waiting.handle_id != kInvalidServiceWorkerHandleId)
315 worker_to_provider_[attrs.waiting.handle_id] = provider->second;
316 if (attrs.active.handle_id != kInvalidServiceWorkerHandleId)
317 worker_to_provider_[attrs.active.handle_id] = provider->second;
320 void ServiceWorkerDispatcher::OnDisassociateRegistration(
321 int thread_id,
322 int provider_id) {
323 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
324 if (provider == provider_contexts_.end())
325 return;
326 provider->second->OnDisassociateRegistration();
327 worker_to_provider_.erase(provider->second->installing_handle_id());
328 worker_to_provider_.erase(provider->second->waiting_handle_id());
329 worker_to_provider_.erase(provider->second->active_handle_id());
330 worker_to_provider_.erase(provider->second->controller_handle_id());
333 void ServiceWorkerDispatcher::OnRegistered(
334 int thread_id,
335 int request_id,
336 const ServiceWorkerRegistrationObjectInfo& info,
337 const ServiceWorkerVersionAttributes& attrs) {
338 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
339 "ServiceWorkerDispatcher::RegisterServiceWorker",
340 request_id,
341 "OnRegistered");
342 TRACE_EVENT_ASYNC_END0("ServiceWorker",
343 "ServiceWorkerDispatcher::RegisterServiceWorker",
344 request_id);
345 WebServiceWorkerRegistrationCallbacks* callbacks =
346 pending_registration_callbacks_.Lookup(request_id);
347 DCHECK(callbacks);
348 if (!callbacks)
349 return;
351 callbacks->onSuccess(FindOrCreateRegistration(info, attrs));
352 pending_registration_callbacks_.Remove(request_id);
355 void ServiceWorkerDispatcher::OnUnregistered(int thread_id,
356 int request_id,
357 bool is_success) {
358 TRACE_EVENT_ASYNC_STEP_INTO0(
359 "ServiceWorker",
360 "ServiceWorkerDispatcher::UnregisterServiceWorker",
361 request_id,
362 "OnUnregistered");
363 TRACE_EVENT_ASYNC_END0("ServiceWorker",
364 "ServiceWorkerDispatcher::UnregisterServiceWorker",
365 request_id);
366 WebServiceWorkerUnregistrationCallbacks* callbacks =
367 pending_unregistration_callbacks_.Lookup(request_id);
368 DCHECK(callbacks);
369 if (!callbacks)
370 return;
371 callbacks->onSuccess(&is_success);
372 pending_unregistration_callbacks_.Remove(request_id);
375 void ServiceWorkerDispatcher::OnDidGetRegistration(
376 int thread_id,
377 int request_id,
378 const ServiceWorkerRegistrationObjectInfo& info,
379 const ServiceWorkerVersionAttributes& attrs) {
380 TRACE_EVENT_ASYNC_STEP_INTO0(
381 "ServiceWorker",
382 "ServiceWorkerDispatcher::GetRegistration",
383 request_id,
384 "OnDidGetRegistration");
385 TRACE_EVENT_ASYNC_END0("ServiceWorker",
386 "ServiceWorkerDispatcher::GetRegistration",
387 request_id);
388 WebServiceWorkerRegistrationCallbacks* callbacks =
389 pending_get_registration_callbacks_.Lookup(request_id);
390 DCHECK(callbacks);
391 if (!callbacks)
392 return;
394 WebServiceWorkerRegistrationImpl* registration = NULL;
395 if (info.handle_id != kInvalidServiceWorkerHandleId)
396 registration = FindOrCreateRegistration(info, attrs);
398 callbacks->onSuccess(registration);
399 pending_get_registration_callbacks_.Remove(request_id);
402 void ServiceWorkerDispatcher::OnRegistrationError(
403 int thread_id,
404 int request_id,
405 WebServiceWorkerError::ErrorType error_type,
406 const base::string16& message) {
407 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
408 "ServiceWorkerDispatcher::RegisterServiceWorker",
409 request_id,
410 "OnRegistrationError");
411 TRACE_EVENT_ASYNC_END0("ServiceWorker",
412 "ServiceWorkerDispatcher::RegisterServiceWorker",
413 request_id);
414 WebServiceWorkerRegistrationCallbacks* callbacks =
415 pending_registration_callbacks_.Lookup(request_id);
416 DCHECK(callbacks);
417 if (!callbacks)
418 return;
420 scoped_ptr<WebServiceWorkerError> error(
421 new WebServiceWorkerError(error_type, message));
422 callbacks->onError(error.release());
423 pending_registration_callbacks_.Remove(request_id);
426 void ServiceWorkerDispatcher::OnUnregistrationError(
427 int thread_id,
428 int request_id,
429 WebServiceWorkerError::ErrorType error_type,
430 const base::string16& message) {
431 TRACE_EVENT_ASYNC_STEP_INTO0(
432 "ServiceWorker",
433 "ServiceWorkerDispatcher::UnregisterServiceWorker",
434 request_id,
435 "OnUnregistrationError");
436 TRACE_EVENT_ASYNC_END0("ServiceWorker",
437 "ServiceWorkerDispatcher::UnregisterServiceWorker",
438 request_id);
439 WebServiceWorkerUnregistrationCallbacks* callbacks =
440 pending_unregistration_callbacks_.Lookup(request_id);
441 DCHECK(callbacks);
442 if (!callbacks)
443 return;
445 scoped_ptr<WebServiceWorkerError> error(
446 new WebServiceWorkerError(error_type, message));
447 callbacks->onError(error.release());
448 pending_unregistration_callbacks_.Remove(request_id);
451 void ServiceWorkerDispatcher::OnGetRegistrationError(
452 int thread_id,
453 int request_id,
454 WebServiceWorkerError::ErrorType error_type,
455 const base::string16& message) {
456 TRACE_EVENT_ASYNC_STEP_INTO0(
457 "ServiceWorker",
458 "ServiceWorkerDispatcher::GetRegistration",
459 request_id,
460 "OnGetRegistrationError");
461 TRACE_EVENT_ASYNC_END0("ServiceWorker",
462 "ServiceWorkerDispatcher::GetRegistration",
463 request_id);
464 WebServiceWorkerGetRegistrationCallbacks* callbacks =
465 pending_get_registration_callbacks_.Lookup(request_id);
466 DCHECK(callbacks);
467 if (!callbacks)
468 return;
470 scoped_ptr<WebServiceWorkerError> error(
471 new WebServiceWorkerError(error_type, message));
472 callbacks->onError(error.release());
473 pending_get_registration_callbacks_.Remove(request_id);
476 void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
477 int thread_id,
478 int handle_id,
479 blink::WebServiceWorkerState state) {
480 TRACE_EVENT2("ServiceWorker",
481 "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
482 "Thread ID", thread_id,
483 "State", state);
484 WorkerObjectMap::iterator worker = service_workers_.find(handle_id);
485 if (worker != service_workers_.end())
486 worker->second->OnStateChanged(state);
488 WorkerToProviderMap::iterator provider = worker_to_provider_.find(handle_id);
489 if (provider != worker_to_provider_.end())
490 provider->second->OnServiceWorkerStateChanged(handle_id, state);
493 void ServiceWorkerDispatcher::OnSetVersionAttributes(
494 int thread_id,
495 int provider_id,
496 int registration_handle_id,
497 int changed_mask,
498 const ServiceWorkerVersionAttributes& attrs) {
499 TRACE_EVENT1("ServiceWorker",
500 "ServiceWorkerDispatcher::OnSetVersionAttributes",
501 "Thread ID", thread_id);
503 ChangedVersionAttributesMask mask(changed_mask);
504 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
505 if (provider != provider_contexts_.end() &&
506 provider->second->registration_handle_id() == registration_handle_id) {
507 if (mask.installing_changed()) {
508 worker_to_provider_.erase(provider->second->installing_handle_id());
509 if (attrs.installing.handle_id != kInvalidServiceWorkerHandleId)
510 worker_to_provider_[attrs.installing.handle_id] = provider->second;
512 if (mask.waiting_changed()) {
513 worker_to_provider_.erase(provider->second->waiting_handle_id());
514 if (attrs.waiting.handle_id != kInvalidServiceWorkerHandleId)
515 worker_to_provider_[attrs.waiting.handle_id] = provider->second;
517 if (mask.active_changed()) {
518 worker_to_provider_.erase(provider->second->active_handle_id());
519 if (attrs.active.handle_id != kInvalidServiceWorkerHandleId)
520 worker_to_provider_[attrs.active.handle_id] = provider->second;
522 provider->second->SetVersionAttributes(mask, attrs);
525 RegistrationObjectMap::iterator found =
526 registrations_.find(registration_handle_id);
527 if (found != registrations_.end()) {
528 // Populate the version fields (eg. .installing) with new worker objects.
529 if (mask.installing_changed())
530 found->second->SetInstalling(GetServiceWorker(attrs.installing, false));
531 if (mask.waiting_changed())
532 found->second->SetWaiting(GetServiceWorker(attrs.waiting, false));
533 if (mask.active_changed())
534 found->second->SetActive(GetServiceWorker(attrs.active, false));
537 if (mask.active_changed())
538 SetReadyRegistration(provider_id, registration_handle_id);
541 void ServiceWorkerDispatcher::OnUpdateFound(
542 int thread_id,
543 const ServiceWorkerRegistrationObjectInfo& info) {
544 TRACE_EVENT0("ServiceWorker",
545 "ServiceWorkerDispatcher::OnUpdateFound");
546 RegistrationObjectMap::iterator found = registrations_.find(info.handle_id);
547 if (found != registrations_.end())
548 found->second->OnUpdateFound();
551 void ServiceWorkerDispatcher::SetReadyRegistration(
552 int provider_id,
553 int registration_handle_id) {
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 provider->second->active_handle_id() == kInvalidServiceWorkerHandleId) {
558 return;
561 ProviderClientMap::iterator client = provider_clients_.find(provider_id);
562 if (client == provider_clients_.end())
563 return;
565 ServiceWorkerRegistrationObjectInfo info =
566 provider->second->registration()->info();
567 WebServiceWorkerRegistrationImpl* registration =
568 FindServiceWorkerRegistration(info, false);
569 if (!registration) {
570 registration = CreateServiceWorkerRegistration(info, false);
571 ServiceWorkerVersionAttributes attrs =
572 provider->second->GetVersionAttributes();
573 registration->SetInstalling(GetServiceWorker(attrs.installing, false));
574 registration->SetWaiting(GetServiceWorker(attrs.waiting, false));
575 registration->SetActive(GetServiceWorker(attrs.active, false));
578 // Resolve the .ready promise with the registration object.
579 client->second->setReadyRegistration(registration);
582 void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
583 int thread_id,
584 int provider_id,
585 const ServiceWorkerObjectInfo& info,
586 bool should_notify_controllerchange) {
587 TRACE_EVENT2("ServiceWorker",
588 "ServiceWorkerDispatcher::OnSetControllerServiceWorker",
589 "Thread ID", thread_id,
590 "Provider ID", provider_id);
592 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
593 if (provider != provider_contexts_.end()) {
594 worker_to_provider_.erase(provider->second->controller_handle_id());
595 if (info.handle_id != kInvalidServiceWorkerHandleId)
596 worker_to_provider_[info.handle_id] = provider->second;
597 provider->second->OnSetControllerServiceWorker(info);
600 ProviderClientMap::iterator found = provider_clients_.find(provider_id);
601 if (found != provider_clients_.end()) {
602 // Populate the .controller field with the new worker object.
603 found->second->setController(GetServiceWorker(info, false),
604 should_notify_controllerchange);
608 void ServiceWorkerDispatcher::OnPostMessage(
609 int thread_id,
610 int provider_id,
611 const base::string16& message,
612 const std::vector<int>& sent_message_port_ids,
613 const std::vector<int>& new_routing_ids) {
614 // Make sure we're on the main document thread. (That must be the only
615 // thread we get this message)
616 DCHECK(ChildThread::current());
617 TRACE_EVENT1("ServiceWorker",
618 "ServiceWorkerDispatcher::OnPostMessage",
619 "Thread ID", thread_id);
621 ProviderClientMap::iterator found = provider_clients_.find(provider_id);
622 if (found == provider_clients_.end()) {
623 // For now we do no queueing for messages sent to nonexistent / unattached
624 // client.
625 return;
628 std::vector<WebMessagePortChannelImpl*> ports;
629 if (!sent_message_port_ids.empty()) {
630 ports.resize(sent_message_port_ids.size());
631 for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
632 ports[i] = new WebMessagePortChannelImpl(
633 new_routing_ids[i], sent_message_port_ids[i],
634 base::MessageLoopProxy::current());
638 found->second->dispatchMessageEvent(message, ports);
641 void ServiceWorkerDispatcher::OnGetClientInfo(int thread_id,
642 int embedded_worker_id,
643 int request_id,
644 int provider_id) {
645 blink::WebServiceWorkerClientInfo info;
646 ProviderClientMap::iterator found = provider_clients_.find(provider_id);
647 // TODO(ksakamoto): Could we track these values in the browser side? Except
648 // for |isFocused|, it would be pretty easy.
649 if (found != provider_clients_.end() && found->second->getClientInfo(&info)) {
650 ServiceWorkerClientInfo result;
651 result.client_id = info.clientID;
652 result.page_visibility_state = info.pageVisibilityState;
653 result.is_focused = info.isFocused;
654 result.url = info.url;
655 result.frame_type = static_cast<RequestContextFrameType>(info.frameType);
657 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetClientInfoSuccess(
658 embedded_worker_id, request_id, result));
659 } else {
660 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetClientInfoError(
661 embedded_worker_id, request_id));
665 void ServiceWorkerDispatcher::AddServiceWorker(
666 int handle_id, WebServiceWorkerImpl* worker) {
667 DCHECK(!ContainsKey(service_workers_, handle_id));
668 service_workers_[handle_id] = worker;
671 void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id) {
672 DCHECK(ContainsKey(service_workers_, handle_id));
673 service_workers_.erase(handle_id);
676 void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
677 int registration_handle_id,
678 WebServiceWorkerRegistrationImpl* registration) {
679 DCHECK(!ContainsKey(registrations_, registration_handle_id));
680 registrations_[registration_handle_id] = registration;
683 void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
684 int registration_handle_id) {
685 DCHECK(ContainsKey(registrations_, registration_handle_id));
686 registrations_.erase(registration_handle_id);
689 WebServiceWorkerRegistrationImpl*
690 ServiceWorkerDispatcher::FindOrCreateRegistration(
691 const ServiceWorkerRegistrationObjectInfo& info,
692 const ServiceWorkerVersionAttributes& attrs) {
693 WebServiceWorkerRegistrationImpl* registration =
694 FindServiceWorkerRegistration(info, true);
695 if (!registration) {
696 registration = CreateServiceWorkerRegistration(info, true);
697 registration->SetInstalling(GetServiceWorker(attrs.installing, true));
698 registration->SetWaiting(GetServiceWorker(attrs.waiting, true));
699 registration->SetActive(GetServiceWorker(attrs.active, true));
700 } else {
701 // |registration| must already have version attributes, so adopt and destroy
702 // handle refs for them.
703 ServiceWorkerHandleReference::Adopt(
704 attrs.installing, thread_safe_sender_.get());
705 ServiceWorkerHandleReference::Adopt(
706 attrs.waiting, thread_safe_sender_.get());
707 ServiceWorkerHandleReference::Adopt(
708 attrs.active, thread_safe_sender_.get());
710 return registration;
713 } // namespace content