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"
29 using blink::WebServiceWorkerError
;
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
,
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
);
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() {
106 GetContext()->RemoveAllProviderHostsForProcess(render_process_id_
);
107 GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
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
)));
122 context_wrapper_
= context_wrapper
;
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.
144 GetContext()->RemoveAllProviderHostsForProcess(render_process_id_
);
145 GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
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
) {
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
,
166 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistrationForReady
,
167 OnGetRegistrationForReady
)
168 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderCreated
,
170 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed
,
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
,
186 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped
,
188 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_DidPauseAfterDownload
,
189 OnPausedAfterDownload
)
190 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportException
,
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_
);
210 BadMessageReceived();
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.
223 pending_messages_
.push_back(message
);
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 ServiceWorkerHandle
* ServiceWorkerDispatcherHost::FindServiceWorkerHandle(
242 for (IDMap
<ServiceWorkerHandle
, IDMapOwnPointer
>::iterator
iter(&handles_
);
243 !iter
.IsAtEnd(); iter
.Advance()) {
244 ServiceWorkerHandle
* handle
= iter
.GetCurrentValue();
246 DCHECK(handle
->version());
247 if (handle
->provider_id() == provider_id
&&
248 handle
->version()->version_id() == version_id
) {
255 ServiceWorkerRegistrationHandle
*
256 ServiceWorkerDispatcherHost::GetOrCreateRegistrationHandle(
257 base::WeakPtr
<ServiceWorkerProviderHost
> provider_host
,
258 ServiceWorkerRegistration
* registration
) {
259 DCHECK(provider_host
);
260 ServiceWorkerRegistrationHandle
* handle
=
261 FindRegistrationHandle(provider_host
->provider_id(), registration
->id());
263 handle
->IncrementRefCount();
267 scoped_ptr
<ServiceWorkerRegistrationHandle
> new_handle(
268 new ServiceWorkerRegistrationHandle(
269 GetContext()->AsWeakPtr(), provider_host
, registration
));
270 handle
= new_handle
.get();
271 RegisterServiceWorkerRegistrationHandle(new_handle
.Pass());
275 void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
280 const GURL
& script_url
) {
281 TRACE_EVENT0("ServiceWorker",
282 "ServiceWorkerDispatcherHost::OnRegisterServiceWorker");
284 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
285 thread_id
, request_id
, WebServiceWorkerError::ErrorTypeAbort
,
286 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix
) +
287 base::ASCIIToUTF16(kShutdownErrorMessage
)));
290 if (!pattern
.is_valid() || !script_url
.is_valid()) {
291 BadMessageReceived();
295 ServiceWorkerProviderHost
* provider_host
= GetContext()->GetProviderHost(
296 render_process_id_
, provider_id
);
297 if (!provider_host
) {
298 BadMessageReceived();
301 if (!provider_host
->IsContextAlive()) {
302 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
303 thread_id
, request_id
, WebServiceWorkerError::ErrorTypeAbort
,
304 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix
) +
305 base::ASCIIToUTF16(kShutdownErrorMessage
)));
309 // TODO(ksakamoto): Currently, document_url is empty if the document is in an
310 // IFRAME using frame.contentDocument.write(...). We can remove this check
311 // once crbug.com/439697 is fixed.
312 if (provider_host
->document_url().is_empty()) {
313 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
314 thread_id
, request_id
, WebServiceWorkerError::ErrorTypeSecurity
,
315 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix
) +
316 base::ASCIIToUTF16(kNoDocumentURLErrorMessage
)));
320 if (!CanRegisterServiceWorker(
321 provider_host
->document_url(), pattern
, script_url
)) {
322 BadMessageReceived();
326 std::string error_message
;
327 if (ServiceWorkerUtils::ContainsDisallowedCharacter(pattern
, script_url
,
329 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
330 thread_id
, request_id
, WebServiceWorkerError::ErrorTypeSecurity
,
331 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix
) +
332 base::UTF8ToUTF16(error_message
)));
336 if (!GetContentClient()->browser()->AllowServiceWorker(
337 pattern
, provider_host
->topmost_frame_url(), resource_context_
)) {
338 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
339 thread_id
, request_id
, WebServiceWorkerError::ErrorTypeUnknown
,
340 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix
) +
341 base::ASCIIToUTF16(kUserDeniedPermissionMessage
)));
345 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
346 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
348 "Pattern", pattern
.spec(),
349 "Script URL", script_url
.spec());
350 GetContext()->RegisterServiceWorker(
354 base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete
,
361 void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
365 const GURL
& pattern
) {
366 TRACE_EVENT0("ServiceWorker",
367 "ServiceWorkerDispatcherHost::OnUnregisterServiceWorker");
369 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
372 blink::WebServiceWorkerError::ErrorTypeAbort
,
373 base::ASCIIToUTF16(kShutdownErrorMessage
)));
376 if (!pattern
.is_valid()) {
377 BadMessageReceived();
381 ServiceWorkerProviderHost
* provider_host
= GetContext()->GetProviderHost(
382 render_process_id_
, provider_id
);
383 if (!provider_host
) {
384 BadMessageReceived();
387 if (!provider_host
->IsContextAlive()) {
388 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
391 blink::WebServiceWorkerError::ErrorTypeAbort
,
392 base::ASCIIToUTF16(kShutdownErrorMessage
)));
396 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
397 if (provider_host
->document_url().is_empty()) {
398 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
401 WebServiceWorkerError::ErrorTypeSecurity
,
402 base::ASCIIToUTF16(kNoDocumentURLErrorMessage
)));
406 if (!CanUnregisterServiceWorker(provider_host
->document_url(), pattern
)) {
407 BadMessageReceived();
411 if (!GetContentClient()->browser()->AllowServiceWorker(
412 pattern
, provider_host
->topmost_frame_url(), resource_context_
)) {
413 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
416 WebServiceWorkerError::ErrorTypeUnknown
,
417 base::ASCIIToUTF16(kUserDeniedPermissionMessage
)));
421 TRACE_EVENT_ASYNC_BEGIN1(
423 "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
425 "Pattern", pattern
.spec());
426 GetContext()->UnregisterServiceWorker(
428 base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete
,
434 void ServiceWorkerDispatcherHost::OnGetRegistration(
438 const GURL
& document_url
) {
439 TRACE_EVENT0("ServiceWorker",
440 "ServiceWorkerDispatcherHost::OnGetRegistration");
442 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
443 thread_id
, request_id
, blink::WebServiceWorkerError::ErrorTypeAbort
,
444 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix
) +
445 base::ASCIIToUTF16(kShutdownErrorMessage
)));
448 if (!document_url
.is_valid()) {
449 BadMessageReceived();
453 ServiceWorkerProviderHost
* provider_host
= GetContext()->GetProviderHost(
454 render_process_id_
, provider_id
);
455 if (!provider_host
) {
456 BadMessageReceived();
459 if (!provider_host
->IsContextAlive()) {
460 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
461 thread_id
, request_id
, blink::WebServiceWorkerError::ErrorTypeAbort
,
462 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix
) +
463 base::ASCIIToUTF16(kShutdownErrorMessage
)));
467 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
468 if (provider_host
->document_url().is_empty()) {
469 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
470 thread_id
, request_id
, WebServiceWorkerError::ErrorTypeSecurity
,
471 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix
) +
472 base::ASCIIToUTF16(kNoDocumentURLErrorMessage
)));
476 if (!CanGetRegistration(provider_host
->document_url(), document_url
)) {
477 BadMessageReceived();
481 if (!GetContentClient()->browser()->AllowServiceWorker(
482 provider_host
->document_url(),
483 provider_host
->topmost_frame_url(),
484 resource_context_
)) {
485 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
486 thread_id
, request_id
, WebServiceWorkerError::ErrorTypeUnknown
,
487 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix
) +
488 base::ASCIIToUTF16(kUserDeniedPermissionMessage
)));
492 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
493 if (GetContext()->storage()->IsDisabled()) {
494 SendGetRegistrationError(thread_id
, request_id
, SERVICE_WORKER_ERROR_ABORT
);
498 TRACE_EVENT_ASYNC_BEGIN1(
500 "ServiceWorkerDispatcherHost::GetRegistration",
502 "Document URL", document_url
.spec());
504 GetContext()->storage()->FindRegistrationForDocument(
506 base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationComplete
,
513 void ServiceWorkerDispatcherHost::OnGetRegistrationForReady(
517 TRACE_EVENT0("ServiceWorker",
518 "ServiceWorkerDispatcherHost::OnGetRegistrationForReady");
521 ServiceWorkerProviderHost
* provider_host
=
522 GetContext()->GetProviderHost(render_process_id_
, provider_id
);
523 if (!provider_host
) {
524 BadMessageReceived();
527 if (!provider_host
->IsContextAlive())
530 TRACE_EVENT_ASYNC_BEGIN0(
532 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
535 if (!provider_host
->GetRegistrationForReady(base::Bind(
536 &ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete
,
537 this, thread_id
, request_id
, provider_host
->AsWeakPtr()))) {
538 BadMessageReceived();
542 void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
544 const base::string16
& message
,
545 const std::vector
<TransferredMessagePort
>& sent_message_ports
) {
546 TRACE_EVENT0("ServiceWorker",
547 "ServiceWorkerDispatcherHost::OnPostMessageToWorker");
551 ServiceWorkerHandle
* handle
= handles_
.Lookup(handle_id
);
553 BadMessageReceived();
557 handle
->version()->DispatchMessageEvent(
558 message
, sent_message_ports
,
559 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback
));
562 void ServiceWorkerDispatcherHost::OnProviderCreated(
565 ServiceWorkerProviderType provider_type
) {
566 TRACE_EVENT0("ServiceWorker",
567 "ServiceWorkerDispatcherHost::OnProviderCreated");
570 if (GetContext()->GetProviderHost(render_process_id_
, provider_id
)) {
571 BadMessageReceived();
574 scoped_ptr
<ServiceWorkerProviderHost
> provider_host(
575 new ServiceWorkerProviderHost(render_process_id_
,
579 GetContext()->AsWeakPtr(),
581 GetContext()->AddProviderHost(provider_host
.Pass());
584 void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id
) {
585 TRACE_EVENT0("ServiceWorker",
586 "ServiceWorkerDispatcherHost::OnProviderDestroyed");
589 if (!GetContext()->GetProviderHost(render_process_id_
, provider_id
)) {
590 BadMessageReceived();
593 GetContext()->RemoveProviderHost(render_process_id_
, provider_id
);
596 void ServiceWorkerDispatcherHost::OnSetHostedVersionId(
597 int provider_id
, int64 version_id
) {
598 TRACE_EVENT0("ServiceWorker",
599 "ServiceWorkerDispatcherHost::OnSetHostedVersionId");
602 ServiceWorkerProviderHost
* provider_host
=
603 GetContext()->GetProviderHost(render_process_id_
, provider_id
);
604 if (!provider_host
) {
605 BadMessageReceived();
608 if (!provider_host
->IsContextAlive())
610 if (!provider_host
->SetHostedVersionId(version_id
))
611 BadMessageReceived();
613 ServiceWorkerVersion
* version
= GetContext()->GetLiveVersion(version_id
);
617 // Retrieve the registration associated with |version|. The registration
618 // must be alive because the version keeps it during starting worker.
619 ServiceWorkerRegistration
* registration
=
620 GetContext()->GetLiveRegistration(version
->registration_id());
621 DCHECK(registration
);
622 // TODO(ksakamoto): This is a quick fix for crbug.com/459916.
626 // Set the document URL to the script url in order to allow
627 // register/unregister/getRegistration on ServiceWorkerGlobalScope.
628 provider_host
->SetDocumentUrl(version
->script_url());
630 ServiceWorkerRegistrationObjectInfo info
;
631 ServiceWorkerVersionAttributes attrs
;
632 GetRegistrationObjectInfoAndVersionAttributes(
633 provider_host
->AsWeakPtr(), registration
, &info
, &attrs
);
635 Send(new ServiceWorkerMsg_AssociateRegistrationWithServiceWorker(
636 kDocumentMainThreadId
, provider_id
, info
, attrs
));
639 ServiceWorkerRegistrationHandle
*
640 ServiceWorkerDispatcherHost::FindRegistrationHandle(int provider_id
,
641 int64 registration_id
) {
642 for (IDMap
<ServiceWorkerRegistrationHandle
, IDMapOwnPointer
>::iterator
643 iter(®istration_handles_
);
646 ServiceWorkerRegistrationHandle
* handle
= iter
.GetCurrentValue();
648 DCHECK(handle
->registration());
649 if (handle
->provider_id() == provider_id
&&
650 handle
->registration()->id() == registration_id
) {
657 void ServiceWorkerDispatcherHost::GetRegistrationObjectInfoAndVersionAttributes(
658 base::WeakPtr
<ServiceWorkerProviderHost
> provider_host
,
659 ServiceWorkerRegistration
* registration
,
660 ServiceWorkerRegistrationObjectInfo
* info
,
661 ServiceWorkerVersionAttributes
* attrs
) {
662 ServiceWorkerRegistrationHandle
* handle
=
663 GetOrCreateRegistrationHandle(provider_host
, registration
);
664 *info
= handle
->GetObjectInfo();
666 attrs
->installing
= provider_host
->GetOrCreateServiceWorkerHandle(
667 registration
->installing_version());
668 attrs
->waiting
= provider_host
->GetOrCreateServiceWorkerHandle(
669 registration
->waiting_version());
670 attrs
->active
= provider_host
->GetOrCreateServiceWorkerHandle(
671 registration
->active_version());
674 void ServiceWorkerDispatcherHost::RegistrationComplete(
678 ServiceWorkerStatusCode status
,
679 const std::string
& status_message
,
680 int64 registration_id
) {
684 ServiceWorkerProviderHost
* provider_host
=
685 GetContext()->GetProviderHost(render_process_id_
, provider_id
);
687 return; // The provider has already been destroyed.
689 if (status
!= SERVICE_WORKER_OK
) {
690 SendRegistrationError(thread_id
, request_id
, status
, status_message
);
694 ServiceWorkerRegistration
* registration
=
695 GetContext()->GetLiveRegistration(registration_id
);
696 DCHECK(registration
);
698 ServiceWorkerRegistrationObjectInfo info
;
699 ServiceWorkerVersionAttributes attrs
;
700 GetRegistrationObjectInfoAndVersionAttributes(
701 provider_host
->AsWeakPtr(), registration
, &info
, &attrs
);
703 Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
704 thread_id
, request_id
, info
, attrs
));
705 TRACE_EVENT_ASYNC_END1("ServiceWorker",
706 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
712 void ServiceWorkerDispatcherHost::OnWorkerReadyForInspection(
713 int embedded_worker_id
) {
714 TRACE_EVENT0("ServiceWorker",
715 "ServiceWorkerDispatcherHost::OnWorkerReadyForInspection");
718 EmbeddedWorkerRegistry
* registry
= GetContext()->embedded_worker_registry();
719 if (!registry
->CanHandle(embedded_worker_id
))
721 registry
->OnWorkerReadyForInspection(render_process_id_
, embedded_worker_id
);
724 void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(
725 int embedded_worker_id
,
728 TRACE_EVENT0("ServiceWorker",
729 "ServiceWorkerDispatcherHost::OnWorkerScriptLoaded");
733 ServiceWorkerProviderHost
* provider_host
=
734 GetContext()->GetProviderHost(render_process_id_
, provider_id
);
735 if (!provider_host
) {
736 BadMessageReceived();
740 provider_host
->SetReadyToSendMessagesToWorker(thread_id
);
742 EmbeddedWorkerRegistry
* registry
= GetContext()->embedded_worker_registry();
743 if (!registry
->CanHandle(embedded_worker_id
))
745 registry
->OnWorkerScriptLoaded(
746 render_process_id_
, thread_id
, embedded_worker_id
);
749 void ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed(
750 int embedded_worker_id
) {
751 TRACE_EVENT0("ServiceWorker",
752 "ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed");
755 EmbeddedWorkerRegistry
* registry
= GetContext()->embedded_worker_registry();
756 if (!registry
->CanHandle(embedded_worker_id
))
758 registry
->OnWorkerScriptLoadFailed(render_process_id_
, embedded_worker_id
);
761 void ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated(
762 int embedded_worker_id
,
764 TRACE_EVENT0("ServiceWorker",
765 "ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated");
768 EmbeddedWorkerRegistry
* registry
= GetContext()->embedded_worker_registry();
769 if (!registry
->CanHandle(embedded_worker_id
))
771 registry
->OnWorkerScriptEvaluated(
772 render_process_id_
, embedded_worker_id
, success
);
775 void ServiceWorkerDispatcherHost::OnWorkerStarted(int embedded_worker_id
) {
776 TRACE_EVENT0("ServiceWorker",
777 "ServiceWorkerDispatcherHost::OnWorkerStarted");
780 EmbeddedWorkerRegistry
* registry
= GetContext()->embedded_worker_registry();
781 if (!registry
->CanHandle(embedded_worker_id
))
783 registry
->OnWorkerStarted(render_process_id_
, embedded_worker_id
);
786 void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id
) {
787 TRACE_EVENT0("ServiceWorker",
788 "ServiceWorkerDispatcherHost::OnWorkerStopped");
791 EmbeddedWorkerRegistry
* registry
= GetContext()->embedded_worker_registry();
792 if (!registry
->CanHandle(embedded_worker_id
))
794 registry
->OnWorkerStopped(render_process_id_
, embedded_worker_id
);
797 void ServiceWorkerDispatcherHost::OnPausedAfterDownload(
798 int embedded_worker_id
) {
799 TRACE_EVENT0("ServiceWorker",
800 "ServiceWorkerDispatcherHost::OnPausedAfterDownload");
803 GetContext()->embedded_worker_registry()->OnPausedAfterDownload(
804 render_process_id_
, embedded_worker_id
);
807 void ServiceWorkerDispatcherHost::OnReportException(
808 int embedded_worker_id
,
809 const base::string16
& error_message
,
812 const GURL
& source_url
) {
813 TRACE_EVENT0("ServiceWorker",
814 "ServiceWorkerDispatcherHost::OnReportException");
817 EmbeddedWorkerRegistry
* registry
= GetContext()->embedded_worker_registry();
818 if (!registry
->CanHandle(embedded_worker_id
))
820 registry
->OnReportException(embedded_worker_id
,
827 void ServiceWorkerDispatcherHost::OnReportConsoleMessage(
828 int embedded_worker_id
,
829 const EmbeddedWorkerHostMsg_ReportConsoleMessage_Params
& params
) {
830 TRACE_EVENT0("ServiceWorker",
831 "ServiceWorkerDispatcherHost::OnReportConsoleMessage");
834 EmbeddedWorkerRegistry
* registry
= GetContext()->embedded_worker_registry();
835 if (!registry
->CanHandle(embedded_worker_id
))
837 registry
->OnReportConsoleMessage(embedded_worker_id
,
838 params
.source_identifier
,
839 params
.message_level
,
845 void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
847 TRACE_EVENT0("ServiceWorker",
848 "ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount");
849 ServiceWorkerHandle
* handle
= handles_
.Lookup(handle_id
);
851 BadMessageReceived();
854 handle
->IncrementRefCount();
857 void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
859 TRACE_EVENT0("ServiceWorker",
860 "ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount");
861 ServiceWorkerHandle
* handle
= handles_
.Lookup(handle_id
);
863 BadMessageReceived();
866 handle
->DecrementRefCount();
867 if (handle
->HasNoRefCount())
868 handles_
.Remove(handle_id
);
871 void ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount(
872 int registration_handle_id
) {
873 TRACE_EVENT0("ServiceWorker",
874 "ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount");
875 ServiceWorkerRegistrationHandle
* handle
=
876 registration_handles_
.Lookup(registration_handle_id
);
878 BadMessageReceived();
881 handle
->IncrementRefCount();
884 void ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount(
885 int registration_handle_id
) {
886 TRACE_EVENT0("ServiceWorker",
887 "ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount");
888 ServiceWorkerRegistrationHandle
* handle
=
889 registration_handles_
.Lookup(registration_handle_id
);
891 BadMessageReceived();
894 handle
->DecrementRefCount();
895 if (handle
->HasNoRefCount())
896 registration_handles_
.Remove(registration_handle_id
);
899 void ServiceWorkerDispatcherHost::UnregistrationComplete(
902 ServiceWorkerStatusCode status
) {
903 if (status
!= SERVICE_WORKER_OK
&& status
!= SERVICE_WORKER_ERROR_NOT_FOUND
) {
904 SendUnregistrationError(thread_id
, request_id
, status
);
907 const bool is_success
= (status
== SERVICE_WORKER_OK
);
908 Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id
,
911 TRACE_EVENT_ASYNC_END1(
913 "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
918 void ServiceWorkerDispatcherHost::GetRegistrationComplete(
922 ServiceWorkerStatusCode status
,
923 const scoped_refptr
<ServiceWorkerRegistration
>& registration
) {
924 TRACE_EVENT_ASYNC_END1("ServiceWorker",
925 "ServiceWorkerDispatcherHost::GetRegistration",
928 registration
.get() ? registration
->id()
929 : kInvalidServiceWorkerRegistrationId
);
934 ServiceWorkerProviderHost
* provider_host
=
935 GetContext()->GetProviderHost(render_process_id_
, provider_id
);
937 return; // The provider has already been destroyed.
939 if (status
!= SERVICE_WORKER_OK
&& status
!= SERVICE_WORKER_ERROR_NOT_FOUND
) {
940 SendGetRegistrationError(thread_id
, request_id
, status
);
944 ServiceWorkerRegistrationObjectInfo info
;
945 ServiceWorkerVersionAttributes attrs
;
946 if (status
== SERVICE_WORKER_OK
) {
947 DCHECK(registration
.get());
948 if (!registration
->is_uninstalling()) {
949 GetRegistrationObjectInfoAndVersionAttributes(
950 provider_host
->AsWeakPtr(), registration
.get(), &info
, &attrs
);
954 Send(new ServiceWorkerMsg_DidGetRegistration(
955 thread_id
, request_id
, info
, attrs
));
958 void ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete(
961 base::WeakPtr
<ServiceWorkerProviderHost
> provider_host
,
962 ServiceWorkerRegistration
* registration
) {
963 DCHECK(registration
);
964 TRACE_EVENT_ASYNC_END1("ServiceWorker",
965 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
968 registration
? registration
->id()
969 : kInvalidServiceWorkerRegistrationId
);
974 ServiceWorkerRegistrationObjectInfo info
;
975 ServiceWorkerVersionAttributes attrs
;
976 GetRegistrationObjectInfoAndVersionAttributes(
977 provider_host
, registration
, &info
, &attrs
);
978 Send(new ServiceWorkerMsg_DidGetRegistrationForReady(
979 thread_id
, request_id
, info
, attrs
));
982 void ServiceWorkerDispatcherHost::SendRegistrationError(
985 ServiceWorkerStatusCode status
,
986 const std::string
& status_message
) {
987 base::string16 error_message
;
988 blink::WebServiceWorkerError::ErrorType error_type
;
989 GetServiceWorkerRegistrationStatusResponse(status
, status_message
,
990 &error_type
, &error_message
);
991 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
992 thread_id
, request_id
, error_type
,
993 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix
) + error_message
));
996 void ServiceWorkerDispatcherHost::SendUnregistrationError(
999 ServiceWorkerStatusCode status
) {
1000 base::string16 error_message
;
1001 blink::WebServiceWorkerError::ErrorType error_type
;
1002 GetServiceWorkerRegistrationStatusResponse(status
, std::string(), &error_type
,
1004 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
1005 thread_id
, request_id
, error_type
,
1006 base::ASCIIToUTF16(kServiceWorkerUnregisterErrorPrefix
) + error_message
));
1009 void ServiceWorkerDispatcherHost::SendGetRegistrationError(
1012 ServiceWorkerStatusCode status
) {
1013 base::string16 error_message
;
1014 blink::WebServiceWorkerError::ErrorType error_type
;
1015 GetServiceWorkerRegistrationStatusResponse(status
, std::string(), &error_type
,
1017 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
1018 thread_id
, request_id
, error_type
,
1019 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix
) +
1023 ServiceWorkerContextCore
* ServiceWorkerDispatcherHost::GetContext() {
1024 if (!context_wrapper_
.get())
1026 return context_wrapper_
->context();
1029 void ServiceWorkerDispatcherHost::OnTerminateWorker(int handle_id
) {
1030 ServiceWorkerHandle
* handle
= handles_
.Lookup(handle_id
);
1032 BadMessageReceived();
1035 handle
->version()->StopWorker(
1036 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback
));
1039 } // namespace content