Upstreaming browser/ui/uikit_ui_util from iOS.
[chromium-blink-merge.git] / content / child / service_worker / service_worker_dispatcher.cc
blob1a8244258aff252e023658906df5b8b7678b4f08
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/WebServiceWorkerClientsInfo.h"
25 #include "third_party/WebKit/public/platform/WebServiceWorkerProviderClient.h"
26 #include "third_party/WebKit/public/platform/WebString.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<ServiceWorkerDispatcher> >::Leaky
38 g_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
40 ServiceWorkerDispatcher* const kHasBeenDeleted =
41 reinterpret_cast<ServiceWorkerDispatcher*>(0x1);
43 int CurrentWorkerId() {
44 return WorkerTaskRunner::Instance()->CurrentWorkerId();
47 } // namespace
49 ServiceWorkerDispatcher::ServiceWorkerDispatcher(
50 ThreadSafeSender* thread_safe_sender,
51 base::SingleThreadTaskRunner* main_thread_task_runner)
52 : thread_safe_sender_(thread_safe_sender),
53 main_thread_task_runner_(main_thread_task_runner) {
54 g_dispatcher_tls.Pointer()->Set(this);
57 ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
58 g_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
61 void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message& msg) {
62 bool handled = true;
63 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher, msg)
64 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistrationWithServiceWorker,
65 OnAssociateRegistrationWithServiceWorker)
66 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistration,
67 OnAssociateRegistration)
68 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DisassociateRegistration,
69 OnDisassociateRegistration)
70 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered, OnRegistered)
71 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUpdated, OnUpdated)
72 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered,
73 OnUnregistered)
74 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistration,
75 OnDidGetRegistration)
76 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistrations,
77 OnDidGetRegistrations)
78 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistrationForReady,
79 OnDidGetRegistrationForReady)
80 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError,
81 OnRegistrationError)
82 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUpdateError,
83 OnUpdateError)
84 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistrationError,
85 OnUnregistrationError)
86 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationError,
87 OnGetRegistrationError)
88 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationsError,
89 OnGetRegistrationsError)
90 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged,
91 OnServiceWorkerStateChanged)
92 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes,
93 OnSetVersionAttributes)
94 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_UpdateFound,
95 OnUpdateFound)
96 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker,
97 OnSetControllerServiceWorker)
98 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument,
99 OnPostMessage)
100 IPC_MESSAGE_UNHANDLED(handled = false)
101 IPC_END_MESSAGE_MAP()
102 DCHECK(handled) << "Unhandled message:" << msg.type();
105 bool ServiceWorkerDispatcher::Send(IPC::Message* msg) {
106 return thread_safe_sender_->Send(msg);
109 void ServiceWorkerDispatcher::RegisterServiceWorker(
110 int provider_id,
111 const GURL& pattern,
112 const GURL& script_url,
113 WebServiceWorkerRegistrationCallbacks* callbacks) {
114 DCHECK(callbacks);
116 if (pattern.possibly_invalid_spec().size() > GetMaxURLChars() ||
117 script_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
118 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
119 owned_callbacks(callbacks);
120 std::string error_message(kServiceWorkerRegisterErrorPrefix);
121 error_message += "The provided scriptURL or scope is too long.";
122 scoped_ptr<WebServiceWorkerError> error(
123 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity,
124 blink::WebString::fromUTF8(error_message)));
125 callbacks->onError(error.release());
126 return;
129 int request_id = pending_registration_callbacks_.Add(callbacks);
130 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
131 "ServiceWorkerDispatcher::RegisterServiceWorker",
132 request_id,
133 "Scope", pattern.spec(),
134 "Script URL", script_url.spec());
135 thread_safe_sender_->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
136 CurrentWorkerId(), request_id, provider_id, pattern, script_url));
139 void ServiceWorkerDispatcher::UpdateServiceWorker(
140 int provider_id,
141 int64 registration_id,
142 WebServiceWorkerUpdateCallbacks* callbacks) {
143 DCHECK(callbacks);
144 int request_id = pending_update_callbacks_.Add(callbacks);
145 thread_safe_sender_->Send(new ServiceWorkerHostMsg_UpdateServiceWorker(
146 CurrentWorkerId(), request_id, provider_id, registration_id));
149 void ServiceWorkerDispatcher::UnregisterServiceWorker(
150 int provider_id,
151 int64 registration_id,
152 WebServiceWorkerUnregistrationCallbacks* callbacks) {
153 DCHECK(callbacks);
154 int request_id = pending_unregistration_callbacks_.Add(callbacks);
155 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
156 "ServiceWorkerDispatcher::UnregisterServiceWorker",
157 request_id, "Registration ID", registration_id);
158 thread_safe_sender_->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
159 CurrentWorkerId(), request_id, provider_id, registration_id));
162 void ServiceWorkerDispatcher::GetRegistration(
163 int provider_id,
164 const GURL& document_url,
165 WebServiceWorkerRegistrationCallbacks* callbacks) {
166 DCHECK(callbacks);
168 if (document_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
169 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
170 owned_callbacks(callbacks);
171 std::string error_message(kServiceWorkerGetRegistrationErrorPrefix);
172 error_message += "The provided documentURL is too long.";
173 scoped_ptr<WebServiceWorkerError> error(
174 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity,
175 blink::WebString::fromUTF8(error_message)));
176 callbacks->onError(error.release());
177 return;
180 int request_id = pending_get_registration_callbacks_.Add(callbacks);
181 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
182 "ServiceWorkerDispatcher::GetRegistration",
183 request_id,
184 "Document URL", document_url.spec());
185 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistration(
186 CurrentWorkerId(), request_id, provider_id, document_url));
189 void ServiceWorkerDispatcher::GetRegistrations(
190 int provider_id,
191 WebServiceWorkerGetRegistrationsCallbacks* callbacks) {
192 DCHECK(callbacks);
194 int request_id = pending_get_registrations_callbacks_.Add(callbacks);
195 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
196 "ServiceWorkerDispatcher::GetRegistrations",
197 request_id);
198 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistrations(
199 CurrentWorkerId(), request_id, provider_id));
202 void ServiceWorkerDispatcher::GetRegistrationForReady(
203 int provider_id,
204 WebServiceWorkerGetRegistrationForReadyCallbacks* callbacks) {
205 int request_id = get_for_ready_callbacks_.Add(callbacks);
206 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
207 "ServiceWorkerDispatcher::GetRegistrationForReady",
208 request_id);
209 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistrationForReady(
210 CurrentWorkerId(), request_id, provider_id));
213 void ServiceWorkerDispatcher::AddProviderContext(
214 ServiceWorkerProviderContext* provider_context) {
215 DCHECK(provider_context);
216 int provider_id = provider_context->provider_id();
217 DCHECK(!ContainsKey(provider_contexts_, provider_id));
218 provider_contexts_[provider_id] = provider_context;
221 void ServiceWorkerDispatcher::RemoveProviderContext(
222 ServiceWorkerProviderContext* provider_context) {
223 DCHECK(provider_context);
224 DCHECK(ContainsKey(provider_contexts_, provider_context->provider_id()));
225 provider_contexts_.erase(provider_context->provider_id());
226 worker_to_provider_.erase(provider_context->installing_handle_id());
227 worker_to_provider_.erase(provider_context->waiting_handle_id());
228 worker_to_provider_.erase(provider_context->active_handle_id());
229 worker_to_provider_.erase(provider_context->controller_handle_id());
232 void ServiceWorkerDispatcher::AddProviderClient(
233 int provider_id,
234 blink::WebServiceWorkerProviderClient* client) {
235 DCHECK(client);
236 DCHECK(!ContainsKey(provider_clients_, provider_id));
237 provider_clients_[provider_id] = client;
240 void ServiceWorkerDispatcher::RemoveProviderClient(int provider_id) {
241 // This could be possibly called multiple times to ensure termination.
242 if (ContainsKey(provider_clients_, provider_id))
243 provider_clients_.erase(provider_id);
246 ServiceWorkerDispatcher*
247 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
248 ThreadSafeSender* thread_safe_sender,
249 base::SingleThreadTaskRunner* main_thread_task_runner) {
250 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
251 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
252 g_dispatcher_tls.Pointer()->Set(NULL);
254 if (g_dispatcher_tls.Pointer()->Get())
255 return g_dispatcher_tls.Pointer()->Get();
257 ServiceWorkerDispatcher* dispatcher =
258 new ServiceWorkerDispatcher(thread_safe_sender, main_thread_task_runner);
259 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
260 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
261 return dispatcher;
264 ServiceWorkerDispatcher* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
265 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted)
266 return NULL;
267 return g_dispatcher_tls.Pointer()->Get();
270 void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
271 delete this;
274 WebServiceWorkerImpl* ServiceWorkerDispatcher::GetServiceWorker(
275 const ServiceWorkerObjectInfo& info,
276 bool adopt_handle) {
277 if (info.handle_id == kInvalidServiceWorkerHandleId)
278 return NULL;
280 WorkerObjectMap::iterator existing_worker =
281 service_workers_.find(info.handle_id);
283 if (existing_worker != service_workers_.end()) {
284 if (adopt_handle) {
285 // We are instructed to adopt a handle but we already have one, so
286 // adopt and destroy a handle ref.
287 ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
289 return existing_worker->second;
292 scoped_ptr<ServiceWorkerHandleReference> handle_ref =
293 adopt_handle
294 ? ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get())
295 : ServiceWorkerHandleReference::Create(info,
296 thread_safe_sender_.get());
297 // WebServiceWorkerImpl constructor calls AddServiceWorker.
298 return new WebServiceWorkerImpl(handle_ref.Pass(), thread_safe_sender_.get());
301 WebServiceWorkerRegistrationImpl*
302 ServiceWorkerDispatcher::CreateServiceWorkerRegistration(
303 const ServiceWorkerRegistrationObjectInfo& info,
304 bool adopt_handle) {
305 DCHECK(!ContainsKey(registrations_, info.handle_id));
306 if (info.handle_id == kInvalidServiceWorkerRegistrationHandleId)
307 return NULL;
309 scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref =
310 adopt_handle ? ServiceWorkerRegistrationHandleReference::Adopt(
311 info, thread_safe_sender_.get())
312 : ServiceWorkerRegistrationHandleReference::Create(
313 info, thread_safe_sender_.get());
315 // WebServiceWorkerRegistrationImpl constructor calls
316 // AddServiceWorkerRegistration.
317 return new WebServiceWorkerRegistrationImpl(handle_ref.Pass());
320 // We can assume that this message handler is called before the worker context
321 // starts because script loading happens after this association.
322 // TODO(nhiroki): This association information could be pushed into
323 // EmbeddedWorkerMsg_StartWorker message and handed over to the worker thread
324 // without a lock in ServiceWorkerProviderContext.
325 void ServiceWorkerDispatcher::OnAssociateRegistrationWithServiceWorker(
326 int thread_id,
327 int provider_id,
328 const ServiceWorkerRegistrationObjectInfo& info,
329 const ServiceWorkerVersionAttributes& attrs) {
330 DCHECK_EQ(kDocumentMainThreadId, thread_id);
332 ProviderContextMap::iterator context = provider_contexts_.find(provider_id);
333 if (context == provider_contexts_.end())
334 return;
335 context->second->OnAssociateRegistration(info, attrs);
337 // We don't have to add entries into |worker_to_provider_| because state
338 // change events for the workers will be notified on the worker thread.
341 void ServiceWorkerDispatcher::OnAssociateRegistration(
342 int thread_id,
343 int provider_id,
344 const ServiceWorkerRegistrationObjectInfo& info,
345 const ServiceWorkerVersionAttributes& attrs) {
346 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
347 if (provider == provider_contexts_.end())
348 return;
349 provider->second->OnAssociateRegistration(info, attrs);
350 if (attrs.installing.handle_id != kInvalidServiceWorkerHandleId)
351 worker_to_provider_[attrs.installing.handle_id] = provider->second;
352 if (attrs.waiting.handle_id != kInvalidServiceWorkerHandleId)
353 worker_to_provider_[attrs.waiting.handle_id] = provider->second;
354 if (attrs.active.handle_id != kInvalidServiceWorkerHandleId)
355 worker_to_provider_[attrs.active.handle_id] = provider->second;
358 void ServiceWorkerDispatcher::OnDisassociateRegistration(
359 int thread_id,
360 int provider_id) {
361 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
362 if (provider == provider_contexts_.end())
363 return;
364 worker_to_provider_.erase(provider->second->installing_handle_id());
365 worker_to_provider_.erase(provider->second->waiting_handle_id());
366 worker_to_provider_.erase(provider->second->active_handle_id());
367 worker_to_provider_.erase(provider->second->controller_handle_id());
368 provider->second->OnDisassociateRegistration();
371 void ServiceWorkerDispatcher::OnRegistered(
372 int thread_id,
373 int request_id,
374 const ServiceWorkerRegistrationObjectInfo& info,
375 const ServiceWorkerVersionAttributes& attrs) {
376 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
377 "ServiceWorkerDispatcher::RegisterServiceWorker",
378 request_id,
379 "OnRegistered");
380 TRACE_EVENT_ASYNC_END0("ServiceWorker",
381 "ServiceWorkerDispatcher::RegisterServiceWorker",
382 request_id);
383 WebServiceWorkerRegistrationCallbacks* callbacks =
384 pending_registration_callbacks_.Lookup(request_id);
385 DCHECK(callbacks);
386 if (!callbacks)
387 return;
389 callbacks->onSuccess(FindOrCreateRegistration(info, attrs));
390 pending_registration_callbacks_.Remove(request_id);
393 void ServiceWorkerDispatcher::OnUpdated(int thread_id, int request_id) {
394 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
395 "ServiceWorkerDispatcher::UpdateServiceWorker",
396 request_id, "OnUpdated");
397 TRACE_EVENT_ASYNC_END0("ServiceWorker",
398 "ServiceWorkerDispatcher::UpdateServiceWorker",
399 request_id);
400 WebServiceWorkerUpdateCallbacks* callbacks =
401 pending_update_callbacks_.Lookup(request_id);
402 DCHECK(callbacks);
403 if (!callbacks)
404 return;
406 callbacks->onSuccess();
407 pending_update_callbacks_.Remove(request_id);
410 void ServiceWorkerDispatcher::OnUnregistered(int thread_id,
411 int request_id,
412 bool is_success) {
413 TRACE_EVENT_ASYNC_STEP_INTO0(
414 "ServiceWorker",
415 "ServiceWorkerDispatcher::UnregisterServiceWorker",
416 request_id,
417 "OnUnregistered");
418 TRACE_EVENT_ASYNC_END0("ServiceWorker",
419 "ServiceWorkerDispatcher::UnregisterServiceWorker",
420 request_id);
421 WebServiceWorkerUnregistrationCallbacks* callbacks =
422 pending_unregistration_callbacks_.Lookup(request_id);
423 DCHECK(callbacks);
424 if (!callbacks)
425 return;
426 callbacks->onSuccess(&is_success);
427 pending_unregistration_callbacks_.Remove(request_id);
430 void ServiceWorkerDispatcher::OnDidGetRegistration(
431 int thread_id,
432 int request_id,
433 const ServiceWorkerRegistrationObjectInfo& info,
434 const ServiceWorkerVersionAttributes& attrs) {
435 TRACE_EVENT_ASYNC_STEP_INTO0(
436 "ServiceWorker",
437 "ServiceWorkerDispatcher::GetRegistration",
438 request_id,
439 "OnDidGetRegistration");
440 TRACE_EVENT_ASYNC_END0("ServiceWorker",
441 "ServiceWorkerDispatcher::GetRegistration",
442 request_id);
443 WebServiceWorkerRegistrationCallbacks* callbacks =
444 pending_get_registration_callbacks_.Lookup(request_id);
445 DCHECK(callbacks);
446 if (!callbacks)
447 return;
449 WebServiceWorkerRegistrationImpl* registration = NULL;
450 if (info.handle_id != kInvalidServiceWorkerHandleId)
451 registration = FindOrCreateRegistration(info, attrs);
453 callbacks->onSuccess(registration);
454 pending_get_registration_callbacks_.Remove(request_id);
457 void ServiceWorkerDispatcher::OnDidGetRegistrations(
458 int thread_id,
459 int request_id,
460 const std::vector<ServiceWorkerRegistrationObjectInfo>& infos,
461 const std::vector<ServiceWorkerVersionAttributes>& attrs) {
462 TRACE_EVENT_ASYNC_STEP_INTO0(
463 "ServiceWorker",
464 "ServiceWorkerDispatcher::GetRegistrations",
465 request_id,
466 "OnDidGetRegistrations");
467 TRACE_EVENT_ASYNC_END0("ServiceWorker",
468 "ServiceWorkerDispatcher::GetRegistrations",
469 request_id);
471 WebServiceWorkerGetRegistrationsCallbacks* callbacks =
472 pending_get_registrations_callbacks_.Lookup(request_id);
473 DCHECK(callbacks);
474 if (!callbacks)
475 return;
477 typedef blink::WebVector<blink::WebServiceWorkerRegistration*>
478 WebServiceWorkerRegistrationArray;
479 scoped_ptr<WebServiceWorkerRegistrationArray>
480 registrations(new WebServiceWorkerRegistrationArray(infos.size()));
481 for (size_t i = 0; i < infos.size(); ++i) {
482 if (infos[i].handle_id != kInvalidServiceWorkerHandleId) {
483 ServiceWorkerRegistrationObjectInfo info(infos[i]);
484 ServiceWorkerVersionAttributes attr(attrs[i]);
485 (*registrations)[i] = FindOrCreateRegistration(info, attr);
489 callbacks->onSuccess(registrations.release());
490 pending_get_registrations_callbacks_.Remove(request_id);
493 void ServiceWorkerDispatcher::OnDidGetRegistrationForReady(
494 int thread_id,
495 int request_id,
496 const ServiceWorkerRegistrationObjectInfo& info,
497 const ServiceWorkerVersionAttributes& attrs) {
498 TRACE_EVENT_ASYNC_STEP_INTO0(
499 "ServiceWorker",
500 "ServiceWorkerDispatcher::GetRegistrationForReady",
501 request_id,
502 "OnDidGetRegistrationForReady");
503 TRACE_EVENT_ASYNC_END0("ServiceWorker",
504 "ServiceWorkerDispatcher::GetRegistrationForReady",
505 request_id);
506 WebServiceWorkerGetRegistrationForReadyCallbacks* callbacks =
507 get_for_ready_callbacks_.Lookup(request_id);
508 DCHECK(callbacks);
509 if (!callbacks)
510 return;
512 WebServiceWorkerRegistrationImpl* registration = NULL;
513 DCHECK(info.handle_id != kInvalidServiceWorkerHandleId);
514 registration = FindOrCreateRegistration(info, attrs);
515 callbacks->onSuccess(registration);
516 get_for_ready_callbacks_.Remove(request_id);
519 void ServiceWorkerDispatcher::OnRegistrationError(
520 int thread_id,
521 int request_id,
522 WebServiceWorkerError::ErrorType error_type,
523 const base::string16& message) {
524 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
525 "ServiceWorkerDispatcher::RegisterServiceWorker",
526 request_id,
527 "OnRegistrationError");
528 TRACE_EVENT_ASYNC_END0("ServiceWorker",
529 "ServiceWorkerDispatcher::RegisterServiceWorker",
530 request_id);
531 WebServiceWorkerRegistrationCallbacks* callbacks =
532 pending_registration_callbacks_.Lookup(request_id);
533 DCHECK(callbacks);
534 if (!callbacks)
535 return;
537 scoped_ptr<WebServiceWorkerError> error(
538 new WebServiceWorkerError(error_type, message));
539 callbacks->onError(error.release());
540 pending_registration_callbacks_.Remove(request_id);
543 void ServiceWorkerDispatcher::OnUpdateError(
544 int thread_id,
545 int request_id,
546 WebServiceWorkerError::ErrorType error_type,
547 const base::string16& message) {
548 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
549 "ServiceWorkerDispatcher::UpdateServiceWorker",
550 request_id, "OnUpdateError");
551 TRACE_EVENT_ASYNC_END0("ServiceWorker",
552 "ServiceWorkerDispatcher::UpdateServiceWorker",
553 request_id);
554 WebServiceWorkerUpdateCallbacks* callbacks =
555 pending_update_callbacks_.Lookup(request_id);
556 DCHECK(callbacks);
557 if (!callbacks)
558 return;
560 callbacks->onError(new WebServiceWorkerError(error_type, message));
561 pending_update_callbacks_.Remove(request_id);
564 void ServiceWorkerDispatcher::OnUnregistrationError(
565 int thread_id,
566 int request_id,
567 WebServiceWorkerError::ErrorType error_type,
568 const base::string16& message) {
569 TRACE_EVENT_ASYNC_STEP_INTO0(
570 "ServiceWorker",
571 "ServiceWorkerDispatcher::UnregisterServiceWorker",
572 request_id,
573 "OnUnregistrationError");
574 TRACE_EVENT_ASYNC_END0("ServiceWorker",
575 "ServiceWorkerDispatcher::UnregisterServiceWorker",
576 request_id);
577 WebServiceWorkerUnregistrationCallbacks* callbacks =
578 pending_unregistration_callbacks_.Lookup(request_id);
579 DCHECK(callbacks);
580 if (!callbacks)
581 return;
583 scoped_ptr<WebServiceWorkerError> error(
584 new WebServiceWorkerError(error_type, message));
585 callbacks->onError(error.release());
586 pending_unregistration_callbacks_.Remove(request_id);
589 void ServiceWorkerDispatcher::OnGetRegistrationError(
590 int thread_id,
591 int request_id,
592 WebServiceWorkerError::ErrorType error_type,
593 const base::string16& message) {
594 TRACE_EVENT_ASYNC_STEP_INTO0(
595 "ServiceWorker",
596 "ServiceWorkerDispatcher::GetRegistration",
597 request_id,
598 "OnGetRegistrationError");
599 TRACE_EVENT_ASYNC_END0("ServiceWorker",
600 "ServiceWorkerDispatcher::GetRegistration",
601 request_id);
602 WebServiceWorkerGetRegistrationCallbacks* callbacks =
603 pending_get_registration_callbacks_.Lookup(request_id);
604 DCHECK(callbacks);
605 if (!callbacks)
606 return;
608 scoped_ptr<WebServiceWorkerError> error(
609 new WebServiceWorkerError(error_type, message));
610 callbacks->onError(error.release());
611 pending_get_registration_callbacks_.Remove(request_id);
614 void ServiceWorkerDispatcher::OnGetRegistrationsError(
615 int thread_id,
616 int request_id,
617 WebServiceWorkerError::ErrorType error_type,
618 const base::string16& message) {
619 TRACE_EVENT_ASYNC_STEP_INTO0(
620 "ServiceWorker",
621 "ServiceWorkerDispatcher::GetRegistrations",
622 request_id,
623 "OnGetRegistrationsError");
624 TRACE_EVENT_ASYNC_END0("ServiceWorker",
625 "ServiceWorkerDispatcher::GetRegistrations",
626 request_id);
627 WebServiceWorkerGetRegistrationsCallbacks* callbacks =
628 pending_get_registrations_callbacks_.Lookup(request_id);
629 DCHECK(callbacks);
630 if (!callbacks)
631 return;
633 scoped_ptr<WebServiceWorkerError> error(
634 new WebServiceWorkerError(error_type, message));
635 callbacks->onError(error.release());
636 pending_get_registrations_callbacks_.Remove(request_id);
639 void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
640 int thread_id,
641 int handle_id,
642 blink::WebServiceWorkerState state) {
643 TRACE_EVENT2("ServiceWorker",
644 "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
645 "Thread ID", thread_id,
646 "State", state);
647 WorkerObjectMap::iterator worker = service_workers_.find(handle_id);
648 if (worker != service_workers_.end())
649 worker->second->OnStateChanged(state);
651 WorkerToProviderMap::iterator provider = worker_to_provider_.find(handle_id);
652 if (provider != worker_to_provider_.end())
653 provider->second->OnServiceWorkerStateChanged(handle_id, state);
656 void ServiceWorkerDispatcher::OnSetVersionAttributes(
657 int thread_id,
658 int provider_id,
659 int registration_handle_id,
660 int changed_mask,
661 const ServiceWorkerVersionAttributes& attrs) {
662 TRACE_EVENT1("ServiceWorker",
663 "ServiceWorkerDispatcher::OnSetVersionAttributes",
664 "Thread ID", thread_id);
666 ChangedVersionAttributesMask mask(changed_mask);
667 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
668 if (provider != provider_contexts_.end() &&
669 provider->second->registration_handle_id() == registration_handle_id) {
670 if (mask.installing_changed()) {
671 worker_to_provider_.erase(provider->second->installing_handle_id());
672 if (attrs.installing.handle_id != kInvalidServiceWorkerHandleId)
673 worker_to_provider_[attrs.installing.handle_id] = provider->second;
675 if (mask.waiting_changed()) {
676 worker_to_provider_.erase(provider->second->waiting_handle_id());
677 if (attrs.waiting.handle_id != kInvalidServiceWorkerHandleId)
678 worker_to_provider_[attrs.waiting.handle_id] = provider->second;
680 if (mask.active_changed()) {
681 worker_to_provider_.erase(provider->second->active_handle_id());
682 if (attrs.active.handle_id != kInvalidServiceWorkerHandleId)
683 worker_to_provider_[attrs.active.handle_id] = provider->second;
685 provider->second->SetVersionAttributes(mask, attrs);
688 RegistrationObjectMap::iterator found =
689 registrations_.find(registration_handle_id);
690 if (found != registrations_.end()) {
691 // Populate the version fields (eg. .installing) with new worker objects.
692 if (mask.installing_changed())
693 found->second->SetInstalling(GetServiceWorker(attrs.installing, false));
694 if (mask.waiting_changed())
695 found->second->SetWaiting(GetServiceWorker(attrs.waiting, false));
696 if (mask.active_changed())
697 found->second->SetActive(GetServiceWorker(attrs.active, false));
701 void ServiceWorkerDispatcher::OnUpdateFound(
702 int thread_id,
703 int registration_handle_id) {
704 TRACE_EVENT0("ServiceWorker",
705 "ServiceWorkerDispatcher::OnUpdateFound");
706 RegistrationObjectMap::iterator found =
707 registrations_.find(registration_handle_id);
708 if (found != registrations_.end())
709 found->second->OnUpdateFound();
712 void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
713 int thread_id,
714 int provider_id,
715 const ServiceWorkerObjectInfo& info,
716 bool should_notify_controllerchange) {
717 TRACE_EVENT2("ServiceWorker",
718 "ServiceWorkerDispatcher::OnSetControllerServiceWorker",
719 "Thread ID", thread_id,
720 "Provider ID", provider_id);
722 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
723 if (provider != provider_contexts_.end()) {
724 worker_to_provider_.erase(provider->second->controller_handle_id());
725 if (info.handle_id != kInvalidServiceWorkerHandleId)
726 worker_to_provider_[info.handle_id] = provider->second;
727 provider->second->OnSetControllerServiceWorker(info);
730 ProviderClientMap::iterator found = provider_clients_.find(provider_id);
731 if (found != provider_clients_.end()) {
732 // Populate the .controller field with the new worker object.
733 found->second->setController(GetServiceWorker(info, false),
734 should_notify_controllerchange);
738 void ServiceWorkerDispatcher::OnPostMessage(
739 const ServiceWorkerMsg_MessageToDocument_Params& params) {
740 // Make sure we're on the main document thread. (That must be the only
741 // thread we get this message)
742 DCHECK(ChildThreadImpl::current());
743 TRACE_EVENT1("ServiceWorker", "ServiceWorkerDispatcher::OnPostMessage",
744 "Thread ID", params.thread_id);
746 ProviderClientMap::iterator found =
747 provider_clients_.find(params.provider_id);
748 if (found == provider_clients_.end()) {
749 // For now we do no queueing for messages sent to nonexistent / unattached
750 // client.
751 return;
754 blink::WebMessagePortChannelArray ports =
755 WebMessagePortChannelImpl::CreatePorts(
756 params.message_ports, params.new_routing_ids,
757 base::ThreadTaskRunnerHandle::Get());
759 found->second->dispatchMessageEvent(
760 GetServiceWorker(params.service_worker_info, false /* adopt_handle */),
761 params.message, ports);
764 void ServiceWorkerDispatcher::AddServiceWorker(
765 int handle_id, WebServiceWorkerImpl* worker) {
766 DCHECK(!ContainsKey(service_workers_, handle_id));
767 service_workers_[handle_id] = worker;
770 void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id) {
771 DCHECK(ContainsKey(service_workers_, handle_id));
772 service_workers_.erase(handle_id);
775 void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
776 int registration_handle_id,
777 WebServiceWorkerRegistrationImpl* registration) {
778 DCHECK(!ContainsKey(registrations_, registration_handle_id));
779 registrations_[registration_handle_id] = registration;
782 void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
783 int registration_handle_id) {
784 DCHECK(ContainsKey(registrations_, registration_handle_id));
785 registrations_.erase(registration_handle_id);
788 WebServiceWorkerRegistrationImpl*
789 ServiceWorkerDispatcher::FindOrCreateRegistration(
790 const ServiceWorkerRegistrationObjectInfo& info,
791 const ServiceWorkerVersionAttributes& attrs) {
792 RegistrationObjectMap::iterator found = registrations_.find(info.handle_id);
793 if (found != registrations_.end()) {
794 ServiceWorkerRegistrationHandleReference::Adopt(info,
795 thread_safe_sender_.get());
796 ServiceWorkerHandleReference::Adopt(attrs.installing,
797 thread_safe_sender_.get());
798 ServiceWorkerHandleReference::Adopt(attrs.waiting,
799 thread_safe_sender_.get());
800 ServiceWorkerHandleReference::Adopt(attrs.active,
801 thread_safe_sender_.get());
802 return found->second;
805 bool adopt_handle = true;
806 WebServiceWorkerRegistrationImpl* registration =
807 CreateServiceWorkerRegistration(info, adopt_handle);
808 registration->SetInstalling(GetServiceWorker(attrs.installing, adopt_handle));
809 registration->SetWaiting(GetServiceWorker(attrs.waiting, adopt_handle));
810 registration->SetActive(GetServiceWorker(attrs.active, adopt_handle));
811 return registration;
814 } // namespace content