Removing uses of X11 native key events.
[chromium-blink-merge.git] / content / child / service_worker / service_worker_dispatcher.cc
blob4ebb9edbb32c82f87153e4f4c71ba970d9b61b4c
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/WebServiceWorkerProviderClient.h"
22 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
24 using blink::WebServiceWorkerError;
25 using blink::WebServiceWorkerProvider;
26 using base::ThreadLocalPointer;
28 namespace content {
30 namespace {
32 base::LazyInstance<ThreadLocalPointer<ServiceWorkerDispatcher> >::Leaky
33 g_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
35 ServiceWorkerDispatcher* const kHasBeenDeleted =
36 reinterpret_cast<ServiceWorkerDispatcher*>(0x1);
38 int CurrentWorkerId() {
39 return WorkerTaskRunner::Instance()->CurrentWorkerId();
42 } // namespace
44 ServiceWorkerDispatcher::ServiceWorkerDispatcher(
45 ThreadSafeSender* thread_safe_sender)
46 : thread_safe_sender_(thread_safe_sender) {
47 g_dispatcher_tls.Pointer()->Set(this);
50 ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
51 g_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
54 void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message& msg) {
55 bool handled = true;
56 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher, msg)
57 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistration,
58 OnAssociateRegistration)
59 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DisassociateRegistration,
60 OnDisassociateRegistration)
61 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered, OnRegistered)
62 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered,
63 OnUnregistered)
64 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistration,
65 OnDidGetRegistration)
66 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError,
67 OnRegistrationError)
68 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistrationError,
69 OnUnregistrationError)
70 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationError,
71 OnGetRegistrationError)
72 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged,
73 OnServiceWorkerStateChanged)
74 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes,
75 OnSetVersionAttributes)
76 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_UpdateFound,
77 OnUpdateFound)
78 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker,
79 OnSetControllerServiceWorker)
80 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument,
81 OnPostMessage)
82 IPC_MESSAGE_UNHANDLED(handled = false)
83 IPC_END_MESSAGE_MAP()
84 DCHECK(handled) << "Unhandled message:" << msg.type();
87 bool ServiceWorkerDispatcher::Send(IPC::Message* msg) {
88 return thread_safe_sender_->Send(msg);
91 void ServiceWorkerDispatcher::RegisterServiceWorker(
92 int provider_id,
93 const GURL& pattern,
94 const GURL& script_url,
95 WebServiceWorkerRegistrationCallbacks* callbacks) {
96 DCHECK(callbacks);
98 if (pattern.possibly_invalid_spec().size() > GetMaxURLChars() ||
99 script_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
100 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
101 owned_callbacks(callbacks);
102 scoped_ptr<WebServiceWorkerError> error(new WebServiceWorkerError(
103 WebServiceWorkerError::ErrorTypeSecurity, "URL too long"));
104 callbacks->onError(error.release());
105 return;
108 int request_id = pending_registration_callbacks_.Add(callbacks);
109 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
110 "ServiceWorkerDispatcher::RegisterServiceWorker",
111 request_id,
112 "Pettern", pattern.spec(),
113 "Script URL", script_url.spec());
114 thread_safe_sender_->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
115 CurrentWorkerId(), request_id, provider_id, pattern, script_url));
118 void ServiceWorkerDispatcher::UnregisterServiceWorker(
119 int provider_id,
120 const GURL& pattern,
121 WebServiceWorkerUnregistrationCallbacks* callbacks) {
122 DCHECK(callbacks);
124 if (pattern.possibly_invalid_spec().size() > GetMaxURLChars()) {
125 scoped_ptr<WebServiceWorkerUnregistrationCallbacks>
126 owned_callbacks(callbacks);
127 scoped_ptr<WebServiceWorkerError> error(new WebServiceWorkerError(
128 WebServiceWorkerError::ErrorTypeSecurity, "URL too long"));
129 callbacks->onError(error.release());
130 return;
133 int request_id = pending_unregistration_callbacks_.Add(callbacks);
134 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
135 "ServiceWorkerDispatcher::UnregisterServiceWorker",
136 request_id,
137 "Pettern", pattern.spec());
138 thread_safe_sender_->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
139 CurrentWorkerId(), request_id, provider_id, pattern));
142 void ServiceWorkerDispatcher::GetRegistration(
143 int provider_id,
144 const GURL& document_url,
145 WebServiceWorkerRegistrationCallbacks* callbacks) {
146 DCHECK(callbacks);
148 if (document_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
149 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
150 owned_callbacks(callbacks);
151 scoped_ptr<WebServiceWorkerError> error(new WebServiceWorkerError(
152 WebServiceWorkerError::ErrorTypeSecurity, "URL too long"));
153 callbacks->onError(error.release());
154 return;
157 int request_id = pending_get_registration_callbacks_.Add(callbacks);
158 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
159 "ServiceWorkerDispatcher::GetRegistration",
160 request_id,
161 "Document URL", document_url.spec());
162 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistration(
163 CurrentWorkerId(), request_id, provider_id, document_url));
166 void ServiceWorkerDispatcher::AddProviderContext(
167 ServiceWorkerProviderContext* provider_context) {
168 DCHECK(provider_context);
169 int provider_id = provider_context->provider_id();
170 DCHECK(!ContainsKey(provider_contexts_, provider_id));
171 provider_contexts_[provider_id] = provider_context;
174 void ServiceWorkerDispatcher::RemoveProviderContext(
175 ServiceWorkerProviderContext* provider_context) {
176 DCHECK(provider_context);
177 DCHECK(ContainsKey(provider_contexts_, provider_context->provider_id()));
178 provider_contexts_.erase(provider_context->provider_id());
179 worker_to_provider_.erase(provider_context->installing_handle_id());
180 worker_to_provider_.erase(provider_context->waiting_handle_id());
181 worker_to_provider_.erase(provider_context->active_handle_id());
182 worker_to_provider_.erase(provider_context->controller_handle_id());
185 void ServiceWorkerDispatcher::AddScriptClient(
186 int provider_id,
187 blink::WebServiceWorkerProviderClient* client) {
188 DCHECK(client);
189 DCHECK(!ContainsKey(script_clients_, provider_id));
190 script_clients_[provider_id] = client;
193 void ServiceWorkerDispatcher::RemoveScriptClient(int provider_id) {
194 // This could be possibly called multiple times to ensure termination.
195 if (ContainsKey(script_clients_, provider_id))
196 script_clients_.erase(provider_id);
199 ServiceWorkerDispatcher*
200 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
201 ThreadSafeSender* thread_safe_sender) {
202 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
203 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
204 g_dispatcher_tls.Pointer()->Set(NULL);
206 if (g_dispatcher_tls.Pointer()->Get())
207 return g_dispatcher_tls.Pointer()->Get();
209 ServiceWorkerDispatcher* dispatcher =
210 new ServiceWorkerDispatcher(thread_safe_sender);
211 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
212 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
213 return dispatcher;
216 ServiceWorkerDispatcher* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
217 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted)
218 return NULL;
219 return g_dispatcher_tls.Pointer()->Get();
222 void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
223 delete this;
226 WebServiceWorkerImpl* ServiceWorkerDispatcher::GetServiceWorker(
227 const ServiceWorkerObjectInfo& info,
228 bool adopt_handle) {
229 if (info.handle_id == kInvalidServiceWorkerHandleId)
230 return NULL;
232 WorkerObjectMap::iterator existing_worker =
233 service_workers_.find(info.handle_id);
235 if (existing_worker != service_workers_.end()) {
236 if (adopt_handle) {
237 // We are instructed to adopt a handle but we already have one, so
238 // adopt and destroy a handle ref.
239 ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
241 return existing_worker->second;
244 scoped_ptr<ServiceWorkerHandleReference> handle_ref =
245 adopt_handle
246 ? ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get())
247 : ServiceWorkerHandleReference::Create(info,
248 thread_safe_sender_.get());
249 // WebServiceWorkerImpl constructor calls AddServiceWorker.
250 return new WebServiceWorkerImpl(handle_ref.Pass(), thread_safe_sender_.get());
253 WebServiceWorkerRegistrationImpl*
254 ServiceWorkerDispatcher::FindServiceWorkerRegistration(
255 const ServiceWorkerRegistrationObjectInfo& info,
256 bool adopt_handle) {
257 RegistrationObjectMap::iterator registration =
258 registrations_.find(info.handle_id);
259 if (registration == registrations_.end())
260 return NULL;
261 if (adopt_handle) {
262 // We are instructed to adopt a handle but we already have one, so
263 // adopt and destroy a handle ref.
264 ServiceWorkerRegistrationHandleReference::Adopt(
265 info, thread_safe_sender_.get());
267 return registration->second;
270 WebServiceWorkerRegistrationImpl*
271 ServiceWorkerDispatcher::CreateServiceWorkerRegistration(
272 const ServiceWorkerRegistrationObjectInfo& info,
273 bool adopt_handle) {
274 DCHECK(!FindServiceWorkerRegistration(info, adopt_handle));
275 if (info.handle_id == kInvalidServiceWorkerRegistrationHandleId)
276 return NULL;
278 scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref =
279 adopt_handle ? ServiceWorkerRegistrationHandleReference::Adopt(
280 info, thread_safe_sender_.get())
281 : ServiceWorkerRegistrationHandleReference::Create(
282 info, thread_safe_sender_.get());
284 // WebServiceWorkerRegistrationImpl constructor calls
285 // AddServiceWorkerRegistration.
286 return new WebServiceWorkerRegistrationImpl(handle_ref.Pass());
289 void ServiceWorkerDispatcher::OnAssociateRegistration(
290 int thread_id,
291 int provider_id,
292 const ServiceWorkerRegistrationObjectInfo& info,
293 const ServiceWorkerVersionAttributes& attrs) {
294 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
295 if (provider == provider_contexts_.end())
296 return;
297 provider->second->OnAssociateRegistration(info, attrs);
298 if (attrs.installing.handle_id != kInvalidServiceWorkerHandleId)
299 worker_to_provider_[attrs.installing.handle_id] = provider->second;
300 if (attrs.waiting.handle_id != kInvalidServiceWorkerHandleId)
301 worker_to_provider_[attrs.waiting.handle_id] = provider->second;
302 if (attrs.active.handle_id != kInvalidServiceWorkerHandleId)
303 worker_to_provider_[attrs.active.handle_id] = provider->second;
306 void ServiceWorkerDispatcher::OnDisassociateRegistration(
307 int thread_id,
308 int provider_id) {
309 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
310 if (provider == provider_contexts_.end())
311 return;
312 provider->second->OnDisassociateRegistration();
313 worker_to_provider_.erase(provider->second->installing_handle_id());
314 worker_to_provider_.erase(provider->second->waiting_handle_id());
315 worker_to_provider_.erase(provider->second->active_handle_id());
316 worker_to_provider_.erase(provider->second->controller_handle_id());
319 void ServiceWorkerDispatcher::OnRegistered(
320 int thread_id,
321 int request_id,
322 const ServiceWorkerRegistrationObjectInfo& info,
323 const ServiceWorkerVersionAttributes& attrs) {
324 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
325 "ServiceWorkerDispatcher::RegisterServiceWorker",
326 request_id,
327 "OnRegistered");
328 WebServiceWorkerRegistrationCallbacks* callbacks =
329 pending_registration_callbacks_.Lookup(request_id);
330 DCHECK(callbacks);
331 if (!callbacks)
332 return;
334 callbacks->onSuccess(FindOrCreateRegistration(info, attrs));
335 pending_registration_callbacks_.Remove(request_id);
336 TRACE_EVENT_ASYNC_END0("ServiceWorker",
337 "ServiceWorkerDispatcher::RegisterServiceWorker",
338 request_id);
341 void ServiceWorkerDispatcher::OnUnregistered(int thread_id,
342 int request_id,
343 bool is_success) {
344 WebServiceWorkerUnregistrationCallbacks* callbacks =
345 pending_unregistration_callbacks_.Lookup(request_id);
346 TRACE_EVENT_ASYNC_STEP_INTO0(
347 "ServiceWorker",
348 "ServiceWorkerDispatcher::UnregisterServiceWorker",
349 request_id,
350 "OnUnregistered");
351 DCHECK(callbacks);
352 if (!callbacks)
353 return;
354 callbacks->onSuccess(&is_success);
355 pending_unregistration_callbacks_.Remove(request_id);
356 TRACE_EVENT_ASYNC_END0("ServiceWorker",
357 "ServiceWorkerDispatcher::UnregisterServiceWorker",
358 request_id);
361 void ServiceWorkerDispatcher::OnDidGetRegistration(
362 int thread_id,
363 int request_id,
364 const ServiceWorkerRegistrationObjectInfo& info,
365 const ServiceWorkerVersionAttributes& attrs) {
366 WebServiceWorkerRegistrationCallbacks* callbacks =
367 pending_get_registration_callbacks_.Lookup(request_id);
368 TRACE_EVENT_ASYNC_STEP_INTO0(
369 "ServiceWorker",
370 "ServiceWorkerDispatcher::GetRegistration",
371 request_id,
372 "OnDidGetRegistration");
373 DCHECK(callbacks);
374 if (!callbacks)
375 return;
377 WebServiceWorkerRegistrationImpl* registration = NULL;
378 if (info.handle_id != kInvalidServiceWorkerHandleId)
379 registration = FindOrCreateRegistration(info, attrs);
381 callbacks->onSuccess(registration);
382 pending_get_registration_callbacks_.Remove(request_id);
383 TRACE_EVENT_ASYNC_END0("ServiceWorker",
384 "ServiceWorkerDispatcher::GetRegistration",
385 request_id);
388 void ServiceWorkerDispatcher::OnRegistrationError(
389 int thread_id,
390 int request_id,
391 WebServiceWorkerError::ErrorType error_type,
392 const base::string16& message) {
393 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
394 "ServiceWorkerDispatcher::RegisterServiceWorker",
395 request_id,
396 "OnRegistrationError");
397 WebServiceWorkerRegistrationCallbacks* callbacks =
398 pending_registration_callbacks_.Lookup(request_id);
399 DCHECK(callbacks);
400 if (!callbacks)
401 return;
403 scoped_ptr<WebServiceWorkerError> error(
404 new WebServiceWorkerError(error_type, message));
405 callbacks->onError(error.release());
406 pending_registration_callbacks_.Remove(request_id);
407 TRACE_EVENT_ASYNC_END0("ServiceWorker",
408 "ServiceWorkerDispatcher::RegisterServiceWorker",
409 request_id);
412 void ServiceWorkerDispatcher::OnUnregistrationError(
413 int thread_id,
414 int request_id,
415 WebServiceWorkerError::ErrorType error_type,
416 const base::string16& message) {
417 TRACE_EVENT_ASYNC_STEP_INTO0(
418 "ServiceWorker",
419 "ServiceWorkerDispatcher::UnregisterServiceWorker",
420 request_id,
421 "OnUnregistrationError");
422 WebServiceWorkerUnregistrationCallbacks* callbacks =
423 pending_unregistration_callbacks_.Lookup(request_id);
424 DCHECK(callbacks);
425 if (!callbacks)
426 return;
428 scoped_ptr<WebServiceWorkerError> error(
429 new WebServiceWorkerError(error_type, message));
430 callbacks->onError(error.release());
431 pending_unregistration_callbacks_.Remove(request_id);
432 TRACE_EVENT_ASYNC_END0("ServiceWorker",
433 "ServiceWorkerDispatcher::UnregisterServiceWorker",
434 request_id);
437 void ServiceWorkerDispatcher::OnGetRegistrationError(
438 int thread_id,
439 int request_id,
440 WebServiceWorkerError::ErrorType error_type,
441 const base::string16& message) {
442 TRACE_EVENT_ASYNC_STEP_INTO0(
443 "ServiceWorker",
444 "ServiceWorkerDispatcher::GetRegistration",
445 request_id,
446 "OnGetRegistrationError");
447 WebServiceWorkerGetRegistrationCallbacks* callbacks =
448 pending_get_registration_callbacks_.Lookup(request_id);
449 DCHECK(callbacks);
450 if (!callbacks)
451 return;
453 scoped_ptr<WebServiceWorkerError> error(
454 new WebServiceWorkerError(error_type, message));
455 callbacks->onError(error.release());
456 pending_get_registration_callbacks_.Remove(request_id);
457 TRACE_EVENT_ASYNC_END0("ServiceWorker",
458 "ServiceWorkerDispatcher::GetRegistration",
459 request_id);
462 void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
463 int thread_id,
464 int handle_id,
465 blink::WebServiceWorkerState state) {
466 TRACE_EVENT2("ServiceWorker",
467 "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
468 "Thread ID", thread_id,
469 "State", state);
470 WorkerObjectMap::iterator worker = service_workers_.find(handle_id);
471 if (worker != service_workers_.end())
472 worker->second->OnStateChanged(state);
474 WorkerToProviderMap::iterator provider = worker_to_provider_.find(handle_id);
475 if (provider != worker_to_provider_.end())
476 provider->second->OnServiceWorkerStateChanged(handle_id, state);
479 void ServiceWorkerDispatcher::OnSetVersionAttributes(
480 int thread_id,
481 int provider_id,
482 int registration_handle_id,
483 int changed_mask,
484 const ServiceWorkerVersionAttributes& attributes) {
485 TRACE_EVENT1("ServiceWorker",
486 "ServiceWorkerDispatcher::OnSetVersionAttributes",
487 "Thread ID", thread_id);
488 ChangedVersionAttributesMask mask(changed_mask);
489 if (mask.installing_changed()) {
490 SetInstallingServiceWorker(provider_id,
491 registration_handle_id,
492 attributes.installing);
494 if (mask.waiting_changed()) {
495 SetWaitingServiceWorker(provider_id,
496 registration_handle_id,
497 attributes.waiting);
499 if (mask.active_changed()) {
500 SetActiveServiceWorker(provider_id,
501 registration_handle_id,
502 attributes.active);
503 SetReadyRegistration(provider_id, registration_handle_id);
507 void ServiceWorkerDispatcher::OnUpdateFound(
508 int thread_id,
509 const ServiceWorkerRegistrationObjectInfo& info) {
510 TRACE_EVENT0("ServiceWorker",
511 "ServiceWorkerDispatcher::OnUpdateFound");
512 RegistrationObjectMap::iterator found = registrations_.find(info.handle_id);
513 if (found != registrations_.end())
514 found->second->OnUpdateFound();
517 void ServiceWorkerDispatcher::SetInstallingServiceWorker(
518 int provider_id,
519 int registration_handle_id,
520 const ServiceWorkerObjectInfo& info) {
521 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
522 if (provider != provider_contexts_.end() &&
523 provider->second->registration_handle_id() == registration_handle_id) {
524 int existing_installing_id = provider->second->installing_handle_id();
525 if (existing_installing_id != info.handle_id &&
526 existing_installing_id != kInvalidServiceWorkerHandleId) {
527 WorkerToProviderMap::iterator associated_provider =
528 worker_to_provider_.find(existing_installing_id);
529 DCHECK(associated_provider != worker_to_provider_.end());
530 DCHECK(associated_provider->second->provider_id() == provider_id);
531 worker_to_provider_.erase(associated_provider);
533 provider->second->OnSetInstallingServiceWorker(
534 registration_handle_id, info);
535 if (info.handle_id != kInvalidServiceWorkerHandleId)
536 worker_to_provider_[info.handle_id] = provider->second;
539 RegistrationObjectMap::iterator found =
540 registrations_.find(registration_handle_id);
541 if (found != registrations_.end()) {
542 // Populate the .installing field with the new worker object.
543 found->second->SetInstalling(GetServiceWorker(info, false));
547 void ServiceWorkerDispatcher::SetWaitingServiceWorker(
548 int provider_id,
549 int registration_handle_id,
550 const ServiceWorkerObjectInfo& info) {
551 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
552 if (provider != provider_contexts_.end() &&
553 provider->second->registration_handle_id() == registration_handle_id) {
554 int existing_waiting_id = provider->second->waiting_handle_id();
555 if (existing_waiting_id != info.handle_id &&
556 existing_waiting_id != kInvalidServiceWorkerHandleId) {
557 WorkerToProviderMap::iterator associated_provider =
558 worker_to_provider_.find(existing_waiting_id);
559 DCHECK(associated_provider != worker_to_provider_.end());
560 DCHECK(associated_provider->second->provider_id() == provider_id);
561 worker_to_provider_.erase(associated_provider);
563 provider->second->OnSetWaitingServiceWorker(registration_handle_id, info);
564 if (info.handle_id != kInvalidServiceWorkerHandleId)
565 worker_to_provider_[info.handle_id] = provider->second;
568 RegistrationObjectMap::iterator found =
569 registrations_.find(registration_handle_id);
570 if (found != registrations_.end()) {
571 // Populate the .waiting field with the new worker object.
572 found->second->SetWaiting(GetServiceWorker(info, false));
576 void ServiceWorkerDispatcher::SetActiveServiceWorker(
577 int provider_id,
578 int registration_handle_id,
579 const ServiceWorkerObjectInfo& info) {
580 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
581 if (provider != provider_contexts_.end() &&
582 provider->second->registration_handle_id() == registration_handle_id) {
583 int existing_active_id = provider->second->active_handle_id();
584 if (existing_active_id != info.handle_id &&
585 existing_active_id != kInvalidServiceWorkerHandleId) {
586 WorkerToProviderMap::iterator associated_provider =
587 worker_to_provider_.find(existing_active_id);
588 DCHECK(associated_provider != worker_to_provider_.end());
589 DCHECK(associated_provider->second->provider_id() == provider_id);
590 worker_to_provider_.erase(associated_provider);
592 provider->second->OnSetActiveServiceWorker(registration_handle_id, info);
593 if (info.handle_id != kInvalidServiceWorkerHandleId)
594 worker_to_provider_[info.handle_id] = provider->second;
597 RegistrationObjectMap::iterator found =
598 registrations_.find(registration_handle_id);
599 if (found != registrations_.end()) {
600 // Populate the .active field with the new worker object.
601 found->second->SetActive(GetServiceWorker(info, false));
605 void ServiceWorkerDispatcher::SetReadyRegistration(
606 int provider_id,
607 int registration_handle_id) {
608 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
609 if (provider == provider_contexts_.end() ||
610 provider->second->registration_handle_id() != registration_handle_id ||
611 provider->second->active_handle_id() == kInvalidServiceWorkerHandleId) {
612 return;
615 ScriptClientMap::iterator client = script_clients_.find(provider_id);
616 if (client == script_clients_.end())
617 return;
619 ServiceWorkerRegistrationObjectInfo info =
620 provider->second->registration()->info();
621 WebServiceWorkerRegistrationImpl* registration =
622 FindServiceWorkerRegistration(info, false);
623 if (!registration) {
624 registration = CreateServiceWorkerRegistration(info, false);
625 ServiceWorkerVersionAttributes attrs =
626 provider->second->GetVersionAttributes();
627 registration->SetInstalling(GetServiceWorker(attrs.installing, false));
628 registration->SetWaiting(GetServiceWorker(attrs.waiting, false));
629 registration->SetActive(GetServiceWorker(attrs.active, false));
632 // Resolve the .ready promise with the registration object.
633 client->second->setReadyRegistration(registration);
636 void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
637 int thread_id,
638 int provider_id,
639 const ServiceWorkerObjectInfo& info) {
640 TRACE_EVENT2("ServiceWorker",
641 "ServiceWorkerDispatcher::OnSetControllerServiceWorker",
642 "Thread ID", thread_id,
643 "Provider ID", provider_id);
644 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
645 if (provider != provider_contexts_.end()) {
646 provider->second->OnSetControllerServiceWorker(
647 provider->second->registration_handle_id(), info);
648 worker_to_provider_[info.handle_id] = provider->second;
651 ScriptClientMap::iterator found = script_clients_.find(provider_id);
652 if (found != script_clients_.end()) {
653 // Populate the .controller field with the new worker object.
654 found->second->setController(GetServiceWorker(info, false));
658 void ServiceWorkerDispatcher::OnPostMessage(
659 int thread_id,
660 int provider_id,
661 const base::string16& message,
662 const std::vector<int>& sent_message_port_ids,
663 const std::vector<int>& new_routing_ids) {
664 // Make sure we're on the main document thread. (That must be the only
665 // thread we get this message)
666 DCHECK(ChildThread::current());
667 TRACE_EVENT1("ServiceWorker",
668 "ServiceWorkerDispatcher::OnPostMessage",
669 "Thread ID", thread_id);
671 ScriptClientMap::iterator found = script_clients_.find(provider_id);
672 if (found == script_clients_.end()) {
673 // For now we do no queueing for messages sent to nonexistent / unattached
674 // client.
675 return;
678 std::vector<WebMessagePortChannelImpl*> ports;
679 if (!sent_message_port_ids.empty()) {
680 ports.resize(sent_message_port_ids.size());
681 for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
682 ports[i] = new WebMessagePortChannelImpl(
683 new_routing_ids[i], sent_message_port_ids[i],
684 base::MessageLoopProxy::current());
688 found->second->dispatchMessageEvent(message, ports);
691 void ServiceWorkerDispatcher::AddServiceWorker(
692 int handle_id, WebServiceWorkerImpl* worker) {
693 DCHECK(!ContainsKey(service_workers_, handle_id));
694 service_workers_[handle_id] = worker;
697 void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id) {
698 DCHECK(ContainsKey(service_workers_, handle_id));
699 service_workers_.erase(handle_id);
702 void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
703 int registration_handle_id,
704 WebServiceWorkerRegistrationImpl* registration) {
705 DCHECK(!ContainsKey(registrations_, registration_handle_id));
706 registrations_[registration_handle_id] = registration;
709 void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
710 int registration_handle_id) {
711 DCHECK(ContainsKey(registrations_, registration_handle_id));
712 registrations_.erase(registration_handle_id);
715 WebServiceWorkerRegistrationImpl*
716 ServiceWorkerDispatcher::FindOrCreateRegistration(
717 const ServiceWorkerRegistrationObjectInfo& info,
718 const ServiceWorkerVersionAttributes& attrs) {
719 WebServiceWorkerRegistrationImpl* registration =
720 FindServiceWorkerRegistration(info, true);
721 if (!registration) {
722 registration = CreateServiceWorkerRegistration(info, true);
723 registration->SetInstalling(GetServiceWorker(attrs.installing, true));
724 registration->SetWaiting(GetServiceWorker(attrs.waiting, true));
725 registration->SetActive(GetServiceWorker(attrs.active, true));
726 } else {
727 // |registration| must already have version attributes, so adopt and destroy
728 // handle refs for them.
729 ServiceWorkerHandleReference::Adopt(
730 attrs.installing, thread_safe_sender_.get());
731 ServiceWorkerHandleReference::Adopt(
732 attrs.waiting, thread_safe_sender_.get());
733 ServiceWorkerHandleReference::Adopt(
734 attrs.active, thread_safe_sender_.get());
736 return registration;
739 } // namespace content