base/threading: remove ScopedTracker placed for experiments
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_dispatcher_host.cc
blobf1ee3e7ec5112814edb05ac63361907f595f089e
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/browser/service_worker/service_worker_dispatcher_host.h"
7 #include "base/logging.h"
8 #include "base/profiler/scoped_tracker.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/trace_event/trace_event.h"
11 #include "content/browser/bad_message.h"
12 #include "content/browser/message_port_message_filter.h"
13 #include "content/browser/message_port_service.h"
14 #include "content/browser/service_worker/embedded_worker_registry.h"
15 #include "content/browser/service_worker/service_worker_context_core.h"
16 #include "content/browser/service_worker/service_worker_context_wrapper.h"
17 #include "content/browser/service_worker/service_worker_handle.h"
18 #include "content/browser/service_worker/service_worker_registration.h"
19 #include "content/browser/service_worker/service_worker_registration_handle.h"
20 #include "content/browser/service_worker/service_worker_utils.h"
21 #include "content/common/service_worker/embedded_worker_messages.h"
22 #include "content/common/service_worker/service_worker_messages.h"
23 #include "content/common/service_worker/service_worker_types.h"
24 #include "content/public/browser/content_browser_client.h"
25 #include "content/public/common/content_client.h"
26 #include "content/public/common/origin_util.h"
27 #include "ipc/ipc_message_macros.h"
28 #include "net/base/net_util.h"
29 #include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
30 #include "url/gurl.h"
32 using blink::WebServiceWorkerError;
34 namespace content {
36 namespace {
38 const char kNoDocumentURLErrorMessage[] =
39 "No URL is associated with the caller's document.";
40 const char kShutdownErrorMessage[] =
41 "The Service Worker system has shutdown.";
42 const char kUserDeniedPermissionMessage[] =
43 "The user denied permission to use Service Worker.";
44 const char kInvalidStateErrorMessage[] = "The object is in an invalid state.";
46 const uint32 kFilteredMessageClasses[] = {
47 ServiceWorkerMsgStart,
48 EmbeddedWorkerMsgStart,
51 bool AllOriginsMatch(const GURL& url_a, const GURL& url_b, const GURL& url_c) {
52 return url_a.GetOrigin() == url_b.GetOrigin() &&
53 url_a.GetOrigin() == url_c.GetOrigin();
56 bool CanRegisterServiceWorker(const GURL& document_url,
57 const GURL& pattern,
58 const GURL& script_url) {
59 DCHECK(document_url.is_valid());
60 DCHECK(pattern.is_valid());
61 DCHECK(script_url.is_valid());
62 return AllOriginsMatch(document_url, pattern, script_url) &&
63 OriginCanAccessServiceWorkers(document_url) &&
64 OriginCanAccessServiceWorkers(pattern) &&
65 OriginCanAccessServiceWorkers(script_url);
68 bool CanUnregisterServiceWorker(const GURL& document_url,
69 const GURL& pattern) {
70 DCHECK(document_url.is_valid());
71 DCHECK(pattern.is_valid());
72 return document_url.GetOrigin() == pattern.GetOrigin() &&
73 OriginCanAccessServiceWorkers(document_url) &&
74 OriginCanAccessServiceWorkers(pattern);
77 bool CanUpdateServiceWorker(const GURL& document_url, const GURL& pattern) {
78 DCHECK(document_url.is_valid());
79 DCHECK(pattern.is_valid());
80 DCHECK(OriginCanAccessServiceWorkers(document_url));
81 DCHECK(OriginCanAccessServiceWorkers(pattern));
82 return document_url.GetOrigin() == pattern.GetOrigin();
85 bool CanGetRegistration(const GURL& document_url,
86 const GURL& given_document_url) {
87 DCHECK(document_url.is_valid());
88 DCHECK(given_document_url.is_valid());
89 return document_url.GetOrigin() == given_document_url.GetOrigin() &&
90 OriginCanAccessServiceWorkers(document_url) &&
91 OriginCanAccessServiceWorkers(given_document_url);
94 } // namespace
96 ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
97 int render_process_id,
98 MessagePortMessageFilter* message_port_message_filter,
99 ResourceContext* resource_context)
100 : BrowserMessageFilter(kFilteredMessageClasses,
101 arraysize(kFilteredMessageClasses)),
102 render_process_id_(render_process_id),
103 message_port_message_filter_(message_port_message_filter),
104 resource_context_(resource_context),
105 channel_ready_(false) {
108 ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
109 if (GetContext()) {
110 GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
111 GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
112 render_process_id_);
116 void ServiceWorkerDispatcherHost::Init(
117 ServiceWorkerContextWrapper* context_wrapper) {
118 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
119 BrowserThread::PostTask(
120 BrowserThread::IO, FROM_HERE,
121 base::Bind(&ServiceWorkerDispatcherHost::Init,
122 this, make_scoped_refptr(context_wrapper)));
123 return;
126 context_wrapper_ = context_wrapper;
127 if (!GetContext())
128 return;
129 GetContext()->embedded_worker_registry()->AddChildProcessSender(
130 render_process_id_, this, message_port_message_filter_);
133 void ServiceWorkerDispatcherHost::OnFilterAdded(IPC::Sender* sender) {
134 TRACE_EVENT0("ServiceWorker",
135 "ServiceWorkerDispatcherHost::OnFilterAdded");
136 channel_ready_ = true;
137 std::vector<IPC::Message*> messages;
138 pending_messages_.release(&messages);
139 for (size_t i = 0; i < messages.size(); ++i) {
140 BrowserMessageFilter::Send(messages[i]);
144 void ServiceWorkerDispatcherHost::OnFilterRemoved() {
145 // Don't wait until the destructor to teardown since a new dispatcher host
146 // for this process might be created before then.
147 if (GetContext()) {
148 GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
149 GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
150 render_process_id_);
152 context_wrapper_ = nullptr;
153 channel_ready_ = false;
156 void ServiceWorkerDispatcherHost::OnDestruct() const {
157 BrowserThread::DeleteOnIOThread::Destruct(this);
160 bool ServiceWorkerDispatcherHost::OnMessageReceived(
161 const IPC::Message& message) {
162 bool handled = true;
163 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcherHost, message)
164 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_RegisterServiceWorker,
165 OnRegisterServiceWorker)
166 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_UpdateServiceWorker,
167 OnUpdateServiceWorker)
168 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_UnregisterServiceWorker,
169 OnUnregisterServiceWorker)
170 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistration,
171 OnGetRegistration)
172 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistrations,
173 OnGetRegistrations)
174 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistrationForReady,
175 OnGetRegistrationForReady)
176 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderCreated,
177 OnProviderCreated)
178 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed,
179 OnProviderDestroyed)
180 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetVersionId,
181 OnSetHostedVersionId)
182 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToWorker,
183 OnPostMessageToWorker)
184 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerReadyForInspection,
185 OnWorkerReadyForInspection)
186 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoaded,
187 OnWorkerScriptLoaded)
188 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoadFailed,
189 OnWorkerScriptLoadFailed)
190 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptEvaluated,
191 OnWorkerScriptEvaluated)
192 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted,
193 OnWorkerStarted)
194 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped,
195 OnWorkerStopped)
196 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportException,
197 OnReportException)
198 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportConsoleMessage,
199 OnReportConsoleMessage)
200 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount,
201 OnIncrementServiceWorkerRefCount)
202 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount,
203 OnDecrementServiceWorkerRefCount)
204 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementRegistrationRefCount,
205 OnIncrementRegistrationRefCount)
206 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
207 OnDecrementRegistrationRefCount)
208 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_TerminateWorker, OnTerminateWorker)
209 IPC_MESSAGE_UNHANDLED(handled = false)
210 IPC_END_MESSAGE_MAP()
212 if (!handled && GetContext()) {
213 handled = GetContext()->embedded_worker_registry()->OnMessageReceived(
214 message, render_process_id_);
215 if (!handled)
216 bad_message::ReceivedBadMessage(this, bad_message::SWDH_NOT_HANDLED);
219 return handled;
222 bool ServiceWorkerDispatcherHost::Send(IPC::Message* message) {
223 if (channel_ready_) {
224 BrowserMessageFilter::Send(message);
225 // Don't bother passing through Send()'s result: it's not reliable.
226 return true;
229 pending_messages_.push_back(message);
230 return true;
233 void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle(
234 scoped_ptr<ServiceWorkerHandle> handle) {
235 int handle_id = handle->handle_id();
236 handles_.AddWithID(handle.release(), handle_id);
239 void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationHandle(
240 scoped_ptr<ServiceWorkerRegistrationHandle> handle) {
241 int handle_id = handle->handle_id();
242 registration_handles_.AddWithID(handle.release(), handle_id);
245 ServiceWorkerHandle* ServiceWorkerDispatcherHost::FindServiceWorkerHandle(
246 int provider_id,
247 int64 version_id) {
248 for (IDMap<ServiceWorkerHandle, IDMapOwnPointer>::iterator iter(&handles_);
249 !iter.IsAtEnd(); iter.Advance()) {
250 ServiceWorkerHandle* handle = iter.GetCurrentValue();
251 DCHECK(handle);
252 DCHECK(handle->version());
253 if (handle->provider_id() == provider_id &&
254 handle->version()->version_id() == version_id) {
255 return handle;
258 return NULL;
261 ServiceWorkerRegistrationHandle*
262 ServiceWorkerDispatcherHost::GetOrCreateRegistrationHandle(
263 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
264 ServiceWorkerRegistration* registration) {
265 DCHECK(provider_host);
266 ServiceWorkerRegistrationHandle* handle =
267 FindRegistrationHandle(provider_host->provider_id(), registration->id());
268 if (handle) {
269 handle->IncrementRefCount();
270 return handle;
273 scoped_ptr<ServiceWorkerRegistrationHandle> new_handle(
274 new ServiceWorkerRegistrationHandle(
275 GetContext()->AsWeakPtr(), provider_host, registration));
276 handle = new_handle.get();
277 RegisterServiceWorkerRegistrationHandle(new_handle.Pass());
278 return handle;
281 void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
282 int thread_id,
283 int request_id,
284 int provider_id,
285 const GURL& pattern,
286 const GURL& script_url) {
287 TRACE_EVENT0("ServiceWorker",
288 "ServiceWorkerDispatcherHost::OnRegisterServiceWorker");
289 if (!GetContext()) {
290 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
291 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
292 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
293 base::ASCIIToUTF16(kShutdownErrorMessage)));
294 return;
296 if (!pattern.is_valid() || !script_url.is_valid()) {
297 bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_BAD_URL);
298 return;
301 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
302 render_process_id_, provider_id);
303 if (!provider_host) {
304 bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_NO_HOST);
305 return;
307 if (!provider_host->IsContextAlive()) {
308 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
309 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
310 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
311 base::ASCIIToUTF16(kShutdownErrorMessage)));
312 return;
315 // TODO(ksakamoto): Currently, document_url is empty if the document is in an
316 // IFRAME using frame.contentDocument.write(...). We can remove this check
317 // once crbug.com/439697 is fixed.
318 if (provider_host->document_url().is_empty()) {
319 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
320 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
321 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
322 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
323 return;
326 if (!CanRegisterServiceWorker(
327 provider_host->document_url(), pattern, script_url)) {
328 bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_CANNOT);
329 return;
332 std::string error_message;
333 if (ServiceWorkerUtils::ContainsDisallowedCharacter(pattern, script_url,
334 &error_message)) {
335 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
336 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
337 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
338 base::UTF8ToUTF16(error_message)));
339 return;
342 if (!GetContentClient()->browser()->AllowServiceWorker(
343 pattern, provider_host->topmost_frame_url(), resource_context_,
344 render_process_id_, provider_host->frame_id())) {
345 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
346 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
347 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
348 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
349 return;
352 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
353 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
354 request_id,
355 "Pattern", pattern.spec(),
356 "Script URL", script_url.spec());
357 GetContext()->RegisterServiceWorker(
358 pattern,
359 script_url,
360 provider_host,
361 base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete,
362 this,
363 thread_id,
364 provider_id,
365 request_id));
368 void ServiceWorkerDispatcherHost::OnUpdateServiceWorker(int thread_id,
369 int request_id,
370 int provider_id,
371 int64 registration_id) {
372 TRACE_EVENT0("ServiceWorker",
373 "ServiceWorkerDispatcherHost::OnUpdateServiceWorker");
374 if (!GetContext()) {
375 Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
376 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
377 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
378 base::ASCIIToUTF16(kShutdownErrorMessage)));
379 return;
382 ServiceWorkerProviderHost* provider_host =
383 GetContext()->GetProviderHost(render_process_id_, provider_id);
384 if (!provider_host) {
385 bad_message::ReceivedBadMessage(this, bad_message::SWDH_UPDATE_NO_HOST);
386 return;
388 if (!provider_host->IsContextAlive()) {
389 Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
390 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
391 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
392 base::ASCIIToUTF16(kShutdownErrorMessage)));
393 return;
396 // TODO(jungkees): This check can be removed once crbug.com/439697 is fixed.
397 if (provider_host->document_url().is_empty()) {
398 Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
399 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
400 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
401 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
402 return;
405 ServiceWorkerRegistration* registration =
406 GetContext()->GetLiveRegistration(registration_id);
407 if (!registration) {
408 // |registration| must be alive because a renderer retains a registration
409 // reference at this point.
410 bad_message::ReceivedBadMessage(
411 this, bad_message::SWDH_UPDATE_BAD_REGISTRATION_ID);
412 return;
415 if (!CanUpdateServiceWorker(provider_host->document_url(),
416 registration->pattern())) {
417 bad_message::ReceivedBadMessage(this, bad_message::SWDH_UPDATE_CANNOT);
418 return;
421 if (!GetContentClient()->browser()->AllowServiceWorker(
422 registration->pattern(), provider_host->topmost_frame_url(),
423 resource_context_, render_process_id_, provider_host->frame_id())) {
424 Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
425 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
426 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
427 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
428 return;
431 if (!registration->GetNewestVersion()) {
432 // This can happen if update() is called during initial script evaluation.
433 // Abort the following steps according to the spec.
434 Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
435 thread_id, request_id, WebServiceWorkerError::ErrorTypeState,
436 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
437 base::ASCIIToUTF16(kInvalidStateErrorMessage)));
438 return;
441 // The spec says, "update() pings the server for an updated version of this
442 // script without consulting caches", so set |force_bypass_cache| to true.
443 GetContext()->UpdateServiceWorker(
444 registration, true, /* force_bypass_cache */
445 provider_host, base::Bind(&ServiceWorkerDispatcherHost::UpdateComplete,
446 this, thread_id, provider_id, request_id));
449 void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
450 int thread_id,
451 int request_id,
452 int provider_id,
453 int64 registration_id) {
454 TRACE_EVENT0("ServiceWorker",
455 "ServiceWorkerDispatcherHost::OnUnregisterServiceWorker");
456 if (!GetContext()) {
457 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
458 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
459 base::ASCIIToUTF16(kShutdownErrorMessage)));
460 return;
463 ServiceWorkerProviderHost* provider_host =
464 GetContext()->GetProviderHost(render_process_id_, provider_id);
465 if (!provider_host) {
466 bad_message::ReceivedBadMessage(this, bad_message::SWDH_UNREGISTER_NO_HOST);
467 return;
469 if (!provider_host->IsContextAlive()) {
470 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
471 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
472 base::ASCIIToUTF16(kShutdownErrorMessage)));
473 return;
476 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
477 if (provider_host->document_url().is_empty()) {
478 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
479 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
480 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
481 return;
484 ServiceWorkerRegistration* registration =
485 GetContext()->GetLiveRegistration(registration_id);
486 if (!registration) {
487 // |registration| must be alive because a renderer retains a registration
488 // reference at this point.
489 bad_message::ReceivedBadMessage(
490 this, bad_message::SWDH_UNREGISTER_BAD_REGISTRATION_ID);
491 return;
494 if (!CanUnregisterServiceWorker(provider_host->document_url(),
495 registration->pattern())) {
496 bad_message::ReceivedBadMessage(this, bad_message::SWDH_UNREGISTER_CANNOT);
497 return;
500 if (!GetContentClient()->browser()->AllowServiceWorker(
501 registration->pattern(), provider_host->topmost_frame_url(),
502 resource_context_, render_process_id_, provider_host->frame_id())) {
503 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
504 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
505 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
506 return;
509 TRACE_EVENT_ASYNC_BEGIN1(
510 "ServiceWorker", "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
511 request_id, "Pattern", registration->pattern().spec());
512 GetContext()->UnregisterServiceWorker(
513 registration->pattern(),
514 base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete, this,
515 thread_id, request_id));
518 void ServiceWorkerDispatcherHost::OnGetRegistration(
519 int thread_id,
520 int request_id,
521 int provider_id,
522 const GURL& document_url) {
523 TRACE_EVENT0("ServiceWorker",
524 "ServiceWorkerDispatcherHost::OnGetRegistration");
526 DCHECK_CURRENTLY_ON(BrowserThread::IO);
528 if (!GetContext()) {
529 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
530 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
531 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
532 base::ASCIIToUTF16(kShutdownErrorMessage)));
533 return;
535 if (!document_url.is_valid()) {
536 bad_message::ReceivedBadMessage(this,
537 bad_message::SWDH_GET_REGISTRATION_BAD_URL);
538 return;
541 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
542 render_process_id_, provider_id);
543 if (!provider_host) {
544 bad_message::ReceivedBadMessage(this,
545 bad_message::SWDH_GET_REGISTRATION_NO_HOST);
546 return;
548 if (!provider_host->IsContextAlive()) {
549 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
550 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
551 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
552 base::ASCIIToUTF16(kShutdownErrorMessage)));
553 return;
556 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
557 if (provider_host->document_url().is_empty()) {
558 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
559 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
560 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
561 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
562 return;
565 if (!CanGetRegistration(provider_host->document_url(), document_url)) {
566 bad_message::ReceivedBadMessage(this,
567 bad_message::SWDH_GET_REGISTRATION_CANNOT);
568 return;
571 if (!GetContentClient()->browser()->AllowServiceWorker(
572 provider_host->document_url(), provider_host->topmost_frame_url(),
573 resource_context_, render_process_id_, provider_host->frame_id())) {
574 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
575 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
576 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
577 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
578 return;
581 if (GetContext()->storage()->IsDisabled()) {
582 SendGetRegistrationError(thread_id, request_id, SERVICE_WORKER_ERROR_ABORT);
583 return;
586 TRACE_EVENT_ASYNC_BEGIN1(
587 "ServiceWorker",
588 "ServiceWorkerDispatcherHost::GetRegistration",
589 request_id,
590 "Document URL", document_url.spec());
592 GetContext()->storage()->FindRegistrationForDocument(
593 document_url,
594 base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationComplete,
595 this,
596 thread_id,
597 provider_id,
598 request_id));
601 void ServiceWorkerDispatcherHost::OnGetRegistrations(int thread_id,
602 int request_id,
603 int provider_id) {
604 DCHECK_CURRENTLY_ON(BrowserThread::IO);
606 if (!GetContext()) {
607 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
608 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
609 base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
610 base::ASCIIToUTF16(kShutdownErrorMessage)));
611 return;
614 ServiceWorkerProviderHost* provider_host =
615 GetContext()->GetProviderHost(render_process_id_, provider_id);
616 if (!provider_host) {
617 bad_message::ReceivedBadMessage(
618 this, bad_message::SWDH_GET_REGISTRATIONS_NO_HOST);
619 return;
621 if (!provider_host->IsContextAlive()) {
622 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
623 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
624 base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
625 base::ASCIIToUTF16(kShutdownErrorMessage)));
626 return;
629 // TODO(jungkees): This check can be removed once crbug.com/439697 is fixed.
630 if (provider_host->document_url().is_empty()) {
631 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
632 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
633 base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
634 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
635 return;
638 if (!OriginCanAccessServiceWorkers(provider_host->document_url())) {
639 bad_message::ReceivedBadMessage(
640 this, bad_message::SWDH_GET_REGISTRATIONS_INVALID_ORIGIN);
641 return;
644 if (!GetContentClient()->browser()->AllowServiceWorker(
645 provider_host->document_url(), provider_host->topmost_frame_url(),
646 resource_context_, render_process_id_, provider_host->frame_id())) {
647 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
648 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
649 base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
650 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
651 return;
654 if (GetContext()->storage()->IsDisabled()) {
655 SendGetRegistrationsError(thread_id, request_id,
656 SERVICE_WORKER_ERROR_ABORT);
657 return;
660 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
661 "ServiceWorkerDispatcherHost::GetRegistrations",
662 request_id);
664 GetContext()->storage()->GetRegistrationsForOrigin(
665 provider_host->document_url().GetOrigin(),
666 base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationsComplete, this,
667 thread_id, provider_id, request_id));
670 void ServiceWorkerDispatcherHost::OnGetRegistrationForReady(
671 int thread_id,
672 int request_id,
673 int provider_id) {
674 TRACE_EVENT0("ServiceWorker",
675 "ServiceWorkerDispatcherHost::OnGetRegistrationForReady");
676 if (!GetContext())
677 return;
678 ServiceWorkerProviderHost* provider_host =
679 GetContext()->GetProviderHost(render_process_id_, provider_id);
680 if (!provider_host) {
681 bad_message::ReceivedBadMessage(
682 this, bad_message::SWDH_GET_REGISTRATION_FOR_READY_NO_HOST);
683 return;
685 if (!provider_host->IsContextAlive())
686 return;
688 TRACE_EVENT_ASYNC_BEGIN0(
689 "ServiceWorker",
690 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
691 request_id);
693 if (!provider_host->GetRegistrationForReady(base::Bind(
694 &ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete,
695 this, thread_id, request_id, provider_host->AsWeakPtr()))) {
696 bad_message::ReceivedBadMessage(
697 this, bad_message::SWDH_GET_REGISTRATION_FOR_READY_ALREADY_IN_PROGRESS);
701 void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
702 int handle_id,
703 const base::string16& message,
704 const std::vector<TransferredMessagePort>& sent_message_ports) {
705 TRACE_EVENT0("ServiceWorker",
706 "ServiceWorkerDispatcherHost::OnPostMessageToWorker");
707 if (!GetContext())
708 return;
710 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
711 if (!handle) {
712 bad_message::ReceivedBadMessage(this, bad_message::SWDH_POST_MESSAGE);
713 return;
716 handle->version()->DispatchMessageEvent(
717 message, sent_message_ports,
718 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
721 void ServiceWorkerDispatcherHost::OnProviderCreated(
722 int provider_id,
723 int route_id,
724 ServiceWorkerProviderType provider_type) {
725 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
726 tracked_objects::ScopedTracker tracking_profile(
727 FROM_HERE_WITH_EXPLICIT_FUNCTION(
728 "477117 ServiceWorkerDispatcherHost::OnProviderCreated"));
729 TRACE_EVENT0("ServiceWorker",
730 "ServiceWorkerDispatcherHost::OnProviderCreated");
731 if (!GetContext())
732 return;
733 if (GetContext()->GetProviderHost(render_process_id_, provider_id)) {
734 bad_message::ReceivedBadMessage(this,
735 bad_message::SWDH_PROVIDER_CREATED_NO_HOST);
736 return;
738 scoped_ptr<ServiceWorkerProviderHost> provider_host(
739 new ServiceWorkerProviderHost(render_process_id_, route_id, provider_id,
740 provider_type, GetContext()->AsWeakPtr(),
741 this));
742 GetContext()->AddProviderHost(provider_host.Pass());
745 void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
746 TRACE_EVENT0("ServiceWorker",
747 "ServiceWorkerDispatcherHost::OnProviderDestroyed");
748 if (!GetContext())
749 return;
750 if (!GetContext()->GetProviderHost(render_process_id_, provider_id)) {
751 bad_message::ReceivedBadMessage(
752 this, bad_message::SWDH_PROVIDER_DESTROYED_NO_HOST);
753 return;
755 GetContext()->RemoveProviderHost(render_process_id_, provider_id);
758 void ServiceWorkerDispatcherHost::OnSetHostedVersionId(
759 int provider_id, int64 version_id) {
760 TRACE_EVENT0("ServiceWorker",
761 "ServiceWorkerDispatcherHost::OnSetHostedVersionId");
762 if (!GetContext())
763 return;
764 ServiceWorkerProviderHost* provider_host =
765 GetContext()->GetProviderHost(render_process_id_, provider_id);
766 if (!provider_host) {
767 bad_message::ReceivedBadMessage(
768 this, bad_message::SWDH_SET_HOSTED_VERSION_NO_HOST);
769 return;
771 if (!provider_host->IsContextAlive())
772 return;
773 if (!provider_host->SetHostedVersionId(version_id))
774 bad_message::ReceivedBadMessage(this, bad_message::SWDH_SET_HOSTED_VERSION);
776 ServiceWorkerVersion* version = GetContext()->GetLiveVersion(version_id);
777 if (!version)
778 return;
780 // Retrieve the registration associated with |version|. The registration
781 // must be alive because the version keeps it during starting worker.
782 ServiceWorkerRegistration* registration =
783 GetContext()->GetLiveRegistration(version->registration_id());
784 DCHECK(registration);
785 // TODO(ksakamoto): This is a quick fix for crbug.com/459916.
786 if (!registration)
787 return;
789 // Set the document URL to the script url in order to allow
790 // register/unregister/getRegistration on ServiceWorkerGlobalScope.
791 provider_host->SetDocumentUrl(version->script_url());
793 ServiceWorkerRegistrationObjectInfo info;
794 ServiceWorkerVersionAttributes attrs;
795 GetRegistrationObjectInfoAndVersionAttributes(
796 provider_host->AsWeakPtr(), registration, &info, &attrs);
798 Send(new ServiceWorkerMsg_AssociateRegistrationWithServiceWorker(
799 kDocumentMainThreadId, provider_id, info, attrs));
802 ServiceWorkerRegistrationHandle*
803 ServiceWorkerDispatcherHost::FindRegistrationHandle(int provider_id,
804 int64 registration_id) {
805 for (IDMap<ServiceWorkerRegistrationHandle, IDMapOwnPointer>::iterator
806 iter(&registration_handles_);
807 !iter.IsAtEnd();
808 iter.Advance()) {
809 ServiceWorkerRegistrationHandle* handle = iter.GetCurrentValue();
810 DCHECK(handle);
811 DCHECK(handle->registration());
812 if (handle->provider_id() == provider_id &&
813 handle->registration()->id() == registration_id) {
814 return handle;
817 return NULL;
820 void ServiceWorkerDispatcherHost::GetRegistrationObjectInfoAndVersionAttributes(
821 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
822 ServiceWorkerRegistration* registration,
823 ServiceWorkerRegistrationObjectInfo* info,
824 ServiceWorkerVersionAttributes* attrs) {
825 ServiceWorkerRegistrationHandle* handle =
826 GetOrCreateRegistrationHandle(provider_host, registration);
827 *info = handle->GetObjectInfo();
829 attrs->installing = provider_host->GetOrCreateServiceWorkerHandle(
830 registration->installing_version());
831 attrs->waiting = provider_host->GetOrCreateServiceWorkerHandle(
832 registration->waiting_version());
833 attrs->active = provider_host->GetOrCreateServiceWorkerHandle(
834 registration->active_version());
837 void ServiceWorkerDispatcherHost::RegistrationComplete(
838 int thread_id,
839 int provider_id,
840 int request_id,
841 ServiceWorkerStatusCode status,
842 const std::string& status_message,
843 int64 registration_id) {
844 if (!GetContext())
845 return;
847 ServiceWorkerProviderHost* provider_host =
848 GetContext()->GetProviderHost(render_process_id_, provider_id);
849 if (!provider_host)
850 return; // The provider has already been destroyed.
852 if (status != SERVICE_WORKER_OK) {
853 SendRegistrationError(thread_id, request_id, status, status_message);
854 return;
857 ServiceWorkerRegistration* registration =
858 GetContext()->GetLiveRegistration(registration_id);
859 DCHECK(registration);
861 ServiceWorkerRegistrationObjectInfo info;
862 ServiceWorkerVersionAttributes attrs;
863 GetRegistrationObjectInfoAndVersionAttributes(
864 provider_host->AsWeakPtr(), registration, &info, &attrs);
866 Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
867 thread_id, request_id, info, attrs));
868 TRACE_EVENT_ASYNC_END1("ServiceWorker",
869 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
870 request_id,
871 "Registration ID",
872 registration_id);
875 void ServiceWorkerDispatcherHost::UpdateComplete(
876 int thread_id,
877 int provider_id,
878 int request_id,
879 ServiceWorkerStatusCode status,
880 const std::string& status_message,
881 int64 registration_id) {
882 if (!GetContext())
883 return;
885 ServiceWorkerProviderHost* provider_host =
886 GetContext()->GetProviderHost(render_process_id_, provider_id);
887 if (!provider_host)
888 return; // The provider has already been destroyed.
890 if (status != SERVICE_WORKER_OK) {
891 SendRegistrationError(thread_id, request_id, status, status_message);
892 return;
895 ServiceWorkerRegistration* registration =
896 GetContext()->GetLiveRegistration(registration_id);
897 DCHECK(registration);
899 ServiceWorkerRegistrationObjectInfo info;
900 ServiceWorkerVersionAttributes attrs;
901 GetRegistrationObjectInfoAndVersionAttributes(provider_host->AsWeakPtr(),
902 registration, &info, &attrs);
904 Send(new ServiceWorkerMsg_ServiceWorkerUpdated(thread_id, request_id));
905 TRACE_EVENT_ASYNC_END1("ServiceWorker",
906 "ServiceWorkerDispatcherHost::UpdateServiceWorker",
907 request_id, "Registration ID", registration_id);
910 void ServiceWorkerDispatcherHost::OnWorkerReadyForInspection(
911 int embedded_worker_id) {
912 TRACE_EVENT0("ServiceWorker",
913 "ServiceWorkerDispatcherHost::OnWorkerReadyForInspection");
914 if (!GetContext())
915 return;
916 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
917 if (!registry->CanHandle(embedded_worker_id))
918 return;
919 registry->OnWorkerReadyForInspection(render_process_id_, embedded_worker_id);
922 void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(
923 int embedded_worker_id,
924 int thread_id,
925 int provider_id) {
926 TRACE_EVENT0("ServiceWorker",
927 "ServiceWorkerDispatcherHost::OnWorkerScriptLoaded");
928 if (!GetContext())
929 return;
931 ServiceWorkerProviderHost* provider_host =
932 GetContext()->GetProviderHost(render_process_id_, provider_id);
933 if (!provider_host) {
934 bad_message::ReceivedBadMessage(
935 this, bad_message::SWDH_WORKER_SCRIPT_LOAD_NO_HOST);
936 return;
939 provider_host->SetReadyToSendMessagesToWorker(thread_id);
941 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
942 if (!registry->CanHandle(embedded_worker_id))
943 return;
944 registry->OnWorkerScriptLoaded(
945 render_process_id_, thread_id, embedded_worker_id);
948 void ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed(
949 int embedded_worker_id) {
950 TRACE_EVENT0("ServiceWorker",
951 "ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed");
952 if (!GetContext())
953 return;
954 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
955 if (!registry->CanHandle(embedded_worker_id))
956 return;
957 registry->OnWorkerScriptLoadFailed(render_process_id_, embedded_worker_id);
960 void ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated(
961 int embedded_worker_id,
962 bool success) {
963 TRACE_EVENT0("ServiceWorker",
964 "ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated");
965 if (!GetContext())
966 return;
967 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
968 if (!registry->CanHandle(embedded_worker_id))
969 return;
970 registry->OnWorkerScriptEvaluated(
971 render_process_id_, embedded_worker_id, success);
974 void ServiceWorkerDispatcherHost::OnWorkerStarted(int embedded_worker_id) {
975 TRACE_EVENT0("ServiceWorker",
976 "ServiceWorkerDispatcherHost::OnWorkerStarted");
977 if (!GetContext())
978 return;
979 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
980 if (!registry->CanHandle(embedded_worker_id))
981 return;
982 registry->OnWorkerStarted(render_process_id_, embedded_worker_id);
985 void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) {
986 TRACE_EVENT0("ServiceWorker",
987 "ServiceWorkerDispatcherHost::OnWorkerStopped");
988 if (!GetContext())
989 return;
990 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
991 if (!registry->CanHandle(embedded_worker_id))
992 return;
993 registry->OnWorkerStopped(render_process_id_, embedded_worker_id);
996 void ServiceWorkerDispatcherHost::OnReportException(
997 int embedded_worker_id,
998 const base::string16& error_message,
999 int line_number,
1000 int column_number,
1001 const GURL& source_url) {
1002 TRACE_EVENT0("ServiceWorker",
1003 "ServiceWorkerDispatcherHost::OnReportException");
1004 if (!GetContext())
1005 return;
1006 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
1007 if (!registry->CanHandle(embedded_worker_id))
1008 return;
1009 registry->OnReportException(embedded_worker_id,
1010 error_message,
1011 line_number,
1012 column_number,
1013 source_url);
1016 void ServiceWorkerDispatcherHost::OnReportConsoleMessage(
1017 int embedded_worker_id,
1018 const EmbeddedWorkerHostMsg_ReportConsoleMessage_Params& params) {
1019 TRACE_EVENT0("ServiceWorker",
1020 "ServiceWorkerDispatcherHost::OnReportConsoleMessage");
1021 if (!GetContext())
1022 return;
1023 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
1024 if (!registry->CanHandle(embedded_worker_id))
1025 return;
1026 registry->OnReportConsoleMessage(embedded_worker_id,
1027 params.source_identifier,
1028 params.message_level,
1029 params.message,
1030 params.line_number,
1031 params.source_url);
1034 void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
1035 int handle_id) {
1036 TRACE_EVENT0("ServiceWorker",
1037 "ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount");
1038 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
1039 if (!handle) {
1040 bad_message::ReceivedBadMessage(
1041 this, bad_message::SWDH_INCREMENT_WORKER_BAD_HANDLE);
1042 return;
1044 handle->IncrementRefCount();
1047 void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
1048 int handle_id) {
1049 TRACE_EVENT0("ServiceWorker",
1050 "ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount");
1051 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
1052 if (!handle) {
1053 bad_message::ReceivedBadMessage(
1054 this, bad_message::SWDH_DECREMENT_WORKER_BAD_HANDLE);
1055 return;
1057 handle->DecrementRefCount();
1058 if (handle->HasNoRefCount())
1059 handles_.Remove(handle_id);
1062 void ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount(
1063 int registration_handle_id) {
1064 TRACE_EVENT0("ServiceWorker",
1065 "ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount");
1066 ServiceWorkerRegistrationHandle* handle =
1067 registration_handles_.Lookup(registration_handle_id);
1068 if (!handle) {
1069 bad_message::ReceivedBadMessage(
1070 this, bad_message::SWDH_INCREMENT_REGISTRATION_BAD_HANDLE);
1071 return;
1073 handle->IncrementRefCount();
1076 void ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount(
1077 int registration_handle_id) {
1078 TRACE_EVENT0("ServiceWorker",
1079 "ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount");
1080 ServiceWorkerRegistrationHandle* handle =
1081 registration_handles_.Lookup(registration_handle_id);
1082 if (!handle) {
1083 bad_message::ReceivedBadMessage(
1084 this, bad_message::SWDH_DECREMENT_REGISTRATION_BAD_HANDLE);
1085 return;
1087 handle->DecrementRefCount();
1088 if (handle->HasNoRefCount())
1089 registration_handles_.Remove(registration_handle_id);
1092 void ServiceWorkerDispatcherHost::UnregistrationComplete(
1093 int thread_id,
1094 int request_id,
1095 ServiceWorkerStatusCode status) {
1096 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
1097 SendUnregistrationError(thread_id, request_id, status);
1098 return;
1100 const bool is_success = (status == SERVICE_WORKER_OK);
1101 Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id,
1102 request_id,
1103 is_success));
1104 TRACE_EVENT_ASYNC_END1(
1105 "ServiceWorker",
1106 "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
1107 request_id,
1108 "Status", status);
1111 void ServiceWorkerDispatcherHost::GetRegistrationComplete(
1112 int thread_id,
1113 int provider_id,
1114 int request_id,
1115 ServiceWorkerStatusCode status,
1116 const scoped_refptr<ServiceWorkerRegistration>& registration) {
1117 TRACE_EVENT_ASYNC_END1("ServiceWorker",
1118 "ServiceWorkerDispatcherHost::GetRegistration",
1119 request_id,
1120 "Registration ID",
1121 registration.get() ? registration->id()
1122 : kInvalidServiceWorkerRegistrationId);
1124 if (!GetContext())
1125 return;
1127 ServiceWorkerProviderHost* provider_host =
1128 GetContext()->GetProviderHost(render_process_id_, provider_id);
1129 if (!provider_host)
1130 return; // The provider has already been destroyed.
1132 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
1133 SendGetRegistrationError(thread_id, request_id, status);
1134 return;
1137 ServiceWorkerRegistrationObjectInfo info;
1138 ServiceWorkerVersionAttributes attrs;
1139 if (status == SERVICE_WORKER_OK) {
1140 DCHECK(registration.get());
1141 if (!registration->is_uninstalling()) {
1142 GetRegistrationObjectInfoAndVersionAttributes(
1143 provider_host->AsWeakPtr(), registration.get(), &info, &attrs);
1147 Send(new ServiceWorkerMsg_DidGetRegistration(
1148 thread_id, request_id, info, attrs));
1151 void ServiceWorkerDispatcherHost::GetRegistrationsComplete(
1152 int thread_id,
1153 int provider_id,
1154 int request_id,
1155 const std::vector<scoped_refptr<ServiceWorkerRegistration>>&
1156 registrations) {
1157 TRACE_EVENT_ASYNC_END0("ServiceWorker",
1158 "ServiceWorkerDispatcherHost::GetRegistrations",
1159 request_id);
1160 if (!GetContext())
1161 return;
1163 ServiceWorkerProviderHost* provider_host =
1164 GetContext()->GetProviderHost(render_process_id_, provider_id);
1165 if (!provider_host)
1166 return; // The provider has already been destroyed.
1168 std::vector<ServiceWorkerRegistrationObjectInfo> object_infos;
1169 std::vector<ServiceWorkerVersionAttributes> version_attrs;
1171 for (const auto& registration : registrations) {
1172 DCHECK(registration.get());
1173 if (!registration->is_uninstalling()) {
1174 ServiceWorkerRegistrationObjectInfo object_info;
1175 ServiceWorkerVersionAttributes version_attr;
1176 GetRegistrationObjectInfoAndVersionAttributes(
1177 provider_host->AsWeakPtr(), registration.get(), &object_info,
1178 &version_attr);
1179 object_infos.push_back(object_info);
1180 version_attrs.push_back(version_attr);
1184 Send(new ServiceWorkerMsg_DidGetRegistrations(thread_id, request_id,
1185 object_infos, version_attrs));
1188 void ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete(
1189 int thread_id,
1190 int request_id,
1191 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
1192 ServiceWorkerRegistration* registration) {
1193 DCHECK(registration);
1194 TRACE_EVENT_ASYNC_END1("ServiceWorker",
1195 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
1196 request_id,
1197 "Registration ID",
1198 registration ? registration->id()
1199 : kInvalidServiceWorkerRegistrationId);
1201 if (!GetContext())
1202 return;
1204 ServiceWorkerRegistrationObjectInfo info;
1205 ServiceWorkerVersionAttributes attrs;
1206 GetRegistrationObjectInfoAndVersionAttributes(
1207 provider_host, registration, &info, &attrs);
1208 Send(new ServiceWorkerMsg_DidGetRegistrationForReady(
1209 thread_id, request_id, info, attrs));
1212 void ServiceWorkerDispatcherHost::SendRegistrationError(
1213 int thread_id,
1214 int request_id,
1215 ServiceWorkerStatusCode status,
1216 const std::string& status_message) {
1217 base::string16 error_message;
1218 blink::WebServiceWorkerError::ErrorType error_type;
1219 GetServiceWorkerRegistrationStatusResponse(status, status_message,
1220 &error_type, &error_message);
1221 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
1222 thread_id, request_id, error_type,
1223 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) + error_message));
1226 void ServiceWorkerDispatcherHost::SendUnregistrationError(
1227 int thread_id,
1228 int request_id,
1229 ServiceWorkerStatusCode status) {
1230 base::string16 error_message;
1231 blink::WebServiceWorkerError::ErrorType error_type;
1232 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
1233 &error_message);
1234 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
1235 thread_id, request_id, error_type,
1236 base::ASCIIToUTF16(kServiceWorkerUnregisterErrorPrefix) + error_message));
1239 void ServiceWorkerDispatcherHost::SendGetRegistrationError(
1240 int thread_id,
1241 int request_id,
1242 ServiceWorkerStatusCode status) {
1243 base::string16 error_message;
1244 blink::WebServiceWorkerError::ErrorType error_type;
1245 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
1246 &error_message);
1247 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
1248 thread_id, request_id, error_type,
1249 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
1250 error_message));
1253 void ServiceWorkerDispatcherHost::SendGetRegistrationsError(
1254 int thread_id,
1255 int request_id,
1256 ServiceWorkerStatusCode status) {
1257 base::string16 error_message;
1258 blink::WebServiceWorkerError::ErrorType error_type;
1259 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
1260 &error_message);
1261 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
1262 thread_id, request_id, error_type,
1263 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
1264 error_message));
1267 ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
1268 if (!context_wrapper_.get())
1269 return nullptr;
1270 return context_wrapper_->context();
1273 void ServiceWorkerDispatcherHost::OnTerminateWorker(int handle_id) {
1274 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
1275 if (!handle) {
1276 bad_message::ReceivedBadMessage(this,
1277 bad_message::SWDH_TERMINATE_BAD_HANDLE);
1278 return;
1280 handle->version()->StopWorker(
1281 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
1284 } // namespace content