ServiceWorker: Stop exposing ServiceWorkerContextCore
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_dispatcher_host.cc
blob3340f871853af14d17d1567f3b6680e016326c36
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"
28 #include "url/gurl.h"
30 using blink::WebServiceWorkerError;
32 namespace content {
34 namespace {
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,
62 const GURL& pattern,
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);
91 } // namespace
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() {
106 if (GetContext()) {
107 GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
108 GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
109 render_process_id_);
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)));
120 return;
123 context_wrapper_ = context_wrapper;
124 if (!GetContext())
125 return;
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.
144 if (GetContext()) {
145 GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
146 GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
147 render_process_id_);
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) {
159 bool handled = true;
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,
166 OnGetRegistration)
167 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistrationForReady,
168 OnGetRegistrationForReady)
169 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderCreated,
170 OnProviderCreated)
171 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed,
172 OnProviderDestroyed)
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,
186 OnWorkerStarted)
187 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped,
188 OnWorkerStopped)
189 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_DidPauseAfterDownload,
190 OnPausedAfterDownload)
191 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportException,
192 OnReportException)
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_);
210 if (!handled)
211 BadMessageReceived();
214 return handled;
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.
221 return true;
224 pending_messages_.push_back(message);
225 return true;
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(
241 int provider_id,
242 int64 version_id) {
243 for (IDMap<ServiceWorkerHandle, IDMapOwnPointer>::iterator iter(&handles_);
244 !iter.IsAtEnd(); iter.Advance()) {
245 ServiceWorkerHandle* handle = iter.GetCurrentValue();
246 DCHECK(handle);
247 DCHECK(handle->version());
248 if (handle->provider_id() == provider_id &&
249 handle->version()->version_id() == version_id) {
250 return handle;
253 return NULL;
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());
263 if (handle) {
264 handle->IncrementRefCount();
265 return handle;
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());
273 return handle;
276 void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
277 int thread_id,
278 int request_id,
279 int provider_id,
280 const GURL& pattern,
281 const GURL& script_url) {
282 TRACE_EVENT0("ServiceWorker",
283 "ServiceWorkerDispatcherHost::OnRegisterServiceWorker");
284 if (!GetContext()) {
285 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
286 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
287 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
288 base::ASCIIToUTF16(kShutdownErrorMessage)));
289 return;
291 if (!pattern.is_valid() || !script_url.is_valid()) {
292 BadMessageReceived();
293 return;
296 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
297 render_process_id_, provider_id);
298 if (!provider_host) {
299 BadMessageReceived();
300 return;
302 if (!provider_host->IsContextAlive()) {
303 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
304 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
305 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
306 base::ASCIIToUTF16(kShutdownErrorMessage)));
307 return;
310 // TODO(ksakamoto): Currently, document_url is empty if the document is in an
311 // IFRAME using frame.contentDocument.write(...). We can remove this check
312 // once crbug.com/439697 is fixed.
313 if (provider_host->document_url().is_empty()) {
314 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
315 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
316 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
317 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
318 return;
321 if (!CanRegisterServiceWorker(
322 provider_host->document_url(), pattern, script_url)) {
323 BadMessageReceived();
324 return;
327 std::string error_message;
328 if (ServiceWorkerUtils::ContainsDisallowedCharacter(pattern, script_url,
329 &error_message)) {
330 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
331 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
332 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
333 base::UTF8ToUTF16(error_message)));
334 return;
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)));
343 return;
346 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
347 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
348 request_id,
349 "Pattern", pattern.spec(),
350 "Script URL", script_url.spec());
351 GetContext()->RegisterServiceWorker(
352 pattern,
353 script_url,
354 provider_host,
355 base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete,
356 this,
357 thread_id,
358 provider_id,
359 request_id));
362 void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
363 int thread_id,
364 int request_id,
365 int provider_id,
366 const GURL& pattern) {
367 TRACE_EVENT0("ServiceWorker",
368 "ServiceWorkerDispatcherHost::OnUnregisterServiceWorker");
369 if (!GetContext()) {
370 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
371 thread_id,
372 request_id,
373 blink::WebServiceWorkerError::ErrorTypeAbort,
374 base::ASCIIToUTF16(kShutdownErrorMessage)));
375 return;
377 if (!pattern.is_valid()) {
378 BadMessageReceived();
379 return;
382 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
383 render_process_id_, provider_id);
384 if (!provider_host) {
385 BadMessageReceived();
386 return;
388 if (!provider_host->IsContextAlive()) {
389 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
390 thread_id,
391 request_id,
392 blink::WebServiceWorkerError::ErrorTypeAbort,
393 base::ASCIIToUTF16(kShutdownErrorMessage)));
394 return;
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(
400 thread_id,
401 request_id,
402 WebServiceWorkerError::ErrorTypeSecurity,
403 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
404 return;
407 if (!CanUnregisterServiceWorker(provider_host->document_url(), pattern)) {
408 BadMessageReceived();
409 return;
412 if (!GetContentClient()->browser()->AllowServiceWorker(
413 pattern, provider_host->topmost_frame_url(), resource_context_)) {
414 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
415 thread_id,
416 request_id,
417 WebServiceWorkerError::ErrorTypeUnknown,
418 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
419 return;
422 TRACE_EVENT_ASYNC_BEGIN1(
423 "ServiceWorker",
424 "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
425 request_id,
426 "Pattern", pattern.spec());
427 GetContext()->UnregisterServiceWorker(
428 pattern,
429 base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete,
430 this,
431 thread_id,
432 request_id));
435 void ServiceWorkerDispatcherHost::OnGetRegistration(
436 int thread_id,
437 int request_id,
438 int provider_id,
439 const GURL& document_url) {
440 TRACE_EVENT0("ServiceWorker",
441 "ServiceWorkerDispatcherHost::OnGetRegistration");
442 if (!GetContext()) {
443 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
444 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
445 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
446 base::ASCIIToUTF16(kShutdownErrorMessage)));
447 return;
449 if (!document_url.is_valid()) {
450 BadMessageReceived();
451 return;
454 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
455 render_process_id_, provider_id);
456 if (!provider_host) {
457 BadMessageReceived();
458 return;
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)));
465 return;
468 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
469 if (provider_host->document_url().is_empty()) {
470 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
471 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
472 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
473 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
474 return;
477 if (!CanGetRegistration(provider_host->document_url(), document_url)) {
478 BadMessageReceived();
479 return;
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)));
490 return;
493 DCHECK_CURRENTLY_ON(BrowserThread::IO);
494 if (GetContext()->storage()->IsDisabled()) {
495 SendGetRegistrationError(thread_id, request_id, SERVICE_WORKER_ERROR_ABORT);
496 return;
499 TRACE_EVENT_ASYNC_BEGIN1(
500 "ServiceWorker",
501 "ServiceWorkerDispatcherHost::GetRegistration",
502 request_id,
503 "Document URL", document_url.spec());
505 GetContext()->storage()->FindRegistrationForDocument(
506 document_url,
507 base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationComplete,
508 this,
509 thread_id,
510 provider_id,
511 request_id));
514 void ServiceWorkerDispatcherHost::OnGetRegistrationForReady(
515 int thread_id,
516 int request_id,
517 int provider_id) {
518 TRACE_EVENT0("ServiceWorker",
519 "ServiceWorkerDispatcherHost::OnGetRegistrationForReady");
520 if (!GetContext())
521 return;
522 ServiceWorkerProviderHost* provider_host =
523 GetContext()->GetProviderHost(render_process_id_, provider_id);
524 if (!provider_host) {
525 BadMessageReceived();
526 return;
528 if (!provider_host->IsContextAlive())
529 return;
531 TRACE_EVENT_ASYNC_BEGIN0(
532 "ServiceWorker",
533 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
534 request_id);
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(
544 int handle_id,
545 const base::string16& message,
546 const std::vector<TransferredMessagePort>& sent_message_ports) {
547 TRACE_EVENT0("ServiceWorker",
548 "ServiceWorkerDispatcherHost::OnPostMessageToWorker");
549 if (!GetContext())
550 return;
552 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
553 if (!handle) {
554 BadMessageReceived();
555 return;
558 handle->version()->DispatchMessageEvent(
559 message, sent_message_ports,
560 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
563 void ServiceWorkerDispatcherHost::OnProviderCreated(
564 int provider_id,
565 int render_frame_id,
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");
573 if (!GetContext())
574 return;
575 if (GetContext()->GetProviderHost(render_process_id_, provider_id)) {
576 BadMessageReceived();
577 return;
579 scoped_ptr<ServiceWorkerProviderHost> provider_host(
580 new ServiceWorkerProviderHost(render_process_id_,
581 render_frame_id,
582 provider_id,
583 provider_type,
584 GetContext()->AsWeakPtr(),
585 this));
586 GetContext()->AddProviderHost(provider_host.Pass());
589 void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
590 TRACE_EVENT0("ServiceWorker",
591 "ServiceWorkerDispatcherHost::OnProviderDestroyed");
592 if (!GetContext())
593 return;
594 if (!GetContext()->GetProviderHost(render_process_id_, provider_id)) {
595 BadMessageReceived();
596 return;
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");
605 if (!GetContext())
606 return;
607 ServiceWorkerProviderHost* provider_host =
608 GetContext()->GetProviderHost(render_process_id_, provider_id);
609 if (!provider_host) {
610 BadMessageReceived();
611 return;
613 if (!provider_host->IsContextAlive())
614 return;
615 if (!provider_host->SetHostedVersionId(version_id))
616 BadMessageReceived();
618 ServiceWorkerVersion* version = GetContext()->GetLiveVersion(version_id);
619 if (!version)
620 return;
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.
628 if (!registration)
629 return;
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(&registration_handles_);
649 !iter.IsAtEnd();
650 iter.Advance()) {
651 ServiceWorkerRegistrationHandle* handle = iter.GetCurrentValue();
652 DCHECK(handle);
653 DCHECK(handle->registration());
654 if (handle->provider_id() == provider_id &&
655 handle->registration()->id() == registration_id) {
656 return handle;
659 return NULL;
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(
680 int thread_id,
681 int provider_id,
682 int request_id,
683 ServiceWorkerStatusCode status,
684 const std::string& status_message,
685 int64 registration_id) {
686 if (!GetContext())
687 return;
689 ServiceWorkerProviderHost* provider_host =
690 GetContext()->GetProviderHost(render_process_id_, provider_id);
691 if (!provider_host)
692 return; // The provider has already been destroyed.
694 if (status != SERVICE_WORKER_OK) {
695 SendRegistrationError(thread_id, request_id, status, status_message);
696 return;
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",
712 request_id,
713 "Registration ID",
714 registration_id);
717 void ServiceWorkerDispatcherHost::OnWorkerReadyForInspection(
718 int embedded_worker_id) {
719 TRACE_EVENT0("ServiceWorker",
720 "ServiceWorkerDispatcherHost::OnWorkerReadyForInspection");
721 if (!GetContext())
722 return;
723 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
724 if (!registry->CanHandle(embedded_worker_id))
725 return;
726 registry->OnWorkerReadyForInspection(render_process_id_, embedded_worker_id);
729 void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(
730 int embedded_worker_id,
731 int thread_id,
732 int provider_id) {
733 TRACE_EVENT0("ServiceWorker",
734 "ServiceWorkerDispatcherHost::OnWorkerScriptLoaded");
735 if (!GetContext())
736 return;
738 ServiceWorkerProviderHost* provider_host =
739 GetContext()->GetProviderHost(render_process_id_, provider_id);
740 if (!provider_host) {
741 BadMessageReceived();
742 return;
745 provider_host->SetReadyToSendMessagesToWorker(thread_id);
747 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
748 if (!registry->CanHandle(embedded_worker_id))
749 return;
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");
758 if (!GetContext())
759 return;
760 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
761 if (!registry->CanHandle(embedded_worker_id))
762 return;
763 registry->OnWorkerScriptLoadFailed(render_process_id_, embedded_worker_id);
766 void ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated(
767 int embedded_worker_id,
768 bool success) {
769 TRACE_EVENT0("ServiceWorker",
770 "ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated");
771 if (!GetContext())
772 return;
773 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
774 if (!registry->CanHandle(embedded_worker_id))
775 return;
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");
783 if (!GetContext())
784 return;
785 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
786 if (!registry->CanHandle(embedded_worker_id))
787 return;
788 registry->OnWorkerStarted(render_process_id_, embedded_worker_id);
791 void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) {
792 TRACE_EVENT0("ServiceWorker",
793 "ServiceWorkerDispatcherHost::OnWorkerStopped");
794 if (!GetContext())
795 return;
796 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
797 if (!registry->CanHandle(embedded_worker_id))
798 return;
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");
806 if (!GetContext())
807 return;
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,
815 int line_number,
816 int column_number,
817 const GURL& source_url) {
818 TRACE_EVENT0("ServiceWorker",
819 "ServiceWorkerDispatcherHost::OnReportException");
820 if (!GetContext())
821 return;
822 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
823 if (!registry->CanHandle(embedded_worker_id))
824 return;
825 registry->OnReportException(embedded_worker_id,
826 error_message,
827 line_number,
828 column_number,
829 source_url);
832 void ServiceWorkerDispatcherHost::OnReportConsoleMessage(
833 int embedded_worker_id,
834 const EmbeddedWorkerHostMsg_ReportConsoleMessage_Params& params) {
835 TRACE_EVENT0("ServiceWorker",
836 "ServiceWorkerDispatcherHost::OnReportConsoleMessage");
837 if (!GetContext())
838 return;
839 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
840 if (!registry->CanHandle(embedded_worker_id))
841 return;
842 registry->OnReportConsoleMessage(embedded_worker_id,
843 params.source_identifier,
844 params.message_level,
845 params.message,
846 params.line_number,
847 params.source_url);
850 void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
851 int handle_id) {
852 TRACE_EVENT0("ServiceWorker",
853 "ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount");
854 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
855 if (!handle) {
856 BadMessageReceived();
857 return;
859 handle->IncrementRefCount();
862 void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
863 int handle_id) {
864 TRACE_EVENT0("ServiceWorker",
865 "ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount");
866 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
867 if (!handle) {
868 BadMessageReceived();
869 return;
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);
882 if (!handle) {
883 BadMessageReceived();
884 return;
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);
895 if (!handle) {
896 BadMessageReceived();
897 return;
899 handle->DecrementRefCount();
900 if (handle->HasNoRefCount())
901 registration_handles_.Remove(registration_handle_id);
904 void ServiceWorkerDispatcherHost::UnregistrationComplete(
905 int thread_id,
906 int request_id,
907 ServiceWorkerStatusCode status) {
908 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
909 SendUnregistrationError(thread_id, request_id, status);
910 return;
912 const bool is_success = (status == SERVICE_WORKER_OK);
913 Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id,
914 request_id,
915 is_success));
916 TRACE_EVENT_ASYNC_END1(
917 "ServiceWorker",
918 "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
919 request_id,
920 "Status", status);
923 void ServiceWorkerDispatcherHost::GetRegistrationComplete(
924 int thread_id,
925 int provider_id,
926 int request_id,
927 ServiceWorkerStatusCode status,
928 const scoped_refptr<ServiceWorkerRegistration>& registration) {
929 TRACE_EVENT_ASYNC_END1("ServiceWorker",
930 "ServiceWorkerDispatcherHost::GetRegistration",
931 request_id,
932 "Registration ID",
933 registration.get() ? registration->id()
934 : kInvalidServiceWorkerRegistrationId);
936 if (!GetContext())
937 return;
939 ServiceWorkerProviderHost* provider_host =
940 GetContext()->GetProviderHost(render_process_id_, provider_id);
941 if (!provider_host)
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);
946 return;
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(
964 int thread_id,
965 int request_id,
966 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
967 ServiceWorkerRegistration* registration) {
968 DCHECK(registration);
969 TRACE_EVENT_ASYNC_END1("ServiceWorker",
970 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
971 request_id,
972 "Registration ID",
973 registration ? registration->id()
974 : kInvalidServiceWorkerRegistrationId);
976 if (!GetContext())
977 return;
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(
988 int thread_id,
989 int request_id,
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(
1002 int thread_id,
1003 int request_id,
1004 ServiceWorkerStatusCode status) {
1005 base::string16 error_message;
1006 blink::WebServiceWorkerError::ErrorType error_type;
1007 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
1008 &error_message);
1009 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
1010 thread_id, request_id, error_type,
1011 base::ASCIIToUTF16(kServiceWorkerUnregisterErrorPrefix) + error_message));
1014 void ServiceWorkerDispatcherHost::SendGetRegistrationError(
1015 int thread_id,
1016 int request_id,
1017 ServiceWorkerStatusCode status) {
1018 base::string16 error_message;
1019 blink::WebServiceWorkerError::ErrorType error_type;
1020 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
1021 &error_message);
1022 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
1023 thread_id, request_id, error_type,
1024 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
1025 error_message));
1028 ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
1029 if (!context_wrapper_.get())
1030 return nullptr;
1031 return context_wrapper_->context();
1034 void ServiceWorkerDispatcherHost::OnTerminateWorker(int handle_id) {
1035 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
1036 if (!handle) {
1037 BadMessageReceived();
1038 return;
1040 handle->version()->StopWorker(
1041 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
1044 } // namespace content