Fix link in German terms of service.
[chromium-blink-merge.git] / content / child / service_worker / service_worker_dispatcher.cc
blobe68f64451ba918e53105238a7f6daec12016fdd6
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_DidGetRegistrationForReady,
73 OnDidGetRegistrationForReady)
74 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError,
75 OnRegistrationError)
76 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistrationError,
77 OnUnregistrationError)
78 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationError,
79 OnGetRegistrationError)
80 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged,
81 OnServiceWorkerStateChanged)
82 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes,
83 OnSetVersionAttributes)
84 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_UpdateFound,
85 OnUpdateFound)
86 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker,
87 OnSetControllerServiceWorker)
88 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument,
89 OnPostMessage)
90 IPC_MESSAGE_UNHANDLED(handled = false)
91 IPC_END_MESSAGE_MAP()
92 DCHECK(handled) << "Unhandled message:" << msg.type();
95 bool ServiceWorkerDispatcher::Send(IPC::Message* msg) {
96 return thread_safe_sender_->Send(msg);
99 void ServiceWorkerDispatcher::RegisterServiceWorker(
100 int provider_id,
101 const GURL& pattern,
102 const GURL& script_url,
103 WebServiceWorkerRegistrationCallbacks* callbacks) {
104 DCHECK(callbacks);
106 if (pattern.possibly_invalid_spec().size() > GetMaxURLChars() ||
107 script_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
108 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
109 owned_callbacks(callbacks);
110 std::string error_message(kServiceWorkerRegisterErrorPrefix);
111 error_message += "The provided scriptURL or scope is too long.";
112 scoped_ptr<WebServiceWorkerError> error(
113 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity,
114 blink::WebString::fromUTF8(error_message)));
115 callbacks->onError(error.release());
116 return;
119 int request_id = pending_registration_callbacks_.Add(callbacks);
120 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
121 "ServiceWorkerDispatcher::RegisterServiceWorker",
122 request_id,
123 "Scope", pattern.spec(),
124 "Script URL", script_url.spec());
125 thread_safe_sender_->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
126 CurrentWorkerId(), request_id, provider_id, pattern, script_url));
129 void ServiceWorkerDispatcher::UnregisterServiceWorker(
130 int provider_id,
131 const GURL& pattern,
132 WebServiceWorkerUnregistrationCallbacks* callbacks) {
133 DCHECK(callbacks);
135 if (pattern.possibly_invalid_spec().size() > GetMaxURLChars()) {
136 scoped_ptr<WebServiceWorkerUnregistrationCallbacks>
137 owned_callbacks(callbacks);
138 std::string error_message(kServiceWorkerUnregisterErrorPrefix);
139 error_message += "The provided scope is too long.";
140 scoped_ptr<WebServiceWorkerError> error(
141 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity,
142 blink::WebString::fromUTF8(error_message)));
143 callbacks->onError(error.release());
144 return;
147 int request_id = pending_unregistration_callbacks_.Add(callbacks);
148 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
149 "ServiceWorkerDispatcher::UnregisterServiceWorker",
150 request_id,
151 "Scope", pattern.spec());
152 thread_safe_sender_->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
153 CurrentWorkerId(), request_id, provider_id, pattern));
156 void ServiceWorkerDispatcher::GetRegistration(
157 int provider_id,
158 const GURL& document_url,
159 WebServiceWorkerRegistrationCallbacks* callbacks) {
160 DCHECK(callbacks);
162 if (document_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
163 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
164 owned_callbacks(callbacks);
165 std::string error_message(kServiceWorkerGetRegistrationErrorPrefix);
166 error_message += "The provided documentURL is too long.";
167 scoped_ptr<WebServiceWorkerError> error(
168 new WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity,
169 blink::WebString::fromUTF8(error_message)));
170 callbacks->onError(error.release());
171 return;
174 int request_id = pending_get_registration_callbacks_.Add(callbacks);
175 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
176 "ServiceWorkerDispatcher::GetRegistration",
177 request_id,
178 "Document URL", document_url.spec());
179 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistration(
180 CurrentWorkerId(), request_id, provider_id, document_url));
183 void ServiceWorkerDispatcher::GetRegistrationForReady(
184 int provider_id,
185 WebServiceWorkerGetRegistrationForReadyCallbacks* callbacks) {
186 int request_id = get_for_ready_callbacks_.Add(callbacks);
187 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
188 "ServiceWorkerDispatcher::GetRegistrationForReady",
189 request_id);
190 thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistrationForReady(
191 CurrentWorkerId(), request_id, provider_id));
194 void ServiceWorkerDispatcher::AddProviderContext(
195 ServiceWorkerProviderContext* provider_context) {
196 DCHECK(provider_context);
197 int provider_id = provider_context->provider_id();
198 DCHECK(!ContainsKey(provider_contexts_, provider_id));
199 provider_contexts_[provider_id] = provider_context;
202 void ServiceWorkerDispatcher::RemoveProviderContext(
203 ServiceWorkerProviderContext* provider_context) {
204 DCHECK(provider_context);
205 DCHECK(ContainsKey(provider_contexts_, provider_context->provider_id()));
206 provider_contexts_.erase(provider_context->provider_id());
207 worker_to_provider_.erase(provider_context->installing_handle_id());
208 worker_to_provider_.erase(provider_context->waiting_handle_id());
209 worker_to_provider_.erase(provider_context->active_handle_id());
210 worker_to_provider_.erase(provider_context->controller_handle_id());
213 void ServiceWorkerDispatcher::AddProviderClient(
214 int provider_id,
215 blink::WebServiceWorkerProviderClient* client) {
216 DCHECK(client);
217 DCHECK(!ContainsKey(provider_clients_, provider_id));
218 provider_clients_[provider_id] = client;
221 void ServiceWorkerDispatcher::RemoveProviderClient(int provider_id) {
222 // This could be possibly called multiple times to ensure termination.
223 if (ContainsKey(provider_clients_, provider_id))
224 provider_clients_.erase(provider_id);
227 ServiceWorkerDispatcher*
228 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
229 ThreadSafeSender* thread_safe_sender) {
230 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
231 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
232 g_dispatcher_tls.Pointer()->Set(NULL);
234 if (g_dispatcher_tls.Pointer()->Get())
235 return g_dispatcher_tls.Pointer()->Get();
237 ServiceWorkerDispatcher* dispatcher =
238 new ServiceWorkerDispatcher(thread_safe_sender);
239 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
240 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
241 return dispatcher;
244 ServiceWorkerDispatcher* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
245 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted)
246 return NULL;
247 return g_dispatcher_tls.Pointer()->Get();
250 void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
251 delete this;
254 WebServiceWorkerImpl* ServiceWorkerDispatcher::GetServiceWorker(
255 const ServiceWorkerObjectInfo& info,
256 bool adopt_handle) {
257 if (info.handle_id == kInvalidServiceWorkerHandleId)
258 return NULL;
260 WorkerObjectMap::iterator existing_worker =
261 service_workers_.find(info.handle_id);
263 if (existing_worker != service_workers_.end()) {
264 if (adopt_handle) {
265 // We are instructed to adopt a handle but we already have one, so
266 // adopt and destroy a handle ref.
267 ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
269 return existing_worker->second;
272 scoped_ptr<ServiceWorkerHandleReference> handle_ref =
273 adopt_handle
274 ? ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get())
275 : ServiceWorkerHandleReference::Create(info,
276 thread_safe_sender_.get());
277 // WebServiceWorkerImpl constructor calls AddServiceWorker.
278 return new WebServiceWorkerImpl(handle_ref.Pass(), thread_safe_sender_.get());
281 WebServiceWorkerRegistrationImpl*
282 ServiceWorkerDispatcher::CreateServiceWorkerRegistration(
283 const ServiceWorkerRegistrationObjectInfo& info,
284 bool adopt_handle) {
285 DCHECK(!ContainsKey(registrations_, info.handle_id));
286 if (info.handle_id == kInvalidServiceWorkerRegistrationHandleId)
287 return NULL;
289 scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref =
290 adopt_handle ? ServiceWorkerRegistrationHandleReference::Adopt(
291 info, thread_safe_sender_.get())
292 : ServiceWorkerRegistrationHandleReference::Create(
293 info, thread_safe_sender_.get());
295 // WebServiceWorkerRegistrationImpl constructor calls
296 // AddServiceWorkerRegistration.
297 return new WebServiceWorkerRegistrationImpl(handle_ref.Pass());
300 // We can assume that this message handler is called before the worker context
301 // starts because script loading happens after this association.
302 // TODO(nhiroki): This association information could be pushed into
303 // EmbeddedWorkerMsg_StartWorker message and handed over to the worker thread
304 // without a lock in ServiceWorkerProviderContext.
305 void ServiceWorkerDispatcher::OnAssociateRegistrationWithServiceWorker(
306 int thread_id,
307 int provider_id,
308 const ServiceWorkerRegistrationObjectInfo& info,
309 const ServiceWorkerVersionAttributes& attrs) {
310 DCHECK_EQ(kDocumentMainThreadId, thread_id);
312 ProviderContextMap::iterator context = provider_contexts_.find(provider_id);
313 if (context == provider_contexts_.end())
314 return;
315 context->second->OnAssociateRegistration(info, attrs);
317 // We don't have to add entries into |worker_to_provider_| because state
318 // change events for the workers will be notified on the worker thread.
321 void ServiceWorkerDispatcher::OnAssociateRegistration(
322 int thread_id,
323 int provider_id,
324 const ServiceWorkerRegistrationObjectInfo& info,
325 const ServiceWorkerVersionAttributes& attrs) {
326 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
327 if (provider == provider_contexts_.end())
328 return;
329 provider->second->OnAssociateRegistration(info, attrs);
330 if (attrs.installing.handle_id != kInvalidServiceWorkerHandleId)
331 worker_to_provider_[attrs.installing.handle_id] = provider->second;
332 if (attrs.waiting.handle_id != kInvalidServiceWorkerHandleId)
333 worker_to_provider_[attrs.waiting.handle_id] = provider->second;
334 if (attrs.active.handle_id != kInvalidServiceWorkerHandleId)
335 worker_to_provider_[attrs.active.handle_id] = provider->second;
338 void ServiceWorkerDispatcher::OnDisassociateRegistration(
339 int thread_id,
340 int provider_id) {
341 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
342 if (provider == provider_contexts_.end())
343 return;
344 worker_to_provider_.erase(provider->second->installing_handle_id());
345 worker_to_provider_.erase(provider->second->waiting_handle_id());
346 worker_to_provider_.erase(provider->second->active_handle_id());
347 worker_to_provider_.erase(provider->second->controller_handle_id());
348 provider->second->OnDisassociateRegistration();
351 void ServiceWorkerDispatcher::OnRegistered(
352 int thread_id,
353 int request_id,
354 const ServiceWorkerRegistrationObjectInfo& info,
355 const ServiceWorkerVersionAttributes& attrs) {
356 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
357 "ServiceWorkerDispatcher::RegisterServiceWorker",
358 request_id,
359 "OnRegistered");
360 TRACE_EVENT_ASYNC_END0("ServiceWorker",
361 "ServiceWorkerDispatcher::RegisterServiceWorker",
362 request_id);
363 WebServiceWorkerRegistrationCallbacks* callbacks =
364 pending_registration_callbacks_.Lookup(request_id);
365 DCHECK(callbacks);
366 if (!callbacks)
367 return;
369 callbacks->onSuccess(FindOrCreateRegistration(info, attrs));
370 pending_registration_callbacks_.Remove(request_id);
373 void ServiceWorkerDispatcher::OnUnregistered(int thread_id,
374 int request_id,
375 bool is_success) {
376 TRACE_EVENT_ASYNC_STEP_INTO0(
377 "ServiceWorker",
378 "ServiceWorkerDispatcher::UnregisterServiceWorker",
379 request_id,
380 "OnUnregistered");
381 TRACE_EVENT_ASYNC_END0("ServiceWorker",
382 "ServiceWorkerDispatcher::UnregisterServiceWorker",
383 request_id);
384 WebServiceWorkerUnregistrationCallbacks* callbacks =
385 pending_unregistration_callbacks_.Lookup(request_id);
386 DCHECK(callbacks);
387 if (!callbacks)
388 return;
389 callbacks->onSuccess(&is_success);
390 pending_unregistration_callbacks_.Remove(request_id);
393 void ServiceWorkerDispatcher::OnDidGetRegistration(
394 int thread_id,
395 int request_id,
396 const ServiceWorkerRegistrationObjectInfo& info,
397 const ServiceWorkerVersionAttributes& attrs) {
398 TRACE_EVENT_ASYNC_STEP_INTO0(
399 "ServiceWorker",
400 "ServiceWorkerDispatcher::GetRegistration",
401 request_id,
402 "OnDidGetRegistration");
403 TRACE_EVENT_ASYNC_END0("ServiceWorker",
404 "ServiceWorkerDispatcher::GetRegistration",
405 request_id);
406 WebServiceWorkerRegistrationCallbacks* callbacks =
407 pending_get_registration_callbacks_.Lookup(request_id);
408 DCHECK(callbacks);
409 if (!callbacks)
410 return;
412 WebServiceWorkerRegistrationImpl* registration = NULL;
413 if (info.handle_id != kInvalidServiceWorkerHandleId)
414 registration = FindOrCreateRegistration(info, attrs);
416 callbacks->onSuccess(registration);
417 pending_get_registration_callbacks_.Remove(request_id);
420 void ServiceWorkerDispatcher::OnDidGetRegistrationForReady(
421 int thread_id,
422 int request_id,
423 const ServiceWorkerRegistrationObjectInfo& info,
424 const ServiceWorkerVersionAttributes& attrs) {
425 TRACE_EVENT_ASYNC_STEP_INTO0(
426 "ServiceWorker",
427 "ServiceWorkerDispatcher::GetRegistrationForReady",
428 request_id,
429 "OnDidGetRegistrationForReady");
430 TRACE_EVENT_ASYNC_END0("ServiceWorker",
431 "ServiceWorkerDispatcher::GetRegistrationForReady",
432 request_id);
433 WebServiceWorkerGetRegistrationForReadyCallbacks* callbacks =
434 get_for_ready_callbacks_.Lookup(request_id);
435 DCHECK(callbacks);
436 if (!callbacks)
437 return;
439 WebServiceWorkerRegistrationImpl* registration = NULL;
440 DCHECK(info.handle_id != kInvalidServiceWorkerHandleId);
441 registration = FindOrCreateRegistration(info, attrs);
442 callbacks->onSuccess(registration);
443 get_for_ready_callbacks_.Remove(request_id);
446 void ServiceWorkerDispatcher::OnRegistrationError(
447 int thread_id,
448 int request_id,
449 WebServiceWorkerError::ErrorType error_type,
450 const base::string16& message) {
451 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
452 "ServiceWorkerDispatcher::RegisterServiceWorker",
453 request_id,
454 "OnRegistrationError");
455 TRACE_EVENT_ASYNC_END0("ServiceWorker",
456 "ServiceWorkerDispatcher::RegisterServiceWorker",
457 request_id);
458 WebServiceWorkerRegistrationCallbacks* callbacks =
459 pending_registration_callbacks_.Lookup(request_id);
460 DCHECK(callbacks);
461 if (!callbacks)
462 return;
464 scoped_ptr<WebServiceWorkerError> error(
465 new WebServiceWorkerError(error_type, message));
466 callbacks->onError(error.release());
467 pending_registration_callbacks_.Remove(request_id);
470 void ServiceWorkerDispatcher::OnUnregistrationError(
471 int thread_id,
472 int request_id,
473 WebServiceWorkerError::ErrorType error_type,
474 const base::string16& message) {
475 TRACE_EVENT_ASYNC_STEP_INTO0(
476 "ServiceWorker",
477 "ServiceWorkerDispatcher::UnregisterServiceWorker",
478 request_id,
479 "OnUnregistrationError");
480 TRACE_EVENT_ASYNC_END0("ServiceWorker",
481 "ServiceWorkerDispatcher::UnregisterServiceWorker",
482 request_id);
483 WebServiceWorkerUnregistrationCallbacks* callbacks =
484 pending_unregistration_callbacks_.Lookup(request_id);
485 DCHECK(callbacks);
486 if (!callbacks)
487 return;
489 scoped_ptr<WebServiceWorkerError> error(
490 new WebServiceWorkerError(error_type, message));
491 callbacks->onError(error.release());
492 pending_unregistration_callbacks_.Remove(request_id);
495 void ServiceWorkerDispatcher::OnGetRegistrationError(
496 int thread_id,
497 int request_id,
498 WebServiceWorkerError::ErrorType error_type,
499 const base::string16& message) {
500 TRACE_EVENT_ASYNC_STEP_INTO0(
501 "ServiceWorker",
502 "ServiceWorkerDispatcher::GetRegistration",
503 request_id,
504 "OnGetRegistrationError");
505 TRACE_EVENT_ASYNC_END0("ServiceWorker",
506 "ServiceWorkerDispatcher::GetRegistration",
507 request_id);
508 WebServiceWorkerGetRegistrationCallbacks* callbacks =
509 pending_get_registration_callbacks_.Lookup(request_id);
510 DCHECK(callbacks);
511 if (!callbacks)
512 return;
514 scoped_ptr<WebServiceWorkerError> error(
515 new WebServiceWorkerError(error_type, message));
516 callbacks->onError(error.release());
517 pending_get_registration_callbacks_.Remove(request_id);
520 void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
521 int thread_id,
522 int handle_id,
523 blink::WebServiceWorkerState state) {
524 TRACE_EVENT2("ServiceWorker",
525 "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
526 "Thread ID", thread_id,
527 "State", state);
528 WorkerObjectMap::iterator worker = service_workers_.find(handle_id);
529 if (worker != service_workers_.end())
530 worker->second->OnStateChanged(state);
532 WorkerToProviderMap::iterator provider = worker_to_provider_.find(handle_id);
533 if (provider != worker_to_provider_.end())
534 provider->second->OnServiceWorkerStateChanged(handle_id, state);
537 void ServiceWorkerDispatcher::OnSetVersionAttributes(
538 int thread_id,
539 int provider_id,
540 int registration_handle_id,
541 int changed_mask,
542 const ServiceWorkerVersionAttributes& attrs) {
543 TRACE_EVENT1("ServiceWorker",
544 "ServiceWorkerDispatcher::OnSetVersionAttributes",
545 "Thread ID", thread_id);
547 ChangedVersionAttributesMask mask(changed_mask);
548 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
549 if (provider != provider_contexts_.end() &&
550 provider->second->registration_handle_id() == registration_handle_id) {
551 if (mask.installing_changed()) {
552 worker_to_provider_.erase(provider->second->installing_handle_id());
553 if (attrs.installing.handle_id != kInvalidServiceWorkerHandleId)
554 worker_to_provider_[attrs.installing.handle_id] = provider->second;
556 if (mask.waiting_changed()) {
557 worker_to_provider_.erase(provider->second->waiting_handle_id());
558 if (attrs.waiting.handle_id != kInvalidServiceWorkerHandleId)
559 worker_to_provider_[attrs.waiting.handle_id] = provider->second;
561 if (mask.active_changed()) {
562 worker_to_provider_.erase(provider->second->active_handle_id());
563 if (attrs.active.handle_id != kInvalidServiceWorkerHandleId)
564 worker_to_provider_[attrs.active.handle_id] = provider->second;
566 provider->second->SetVersionAttributes(mask, attrs);
569 RegistrationObjectMap::iterator found =
570 registrations_.find(registration_handle_id);
571 if (found != registrations_.end()) {
572 // Populate the version fields (eg. .installing) with new worker objects.
573 if (mask.installing_changed())
574 found->second->SetInstalling(GetServiceWorker(attrs.installing, false));
575 if (mask.waiting_changed())
576 found->second->SetWaiting(GetServiceWorker(attrs.waiting, false));
577 if (mask.active_changed())
578 found->second->SetActive(GetServiceWorker(attrs.active, false));
582 void ServiceWorkerDispatcher::OnUpdateFound(
583 int thread_id,
584 int registration_handle_id) {
585 TRACE_EVENT0("ServiceWorker",
586 "ServiceWorkerDispatcher::OnUpdateFound");
587 RegistrationObjectMap::iterator found =
588 registrations_.find(registration_handle_id);
589 if (found != registrations_.end())
590 found->second->OnUpdateFound();
593 void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
594 int thread_id,
595 int provider_id,
596 const ServiceWorkerObjectInfo& info,
597 bool should_notify_controllerchange) {
598 TRACE_EVENT2("ServiceWorker",
599 "ServiceWorkerDispatcher::OnSetControllerServiceWorker",
600 "Thread ID", thread_id,
601 "Provider ID", provider_id);
603 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
604 if (provider != provider_contexts_.end()) {
605 worker_to_provider_.erase(provider->second->controller_handle_id());
606 if (info.handle_id != kInvalidServiceWorkerHandleId)
607 worker_to_provider_[info.handle_id] = provider->second;
608 provider->second->OnSetControllerServiceWorker(info);
611 ProviderClientMap::iterator found = provider_clients_.find(provider_id);
612 if (found != provider_clients_.end()) {
613 // Populate the .controller field with the new worker object.
614 found->second->setController(GetServiceWorker(info, false),
615 should_notify_controllerchange);
619 void ServiceWorkerDispatcher::OnPostMessage(
620 int thread_id,
621 int provider_id,
622 const base::string16& message,
623 const std::vector<TransferredMessagePort>& sent_message_ports,
624 const std::vector<int>& new_routing_ids) {
625 // Make sure we're on the main document thread. (That must be the only
626 // thread we get this message)
627 DCHECK(ChildThreadImpl::current());
628 TRACE_EVENT1("ServiceWorker",
629 "ServiceWorkerDispatcher::OnPostMessage",
630 "Thread ID", thread_id);
632 ProviderClientMap::iterator found = provider_clients_.find(provider_id);
633 if (found == provider_clients_.end()) {
634 // For now we do no queueing for messages sent to nonexistent / unattached
635 // client.
636 return;
639 blink::WebMessagePortChannelArray ports =
640 WebMessagePortChannelImpl::CreatePorts(
641 sent_message_ports, new_routing_ids,
642 base::ThreadTaskRunnerHandle::Get());
644 found->second->dispatchMessageEvent(message, ports);
647 void ServiceWorkerDispatcher::AddServiceWorker(
648 int handle_id, WebServiceWorkerImpl* worker) {
649 DCHECK(!ContainsKey(service_workers_, handle_id));
650 service_workers_[handle_id] = worker;
653 void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id) {
654 DCHECK(ContainsKey(service_workers_, handle_id));
655 service_workers_.erase(handle_id);
658 void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
659 int registration_handle_id,
660 WebServiceWorkerRegistrationImpl* registration) {
661 DCHECK(!ContainsKey(registrations_, registration_handle_id));
662 registrations_[registration_handle_id] = registration;
665 void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
666 int registration_handle_id) {
667 DCHECK(ContainsKey(registrations_, registration_handle_id));
668 registrations_.erase(registration_handle_id);
671 WebServiceWorkerRegistrationImpl*
672 ServiceWorkerDispatcher::FindOrCreateRegistration(
673 const ServiceWorkerRegistrationObjectInfo& info,
674 const ServiceWorkerVersionAttributes& attrs) {
675 RegistrationObjectMap::iterator found = registrations_.find(info.handle_id);
676 if (found != registrations_.end()) {
677 ServiceWorkerRegistrationHandleReference::Adopt(info,
678 thread_safe_sender_.get());
679 ServiceWorkerHandleReference::Adopt(attrs.installing,
680 thread_safe_sender_.get());
681 ServiceWorkerHandleReference::Adopt(attrs.waiting,
682 thread_safe_sender_.get());
683 ServiceWorkerHandleReference::Adopt(attrs.active,
684 thread_safe_sender_.get());
685 return found->second;
688 bool adopt_handle = true;
689 WebServiceWorkerRegistrationImpl* registration =
690 CreateServiceWorkerRegistration(info, adopt_handle);
691 registration->SetInstalling(GetServiceWorker(attrs.installing, adopt_handle));
692 registration->SetWaiting(GetServiceWorker(attrs.waiting, adopt_handle));
693 registration->SetActive(GetServiceWorker(attrs.active, adopt_handle));
694 return registration;
697 } // namespace content