Update broken references to image assets
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_dispatcher_host.cc
blob0e9f3c97f2bd3bd9ac021b6cb958b4903137f19e
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/common/service_worker/embedded_worker_messages.h"
21 #include "content/common/service_worker/service_worker_messages.h"
22 #include "content/common/service_worker/service_worker_types.h"
23 #include "content/common/service_worker/service_worker_utils.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/modules/serviceworker/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 bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_CANNOT);
336 return;
339 if (!GetContentClient()->browser()->AllowServiceWorker(
340 pattern, provider_host->topmost_frame_url(), resource_context_,
341 render_process_id_, provider_host->frame_id())) {
342 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
343 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
344 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
345 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
346 return;
349 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
350 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
351 request_id,
352 "Pattern", pattern.spec(),
353 "Script URL", script_url.spec());
354 GetContext()->RegisterServiceWorker(
355 pattern,
356 script_url,
357 provider_host,
358 base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete,
359 this,
360 thread_id,
361 provider_id,
362 request_id));
365 void ServiceWorkerDispatcherHost::OnUpdateServiceWorker(int thread_id,
366 int request_id,
367 int provider_id,
368 int64 registration_id) {
369 TRACE_EVENT0("ServiceWorker",
370 "ServiceWorkerDispatcherHost::OnUpdateServiceWorker");
371 if (!GetContext()) {
372 Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
373 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
374 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
375 base::ASCIIToUTF16(kShutdownErrorMessage)));
376 return;
379 ServiceWorkerProviderHost* provider_host =
380 GetContext()->GetProviderHost(render_process_id_, provider_id);
381 if (!provider_host) {
382 bad_message::ReceivedBadMessage(this, bad_message::SWDH_UPDATE_NO_HOST);
383 return;
385 if (!provider_host->IsContextAlive()) {
386 Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
387 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
388 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
389 base::ASCIIToUTF16(kShutdownErrorMessage)));
390 return;
393 // TODO(jungkees): This check can be removed once crbug.com/439697 is fixed.
394 if (provider_host->document_url().is_empty()) {
395 Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
396 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
397 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
398 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
399 return;
402 ServiceWorkerRegistration* registration =
403 GetContext()->GetLiveRegistration(registration_id);
404 if (!registration) {
405 // |registration| must be alive because a renderer retains a registration
406 // reference at this point.
407 bad_message::ReceivedBadMessage(
408 this, bad_message::SWDH_UPDATE_BAD_REGISTRATION_ID);
409 return;
412 if (!CanUpdateServiceWorker(provider_host->document_url(),
413 registration->pattern())) {
414 bad_message::ReceivedBadMessage(this, bad_message::SWDH_UPDATE_CANNOT);
415 return;
418 if (!GetContentClient()->browser()->AllowServiceWorker(
419 registration->pattern(), provider_host->topmost_frame_url(),
420 resource_context_, render_process_id_, provider_host->frame_id())) {
421 Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
422 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
423 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
424 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
425 return;
428 if (!registration->GetNewestVersion()) {
429 // This can happen if update() is called during initial script evaluation.
430 // Abort the following steps according to the spec.
431 Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
432 thread_id, request_id, WebServiceWorkerError::ErrorTypeState,
433 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
434 base::ASCIIToUTF16(kInvalidStateErrorMessage)));
435 return;
438 // The spec says, "update() pings the server for an updated version of this
439 // script without consulting caches", so set |force_bypass_cache| to true.
440 GetContext()->UpdateServiceWorker(
441 registration, true, /* force_bypass_cache */
442 provider_host, base::Bind(&ServiceWorkerDispatcherHost::UpdateComplete,
443 this, thread_id, provider_id, request_id));
446 void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
447 int thread_id,
448 int request_id,
449 int provider_id,
450 int64 registration_id) {
451 TRACE_EVENT0("ServiceWorker",
452 "ServiceWorkerDispatcherHost::OnUnregisterServiceWorker");
453 if (!GetContext()) {
454 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
455 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
456 base::ASCIIToUTF16(kShutdownErrorMessage)));
457 return;
460 ServiceWorkerProviderHost* provider_host =
461 GetContext()->GetProviderHost(render_process_id_, provider_id);
462 if (!provider_host) {
463 bad_message::ReceivedBadMessage(this, bad_message::SWDH_UNREGISTER_NO_HOST);
464 return;
466 if (!provider_host->IsContextAlive()) {
467 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
468 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
469 base::ASCIIToUTF16(kShutdownErrorMessage)));
470 return;
473 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
474 if (provider_host->document_url().is_empty()) {
475 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
476 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
477 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
478 return;
481 ServiceWorkerRegistration* registration =
482 GetContext()->GetLiveRegistration(registration_id);
483 if (!registration) {
484 // |registration| must be alive because a renderer retains a registration
485 // reference at this point.
486 bad_message::ReceivedBadMessage(
487 this, bad_message::SWDH_UNREGISTER_BAD_REGISTRATION_ID);
488 return;
491 if (!CanUnregisterServiceWorker(provider_host->document_url(),
492 registration->pattern())) {
493 bad_message::ReceivedBadMessage(this, bad_message::SWDH_UNREGISTER_CANNOT);
494 return;
497 if (!GetContentClient()->browser()->AllowServiceWorker(
498 registration->pattern(), provider_host->topmost_frame_url(),
499 resource_context_, render_process_id_, provider_host->frame_id())) {
500 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
501 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
502 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
503 return;
506 TRACE_EVENT_ASYNC_BEGIN1(
507 "ServiceWorker", "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
508 request_id, "Pattern", registration->pattern().spec());
509 GetContext()->UnregisterServiceWorker(
510 registration->pattern(),
511 base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete, this,
512 thread_id, request_id));
515 void ServiceWorkerDispatcherHost::OnGetRegistration(
516 int thread_id,
517 int request_id,
518 int provider_id,
519 const GURL& document_url) {
520 TRACE_EVENT0("ServiceWorker",
521 "ServiceWorkerDispatcherHost::OnGetRegistration");
523 DCHECK_CURRENTLY_ON(BrowserThread::IO);
525 if (!GetContext()) {
526 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
527 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
528 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
529 base::ASCIIToUTF16(kShutdownErrorMessage)));
530 return;
532 if (!document_url.is_valid()) {
533 bad_message::ReceivedBadMessage(this,
534 bad_message::SWDH_GET_REGISTRATION_BAD_URL);
535 return;
538 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
539 render_process_id_, provider_id);
540 if (!provider_host) {
541 bad_message::ReceivedBadMessage(this,
542 bad_message::SWDH_GET_REGISTRATION_NO_HOST);
543 return;
545 if (!provider_host->IsContextAlive()) {
546 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
547 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
548 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
549 base::ASCIIToUTF16(kShutdownErrorMessage)));
550 return;
553 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
554 if (provider_host->document_url().is_empty()) {
555 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
556 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
557 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
558 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
559 return;
562 if (!CanGetRegistration(provider_host->document_url(), document_url)) {
563 bad_message::ReceivedBadMessage(this,
564 bad_message::SWDH_GET_REGISTRATION_CANNOT);
565 return;
568 if (!GetContentClient()->browser()->AllowServiceWorker(
569 provider_host->document_url(), provider_host->topmost_frame_url(),
570 resource_context_, render_process_id_, provider_host->frame_id())) {
571 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
572 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
573 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
574 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
575 return;
578 if (GetContext()->storage()->IsDisabled()) {
579 SendGetRegistrationError(thread_id, request_id, SERVICE_WORKER_ERROR_ABORT);
580 return;
583 TRACE_EVENT_ASYNC_BEGIN1(
584 "ServiceWorker",
585 "ServiceWorkerDispatcherHost::GetRegistration",
586 request_id,
587 "Document URL", document_url.spec());
589 GetContext()->storage()->FindRegistrationForDocument(
590 document_url,
591 base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationComplete,
592 this,
593 thread_id,
594 provider_id,
595 request_id));
598 void ServiceWorkerDispatcherHost::OnGetRegistrations(int thread_id,
599 int request_id,
600 int provider_id) {
601 DCHECK_CURRENTLY_ON(BrowserThread::IO);
603 if (!GetContext()) {
604 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
605 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
606 base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
607 base::ASCIIToUTF16(kShutdownErrorMessage)));
608 return;
611 ServiceWorkerProviderHost* provider_host =
612 GetContext()->GetProviderHost(render_process_id_, provider_id);
613 if (!provider_host) {
614 bad_message::ReceivedBadMessage(
615 this, bad_message::SWDH_GET_REGISTRATIONS_NO_HOST);
616 return;
618 if (!provider_host->IsContextAlive()) {
619 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
620 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
621 base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
622 base::ASCIIToUTF16(kShutdownErrorMessage)));
623 return;
626 // TODO(jungkees): This check can be removed once crbug.com/439697 is fixed.
627 if (provider_host->document_url().is_empty()) {
628 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
629 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
630 base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
631 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
632 return;
635 if (!OriginCanAccessServiceWorkers(provider_host->document_url())) {
636 bad_message::ReceivedBadMessage(
637 this, bad_message::SWDH_GET_REGISTRATIONS_INVALID_ORIGIN);
638 return;
641 if (!GetContentClient()->browser()->AllowServiceWorker(
642 provider_host->document_url(), provider_host->topmost_frame_url(),
643 resource_context_, render_process_id_, provider_host->frame_id())) {
644 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
645 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
646 base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
647 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
648 return;
651 if (GetContext()->storage()->IsDisabled()) {
652 SendGetRegistrationsError(thread_id, request_id,
653 SERVICE_WORKER_ERROR_ABORT);
654 return;
657 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
658 "ServiceWorkerDispatcherHost::GetRegistrations",
659 request_id);
661 GetContext()->storage()->GetRegistrationsForOrigin(
662 provider_host->document_url().GetOrigin(),
663 base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationsComplete, this,
664 thread_id, provider_id, request_id));
667 void ServiceWorkerDispatcherHost::OnGetRegistrationForReady(
668 int thread_id,
669 int request_id,
670 int provider_id) {
671 TRACE_EVENT0("ServiceWorker",
672 "ServiceWorkerDispatcherHost::OnGetRegistrationForReady");
673 if (!GetContext())
674 return;
675 ServiceWorkerProviderHost* provider_host =
676 GetContext()->GetProviderHost(render_process_id_, provider_id);
677 if (!provider_host) {
678 bad_message::ReceivedBadMessage(
679 this, bad_message::SWDH_GET_REGISTRATION_FOR_READY_NO_HOST);
680 return;
682 if (!provider_host->IsContextAlive())
683 return;
685 TRACE_EVENT_ASYNC_BEGIN0(
686 "ServiceWorker",
687 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
688 request_id);
690 if (!provider_host->GetRegistrationForReady(base::Bind(
691 &ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete,
692 this, thread_id, request_id, provider_host->AsWeakPtr()))) {
693 bad_message::ReceivedBadMessage(
694 this, bad_message::SWDH_GET_REGISTRATION_FOR_READY_ALREADY_IN_PROGRESS);
698 void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
699 int handle_id,
700 const base::string16& message,
701 const std::vector<TransferredMessagePort>& sent_message_ports) {
702 TRACE_EVENT0("ServiceWorker",
703 "ServiceWorkerDispatcherHost::OnPostMessageToWorker");
704 if (!GetContext())
705 return;
707 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
708 if (!handle) {
709 bad_message::ReceivedBadMessage(this, bad_message::SWDH_POST_MESSAGE);
710 return;
713 handle->version()->DispatchMessageEvent(
714 message, sent_message_ports,
715 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
718 void ServiceWorkerDispatcherHost::OnProviderCreated(
719 int provider_id,
720 int route_id,
721 ServiceWorkerProviderType provider_type) {
722 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
723 tracked_objects::ScopedTracker tracking_profile(
724 FROM_HERE_WITH_EXPLICIT_FUNCTION(
725 "477117 ServiceWorkerDispatcherHost::OnProviderCreated"));
726 TRACE_EVENT0("ServiceWorker",
727 "ServiceWorkerDispatcherHost::OnProviderCreated");
728 if (!GetContext())
729 return;
730 if (GetContext()->GetProviderHost(render_process_id_, provider_id)) {
731 bad_message::ReceivedBadMessage(this,
732 bad_message::SWDH_PROVIDER_CREATED_NO_HOST);
733 return;
735 scoped_ptr<ServiceWorkerProviderHost> provider_host(
736 new ServiceWorkerProviderHost(render_process_id_, route_id, provider_id,
737 provider_type, GetContext()->AsWeakPtr(),
738 this));
739 GetContext()->AddProviderHost(provider_host.Pass());
742 void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
743 TRACE_EVENT0("ServiceWorker",
744 "ServiceWorkerDispatcherHost::OnProviderDestroyed");
745 if (!GetContext())
746 return;
747 if (!GetContext()->GetProviderHost(render_process_id_, provider_id)) {
748 bad_message::ReceivedBadMessage(
749 this, bad_message::SWDH_PROVIDER_DESTROYED_NO_HOST);
750 return;
752 GetContext()->RemoveProviderHost(render_process_id_, provider_id);
755 void ServiceWorkerDispatcherHost::OnSetHostedVersionId(
756 int provider_id, int64 version_id) {
757 TRACE_EVENT0("ServiceWorker",
758 "ServiceWorkerDispatcherHost::OnSetHostedVersionId");
759 if (!GetContext())
760 return;
761 ServiceWorkerProviderHost* provider_host =
762 GetContext()->GetProviderHost(render_process_id_, provider_id);
763 if (!provider_host) {
764 bad_message::ReceivedBadMessage(
765 this, bad_message::SWDH_SET_HOSTED_VERSION_NO_HOST);
766 return;
768 if (!provider_host->IsContextAlive())
769 return;
770 if (!provider_host->SetHostedVersionId(version_id))
771 bad_message::ReceivedBadMessage(this, bad_message::SWDH_SET_HOSTED_VERSION);
773 ServiceWorkerVersion* version = GetContext()->GetLiveVersion(version_id);
774 if (!version)
775 return;
777 // Retrieve the registration associated with |version|. The registration
778 // must be alive because the version keeps it during starting worker.
779 ServiceWorkerRegistration* registration =
780 GetContext()->GetLiveRegistration(version->registration_id());
781 DCHECK(registration);
782 // TODO(ksakamoto): This is a quick fix for crbug.com/459916.
783 if (!registration)
784 return;
786 // Set the document URL to the script url in order to allow
787 // register/unregister/getRegistration on ServiceWorkerGlobalScope.
788 provider_host->SetDocumentUrl(version->script_url());
790 ServiceWorkerRegistrationObjectInfo info;
791 ServiceWorkerVersionAttributes attrs;
792 GetRegistrationObjectInfoAndVersionAttributes(
793 provider_host->AsWeakPtr(), registration, &info, &attrs);
795 Send(new ServiceWorkerMsg_AssociateRegistrationWithServiceWorker(
796 kDocumentMainThreadId, provider_id, info, attrs));
799 ServiceWorkerRegistrationHandle*
800 ServiceWorkerDispatcherHost::FindRegistrationHandle(int provider_id,
801 int64 registration_id) {
802 for (IDMap<ServiceWorkerRegistrationHandle, IDMapOwnPointer>::iterator
803 iter(&registration_handles_);
804 !iter.IsAtEnd();
805 iter.Advance()) {
806 ServiceWorkerRegistrationHandle* handle = iter.GetCurrentValue();
807 DCHECK(handle);
808 DCHECK(handle->registration());
809 if (handle->provider_id() == provider_id &&
810 handle->registration()->id() == registration_id) {
811 return handle;
814 return NULL;
817 void ServiceWorkerDispatcherHost::GetRegistrationObjectInfoAndVersionAttributes(
818 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
819 ServiceWorkerRegistration* registration,
820 ServiceWorkerRegistrationObjectInfo* info,
821 ServiceWorkerVersionAttributes* attrs) {
822 ServiceWorkerRegistrationHandle* handle =
823 GetOrCreateRegistrationHandle(provider_host, registration);
824 *info = handle->GetObjectInfo();
826 attrs->installing = provider_host->GetOrCreateServiceWorkerHandle(
827 registration->installing_version());
828 attrs->waiting = provider_host->GetOrCreateServiceWorkerHandle(
829 registration->waiting_version());
830 attrs->active = provider_host->GetOrCreateServiceWorkerHandle(
831 registration->active_version());
834 void ServiceWorkerDispatcherHost::RegistrationComplete(
835 int thread_id,
836 int provider_id,
837 int request_id,
838 ServiceWorkerStatusCode status,
839 const std::string& status_message,
840 int64 registration_id) {
841 if (!GetContext())
842 return;
844 ServiceWorkerProviderHost* provider_host =
845 GetContext()->GetProviderHost(render_process_id_, provider_id);
846 if (!provider_host)
847 return; // The provider has already been destroyed.
849 if (status != SERVICE_WORKER_OK) {
850 SendRegistrationError(thread_id, request_id, status, status_message);
851 return;
854 ServiceWorkerRegistration* registration =
855 GetContext()->GetLiveRegistration(registration_id);
856 DCHECK(registration);
858 ServiceWorkerRegistrationObjectInfo info;
859 ServiceWorkerVersionAttributes attrs;
860 GetRegistrationObjectInfoAndVersionAttributes(
861 provider_host->AsWeakPtr(), registration, &info, &attrs);
863 Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
864 thread_id, request_id, info, attrs));
865 TRACE_EVENT_ASYNC_END1("ServiceWorker",
866 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
867 request_id,
868 "Registration ID",
869 registration_id);
872 void ServiceWorkerDispatcherHost::UpdateComplete(
873 int thread_id,
874 int provider_id,
875 int request_id,
876 ServiceWorkerStatusCode status,
877 const std::string& status_message,
878 int64 registration_id) {
879 if (!GetContext())
880 return;
882 ServiceWorkerProviderHost* provider_host =
883 GetContext()->GetProviderHost(render_process_id_, provider_id);
884 if (!provider_host)
885 return; // The provider has already been destroyed.
887 if (status != SERVICE_WORKER_OK) {
888 SendUpdateError(thread_id, request_id, status, status_message);
889 return;
892 ServiceWorkerRegistration* registration =
893 GetContext()->GetLiveRegistration(registration_id);
894 DCHECK(registration);
896 ServiceWorkerRegistrationObjectInfo info;
897 ServiceWorkerVersionAttributes attrs;
898 GetRegistrationObjectInfoAndVersionAttributes(provider_host->AsWeakPtr(),
899 registration, &info, &attrs);
901 Send(new ServiceWorkerMsg_ServiceWorkerUpdated(thread_id, request_id));
902 TRACE_EVENT_ASYNC_END1("ServiceWorker",
903 "ServiceWorkerDispatcherHost::UpdateServiceWorker",
904 request_id, "Registration ID", registration_id);
907 void ServiceWorkerDispatcherHost::OnWorkerReadyForInspection(
908 int embedded_worker_id) {
909 TRACE_EVENT0("ServiceWorker",
910 "ServiceWorkerDispatcherHost::OnWorkerReadyForInspection");
911 if (!GetContext())
912 return;
913 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
914 if (!registry->CanHandle(embedded_worker_id))
915 return;
916 registry->OnWorkerReadyForInspection(render_process_id_, embedded_worker_id);
919 void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(
920 int embedded_worker_id,
921 int thread_id,
922 int provider_id) {
923 TRACE_EVENT0("ServiceWorker",
924 "ServiceWorkerDispatcherHost::OnWorkerScriptLoaded");
925 if (!GetContext())
926 return;
928 ServiceWorkerProviderHost* provider_host =
929 GetContext()->GetProviderHost(render_process_id_, provider_id);
930 if (!provider_host) {
931 bad_message::ReceivedBadMessage(
932 this, bad_message::SWDH_WORKER_SCRIPT_LOAD_NO_HOST);
933 return;
936 provider_host->SetReadyToSendMessagesToWorker(thread_id);
938 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
939 if (!registry->CanHandle(embedded_worker_id))
940 return;
941 registry->OnWorkerScriptLoaded(
942 render_process_id_, thread_id, embedded_worker_id);
945 void ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed(
946 int embedded_worker_id) {
947 TRACE_EVENT0("ServiceWorker",
948 "ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed");
949 if (!GetContext())
950 return;
951 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
952 if (!registry->CanHandle(embedded_worker_id))
953 return;
954 registry->OnWorkerScriptLoadFailed(render_process_id_, embedded_worker_id);
957 void ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated(
958 int embedded_worker_id,
959 bool success) {
960 TRACE_EVENT0("ServiceWorker",
961 "ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated");
962 if (!GetContext())
963 return;
964 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
965 if (!registry->CanHandle(embedded_worker_id))
966 return;
967 registry->OnWorkerScriptEvaluated(
968 render_process_id_, embedded_worker_id, success);
971 void ServiceWorkerDispatcherHost::OnWorkerStarted(int embedded_worker_id) {
972 TRACE_EVENT0("ServiceWorker",
973 "ServiceWorkerDispatcherHost::OnWorkerStarted");
974 if (!GetContext())
975 return;
976 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
977 if (!registry->CanHandle(embedded_worker_id))
978 return;
979 registry->OnWorkerStarted(render_process_id_, embedded_worker_id);
982 void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) {
983 TRACE_EVENT0("ServiceWorker",
984 "ServiceWorkerDispatcherHost::OnWorkerStopped");
985 if (!GetContext())
986 return;
987 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
988 if (!registry->CanHandle(embedded_worker_id))
989 return;
990 registry->OnWorkerStopped(render_process_id_, embedded_worker_id);
993 void ServiceWorkerDispatcherHost::OnReportException(
994 int embedded_worker_id,
995 const base::string16& error_message,
996 int line_number,
997 int column_number,
998 const GURL& source_url) {
999 TRACE_EVENT0("ServiceWorker",
1000 "ServiceWorkerDispatcherHost::OnReportException");
1001 if (!GetContext())
1002 return;
1003 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
1004 if (!registry->CanHandle(embedded_worker_id))
1005 return;
1006 registry->OnReportException(embedded_worker_id,
1007 error_message,
1008 line_number,
1009 column_number,
1010 source_url);
1013 void ServiceWorkerDispatcherHost::OnReportConsoleMessage(
1014 int embedded_worker_id,
1015 const EmbeddedWorkerHostMsg_ReportConsoleMessage_Params& params) {
1016 TRACE_EVENT0("ServiceWorker",
1017 "ServiceWorkerDispatcherHost::OnReportConsoleMessage");
1018 if (!GetContext())
1019 return;
1020 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
1021 if (!registry->CanHandle(embedded_worker_id))
1022 return;
1023 registry->OnReportConsoleMessage(embedded_worker_id,
1024 params.source_identifier,
1025 params.message_level,
1026 params.message,
1027 params.line_number,
1028 params.source_url);
1031 void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
1032 int handle_id) {
1033 TRACE_EVENT0("ServiceWorker",
1034 "ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount");
1035 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
1036 if (!handle) {
1037 bad_message::ReceivedBadMessage(
1038 this, bad_message::SWDH_INCREMENT_WORKER_BAD_HANDLE);
1039 return;
1041 handle->IncrementRefCount();
1044 void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
1045 int handle_id) {
1046 TRACE_EVENT0("ServiceWorker",
1047 "ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount");
1048 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
1049 if (!handle) {
1050 bad_message::ReceivedBadMessage(
1051 this, bad_message::SWDH_DECREMENT_WORKER_BAD_HANDLE);
1052 return;
1054 handle->DecrementRefCount();
1055 if (handle->HasNoRefCount())
1056 handles_.Remove(handle_id);
1059 void ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount(
1060 int registration_handle_id) {
1061 TRACE_EVENT0("ServiceWorker",
1062 "ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount");
1063 ServiceWorkerRegistrationHandle* handle =
1064 registration_handles_.Lookup(registration_handle_id);
1065 if (!handle) {
1066 bad_message::ReceivedBadMessage(
1067 this, bad_message::SWDH_INCREMENT_REGISTRATION_BAD_HANDLE);
1068 return;
1070 handle->IncrementRefCount();
1073 void ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount(
1074 int registration_handle_id) {
1075 TRACE_EVENT0("ServiceWorker",
1076 "ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount");
1077 ServiceWorkerRegistrationHandle* handle =
1078 registration_handles_.Lookup(registration_handle_id);
1079 if (!handle) {
1080 bad_message::ReceivedBadMessage(
1081 this, bad_message::SWDH_DECREMENT_REGISTRATION_BAD_HANDLE);
1082 return;
1084 handle->DecrementRefCount();
1085 if (handle->HasNoRefCount())
1086 registration_handles_.Remove(registration_handle_id);
1089 void ServiceWorkerDispatcherHost::UnregistrationComplete(
1090 int thread_id,
1091 int request_id,
1092 ServiceWorkerStatusCode status) {
1093 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
1094 SendUnregistrationError(thread_id, request_id, status);
1095 return;
1097 const bool is_success = (status == SERVICE_WORKER_OK);
1098 Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id,
1099 request_id,
1100 is_success));
1101 TRACE_EVENT_ASYNC_END1(
1102 "ServiceWorker",
1103 "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
1104 request_id,
1105 "Status", status);
1108 void ServiceWorkerDispatcherHost::GetRegistrationComplete(
1109 int thread_id,
1110 int provider_id,
1111 int request_id,
1112 ServiceWorkerStatusCode status,
1113 const scoped_refptr<ServiceWorkerRegistration>& registration) {
1114 TRACE_EVENT_ASYNC_END1("ServiceWorker",
1115 "ServiceWorkerDispatcherHost::GetRegistration",
1116 request_id,
1117 "Registration ID",
1118 registration.get() ? registration->id()
1119 : kInvalidServiceWorkerRegistrationId);
1121 if (!GetContext())
1122 return;
1124 ServiceWorkerProviderHost* provider_host =
1125 GetContext()->GetProviderHost(render_process_id_, provider_id);
1126 if (!provider_host)
1127 return; // The provider has already been destroyed.
1129 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
1130 SendGetRegistrationError(thread_id, request_id, status);
1131 return;
1134 ServiceWorkerRegistrationObjectInfo info;
1135 ServiceWorkerVersionAttributes attrs;
1136 if (status == SERVICE_WORKER_OK) {
1137 DCHECK(registration.get());
1138 if (!registration->is_uninstalling()) {
1139 GetRegistrationObjectInfoAndVersionAttributes(
1140 provider_host->AsWeakPtr(), registration.get(), &info, &attrs);
1144 Send(new ServiceWorkerMsg_DidGetRegistration(
1145 thread_id, request_id, info, attrs));
1148 void ServiceWorkerDispatcherHost::GetRegistrationsComplete(
1149 int thread_id,
1150 int provider_id,
1151 int request_id,
1152 const std::vector<scoped_refptr<ServiceWorkerRegistration>>&
1153 registrations) {
1154 TRACE_EVENT_ASYNC_END0("ServiceWorker",
1155 "ServiceWorkerDispatcherHost::GetRegistrations",
1156 request_id);
1157 if (!GetContext())
1158 return;
1160 ServiceWorkerProviderHost* provider_host =
1161 GetContext()->GetProviderHost(render_process_id_, provider_id);
1162 if (!provider_host)
1163 return; // The provider has already been destroyed.
1165 std::vector<ServiceWorkerRegistrationObjectInfo> object_infos;
1166 std::vector<ServiceWorkerVersionAttributes> version_attrs;
1168 for (const auto& registration : registrations) {
1169 DCHECK(registration.get());
1170 if (!registration->is_uninstalling()) {
1171 ServiceWorkerRegistrationObjectInfo object_info;
1172 ServiceWorkerVersionAttributes version_attr;
1173 GetRegistrationObjectInfoAndVersionAttributes(
1174 provider_host->AsWeakPtr(), registration.get(), &object_info,
1175 &version_attr);
1176 object_infos.push_back(object_info);
1177 version_attrs.push_back(version_attr);
1181 Send(new ServiceWorkerMsg_DidGetRegistrations(thread_id, request_id,
1182 object_infos, version_attrs));
1185 void ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete(
1186 int thread_id,
1187 int request_id,
1188 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
1189 ServiceWorkerRegistration* registration) {
1190 DCHECK(registration);
1191 TRACE_EVENT_ASYNC_END1("ServiceWorker",
1192 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
1193 request_id,
1194 "Registration ID",
1195 registration ? registration->id()
1196 : kInvalidServiceWorkerRegistrationId);
1198 if (!GetContext())
1199 return;
1201 ServiceWorkerRegistrationObjectInfo info;
1202 ServiceWorkerVersionAttributes attrs;
1203 GetRegistrationObjectInfoAndVersionAttributes(
1204 provider_host, registration, &info, &attrs);
1205 Send(new ServiceWorkerMsg_DidGetRegistrationForReady(
1206 thread_id, request_id, info, attrs));
1209 void ServiceWorkerDispatcherHost::SendRegistrationError(
1210 int thread_id,
1211 int request_id,
1212 ServiceWorkerStatusCode status,
1213 const std::string& status_message) {
1214 base::string16 error_message;
1215 blink::WebServiceWorkerError::ErrorType error_type;
1216 GetServiceWorkerRegistrationStatusResponse(status, status_message,
1217 &error_type, &error_message);
1218 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
1219 thread_id, request_id, error_type,
1220 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) + error_message));
1223 void ServiceWorkerDispatcherHost::SendUpdateError(
1224 int thread_id,
1225 int request_id,
1226 ServiceWorkerStatusCode status,
1227 const std::string& status_message) {
1228 base::string16 error_message;
1229 blink::WebServiceWorkerError::ErrorType error_type;
1230 GetServiceWorkerRegistrationStatusResponse(status, status_message,
1231 &error_type, &error_message);
1232 Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
1233 thread_id, request_id, error_type,
1234 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) + error_message));
1237 void ServiceWorkerDispatcherHost::SendUnregistrationError(
1238 int thread_id,
1239 int request_id,
1240 ServiceWorkerStatusCode status) {
1241 base::string16 error_message;
1242 blink::WebServiceWorkerError::ErrorType error_type;
1243 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
1244 &error_message);
1245 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
1246 thread_id, request_id, error_type,
1247 base::ASCIIToUTF16(kServiceWorkerUnregisterErrorPrefix) + error_message));
1250 void ServiceWorkerDispatcherHost::SendGetRegistrationError(
1251 int thread_id,
1252 int request_id,
1253 ServiceWorkerStatusCode status) {
1254 base::string16 error_message;
1255 blink::WebServiceWorkerError::ErrorType error_type;
1256 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
1257 &error_message);
1258 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
1259 thread_id, request_id, error_type,
1260 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
1261 error_message));
1264 void ServiceWorkerDispatcherHost::SendGetRegistrationsError(
1265 int thread_id,
1266 int request_id,
1267 ServiceWorkerStatusCode status) {
1268 base::string16 error_message;
1269 blink::WebServiceWorkerError::ErrorType error_type;
1270 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
1271 &error_message);
1272 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
1273 thread_id, request_id, error_type,
1274 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
1275 error_message));
1278 ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
1279 if (!context_wrapper_.get())
1280 return nullptr;
1281 return context_wrapper_->context();
1284 void ServiceWorkerDispatcherHost::OnTerminateWorker(int handle_id) {
1285 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
1286 if (!handle) {
1287 bad_message::ReceivedBadMessage(this,
1288 bad_message::SWDH_TERMINATE_BAD_HANDLE);
1289 return;
1291 handle->version()->StopWorker(
1292 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
1295 } // namespace content