Roll src/third_party/WebKit 6cdd902:94953d6 (svn 197985:197991)
[chromium-blink-merge.git] / content / child / service_worker / service_worker_dispatcher.cc
blobf28058180def3d1f97f9ab60bf13d43e43dc17e5
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/stl_util.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "base/threading/thread_local.h"
11 #include "base/trace_event/trace_event.h"
12 #include "content/child/child_thread_impl.h"
13 #include "content/child/service_worker/service_worker_handle_reference.h"
14 #include "content/child/service_worker/service_worker_provider_context.h"
15 #include "content/child/service_worker/service_worker_registration_handle_reference.h"
16 #include "content/child/service_worker/web_service_worker_impl.h"
17 #include "content/child/service_worker/web_service_worker_registration_impl.h"
18 #include "content/child/thread_safe_sender.h"
19 #include "content/child/webmessageportchannel_impl.h"
20 #include "content/common/service_worker/service_worker_messages.h"
21 #include "content/common/service_worker/service_worker_types.h"
22 #include "content/public/common/url_utils.h"
23 #include "third_party/WebKit/public/platform/WebServiceWorkerClientsInfo.h"
24 #include "third_party/WebKit/public/platform/WebServiceWorkerProviderClient.h"
25 #include "third_party/WebKit/public/platform/WebString.h"
26 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
28 using blink::WebServiceWorkerError;
29 using blink::WebServiceWorkerProvider;
30 using base::ThreadLocalPointer;
32 namespace content {
34 namespace {
36 base::LazyInstance<ThreadLocalPointer<ServiceWorkerDispatcher> >::Leaky
37 g_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
39 ServiceWorkerDispatcher* const kHasBeenDeleted =
40 reinterpret_cast<ServiceWorkerDispatcher*>(0x1);
42 int CurrentWorkerId() {
43 return WorkerTaskRunner::Instance()->CurrentWorkerId();
46 } // namespace
48 ServiceWorkerDispatcher::ServiceWorkerDispatcher(
49 ThreadSafeSender* thread_safe_sender)
50 : thread_safe_sender_(thread_safe_sender) {
51 g_dispatcher_tls.Pointer()->Set(this);
54 ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
55 g_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
58 void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message& msg) {
59 bool handled = true;
60 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher, msg)
61 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistrationWithServiceWorker,
62 OnAssociateRegistrationWithServiceWorker)
63 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistration,
64 OnAssociateRegistration)
65 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DisassociateRegistration,
66 OnDisassociateRegistration)
67 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered, OnRegistered)
68 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered,
69 OnUnregistered)
70 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistration,
71 OnDidGetRegistration)
72 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistrations,
73 OnDidGetRegistrations)
74 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistrationForReady,
75 OnDidGetRegistrationForReady)
76 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError,
77 OnRegistrationError)
78 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistrationError,
79 OnUnregistrationError)
80 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationError,
81 OnGetRegistrationError)
82 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationsError,
83 OnGetRegistrationsError)
84 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged,
85 OnServiceWorkerStateChanged)
86 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes,
87 OnSetVersionAttributes)
88 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_UpdateFound,
89 OnUpdateFound)
90 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker,
91 OnSetControllerServiceWorker)
92 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument,
93 OnPostMessage)
94 IPC_MESSAGE_UNHANDLED(handled = false)
95 IPC_END_MESSAGE_MAP()
96 DCHECK(handled) << "Unhandled message:" << msg.type();
99 bool ServiceWorkerDispatcher::Send(IPC::Message* msg) {
100 return thread_safe_sender_->Send(msg);
103 void ServiceWorkerDispatcher::RegisterServiceWorker(
104 int provider_id,
105 const GURL& pattern,
106 const GURL& script_url,
107 WebServiceWorkerRegistrationCallbacks* callbacks) {
108 DCHECK(callbacks);
110 if (pattern.possibly_invalid_spec().size() > GetMaxURLChars() ||
111 script_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
112 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
113 owned_callbacks(callbacks);
114 std::string error_message(kServiceWorkerRegisterErrorPrefix);
115 error_message += "The provided scriptURL or scope is too long.";
116 scoped_ptr<WebServiceWorkerError> error(
117 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity,
118 blink::WebString::fromUTF8(error_message)));
119 callbacks->onError(error.release());
120 return;
123 int request_id = pending_registration_callbacks_.Add(callbacks);
124 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
125 "ServiceWorkerDispatcher::RegisterServiceWorker",
126 request_id,
127 "Scope", pattern.spec(),
128 "Script URL", script_url.spec());
129 thread_safe_sender_->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
130 CurrentWorkerId(), request_id, provider_id, pattern, script_url));
133 void ServiceWorkerDispatcher::UpdateServiceWorker(int provider_id,
134 int64 registration_id) {
135 thread_safe_sender_->Send(new ServiceWorkerHostMsg_UpdateServiceWorker(
136 provider_id, registration_id));
139 void ServiceWorkerDispatcher::UnregisterServiceWorker(
140 int provider_id,
141 int64 registration_id,
142 WebServiceWorkerUnregistrationCallbacks* callbacks) {
143 DCHECK(callbacks);
144 int request_id = pending_unregistration_callbacks_.Add(callbacks);
145 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
146 "ServiceWorkerDispatcher::UnregisterServiceWorker",
147 request_id, "Registration ID", registration_id);
148 thread_safe_sender_->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
149 CurrentWorkerId(), request_id, provider_id, registration_id));
152 void ServiceWorkerDispatcher::GetRegistration(
153 int provider_id,
154 const GURL& document_url,
155 WebServiceWorkerRegistrationCallbacks* callbacks) {
156 DCHECK(callbacks);
158 if (document_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
159 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
160 owned_callbacks(callbacks);
161 std::string error_message(kServiceWorkerGetRegistrationErrorPrefix);
162 error_message += "The provided documentURL is too long.";
163 scoped_ptr<WebServiceWorkerError> error(
164 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity,
165 blink::WebString::fromUTF8(error_message)));
166 callbacks->onError(error.release());
167 return;
170 int request_id = pending_get_registration_callbacks_.Add(callbacks);
171 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
172 "ServiceWorkerDispatcher::GetRegistration",
173 request_id,
174 "Document URL", document_url.spec());
175 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistration(
176 CurrentWorkerId(), request_id, provider_id, document_url));
179 void ServiceWorkerDispatcher::GetRegistrations(
180 int provider_id,
181 WebServiceWorkerGetRegistrationsCallbacks* callbacks) {
182 DCHECK(callbacks);
184 int request_id = pending_get_registrations_callbacks_.Add(callbacks);
185 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
186 "ServiceWorkerDispatcher::GetRegistrations",
187 request_id);
188 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistrations(
189 CurrentWorkerId(), request_id, provider_id));
192 void ServiceWorkerDispatcher::GetRegistrationForReady(
193 int provider_id,
194 WebServiceWorkerGetRegistrationForReadyCallbacks* callbacks) {
195 int request_id = get_for_ready_callbacks_.Add(callbacks);
196 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
197 "ServiceWorkerDispatcher::GetRegistrationForReady",
198 request_id);
199 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistrationForReady(
200 CurrentWorkerId(), request_id, provider_id));
203 void ServiceWorkerDispatcher::AddProviderContext(
204 ServiceWorkerProviderContext* provider_context) {
205 DCHECK(provider_context);
206 int provider_id = provider_context->provider_id();
207 DCHECK(!ContainsKey(provider_contexts_, provider_id));
208 provider_contexts_[provider_id] = provider_context;
211 void ServiceWorkerDispatcher::RemoveProviderContext(
212 ServiceWorkerProviderContext* provider_context) {
213 DCHECK(provider_context);
214 DCHECK(ContainsKey(provider_contexts_, provider_context->provider_id()));
215 provider_contexts_.erase(provider_context->provider_id());
216 worker_to_provider_.erase(provider_context->installing_handle_id());
217 worker_to_provider_.erase(provider_context->waiting_handle_id());
218 worker_to_provider_.erase(provider_context->active_handle_id());
219 worker_to_provider_.erase(provider_context->controller_handle_id());
222 void ServiceWorkerDispatcher::AddProviderClient(
223 int provider_id,
224 blink::WebServiceWorkerProviderClient* client) {
225 DCHECK(client);
226 DCHECK(!ContainsKey(provider_clients_, provider_id));
227 provider_clients_[provider_id] = client;
230 void ServiceWorkerDispatcher::RemoveProviderClient(int provider_id) {
231 // This could be possibly called multiple times to ensure termination.
232 if (ContainsKey(provider_clients_, provider_id))
233 provider_clients_.erase(provider_id);
236 ServiceWorkerDispatcher*
237 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
238 ThreadSafeSender* thread_safe_sender) {
239 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
240 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
241 g_dispatcher_tls.Pointer()->Set(NULL);
243 if (g_dispatcher_tls.Pointer()->Get())
244 return g_dispatcher_tls.Pointer()->Get();
246 ServiceWorkerDispatcher* dispatcher =
247 new ServiceWorkerDispatcher(thread_safe_sender);
248 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
249 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
250 return dispatcher;
253 ServiceWorkerDispatcher* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
254 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted)
255 return NULL;
256 return g_dispatcher_tls.Pointer()->Get();
259 void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
260 delete this;
263 WebServiceWorkerImpl* ServiceWorkerDispatcher::GetServiceWorker(
264 const ServiceWorkerObjectInfo& info,
265 bool adopt_handle) {
266 if (info.handle_id == kInvalidServiceWorkerHandleId)
267 return NULL;
269 WorkerObjectMap::iterator existing_worker =
270 service_workers_.find(info.handle_id);
272 if (existing_worker != service_workers_.end()) {
273 if (adopt_handle) {
274 // We are instructed to adopt a handle but we already have one, so
275 // adopt and destroy a handle ref.
276 ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
278 return existing_worker->second;
281 scoped_ptr<ServiceWorkerHandleReference> handle_ref =
282 adopt_handle
283 ? ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get())
284 : ServiceWorkerHandleReference::Create(info,
285 thread_safe_sender_.get());
286 // WebServiceWorkerImpl constructor calls AddServiceWorker.
287 return new WebServiceWorkerImpl(handle_ref.Pass(), thread_safe_sender_.get());
290 WebServiceWorkerRegistrationImpl*
291 ServiceWorkerDispatcher::CreateServiceWorkerRegistration(
292 const ServiceWorkerRegistrationObjectInfo& info,
293 bool adopt_handle) {
294 DCHECK(!ContainsKey(registrations_, info.handle_id));
295 if (info.handle_id == kInvalidServiceWorkerRegistrationHandleId)
296 return NULL;
298 scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref =
299 adopt_handle ? ServiceWorkerRegistrationHandleReference::Adopt(
300 info, thread_safe_sender_.get())
301 : ServiceWorkerRegistrationHandleReference::Create(
302 info, thread_safe_sender_.get());
304 // WebServiceWorkerRegistrationImpl constructor calls
305 // AddServiceWorkerRegistration.
306 return new WebServiceWorkerRegistrationImpl(handle_ref.Pass());
309 // We can assume that this message handler is called before the worker context
310 // starts because script loading happens after this association.
311 // TODO(nhiroki): This association information could be pushed into
312 // EmbeddedWorkerMsg_StartWorker message and handed over to the worker thread
313 // without a lock in ServiceWorkerProviderContext.
314 void ServiceWorkerDispatcher::OnAssociateRegistrationWithServiceWorker(
315 int thread_id,
316 int provider_id,
317 const ServiceWorkerRegistrationObjectInfo& info,
318 const ServiceWorkerVersionAttributes& attrs) {
319 DCHECK_EQ(kDocumentMainThreadId, thread_id);
321 ProviderContextMap::iterator context = provider_contexts_.find(provider_id);
322 if (context == provider_contexts_.end())
323 return;
324 context->second->OnAssociateRegistration(info, attrs);
326 // We don't have to add entries into |worker_to_provider_| because state
327 // change events for the workers will be notified on the worker thread.
330 void ServiceWorkerDispatcher::OnAssociateRegistration(
331 int thread_id,
332 int provider_id,
333 const ServiceWorkerRegistrationObjectInfo& info,
334 const ServiceWorkerVersionAttributes& attrs) {
335 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
336 if (provider == provider_contexts_.end())
337 return;
338 provider->second->OnAssociateRegistration(info, attrs);
339 if (attrs.installing.handle_id != kInvalidServiceWorkerHandleId)
340 worker_to_provider_[attrs.installing.handle_id] = provider->second;
341 if (attrs.waiting.handle_id != kInvalidServiceWorkerHandleId)
342 worker_to_provider_[attrs.waiting.handle_id] = provider->second;
343 if (attrs.active.handle_id != kInvalidServiceWorkerHandleId)
344 worker_to_provider_[attrs.active.handle_id] = provider->second;
347 void ServiceWorkerDispatcher::OnDisassociateRegistration(
348 int thread_id,
349 int provider_id) {
350 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
351 if (provider == provider_contexts_.end())
352 return;
353 worker_to_provider_.erase(provider->second->installing_handle_id());
354 worker_to_provider_.erase(provider->second->waiting_handle_id());
355 worker_to_provider_.erase(provider->second->active_handle_id());
356 worker_to_provider_.erase(provider->second->controller_handle_id());
357 provider->second->OnDisassociateRegistration();
360 void ServiceWorkerDispatcher::OnRegistered(
361 int thread_id,
362 int request_id,
363 const ServiceWorkerRegistrationObjectInfo& info,
364 const ServiceWorkerVersionAttributes& attrs) {
365 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
366 "ServiceWorkerDispatcher::RegisterServiceWorker",
367 request_id,
368 "OnRegistered");
369 TRACE_EVENT_ASYNC_END0("ServiceWorker",
370 "ServiceWorkerDispatcher::RegisterServiceWorker",
371 request_id);
372 WebServiceWorkerRegistrationCallbacks* callbacks =
373 pending_registration_callbacks_.Lookup(request_id);
374 DCHECK(callbacks);
375 if (!callbacks)
376 return;
378 callbacks->onSuccess(FindOrCreateRegistration(info, attrs));
379 pending_registration_callbacks_.Remove(request_id);
382 void ServiceWorkerDispatcher::OnUnregistered(int thread_id,
383 int request_id,
384 bool is_success) {
385 TRACE_EVENT_ASYNC_STEP_INTO0(
386 "ServiceWorker",
387 "ServiceWorkerDispatcher::UnregisterServiceWorker",
388 request_id,
389 "OnUnregistered");
390 TRACE_EVENT_ASYNC_END0("ServiceWorker",
391 "ServiceWorkerDispatcher::UnregisterServiceWorker",
392 request_id);
393 WebServiceWorkerUnregistrationCallbacks* callbacks =
394 pending_unregistration_callbacks_.Lookup(request_id);
395 DCHECK(callbacks);
396 if (!callbacks)
397 return;
398 callbacks->onSuccess(&is_success);
399 pending_unregistration_callbacks_.Remove(request_id);
402 void ServiceWorkerDispatcher::OnDidGetRegistration(
403 int thread_id,
404 int request_id,
405 const ServiceWorkerRegistrationObjectInfo& info,
406 const ServiceWorkerVersionAttributes& attrs) {
407 TRACE_EVENT_ASYNC_STEP_INTO0(
408 "ServiceWorker",
409 "ServiceWorkerDispatcher::GetRegistration",
410 request_id,
411 "OnDidGetRegistration");
412 TRACE_EVENT_ASYNC_END0("ServiceWorker",
413 "ServiceWorkerDispatcher::GetRegistration",
414 request_id);
415 WebServiceWorkerRegistrationCallbacks* callbacks =
416 pending_get_registration_callbacks_.Lookup(request_id);
417 DCHECK(callbacks);
418 if (!callbacks)
419 return;
421 WebServiceWorkerRegistrationImpl* registration = NULL;
422 if (info.handle_id != kInvalidServiceWorkerHandleId)
423 registration = FindOrCreateRegistration(info, attrs);
425 callbacks->onSuccess(registration);
426 pending_get_registration_callbacks_.Remove(request_id);
429 void ServiceWorkerDispatcher::OnDidGetRegistrations(
430 int thread_id,
431 int request_id,
432 const std::vector<ServiceWorkerRegistrationObjectInfo>& infos,
433 const std::vector<ServiceWorkerVersionAttributes>& attrs) {
434 TRACE_EVENT_ASYNC_STEP_INTO0(
435 "ServiceWorker",
436 "ServiceWorkerDispatcher::GetRegistrations",
437 request_id,
438 "OnDidGetRegistrations");
439 TRACE_EVENT_ASYNC_END0("ServiceWorker",
440 "ServiceWorkerDispatcher::GetRegistrations",
441 request_id);
443 WebServiceWorkerGetRegistrationsCallbacks* callbacks =
444 pending_get_registrations_callbacks_.Lookup(request_id);
445 DCHECK(callbacks);
446 if (!callbacks)
447 return;
449 typedef blink::WebVector<blink::WebServiceWorkerRegistration*>
450 WebServiceWorkerRegistrationArray;
451 scoped_ptr<WebServiceWorkerRegistrationArray>
452 registrations(new WebServiceWorkerRegistrationArray(infos.size()));
453 for (size_t i = 0; i < infos.size(); ++i) {
454 if (infos[i].handle_id != kInvalidServiceWorkerHandleId) {
455 ServiceWorkerRegistrationObjectInfo info(infos[i]);
456 ServiceWorkerVersionAttributes attr(attrs[i]);
457 (*registrations)[i] = FindOrCreateRegistration(info, attr);
461 callbacks->onSuccess(registrations.release());
462 pending_get_registrations_callbacks_.Remove(request_id);
465 void ServiceWorkerDispatcher::OnDidGetRegistrationForReady(
466 int thread_id,
467 int request_id,
468 const ServiceWorkerRegistrationObjectInfo& info,
469 const ServiceWorkerVersionAttributes& attrs) {
470 TRACE_EVENT_ASYNC_STEP_INTO0(
471 "ServiceWorker",
472 "ServiceWorkerDispatcher::GetRegistrationForReady",
473 request_id,
474 "OnDidGetRegistrationForReady");
475 TRACE_EVENT_ASYNC_END0("ServiceWorker",
476 "ServiceWorkerDispatcher::GetRegistrationForReady",
477 request_id);
478 WebServiceWorkerGetRegistrationForReadyCallbacks* callbacks =
479 get_for_ready_callbacks_.Lookup(request_id);
480 DCHECK(callbacks);
481 if (!callbacks)
482 return;
484 WebServiceWorkerRegistrationImpl* registration = NULL;
485 DCHECK(info.handle_id != kInvalidServiceWorkerHandleId);
486 registration = FindOrCreateRegistration(info, attrs);
487 callbacks->onSuccess(registration);
488 get_for_ready_callbacks_.Remove(request_id);
491 void ServiceWorkerDispatcher::OnRegistrationError(
492 int thread_id,
493 int request_id,
494 WebServiceWorkerError::ErrorType error_type,
495 const base::string16& message) {
496 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
497 "ServiceWorkerDispatcher::RegisterServiceWorker",
498 request_id,
499 "OnRegistrationError");
500 TRACE_EVENT_ASYNC_END0("ServiceWorker",
501 "ServiceWorkerDispatcher::RegisterServiceWorker",
502 request_id);
503 WebServiceWorkerRegistrationCallbacks* callbacks =
504 pending_registration_callbacks_.Lookup(request_id);
505 DCHECK(callbacks);
506 if (!callbacks)
507 return;
509 scoped_ptr<WebServiceWorkerError> error(
510 new WebServiceWorkerError(error_type, message));
511 callbacks->onError(error.release());
512 pending_registration_callbacks_.Remove(request_id);
515 void ServiceWorkerDispatcher::OnUnregistrationError(
516 int thread_id,
517 int request_id,
518 WebServiceWorkerError::ErrorType error_type,
519 const base::string16& message) {
520 TRACE_EVENT_ASYNC_STEP_INTO0(
521 "ServiceWorker",
522 "ServiceWorkerDispatcher::UnregisterServiceWorker",
523 request_id,
524 "OnUnregistrationError");
525 TRACE_EVENT_ASYNC_END0("ServiceWorker",
526 "ServiceWorkerDispatcher::UnregisterServiceWorker",
527 request_id);
528 WebServiceWorkerUnregistrationCallbacks* callbacks =
529 pending_unregistration_callbacks_.Lookup(request_id);
530 DCHECK(callbacks);
531 if (!callbacks)
532 return;
534 scoped_ptr<WebServiceWorkerError> error(
535 new WebServiceWorkerError(error_type, message));
536 callbacks->onError(error.release());
537 pending_unregistration_callbacks_.Remove(request_id);
540 void ServiceWorkerDispatcher::OnGetRegistrationError(
541 int thread_id,
542 int request_id,
543 WebServiceWorkerError::ErrorType error_type,
544 const base::string16& message) {
545 TRACE_EVENT_ASYNC_STEP_INTO0(
546 "ServiceWorker",
547 "ServiceWorkerDispatcher::GetRegistration",
548 request_id,
549 "OnGetRegistrationError");
550 TRACE_EVENT_ASYNC_END0("ServiceWorker",
551 "ServiceWorkerDispatcher::GetRegistration",
552 request_id);
553 WebServiceWorkerGetRegistrationCallbacks* callbacks =
554 pending_get_registration_callbacks_.Lookup(request_id);
555 DCHECK(callbacks);
556 if (!callbacks)
557 return;
559 scoped_ptr<WebServiceWorkerError> error(
560 new WebServiceWorkerError(error_type, message));
561 callbacks->onError(error.release());
562 pending_get_registration_callbacks_.Remove(request_id);
565 void ServiceWorkerDispatcher::OnGetRegistrationsError(
566 int thread_id,
567 int request_id,
568 WebServiceWorkerError::ErrorType error_type,
569 const base::string16& message) {
570 TRACE_EVENT_ASYNC_STEP_INTO0(
571 "ServiceWorker",
572 "ServiceWorkerDispatcher::GetRegistrations",
573 request_id,
574 "OnGetRegistrationsError");
575 TRACE_EVENT_ASYNC_END0("ServiceWorker",
576 "ServiceWorkerDispatcher::GetRegistrations",
577 request_id);
578 WebServiceWorkerGetRegistrationsCallbacks* callbacks =
579 pending_get_registrations_callbacks_.Lookup(request_id);
580 DCHECK(callbacks);
581 if (!callbacks)
582 return;
584 scoped_ptr<WebServiceWorkerError> error(
585 new WebServiceWorkerError(error_type, message));
586 callbacks->onError(error.release());
587 pending_get_registrations_callbacks_.Remove(request_id);
590 void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
591 int thread_id,
592 int handle_id,
593 blink::WebServiceWorkerState state) {
594 TRACE_EVENT2("ServiceWorker",
595 "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
596 "Thread ID", thread_id,
597 "State", state);
598 WorkerObjectMap::iterator worker = service_workers_.find(handle_id);
599 if (worker != service_workers_.end())
600 worker->second->OnStateChanged(state);
602 WorkerToProviderMap::iterator provider = worker_to_provider_.find(handle_id);
603 if (provider != worker_to_provider_.end())
604 provider->second->OnServiceWorkerStateChanged(handle_id, state);
607 void ServiceWorkerDispatcher::OnSetVersionAttributes(
608 int thread_id,
609 int provider_id,
610 int registration_handle_id,
611 int changed_mask,
612 const ServiceWorkerVersionAttributes& attrs) {
613 TRACE_EVENT1("ServiceWorker",
614 "ServiceWorkerDispatcher::OnSetVersionAttributes",
615 "Thread ID", thread_id);
617 ChangedVersionAttributesMask mask(changed_mask);
618 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
619 if (provider != provider_contexts_.end() &&
620 provider->second->registration_handle_id() == registration_handle_id) {
621 if (mask.installing_changed()) {
622 worker_to_provider_.erase(provider->second->installing_handle_id());
623 if (attrs.installing.handle_id != kInvalidServiceWorkerHandleId)
624 worker_to_provider_[attrs.installing.handle_id] = provider->second;
626 if (mask.waiting_changed()) {
627 worker_to_provider_.erase(provider->second->waiting_handle_id());
628 if (attrs.waiting.handle_id != kInvalidServiceWorkerHandleId)
629 worker_to_provider_[attrs.waiting.handle_id] = provider->second;
631 if (mask.active_changed()) {
632 worker_to_provider_.erase(provider->second->active_handle_id());
633 if (attrs.active.handle_id != kInvalidServiceWorkerHandleId)
634 worker_to_provider_[attrs.active.handle_id] = provider->second;
636 provider->second->SetVersionAttributes(mask, attrs);
639 RegistrationObjectMap::iterator found =
640 registrations_.find(registration_handle_id);
641 if (found != registrations_.end()) {
642 // Populate the version fields (eg. .installing) with new worker objects.
643 if (mask.installing_changed())
644 found->second->SetInstalling(GetServiceWorker(attrs.installing, false));
645 if (mask.waiting_changed())
646 found->second->SetWaiting(GetServiceWorker(attrs.waiting, false));
647 if (mask.active_changed())
648 found->second->SetActive(GetServiceWorker(attrs.active, false));
652 void ServiceWorkerDispatcher::OnUpdateFound(
653 int thread_id,
654 int registration_handle_id) {
655 TRACE_EVENT0("ServiceWorker",
656 "ServiceWorkerDispatcher::OnUpdateFound");
657 RegistrationObjectMap::iterator found =
658 registrations_.find(registration_handle_id);
659 if (found != registrations_.end())
660 found->second->OnUpdateFound();
663 void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
664 int thread_id,
665 int provider_id,
666 const ServiceWorkerObjectInfo& info,
667 bool should_notify_controllerchange) {
668 TRACE_EVENT2("ServiceWorker",
669 "ServiceWorkerDispatcher::OnSetControllerServiceWorker",
670 "Thread ID", thread_id,
671 "Provider ID", provider_id);
673 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
674 if (provider != provider_contexts_.end()) {
675 worker_to_provider_.erase(provider->second->controller_handle_id());
676 if (info.handle_id != kInvalidServiceWorkerHandleId)
677 worker_to_provider_[info.handle_id] = provider->second;
678 provider->second->OnSetControllerServiceWorker(info);
681 ProviderClientMap::iterator found = provider_clients_.find(provider_id);
682 if (found != provider_clients_.end()) {
683 // Populate the .controller field with the new worker object.
684 found->second->setController(GetServiceWorker(info, false),
685 should_notify_controllerchange);
689 void ServiceWorkerDispatcher::OnPostMessage(
690 int thread_id,
691 int provider_id,
692 const base::string16& message,
693 const std::vector<TransferredMessagePort>& sent_message_ports,
694 const std::vector<int>& new_routing_ids) {
695 // Make sure we're on the main document thread. (That must be the only
696 // thread we get this message)
697 DCHECK(ChildThreadImpl::current());
698 TRACE_EVENT1("ServiceWorker",
699 "ServiceWorkerDispatcher::OnPostMessage",
700 "Thread ID", thread_id);
702 ProviderClientMap::iterator found = provider_clients_.find(provider_id);
703 if (found == provider_clients_.end()) {
704 // For now we do no queueing for messages sent to nonexistent / unattached
705 // client.
706 return;
709 blink::WebMessagePortChannelArray ports =
710 WebMessagePortChannelImpl::CreatePorts(
711 sent_message_ports, new_routing_ids,
712 base::ThreadTaskRunnerHandle::Get());
714 found->second->dispatchMessageEvent(message, ports);
717 void ServiceWorkerDispatcher::AddServiceWorker(
718 int handle_id, WebServiceWorkerImpl* worker) {
719 DCHECK(!ContainsKey(service_workers_, handle_id));
720 service_workers_[handle_id] = worker;
723 void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id) {
724 DCHECK(ContainsKey(service_workers_, handle_id));
725 service_workers_.erase(handle_id);
728 void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
729 int registration_handle_id,
730 WebServiceWorkerRegistrationImpl* registration) {
731 DCHECK(!ContainsKey(registrations_, registration_handle_id));
732 registrations_[registration_handle_id] = registration;
735 void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
736 int registration_handle_id) {
737 DCHECK(ContainsKey(registrations_, registration_handle_id));
738 registrations_.erase(registration_handle_id);
741 WebServiceWorkerRegistrationImpl*
742 ServiceWorkerDispatcher::FindOrCreateRegistration(
743 const ServiceWorkerRegistrationObjectInfo& info,
744 const ServiceWorkerVersionAttributes& attrs) {
745 RegistrationObjectMap::iterator found = registrations_.find(info.handle_id);
746 if (found != registrations_.end()) {
747 ServiceWorkerRegistrationHandleReference::Adopt(info,
748 thread_safe_sender_.get());
749 ServiceWorkerHandleReference::Adopt(attrs.installing,
750 thread_safe_sender_.get());
751 ServiceWorkerHandleReference::Adopt(attrs.waiting,
752 thread_safe_sender_.get());
753 ServiceWorkerHandleReference::Adopt(attrs.active,
754 thread_safe_sender_.get());
755 return found->second;
758 bool adopt_handle = true;
759 WebServiceWorkerRegistrationImpl* registration =
760 CreateServiceWorkerRegistration(info, adopt_handle);
761 registration->SetInstalling(GetServiceWorker(attrs.installing, adopt_handle));
762 registration->SetWaiting(GetServiceWorker(attrs.waiting, adopt_handle));
763 registration->SetActive(GetServiceWorker(attrs.active, adopt_handle));
764 return registration;
767 } // namespace content