Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_dispatcher_host.cc
blob2afe6668d3cfce2aba57c507ffda61ff2db0b0bf
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/service_worker/service_worker_dispatcher_host.h"
7 #include "base/logging.h"
8 #include "base/profiler/scoped_tracker.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/trace_event/trace_event.h"
11 #include "content/browser/bad_message.h"
12 #include "content/browser/message_port_message_filter.h"
13 #include "content/browser/message_port_service.h"
14 #include "content/browser/service_worker/embedded_worker_registry.h"
15 #include "content/browser/service_worker/service_worker_context_core.h"
16 #include "content/browser/service_worker/service_worker_context_wrapper.h"
17 #include "content/browser/service_worker/service_worker_handle.h"
18 #include "content/browser/service_worker/service_worker_registration.h"
19 #include "content/browser/service_worker/service_worker_registration_handle.h"
20 #include "content/browser/service_worker/service_worker_utils.h"
21 #include "content/common/service_worker/embedded_worker_messages.h"
22 #include "content/common/service_worker/service_worker_messages.h"
23 #include "content/common/service_worker/service_worker_types.h"
24 #include "content/public/browser/content_browser_client.h"
25 #include "content/public/common/content_client.h"
26 #include "content/public/common/origin_util.h"
27 #include "ipc/ipc_message_macros.h"
28 #include "net/base/net_util.h"
29 #include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
30 #include "url/gurl.h"
32 using blink::WebServiceWorkerError;
34 namespace content {
36 namespace {
38 const char kNoDocumentURLErrorMessage[] =
39 "No URL is associated with the caller's document.";
40 const char kShutdownErrorMessage[] =
41 "The Service Worker system has shutdown.";
42 const char kUserDeniedPermissionMessage[] =
43 "The user denied permission to use Service Worker.";
45 const uint32 kFilteredMessageClasses[] = {
46 ServiceWorkerMsgStart,
47 EmbeddedWorkerMsgStart,
50 bool AllOriginsMatch(const GURL& url_a, const GURL& url_b, const GURL& url_c) {
51 return url_a.GetOrigin() == url_b.GetOrigin() &&
52 url_a.GetOrigin() == url_c.GetOrigin();
55 bool OriginCanAccessServiceWorkers(const GURL& url) {
56 return url.SchemeIsHTTPOrHTTPS() && IsOriginSecure(url);
59 bool CanRegisterServiceWorker(const GURL& document_url,
60 const GURL& pattern,
61 const GURL& script_url) {
62 DCHECK(document_url.is_valid());
63 DCHECK(pattern.is_valid());
64 DCHECK(script_url.is_valid());
65 return AllOriginsMatch(document_url, pattern, script_url) &&
66 OriginCanAccessServiceWorkers(document_url) &&
67 OriginCanAccessServiceWorkers(pattern) &&
68 OriginCanAccessServiceWorkers(script_url);
71 bool CanUnregisterServiceWorker(const GURL& document_url,
72 const GURL& pattern) {
73 DCHECK(document_url.is_valid());
74 DCHECK(pattern.is_valid());
75 return document_url.GetOrigin() == pattern.GetOrigin() &&
76 OriginCanAccessServiceWorkers(document_url) &&
77 OriginCanAccessServiceWorkers(pattern);
80 bool CanUpdateServiceWorker(const GURL& document_url, const GURL& pattern) {
81 DCHECK(document_url.is_valid());
82 DCHECK(pattern.is_valid());
83 DCHECK(OriginCanAccessServiceWorkers(document_url));
84 DCHECK(OriginCanAccessServiceWorkers(pattern));
85 return document_url.GetOrigin() == pattern.GetOrigin();
88 bool CanGetRegistration(const GURL& document_url,
89 const GURL& given_document_url) {
90 DCHECK(document_url.is_valid());
91 DCHECK(given_document_url.is_valid());
92 return document_url.GetOrigin() == given_document_url.GetOrigin() &&
93 OriginCanAccessServiceWorkers(document_url) &&
94 OriginCanAccessServiceWorkers(given_document_url);
97 } // namespace
99 ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
100 int render_process_id,
101 MessagePortMessageFilter* message_port_message_filter,
102 ResourceContext* resource_context)
103 : BrowserMessageFilter(kFilteredMessageClasses,
104 arraysize(kFilteredMessageClasses)),
105 render_process_id_(render_process_id),
106 message_port_message_filter_(message_port_message_filter),
107 resource_context_(resource_context),
108 channel_ready_(false) {
111 ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
112 if (GetContext()) {
113 GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
114 GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
115 render_process_id_);
119 void ServiceWorkerDispatcherHost::Init(
120 ServiceWorkerContextWrapper* context_wrapper) {
121 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
122 BrowserThread::PostTask(
123 BrowserThread::IO, FROM_HERE,
124 base::Bind(&ServiceWorkerDispatcherHost::Init,
125 this, make_scoped_refptr(context_wrapper)));
126 return;
129 context_wrapper_ = context_wrapper;
130 if (!GetContext())
131 return;
132 GetContext()->embedded_worker_registry()->AddChildProcessSender(
133 render_process_id_, this, message_port_message_filter_);
136 void ServiceWorkerDispatcherHost::OnFilterAdded(IPC::Sender* sender) {
137 TRACE_EVENT0("ServiceWorker",
138 "ServiceWorkerDispatcherHost::OnFilterAdded");
139 channel_ready_ = true;
140 std::vector<IPC::Message*> messages;
141 pending_messages_.release(&messages);
142 for (size_t i = 0; i < messages.size(); ++i) {
143 BrowserMessageFilter::Send(messages[i]);
147 void ServiceWorkerDispatcherHost::OnFilterRemoved() {
148 // Don't wait until the destructor to teardown since a new dispatcher host
149 // for this process might be created before then.
150 if (GetContext()) {
151 GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
152 GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
153 render_process_id_);
155 context_wrapper_ = nullptr;
156 channel_ready_ = false;
159 void ServiceWorkerDispatcherHost::OnDestruct() const {
160 BrowserThread::DeleteOnIOThread::Destruct(this);
163 bool ServiceWorkerDispatcherHost::OnMessageReceived(
164 const IPC::Message& message) {
165 bool handled = true;
166 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcherHost, message)
167 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_RegisterServiceWorker,
168 OnRegisterServiceWorker)
169 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_UpdateServiceWorker,
170 OnUpdateServiceWorker)
171 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_UnregisterServiceWorker,
172 OnUnregisterServiceWorker)
173 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistration,
174 OnGetRegistration)
175 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistrations,
176 OnGetRegistrations)
177 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistrationForReady,
178 OnGetRegistrationForReady)
179 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderCreated,
180 OnProviderCreated)
181 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed,
182 OnProviderDestroyed)
183 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetVersionId,
184 OnSetHostedVersionId)
185 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToWorker,
186 OnPostMessageToWorker)
187 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerReadyForInspection,
188 OnWorkerReadyForInspection)
189 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoaded,
190 OnWorkerScriptLoaded)
191 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoadFailed,
192 OnWorkerScriptLoadFailed)
193 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptEvaluated,
194 OnWorkerScriptEvaluated)
195 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted,
196 OnWorkerStarted)
197 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped,
198 OnWorkerStopped)
199 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportException,
200 OnReportException)
201 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportConsoleMessage,
202 OnReportConsoleMessage)
203 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount,
204 OnIncrementServiceWorkerRefCount)
205 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount,
206 OnDecrementServiceWorkerRefCount)
207 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementRegistrationRefCount,
208 OnIncrementRegistrationRefCount)
209 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
210 OnDecrementRegistrationRefCount)
211 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_TerminateWorker, OnTerminateWorker)
212 IPC_MESSAGE_UNHANDLED(handled = false)
213 IPC_END_MESSAGE_MAP()
215 if (!handled && GetContext()) {
216 handled = GetContext()->embedded_worker_registry()->OnMessageReceived(
217 message, render_process_id_);
218 if (!handled)
219 bad_message::ReceivedBadMessage(this, bad_message::SWDH_NOT_HANDLED);
222 return handled;
225 bool ServiceWorkerDispatcherHost::Send(IPC::Message* message) {
226 if (channel_ready_) {
227 BrowserMessageFilter::Send(message);
228 // Don't bother passing through Send()'s result: it's not reliable.
229 return true;
232 pending_messages_.push_back(message);
233 return true;
236 void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle(
237 scoped_ptr<ServiceWorkerHandle> handle) {
238 int handle_id = handle->handle_id();
239 handles_.AddWithID(handle.release(), handle_id);
242 void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationHandle(
243 scoped_ptr<ServiceWorkerRegistrationHandle> handle) {
244 int handle_id = handle->handle_id();
245 registration_handles_.AddWithID(handle.release(), handle_id);
248 ServiceWorkerHandle* ServiceWorkerDispatcherHost::FindServiceWorkerHandle(
249 int provider_id,
250 int64 version_id) {
251 for (IDMap<ServiceWorkerHandle, IDMapOwnPointer>::iterator iter(&handles_);
252 !iter.IsAtEnd(); iter.Advance()) {
253 ServiceWorkerHandle* handle = iter.GetCurrentValue();
254 DCHECK(handle);
255 DCHECK(handle->version());
256 if (handle->provider_id() == provider_id &&
257 handle->version()->version_id() == version_id) {
258 return handle;
261 return NULL;
264 ServiceWorkerRegistrationHandle*
265 ServiceWorkerDispatcherHost::GetOrCreateRegistrationHandle(
266 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
267 ServiceWorkerRegistration* registration) {
268 DCHECK(provider_host);
269 ServiceWorkerRegistrationHandle* handle =
270 FindRegistrationHandle(provider_host->provider_id(), registration->id());
271 if (handle) {
272 handle->IncrementRefCount();
273 return handle;
276 scoped_ptr<ServiceWorkerRegistrationHandle> new_handle(
277 new ServiceWorkerRegistrationHandle(
278 GetContext()->AsWeakPtr(), provider_host, registration));
279 handle = new_handle.get();
280 RegisterServiceWorkerRegistrationHandle(new_handle.Pass());
281 return handle;
284 void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
285 int thread_id,
286 int request_id,
287 int provider_id,
288 const GURL& pattern,
289 const GURL& script_url) {
290 TRACE_EVENT0("ServiceWorker",
291 "ServiceWorkerDispatcherHost::OnRegisterServiceWorker");
292 if (!GetContext()) {
293 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
294 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
295 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
296 base::ASCIIToUTF16(kShutdownErrorMessage)));
297 return;
299 if (!pattern.is_valid() || !script_url.is_valid()) {
300 bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_BAD_URL);
301 return;
304 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
305 render_process_id_, provider_id);
306 if (!provider_host) {
307 bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_NO_HOST);
308 return;
310 if (!provider_host->IsContextAlive()) {
311 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
312 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
313 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
314 base::ASCIIToUTF16(kShutdownErrorMessage)));
315 return;
318 // TODO(ksakamoto): Currently, document_url is empty if the document is in an
319 // IFRAME using frame.contentDocument.write(...). We can remove this check
320 // once crbug.com/439697 is fixed.
321 if (provider_host->document_url().is_empty()) {
322 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
323 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
324 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
325 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
326 return;
329 if (!CanRegisterServiceWorker(
330 provider_host->document_url(), pattern, script_url)) {
331 bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_CANNOT);
332 return;
335 std::string error_message;
336 if (ServiceWorkerUtils::ContainsDisallowedCharacter(pattern, script_url,
337 &error_message)) {
338 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
339 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
340 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
341 base::UTF8ToUTF16(error_message)));
342 return;
345 if (!GetContentClient()->browser()->AllowServiceWorker(
346 pattern, provider_host->topmost_frame_url(), resource_context_,
347 render_process_id_, provider_host->frame_id())) {
348 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
349 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
350 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
351 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
352 return;
355 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
356 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
357 request_id,
358 "Pattern", pattern.spec(),
359 "Script URL", script_url.spec());
360 GetContext()->RegisterServiceWorker(
361 pattern,
362 script_url,
363 provider_host,
364 base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete,
365 this,
366 thread_id,
367 provider_id,
368 request_id));
371 void ServiceWorkerDispatcherHost::OnUpdateServiceWorker(int provider_id,
372 int64 registration_id) {
373 TRACE_EVENT0("ServiceWorker",
374 "ServiceWorkerDispatcherHost::OnUpdateServiceWorker");
375 if (!GetContext())
376 return;
378 ServiceWorkerProviderHost* provider_host =
379 GetContext()->GetProviderHost(render_process_id_, provider_id);
380 if (!provider_host) {
381 bad_message::ReceivedBadMessage(this, bad_message::SWDH_UPDATE_NO_HOST);
382 return;
384 if (!provider_host->IsContextAlive())
385 return;
387 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
388 if (provider_host->document_url().is_empty())
389 return;
391 ServiceWorkerRegistration* registration =
392 GetContext()->GetLiveRegistration(registration_id);
393 if (!registration) {
394 // |registration| must be alive because a renderer retains a registration
395 // reference at this point.
396 bad_message::ReceivedBadMessage(
397 this, bad_message::SWDH_UPDATE_BAD_REGISTRATION_ID);
398 return;
401 if (!CanUpdateServiceWorker(provider_host->document_url(),
402 registration->pattern())) {
403 bad_message::ReceivedBadMessage(this, bad_message::SWDH_UPDATE_CANNOT);
404 return;
407 if (!GetContentClient()->browser()->AllowServiceWorker(
408 registration->pattern(), provider_host->topmost_frame_url(),
409 resource_context_, render_process_id_, provider_host->frame_id())) {
410 return;
413 if (!registration->GetNewestVersion()) {
414 // This can happen if update() is called during initial script evaluation.
415 // Abort the following steps according to the spec.
416 return;
419 // The spec says, "update() pings the server for an updated version of this
420 // script without consulting caches", so set |force_bypass_cache| to true.
421 GetContext()->UpdateServiceWorker(registration,
422 true /* force_bypass_cache */);
425 void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
426 int thread_id,
427 int request_id,
428 int provider_id,
429 int64 registration_id) {
430 TRACE_EVENT0("ServiceWorker",
431 "ServiceWorkerDispatcherHost::OnUnregisterServiceWorker");
432 if (!GetContext()) {
433 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
434 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
435 base::ASCIIToUTF16(kShutdownErrorMessage)));
436 return;
439 ServiceWorkerProviderHost* provider_host =
440 GetContext()->GetProviderHost(render_process_id_, provider_id);
441 if (!provider_host) {
442 bad_message::ReceivedBadMessage(this, bad_message::SWDH_UNREGISTER_NO_HOST);
443 return;
445 if (!provider_host->IsContextAlive()) {
446 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
447 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
448 base::ASCIIToUTF16(kShutdownErrorMessage)));
449 return;
452 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
453 if (provider_host->document_url().is_empty()) {
454 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
455 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
456 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
457 return;
460 ServiceWorkerRegistration* registration =
461 GetContext()->GetLiveRegistration(registration_id);
462 if (!registration) {
463 // |registration| must be alive because a renderer retains a registration
464 // reference at this point.
465 bad_message::ReceivedBadMessage(
466 this, bad_message::SWDH_UNREGISTER_BAD_REGISTRATION_ID);
467 return;
470 if (!CanUnregisterServiceWorker(provider_host->document_url(),
471 registration->pattern())) {
472 bad_message::ReceivedBadMessage(this, bad_message::SWDH_UNREGISTER_CANNOT);
473 return;
476 if (!GetContentClient()->browser()->AllowServiceWorker(
477 registration->pattern(), provider_host->topmost_frame_url(),
478 resource_context_, render_process_id_, provider_host->frame_id())) {
479 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
480 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
481 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
482 return;
485 TRACE_EVENT_ASYNC_BEGIN1(
486 "ServiceWorker", "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
487 request_id, "Pattern", registration->pattern().spec());
488 GetContext()->UnregisterServiceWorker(
489 registration->pattern(),
490 base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete, this,
491 thread_id, request_id));
494 void ServiceWorkerDispatcherHost::OnGetRegistration(
495 int thread_id,
496 int request_id,
497 int provider_id,
498 const GURL& document_url) {
499 TRACE_EVENT0("ServiceWorker",
500 "ServiceWorkerDispatcherHost::OnGetRegistration");
502 DCHECK_CURRENTLY_ON(BrowserThread::IO);
504 if (!GetContext()) {
505 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
506 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
507 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
508 base::ASCIIToUTF16(kShutdownErrorMessage)));
509 return;
511 if (!document_url.is_valid()) {
512 bad_message::ReceivedBadMessage(this,
513 bad_message::SWDH_GET_REGISTRATION_BAD_URL);
514 return;
517 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
518 render_process_id_, provider_id);
519 if (!provider_host) {
520 bad_message::ReceivedBadMessage(this,
521 bad_message::SWDH_GET_REGISTRATION_NO_HOST);
522 return;
524 if (!provider_host->IsContextAlive()) {
525 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
526 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
527 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
528 base::ASCIIToUTF16(kShutdownErrorMessage)));
529 return;
532 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
533 if (provider_host->document_url().is_empty()) {
534 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
535 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
536 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
537 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
538 return;
541 if (!CanGetRegistration(provider_host->document_url(), document_url)) {
542 bad_message::ReceivedBadMessage(this,
543 bad_message::SWDH_GET_REGISTRATION_CANNOT);
544 return;
547 if (!GetContentClient()->browser()->AllowServiceWorker(
548 provider_host->document_url(), provider_host->topmost_frame_url(),
549 resource_context_, render_process_id_, provider_host->frame_id())) {
550 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
551 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
552 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
553 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
554 return;
557 if (GetContext()->storage()->IsDisabled()) {
558 SendGetRegistrationError(thread_id, request_id, SERVICE_WORKER_ERROR_ABORT);
559 return;
562 TRACE_EVENT_ASYNC_BEGIN1(
563 "ServiceWorker",
564 "ServiceWorkerDispatcherHost::GetRegistration",
565 request_id,
566 "Document URL", document_url.spec());
568 GetContext()->storage()->FindRegistrationForDocument(
569 document_url,
570 base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationComplete,
571 this,
572 thread_id,
573 provider_id,
574 request_id));
577 void ServiceWorkerDispatcherHost::OnGetRegistrations(int thread_id,
578 int request_id,
579 int provider_id) {
580 DCHECK_CURRENTLY_ON(BrowserThread::IO);
582 if (!GetContext()) {
583 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
584 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
585 base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
586 base::ASCIIToUTF16(kShutdownErrorMessage)));
587 return;
590 ServiceWorkerProviderHost* provider_host =
591 GetContext()->GetProviderHost(render_process_id_, provider_id);
592 if (!provider_host) {
593 bad_message::ReceivedBadMessage(
594 this, bad_message::SWDH_GET_REGISTRATIONS_NO_HOST);
595 return;
597 if (!provider_host->IsContextAlive()) {
598 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
599 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
600 base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
601 base::ASCIIToUTF16(kShutdownErrorMessage)));
602 return;
605 // TODO(jungkees): This check can be removed once crbug.com/439697 is fixed.
606 if (provider_host->document_url().is_empty()) {
607 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
608 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
609 base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
610 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
611 return;
614 if (!OriginCanAccessServiceWorkers(provider_host->document_url())) {
615 bad_message::ReceivedBadMessage(
616 this, bad_message::SWDH_GET_REGISTRATIONS_INVALID_ORIGIN);
617 return;
620 if (!GetContentClient()->browser()->AllowServiceWorker(
621 provider_host->document_url(), provider_host->topmost_frame_url(),
622 resource_context_, render_process_id_, provider_host->frame_id())) {
623 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
624 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
625 base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
626 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
627 return;
630 if (GetContext()->storage()->IsDisabled()) {
631 SendGetRegistrationsError(thread_id, request_id,
632 SERVICE_WORKER_ERROR_ABORT);
633 return;
636 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
637 "ServiceWorkerDispatcherHost::GetRegistrations",
638 request_id);
640 GetContext()->storage()->GetRegistrationsForOrigin(
641 provider_host->document_url().GetOrigin(),
642 base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationsComplete, this,
643 thread_id, provider_id, request_id));
646 void ServiceWorkerDispatcherHost::OnGetRegistrationForReady(
647 int thread_id,
648 int request_id,
649 int provider_id) {
650 TRACE_EVENT0("ServiceWorker",
651 "ServiceWorkerDispatcherHost::OnGetRegistrationForReady");
652 if (!GetContext())
653 return;
654 ServiceWorkerProviderHost* provider_host =
655 GetContext()->GetProviderHost(render_process_id_, provider_id);
656 if (!provider_host) {
657 bad_message::ReceivedBadMessage(
658 this, bad_message::SWDH_GET_REGISTRATION_FOR_READY_NO_HOST);
659 return;
661 if (!provider_host->IsContextAlive())
662 return;
664 TRACE_EVENT_ASYNC_BEGIN0(
665 "ServiceWorker",
666 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
667 request_id);
669 if (!provider_host->GetRegistrationForReady(base::Bind(
670 &ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete,
671 this, thread_id, request_id, provider_host->AsWeakPtr()))) {
672 bad_message::ReceivedBadMessage(
673 this, bad_message::SWDH_GET_REGISTRATION_FOR_READY_ALREADY_IN_PROGRESS);
677 void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
678 int handle_id,
679 const base::string16& message,
680 const std::vector<TransferredMessagePort>& sent_message_ports) {
681 TRACE_EVENT0("ServiceWorker",
682 "ServiceWorkerDispatcherHost::OnPostMessageToWorker");
683 if (!GetContext())
684 return;
686 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
687 if (!handle) {
688 bad_message::ReceivedBadMessage(this, bad_message::SWDH_POST_MESSAGE);
689 return;
692 handle->version()->DispatchMessageEvent(
693 message, sent_message_ports,
694 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
697 void ServiceWorkerDispatcherHost::OnProviderCreated(
698 int provider_id,
699 int route_id,
700 ServiceWorkerProviderType provider_type) {
701 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
702 tracked_objects::ScopedTracker tracking_profile(
703 FROM_HERE_WITH_EXPLICIT_FUNCTION(
704 "477117 ServiceWorkerDispatcherHost::OnProviderCreated"));
705 TRACE_EVENT0("ServiceWorker",
706 "ServiceWorkerDispatcherHost::OnProviderCreated");
707 if (!GetContext())
708 return;
709 if (GetContext()->GetProviderHost(render_process_id_, provider_id)) {
710 bad_message::ReceivedBadMessage(this,
711 bad_message::SWDH_PROVIDER_CREATED_NO_HOST);
712 return;
714 scoped_ptr<ServiceWorkerProviderHost> provider_host(
715 new ServiceWorkerProviderHost(render_process_id_, route_id, provider_id,
716 provider_type, GetContext()->AsWeakPtr(),
717 this));
718 GetContext()->AddProviderHost(provider_host.Pass());
721 void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
722 TRACE_EVENT0("ServiceWorker",
723 "ServiceWorkerDispatcherHost::OnProviderDestroyed");
724 if (!GetContext())
725 return;
726 if (!GetContext()->GetProviderHost(render_process_id_, provider_id)) {
727 bad_message::ReceivedBadMessage(
728 this, bad_message::SWDH_PROVIDER_DESTROYED_NO_HOST);
729 return;
731 GetContext()->RemoveProviderHost(render_process_id_, provider_id);
734 void ServiceWorkerDispatcherHost::OnSetHostedVersionId(
735 int provider_id, int64 version_id) {
736 TRACE_EVENT0("ServiceWorker",
737 "ServiceWorkerDispatcherHost::OnSetHostedVersionId");
738 if (!GetContext())
739 return;
740 ServiceWorkerProviderHost* provider_host =
741 GetContext()->GetProviderHost(render_process_id_, provider_id);
742 if (!provider_host) {
743 bad_message::ReceivedBadMessage(
744 this, bad_message::SWDH_SET_HOSTED_VERSION_NO_HOST);
745 return;
747 if (!provider_host->IsContextAlive())
748 return;
749 if (!provider_host->SetHostedVersionId(version_id))
750 bad_message::ReceivedBadMessage(this, bad_message::SWDH_SET_HOSTED_VERSION);
752 ServiceWorkerVersion* version = GetContext()->GetLiveVersion(version_id);
753 if (!version)
754 return;
756 // Retrieve the registration associated with |version|. The registration
757 // must be alive because the version keeps it during starting worker.
758 ServiceWorkerRegistration* registration =
759 GetContext()->GetLiveRegistration(version->registration_id());
760 DCHECK(registration);
761 // TODO(ksakamoto): This is a quick fix for crbug.com/459916.
762 if (!registration)
763 return;
765 // Set the document URL to the script url in order to allow
766 // register/unregister/getRegistration on ServiceWorkerGlobalScope.
767 provider_host->SetDocumentUrl(version->script_url());
769 ServiceWorkerRegistrationObjectInfo info;
770 ServiceWorkerVersionAttributes attrs;
771 GetRegistrationObjectInfoAndVersionAttributes(
772 provider_host->AsWeakPtr(), registration, &info, &attrs);
774 Send(new ServiceWorkerMsg_AssociateRegistrationWithServiceWorker(
775 kDocumentMainThreadId, provider_id, info, attrs));
778 ServiceWorkerRegistrationHandle*
779 ServiceWorkerDispatcherHost::FindRegistrationHandle(int provider_id,
780 int64 registration_id) {
781 for (IDMap<ServiceWorkerRegistrationHandle, IDMapOwnPointer>::iterator
782 iter(&registration_handles_);
783 !iter.IsAtEnd();
784 iter.Advance()) {
785 ServiceWorkerRegistrationHandle* handle = iter.GetCurrentValue();
786 DCHECK(handle);
787 DCHECK(handle->registration());
788 if (handle->provider_id() == provider_id &&
789 handle->registration()->id() == registration_id) {
790 return handle;
793 return NULL;
796 void ServiceWorkerDispatcherHost::GetRegistrationObjectInfoAndVersionAttributes(
797 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
798 ServiceWorkerRegistration* registration,
799 ServiceWorkerRegistrationObjectInfo* info,
800 ServiceWorkerVersionAttributes* attrs) {
801 ServiceWorkerRegistrationHandle* handle =
802 GetOrCreateRegistrationHandle(provider_host, registration);
803 *info = handle->GetObjectInfo();
805 attrs->installing = provider_host->GetOrCreateServiceWorkerHandle(
806 registration->installing_version());
807 attrs->waiting = provider_host->GetOrCreateServiceWorkerHandle(
808 registration->waiting_version());
809 attrs->active = provider_host->GetOrCreateServiceWorkerHandle(
810 registration->active_version());
813 void ServiceWorkerDispatcherHost::RegistrationComplete(
814 int thread_id,
815 int provider_id,
816 int request_id,
817 ServiceWorkerStatusCode status,
818 const std::string& status_message,
819 int64 registration_id) {
820 if (!GetContext())
821 return;
823 ServiceWorkerProviderHost* provider_host =
824 GetContext()->GetProviderHost(render_process_id_, provider_id);
825 if (!provider_host)
826 return; // The provider has already been destroyed.
828 if (status != SERVICE_WORKER_OK) {
829 SendRegistrationError(thread_id, request_id, status, status_message);
830 return;
833 ServiceWorkerRegistration* registration =
834 GetContext()->GetLiveRegistration(registration_id);
835 DCHECK(registration);
837 ServiceWorkerRegistrationObjectInfo info;
838 ServiceWorkerVersionAttributes attrs;
839 GetRegistrationObjectInfoAndVersionAttributes(
840 provider_host->AsWeakPtr(), registration, &info, &attrs);
842 Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
843 thread_id, request_id, info, attrs));
844 TRACE_EVENT_ASYNC_END1("ServiceWorker",
845 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
846 request_id,
847 "Registration ID",
848 registration_id);
851 void ServiceWorkerDispatcherHost::OnWorkerReadyForInspection(
852 int embedded_worker_id) {
853 TRACE_EVENT0("ServiceWorker",
854 "ServiceWorkerDispatcherHost::OnWorkerReadyForInspection");
855 if (!GetContext())
856 return;
857 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
858 if (!registry->CanHandle(embedded_worker_id))
859 return;
860 registry->OnWorkerReadyForInspection(render_process_id_, embedded_worker_id);
863 void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(
864 int embedded_worker_id,
865 int thread_id,
866 int provider_id) {
867 TRACE_EVENT0("ServiceWorker",
868 "ServiceWorkerDispatcherHost::OnWorkerScriptLoaded");
869 if (!GetContext())
870 return;
872 ServiceWorkerProviderHost* provider_host =
873 GetContext()->GetProviderHost(render_process_id_, provider_id);
874 if (!provider_host) {
875 bad_message::ReceivedBadMessage(
876 this, bad_message::SWDH_WORKER_SCRIPT_LOAD_NO_HOST);
877 return;
880 provider_host->SetReadyToSendMessagesToWorker(thread_id);
882 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
883 if (!registry->CanHandle(embedded_worker_id))
884 return;
885 registry->OnWorkerScriptLoaded(
886 render_process_id_, thread_id, embedded_worker_id);
889 void ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed(
890 int embedded_worker_id) {
891 TRACE_EVENT0("ServiceWorker",
892 "ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed");
893 if (!GetContext())
894 return;
895 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
896 if (!registry->CanHandle(embedded_worker_id))
897 return;
898 registry->OnWorkerScriptLoadFailed(render_process_id_, embedded_worker_id);
901 void ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated(
902 int embedded_worker_id,
903 bool success) {
904 TRACE_EVENT0("ServiceWorker",
905 "ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated");
906 if (!GetContext())
907 return;
908 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
909 if (!registry->CanHandle(embedded_worker_id))
910 return;
911 registry->OnWorkerScriptEvaluated(
912 render_process_id_, embedded_worker_id, success);
915 void ServiceWorkerDispatcherHost::OnWorkerStarted(int embedded_worker_id) {
916 TRACE_EVENT0("ServiceWorker",
917 "ServiceWorkerDispatcherHost::OnWorkerStarted");
918 if (!GetContext())
919 return;
920 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
921 if (!registry->CanHandle(embedded_worker_id))
922 return;
923 registry->OnWorkerStarted(render_process_id_, embedded_worker_id);
926 void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) {
927 TRACE_EVENT0("ServiceWorker",
928 "ServiceWorkerDispatcherHost::OnWorkerStopped");
929 if (!GetContext())
930 return;
931 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
932 if (!registry->CanHandle(embedded_worker_id))
933 return;
934 registry->OnWorkerStopped(render_process_id_, embedded_worker_id);
937 void ServiceWorkerDispatcherHost::OnReportException(
938 int embedded_worker_id,
939 const base::string16& error_message,
940 int line_number,
941 int column_number,
942 const GURL& source_url) {
943 TRACE_EVENT0("ServiceWorker",
944 "ServiceWorkerDispatcherHost::OnReportException");
945 if (!GetContext())
946 return;
947 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
948 if (!registry->CanHandle(embedded_worker_id))
949 return;
950 registry->OnReportException(embedded_worker_id,
951 error_message,
952 line_number,
953 column_number,
954 source_url);
957 void ServiceWorkerDispatcherHost::OnReportConsoleMessage(
958 int embedded_worker_id,
959 const EmbeddedWorkerHostMsg_ReportConsoleMessage_Params& params) {
960 TRACE_EVENT0("ServiceWorker",
961 "ServiceWorkerDispatcherHost::OnReportConsoleMessage");
962 if (!GetContext())
963 return;
964 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
965 if (!registry->CanHandle(embedded_worker_id))
966 return;
967 registry->OnReportConsoleMessage(embedded_worker_id,
968 params.source_identifier,
969 params.message_level,
970 params.message,
971 params.line_number,
972 params.source_url);
975 void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
976 int handle_id) {
977 TRACE_EVENT0("ServiceWorker",
978 "ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount");
979 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
980 if (!handle) {
981 bad_message::ReceivedBadMessage(
982 this, bad_message::SWDH_INCREMENT_WORKER_BAD_HANDLE);
983 return;
985 handle->IncrementRefCount();
988 void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
989 int handle_id) {
990 TRACE_EVENT0("ServiceWorker",
991 "ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount");
992 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
993 if (!handle) {
994 bad_message::ReceivedBadMessage(
995 this, bad_message::SWDH_DECREMENT_WORKER_BAD_HANDLE);
996 return;
998 handle->DecrementRefCount();
999 if (handle->HasNoRefCount())
1000 handles_.Remove(handle_id);
1003 void ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount(
1004 int registration_handle_id) {
1005 TRACE_EVENT0("ServiceWorker",
1006 "ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount");
1007 ServiceWorkerRegistrationHandle* handle =
1008 registration_handles_.Lookup(registration_handle_id);
1009 if (!handle) {
1010 bad_message::ReceivedBadMessage(
1011 this, bad_message::SWDH_INCREMENT_REGISTRATION_BAD_HANDLE);
1012 return;
1014 handle->IncrementRefCount();
1017 void ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount(
1018 int registration_handle_id) {
1019 TRACE_EVENT0("ServiceWorker",
1020 "ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount");
1021 ServiceWorkerRegistrationHandle* handle =
1022 registration_handles_.Lookup(registration_handle_id);
1023 if (!handle) {
1024 bad_message::ReceivedBadMessage(
1025 this, bad_message::SWDH_DECREMENT_REGISTRATION_BAD_HANDLE);
1026 return;
1028 handle->DecrementRefCount();
1029 if (handle->HasNoRefCount())
1030 registration_handles_.Remove(registration_handle_id);
1033 void ServiceWorkerDispatcherHost::UnregistrationComplete(
1034 int thread_id,
1035 int request_id,
1036 ServiceWorkerStatusCode status) {
1037 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
1038 SendUnregistrationError(thread_id, request_id, status);
1039 return;
1041 const bool is_success = (status == SERVICE_WORKER_OK);
1042 Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id,
1043 request_id,
1044 is_success));
1045 TRACE_EVENT_ASYNC_END1(
1046 "ServiceWorker",
1047 "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
1048 request_id,
1049 "Status", status);
1052 void ServiceWorkerDispatcherHost::GetRegistrationComplete(
1053 int thread_id,
1054 int provider_id,
1055 int request_id,
1056 ServiceWorkerStatusCode status,
1057 const scoped_refptr<ServiceWorkerRegistration>& registration) {
1058 TRACE_EVENT_ASYNC_END1("ServiceWorker",
1059 "ServiceWorkerDispatcherHost::GetRegistration",
1060 request_id,
1061 "Registration ID",
1062 registration.get() ? registration->id()
1063 : kInvalidServiceWorkerRegistrationId);
1065 if (!GetContext())
1066 return;
1068 ServiceWorkerProviderHost* provider_host =
1069 GetContext()->GetProviderHost(render_process_id_, provider_id);
1070 if (!provider_host)
1071 return; // The provider has already been destroyed.
1073 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
1074 SendGetRegistrationError(thread_id, request_id, status);
1075 return;
1078 ServiceWorkerRegistrationObjectInfo info;
1079 ServiceWorkerVersionAttributes attrs;
1080 if (status == SERVICE_WORKER_OK) {
1081 DCHECK(registration.get());
1082 if (!registration->is_uninstalling()) {
1083 GetRegistrationObjectInfoAndVersionAttributes(
1084 provider_host->AsWeakPtr(), registration.get(), &info, &attrs);
1088 Send(new ServiceWorkerMsg_DidGetRegistration(
1089 thread_id, request_id, info, attrs));
1092 void ServiceWorkerDispatcherHost::GetRegistrationsComplete(
1093 int thread_id,
1094 int provider_id,
1095 int request_id,
1096 const std::vector<scoped_refptr<ServiceWorkerRegistration>>&
1097 registrations) {
1098 TRACE_EVENT_ASYNC_END0("ServiceWorker",
1099 "ServiceWorkerDispatcherHost::GetRegistrations",
1100 request_id);
1101 if (!GetContext())
1102 return;
1104 ServiceWorkerProviderHost* provider_host =
1105 GetContext()->GetProviderHost(render_process_id_, provider_id);
1106 if (!provider_host)
1107 return; // The provider has already been destroyed.
1109 std::vector<ServiceWorkerRegistrationObjectInfo> object_infos;
1110 std::vector<ServiceWorkerVersionAttributes> version_attrs;
1112 for (const auto& registration : registrations) {
1113 DCHECK(registration.get());
1114 if (!registration->is_uninstalling()) {
1115 ServiceWorkerRegistrationObjectInfo object_info;
1116 ServiceWorkerVersionAttributes version_attr;
1117 GetRegistrationObjectInfoAndVersionAttributes(
1118 provider_host->AsWeakPtr(), registration.get(), &object_info,
1119 &version_attr);
1120 object_infos.push_back(object_info);
1121 version_attrs.push_back(version_attr);
1125 Send(new ServiceWorkerMsg_DidGetRegistrations(thread_id, request_id,
1126 object_infos, version_attrs));
1129 void ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete(
1130 int thread_id,
1131 int request_id,
1132 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
1133 ServiceWorkerRegistration* registration) {
1134 DCHECK(registration);
1135 TRACE_EVENT_ASYNC_END1("ServiceWorker",
1136 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
1137 request_id,
1138 "Registration ID",
1139 registration ? registration->id()
1140 : kInvalidServiceWorkerRegistrationId);
1142 if (!GetContext())
1143 return;
1145 ServiceWorkerRegistrationObjectInfo info;
1146 ServiceWorkerVersionAttributes attrs;
1147 GetRegistrationObjectInfoAndVersionAttributes(
1148 provider_host, registration, &info, &attrs);
1149 Send(new ServiceWorkerMsg_DidGetRegistrationForReady(
1150 thread_id, request_id, info, attrs));
1153 void ServiceWorkerDispatcherHost::SendRegistrationError(
1154 int thread_id,
1155 int request_id,
1156 ServiceWorkerStatusCode status,
1157 const std::string& status_message) {
1158 base::string16 error_message;
1159 blink::WebServiceWorkerError::ErrorType error_type;
1160 GetServiceWorkerRegistrationStatusResponse(status, status_message,
1161 &error_type, &error_message);
1162 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
1163 thread_id, request_id, error_type,
1164 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) + error_message));
1167 void ServiceWorkerDispatcherHost::SendUnregistrationError(
1168 int thread_id,
1169 int request_id,
1170 ServiceWorkerStatusCode status) {
1171 base::string16 error_message;
1172 blink::WebServiceWorkerError::ErrorType error_type;
1173 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
1174 &error_message);
1175 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
1176 thread_id, request_id, error_type,
1177 base::ASCIIToUTF16(kServiceWorkerUnregisterErrorPrefix) + error_message));
1180 void ServiceWorkerDispatcherHost::SendGetRegistrationError(
1181 int thread_id,
1182 int request_id,
1183 ServiceWorkerStatusCode status) {
1184 base::string16 error_message;
1185 blink::WebServiceWorkerError::ErrorType error_type;
1186 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
1187 &error_message);
1188 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
1189 thread_id, request_id, error_type,
1190 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
1191 error_message));
1194 void ServiceWorkerDispatcherHost::SendGetRegistrationsError(
1195 int thread_id,
1196 int request_id,
1197 ServiceWorkerStatusCode status) {
1198 base::string16 error_message;
1199 blink::WebServiceWorkerError::ErrorType error_type;
1200 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
1201 &error_message);
1202 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
1203 thread_id, request_id, error_type,
1204 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
1205 error_message));
1208 ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
1209 if (!context_wrapper_.get())
1210 return nullptr;
1211 return context_wrapper_->context();
1214 void ServiceWorkerDispatcherHost::OnTerminateWorker(int handle_id) {
1215 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
1216 if (!handle) {
1217 bad_message::ReceivedBadMessage(this,
1218 bad_message::SWDH_TERMINATE_BAD_HANDLE);
1219 return;
1221 handle->version()->StopWorker(
1222 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
1225 } // namespace content