[Android] Implement 3-way sensor fallback for Device Orientation.
[chromium-blink-merge.git] / content / child / service_worker / service_worker_dispatcher.cc
blob4fd5de13d42ecdb6f2709c7627751fc3035de5a1
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/single_thread_task_runner.h"
9 #include "base/stl_util.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/threading/thread_local.h"
12 #include "base/trace_event/trace_event.h"
13 #include "content/child/child_thread_impl.h"
14 #include "content/child/service_worker/service_worker_handle_reference.h"
15 #include "content/child/service_worker/service_worker_provider_context.h"
16 #include "content/child/service_worker/service_worker_registration_handle_reference.h"
17 #include "content/child/service_worker/web_service_worker_impl.h"
18 #include "content/child/service_worker/web_service_worker_registration_impl.h"
19 #include "content/child/thread_safe_sender.h"
20 #include "content/child/webmessageportchannel_impl.h"
21 #include "content/common/service_worker/service_worker_messages.h"
22 #include "content/common/service_worker/service_worker_types.h"
23 #include "content/public/common/url_utils.h"
24 #include "third_party/WebKit/public/platform/WebString.h"
25 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerClientsInfo.h"
26 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerProviderClient.h"
27 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
29 using blink::WebServiceWorkerError;
30 using blink::WebServiceWorkerProvider;
31 using base::ThreadLocalPointer;
33 namespace content {
35 namespace {
37 base::LazyInstance<ThreadLocalPointer<void>>::Leaky g_dispatcher_tls =
38 LAZY_INSTANCE_INITIALIZER;
40 void* const kHasBeenDeleted = reinterpret_cast<void*>(0x1);
42 int CurrentWorkerId() {
43 return WorkerTaskRunner::Instance()->CurrentWorkerId();
46 } // namespace
48 ServiceWorkerDispatcher::ServiceWorkerDispatcher(
49 ThreadSafeSender* thread_safe_sender,
50 base::SingleThreadTaskRunner* main_thread_task_runner)
51 : thread_safe_sender_(thread_safe_sender),
52 main_thread_task_runner_(main_thread_task_runner) {
53 g_dispatcher_tls.Pointer()->Set(static_cast<void*>(this));
56 ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
57 g_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
60 void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message& msg) {
61 bool handled = true;
62 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher, msg)
63 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistrationWithServiceWorker,
64 OnAssociateRegistrationWithServiceWorker)
65 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistration,
66 OnAssociateRegistration)
67 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DisassociateRegistration,
68 OnDisassociateRegistration)
69 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered, OnRegistered)
70 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUpdated, OnUpdated)
71 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered,
72 OnUnregistered)
73 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistration,
74 OnDidGetRegistration)
75 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistrations,
76 OnDidGetRegistrations)
77 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistrationForReady,
78 OnDidGetRegistrationForReady)
79 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError,
80 OnRegistrationError)
81 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUpdateError,
82 OnUpdateError)
83 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistrationError,
84 OnUnregistrationError)
85 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationError,
86 OnGetRegistrationError)
87 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationsError,
88 OnGetRegistrationsError)
89 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged,
90 OnServiceWorkerStateChanged)
91 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes,
92 OnSetVersionAttributes)
93 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_UpdateFound,
94 OnUpdateFound)
95 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker,
96 OnSetControllerServiceWorker)
97 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument,
98 OnPostMessage)
99 IPC_MESSAGE_UNHANDLED(handled = false)
100 IPC_END_MESSAGE_MAP()
101 DCHECK(handled) << "Unhandled message:" << msg.type();
104 bool ServiceWorkerDispatcher::Send(IPC::Message* msg) {
105 return thread_safe_sender_->Send(msg);
108 void ServiceWorkerDispatcher::RegisterServiceWorker(
109 int provider_id,
110 const GURL& pattern,
111 const GURL& script_url,
112 WebServiceWorkerRegistrationCallbacks* callbacks) {
113 DCHECK(callbacks);
115 if (pattern.possibly_invalid_spec().size() > GetMaxURLChars() ||
116 script_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
117 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
118 owned_callbacks(callbacks);
119 std::string error_message(kServiceWorkerRegisterErrorPrefix);
120 error_message += "The provided scriptURL or scope is too long.";
121 callbacks->onError(
122 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity,
123 blink::WebString::fromUTF8(error_message)));
124 return;
127 int request_id = pending_registration_callbacks_.Add(callbacks);
128 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
129 "ServiceWorkerDispatcher::RegisterServiceWorker",
130 request_id,
131 "Scope", pattern.spec(),
132 "Script URL", script_url.spec());
133 thread_safe_sender_->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
134 CurrentWorkerId(), request_id, provider_id, pattern, script_url));
137 void ServiceWorkerDispatcher::UpdateServiceWorker(
138 int provider_id,
139 int64 registration_id,
140 WebServiceWorkerUpdateCallbacks* callbacks) {
141 DCHECK(callbacks);
142 int request_id = pending_update_callbacks_.Add(callbacks);
143 thread_safe_sender_->Send(new ServiceWorkerHostMsg_UpdateServiceWorker(
144 CurrentWorkerId(), request_id, provider_id, registration_id));
147 void ServiceWorkerDispatcher::UnregisterServiceWorker(
148 int provider_id,
149 int64 registration_id,
150 WebServiceWorkerUnregistrationCallbacks* callbacks) {
151 DCHECK(callbacks);
152 int request_id = pending_unregistration_callbacks_.Add(callbacks);
153 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
154 "ServiceWorkerDispatcher::UnregisterServiceWorker",
155 request_id, "Registration ID", registration_id);
156 thread_safe_sender_->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
157 CurrentWorkerId(), request_id, provider_id, registration_id));
160 void ServiceWorkerDispatcher::GetRegistration(
161 int provider_id,
162 const GURL& document_url,
163 WebServiceWorkerRegistrationCallbacks* callbacks) {
164 DCHECK(callbacks);
166 if (document_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
167 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
168 owned_callbacks(callbacks);
169 std::string error_message(kServiceWorkerGetRegistrationErrorPrefix);
170 error_message += "The provided documentURL is too long.";
171 callbacks->onError(
172 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity,
173 blink::WebString::fromUTF8(error_message)));
174 return;
177 int request_id = pending_get_registration_callbacks_.Add(callbacks);
178 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
179 "ServiceWorkerDispatcher::GetRegistration",
180 request_id,
181 "Document URL", document_url.spec());
182 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistration(
183 CurrentWorkerId(), request_id, provider_id, document_url));
186 void ServiceWorkerDispatcher::GetRegistrations(
187 int provider_id,
188 WebServiceWorkerGetRegistrationsCallbacks* callbacks) {
189 DCHECK(callbacks);
191 int request_id = pending_get_registrations_callbacks_.Add(callbacks);
192 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
193 "ServiceWorkerDispatcher::GetRegistrations",
194 request_id);
195 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistrations(
196 CurrentWorkerId(), request_id, provider_id));
199 void ServiceWorkerDispatcher::GetRegistrationForReady(
200 int provider_id,
201 WebServiceWorkerGetRegistrationForReadyCallbacks* callbacks) {
202 int request_id = get_for_ready_callbacks_.Add(callbacks);
203 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
204 "ServiceWorkerDispatcher::GetRegistrationForReady",
205 request_id);
206 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistrationForReady(
207 CurrentWorkerId(), request_id, provider_id));
210 void ServiceWorkerDispatcher::AddProviderContext(
211 ServiceWorkerProviderContext* provider_context) {
212 DCHECK(provider_context);
213 int provider_id = provider_context->provider_id();
214 DCHECK(!ContainsKey(provider_contexts_, provider_id));
215 provider_contexts_[provider_id] = provider_context;
218 void ServiceWorkerDispatcher::RemoveProviderContext(
219 ServiceWorkerProviderContext* provider_context) {
220 DCHECK(provider_context);
221 DCHECK(ContainsKey(provider_contexts_, provider_context->provider_id()));
222 provider_contexts_.erase(provider_context->provider_id());
223 worker_to_provider_.erase(provider_context->installing_handle_id());
224 worker_to_provider_.erase(provider_context->waiting_handle_id());
225 worker_to_provider_.erase(provider_context->active_handle_id());
226 worker_to_provider_.erase(provider_context->controller_handle_id());
229 void ServiceWorkerDispatcher::AddProviderClient(
230 int provider_id,
231 blink::WebServiceWorkerProviderClient* client) {
232 DCHECK(client);
233 DCHECK(!ContainsKey(provider_clients_, provider_id));
234 provider_clients_[provider_id] = client;
237 void ServiceWorkerDispatcher::RemoveProviderClient(int provider_id) {
238 // This could be possibly called multiple times to ensure termination.
239 if (ContainsKey(provider_clients_, provider_id))
240 provider_clients_.erase(provider_id);
243 ServiceWorkerDispatcher*
244 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
245 ThreadSafeSender* thread_safe_sender,
246 base::SingleThreadTaskRunner* main_thread_task_runner) {
247 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
248 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
249 g_dispatcher_tls.Pointer()->Set(NULL);
251 if (g_dispatcher_tls.Pointer()->Get())
252 return static_cast<ServiceWorkerDispatcher*>(
253 g_dispatcher_tls.Pointer()->Get());
255 ServiceWorkerDispatcher* dispatcher =
256 new ServiceWorkerDispatcher(thread_safe_sender, main_thread_task_runner);
257 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
258 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
259 return dispatcher;
262 ServiceWorkerDispatcher* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
263 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted)
264 return NULL;
265 return static_cast<ServiceWorkerDispatcher*>(
266 g_dispatcher_tls.Pointer()->Get());
269 void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
270 delete this;
273 WebServiceWorkerImpl* ServiceWorkerDispatcher::GetServiceWorker(
274 const ServiceWorkerObjectInfo& info,
275 bool adopt_handle) {
276 if (info.handle_id == kInvalidServiceWorkerHandleId)
277 return NULL;
279 WorkerObjectMap::iterator existing_worker =
280 service_workers_.find(info.handle_id);
282 if (existing_worker != service_workers_.end()) {
283 if (adopt_handle) {
284 // We are instructed to adopt a handle but we already have one, so
285 // adopt and destroy a handle ref.
286 ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
288 return existing_worker->second;
291 scoped_ptr<ServiceWorkerHandleReference> handle_ref =
292 adopt_handle
293 ? ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get())
294 : ServiceWorkerHandleReference::Create(info,
295 thread_safe_sender_.get());
296 // WebServiceWorkerImpl constructor calls AddServiceWorker.
297 return new WebServiceWorkerImpl(handle_ref.Pass(), thread_safe_sender_.get());
300 WebServiceWorkerRegistrationImpl*
301 ServiceWorkerDispatcher::CreateServiceWorkerRegistration(
302 const ServiceWorkerRegistrationObjectInfo& info,
303 bool adopt_handle) {
304 DCHECK(!ContainsKey(registrations_, info.handle_id));
305 if (info.handle_id == kInvalidServiceWorkerRegistrationHandleId)
306 return NULL;
308 scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref =
309 adopt_handle ? ServiceWorkerRegistrationHandleReference::Adopt(
310 info, thread_safe_sender_.get())
311 : ServiceWorkerRegistrationHandleReference::Create(
312 info, thread_safe_sender_.get());
314 // WebServiceWorkerRegistrationImpl constructor calls
315 // AddServiceWorkerRegistration.
316 return new WebServiceWorkerRegistrationImpl(handle_ref.Pass());
319 // We can assume that this message handler is called before the worker context
320 // starts because script loading happens after this association.
321 // TODO(nhiroki): This association information could be pushed into
322 // EmbeddedWorkerMsg_StartWorker message and handed over to the worker thread
323 // without a lock in ServiceWorkerProviderContext.
324 void ServiceWorkerDispatcher::OnAssociateRegistrationWithServiceWorker(
325 int thread_id,
326 int provider_id,
327 const ServiceWorkerRegistrationObjectInfo& info,
328 const ServiceWorkerVersionAttributes& attrs) {
329 DCHECK_EQ(kDocumentMainThreadId, thread_id);
331 ProviderContextMap::iterator context = provider_contexts_.find(provider_id);
332 if (context == provider_contexts_.end())
333 return;
334 context->second->OnAssociateRegistration(info, attrs);
336 // We don't have to add entries into |worker_to_provider_| because state
337 // change events for the workers will be notified on the worker thread.
340 void ServiceWorkerDispatcher::OnAssociateRegistration(
341 int thread_id,
342 int provider_id,
343 const ServiceWorkerRegistrationObjectInfo& info,
344 const ServiceWorkerVersionAttributes& attrs) {
345 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
346 if (provider == provider_contexts_.end())
347 return;
348 provider->second->OnAssociateRegistration(info, attrs);
349 if (attrs.installing.handle_id != kInvalidServiceWorkerHandleId)
350 worker_to_provider_[attrs.installing.handle_id] = provider->second;
351 if (attrs.waiting.handle_id != kInvalidServiceWorkerHandleId)
352 worker_to_provider_[attrs.waiting.handle_id] = provider->second;
353 if (attrs.active.handle_id != kInvalidServiceWorkerHandleId)
354 worker_to_provider_[attrs.active.handle_id] = provider->second;
357 void ServiceWorkerDispatcher::OnDisassociateRegistration(
358 int thread_id,
359 int provider_id) {
360 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
361 if (provider == provider_contexts_.end())
362 return;
363 worker_to_provider_.erase(provider->second->installing_handle_id());
364 worker_to_provider_.erase(provider->second->waiting_handle_id());
365 worker_to_provider_.erase(provider->second->active_handle_id());
366 worker_to_provider_.erase(provider->second->controller_handle_id());
367 provider->second->OnDisassociateRegistration();
370 void ServiceWorkerDispatcher::OnRegistered(
371 int thread_id,
372 int request_id,
373 const ServiceWorkerRegistrationObjectInfo& info,
374 const ServiceWorkerVersionAttributes& attrs) {
375 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
376 "ServiceWorkerDispatcher::RegisterServiceWorker",
377 request_id,
378 "OnRegistered");
379 TRACE_EVENT_ASYNC_END0("ServiceWorker",
380 "ServiceWorkerDispatcher::RegisterServiceWorker",
381 request_id);
382 WebServiceWorkerRegistrationCallbacks* callbacks =
383 pending_registration_callbacks_.Lookup(request_id);
384 DCHECK(callbacks);
385 if (!callbacks)
386 return;
388 callbacks->onSuccess(FindOrCreateRegistration(info, attrs));
389 pending_registration_callbacks_.Remove(request_id);
392 void ServiceWorkerDispatcher::OnUpdated(int thread_id, int request_id) {
393 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
394 "ServiceWorkerDispatcher::UpdateServiceWorker",
395 request_id, "OnUpdated");
396 TRACE_EVENT_ASYNC_END0("ServiceWorker",
397 "ServiceWorkerDispatcher::UpdateServiceWorker",
398 request_id);
399 WebServiceWorkerUpdateCallbacks* callbacks =
400 pending_update_callbacks_.Lookup(request_id);
401 DCHECK(callbacks);
402 if (!callbacks)
403 return;
405 callbacks->onSuccess();
406 pending_update_callbacks_.Remove(request_id);
409 void ServiceWorkerDispatcher::OnUnregistered(int thread_id,
410 int request_id,
411 bool is_success) {
412 TRACE_EVENT_ASYNC_STEP_INTO0(
413 "ServiceWorker",
414 "ServiceWorkerDispatcher::UnregisterServiceWorker",
415 request_id,
416 "OnUnregistered");
417 TRACE_EVENT_ASYNC_END0("ServiceWorker",
418 "ServiceWorkerDispatcher::UnregisterServiceWorker",
419 request_id);
420 WebServiceWorkerUnregistrationCallbacks* callbacks =
421 pending_unregistration_callbacks_.Lookup(request_id);
422 DCHECK(callbacks);
423 if (!callbacks)
424 return;
425 callbacks->onSuccess(is_success);
426 pending_unregistration_callbacks_.Remove(request_id);
429 void ServiceWorkerDispatcher::OnDidGetRegistration(
430 int thread_id,
431 int request_id,
432 const ServiceWorkerRegistrationObjectInfo& info,
433 const ServiceWorkerVersionAttributes& attrs) {
434 TRACE_EVENT_ASYNC_STEP_INTO0(
435 "ServiceWorker",
436 "ServiceWorkerDispatcher::GetRegistration",
437 request_id,
438 "OnDidGetRegistration");
439 TRACE_EVENT_ASYNC_END0("ServiceWorker",
440 "ServiceWorkerDispatcher::GetRegistration",
441 request_id);
442 WebServiceWorkerRegistrationCallbacks* callbacks =
443 pending_get_registration_callbacks_.Lookup(request_id);
444 DCHECK(callbacks);
445 if (!callbacks)
446 return;
448 WebServiceWorkerRegistrationImpl* registration = NULL;
449 if (info.handle_id != kInvalidServiceWorkerHandleId)
450 registration = FindOrCreateRegistration(info, attrs);
452 callbacks->onSuccess(registration);
453 pending_get_registration_callbacks_.Remove(request_id);
456 void ServiceWorkerDispatcher::OnDidGetRegistrations(
457 int thread_id,
458 int request_id,
459 const std::vector<ServiceWorkerRegistrationObjectInfo>& infos,
460 const std::vector<ServiceWorkerVersionAttributes>& attrs) {
461 TRACE_EVENT_ASYNC_STEP_INTO0(
462 "ServiceWorker",
463 "ServiceWorkerDispatcher::GetRegistrations",
464 request_id,
465 "OnDidGetRegistrations");
466 TRACE_EVENT_ASYNC_END0("ServiceWorker",
467 "ServiceWorkerDispatcher::GetRegistrations",
468 request_id);
470 WebServiceWorkerGetRegistrationsCallbacks* callbacks =
471 pending_get_registrations_callbacks_.Lookup(request_id);
472 DCHECK(callbacks);
473 if (!callbacks)
474 return;
476 typedef blink::WebVector<blink::WebServiceWorkerRegistration*>
477 WebServiceWorkerRegistrationArray;
478 WebServiceWorkerRegistrationArray* registrations =
479 new WebServiceWorkerRegistrationArray(infos.size());
480 for (size_t i = 0; i < infos.size(); ++i) {
481 if (infos[i].handle_id != kInvalidServiceWorkerHandleId) {
482 ServiceWorkerRegistrationObjectInfo info(infos[i]);
483 ServiceWorkerVersionAttributes attr(attrs[i]);
484 (*registrations)[i] = FindOrCreateRegistration(info, attr);
488 callbacks->onSuccess(registrations);
489 pending_get_registrations_callbacks_.Remove(request_id);
492 void ServiceWorkerDispatcher::OnDidGetRegistrationForReady(
493 int thread_id,
494 int request_id,
495 const ServiceWorkerRegistrationObjectInfo& info,
496 const ServiceWorkerVersionAttributes& attrs) {
497 TRACE_EVENT_ASYNC_STEP_INTO0(
498 "ServiceWorker",
499 "ServiceWorkerDispatcher::GetRegistrationForReady",
500 request_id,
501 "OnDidGetRegistrationForReady");
502 TRACE_EVENT_ASYNC_END0("ServiceWorker",
503 "ServiceWorkerDispatcher::GetRegistrationForReady",
504 request_id);
505 WebServiceWorkerGetRegistrationForReadyCallbacks* callbacks =
506 get_for_ready_callbacks_.Lookup(request_id);
507 DCHECK(callbacks);
508 if (!callbacks)
509 return;
511 WebServiceWorkerRegistrationImpl* registration = NULL;
512 DCHECK(info.handle_id != kInvalidServiceWorkerHandleId);
513 registration = FindOrCreateRegistration(info, attrs);
514 callbacks->onSuccess(registration);
515 get_for_ready_callbacks_.Remove(request_id);
518 void ServiceWorkerDispatcher::OnRegistrationError(
519 int thread_id,
520 int request_id,
521 WebServiceWorkerError::ErrorType error_type,
522 const base::string16& message) {
523 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
524 "ServiceWorkerDispatcher::RegisterServiceWorker",
525 request_id,
526 "OnRegistrationError");
527 TRACE_EVENT_ASYNC_END0("ServiceWorker",
528 "ServiceWorkerDispatcher::RegisterServiceWorker",
529 request_id);
530 WebServiceWorkerRegistrationCallbacks* callbacks =
531 pending_registration_callbacks_.Lookup(request_id);
532 DCHECK(callbacks);
533 if (!callbacks)
534 return;
536 callbacks->onError(new WebServiceWorkerError(error_type, message));
537 pending_registration_callbacks_.Remove(request_id);
540 void ServiceWorkerDispatcher::OnUpdateError(
541 int thread_id,
542 int request_id,
543 WebServiceWorkerError::ErrorType error_type,
544 const base::string16& message) {
545 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
546 "ServiceWorkerDispatcher::UpdateServiceWorker",
547 request_id, "OnUpdateError");
548 TRACE_EVENT_ASYNC_END0("ServiceWorker",
549 "ServiceWorkerDispatcher::UpdateServiceWorker",
550 request_id);
551 WebServiceWorkerUpdateCallbacks* callbacks =
552 pending_update_callbacks_.Lookup(request_id);
553 DCHECK(callbacks);
554 if (!callbacks)
555 return;
557 callbacks->onError(WebServiceWorkerError(error_type, message));
558 pending_update_callbacks_.Remove(request_id);
561 void ServiceWorkerDispatcher::OnUnregistrationError(
562 int thread_id,
563 int request_id,
564 WebServiceWorkerError::ErrorType error_type,
565 const base::string16& message) {
566 TRACE_EVENT_ASYNC_STEP_INTO0(
567 "ServiceWorker",
568 "ServiceWorkerDispatcher::UnregisterServiceWorker",
569 request_id,
570 "OnUnregistrationError");
571 TRACE_EVENT_ASYNC_END0("ServiceWorker",
572 "ServiceWorkerDispatcher::UnregisterServiceWorker",
573 request_id);
574 WebServiceWorkerUnregistrationCallbacks* callbacks =
575 pending_unregistration_callbacks_.Lookup(request_id);
576 DCHECK(callbacks);
577 if (!callbacks)
578 return;
580 callbacks->onError(WebServiceWorkerError(error_type, message));
581 pending_unregistration_callbacks_.Remove(request_id);
584 void ServiceWorkerDispatcher::OnGetRegistrationError(
585 int thread_id,
586 int request_id,
587 WebServiceWorkerError::ErrorType error_type,
588 const base::string16& message) {
589 TRACE_EVENT_ASYNC_STEP_INTO0(
590 "ServiceWorker",
591 "ServiceWorkerDispatcher::GetRegistration",
592 request_id,
593 "OnGetRegistrationError");
594 TRACE_EVENT_ASYNC_END0("ServiceWorker",
595 "ServiceWorkerDispatcher::GetRegistration",
596 request_id);
597 WebServiceWorkerGetRegistrationCallbacks* callbacks =
598 pending_get_registration_callbacks_.Lookup(request_id);
599 DCHECK(callbacks);
600 if (!callbacks)
601 return;
603 callbacks->onError(new WebServiceWorkerError(error_type, message));
604 pending_get_registration_callbacks_.Remove(request_id);
607 void ServiceWorkerDispatcher::OnGetRegistrationsError(
608 int thread_id,
609 int request_id,
610 WebServiceWorkerError::ErrorType error_type,
611 const base::string16& message) {
612 TRACE_EVENT_ASYNC_STEP_INTO0(
613 "ServiceWorker",
614 "ServiceWorkerDispatcher::GetRegistrations",
615 request_id,
616 "OnGetRegistrationsError");
617 TRACE_EVENT_ASYNC_END0("ServiceWorker",
618 "ServiceWorkerDispatcher::GetRegistrations",
619 request_id);
620 WebServiceWorkerGetRegistrationsCallbacks* callbacks =
621 pending_get_registrations_callbacks_.Lookup(request_id);
622 DCHECK(callbacks);
623 if (!callbacks)
624 return;
626 callbacks->onError(new WebServiceWorkerError(error_type, message));
627 pending_get_registrations_callbacks_.Remove(request_id);
630 void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
631 int thread_id,
632 int handle_id,
633 blink::WebServiceWorkerState state) {
634 TRACE_EVENT2("ServiceWorker",
635 "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
636 "Thread ID", thread_id,
637 "State", state);
638 WorkerObjectMap::iterator worker = service_workers_.find(handle_id);
639 if (worker != service_workers_.end())
640 worker->second->OnStateChanged(state);
642 WorkerToProviderMap::iterator provider = worker_to_provider_.find(handle_id);
643 if (provider != worker_to_provider_.end())
644 provider->second->OnServiceWorkerStateChanged(handle_id, state);
647 void ServiceWorkerDispatcher::OnSetVersionAttributes(
648 int thread_id,
649 int provider_id,
650 int registration_handle_id,
651 int changed_mask,
652 const ServiceWorkerVersionAttributes& attrs) {
653 TRACE_EVENT1("ServiceWorker",
654 "ServiceWorkerDispatcher::OnSetVersionAttributes",
655 "Thread ID", thread_id);
657 ChangedVersionAttributesMask mask(changed_mask);
658 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
659 if (provider != provider_contexts_.end() &&
660 provider->second->registration_handle_id() == registration_handle_id) {
661 if (mask.installing_changed()) {
662 worker_to_provider_.erase(provider->second->installing_handle_id());
663 if (attrs.installing.handle_id != kInvalidServiceWorkerHandleId)
664 worker_to_provider_[attrs.installing.handle_id] = provider->second;
666 if (mask.waiting_changed()) {
667 worker_to_provider_.erase(provider->second->waiting_handle_id());
668 if (attrs.waiting.handle_id != kInvalidServiceWorkerHandleId)
669 worker_to_provider_[attrs.waiting.handle_id] = provider->second;
671 if (mask.active_changed()) {
672 worker_to_provider_.erase(provider->second->active_handle_id());
673 if (attrs.active.handle_id != kInvalidServiceWorkerHandleId)
674 worker_to_provider_[attrs.active.handle_id] = provider->second;
676 provider->second->SetVersionAttributes(mask, attrs);
679 RegistrationObjectMap::iterator found =
680 registrations_.find(registration_handle_id);
681 if (found != registrations_.end()) {
682 // Populate the version fields (eg. .installing) with new worker objects.
683 if (mask.installing_changed())
684 found->second->SetInstalling(GetServiceWorker(attrs.installing, false));
685 if (mask.waiting_changed())
686 found->second->SetWaiting(GetServiceWorker(attrs.waiting, false));
687 if (mask.active_changed())
688 found->second->SetActive(GetServiceWorker(attrs.active, false));
692 void ServiceWorkerDispatcher::OnUpdateFound(
693 int thread_id,
694 int registration_handle_id) {
695 TRACE_EVENT0("ServiceWorker",
696 "ServiceWorkerDispatcher::OnUpdateFound");
697 RegistrationObjectMap::iterator found =
698 registrations_.find(registration_handle_id);
699 if (found != registrations_.end())
700 found->second->OnUpdateFound();
703 void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
704 int thread_id,
705 int provider_id,
706 const ServiceWorkerObjectInfo& info,
707 bool should_notify_controllerchange) {
708 TRACE_EVENT2("ServiceWorker",
709 "ServiceWorkerDispatcher::OnSetControllerServiceWorker",
710 "Thread ID", thread_id,
711 "Provider ID", provider_id);
713 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
714 if (provider != provider_contexts_.end()) {
715 worker_to_provider_.erase(provider->second->controller_handle_id());
716 if (info.handle_id != kInvalidServiceWorkerHandleId)
717 worker_to_provider_[info.handle_id] = provider->second;
718 provider->second->OnSetControllerServiceWorker(info);
721 ProviderClientMap::iterator found = provider_clients_.find(provider_id);
722 if (found != provider_clients_.end()) {
723 // Populate the .controller field with the new worker object.
724 found->second->setController(GetServiceWorker(info, false),
725 should_notify_controllerchange);
729 void ServiceWorkerDispatcher::OnPostMessage(
730 const ServiceWorkerMsg_MessageToDocument_Params& params) {
731 // Make sure we're on the main document thread. (That must be the only
732 // thread we get this message)
733 DCHECK(ChildThreadImpl::current());
734 TRACE_EVENT1("ServiceWorker", "ServiceWorkerDispatcher::OnPostMessage",
735 "Thread ID", params.thread_id);
737 ProviderClientMap::iterator found =
738 provider_clients_.find(params.provider_id);
739 if (found == provider_clients_.end()) {
740 // For now we do no queueing for messages sent to nonexistent / unattached
741 // client.
742 return;
745 blink::WebMessagePortChannelArray ports =
746 WebMessagePortChannelImpl::CreatePorts(
747 params.message_ports, params.new_routing_ids,
748 base::ThreadTaskRunnerHandle::Get());
750 found->second->dispatchMessageEvent(
751 GetServiceWorker(params.service_worker_info, false /* adopt_handle */),
752 params.message, ports);
755 void ServiceWorkerDispatcher::AddServiceWorker(
756 int handle_id, WebServiceWorkerImpl* worker) {
757 DCHECK(!ContainsKey(service_workers_, handle_id));
758 service_workers_[handle_id] = worker;
761 void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id) {
762 DCHECK(ContainsKey(service_workers_, handle_id));
763 service_workers_.erase(handle_id);
766 void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
767 int registration_handle_id,
768 WebServiceWorkerRegistrationImpl* registration) {
769 DCHECK(!ContainsKey(registrations_, registration_handle_id));
770 registrations_[registration_handle_id] = registration;
773 void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
774 int registration_handle_id) {
775 DCHECK(ContainsKey(registrations_, registration_handle_id));
776 registrations_.erase(registration_handle_id);
779 WebServiceWorkerRegistrationImpl*
780 ServiceWorkerDispatcher::FindOrCreateRegistration(
781 const ServiceWorkerRegistrationObjectInfo& info,
782 const ServiceWorkerVersionAttributes& attrs) {
783 RegistrationObjectMap::iterator found = registrations_.find(info.handle_id);
784 if (found != registrations_.end()) {
785 ServiceWorkerRegistrationHandleReference::Adopt(info,
786 thread_safe_sender_.get());
787 ServiceWorkerHandleReference::Adopt(attrs.installing,
788 thread_safe_sender_.get());
789 ServiceWorkerHandleReference::Adopt(attrs.waiting,
790 thread_safe_sender_.get());
791 ServiceWorkerHandleReference::Adopt(attrs.active,
792 thread_safe_sender_.get());
793 return found->second;
796 bool adopt_handle = true;
797 WebServiceWorkerRegistrationImpl* registration =
798 CreateServiceWorkerRegistration(info, adopt_handle);
799 registration->SetInstalling(GetServiceWorker(attrs.installing, adopt_handle));
800 registration->SetWaiting(GetServiceWorker(attrs.waiting, adopt_handle));
801 registration->SetActive(GetServiceWorker(attrs.active, adopt_handle));
802 return registration;
805 } // namespace content