blob: 255c4bf518e9641e4e7ca2e908aeaef8c9e6857a [file] [log] [blame]
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +00001// 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.
4
5#include "content/child/service_worker/service_worker_dispatcher.h"
6
7#include "base/lazy_instance.h"
Ben Murdocha02191e2014-04-16 11:17:03 +01008#include "base/stl_util.h"
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +00009#include "base/threading/thread_local.h"
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +010010#include "content/child/child_thread.h"
11#include "content/child/service_worker/service_worker_handle_reference.h"
12#include "content/child/service_worker/service_worker_provider_context.h"
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010013#include "content/child/service_worker/service_worker_registration_handle_reference.h"
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000014#include "content/child/service_worker/web_service_worker_impl.h"
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +010015#include "content/child/service_worker/web_service_worker_registration_impl.h"
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000016#include "content/child/thread_safe_sender.h"
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +010017#include "content/child/webmessageportchannel_impl.h"
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000018#include "content/common/service_worker/service_worker_messages.h"
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +010019#include "content/public/common/url_utils.h"
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +010020#include "third_party/WebKit/public/platform/WebServiceWorkerProviderClient.h"
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000021#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
22
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +000023using blink::WebServiceWorkerError;
24using blink::WebServiceWorkerProvider;
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000025using base::ThreadLocalPointer;
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000026
27namespace content {
28
29namespace {
30
31base::LazyInstance<ThreadLocalPointer<ServiceWorkerDispatcher> >::Leaky
32 g_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
33
34ServiceWorkerDispatcher* const kHasBeenDeleted =
35 reinterpret_cast<ServiceWorkerDispatcher*>(0x1);
36
37int CurrentWorkerId() {
38 return WorkerTaskRunner::Instance()->CurrentWorkerId();
39}
40
41} // namespace
42
43ServiceWorkerDispatcher::ServiceWorkerDispatcher(
44 ThreadSafeSender* thread_safe_sender)
45 : thread_safe_sender_(thread_safe_sender) {
46 g_dispatcher_tls.Pointer()->Set(this);
47}
48
49ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
50 g_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
51}
52
53void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message& msg) {
54 bool handled = true;
55 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher, msg)
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +000056 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered, OnRegistered)
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000057 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered,
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +000058 OnUnregistered)
59 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError,
60 OnRegistrationError)
Ben Murdocha02191e2014-04-16 11:17:03 +010061 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged,
62 OnServiceWorkerStateChanged)
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010063 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes,
64 OnSetVersionAttributes)
Ben Murdoch116680a2014-07-20 18:25:52 -070065 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker,
66 OnSetControllerServiceWorker)
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +010067 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument,
68 OnPostMessage)
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000069 IPC_MESSAGE_UNHANDLED(handled = false)
70 IPC_END_MESSAGE_MAP()
71 DCHECK(handled) << "Unhandled message:" << msg.type();
72}
73
74bool ServiceWorkerDispatcher::Send(IPC::Message* msg) {
75 return thread_safe_sender_->Send(msg);
76}
77
78void ServiceWorkerDispatcher::RegisterServiceWorker(
Ben Murdocha02191e2014-04-16 11:17:03 +010079 int provider_id,
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000080 const GURL& pattern,
81 const GURL& script_url,
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +010082 WebServiceWorkerRegistrationCallbacks* callbacks) {
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000083 DCHECK(callbacks);
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +010084
85 if (pattern.possibly_invalid_spec().size() > GetMaxURLChars() ||
86 script_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +010087 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +010088 owned_callbacks(callbacks);
89 scoped_ptr<WebServiceWorkerError> error(new WebServiceWorkerError(
90 WebServiceWorkerError::ErrorTypeSecurity, "URL too long"));
91 callbacks->onError(error.release());
92 return;
93 }
94
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000095 int request_id = pending_callbacks_.Add(callbacks);
96 thread_safe_sender_->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
Ben Murdocha02191e2014-04-16 11:17:03 +010097 CurrentWorkerId(), request_id, provider_id, pattern, script_url));
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000098}
99
100void ServiceWorkerDispatcher::UnregisterServiceWorker(
Ben Murdocha02191e2014-04-16 11:17:03 +0100101 int provider_id,
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000102 const GURL& pattern,
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100103 WebServiceWorkerRegistrationCallbacks* callbacks) {
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000104 DCHECK(callbacks);
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100105
106 if (pattern.possibly_invalid_spec().size() > GetMaxURLChars()) {
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100107 scoped_ptr<WebServiceWorkerRegistrationCallbacks>
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100108 owned_callbacks(callbacks);
109 scoped_ptr<WebServiceWorkerError> error(new WebServiceWorkerError(
110 WebServiceWorkerError::ErrorTypeSecurity, "URL too long"));
111 callbacks->onError(error.release());
112 return;
113 }
114
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000115 int request_id = pending_callbacks_.Add(callbacks);
116 thread_safe_sender_->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
Ben Murdocha02191e2014-04-16 11:17:03 +0100117 CurrentWorkerId(), request_id, provider_id, pattern));
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000118}
119
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100120void ServiceWorkerDispatcher::AddProviderContext(
121 ServiceWorkerProviderContext* provider_context) {
122 DCHECK(provider_context);
123 int provider_id = provider_context->provider_id();
124 DCHECK(!ContainsKey(provider_contexts_, provider_id));
125 provider_contexts_[provider_id] = provider_context;
126}
127
128void ServiceWorkerDispatcher::RemoveProviderContext(
129 ServiceWorkerProviderContext* provider_context) {
130 DCHECK(provider_context);
131 DCHECK(ContainsKey(provider_contexts_, provider_context->provider_id()));
132 provider_contexts_.erase(provider_context->provider_id());
Ben Murdoch116680a2014-07-20 18:25:52 -0700133 worker_to_provider_.erase(provider_context->installing_handle_id());
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100134 worker_to_provider_.erase(provider_context->waiting_handle_id());
Ben Murdoch116680a2014-07-20 18:25:52 -0700135 worker_to_provider_.erase(provider_context->active_handle_id());
136 worker_to_provider_.erase(provider_context->controller_handle_id());
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100137}
138
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000139void ServiceWorkerDispatcher::AddScriptClient(
140 int provider_id,
141 blink::WebServiceWorkerProviderClient* client) {
142 DCHECK(client);
143 DCHECK(!ContainsKey(script_clients_, provider_id));
144 script_clients_[provider_id] = client;
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000145}
146
147void ServiceWorkerDispatcher::RemoveScriptClient(int provider_id) {
148 // This could be possibly called multiple times to ensure termination.
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100149 if (ContainsKey(script_clients_, provider_id))
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000150 script_clients_.erase(provider_id);
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000151}
152
Ben Murdocha02191e2014-04-16 11:17:03 +0100153ServiceWorkerDispatcher*
154ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000155 ThreadSafeSender* thread_safe_sender) {
156 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
157 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
158 g_dispatcher_tls.Pointer()->Set(NULL);
159 }
160 if (g_dispatcher_tls.Pointer()->Get())
161 return g_dispatcher_tls.Pointer()->Get();
162
163 ServiceWorkerDispatcher* dispatcher =
164 new ServiceWorkerDispatcher(thread_safe_sender);
165 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000166 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000167 return dispatcher;
168}
169
Ben Murdocha02191e2014-04-16 11:17:03 +0100170ServiceWorkerDispatcher* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
171 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted)
172 return NULL;
173 return g_dispatcher_tls.Pointer()->Get();
174}
175
176void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() {
177 delete this;
178}
179
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100180WebServiceWorkerImpl* ServiceWorkerDispatcher::GetServiceWorker(
181 const ServiceWorkerObjectInfo& info,
182 bool adopt_handle) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100183 if (info.handle_id == kInvalidServiceWorkerHandleId)
184 return NULL;
185
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100186 WorkerObjectMap::iterator existing_worker =
187 service_workers_.find(info.handle_id);
188
189 if (existing_worker != service_workers_.end()) {
190 if (adopt_handle) {
191 // We are instructed to adopt a handle but we already have one, so
192 // adopt and destroy a handle ref.
193 ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_);
194 }
195 return existing_worker->second;
196 }
197
198 scoped_ptr<ServiceWorkerHandleReference> handle_ref =
199 adopt_handle
200 ? ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_)
201 : ServiceWorkerHandleReference::Create(info, thread_safe_sender_);
202 // WebServiceWorkerImpl constructor calls AddServiceWorker.
203 return new WebServiceWorkerImpl(handle_ref.Pass(), thread_safe_sender_);
204}
205
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100206WebServiceWorkerRegistrationImpl*
207ServiceWorkerDispatcher::GetServiceWorkerRegistration(
208 int registration_handle_id,
209 const ServiceWorkerObjectInfo& info,
210 bool adopt_handle) {
211 if (registration_handle_id == kInvalidServiceWorkerRegistrationHandleId)
212 return NULL;
213
214 RegistrationObjectMap::iterator existing_registration =
215 registrations_.find(registration_handle_id);
216
217 if (existing_registration != registrations_.end()) {
218 if (adopt_handle) {
219 // We are instructed to adopt a handle but we already have one, so
220 // adopt and destroy a handle ref.
221 ServiceWorkerRegistrationHandleReference::Adopt(
222 registration_handle_id, info, thread_safe_sender_);
223 }
224 return existing_registration->second;
225 }
226
227 scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref =
228 adopt_handle
229 ? ServiceWorkerRegistrationHandleReference::Adopt(
230 registration_handle_id, info, thread_safe_sender_)
231 : ServiceWorkerRegistrationHandleReference::Create(
232 registration_handle_id, info, thread_safe_sender_);
233
234 // WebServiceWorkerRegistrationImpl constructor calls
235 // AddServiceWorkerRegistration.
236 return new WebServiceWorkerRegistrationImpl(handle_ref.Pass());
237}
238
Ben Murdocha02191e2014-04-16 11:17:03 +0100239void ServiceWorkerDispatcher::OnRegistered(
240 int thread_id,
241 int request_id,
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100242 int registration_handle_id,
Ben Murdocha02191e2014-04-16 11:17:03 +0100243 const ServiceWorkerObjectInfo& info) {
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100244 WebServiceWorkerRegistrationCallbacks* callbacks =
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000245 pending_callbacks_.Lookup(request_id);
246 DCHECK(callbacks);
247 if (!callbacks)
248 return;
249
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100250#ifdef DISABLE_SERVICE_WORKER_REGISTRATION
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100251 callbacks->onSuccess(GetServiceWorker(info, true));
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100252 // We should adopt and destroy an unused handle ref.
253 ServiceWorkerRegistrationHandleReference::Adopt(
254 registration_handle_id, info, thread_safe_sender_);
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100255#else
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100256 callbacks->onSuccess(GetServiceWorkerRegistration(
257 registration_handle_id, info, true));
258 // We should adopt and destroy an unused handle ref.
259 ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_);
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100260#endif
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000261 pending_callbacks_.Remove(request_id);
262}
263
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000264void ServiceWorkerDispatcher::OnUnregistered(
Ben Murdocha02191e2014-04-16 11:17:03 +0100265 int thread_id,
266 int request_id) {
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100267 WebServiceWorkerRegistrationCallbacks* callbacks =
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000268 pending_callbacks_.Lookup(request_id);
269 DCHECK(callbacks);
270 if (!callbacks)
271 return;
272
273 callbacks->onSuccess(NULL);
274 pending_callbacks_.Remove(request_id);
275}
276
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000277void ServiceWorkerDispatcher::OnRegistrationError(
Ben Murdocha02191e2014-04-16 11:17:03 +0100278 int thread_id,
279 int request_id,
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000280 WebServiceWorkerError::ErrorType error_type,
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +0000281 const base::string16& message) {
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100282 WebServiceWorkerRegistrationCallbacks* callbacks =
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000283 pending_callbacks_.Lookup(request_id);
284 DCHECK(callbacks);
285 if (!callbacks)
286 return;
287
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100288 scoped_ptr<WebServiceWorkerError> error(
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000289 new WebServiceWorkerError(error_type, message));
290 callbacks->onError(error.release());
291 pending_callbacks_.Remove(request_id);
292}
293
Ben Murdocha02191e2014-04-16 11:17:03 +0100294void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100295 int thread_id,
Ben Murdocha02191e2014-04-16 11:17:03 +0100296 int handle_id,
297 blink::WebServiceWorkerState state) {
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100298 WorkerObjectMap::iterator worker = service_workers_.find(handle_id);
299 if (worker != service_workers_.end())
300 worker->second->OnStateChanged(state);
301
302 WorkerToProviderMap::iterator provider = worker_to_provider_.find(handle_id);
303 if (provider != worker_to_provider_.end())
304 provider->second->OnServiceWorkerStateChanged(handle_id, state);
Ben Murdocha02191e2014-04-16 11:17:03 +0100305}
306
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100307void ServiceWorkerDispatcher::OnSetVersionAttributes(
Ben Murdoch116680a2014-07-20 18:25:52 -0700308 int thread_id,
309 int provider_id,
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100310 int registration_handle_id,
311 int changed_mask,
312 const ServiceWorkerVersionAttributes& attributes) {
313 ChangedVersionAttributesMask mask(changed_mask);
314 if (mask.installing_changed()) {
315 SetInstallingServiceWorker(provider_id,
316 registration_handle_id,
317 attributes.installing);
318 }
319 if (mask.waiting_changed()) {
320 SetWaitingServiceWorker(provider_id,
321 registration_handle_id,
322 attributes.waiting);
323 }
324 if (mask.active_changed()) {
325 SetActiveServiceWorker(provider_id,
326 registration_handle_id,
327 attributes.active);
328 }
329}
330
331void ServiceWorkerDispatcher::SetInstallingServiceWorker(
332 int provider_id,
333 int registration_handle_id,
Ben Murdoch116680a2014-07-20 18:25:52 -0700334 const ServiceWorkerObjectInfo& info) {
335 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
336 if (provider != provider_contexts_.end()) {
337 int existing_installing_id = provider->second->installing_handle_id();
338 if (existing_installing_id != info.handle_id &&
339 existing_installing_id != kInvalidServiceWorkerHandleId) {
340 WorkerToProviderMap::iterator associated_provider =
341 worker_to_provider_.find(existing_installing_id);
342 DCHECK(associated_provider != worker_to_provider_.end());
343 DCHECK(associated_provider->second->provider_id() == provider_id);
344 worker_to_provider_.erase(associated_provider);
345 }
346 provider->second->OnSetInstallingServiceWorker(provider_id, info);
347 if (info.handle_id != kInvalidServiceWorkerHandleId)
348 worker_to_provider_[info.handle_id] = provider->second;
349 }
350
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100351#ifdef DISABLE_SERVICE_WORKER_REGISTRATION
Ben Murdoch116680a2014-07-20 18:25:52 -0700352 ScriptClientMap::iterator found = script_clients_.find(provider_id);
353 if (found != script_clients_.end()) {
354 // Populate the .installing field with the new worker object.
355 found->second->setInstalling(GetServiceWorker(info, false));
356 }
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100357#else
358 RegistrationObjectMap::iterator found =
359 registrations_.find(registration_handle_id);
360 if (found != registrations_.end()) {
361 found->second->setInstalling(GetServiceWorker(info, false));
362 if (info.handle_id != kInvalidServiceWorkerHandleId)
363 found->second->OnUpdateFound();
364 }
365#endif
Ben Murdoch116680a2014-07-20 18:25:52 -0700366}
367
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100368void ServiceWorkerDispatcher::SetWaitingServiceWorker(
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100369 int provider_id,
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100370 int registration_handle_id,
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100371 const ServiceWorkerObjectInfo& info) {
372 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
373 if (provider != provider_contexts_.end()) {
374 int existing_waiting_id = provider->second->waiting_handle_id();
375 if (existing_waiting_id != info.handle_id &&
376 existing_waiting_id != kInvalidServiceWorkerHandleId) {
377 WorkerToProviderMap::iterator associated_provider =
378 worker_to_provider_.find(existing_waiting_id);
379 DCHECK(associated_provider != worker_to_provider_.end());
380 DCHECK(associated_provider->second->provider_id() == provider_id);
381 worker_to_provider_.erase(associated_provider);
382 }
383 provider->second->OnSetWaitingServiceWorker(provider_id, info);
384 if (info.handle_id != kInvalidServiceWorkerHandleId)
385 worker_to_provider_[info.handle_id] = provider->second;
386 }
387
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100388#ifdef DISABLE_SERVICE_WORKER_REGISTRATION
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100389 ScriptClientMap::iterator found = script_clients_.find(provider_id);
390 if (found != script_clients_.end()) {
391 // Populate the .waiting field with the new worker object.
392 found->second->setWaiting(GetServiceWorker(info, false));
393 }
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100394#else
395 RegistrationObjectMap::iterator found =
396 registrations_.find(registration_handle_id);
397 if (found != registrations_.end())
398 found->second->setWaiting(GetServiceWorker(info, false));
399#endif
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100400}
401
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100402void ServiceWorkerDispatcher::SetActiveServiceWorker(
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100403 int provider_id,
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100404 int registration_handle_id,
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100405 const ServiceWorkerObjectInfo& info) {
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100406 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
407 if (provider != provider_contexts_.end()) {
Ben Murdoch116680a2014-07-20 18:25:52 -0700408 int existing_active_id = provider->second->active_handle_id();
409 if (existing_active_id != info.handle_id &&
410 existing_active_id != kInvalidServiceWorkerHandleId) {
411 WorkerToProviderMap::iterator associated_provider =
412 worker_to_provider_.find(existing_active_id);
413 DCHECK(associated_provider != worker_to_provider_.end());
414 DCHECK(associated_provider->second->provider_id() == provider_id);
415 worker_to_provider_.erase(associated_provider);
416 }
417 provider->second->OnSetActiveServiceWorker(provider_id, info);
418 if (info.handle_id != kInvalidServiceWorkerHandleId)
419 worker_to_provider_[info.handle_id] = provider->second;
420 }
421
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100422#ifdef DISABLE_SERVICE_WORKER_REGISTRATION
Ben Murdoch116680a2014-07-20 18:25:52 -0700423 ScriptClientMap::iterator found = script_clients_.find(provider_id);
424 if (found != script_clients_.end()) {
425 // Populate the .active field with the new worker object.
426 found->second->setActive(GetServiceWorker(info, false));
427 }
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100428#else
429 RegistrationObjectMap::iterator found =
430 registrations_.find(registration_handle_id);
431 if (found != registrations_.end())
432 found->second->setActive(GetServiceWorker(info, false));
433#endif
Ben Murdoch116680a2014-07-20 18:25:52 -0700434}
435
436void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
437 int thread_id,
438 int provider_id,
439 const ServiceWorkerObjectInfo& info) {
440 ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
441 if (provider != provider_contexts_.end()) {
442 provider->second->OnSetControllerServiceWorker(provider_id, info);
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100443 worker_to_provider_[info.handle_id] = provider->second;
444 }
445
446 ScriptClientMap::iterator found = script_clients_.find(provider_id);
447 if (found != script_clients_.end()) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100448 // Populate the .controller field with the new worker object.
449 found->second->setController(GetServiceWorker(info, false));
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100450 }
451}
452
453void ServiceWorkerDispatcher::OnPostMessage(
454 int thread_id,
455 int provider_id,
456 const base::string16& message,
457 const std::vector<int>& sent_message_port_ids,
458 const std::vector<int>& new_routing_ids) {
459 // Make sure we're on the main document thread. (That must be the only
460 // thread we get this message)
461 DCHECK(ChildThread::current());
462
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100463 ScriptClientMap::iterator found = script_clients_.find(provider_id);
464 if (found == script_clients_.end()) {
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100465 // For now we do no queueing for messages sent to nonexistent / unattached
466 // client.
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100467 return;
468 }
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100469
470 std::vector<WebMessagePortChannelImpl*> ports;
471 if (!sent_message_port_ids.empty()) {
472 ports.resize(sent_message_port_ids.size());
473 for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
474 ports[i] = new WebMessagePortChannelImpl(
475 new_routing_ids[i], sent_message_port_ids[i],
476 base::MessageLoopProxy::current());
477 }
478 }
479
480 found->second->dispatchMessageEvent(message, ports);
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100481}
482
Ben Murdocha02191e2014-04-16 11:17:03 +0100483void ServiceWorkerDispatcher::AddServiceWorker(
484 int handle_id, WebServiceWorkerImpl* worker) {
485 DCHECK(!ContainsKey(service_workers_, handle_id));
486 service_workers_[handle_id] = worker;
487}
488
489void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id) {
490 DCHECK(ContainsKey(service_workers_, handle_id));
491 service_workers_.erase(handle_id);
492}
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000493
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100494void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
495 int registration_handle_id,
496 WebServiceWorkerRegistrationImpl* registration) {
497 DCHECK(!ContainsKey(registrations_, registration_handle_id));
498 registrations_[registration_handle_id] = registration;
499}
500
501void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
502 int registration_handle_id) {
503 DCHECK(ContainsKey(registrations_, registration_handle_id));
504 registrations_.erase(registration_handle_id);
505}
506
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000507} // namespace content