Roll src/third_party/WebKit eac3800:0237a66 (svn 202606:202607)
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_dispatcher_host.cc
blobeb65e4e2be475a2b65c4a3f6dc2020cd8ad7bd13
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_WorkerThreadStarted,
189 OnWorkerThreadStarted)
190 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoadFailed,
191 OnWorkerScriptLoadFailed)
192 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptEvaluated,
193 OnWorkerScriptEvaluated)
194 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted,
195 OnWorkerStarted)
196 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped,
197 OnWorkerStopped)
198 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportException,
199 OnReportException)
200 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportConsoleMessage,
201 OnReportConsoleMessage)
202 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount,
203 OnIncrementServiceWorkerRefCount)
204 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount,
205 OnDecrementServiceWorkerRefCount)
206 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementRegistrationRefCount,
207 OnIncrementRegistrationRefCount)
208 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
209 OnDecrementRegistrationRefCount)
210 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_TerminateWorker, OnTerminateWorker)
211 IPC_MESSAGE_UNHANDLED(handled = false)
212 IPC_END_MESSAGE_MAP()
214 if (!handled && GetContext()) {
215 handled = GetContext()->embedded_worker_registry()->OnMessageReceived(
216 message, render_process_id_);
217 if (!handled)
218 bad_message::ReceivedBadMessage(this, bad_message::SWDH_NOT_HANDLED);
221 return handled;
224 bool ServiceWorkerDispatcherHost::Send(IPC::Message* message) {
225 if (channel_ready_) {
226 BrowserMessageFilter::Send(message);
227 // Don't bother passing through Send()'s result: it's not reliable.
228 return true;
231 pending_messages_.push_back(message);
232 return true;
235 void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle(
236 scoped_ptr<ServiceWorkerHandle> handle) {
237 int handle_id = handle->handle_id();
238 handles_.AddWithID(handle.release(), handle_id);
241 void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationHandle(
242 scoped_ptr<ServiceWorkerRegistrationHandle> handle) {
243 int handle_id = handle->handle_id();
244 registration_handles_.AddWithID(handle.release(), handle_id);
247 ServiceWorkerHandle* ServiceWorkerDispatcherHost::FindServiceWorkerHandle(
248 int provider_id,
249 int64 version_id) {
250 for (IDMap<ServiceWorkerHandle, IDMapOwnPointer>::iterator iter(&handles_);
251 !iter.IsAtEnd(); iter.Advance()) {
252 ServiceWorkerHandle* handle = iter.GetCurrentValue();
253 DCHECK(handle);
254 DCHECK(handle->version());
255 if (handle->provider_id() == provider_id &&
256 handle->version()->version_id() == version_id) {
257 return handle;
260 return NULL;
263 ServiceWorkerRegistrationHandle*
264 ServiceWorkerDispatcherHost::CreateRegistrationHandle(
265 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
266 ServiceWorkerRegistration* registration) {
267 DCHECK(provider_host);
268 scoped_ptr<ServiceWorkerRegistrationHandle> handle(
269 new ServiceWorkerRegistrationHandle(GetContext()->AsWeakPtr(),
270 provider_host, registration));
271 ServiceWorkerRegistrationHandle* handle_ptr = handle.get();
272 RegisterServiceWorkerRegistrationHandle(handle.Pass());
273 return handle_ptr;
276 void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
277 int thread_id,
278 int request_id,
279 int provider_id,
280 const GURL& pattern,
281 const GURL& script_url) {
282 TRACE_EVENT0("ServiceWorker",
283 "ServiceWorkerDispatcherHost::OnRegisterServiceWorker");
284 if (!GetContext()) {
285 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
286 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
287 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
288 base::ASCIIToUTF16(kShutdownErrorMessage)));
289 return;
291 if (!pattern.is_valid() || !script_url.is_valid()) {
292 bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_BAD_URL);
293 return;
296 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
297 render_process_id_, provider_id);
298 if (!provider_host) {
299 bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_NO_HOST);
300 return;
302 if (!provider_host->IsContextAlive()) {
303 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
304 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
305 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
306 base::ASCIIToUTF16(kShutdownErrorMessage)));
307 return;
310 // TODO(ksakamoto): Currently, document_url is empty if the document is in an
311 // IFRAME using frame.contentDocument.write(...). We can remove this check
312 // once crbug.com/439697 is fixed.
313 if (provider_host->document_url().is_empty()) {
314 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
315 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
316 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
317 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
318 return;
321 if (!CanRegisterServiceWorker(
322 provider_host->document_url(), pattern, script_url)) {
323 bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_CANNOT);
324 return;
327 std::string error_message;
328 if (ServiceWorkerUtils::ContainsDisallowedCharacter(pattern, script_url,
329 &error_message)) {
330 bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_CANNOT);
331 return;
334 if (!GetContentClient()->browser()->AllowServiceWorker(
335 pattern, provider_host->topmost_frame_url(), resource_context_,
336 render_process_id_, provider_host->frame_id())) {
337 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
338 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
339 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
340 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
341 return;
344 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
345 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
346 request_id,
347 "Pattern", pattern.spec(),
348 "Script URL", script_url.spec());
349 GetContext()->RegisterServiceWorker(
350 pattern,
351 script_url,
352 provider_host,
353 base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete,
354 this,
355 thread_id,
356 provider_id,
357 request_id));
360 void ServiceWorkerDispatcherHost::OnUpdateServiceWorker(int thread_id,
361 int request_id,
362 int provider_id,
363 int64 registration_id) {
364 TRACE_EVENT0("ServiceWorker",
365 "ServiceWorkerDispatcherHost::OnUpdateServiceWorker");
366 if (!GetContext()) {
367 Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
368 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
369 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
370 base::ASCIIToUTF16(kShutdownErrorMessage)));
371 return;
374 ServiceWorkerProviderHost* provider_host =
375 GetContext()->GetProviderHost(render_process_id_, provider_id);
376 if (!provider_host) {
377 bad_message::ReceivedBadMessage(this, bad_message::SWDH_UPDATE_NO_HOST);
378 return;
380 if (!provider_host->IsContextAlive()) {
381 Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
382 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
383 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
384 base::ASCIIToUTF16(kShutdownErrorMessage)));
385 return;
388 // TODO(jungkees): This check can be removed once crbug.com/439697 is fixed.
389 if (provider_host->document_url().is_empty()) {
390 Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
391 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
392 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
393 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
394 return;
397 ServiceWorkerRegistration* registration =
398 GetContext()->GetLiveRegistration(registration_id);
399 if (!registration) {
400 // |registration| must be alive because a renderer retains a registration
401 // reference at this point.
402 bad_message::ReceivedBadMessage(
403 this, bad_message::SWDH_UPDATE_BAD_REGISTRATION_ID);
404 return;
407 if (!CanUpdateServiceWorker(provider_host->document_url(),
408 registration->pattern())) {
409 bad_message::ReceivedBadMessage(this, bad_message::SWDH_UPDATE_CANNOT);
410 return;
413 if (!GetContentClient()->browser()->AllowServiceWorker(
414 registration->pattern(), provider_host->topmost_frame_url(),
415 resource_context_, render_process_id_, provider_host->frame_id())) {
416 Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
417 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
418 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
419 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
420 return;
423 if (!registration->GetNewestVersion()) {
424 // This can happen if update() is called during initial script evaluation.
425 // Abort the following steps according to the spec.
426 Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
427 thread_id, request_id, WebServiceWorkerError::ErrorTypeState,
428 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
429 base::ASCIIToUTF16(kInvalidStateErrorMessage)));
430 return;
433 // The spec says, "update() pings the server for an updated version of this
434 // script without consulting caches", so set |force_bypass_cache| to true.
435 GetContext()->UpdateServiceWorker(
436 registration, true, /* force_bypass_cache */
437 provider_host, base::Bind(&ServiceWorkerDispatcherHost::UpdateComplete,
438 this, thread_id, provider_id, request_id));
441 void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
442 int thread_id,
443 int request_id,
444 int provider_id,
445 int64 registration_id) {
446 TRACE_EVENT0("ServiceWorker",
447 "ServiceWorkerDispatcherHost::OnUnregisterServiceWorker");
448 if (!GetContext()) {
449 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
450 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
451 base::ASCIIToUTF16(kShutdownErrorMessage)));
452 return;
455 ServiceWorkerProviderHost* provider_host =
456 GetContext()->GetProviderHost(render_process_id_, provider_id);
457 if (!provider_host) {
458 bad_message::ReceivedBadMessage(this, bad_message::SWDH_UNREGISTER_NO_HOST);
459 return;
461 if (!provider_host->IsContextAlive()) {
462 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
463 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
464 base::ASCIIToUTF16(kShutdownErrorMessage)));
465 return;
468 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
469 if (provider_host->document_url().is_empty()) {
470 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
471 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
472 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
473 return;
476 ServiceWorkerRegistration* registration =
477 GetContext()->GetLiveRegistration(registration_id);
478 if (!registration) {
479 // |registration| must be alive because a renderer retains a registration
480 // reference at this point.
481 bad_message::ReceivedBadMessage(
482 this, bad_message::SWDH_UNREGISTER_BAD_REGISTRATION_ID);
483 return;
486 if (!CanUnregisterServiceWorker(provider_host->document_url(),
487 registration->pattern())) {
488 bad_message::ReceivedBadMessage(this, bad_message::SWDH_UNREGISTER_CANNOT);
489 return;
492 if (!GetContentClient()->browser()->AllowServiceWorker(
493 registration->pattern(), provider_host->topmost_frame_url(),
494 resource_context_, render_process_id_, provider_host->frame_id())) {
495 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
496 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
497 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
498 return;
501 TRACE_EVENT_ASYNC_BEGIN1(
502 "ServiceWorker", "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
503 request_id, "Pattern", registration->pattern().spec());
504 GetContext()->UnregisterServiceWorker(
505 registration->pattern(),
506 base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete, this,
507 thread_id, request_id));
510 void ServiceWorkerDispatcherHost::OnGetRegistration(
511 int thread_id,
512 int request_id,
513 int provider_id,
514 const GURL& document_url) {
515 TRACE_EVENT0("ServiceWorker",
516 "ServiceWorkerDispatcherHost::OnGetRegistration");
518 DCHECK_CURRENTLY_ON(BrowserThread::IO);
520 if (!GetContext()) {
521 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
522 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
523 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
524 base::ASCIIToUTF16(kShutdownErrorMessage)));
525 return;
527 if (!document_url.is_valid()) {
528 bad_message::ReceivedBadMessage(this,
529 bad_message::SWDH_GET_REGISTRATION_BAD_URL);
530 return;
533 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
534 render_process_id_, provider_id);
535 if (!provider_host) {
536 bad_message::ReceivedBadMessage(this,
537 bad_message::SWDH_GET_REGISTRATION_NO_HOST);
538 return;
540 if (!provider_host->IsContextAlive()) {
541 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
542 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
543 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
544 base::ASCIIToUTF16(kShutdownErrorMessage)));
545 return;
548 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
549 if (provider_host->document_url().is_empty()) {
550 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
551 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
552 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
553 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
554 return;
557 if (!CanGetRegistration(provider_host->document_url(), document_url)) {
558 bad_message::ReceivedBadMessage(this,
559 bad_message::SWDH_GET_REGISTRATION_CANNOT);
560 return;
563 if (!GetContentClient()->browser()->AllowServiceWorker(
564 provider_host->document_url(), provider_host->topmost_frame_url(),
565 resource_context_, render_process_id_, provider_host->frame_id())) {
566 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
567 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
568 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
569 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
570 return;
573 if (GetContext()->storage()->IsDisabled()) {
574 SendGetRegistrationError(thread_id, request_id, SERVICE_WORKER_ERROR_ABORT);
575 return;
578 TRACE_EVENT_ASYNC_BEGIN1(
579 "ServiceWorker",
580 "ServiceWorkerDispatcherHost::GetRegistration",
581 request_id,
582 "Document URL", document_url.spec());
584 GetContext()->storage()->FindRegistrationForDocument(
585 document_url,
586 base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationComplete,
587 this,
588 thread_id,
589 provider_id,
590 request_id));
593 void ServiceWorkerDispatcherHost::OnGetRegistrations(int thread_id,
594 int request_id,
595 int provider_id) {
596 DCHECK_CURRENTLY_ON(BrowserThread::IO);
598 if (!GetContext()) {
599 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
600 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
601 base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
602 base::ASCIIToUTF16(kShutdownErrorMessage)));
603 return;
606 ServiceWorkerProviderHost* provider_host =
607 GetContext()->GetProviderHost(render_process_id_, provider_id);
608 if (!provider_host) {
609 bad_message::ReceivedBadMessage(
610 this, bad_message::SWDH_GET_REGISTRATIONS_NO_HOST);
611 return;
613 if (!provider_host->IsContextAlive()) {
614 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
615 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
616 base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
617 base::ASCIIToUTF16(kShutdownErrorMessage)));
618 return;
621 // TODO(jungkees): This check can be removed once crbug.com/439697 is fixed.
622 if (provider_host->document_url().is_empty()) {
623 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
624 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
625 base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
626 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
627 return;
630 if (!OriginCanAccessServiceWorkers(provider_host->document_url())) {
631 bad_message::ReceivedBadMessage(
632 this, bad_message::SWDH_GET_REGISTRATIONS_INVALID_ORIGIN);
633 return;
636 if (!GetContentClient()->browser()->AllowServiceWorker(
637 provider_host->document_url(), provider_host->topmost_frame_url(),
638 resource_context_, render_process_id_, provider_host->frame_id())) {
639 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
640 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
641 base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
642 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
643 return;
646 if (GetContext()->storage()->IsDisabled()) {
647 SendGetRegistrationsError(thread_id, request_id,
648 SERVICE_WORKER_ERROR_ABORT);
649 return;
652 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
653 "ServiceWorkerDispatcherHost::GetRegistrations",
654 request_id);
656 GetContext()->storage()->GetRegistrationsForOrigin(
657 provider_host->document_url().GetOrigin(),
658 base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationsComplete, this,
659 thread_id, provider_id, request_id));
662 void ServiceWorkerDispatcherHost::OnGetRegistrationForReady(
663 int thread_id,
664 int request_id,
665 int provider_id) {
666 TRACE_EVENT0("ServiceWorker",
667 "ServiceWorkerDispatcherHost::OnGetRegistrationForReady");
668 if (!GetContext())
669 return;
670 ServiceWorkerProviderHost* provider_host =
671 GetContext()->GetProviderHost(render_process_id_, provider_id);
672 if (!provider_host) {
673 bad_message::ReceivedBadMessage(
674 this, bad_message::SWDH_GET_REGISTRATION_FOR_READY_NO_HOST);
675 return;
677 if (!provider_host->IsContextAlive())
678 return;
680 TRACE_EVENT_ASYNC_BEGIN0(
681 "ServiceWorker",
682 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
683 request_id);
685 if (!provider_host->GetRegistrationForReady(base::Bind(
686 &ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete,
687 this, thread_id, request_id, provider_host->AsWeakPtr()))) {
688 bad_message::ReceivedBadMessage(
689 this, bad_message::SWDH_GET_REGISTRATION_FOR_READY_ALREADY_IN_PROGRESS);
693 void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
694 int handle_id,
695 const base::string16& message,
696 const std::vector<TransferredMessagePort>& sent_message_ports) {
697 TRACE_EVENT0("ServiceWorker",
698 "ServiceWorkerDispatcherHost::OnPostMessageToWorker");
699 if (!GetContext())
700 return;
702 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
703 if (!handle) {
704 bad_message::ReceivedBadMessage(this, bad_message::SWDH_POST_MESSAGE);
705 return;
708 handle->version()->DispatchMessageEvent(
709 message, sent_message_ports,
710 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
713 void ServiceWorkerDispatcherHost::OnProviderCreated(
714 int provider_id,
715 int route_id,
716 ServiceWorkerProviderType provider_type) {
717 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
718 tracked_objects::ScopedTracker tracking_profile(
719 FROM_HERE_WITH_EXPLICIT_FUNCTION(
720 "477117 ServiceWorkerDispatcherHost::OnProviderCreated"));
721 TRACE_EVENT0("ServiceWorker",
722 "ServiceWorkerDispatcherHost::OnProviderCreated");
723 if (!GetContext())
724 return;
725 if (GetContext()->GetProviderHost(render_process_id_, provider_id)) {
726 bad_message::ReceivedBadMessage(this,
727 bad_message::SWDH_PROVIDER_CREATED_NO_HOST);
728 return;
730 scoped_ptr<ServiceWorkerProviderHost> provider_host(
731 new ServiceWorkerProviderHost(render_process_id_, route_id, provider_id,
732 provider_type, GetContext()->AsWeakPtr(),
733 this));
734 GetContext()->AddProviderHost(provider_host.Pass());
737 void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
738 TRACE_EVENT0("ServiceWorker",
739 "ServiceWorkerDispatcherHost::OnProviderDestroyed");
740 if (!GetContext())
741 return;
742 if (!GetContext()->GetProviderHost(render_process_id_, provider_id)) {
743 bad_message::ReceivedBadMessage(
744 this, bad_message::SWDH_PROVIDER_DESTROYED_NO_HOST);
745 return;
747 GetContext()->RemoveProviderHost(render_process_id_, provider_id);
750 void ServiceWorkerDispatcherHost::OnSetHostedVersionId(
751 int provider_id, int64 version_id) {
752 TRACE_EVENT0("ServiceWorker",
753 "ServiceWorkerDispatcherHost::OnSetHostedVersionId");
754 if (!GetContext())
755 return;
756 ServiceWorkerProviderHost* provider_host =
757 GetContext()->GetProviderHost(render_process_id_, provider_id);
758 if (!provider_host) {
759 bad_message::ReceivedBadMessage(
760 this, bad_message::SWDH_SET_HOSTED_VERSION_NO_HOST);
761 return;
763 if (!provider_host->IsContextAlive())
764 return;
766 ServiceWorkerVersion* version = GetContext()->GetLiveVersion(version_id);
767 if (!version || version->running_status() == ServiceWorkerVersion::STOPPING)
768 return;
770 if (!provider_host->SetHostedVersionId(version_id))
771 bad_message::ReceivedBadMessage(this, bad_message::SWDH_SET_HOSTED_VERSION);
773 // Retrieve the registration associated with |version|. The registration
774 // must be alive because the version keeps it during starting worker.
775 ServiceWorkerRegistration* registration =
776 GetContext()->GetLiveRegistration(version->registration_id());
777 DCHECK(registration);
779 // Set the document URL to the script url in order to allow
780 // register/unregister/getRegistration on ServiceWorkerGlobalScope.
781 provider_host->SetDocumentUrl(version->script_url());
783 ServiceWorkerRegistrationObjectInfo info;
784 ServiceWorkerVersionAttributes attrs;
785 GetRegistrationObjectInfoAndVersionAttributes(
786 provider_host->AsWeakPtr(), registration, &info, &attrs);
788 Send(new ServiceWorkerMsg_AssociateRegistrationWithServiceWorker(
789 kDocumentMainThreadId, provider_id, info, attrs));
792 void ServiceWorkerDispatcherHost::GetRegistrationObjectInfoAndVersionAttributes(
793 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
794 ServiceWorkerRegistration* registration,
795 ServiceWorkerRegistrationObjectInfo* info,
796 ServiceWorkerVersionAttributes* attrs) {
797 ServiceWorkerRegistrationHandle* handle =
798 CreateRegistrationHandle(provider_host, registration);
799 *info = handle->GetObjectInfo();
801 attrs->installing = provider_host->GetOrCreateServiceWorkerHandle(
802 registration->installing_version());
803 attrs->waiting = provider_host->GetOrCreateServiceWorkerHandle(
804 registration->waiting_version());
805 attrs->active = provider_host->GetOrCreateServiceWorkerHandle(
806 registration->active_version());
809 void ServiceWorkerDispatcherHost::RegistrationComplete(
810 int thread_id,
811 int provider_id,
812 int request_id,
813 ServiceWorkerStatusCode status,
814 const std::string& status_message,
815 int64 registration_id) {
816 if (!GetContext())
817 return;
819 ServiceWorkerProviderHost* provider_host =
820 GetContext()->GetProviderHost(render_process_id_, provider_id);
821 if (!provider_host)
822 return; // The provider has already been destroyed.
824 if (status != SERVICE_WORKER_OK) {
825 SendRegistrationError(thread_id, request_id, status, status_message);
826 return;
829 ServiceWorkerRegistration* registration =
830 GetContext()->GetLiveRegistration(registration_id);
831 DCHECK(registration);
833 ServiceWorkerRegistrationObjectInfo info;
834 ServiceWorkerVersionAttributes attrs;
835 GetRegistrationObjectInfoAndVersionAttributes(
836 provider_host->AsWeakPtr(), registration, &info, &attrs);
838 Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
839 thread_id, request_id, info, attrs));
840 TRACE_EVENT_ASYNC_END1("ServiceWorker",
841 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
842 request_id,
843 "Registration ID",
844 registration_id);
847 void ServiceWorkerDispatcherHost::UpdateComplete(
848 int thread_id,
849 int provider_id,
850 int request_id,
851 ServiceWorkerStatusCode status,
852 const std::string& status_message,
853 int64 registration_id) {
854 if (!GetContext())
855 return;
857 ServiceWorkerProviderHost* provider_host =
858 GetContext()->GetProviderHost(render_process_id_, provider_id);
859 if (!provider_host)
860 return; // The provider has already been destroyed.
862 if (status != SERVICE_WORKER_OK) {
863 SendUpdateError(thread_id, request_id, status, status_message);
864 return;
867 ServiceWorkerRegistration* registration =
868 GetContext()->GetLiveRegistration(registration_id);
869 DCHECK(registration);
871 ServiceWorkerRegistrationObjectInfo info;
872 ServiceWorkerVersionAttributes attrs;
873 GetRegistrationObjectInfoAndVersionAttributes(provider_host->AsWeakPtr(),
874 registration, &info, &attrs);
876 Send(new ServiceWorkerMsg_ServiceWorkerUpdated(thread_id, request_id));
877 TRACE_EVENT_ASYNC_END1("ServiceWorker",
878 "ServiceWorkerDispatcherHost::UpdateServiceWorker",
879 request_id, "Registration ID", registration_id);
882 void ServiceWorkerDispatcherHost::OnWorkerReadyForInspection(
883 int embedded_worker_id) {
884 TRACE_EVENT0("ServiceWorker",
885 "ServiceWorkerDispatcherHost::OnWorkerReadyForInspection");
886 if (!GetContext())
887 return;
888 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
889 if (!registry->CanHandle(embedded_worker_id))
890 return;
891 registry->OnWorkerReadyForInspection(render_process_id_, embedded_worker_id);
894 void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(int embedded_worker_id) {
895 TRACE_EVENT0("ServiceWorker",
896 "ServiceWorkerDispatcherHost::OnWorkerScriptLoaded");
897 if (!GetContext())
898 return;
900 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
901 if (!registry->CanHandle(embedded_worker_id))
902 return;
903 registry->OnWorkerScriptLoaded(render_process_id_, embedded_worker_id);
906 void ServiceWorkerDispatcherHost::OnWorkerThreadStarted(int embedded_worker_id,
907 int thread_id,
908 int provider_id) {
909 TRACE_EVENT0("ServiceWorker",
910 "ServiceWorkerDispatcherHost::OnWorkerThreadStarted");
911 if (!GetContext())
912 return;
914 ServiceWorkerProviderHost* provider_host =
915 GetContext()->GetProviderHost(render_process_id_, provider_id);
916 if (!provider_host) {
917 bad_message::ReceivedBadMessage(
918 this, bad_message::SWDH_WORKER_SCRIPT_LOAD_NO_HOST);
919 return;
922 provider_host->SetReadyToSendMessagesToWorker(thread_id);
924 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
925 if (!registry->CanHandle(embedded_worker_id))
926 return;
927 registry->OnWorkerThreadStarted(render_process_id_, thread_id,
928 embedded_worker_id);
931 void ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed(
932 int embedded_worker_id) {
933 TRACE_EVENT0("ServiceWorker",
934 "ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed");
935 if (!GetContext())
936 return;
937 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
938 if (!registry->CanHandle(embedded_worker_id))
939 return;
940 registry->OnWorkerScriptLoadFailed(render_process_id_, embedded_worker_id);
943 void ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated(
944 int embedded_worker_id,
945 bool success) {
946 TRACE_EVENT0("ServiceWorker",
947 "ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated");
948 if (!GetContext())
949 return;
950 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
951 if (!registry->CanHandle(embedded_worker_id))
952 return;
953 registry->OnWorkerScriptEvaluated(
954 render_process_id_, embedded_worker_id, success);
957 void ServiceWorkerDispatcherHost::OnWorkerStarted(int embedded_worker_id) {
958 TRACE_EVENT0("ServiceWorker",
959 "ServiceWorkerDispatcherHost::OnWorkerStarted");
960 if (!GetContext())
961 return;
962 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
963 if (!registry->CanHandle(embedded_worker_id))
964 return;
965 registry->OnWorkerStarted(render_process_id_, embedded_worker_id);
968 void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) {
969 TRACE_EVENT0("ServiceWorker",
970 "ServiceWorkerDispatcherHost::OnWorkerStopped");
971 if (!GetContext())
972 return;
973 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
974 if (!registry->CanHandle(embedded_worker_id))
975 return;
976 registry->OnWorkerStopped(render_process_id_, embedded_worker_id);
979 void ServiceWorkerDispatcherHost::OnReportException(
980 int embedded_worker_id,
981 const base::string16& error_message,
982 int line_number,
983 int column_number,
984 const GURL& source_url) {
985 TRACE_EVENT0("ServiceWorker",
986 "ServiceWorkerDispatcherHost::OnReportException");
987 if (!GetContext())
988 return;
989 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
990 if (!registry->CanHandle(embedded_worker_id))
991 return;
992 registry->OnReportException(embedded_worker_id,
993 error_message,
994 line_number,
995 column_number,
996 source_url);
999 void ServiceWorkerDispatcherHost::OnReportConsoleMessage(
1000 int embedded_worker_id,
1001 const EmbeddedWorkerHostMsg_ReportConsoleMessage_Params& params) {
1002 TRACE_EVENT0("ServiceWorker",
1003 "ServiceWorkerDispatcherHost::OnReportConsoleMessage");
1004 if (!GetContext())
1005 return;
1006 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
1007 if (!registry->CanHandle(embedded_worker_id))
1008 return;
1009 registry->OnReportConsoleMessage(embedded_worker_id,
1010 params.source_identifier,
1011 params.message_level,
1012 params.message,
1013 params.line_number,
1014 params.source_url);
1017 void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
1018 int handle_id) {
1019 TRACE_EVENT0("ServiceWorker",
1020 "ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount");
1021 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
1022 if (!handle) {
1023 bad_message::ReceivedBadMessage(
1024 this, bad_message::SWDH_INCREMENT_WORKER_BAD_HANDLE);
1025 return;
1027 handle->IncrementRefCount();
1030 void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
1031 int handle_id) {
1032 TRACE_EVENT0("ServiceWorker",
1033 "ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount");
1034 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
1035 if (!handle) {
1036 bad_message::ReceivedBadMessage(
1037 this, bad_message::SWDH_DECREMENT_WORKER_BAD_HANDLE);
1038 return;
1040 handle->DecrementRefCount();
1041 if (handle->HasNoRefCount())
1042 handles_.Remove(handle_id);
1045 void ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount(
1046 int registration_handle_id) {
1047 TRACE_EVENT0("ServiceWorker",
1048 "ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount");
1049 ServiceWorkerRegistrationHandle* handle =
1050 registration_handles_.Lookup(registration_handle_id);
1051 if (!handle) {
1052 bad_message::ReceivedBadMessage(
1053 this, bad_message::SWDH_INCREMENT_REGISTRATION_BAD_HANDLE);
1054 return;
1056 handle->IncrementRefCount();
1059 void ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount(
1060 int registration_handle_id) {
1061 TRACE_EVENT0("ServiceWorker",
1062 "ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount");
1063 ServiceWorkerRegistrationHandle* handle =
1064 registration_handles_.Lookup(registration_handle_id);
1065 if (!handle) {
1066 bad_message::ReceivedBadMessage(
1067 this, bad_message::SWDH_DECREMENT_REGISTRATION_BAD_HANDLE);
1068 return;
1070 handle->DecrementRefCount();
1071 if (handle->HasNoRefCount())
1072 registration_handles_.Remove(registration_handle_id);
1075 void ServiceWorkerDispatcherHost::UnregistrationComplete(
1076 int thread_id,
1077 int request_id,
1078 ServiceWorkerStatusCode status) {
1079 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
1080 SendUnregistrationError(thread_id, request_id, status);
1081 return;
1083 const bool is_success = (status == SERVICE_WORKER_OK);
1084 Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id,
1085 request_id,
1086 is_success));
1087 TRACE_EVENT_ASYNC_END1(
1088 "ServiceWorker",
1089 "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
1090 request_id,
1091 "Status", status);
1094 void ServiceWorkerDispatcherHost::GetRegistrationComplete(
1095 int thread_id,
1096 int provider_id,
1097 int request_id,
1098 ServiceWorkerStatusCode status,
1099 const scoped_refptr<ServiceWorkerRegistration>& registration) {
1100 TRACE_EVENT_ASYNC_END1("ServiceWorker",
1101 "ServiceWorkerDispatcherHost::GetRegistration",
1102 request_id,
1103 "Registration ID",
1104 registration.get() ? registration->id()
1105 : kInvalidServiceWorkerRegistrationId);
1107 if (!GetContext())
1108 return;
1110 ServiceWorkerProviderHost* provider_host =
1111 GetContext()->GetProviderHost(render_process_id_, provider_id);
1112 if (!provider_host)
1113 return; // The provider has already been destroyed.
1115 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
1116 SendGetRegistrationError(thread_id, request_id, status);
1117 return;
1120 ServiceWorkerRegistrationObjectInfo info;
1121 ServiceWorkerVersionAttributes attrs;
1122 if (status == SERVICE_WORKER_OK) {
1123 DCHECK(registration.get());
1124 if (!registration->is_uninstalling()) {
1125 GetRegistrationObjectInfoAndVersionAttributes(
1126 provider_host->AsWeakPtr(), registration.get(), &info, &attrs);
1130 Send(new ServiceWorkerMsg_DidGetRegistration(
1131 thread_id, request_id, info, attrs));
1134 void ServiceWorkerDispatcherHost::GetRegistrationsComplete(
1135 int thread_id,
1136 int provider_id,
1137 int request_id,
1138 const std::vector<scoped_refptr<ServiceWorkerRegistration>>&
1139 registrations) {
1140 TRACE_EVENT_ASYNC_END0("ServiceWorker",
1141 "ServiceWorkerDispatcherHost::GetRegistrations",
1142 request_id);
1143 if (!GetContext())
1144 return;
1146 ServiceWorkerProviderHost* provider_host =
1147 GetContext()->GetProviderHost(render_process_id_, provider_id);
1148 if (!provider_host)
1149 return; // The provider has already been destroyed.
1151 std::vector<ServiceWorkerRegistrationObjectInfo> object_infos;
1152 std::vector<ServiceWorkerVersionAttributes> version_attrs;
1154 for (const auto& registration : registrations) {
1155 DCHECK(registration.get());
1156 if (!registration->is_uninstalling()) {
1157 ServiceWorkerRegistrationObjectInfo object_info;
1158 ServiceWorkerVersionAttributes version_attr;
1159 GetRegistrationObjectInfoAndVersionAttributes(
1160 provider_host->AsWeakPtr(), registration.get(), &object_info,
1161 &version_attr);
1162 object_infos.push_back(object_info);
1163 version_attrs.push_back(version_attr);
1167 Send(new ServiceWorkerMsg_DidGetRegistrations(thread_id, request_id,
1168 object_infos, version_attrs));
1171 void ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete(
1172 int thread_id,
1173 int request_id,
1174 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
1175 ServiceWorkerRegistration* registration) {
1176 DCHECK(registration);
1177 TRACE_EVENT_ASYNC_END1("ServiceWorker",
1178 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
1179 request_id,
1180 "Registration ID",
1181 registration ? registration->id()
1182 : kInvalidServiceWorkerRegistrationId);
1184 if (!GetContext())
1185 return;
1187 ServiceWorkerRegistrationObjectInfo info;
1188 ServiceWorkerVersionAttributes attrs;
1189 GetRegistrationObjectInfoAndVersionAttributes(
1190 provider_host, registration, &info, &attrs);
1191 Send(new ServiceWorkerMsg_DidGetRegistrationForReady(
1192 thread_id, request_id, info, attrs));
1195 void ServiceWorkerDispatcherHost::SendRegistrationError(
1196 int thread_id,
1197 int request_id,
1198 ServiceWorkerStatusCode status,
1199 const std::string& status_message) {
1200 base::string16 error_message;
1201 blink::WebServiceWorkerError::ErrorType error_type;
1202 GetServiceWorkerRegistrationStatusResponse(status, status_message,
1203 &error_type, &error_message);
1204 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
1205 thread_id, request_id, error_type,
1206 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) + error_message));
1209 void ServiceWorkerDispatcherHost::SendUpdateError(
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_ServiceWorkerUpdateError(
1219 thread_id, request_id, error_type,
1220 base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) + error_message));
1223 void ServiceWorkerDispatcherHost::SendUnregistrationError(
1224 int thread_id,
1225 int request_id,
1226 ServiceWorkerStatusCode status) {
1227 base::string16 error_message;
1228 blink::WebServiceWorkerError::ErrorType error_type;
1229 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
1230 &error_message);
1231 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
1232 thread_id, request_id, error_type,
1233 base::ASCIIToUTF16(kServiceWorkerUnregisterErrorPrefix) + error_message));
1236 void ServiceWorkerDispatcherHost::SendGetRegistrationError(
1237 int thread_id,
1238 int request_id,
1239 ServiceWorkerStatusCode status) {
1240 base::string16 error_message;
1241 blink::WebServiceWorkerError::ErrorType error_type;
1242 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
1243 &error_message);
1244 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
1245 thread_id, request_id, error_type,
1246 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
1247 error_message));
1250 void ServiceWorkerDispatcherHost::SendGetRegistrationsError(
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_ServiceWorkerGetRegistrationsError(
1259 thread_id, request_id, error_type,
1260 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
1261 error_message));
1264 ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
1265 if (!context_wrapper_.get())
1266 return nullptr;
1267 return context_wrapper_->context();
1270 void ServiceWorkerDispatcherHost::OnTerminateWorker(int handle_id) {
1271 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
1272 if (!handle) {
1273 bad_message::ReceivedBadMessage(this,
1274 bad_message::SWDH_TERMINATE_BAD_HANDLE);
1275 return;
1277 handle->version()->StopWorker(
1278 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
1281 } // namespace content