Simplify ChildProcessLauncher
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_dispatcher_host.cc
blob9629877d38362a0b01cc75c1354bb5905b602b0b
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/strings/utf_string_conversions.h"
9 #include "base/trace_event/trace_event.h"
10 #include "content/browser/message_port_message_filter.h"
11 #include "content/browser/message_port_service.h"
12 #include "content/browser/service_worker/embedded_worker_registry.h"
13 #include "content/browser/service_worker/service_worker_context_core.h"
14 #include "content/browser/service_worker/service_worker_context_wrapper.h"
15 #include "content/browser/service_worker/service_worker_handle.h"
16 #include "content/browser/service_worker/service_worker_registration.h"
17 #include "content/browser/service_worker/service_worker_registration_handle.h"
18 #include "content/browser/service_worker/service_worker_utils.h"
19 #include "content/common/service_worker/embedded_worker_messages.h"
20 #include "content/common/service_worker/service_worker_messages.h"
21 #include "content/common/service_worker/service_worker_types.h"
22 #include "content/public/browser/content_browser_client.h"
23 #include "content/public/common/content_client.h"
24 #include "ipc/ipc_message_macros.h"
25 #include "net/base/net_util.h"
26 #include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
27 #include "url/gurl.h"
29 using blink::WebServiceWorkerError;
31 namespace content {
33 namespace {
35 const char kNoDocumentURLErrorMessage[] =
36 "No URL is associated with the caller's document.";
37 const char kShutdownErrorMessage[] =
38 "The Service Worker system has shutdown.";
39 const char kUserDeniedPermissionMessage[] =
40 "The user denied permission to use Service Worker.";
42 const uint32 kFilteredMessageClasses[] = {
43 ServiceWorkerMsgStart,
44 EmbeddedWorkerMsgStart,
47 bool AllOriginsMatch(const GURL& url_a, const GURL& url_b, const GURL& url_c) {
48 return url_a.GetOrigin() == url_b.GetOrigin() &&
49 url_a.GetOrigin() == url_c.GetOrigin();
52 // TODO(dominicc): When crbug.com/362214 is fixed use that to be
53 // consistent with Blink's
54 // SecurityOrigin::canAccessFeatureRequiringSecureOrigin.
55 bool OriginCanAccessServiceWorkers(const GURL& url) {
56 return url.SchemeIsHTTPOrHTTPS() &&
57 (url.SchemeIsSecure() || net::IsLocalhost(url.host()));
60 bool CanRegisterServiceWorker(const GURL& document_url,
61 const GURL& pattern,
62 const GURL& script_url) {
63 DCHECK(document_url.is_valid());
64 DCHECK(pattern.is_valid());
65 DCHECK(script_url.is_valid());
66 return AllOriginsMatch(document_url, pattern, script_url) &&
67 OriginCanAccessServiceWorkers(document_url) &&
68 OriginCanAccessServiceWorkers(pattern) &&
69 OriginCanAccessServiceWorkers(script_url);
72 bool CanUnregisterServiceWorker(const GURL& document_url,
73 const GURL& pattern) {
74 DCHECK(document_url.is_valid());
75 DCHECK(pattern.is_valid());
76 return document_url.GetOrigin() == pattern.GetOrigin() &&
77 OriginCanAccessServiceWorkers(document_url) &&
78 OriginCanAccessServiceWorkers(pattern);
81 bool CanGetRegistration(const GURL& document_url,
82 const GURL& given_document_url) {
83 DCHECK(document_url.is_valid());
84 DCHECK(given_document_url.is_valid());
85 return document_url.GetOrigin() == given_document_url.GetOrigin() &&
86 OriginCanAccessServiceWorkers(document_url) &&
87 OriginCanAccessServiceWorkers(given_document_url);
90 } // namespace
92 ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
93 int render_process_id,
94 MessagePortMessageFilter* message_port_message_filter,
95 ResourceContext* resource_context)
96 : BrowserMessageFilter(kFilteredMessageClasses,
97 arraysize(kFilteredMessageClasses)),
98 render_process_id_(render_process_id),
99 message_port_message_filter_(message_port_message_filter),
100 resource_context_(resource_context),
101 channel_ready_(false) {
104 ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
105 if (GetContext()) {
106 GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
107 GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
108 render_process_id_);
112 void ServiceWorkerDispatcherHost::Init(
113 ServiceWorkerContextWrapper* context_wrapper) {
114 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
115 BrowserThread::PostTask(
116 BrowserThread::IO, FROM_HERE,
117 base::Bind(&ServiceWorkerDispatcherHost::Init,
118 this, make_scoped_refptr(context_wrapper)));
119 return;
122 context_wrapper_ = context_wrapper;
123 if (!GetContext())
124 return;
125 GetContext()->embedded_worker_registry()->AddChildProcessSender(
126 render_process_id_, this, message_port_message_filter_);
129 void ServiceWorkerDispatcherHost::OnFilterAdded(IPC::Sender* sender) {
130 TRACE_EVENT0("ServiceWorker",
131 "ServiceWorkerDispatcherHost::OnFilterAdded");
132 channel_ready_ = true;
133 std::vector<IPC::Message*> messages;
134 pending_messages_.release(&messages);
135 for (size_t i = 0; i < messages.size(); ++i) {
136 BrowserMessageFilter::Send(messages[i]);
140 void ServiceWorkerDispatcherHost::OnFilterRemoved() {
141 // Don't wait until the destructor to teardown since a new dispatcher host
142 // for this process might be created before then.
143 if (GetContext()) {
144 GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
145 GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
146 render_process_id_);
148 context_wrapper_ = nullptr;
149 channel_ready_ = false;
152 void ServiceWorkerDispatcherHost::OnDestruct() const {
153 BrowserThread::DeleteOnIOThread::Destruct(this);
156 bool ServiceWorkerDispatcherHost::OnMessageReceived(
157 const IPC::Message& message) {
158 bool handled = true;
159 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcherHost, message)
160 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_RegisterServiceWorker,
161 OnRegisterServiceWorker)
162 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_UnregisterServiceWorker,
163 OnUnregisterServiceWorker)
164 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistration,
165 OnGetRegistration)
166 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistrationForReady,
167 OnGetRegistrationForReady)
168 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderCreated,
169 OnProviderCreated)
170 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed,
171 OnProviderDestroyed)
172 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetVersionId,
173 OnSetHostedVersionId)
174 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToWorker,
175 OnPostMessageToWorker)
176 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerReadyForInspection,
177 OnWorkerReadyForInspection)
178 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoaded,
179 OnWorkerScriptLoaded)
180 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoadFailed,
181 OnWorkerScriptLoadFailed)
182 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptEvaluated,
183 OnWorkerScriptEvaluated)
184 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted,
185 OnWorkerStarted)
186 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped,
187 OnWorkerStopped)
188 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_DidPauseAfterDownload,
189 OnPausedAfterDownload)
190 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportException,
191 OnReportException)
192 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportConsoleMessage,
193 OnReportConsoleMessage)
194 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount,
195 OnIncrementServiceWorkerRefCount)
196 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount,
197 OnDecrementServiceWorkerRefCount)
198 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementRegistrationRefCount,
199 OnIncrementRegistrationRefCount)
200 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
201 OnDecrementRegistrationRefCount)
202 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_TerminateWorker, OnTerminateWorker)
203 IPC_MESSAGE_UNHANDLED(handled = false)
204 IPC_END_MESSAGE_MAP()
206 if (!handled && GetContext()) {
207 handled = GetContext()->embedded_worker_registry()->OnMessageReceived(
208 message, render_process_id_);
209 if (!handled)
210 BadMessageReceived();
213 return handled;
216 bool ServiceWorkerDispatcherHost::Send(IPC::Message* message) {
217 if (channel_ready_) {
218 BrowserMessageFilter::Send(message);
219 // Don't bother passing through Send()'s result: it's not reliable.
220 return true;
223 pending_messages_.push_back(message);
224 return true;
227 void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle(
228 scoped_ptr<ServiceWorkerHandle> handle) {
229 int handle_id = handle->handle_id();
230 handles_.AddWithID(handle.release(), handle_id);
233 void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationHandle(
234 scoped_ptr<ServiceWorkerRegistrationHandle> handle) {
235 int handle_id = handle->handle_id();
236 registration_handles_.AddWithID(handle.release(), handle_id);
239 ServiceWorkerRegistrationHandle*
240 ServiceWorkerDispatcherHost::GetOrCreateRegistrationHandle(
241 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
242 ServiceWorkerRegistration* registration) {
243 DCHECK(provider_host);
244 ServiceWorkerRegistrationHandle* handle =
245 FindRegistrationHandle(provider_host->provider_id(), registration->id());
246 if (handle) {
247 handle->IncrementRefCount();
248 return handle;
251 scoped_ptr<ServiceWorkerRegistrationHandle> new_handle(
252 new ServiceWorkerRegistrationHandle(
253 GetContext()->AsWeakPtr(), provider_host, registration));
254 handle = new_handle.get();
255 RegisterServiceWorkerRegistrationHandle(new_handle.Pass());
256 return handle;
259 void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
260 int thread_id,
261 int request_id,
262 int provider_id,
263 const GURL& pattern,
264 const GURL& script_url) {
265 TRACE_EVENT0("ServiceWorker",
266 "ServiceWorkerDispatcherHost::OnRegisterServiceWorker");
267 if (!GetContext()) {
268 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
269 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
270 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
271 base::ASCIIToUTF16(kShutdownErrorMessage)));
272 return;
274 if (!pattern.is_valid() || !script_url.is_valid()) {
275 BadMessageReceived();
276 return;
279 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
280 render_process_id_, provider_id);
281 if (!provider_host) {
282 BadMessageReceived();
283 return;
285 if (!provider_host->IsContextAlive()) {
286 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
287 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
288 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
289 base::ASCIIToUTF16(kShutdownErrorMessage)));
290 return;
293 // TODO(ksakamoto): Currently, document_url is empty if the document is in an
294 // IFRAME using frame.contentDocument.write(...). We can remove this check
295 // once crbug.com/439697 is fixed.
296 if (provider_host->document_url().is_empty()) {
297 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
298 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
299 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
300 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
301 return;
304 if (!CanRegisterServiceWorker(
305 provider_host->document_url(), pattern, script_url)) {
306 BadMessageReceived();
307 return;
310 std::string error_message;
311 if (ServiceWorkerUtils::ContainsDisallowedCharacter(pattern, script_url,
312 &error_message)) {
313 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
314 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
315 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
316 base::UTF8ToUTF16(error_message)));
317 return;
320 if (!GetContentClient()->browser()->AllowServiceWorker(
321 pattern, provider_host->topmost_frame_url(), resource_context_)) {
322 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
323 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
324 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
325 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
326 return;
329 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
330 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
331 request_id,
332 "Pattern", pattern.spec(),
333 "Script URL", script_url.spec());
334 GetContext()->RegisterServiceWorker(
335 pattern,
336 script_url,
337 provider_host,
338 base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete,
339 this,
340 thread_id,
341 provider_id,
342 request_id));
345 void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
346 int thread_id,
347 int request_id,
348 int provider_id,
349 const GURL& pattern) {
350 TRACE_EVENT0("ServiceWorker",
351 "ServiceWorkerDispatcherHost::OnUnregisterServiceWorker");
352 if (!GetContext()) {
353 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
354 thread_id,
355 request_id,
356 blink::WebServiceWorkerError::ErrorTypeAbort,
357 base::ASCIIToUTF16(kShutdownErrorMessage)));
358 return;
360 if (!pattern.is_valid()) {
361 BadMessageReceived();
362 return;
365 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
366 render_process_id_, provider_id);
367 if (!provider_host) {
368 BadMessageReceived();
369 return;
371 if (!provider_host->IsContextAlive()) {
372 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
373 thread_id,
374 request_id,
375 blink::WebServiceWorkerError::ErrorTypeAbort,
376 base::ASCIIToUTF16(kShutdownErrorMessage)));
377 return;
380 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
381 if (provider_host->document_url().is_empty()) {
382 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
383 thread_id,
384 request_id,
385 WebServiceWorkerError::ErrorTypeSecurity,
386 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
387 return;
390 if (!CanUnregisterServiceWorker(provider_host->document_url(), pattern)) {
391 BadMessageReceived();
392 return;
395 if (!GetContentClient()->browser()->AllowServiceWorker(
396 pattern, provider_host->topmost_frame_url(), resource_context_)) {
397 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
398 thread_id,
399 request_id,
400 WebServiceWorkerError::ErrorTypeUnknown,
401 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
402 return;
405 TRACE_EVENT_ASYNC_BEGIN1(
406 "ServiceWorker",
407 "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
408 request_id,
409 "Pattern", pattern.spec());
410 GetContext()->UnregisterServiceWorker(
411 pattern,
412 base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete,
413 this,
414 thread_id,
415 request_id));
418 void ServiceWorkerDispatcherHost::OnGetRegistration(
419 int thread_id,
420 int request_id,
421 int provider_id,
422 const GURL& document_url) {
423 TRACE_EVENT0("ServiceWorker",
424 "ServiceWorkerDispatcherHost::OnGetRegistration");
425 if (!GetContext()) {
426 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
427 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
428 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
429 base::ASCIIToUTF16(kShutdownErrorMessage)));
430 return;
432 if (!document_url.is_valid()) {
433 BadMessageReceived();
434 return;
437 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
438 render_process_id_, provider_id);
439 if (!provider_host) {
440 BadMessageReceived();
441 return;
443 if (!provider_host->IsContextAlive()) {
444 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
445 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
446 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
447 base::ASCIIToUTF16(kShutdownErrorMessage)));
448 return;
451 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
452 if (provider_host->document_url().is_empty()) {
453 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
454 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
455 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
456 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
457 return;
460 if (!CanGetRegistration(provider_host->document_url(), document_url)) {
461 BadMessageReceived();
462 return;
465 if (!GetContentClient()->browser()->AllowServiceWorker(
466 provider_host->document_url(),
467 provider_host->topmost_frame_url(),
468 resource_context_)) {
469 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
470 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
471 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
472 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
473 return;
476 DCHECK_CURRENTLY_ON(BrowserThread::IO);
477 if (GetContext()->storage()->IsDisabled()) {
478 SendGetRegistrationError(thread_id, request_id, SERVICE_WORKER_ERROR_ABORT);
479 return;
482 TRACE_EVENT_ASYNC_BEGIN1(
483 "ServiceWorker",
484 "ServiceWorkerDispatcherHost::GetRegistration",
485 request_id,
486 "Document URL", document_url.spec());
488 GetContext()->storage()->FindRegistrationForDocument(
489 document_url,
490 base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationComplete,
491 this,
492 thread_id,
493 provider_id,
494 request_id));
497 void ServiceWorkerDispatcherHost::OnGetRegistrationForReady(
498 int thread_id,
499 int request_id,
500 int provider_id) {
501 TRACE_EVENT0("ServiceWorker",
502 "ServiceWorkerDispatcherHost::OnGetRegistrationForReady");
503 if (!GetContext())
504 return;
505 ServiceWorkerProviderHost* provider_host =
506 GetContext()->GetProviderHost(render_process_id_, provider_id);
507 if (!provider_host) {
508 BadMessageReceived();
509 return;
511 if (!provider_host->IsContextAlive())
512 return;
514 TRACE_EVENT_ASYNC_BEGIN0(
515 "ServiceWorker",
516 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
517 request_id);
519 if (!provider_host->GetRegistrationForReady(base::Bind(
520 &ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete,
521 this, thread_id, request_id, provider_host->AsWeakPtr()))) {
522 BadMessageReceived();
526 void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
527 int handle_id,
528 const base::string16& message,
529 const std::vector<TransferredMessagePort>& sent_message_ports) {
530 TRACE_EVENT0("ServiceWorker",
531 "ServiceWorkerDispatcherHost::OnPostMessageToWorker");
532 if (!GetContext())
533 return;
535 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
536 if (!handle) {
537 BadMessageReceived();
538 return;
541 handle->version()->DispatchMessageEvent(
542 message, sent_message_ports,
543 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
546 void ServiceWorkerDispatcherHost::OnProviderCreated(
547 int provider_id,
548 int render_frame_id,
549 ServiceWorkerProviderType provider_type) {
550 TRACE_EVENT0("ServiceWorker",
551 "ServiceWorkerDispatcherHost::OnProviderCreated");
552 if (!GetContext())
553 return;
554 if (GetContext()->GetProviderHost(render_process_id_, provider_id)) {
555 BadMessageReceived();
556 return;
558 scoped_ptr<ServiceWorkerProviderHost> provider_host(
559 new ServiceWorkerProviderHost(render_process_id_,
560 render_frame_id,
561 provider_id,
562 provider_type,
563 GetContext()->AsWeakPtr(),
564 this));
565 GetContext()->AddProviderHost(provider_host.Pass());
568 void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
569 TRACE_EVENT0("ServiceWorker",
570 "ServiceWorkerDispatcherHost::OnProviderDestroyed");
571 if (!GetContext())
572 return;
573 if (!GetContext()->GetProviderHost(render_process_id_, provider_id)) {
574 BadMessageReceived();
575 return;
577 GetContext()->RemoveProviderHost(render_process_id_, provider_id);
580 void ServiceWorkerDispatcherHost::OnSetHostedVersionId(
581 int provider_id, int64 version_id) {
582 TRACE_EVENT0("ServiceWorker",
583 "ServiceWorkerDispatcherHost::OnSetHostedVersionId");
584 if (!GetContext())
585 return;
586 ServiceWorkerProviderHost* provider_host =
587 GetContext()->GetProviderHost(render_process_id_, provider_id);
588 if (!provider_host) {
589 BadMessageReceived();
590 return;
592 if (!provider_host->IsContextAlive())
593 return;
594 if (!provider_host->SetHostedVersionId(version_id))
595 BadMessageReceived();
597 ServiceWorkerVersion* version = GetContext()->GetLiveVersion(version_id);
598 if (!version)
599 return;
601 // Retrieve the registration associated with |version|. The registration
602 // must be alive because the version keeps it during starting worker.
603 ServiceWorkerRegistration* registration =
604 GetContext()->GetLiveRegistration(version->registration_id());
605 DCHECK(registration);
606 // TODO(ksakamoto): This is a quick fix for crbug.com/459916.
607 if (!registration)
608 return;
610 // Set the document URL to the script url in order to allow
611 // register/unregister/getRegistration on ServiceWorkerGlobalScope.
612 provider_host->SetDocumentUrl(version->script_url());
614 ServiceWorkerRegistrationObjectInfo info;
615 ServiceWorkerVersionAttributes attrs;
616 GetRegistrationObjectInfoAndVersionAttributes(
617 provider_host->AsWeakPtr(), registration, &info, &attrs);
619 Send(new ServiceWorkerMsg_AssociateRegistrationWithServiceWorker(
620 kDocumentMainThreadId, provider_id, info, attrs));
623 ServiceWorkerRegistrationHandle*
624 ServiceWorkerDispatcherHost::FindRegistrationHandle(int provider_id,
625 int64 registration_id) {
626 for (IDMap<ServiceWorkerRegistrationHandle, IDMapOwnPointer>::iterator
627 iter(&registration_handles_);
628 !iter.IsAtEnd();
629 iter.Advance()) {
630 ServiceWorkerRegistrationHandle* handle = iter.GetCurrentValue();
631 DCHECK(handle);
632 if (handle->provider_id() == provider_id && handle->registration() &&
633 handle->registration()->id() == registration_id) {
634 return handle;
637 return NULL;
640 void ServiceWorkerDispatcherHost::GetRegistrationObjectInfoAndVersionAttributes(
641 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
642 ServiceWorkerRegistration* registration,
643 ServiceWorkerRegistrationObjectInfo* info,
644 ServiceWorkerVersionAttributes* attrs) {
645 ServiceWorkerRegistrationHandle* handle =
646 GetOrCreateRegistrationHandle(provider_host, registration);
647 *info = handle->GetObjectInfo();
649 attrs->installing =
650 provider_host->CreateAndRegisterServiceWorkerHandle(
651 registration->installing_version());
652 attrs->waiting =
653 provider_host->CreateAndRegisterServiceWorkerHandle(
654 registration->waiting_version());
655 attrs->active =
656 provider_host->CreateAndRegisterServiceWorkerHandle(
657 registration->active_version());
660 void ServiceWorkerDispatcherHost::RegistrationComplete(
661 int thread_id,
662 int provider_id,
663 int request_id,
664 ServiceWorkerStatusCode status,
665 const std::string& status_message,
666 int64 registration_id) {
667 if (!GetContext())
668 return;
670 ServiceWorkerProviderHost* provider_host =
671 GetContext()->GetProviderHost(render_process_id_, provider_id);
672 if (!provider_host)
673 return; // The provider has already been destroyed.
675 if (status != SERVICE_WORKER_OK) {
676 SendRegistrationError(thread_id, request_id, status, status_message);
677 return;
680 ServiceWorkerRegistration* registration =
681 GetContext()->GetLiveRegistration(registration_id);
682 DCHECK(registration);
684 ServiceWorkerRegistrationObjectInfo info;
685 ServiceWorkerVersionAttributes attrs;
686 GetRegistrationObjectInfoAndVersionAttributes(
687 provider_host->AsWeakPtr(), registration, &info, &attrs);
689 Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
690 thread_id, request_id, info, attrs));
691 TRACE_EVENT_ASYNC_END1("ServiceWorker",
692 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
693 request_id,
694 "Registration ID",
695 registration_id);
698 void ServiceWorkerDispatcherHost::OnWorkerReadyForInspection(
699 int embedded_worker_id) {
700 TRACE_EVENT0("ServiceWorker",
701 "ServiceWorkerDispatcherHost::OnWorkerReadyForInspection");
702 if (!GetContext())
703 return;
704 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
705 if (!registry->CanHandle(embedded_worker_id))
706 return;
707 registry->OnWorkerReadyForInspection(render_process_id_, embedded_worker_id);
710 void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(
711 int embedded_worker_id,
712 int thread_id,
713 int provider_id) {
714 TRACE_EVENT0("ServiceWorker",
715 "ServiceWorkerDispatcherHost::OnWorkerScriptLoaded");
716 if (!GetContext())
717 return;
719 ServiceWorkerProviderHost* provider_host =
720 GetContext()->GetProviderHost(render_process_id_, provider_id);
721 if (!provider_host) {
722 BadMessageReceived();
723 return;
726 provider_host->SetReadyToSendMessagesToWorker(thread_id);
728 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
729 if (!registry->CanHandle(embedded_worker_id))
730 return;
731 registry->OnWorkerScriptLoaded(
732 render_process_id_, thread_id, embedded_worker_id);
735 void ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed(
736 int embedded_worker_id) {
737 TRACE_EVENT0("ServiceWorker",
738 "ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed");
739 if (!GetContext())
740 return;
741 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
742 if (!registry->CanHandle(embedded_worker_id))
743 return;
744 registry->OnWorkerScriptLoadFailed(render_process_id_, embedded_worker_id);
747 void ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated(
748 int embedded_worker_id,
749 bool success) {
750 TRACE_EVENT0("ServiceWorker",
751 "ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated");
752 if (!GetContext())
753 return;
754 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
755 if (!registry->CanHandle(embedded_worker_id))
756 return;
757 registry->OnWorkerScriptEvaluated(
758 render_process_id_, embedded_worker_id, success);
761 void ServiceWorkerDispatcherHost::OnWorkerStarted(int embedded_worker_id) {
762 TRACE_EVENT0("ServiceWorker",
763 "ServiceWorkerDispatcherHost::OnWorkerStarted");
764 if (!GetContext())
765 return;
766 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
767 if (!registry->CanHandle(embedded_worker_id))
768 return;
769 registry->OnWorkerStarted(render_process_id_, embedded_worker_id);
772 void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) {
773 TRACE_EVENT0("ServiceWorker",
774 "ServiceWorkerDispatcherHost::OnWorkerStopped");
775 if (!GetContext())
776 return;
777 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
778 if (!registry->CanHandle(embedded_worker_id))
779 return;
780 registry->OnWorkerStopped(render_process_id_, embedded_worker_id);
783 void ServiceWorkerDispatcherHost::OnPausedAfterDownload(
784 int embedded_worker_id) {
785 TRACE_EVENT0("ServiceWorker",
786 "ServiceWorkerDispatcherHost::OnPausedAfterDownload");
787 if (!GetContext())
788 return;
789 GetContext()->embedded_worker_registry()->OnPausedAfterDownload(
790 render_process_id_, embedded_worker_id);
793 void ServiceWorkerDispatcherHost::OnReportException(
794 int embedded_worker_id,
795 const base::string16& error_message,
796 int line_number,
797 int column_number,
798 const GURL& source_url) {
799 TRACE_EVENT0("ServiceWorker",
800 "ServiceWorkerDispatcherHost::OnReportException");
801 if (!GetContext())
802 return;
803 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
804 if (!registry->CanHandle(embedded_worker_id))
805 return;
806 registry->OnReportException(embedded_worker_id,
807 error_message,
808 line_number,
809 column_number,
810 source_url);
813 void ServiceWorkerDispatcherHost::OnReportConsoleMessage(
814 int embedded_worker_id,
815 const EmbeddedWorkerHostMsg_ReportConsoleMessage_Params& params) {
816 TRACE_EVENT0("ServiceWorker",
817 "ServiceWorkerDispatcherHost::OnReportConsoleMessage");
818 if (!GetContext())
819 return;
820 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
821 if (!registry->CanHandle(embedded_worker_id))
822 return;
823 registry->OnReportConsoleMessage(embedded_worker_id,
824 params.source_identifier,
825 params.message_level,
826 params.message,
827 params.line_number,
828 params.source_url);
831 void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
832 int handle_id) {
833 TRACE_EVENT0("ServiceWorker",
834 "ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount");
835 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
836 if (!handle) {
837 BadMessageReceived();
838 return;
840 handle->IncrementRefCount();
843 void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
844 int handle_id) {
845 TRACE_EVENT0("ServiceWorker",
846 "ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount");
847 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
848 if (!handle) {
849 BadMessageReceived();
850 return;
852 handle->DecrementRefCount();
853 if (handle->HasNoRefCount())
854 handles_.Remove(handle_id);
857 void ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount(
858 int registration_handle_id) {
859 TRACE_EVENT0("ServiceWorker",
860 "ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount");
861 ServiceWorkerRegistrationHandle* handle =
862 registration_handles_.Lookup(registration_handle_id);
863 if (!handle) {
864 BadMessageReceived();
865 return;
867 handle->IncrementRefCount();
870 void ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount(
871 int registration_handle_id) {
872 TRACE_EVENT0("ServiceWorker",
873 "ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount");
874 ServiceWorkerRegistrationHandle* handle =
875 registration_handles_.Lookup(registration_handle_id);
876 if (!handle) {
877 BadMessageReceived();
878 return;
880 handle->DecrementRefCount();
881 if (handle->HasNoRefCount())
882 registration_handles_.Remove(registration_handle_id);
885 void ServiceWorkerDispatcherHost::UnregistrationComplete(
886 int thread_id,
887 int request_id,
888 ServiceWorkerStatusCode status) {
889 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
890 SendUnregistrationError(thread_id, request_id, status);
891 return;
893 const bool is_success = (status == SERVICE_WORKER_OK);
894 Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id,
895 request_id,
896 is_success));
897 TRACE_EVENT_ASYNC_END1(
898 "ServiceWorker",
899 "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
900 request_id,
901 "Status", status);
904 void ServiceWorkerDispatcherHost::GetRegistrationComplete(
905 int thread_id,
906 int provider_id,
907 int request_id,
908 ServiceWorkerStatusCode status,
909 const scoped_refptr<ServiceWorkerRegistration>& registration) {
910 TRACE_EVENT_ASYNC_END1("ServiceWorker",
911 "ServiceWorkerDispatcherHost::GetRegistration",
912 request_id,
913 "Registration ID",
914 registration.get() ? registration->id()
915 : kInvalidServiceWorkerRegistrationId);
917 if (!GetContext())
918 return;
920 ServiceWorkerProviderHost* provider_host =
921 GetContext()->GetProviderHost(render_process_id_, provider_id);
922 if (!provider_host)
923 return; // The provider has already been destroyed.
925 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
926 SendGetRegistrationError(thread_id, request_id, status);
927 return;
930 ServiceWorkerRegistrationObjectInfo info;
931 ServiceWorkerVersionAttributes attrs;
932 if (status == SERVICE_WORKER_OK) {
933 DCHECK(registration.get());
934 if (!registration->is_uninstalling()) {
935 GetRegistrationObjectInfoAndVersionAttributes(
936 provider_host->AsWeakPtr(), registration.get(), &info, &attrs);
940 Send(new ServiceWorkerMsg_DidGetRegistration(
941 thread_id, request_id, info, attrs));
944 void ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete(
945 int thread_id,
946 int request_id,
947 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
948 ServiceWorkerRegistration* registration) {
949 DCHECK(registration);
950 TRACE_EVENT_ASYNC_END1("ServiceWorker",
951 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
952 request_id,
953 "Registration ID",
954 registration ? registration->id()
955 : kInvalidServiceWorkerRegistrationId);
957 if (!GetContext())
958 return;
960 ServiceWorkerRegistrationObjectInfo info;
961 ServiceWorkerVersionAttributes attrs;
962 GetRegistrationObjectInfoAndVersionAttributes(
963 provider_host, registration, &info, &attrs);
964 Send(new ServiceWorkerMsg_DidGetRegistrationForReady(
965 thread_id, request_id, info, attrs));
968 void ServiceWorkerDispatcherHost::SendRegistrationError(
969 int thread_id,
970 int request_id,
971 ServiceWorkerStatusCode status,
972 const std::string& status_message) {
973 base::string16 error_message;
974 blink::WebServiceWorkerError::ErrorType error_type;
975 GetServiceWorkerRegistrationStatusResponse(status, status_message,
976 &error_type, &error_message);
977 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
978 thread_id, request_id, error_type,
979 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) + error_message));
982 void ServiceWorkerDispatcherHost::SendUnregistrationError(
983 int thread_id,
984 int request_id,
985 ServiceWorkerStatusCode status) {
986 base::string16 error_message;
987 blink::WebServiceWorkerError::ErrorType error_type;
988 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
989 &error_message);
990 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
991 thread_id, request_id, error_type,
992 base::ASCIIToUTF16(kServiceWorkerUnregisterErrorPrefix) + error_message));
995 void ServiceWorkerDispatcherHost::SendGetRegistrationError(
996 int thread_id,
997 int request_id,
998 ServiceWorkerStatusCode status) {
999 base::string16 error_message;
1000 blink::WebServiceWorkerError::ErrorType error_type;
1001 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
1002 &error_message);
1003 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
1004 thread_id, request_id, error_type,
1005 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
1006 error_message));
1009 ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
1010 if (!context_wrapper_.get())
1011 return nullptr;
1012 return context_wrapper_->context();
1015 void ServiceWorkerDispatcherHost::OnTerminateWorker(int handle_id) {
1016 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
1017 if (!handle) {
1018 BadMessageReceived();
1019 return;
1021 handle->version()->StopWorker(
1022 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
1025 } // namespace content