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/message_port_message_filter.h"
12 #include "content/browser/message_port_service.h"
13 #include "content/browser/service_worker/embedded_worker_registry.h"
14 #include "content/browser/service_worker/service_worker_context_core.h"
15 #include "content/browser/service_worker/service_worker_context_wrapper.h"
16 #include "content/browser/service_worker/service_worker_handle.h"
17 #include "content/browser/service_worker/service_worker_registration.h"
18 #include "content/browser/service_worker/service_worker_registration_handle.h"
19 #include "content/browser/service_worker/service_worker_utils.h"
20 #include "content/common/service_worker/embedded_worker_messages.h"
21 #include "content/common/service_worker/service_worker_messages.h"
22 #include "content/common/service_worker/service_worker_types.h"
23 #include "content/public/browser/content_browser_client.h"
24 #include "content/public/common/content_client.h"
25 #include "ipc/ipc_message_macros.h"
26 #include "net/base/net_util.h"
27 #include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
30 using blink::WebServiceWorkerError
;
36 const char kNoDocumentURLErrorMessage
[] =
37 "No URL is associated with the caller's document.";
38 const char kShutdownErrorMessage
[] =
39 "The Service Worker system has shutdown.";
40 const char kUserDeniedPermissionMessage
[] =
41 "The user denied permission to use Service Worker.";
43 const uint32 kFilteredMessageClasses
[] = {
44 ServiceWorkerMsgStart
,
45 EmbeddedWorkerMsgStart
,
48 bool AllOriginsMatch(const GURL
& url_a
, const GURL
& url_b
, const GURL
& url_c
) {
49 return url_a
.GetOrigin() == url_b
.GetOrigin() &&
50 url_a
.GetOrigin() == url_c
.GetOrigin();
53 // TODO(dominicc): When crbug.com/362214 is fixed use that to be
54 // consistent with Blink's
55 // SecurityOrigin::canAccessFeatureRequiringSecureOrigin.
56 bool OriginCanAccessServiceWorkers(const GURL
& url
) {
57 return url
.SchemeIsHTTPOrHTTPS() &&
58 (url
.SchemeIsSecure() || net::IsLocalhost(url
.host()));
61 bool CanRegisterServiceWorker(const GURL
& document_url
,
63 const GURL
& script_url
) {
64 DCHECK(document_url
.is_valid());
65 DCHECK(pattern
.is_valid());
66 DCHECK(script_url
.is_valid());
67 return AllOriginsMatch(document_url
, pattern
, script_url
) &&
68 OriginCanAccessServiceWorkers(document_url
) &&
69 OriginCanAccessServiceWorkers(pattern
) &&
70 OriginCanAccessServiceWorkers(script_url
);
73 bool CanUnregisterServiceWorker(const GURL
& document_url
,
74 const GURL
& pattern
) {
75 DCHECK(document_url
.is_valid());
76 DCHECK(pattern
.is_valid());
77 return document_url
.GetOrigin() == pattern
.GetOrigin() &&
78 OriginCanAccessServiceWorkers(document_url
) &&
79 OriginCanAccessServiceWorkers(pattern
);
82 bool CanGetRegistration(const GURL
& document_url
,
83 const GURL
& given_document_url
) {
84 DCHECK(document_url
.is_valid());
85 DCHECK(given_document_url
.is_valid());
86 return document_url
.GetOrigin() == given_document_url
.GetOrigin() &&
87 OriginCanAccessServiceWorkers(document_url
) &&
88 OriginCanAccessServiceWorkers(given_document_url
);
93 ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
94 int render_process_id
,
95 MessagePortMessageFilter
* message_port_message_filter
,
96 ResourceContext
* resource_context
)
97 : BrowserMessageFilter(kFilteredMessageClasses
,
98 arraysize(kFilteredMessageClasses
)),
99 render_process_id_(render_process_id
),
100 message_port_message_filter_(message_port_message_filter
),
101 resource_context_(resource_context
),
102 channel_ready_(false) {
105 ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
107 GetContext()->RemoveAllProviderHostsForProcess(render_process_id_
);
108 GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
113 void ServiceWorkerDispatcherHost::Init(
114 ServiceWorkerContextWrapper
* context_wrapper
) {
115 if (!BrowserThread::CurrentlyOn(BrowserThread::IO
)) {
116 BrowserThread::PostTask(
117 BrowserThread::IO
, FROM_HERE
,
118 base::Bind(&ServiceWorkerDispatcherHost::Init
,
119 this, make_scoped_refptr(context_wrapper
)));
123 context_wrapper_
= context_wrapper
;
126 GetContext()->embedded_worker_registry()->AddChildProcessSender(
127 render_process_id_
, this, message_port_message_filter_
);
130 void ServiceWorkerDispatcherHost::OnFilterAdded(IPC::Sender
* sender
) {
131 TRACE_EVENT0("ServiceWorker",
132 "ServiceWorkerDispatcherHost::OnFilterAdded");
133 channel_ready_
= true;
134 std::vector
<IPC::Message
*> messages
;
135 pending_messages_
.release(&messages
);
136 for (size_t i
= 0; i
< messages
.size(); ++i
) {
137 BrowserMessageFilter::Send(messages
[i
]);
141 void ServiceWorkerDispatcherHost::OnFilterRemoved() {
142 // Don't wait until the destructor to teardown since a new dispatcher host
143 // for this process might be created before then.
145 GetContext()->RemoveAllProviderHostsForProcess(render_process_id_
);
146 GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
149 context_wrapper_
= nullptr;
150 channel_ready_
= false;
153 void ServiceWorkerDispatcherHost::OnDestruct() const {
154 BrowserThread::DeleteOnIOThread::Destruct(this);
157 bool ServiceWorkerDispatcherHost::OnMessageReceived(
158 const IPC::Message
& message
) {
160 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcherHost
, message
)
161 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_RegisterServiceWorker
,
162 OnRegisterServiceWorker
)
163 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_UnregisterServiceWorker
,
164 OnUnregisterServiceWorker
)
165 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistration
,
167 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistrationForReady
,
168 OnGetRegistrationForReady
)
169 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderCreated
,
171 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed
,
173 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetVersionId
,
174 OnSetHostedVersionId
)
175 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToWorker
,
176 OnPostMessageToWorker
)
177 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerReadyForInspection
,
178 OnWorkerReadyForInspection
)
179 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoaded
,
180 OnWorkerScriptLoaded
)
181 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoadFailed
,
182 OnWorkerScriptLoadFailed
)
183 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptEvaluated
,
184 OnWorkerScriptEvaluated
)
185 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted
,
187 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped
,
189 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_DidPauseAfterDownload
,
190 OnPausedAfterDownload
)
191 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportException
,
193 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportConsoleMessage
,
194 OnReportConsoleMessage
)
195 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount
,
196 OnIncrementServiceWorkerRefCount
)
197 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount
,
198 OnDecrementServiceWorkerRefCount
)
199 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementRegistrationRefCount
,
200 OnIncrementRegistrationRefCount
)
201 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementRegistrationRefCount
,
202 OnDecrementRegistrationRefCount
)
203 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_TerminateWorker
, OnTerminateWorker
)
204 IPC_MESSAGE_UNHANDLED(handled
= false)
205 IPC_END_MESSAGE_MAP()
207 if (!handled
&& GetContext()) {
208 handled
= GetContext()->embedded_worker_registry()->OnMessageReceived(
209 message
, render_process_id_
);
211 BadMessageReceived();
217 bool ServiceWorkerDispatcherHost::Send(IPC::Message
* message
) {
218 if (channel_ready_
) {
219 BrowserMessageFilter::Send(message
);
220 // Don't bother passing through Send()'s result: it's not reliable.
224 pending_messages_
.push_back(message
);
228 void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle(
229 scoped_ptr
<ServiceWorkerHandle
> handle
) {
230 int handle_id
= handle
->handle_id();
231 handles_
.AddWithID(handle
.release(), handle_id
);
234 void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationHandle(
235 scoped_ptr
<ServiceWorkerRegistrationHandle
> handle
) {
236 int handle_id
= handle
->handle_id();
237 registration_handles_
.AddWithID(handle
.release(), handle_id
);
240 ServiceWorkerHandle
* ServiceWorkerDispatcherHost::FindServiceWorkerHandle(
243 for (IDMap
<ServiceWorkerHandle
, IDMapOwnPointer
>::iterator
iter(&handles_
);
244 !iter
.IsAtEnd(); iter
.Advance()) {
245 ServiceWorkerHandle
* handle
= iter
.GetCurrentValue();
247 DCHECK(handle
->version());
248 if (handle
->provider_id() == provider_id
&&
249 handle
->version()->version_id() == version_id
) {
256 ServiceWorkerRegistrationHandle
*
257 ServiceWorkerDispatcherHost::GetOrCreateRegistrationHandle(
258 base::WeakPtr
<ServiceWorkerProviderHost
> provider_host
,
259 ServiceWorkerRegistration
* registration
) {
260 DCHECK(provider_host
);
261 ServiceWorkerRegistrationHandle
* handle
=
262 FindRegistrationHandle(provider_host
->provider_id(), registration
->id());
264 handle
->IncrementRefCount();
268 scoped_ptr
<ServiceWorkerRegistrationHandle
> new_handle(
269 new ServiceWorkerRegistrationHandle(
270 GetContext()->AsWeakPtr(), provider_host
, registration
));
271 handle
= new_handle
.get();
272 RegisterServiceWorkerRegistrationHandle(new_handle
.Pass());
276 void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
281 const GURL
& script_url
) {
282 TRACE_EVENT0("ServiceWorker",
283 "ServiceWorkerDispatcherHost::OnRegisterServiceWorker");
285 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
286 thread_id
, request_id
, WebServiceWorkerError::ErrorTypeAbort
,
287 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix
) +
288 base::ASCIIToUTF16(kShutdownErrorMessage
)));
291 if (!pattern
.is_valid() || !script_url
.is_valid()) {
292 BadMessageReceived();
296 ServiceWorkerProviderHost
* provider_host
= GetContext()->GetProviderHost(
297 render_process_id_
, provider_id
);
298 if (!provider_host
) {
299 BadMessageReceived();
302 if (!provider_host
->IsContextAlive()) {
303 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
304 thread_id
, request_id
, WebServiceWorkerError::ErrorTypeAbort
,
305 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix
) +
306 base::ASCIIToUTF16(kShutdownErrorMessage
)));
310 // TODO(ksakamoto): Currently, document_url is empty if the document is in an
311 // IFRAME using frame.contentDocument.write(...). We can remove this check
312 // once crbug.com/439697 is fixed.
313 if (provider_host
->document_url().is_empty()) {
314 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
315 thread_id
, request_id
, WebServiceWorkerError::ErrorTypeSecurity
,
316 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix
) +
317 base::ASCIIToUTF16(kNoDocumentURLErrorMessage
)));
321 if (!CanRegisterServiceWorker(
322 provider_host
->document_url(), pattern
, script_url
)) {
323 BadMessageReceived();
327 std::string error_message
;
328 if (ServiceWorkerUtils::ContainsDisallowedCharacter(pattern
, script_url
,
330 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
331 thread_id
, request_id
, WebServiceWorkerError::ErrorTypeSecurity
,
332 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix
) +
333 base::UTF8ToUTF16(error_message
)));
337 if (!GetContentClient()->browser()->AllowServiceWorker(
338 pattern
, provider_host
->topmost_frame_url(), resource_context_
)) {
339 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
340 thread_id
, request_id
, WebServiceWorkerError::ErrorTypeUnknown
,
341 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix
) +
342 base::ASCIIToUTF16(kUserDeniedPermissionMessage
)));
346 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
347 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
349 "Pattern", pattern
.spec(),
350 "Script URL", script_url
.spec());
351 GetContext()->RegisterServiceWorker(
355 base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete
,
362 void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
366 const GURL
& pattern
) {
367 TRACE_EVENT0("ServiceWorker",
368 "ServiceWorkerDispatcherHost::OnUnregisterServiceWorker");
370 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
373 blink::WebServiceWorkerError::ErrorTypeAbort
,
374 base::ASCIIToUTF16(kShutdownErrorMessage
)));
377 if (!pattern
.is_valid()) {
378 BadMessageReceived();
382 ServiceWorkerProviderHost
* provider_host
= GetContext()->GetProviderHost(
383 render_process_id_
, provider_id
);
384 if (!provider_host
) {
385 BadMessageReceived();
388 if (!provider_host
->IsContextAlive()) {
389 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
392 blink::WebServiceWorkerError::ErrorTypeAbort
,
393 base::ASCIIToUTF16(kShutdownErrorMessage
)));
397 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
398 if (provider_host
->document_url().is_empty()) {
399 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
402 WebServiceWorkerError::ErrorTypeSecurity
,
403 base::ASCIIToUTF16(kNoDocumentURLErrorMessage
)));
407 if (!CanUnregisterServiceWorker(provider_host
->document_url(), pattern
)) {
408 BadMessageReceived();
412 if (!GetContentClient()->browser()->AllowServiceWorker(
413 pattern
, provider_host
->topmost_frame_url(), resource_context_
)) {
414 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
417 WebServiceWorkerError::ErrorTypeUnknown
,
418 base::ASCIIToUTF16(kUserDeniedPermissionMessage
)));
422 TRACE_EVENT_ASYNC_BEGIN1(
424 "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
426 "Pattern", pattern
.spec());
427 GetContext()->UnregisterServiceWorker(
429 base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete
,
435 void ServiceWorkerDispatcherHost::OnGetRegistration(
439 const GURL
& document_url
) {
440 TRACE_EVENT0("ServiceWorker",
441 "ServiceWorkerDispatcherHost::OnGetRegistration");
443 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
444 thread_id
, request_id
, blink::WebServiceWorkerError::ErrorTypeAbort
,
445 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix
) +
446 base::ASCIIToUTF16(kShutdownErrorMessage
)));
449 if (!document_url
.is_valid()) {
450 BadMessageReceived();
454 ServiceWorkerProviderHost
* provider_host
= GetContext()->GetProviderHost(
455 render_process_id_
, provider_id
);
456 if (!provider_host
) {
457 BadMessageReceived();
460 if (!provider_host
->IsContextAlive()) {
461 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
462 thread_id
, request_id
, blink::WebServiceWorkerError::ErrorTypeAbort
,
463 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix
) +
464 base::ASCIIToUTF16(kShutdownErrorMessage
)));
468 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
469 if (provider_host
->document_url().is_empty()) {
470 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
471 thread_id
, request_id
, WebServiceWorkerError::ErrorTypeSecurity
,
472 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix
) +
473 base::ASCIIToUTF16(kNoDocumentURLErrorMessage
)));
477 if (!CanGetRegistration(provider_host
->document_url(), document_url
)) {
478 BadMessageReceived();
482 if (!GetContentClient()->browser()->AllowServiceWorker(
483 provider_host
->document_url(),
484 provider_host
->topmost_frame_url(),
485 resource_context_
)) {
486 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
487 thread_id
, request_id
, WebServiceWorkerError::ErrorTypeUnknown
,
488 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix
) +
489 base::ASCIIToUTF16(kUserDeniedPermissionMessage
)));
493 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
494 if (GetContext()->storage()->IsDisabled()) {
495 SendGetRegistrationError(thread_id
, request_id
, SERVICE_WORKER_ERROR_ABORT
);
499 TRACE_EVENT_ASYNC_BEGIN1(
501 "ServiceWorkerDispatcherHost::GetRegistration",
503 "Document URL", document_url
.spec());
505 GetContext()->storage()->FindRegistrationForDocument(
507 base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationComplete
,
514 void ServiceWorkerDispatcherHost::OnGetRegistrationForReady(
518 TRACE_EVENT0("ServiceWorker",
519 "ServiceWorkerDispatcherHost::OnGetRegistrationForReady");
522 ServiceWorkerProviderHost
* provider_host
=
523 GetContext()->GetProviderHost(render_process_id_
, provider_id
);
524 if (!provider_host
) {
525 BadMessageReceived();
528 if (!provider_host
->IsContextAlive())
531 TRACE_EVENT_ASYNC_BEGIN0(
533 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
536 if (!provider_host
->GetRegistrationForReady(base::Bind(
537 &ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete
,
538 this, thread_id
, request_id
, provider_host
->AsWeakPtr()))) {
539 BadMessageReceived();
543 void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
545 const base::string16
& message
,
546 const std::vector
<TransferredMessagePort
>& sent_message_ports
) {
547 TRACE_EVENT0("ServiceWorker",
548 "ServiceWorkerDispatcherHost::OnPostMessageToWorker");
552 ServiceWorkerHandle
* handle
= handles_
.Lookup(handle_id
);
554 BadMessageReceived();
558 handle
->version()->DispatchMessageEvent(
559 message
, sent_message_ports
,
560 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback
));
563 void ServiceWorkerDispatcherHost::OnProviderCreated(
566 ServiceWorkerProviderType provider_type
) {
567 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
568 tracked_objects::ScopedTracker
tracking_profile(
569 FROM_HERE_WITH_EXPLICIT_FUNCTION(
570 "477117 ServiceWorkerDispatcherHost::OnProviderCreated"));
571 TRACE_EVENT0("ServiceWorker",
572 "ServiceWorkerDispatcherHost::OnProviderCreated");
575 if (GetContext()->GetProviderHost(render_process_id_
, provider_id
)) {
576 BadMessageReceived();
579 scoped_ptr
<ServiceWorkerProviderHost
> provider_host(
580 new ServiceWorkerProviderHost(render_process_id_
,
584 GetContext()->AsWeakPtr(),
586 GetContext()->AddProviderHost(provider_host
.Pass());
589 void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id
) {
590 TRACE_EVENT0("ServiceWorker",
591 "ServiceWorkerDispatcherHost::OnProviderDestroyed");
594 if (!GetContext()->GetProviderHost(render_process_id_
, provider_id
)) {
595 BadMessageReceived();
598 GetContext()->RemoveProviderHost(render_process_id_
, provider_id
);
601 void ServiceWorkerDispatcherHost::OnSetHostedVersionId(
602 int provider_id
, int64 version_id
) {
603 TRACE_EVENT0("ServiceWorker",
604 "ServiceWorkerDispatcherHost::OnSetHostedVersionId");
607 ServiceWorkerProviderHost
* provider_host
=
608 GetContext()->GetProviderHost(render_process_id_
, provider_id
);
609 if (!provider_host
) {
610 BadMessageReceived();
613 if (!provider_host
->IsContextAlive())
615 if (!provider_host
->SetHostedVersionId(version_id
))
616 BadMessageReceived();
618 ServiceWorkerVersion
* version
= GetContext()->GetLiveVersion(version_id
);
622 // Retrieve the registration associated with |version|. The registration
623 // must be alive because the version keeps it during starting worker.
624 ServiceWorkerRegistration
* registration
=
625 GetContext()->GetLiveRegistration(version
->registration_id());
626 DCHECK(registration
);
627 // TODO(ksakamoto): This is a quick fix for crbug.com/459916.
631 // Set the document URL to the script url in order to allow
632 // register/unregister/getRegistration on ServiceWorkerGlobalScope.
633 provider_host
->SetDocumentUrl(version
->script_url());
635 ServiceWorkerRegistrationObjectInfo info
;
636 ServiceWorkerVersionAttributes attrs
;
637 GetRegistrationObjectInfoAndVersionAttributes(
638 provider_host
->AsWeakPtr(), registration
, &info
, &attrs
);
640 Send(new ServiceWorkerMsg_AssociateRegistrationWithServiceWorker(
641 kDocumentMainThreadId
, provider_id
, info
, attrs
));
644 ServiceWorkerRegistrationHandle
*
645 ServiceWorkerDispatcherHost::FindRegistrationHandle(int provider_id
,
646 int64 registration_id
) {
647 for (IDMap
<ServiceWorkerRegistrationHandle
, IDMapOwnPointer
>::iterator
648 iter(®istration_handles_
);
651 ServiceWorkerRegistrationHandle
* handle
= iter
.GetCurrentValue();
653 DCHECK(handle
->registration());
654 if (handle
->provider_id() == provider_id
&&
655 handle
->registration()->id() == registration_id
) {
662 void ServiceWorkerDispatcherHost::GetRegistrationObjectInfoAndVersionAttributes(
663 base::WeakPtr
<ServiceWorkerProviderHost
> provider_host
,
664 ServiceWorkerRegistration
* registration
,
665 ServiceWorkerRegistrationObjectInfo
* info
,
666 ServiceWorkerVersionAttributes
* attrs
) {
667 ServiceWorkerRegistrationHandle
* handle
=
668 GetOrCreateRegistrationHandle(provider_host
, registration
);
669 *info
= handle
->GetObjectInfo();
671 attrs
->installing
= provider_host
->GetOrCreateServiceWorkerHandle(
672 registration
->installing_version());
673 attrs
->waiting
= provider_host
->GetOrCreateServiceWorkerHandle(
674 registration
->waiting_version());
675 attrs
->active
= provider_host
->GetOrCreateServiceWorkerHandle(
676 registration
->active_version());
679 void ServiceWorkerDispatcherHost::RegistrationComplete(
683 ServiceWorkerStatusCode status
,
684 const std::string
& status_message
,
685 int64 registration_id
) {
689 ServiceWorkerProviderHost
* provider_host
=
690 GetContext()->GetProviderHost(render_process_id_
, provider_id
);
692 return; // The provider has already been destroyed.
694 if (status
!= SERVICE_WORKER_OK
) {
695 SendRegistrationError(thread_id
, request_id
, status
, status_message
);
699 ServiceWorkerRegistration
* registration
=
700 GetContext()->GetLiveRegistration(registration_id
);
701 DCHECK(registration
);
703 ServiceWorkerRegistrationObjectInfo info
;
704 ServiceWorkerVersionAttributes attrs
;
705 GetRegistrationObjectInfoAndVersionAttributes(
706 provider_host
->AsWeakPtr(), registration
, &info
, &attrs
);
708 Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
709 thread_id
, request_id
, info
, attrs
));
710 TRACE_EVENT_ASYNC_END1("ServiceWorker",
711 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
717 void ServiceWorkerDispatcherHost::OnWorkerReadyForInspection(
718 int embedded_worker_id
) {
719 TRACE_EVENT0("ServiceWorker",
720 "ServiceWorkerDispatcherHost::OnWorkerReadyForInspection");
723 EmbeddedWorkerRegistry
* registry
= GetContext()->embedded_worker_registry();
724 if (!registry
->CanHandle(embedded_worker_id
))
726 registry
->OnWorkerReadyForInspection(render_process_id_
, embedded_worker_id
);
729 void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(
730 int embedded_worker_id
,
733 TRACE_EVENT0("ServiceWorker",
734 "ServiceWorkerDispatcherHost::OnWorkerScriptLoaded");
738 ServiceWorkerProviderHost
* provider_host
=
739 GetContext()->GetProviderHost(render_process_id_
, provider_id
);
740 if (!provider_host
) {
741 BadMessageReceived();
745 provider_host
->SetReadyToSendMessagesToWorker(thread_id
);
747 EmbeddedWorkerRegistry
* registry
= GetContext()->embedded_worker_registry();
748 if (!registry
->CanHandle(embedded_worker_id
))
750 registry
->OnWorkerScriptLoaded(
751 render_process_id_
, thread_id
, embedded_worker_id
);
754 void ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed(
755 int embedded_worker_id
) {
756 TRACE_EVENT0("ServiceWorker",
757 "ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed");
760 EmbeddedWorkerRegistry
* registry
= GetContext()->embedded_worker_registry();
761 if (!registry
->CanHandle(embedded_worker_id
))
763 registry
->OnWorkerScriptLoadFailed(render_process_id_
, embedded_worker_id
);
766 void ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated(
767 int embedded_worker_id
,
769 TRACE_EVENT0("ServiceWorker",
770 "ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated");
773 EmbeddedWorkerRegistry
* registry
= GetContext()->embedded_worker_registry();
774 if (!registry
->CanHandle(embedded_worker_id
))
776 registry
->OnWorkerScriptEvaluated(
777 render_process_id_
, embedded_worker_id
, success
);
780 void ServiceWorkerDispatcherHost::OnWorkerStarted(int embedded_worker_id
) {
781 TRACE_EVENT0("ServiceWorker",
782 "ServiceWorkerDispatcherHost::OnWorkerStarted");
785 EmbeddedWorkerRegistry
* registry
= GetContext()->embedded_worker_registry();
786 if (!registry
->CanHandle(embedded_worker_id
))
788 registry
->OnWorkerStarted(render_process_id_
, embedded_worker_id
);
791 void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id
) {
792 TRACE_EVENT0("ServiceWorker",
793 "ServiceWorkerDispatcherHost::OnWorkerStopped");
796 EmbeddedWorkerRegistry
* registry
= GetContext()->embedded_worker_registry();
797 if (!registry
->CanHandle(embedded_worker_id
))
799 registry
->OnWorkerStopped(render_process_id_
, embedded_worker_id
);
802 void ServiceWorkerDispatcherHost::OnPausedAfterDownload(
803 int embedded_worker_id
) {
804 TRACE_EVENT0("ServiceWorker",
805 "ServiceWorkerDispatcherHost::OnPausedAfterDownload");
808 GetContext()->embedded_worker_registry()->OnPausedAfterDownload(
809 render_process_id_
, embedded_worker_id
);
812 void ServiceWorkerDispatcherHost::OnReportException(
813 int embedded_worker_id
,
814 const base::string16
& error_message
,
817 const GURL
& source_url
) {
818 TRACE_EVENT0("ServiceWorker",
819 "ServiceWorkerDispatcherHost::OnReportException");
822 EmbeddedWorkerRegistry
* registry
= GetContext()->embedded_worker_registry();
823 if (!registry
->CanHandle(embedded_worker_id
))
825 registry
->OnReportException(embedded_worker_id
,
832 void ServiceWorkerDispatcherHost::OnReportConsoleMessage(
833 int embedded_worker_id
,
834 const EmbeddedWorkerHostMsg_ReportConsoleMessage_Params
& params
) {
835 TRACE_EVENT0("ServiceWorker",
836 "ServiceWorkerDispatcherHost::OnReportConsoleMessage");
839 EmbeddedWorkerRegistry
* registry
= GetContext()->embedded_worker_registry();
840 if (!registry
->CanHandle(embedded_worker_id
))
842 registry
->OnReportConsoleMessage(embedded_worker_id
,
843 params
.source_identifier
,
844 params
.message_level
,
850 void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
852 TRACE_EVENT0("ServiceWorker",
853 "ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount");
854 ServiceWorkerHandle
* handle
= handles_
.Lookup(handle_id
);
856 BadMessageReceived();
859 handle
->IncrementRefCount();
862 void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
864 TRACE_EVENT0("ServiceWorker",
865 "ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount");
866 ServiceWorkerHandle
* handle
= handles_
.Lookup(handle_id
);
868 BadMessageReceived();
871 handle
->DecrementRefCount();
872 if (handle
->HasNoRefCount())
873 handles_
.Remove(handle_id
);
876 void ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount(
877 int registration_handle_id
) {
878 TRACE_EVENT0("ServiceWorker",
879 "ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount");
880 ServiceWorkerRegistrationHandle
* handle
=
881 registration_handles_
.Lookup(registration_handle_id
);
883 BadMessageReceived();
886 handle
->IncrementRefCount();
889 void ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount(
890 int registration_handle_id
) {
891 TRACE_EVENT0("ServiceWorker",
892 "ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount");
893 ServiceWorkerRegistrationHandle
* handle
=
894 registration_handles_
.Lookup(registration_handle_id
);
896 BadMessageReceived();
899 handle
->DecrementRefCount();
900 if (handle
->HasNoRefCount())
901 registration_handles_
.Remove(registration_handle_id
);
904 void ServiceWorkerDispatcherHost::UnregistrationComplete(
907 ServiceWorkerStatusCode status
) {
908 if (status
!= SERVICE_WORKER_OK
&& status
!= SERVICE_WORKER_ERROR_NOT_FOUND
) {
909 SendUnregistrationError(thread_id
, request_id
, status
);
912 const bool is_success
= (status
== SERVICE_WORKER_OK
);
913 Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id
,
916 TRACE_EVENT_ASYNC_END1(
918 "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
923 void ServiceWorkerDispatcherHost::GetRegistrationComplete(
927 ServiceWorkerStatusCode status
,
928 const scoped_refptr
<ServiceWorkerRegistration
>& registration
) {
929 TRACE_EVENT_ASYNC_END1("ServiceWorker",
930 "ServiceWorkerDispatcherHost::GetRegistration",
933 registration
.get() ? registration
->id()
934 : kInvalidServiceWorkerRegistrationId
);
939 ServiceWorkerProviderHost
* provider_host
=
940 GetContext()->GetProviderHost(render_process_id_
, provider_id
);
942 return; // The provider has already been destroyed.
944 if (status
!= SERVICE_WORKER_OK
&& status
!= SERVICE_WORKER_ERROR_NOT_FOUND
) {
945 SendGetRegistrationError(thread_id
, request_id
, status
);
949 ServiceWorkerRegistrationObjectInfo info
;
950 ServiceWorkerVersionAttributes attrs
;
951 if (status
== SERVICE_WORKER_OK
) {
952 DCHECK(registration
.get());
953 if (!registration
->is_uninstalling()) {
954 GetRegistrationObjectInfoAndVersionAttributes(
955 provider_host
->AsWeakPtr(), registration
.get(), &info
, &attrs
);
959 Send(new ServiceWorkerMsg_DidGetRegistration(
960 thread_id
, request_id
, info
, attrs
));
963 void ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete(
966 base::WeakPtr
<ServiceWorkerProviderHost
> provider_host
,
967 ServiceWorkerRegistration
* registration
) {
968 DCHECK(registration
);
969 TRACE_EVENT_ASYNC_END1("ServiceWorker",
970 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
973 registration
? registration
->id()
974 : kInvalidServiceWorkerRegistrationId
);
979 ServiceWorkerRegistrationObjectInfo info
;
980 ServiceWorkerVersionAttributes attrs
;
981 GetRegistrationObjectInfoAndVersionAttributes(
982 provider_host
, registration
, &info
, &attrs
);
983 Send(new ServiceWorkerMsg_DidGetRegistrationForReady(
984 thread_id
, request_id
, info
, attrs
));
987 void ServiceWorkerDispatcherHost::SendRegistrationError(
990 ServiceWorkerStatusCode status
,
991 const std::string
& status_message
) {
992 base::string16 error_message
;
993 blink::WebServiceWorkerError::ErrorType error_type
;
994 GetServiceWorkerRegistrationStatusResponse(status
, status_message
,
995 &error_type
, &error_message
);
996 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
997 thread_id
, request_id
, error_type
,
998 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix
) + error_message
));
1001 void ServiceWorkerDispatcherHost::SendUnregistrationError(
1004 ServiceWorkerStatusCode status
) {
1005 base::string16 error_message
;
1006 blink::WebServiceWorkerError::ErrorType error_type
;
1007 GetServiceWorkerRegistrationStatusResponse(status
, std::string(), &error_type
,
1009 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
1010 thread_id
, request_id
, error_type
,
1011 base::ASCIIToUTF16(kServiceWorkerUnregisterErrorPrefix
) + error_message
));
1014 void ServiceWorkerDispatcherHost::SendGetRegistrationError(
1017 ServiceWorkerStatusCode status
) {
1018 base::string16 error_message
;
1019 blink::WebServiceWorkerError::ErrorType error_type
;
1020 GetServiceWorkerRegistrationStatusResponse(status
, std::string(), &error_type
,
1022 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
1023 thread_id
, request_id
, error_type
,
1024 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix
) +
1028 ServiceWorkerContextCore
* ServiceWorkerDispatcherHost::GetContext() {
1029 if (!context_wrapper_
.get())
1031 return context_wrapper_
->context();
1034 void ServiceWorkerDispatcherHost::OnTerminateWorker(int handle_id
) {
1035 ServiceWorkerHandle
* handle
= handles_
.Lookup(handle_id
);
1037 BadMessageReceived();
1040 handle
->version()->StopWorker(
1041 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback
));
1044 } // namespace content