Add remaining Linux configs for MB.
[chromium-blink-merge.git] / content / child / service_worker / service_worker_dispatcher.cc
blob76485877c5c891281985f549a621053d6ad1f9d2
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 callbacks->onError(
123 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity,
124 blink::WebString::fromUTF8(error_message)));
125 return;
128 int request_id = pending_registration_callbacks_.Add(callbacks);
129 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
130 "ServiceWorkerDispatcher::RegisterServiceWorker",
131 request_id,
132 "Scope", pattern.spec(),
133 "Script URL", script_url.spec());
134 thread_safe_sender_->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
135 CurrentWorkerId(), request_id, provider_id, pattern, script_url));
138 void ServiceWorkerDispatcher::UpdateServiceWorker(
139 int provider_id,
140 int64 registration_id,
141 WebServiceWorkerUpdateCallbacks* callbacks) {
142 DCHECK(callbacks);
143 int request_id = pending_update_callbacks_.Add(callbacks);
144 thread_safe_sender_->Send(new ServiceWorkerHostMsg_UpdateServiceWorker(
145 CurrentWorkerId(), request_id, provider_id, registration_id));
148 void ServiceWorkerDispatcher::UnregisterServiceWorker(
149 int provider_id,
150 int64 registration_id,
151 WebServiceWorkerUnregistrationCallbacks* callbacks) {
152 DCHECK(callbacks);
153 int request_id = pending_unregistration_callbacks_.Add(callbacks);
154 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
155 "ServiceWorkerDispatcher::UnregisterServiceWorker",
156 request_id, "Registration ID", registration_id);
157 thread_safe_sender_->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
158 CurrentWorkerId(), request_id, provider_id, registration_id));
161 void ServiceWorkerDispatcher::GetRegistration(
162 int provider_id,
163 const GURL& document_url,
164 WebServiceWorkerRegistrationCallbacks* callbacks) {
165 DCHECK(callbacks);
167 if (document_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
168 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
169 owned_callbacks(callbacks);
170 std::string error_message(kServiceWorkerGetRegistrationErrorPrefix);
171 error_message += "The provided documentURL is too long.";
172 callbacks->onError(
173 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity,
174 blink::WebString::fromUTF8(error_message)));
175 return;
178 int request_id = pending_get_registration_callbacks_.Add(callbacks);
179 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
180 "ServiceWorkerDispatcher::GetRegistration",
181 request_id,
182 "Document URL", document_url.spec());
183 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistration(
184 CurrentWorkerId(), request_id, provider_id, document_url));
187 void ServiceWorkerDispatcher::GetRegistrations(
188 int provider_id,
189 WebServiceWorkerGetRegistrationsCallbacks* callbacks) {
190 DCHECK(callbacks);
192 int request_id = pending_get_registrations_callbacks_.Add(callbacks);
193 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
194 "ServiceWorkerDispatcher::GetRegistrations",
195 request_id);
196 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistrations(
197 CurrentWorkerId(), request_id, provider_id));
200 void ServiceWorkerDispatcher::GetRegistrationForReady(
201 int provider_id,
202 WebServiceWorkerGetRegistrationForReadyCallbacks* callbacks) {
203 int request_id = get_for_ready_callbacks_.Add(callbacks);
204 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
205 "ServiceWorkerDispatcher::GetRegistrationForReady",
206 request_id);
207 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistrationForReady(
208 CurrentWorkerId(), request_id, provider_id));
211 void ServiceWorkerDispatcher::AddProviderContext(
212 ServiceWorkerProviderContext* provider_context) {
213 DCHECK(provider_context);
214 int provider_id = provider_context->provider_id();
215 DCHECK(!ContainsKey(provider_contexts_, provider_id));
216 provider_contexts_[provider_id] = provider_context;
219 void ServiceWorkerDispatcher::RemoveProviderContext(
220 ServiceWorkerProviderContext* provider_context) {
221 DCHECK(provider_context);
222 DCHECK(ContainsKey(provider_contexts_, provider_context->provider_id()));
223 provider_contexts_.erase(provider_context->provider_id());
224 worker_to_provider_.erase(provider_context->installing_handle_id());
225 worker_to_provider_.erase(provider_context->waiting_handle_id());
226 worker_to_provider_.erase(provider_context->active_handle_id());
227 worker_to_provider_.erase(provider_context->controller_handle_id());
230 void ServiceWorkerDispatcher::AddProviderClient(
231 int provider_id,
232 blink::WebServiceWorkerProviderClient* client) {
233 DCHECK(client);
234 DCHECK(!ContainsKey(provider_clients_, provider_id));
235 provider_clients_[provider_id] = client;
238 void ServiceWorkerDispatcher::RemoveProviderClient(int provider_id) {
239 // This could be possibly called multiple times to ensure termination.
240 if (ContainsKey(provider_clients_, provider_id))
241 provider_clients_.erase(provider_id);
244 ServiceWorkerDispatcher*
245 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
246 ThreadSafeSender* thread_safe_sender,
247 base::SingleThreadTaskRunner* main_thread_task_runner) {
248 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
249 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
250 g_dispatcher_tls.Pointer()->Set(NULL);
252 if (g_dispatcher_tls.Pointer()->Get())
253 return 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 g_dispatcher_tls.Pointer()->Get();
268 void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
269 delete this;
272 WebServiceWorkerImpl* ServiceWorkerDispatcher::GetServiceWorker(
273 const ServiceWorkerObjectInfo& info,
274 bool adopt_handle) {
275 if (info.handle_id == kInvalidServiceWorkerHandleId)
276 return NULL;
278 WorkerObjectMap::iterator existing_worker =
279 service_workers_.find(info.handle_id);
281 if (existing_worker != service_workers_.end()) {
282 if (adopt_handle) {
283 // We are instructed to adopt a handle but we already have one, so
284 // adopt and destroy a handle ref.
285 ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
287 return existing_worker->second;
290 scoped_ptr<ServiceWorkerHandleReference> handle_ref =
291 adopt_handle
292 ? ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get())
293 : ServiceWorkerHandleReference::Create(info,
294 thread_safe_sender_.get());
295 // WebServiceWorkerImpl constructor calls AddServiceWorker.
296 return new WebServiceWorkerImpl(handle_ref.Pass(), thread_safe_sender_.get());
299 WebServiceWorkerRegistrationImpl*
300 ServiceWorkerDispatcher::CreateServiceWorkerRegistration(
301 const ServiceWorkerRegistrationObjectInfo& info,
302 bool adopt_handle) {
303 DCHECK(!ContainsKey(registrations_, info.handle_id));
304 if (info.handle_id == kInvalidServiceWorkerRegistrationHandleId)
305 return NULL;
307 scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref =
308 adopt_handle ? ServiceWorkerRegistrationHandleReference::Adopt(
309 info, thread_safe_sender_.get())
310 : ServiceWorkerRegistrationHandleReference::Create(
311 info, thread_safe_sender_.get());
313 // WebServiceWorkerRegistrationImpl constructor calls
314 // AddServiceWorkerRegistration.
315 return new WebServiceWorkerRegistrationImpl(handle_ref.Pass());
318 // We can assume that this message handler is called before the worker context
319 // starts because script loading happens after this association.
320 // TODO(nhiroki): This association information could be pushed into
321 // EmbeddedWorkerMsg_StartWorker message and handed over to the worker thread
322 // without a lock in ServiceWorkerProviderContext.
323 void ServiceWorkerDispatcher::OnAssociateRegistrationWithServiceWorker(
324 int thread_id,
325 int provider_id,
326 const ServiceWorkerRegistrationObjectInfo& info,
327 const ServiceWorkerVersionAttributes& attrs) {
328 DCHECK_EQ(kDocumentMainThreadId, thread_id);
330 ProviderContextMap::iterator context = provider_contexts_.find(provider_id);
331 if (context == provider_contexts_.end())
332 return;
333 context->second->OnAssociateRegistration(info, attrs);
335 // We don't have to add entries into |worker_to_provider_| because state
336 // change events for the workers will be notified on the worker thread.
339 void ServiceWorkerDispatcher::OnAssociateRegistration(
340 int thread_id,
341 int provider_id,
342 const ServiceWorkerRegistrationObjectInfo& info,
343 const ServiceWorkerVersionAttributes& attrs) {
344 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
345 if (provider == provider_contexts_.end())
346 return;
347 provider->second->OnAssociateRegistration(info, attrs);
348 if (attrs.installing.handle_id != kInvalidServiceWorkerHandleId)
349 worker_to_provider_[attrs.installing.handle_id] = provider->second;
350 if (attrs.waiting.handle_id != kInvalidServiceWorkerHandleId)
351 worker_to_provider_[attrs.waiting.handle_id] = provider->second;
352 if (attrs.active.handle_id != kInvalidServiceWorkerHandleId)
353 worker_to_provider_[attrs.active.handle_id] = provider->second;
356 void ServiceWorkerDispatcher::OnDisassociateRegistration(
357 int thread_id,
358 int provider_id) {
359 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
360 if (provider == provider_contexts_.end())
361 return;
362 worker_to_provider_.erase(provider->second->installing_handle_id());
363 worker_to_provider_.erase(provider->second->waiting_handle_id());
364 worker_to_provider_.erase(provider->second->active_handle_id());
365 worker_to_provider_.erase(provider->second->controller_handle_id());
366 provider->second->OnDisassociateRegistration();
369 void ServiceWorkerDispatcher::OnRegistered(
370 int thread_id,
371 int request_id,
372 const ServiceWorkerRegistrationObjectInfo& info,
373 const ServiceWorkerVersionAttributes& attrs) {
374 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
375 "ServiceWorkerDispatcher::RegisterServiceWorker",
376 request_id,
377 "OnRegistered");
378 TRACE_EVENT_ASYNC_END0("ServiceWorker",
379 "ServiceWorkerDispatcher::RegisterServiceWorker",
380 request_id);
381 WebServiceWorkerRegistrationCallbacks* callbacks =
382 pending_registration_callbacks_.Lookup(request_id);
383 DCHECK(callbacks);
384 if (!callbacks)
385 return;
387 callbacks->onSuccess(FindOrCreateRegistration(info, attrs));
388 pending_registration_callbacks_.Remove(request_id);
391 void ServiceWorkerDispatcher::OnUpdated(int thread_id, int request_id) {
392 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
393 "ServiceWorkerDispatcher::UpdateServiceWorker",
394 request_id, "OnUpdated");
395 TRACE_EVENT_ASYNC_END0("ServiceWorker",
396 "ServiceWorkerDispatcher::UpdateServiceWorker",
397 request_id);
398 WebServiceWorkerUpdateCallbacks* callbacks =
399 pending_update_callbacks_.Lookup(request_id);
400 DCHECK(callbacks);
401 if (!callbacks)
402 return;
404 callbacks->onSuccess();
405 pending_update_callbacks_.Remove(request_id);
408 void ServiceWorkerDispatcher::OnUnregistered(int thread_id,
409 int request_id,
410 bool is_success) {
411 TRACE_EVENT_ASYNC_STEP_INTO0(
412 "ServiceWorker",
413 "ServiceWorkerDispatcher::UnregisterServiceWorker",
414 request_id,
415 "OnUnregistered");
416 TRACE_EVENT_ASYNC_END0("ServiceWorker",
417 "ServiceWorkerDispatcher::UnregisterServiceWorker",
418 request_id);
419 WebServiceWorkerUnregistrationCallbacks* callbacks =
420 pending_unregistration_callbacks_.Lookup(request_id);
421 DCHECK(callbacks);
422 if (!callbacks)
423 return;
424 callbacks->onSuccess(is_success);
425 pending_unregistration_callbacks_.Remove(request_id);
428 void ServiceWorkerDispatcher::OnDidGetRegistration(
429 int thread_id,
430 int request_id,
431 const ServiceWorkerRegistrationObjectInfo& info,
432 const ServiceWorkerVersionAttributes& attrs) {
433 TRACE_EVENT_ASYNC_STEP_INTO0(
434 "ServiceWorker",
435 "ServiceWorkerDispatcher::GetRegistration",
436 request_id,
437 "OnDidGetRegistration");
438 TRACE_EVENT_ASYNC_END0("ServiceWorker",
439 "ServiceWorkerDispatcher::GetRegistration",
440 request_id);
441 WebServiceWorkerRegistrationCallbacks* callbacks =
442 pending_get_registration_callbacks_.Lookup(request_id);
443 DCHECK(callbacks);
444 if (!callbacks)
445 return;
447 WebServiceWorkerRegistrationImpl* registration = NULL;
448 if (info.handle_id != kInvalidServiceWorkerHandleId)
449 registration = FindOrCreateRegistration(info, attrs);
451 callbacks->onSuccess(registration);
452 pending_get_registration_callbacks_.Remove(request_id);
455 void ServiceWorkerDispatcher::OnDidGetRegistrations(
456 int thread_id,
457 int request_id,
458 const std::vector<ServiceWorkerRegistrationObjectInfo>& infos,
459 const std::vector<ServiceWorkerVersionAttributes>& attrs) {
460 TRACE_EVENT_ASYNC_STEP_INTO0(
461 "ServiceWorker",
462 "ServiceWorkerDispatcher::GetRegistrations",
463 request_id,
464 "OnDidGetRegistrations");
465 TRACE_EVENT_ASYNC_END0("ServiceWorker",
466 "ServiceWorkerDispatcher::GetRegistrations",
467 request_id);
469 WebServiceWorkerGetRegistrationsCallbacks* callbacks =
470 pending_get_registrations_callbacks_.Lookup(request_id);
471 DCHECK(callbacks);
472 if (!callbacks)
473 return;
475 typedef blink::WebVector<blink::WebServiceWorkerRegistration*>
476 WebServiceWorkerRegistrationArray;
477 WebServiceWorkerRegistrationArray* registrations =
478 new WebServiceWorkerRegistrationArray(infos.size());
479 for (size_t i = 0; i < infos.size(); ++i) {
480 if (infos[i].handle_id != kInvalidServiceWorkerHandleId) {
481 ServiceWorkerRegistrationObjectInfo info(infos[i]);
482 ServiceWorkerVersionAttributes attr(attrs[i]);
483 (*registrations)[i] = FindOrCreateRegistration(info, attr);
487 callbacks->onSuccess(registrations);
488 pending_get_registrations_callbacks_.Remove(request_id);
491 void ServiceWorkerDispatcher::OnDidGetRegistrationForReady(
492 int thread_id,
493 int request_id,
494 const ServiceWorkerRegistrationObjectInfo& info,
495 const ServiceWorkerVersionAttributes& attrs) {
496 TRACE_EVENT_ASYNC_STEP_INTO0(
497 "ServiceWorker",
498 "ServiceWorkerDispatcher::GetRegistrationForReady",
499 request_id,
500 "OnDidGetRegistrationForReady");
501 TRACE_EVENT_ASYNC_END0("ServiceWorker",
502 "ServiceWorkerDispatcher::GetRegistrationForReady",
503 request_id);
504 WebServiceWorkerGetRegistrationForReadyCallbacks* callbacks =
505 get_for_ready_callbacks_.Lookup(request_id);
506 DCHECK(callbacks);
507 if (!callbacks)
508 return;
510 WebServiceWorkerRegistrationImpl* registration = NULL;
511 DCHECK(info.handle_id != kInvalidServiceWorkerHandleId);
512 registration = FindOrCreateRegistration(info, attrs);
513 callbacks->onSuccess(registration);
514 get_for_ready_callbacks_.Remove(request_id);
517 void ServiceWorkerDispatcher::OnRegistrationError(
518 int thread_id,
519 int request_id,
520 WebServiceWorkerError::ErrorType error_type,
521 const base::string16& message) {
522 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
523 "ServiceWorkerDispatcher::RegisterServiceWorker",
524 request_id,
525 "OnRegistrationError");
526 TRACE_EVENT_ASYNC_END0("ServiceWorker",
527 "ServiceWorkerDispatcher::RegisterServiceWorker",
528 request_id);
529 WebServiceWorkerRegistrationCallbacks* callbacks =
530 pending_registration_callbacks_.Lookup(request_id);
531 DCHECK(callbacks);
532 if (!callbacks)
533 return;
535 callbacks->onError(new WebServiceWorkerError(error_type, message));
536 pending_registration_callbacks_.Remove(request_id);
539 void ServiceWorkerDispatcher::OnUpdateError(
540 int thread_id,
541 int request_id,
542 WebServiceWorkerError::ErrorType error_type,
543 const base::string16& message) {
544 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
545 "ServiceWorkerDispatcher::UpdateServiceWorker",
546 request_id, "OnUpdateError");
547 TRACE_EVENT_ASYNC_END0("ServiceWorker",
548 "ServiceWorkerDispatcher::UpdateServiceWorker",
549 request_id);
550 WebServiceWorkerUpdateCallbacks* callbacks =
551 pending_update_callbacks_.Lookup(request_id);
552 DCHECK(callbacks);
553 if (!callbacks)
554 return;
556 callbacks->onError(WebServiceWorkerError(error_type, message));
557 pending_update_callbacks_.Remove(request_id);
560 void ServiceWorkerDispatcher::OnUnregistrationError(
561 int thread_id,
562 int request_id,
563 WebServiceWorkerError::ErrorType error_type,
564 const base::string16& message) {
565 TRACE_EVENT_ASYNC_STEP_INTO0(
566 "ServiceWorker",
567 "ServiceWorkerDispatcher::UnregisterServiceWorker",
568 request_id,
569 "OnUnregistrationError");
570 TRACE_EVENT_ASYNC_END0("ServiceWorker",
571 "ServiceWorkerDispatcher::UnregisterServiceWorker",
572 request_id);
573 WebServiceWorkerUnregistrationCallbacks* callbacks =
574 pending_unregistration_callbacks_.Lookup(request_id);
575 DCHECK(callbacks);
576 if (!callbacks)
577 return;
579 callbacks->onError(WebServiceWorkerError(error_type, message));
580 pending_unregistration_callbacks_.Remove(request_id);
583 void ServiceWorkerDispatcher::OnGetRegistrationError(
584 int thread_id,
585 int request_id,
586 WebServiceWorkerError::ErrorType error_type,
587 const base::string16& message) {
588 TRACE_EVENT_ASYNC_STEP_INTO0(
589 "ServiceWorker",
590 "ServiceWorkerDispatcher::GetRegistration",
591 request_id,
592 "OnGetRegistrationError");
593 TRACE_EVENT_ASYNC_END0("ServiceWorker",
594 "ServiceWorkerDispatcher::GetRegistration",
595 request_id);
596 WebServiceWorkerGetRegistrationCallbacks* callbacks =
597 pending_get_registration_callbacks_.Lookup(request_id);
598 DCHECK(callbacks);
599 if (!callbacks)
600 return;
602 callbacks->onError(new WebServiceWorkerError(error_type, message));
603 pending_get_registration_callbacks_.Remove(request_id);
606 void ServiceWorkerDispatcher::OnGetRegistrationsError(
607 int thread_id,
608 int request_id,
609 WebServiceWorkerError::ErrorType error_type,
610 const base::string16& message) {
611 TRACE_EVENT_ASYNC_STEP_INTO0(
612 "ServiceWorker",
613 "ServiceWorkerDispatcher::GetRegistrations",
614 request_id,
615 "OnGetRegistrationsError");
616 TRACE_EVENT_ASYNC_END0("ServiceWorker",
617 "ServiceWorkerDispatcher::GetRegistrations",
618 request_id);
619 WebServiceWorkerGetRegistrationsCallbacks* callbacks =
620 pending_get_registrations_callbacks_.Lookup(request_id);
621 DCHECK(callbacks);
622 if (!callbacks)
623 return;
625 callbacks->onError(new WebServiceWorkerError(error_type, message));
626 pending_get_registrations_callbacks_.Remove(request_id);
629 void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
630 int thread_id,
631 int handle_id,
632 blink::WebServiceWorkerState state) {
633 TRACE_EVENT2("ServiceWorker",
634 "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
635 "Thread ID", thread_id,
636 "State", state);
637 WorkerObjectMap::iterator worker = service_workers_.find(handle_id);
638 if (worker != service_workers_.end())
639 worker->second->OnStateChanged(state);
641 WorkerToProviderMap::iterator provider = worker_to_provider_.find(handle_id);
642 if (provider != worker_to_provider_.end())
643 provider->second->OnServiceWorkerStateChanged(handle_id, state);
646 void ServiceWorkerDispatcher::OnSetVersionAttributes(
647 int thread_id,
648 int provider_id,
649 int registration_handle_id,
650 int changed_mask,
651 const ServiceWorkerVersionAttributes& attrs) {
652 TRACE_EVENT1("ServiceWorker",
653 "ServiceWorkerDispatcher::OnSetVersionAttributes",
654 "Thread ID", thread_id);
656 ChangedVersionAttributesMask mask(changed_mask);
657 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
658 if (provider != provider_contexts_.end() &&
659 provider->second->registration_handle_id() == registration_handle_id) {
660 if (mask.installing_changed()) {
661 worker_to_provider_.erase(provider->second->installing_handle_id());
662 if (attrs.installing.handle_id != kInvalidServiceWorkerHandleId)
663 worker_to_provider_[attrs.installing.handle_id] = provider->second;
665 if (mask.waiting_changed()) {
666 worker_to_provider_.erase(provider->second->waiting_handle_id());
667 if (attrs.waiting.handle_id != kInvalidServiceWorkerHandleId)
668 worker_to_provider_[attrs.waiting.handle_id] = provider->second;
670 if (mask.active_changed()) {
671 worker_to_provider_.erase(provider->second->active_handle_id());
672 if (attrs.active.handle_id != kInvalidServiceWorkerHandleId)
673 worker_to_provider_[attrs.active.handle_id] = provider->second;
675 provider->second->SetVersionAttributes(mask, attrs);
678 RegistrationObjectMap::iterator found =
679 registrations_.find(registration_handle_id);
680 if (found != registrations_.end()) {
681 // Populate the version fields (eg. .installing) with new worker objects.
682 if (mask.installing_changed())
683 found->second->SetInstalling(GetServiceWorker(attrs.installing, false));
684 if (mask.waiting_changed())
685 found->second->SetWaiting(GetServiceWorker(attrs.waiting, false));
686 if (mask.active_changed())
687 found->second->SetActive(GetServiceWorker(attrs.active, false));
691 void ServiceWorkerDispatcher::OnUpdateFound(
692 int thread_id,
693 int registration_handle_id) {
694 TRACE_EVENT0("ServiceWorker",
695 "ServiceWorkerDispatcher::OnUpdateFound");
696 RegistrationObjectMap::iterator found =
697 registrations_.find(registration_handle_id);
698 if (found != registrations_.end())
699 found->second->OnUpdateFound();
702 void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
703 int thread_id,
704 int provider_id,
705 const ServiceWorkerObjectInfo& info,
706 bool should_notify_controllerchange) {
707 TRACE_EVENT2("ServiceWorker",
708 "ServiceWorkerDispatcher::OnSetControllerServiceWorker",
709 "Thread ID", thread_id,
710 "Provider ID", provider_id);
712 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
713 if (provider != provider_contexts_.end()) {
714 worker_to_provider_.erase(provider->second->controller_handle_id());
715 if (info.handle_id != kInvalidServiceWorkerHandleId)
716 worker_to_provider_[info.handle_id] = provider->second;
717 provider->second->OnSetControllerServiceWorker(info);
720 ProviderClientMap::iterator found = provider_clients_.find(provider_id);
721 if (found != provider_clients_.end()) {
722 // Populate the .controller field with the new worker object.
723 found->second->setController(GetServiceWorker(info, false),
724 should_notify_controllerchange);
728 void ServiceWorkerDispatcher::OnPostMessage(
729 const ServiceWorkerMsg_MessageToDocument_Params& params) {
730 // Make sure we're on the main document thread. (That must be the only
731 // thread we get this message)
732 DCHECK(ChildThreadImpl::current());
733 TRACE_EVENT1("ServiceWorker", "ServiceWorkerDispatcher::OnPostMessage",
734 "Thread ID", params.thread_id);
736 ProviderClientMap::iterator found =
737 provider_clients_.find(params.provider_id);
738 if (found == provider_clients_.end()) {
739 // For now we do no queueing for messages sent to nonexistent / unattached
740 // client.
741 return;
744 blink::WebMessagePortChannelArray ports =
745 WebMessagePortChannelImpl::CreatePorts(
746 params.message_ports, params.new_routing_ids,
747 base::ThreadTaskRunnerHandle::Get());
749 found->second->dispatchMessageEvent(
750 GetServiceWorker(params.service_worker_info, false /* adopt_handle */),
751 params.message, ports);
754 void ServiceWorkerDispatcher::AddServiceWorker(
755 int handle_id, WebServiceWorkerImpl* worker) {
756 DCHECK(!ContainsKey(service_workers_, handle_id));
757 service_workers_[handle_id] = worker;
760 void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id) {
761 DCHECK(ContainsKey(service_workers_, handle_id));
762 service_workers_.erase(handle_id);
765 void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
766 int registration_handle_id,
767 WebServiceWorkerRegistrationImpl* registration) {
768 DCHECK(!ContainsKey(registrations_, registration_handle_id));
769 registrations_[registration_handle_id] = registration;
772 void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
773 int registration_handle_id) {
774 DCHECK(ContainsKey(registrations_, registration_handle_id));
775 registrations_.erase(registration_handle_id);
778 WebServiceWorkerRegistrationImpl*
779 ServiceWorkerDispatcher::FindOrCreateRegistration(
780 const ServiceWorkerRegistrationObjectInfo& info,
781 const ServiceWorkerVersionAttributes& attrs) {
782 RegistrationObjectMap::iterator found = registrations_.find(info.handle_id);
783 if (found != registrations_.end()) {
784 ServiceWorkerRegistrationHandleReference::Adopt(info,
785 thread_safe_sender_.get());
786 ServiceWorkerHandleReference::Adopt(attrs.installing,
787 thread_safe_sender_.get());
788 ServiceWorkerHandleReference::Adopt(attrs.waiting,
789 thread_safe_sender_.get());
790 ServiceWorkerHandleReference::Adopt(attrs.active,
791 thread_safe_sender_.get());
792 return found->second;
795 bool adopt_handle = true;
796 WebServiceWorkerRegistrationImpl* registration =
797 CreateServiceWorkerRegistration(info, adopt_handle);
798 registration->SetInstalling(GetServiceWorker(attrs.installing, adopt_handle));
799 registration->SetWaiting(GetServiceWorker(attrs.waiting, adopt_handle));
800 registration->SetActive(GetServiceWorker(attrs.active, adopt_handle));
801 return registration;
804 } // namespace content