Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_dispatcher_host.cc
blob2c4c774ef966ff89826e702f15a3b9b68dd11fc8
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/service_worker/service_worker_dispatcher_host.h"
7 #include "base/logging.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/trace_event/trace_event.h"
10 #include "content/browser/message_port_message_filter.h"
11 #include "content/browser/message_port_service.h"
12 #include "content/browser/service_worker/embedded_worker_registry.h"
13 #include "content/browser/service_worker/service_worker_context_core.h"
14 #include "content/browser/service_worker/service_worker_context_wrapper.h"
15 #include "content/browser/service_worker/service_worker_handle.h"
16 #include "content/browser/service_worker/service_worker_registration.h"
17 #include "content/browser/service_worker/service_worker_registration_handle.h"
18 #include "content/browser/service_worker/service_worker_utils.h"
19 #include "content/common/service_worker/embedded_worker_messages.h"
20 #include "content/common/service_worker/service_worker_messages.h"
21 #include "content/common/service_worker/service_worker_types.h"
22 #include "content/public/browser/content_browser_client.h"
23 #include "content/public/common/content_client.h"
24 #include "ipc/ipc_message_macros.h"
25 #include "net/base/net_util.h"
26 #include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
27 #include "url/gurl.h"
29 using blink::WebServiceWorkerError;
31 namespace content {
33 namespace {
35 const char kNoDocumentURLErrorMessage[] =
36 "No URL is associated with the caller's document.";
37 const char kShutdownErrorMessage[] =
38 "The Service Worker system has shutdown.";
39 const char kUserDeniedPermissionMessage[] =
40 "The user denied permission to use Service Worker.";
42 const uint32 kFilteredMessageClasses[] = {
43 ServiceWorkerMsgStart,
44 EmbeddedWorkerMsgStart,
47 bool AllOriginsMatch(const GURL& url_a, const GURL& url_b, const GURL& url_c) {
48 return url_a.GetOrigin() == url_b.GetOrigin() &&
49 url_a.GetOrigin() == url_c.GetOrigin();
52 // TODO(dominicc): When crbug.com/362214 is fixed use that to be
53 // consistent with Blink's
54 // SecurityOrigin::canAccessFeatureRequiringSecureOrigin.
55 bool OriginCanAccessServiceWorkers(const GURL& url) {
56 return url.SchemeIsHTTPOrHTTPS() &&
57 (url.SchemeIsSecure() || net::IsLocalhost(url.host()));
60 bool CanRegisterServiceWorker(const GURL& document_url,
61 const GURL& pattern,
62 const GURL& script_url) {
63 DCHECK(document_url.is_valid());
64 DCHECK(pattern.is_valid());
65 DCHECK(script_url.is_valid());
66 return AllOriginsMatch(document_url, pattern, script_url) &&
67 OriginCanAccessServiceWorkers(document_url) &&
68 OriginCanAccessServiceWorkers(pattern) &&
69 OriginCanAccessServiceWorkers(script_url);
72 bool CanUnregisterServiceWorker(const GURL& document_url,
73 const GURL& pattern) {
74 DCHECK(document_url.is_valid());
75 DCHECK(pattern.is_valid());
76 return document_url.GetOrigin() == pattern.GetOrigin() &&
77 OriginCanAccessServiceWorkers(document_url) &&
78 OriginCanAccessServiceWorkers(pattern);
81 bool CanGetRegistration(const GURL& document_url,
82 const GURL& given_document_url) {
83 DCHECK(document_url.is_valid());
84 DCHECK(given_document_url.is_valid());
85 return document_url.GetOrigin() == given_document_url.GetOrigin() &&
86 OriginCanAccessServiceWorkers(document_url) &&
87 OriginCanAccessServiceWorkers(given_document_url);
90 } // namespace
92 ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
93 int render_process_id,
94 MessagePortMessageFilter* message_port_message_filter,
95 ResourceContext* resource_context)
96 : BrowserMessageFilter(kFilteredMessageClasses,
97 arraysize(kFilteredMessageClasses)),
98 render_process_id_(render_process_id),
99 message_port_message_filter_(message_port_message_filter),
100 resource_context_(resource_context),
101 channel_ready_(false) {
104 ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
105 if (GetContext()) {
106 GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
107 GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
108 render_process_id_);
112 void ServiceWorkerDispatcherHost::Init(
113 ServiceWorkerContextWrapper* context_wrapper) {
114 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
115 BrowserThread::PostTask(
116 BrowserThread::IO, FROM_HERE,
117 base::Bind(&ServiceWorkerDispatcherHost::Init,
118 this, make_scoped_refptr(context_wrapper)));
119 return;
122 context_wrapper_ = context_wrapper;
123 if (!GetContext())
124 return;
125 GetContext()->embedded_worker_registry()->AddChildProcessSender(
126 render_process_id_, this, message_port_message_filter_);
129 void ServiceWorkerDispatcherHost::OnFilterAdded(IPC::Sender* sender) {
130 TRACE_EVENT0("ServiceWorker",
131 "ServiceWorkerDispatcherHost::OnFilterAdded");
132 channel_ready_ = true;
133 std::vector<IPC::Message*> messages;
134 pending_messages_.release(&messages);
135 for (size_t i = 0; i < messages.size(); ++i) {
136 BrowserMessageFilter::Send(messages[i]);
140 void ServiceWorkerDispatcherHost::OnFilterRemoved() {
141 // Don't wait until the destructor to teardown since a new dispatcher host
142 // for this process might be created before then.
143 if (GetContext()) {
144 GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
145 GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
146 render_process_id_);
148 context_wrapper_ = nullptr;
149 channel_ready_ = false;
152 void ServiceWorkerDispatcherHost::OnDestruct() const {
153 BrowserThread::DeleteOnIOThread::Destruct(this);
156 bool ServiceWorkerDispatcherHost::OnMessageReceived(
157 const IPC::Message& message) {
158 bool handled = true;
159 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcherHost, message)
160 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_RegisterServiceWorker,
161 OnRegisterServiceWorker)
162 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_UnregisterServiceWorker,
163 OnUnregisterServiceWorker)
164 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistration,
165 OnGetRegistration)
166 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistrationForReady,
167 OnGetRegistrationForReady)
168 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderCreated,
169 OnProviderCreated)
170 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed,
171 OnProviderDestroyed)
172 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetVersionId,
173 OnSetHostedVersionId)
174 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToWorker,
175 OnPostMessageToWorker)
176 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerReadyForInspection,
177 OnWorkerReadyForInspection)
178 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoaded,
179 OnWorkerScriptLoaded)
180 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoadFailed,
181 OnWorkerScriptLoadFailed)
182 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptEvaluated,
183 OnWorkerScriptEvaluated)
184 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted,
185 OnWorkerStarted)
186 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped,
187 OnWorkerStopped)
188 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_DidPauseAfterDownload,
189 OnPausedAfterDownload)
190 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportException,
191 OnReportException)
192 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportConsoleMessage,
193 OnReportConsoleMessage)
194 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount,
195 OnIncrementServiceWorkerRefCount)
196 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount,
197 OnDecrementServiceWorkerRefCount)
198 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementRegistrationRefCount,
199 OnIncrementRegistrationRefCount)
200 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
201 OnDecrementRegistrationRefCount)
202 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_TerminateWorker, OnTerminateWorker)
203 IPC_MESSAGE_UNHANDLED(handled = false)
204 IPC_END_MESSAGE_MAP()
206 if (!handled && GetContext()) {
207 handled = GetContext()->embedded_worker_registry()->OnMessageReceived(
208 message, render_process_id_);
209 if (!handled)
210 BadMessageReceived();
213 return handled;
216 bool ServiceWorkerDispatcherHost::Send(IPC::Message* message) {
217 if (channel_ready_) {
218 BrowserMessageFilter::Send(message);
219 // Don't bother passing through Send()'s result: it's not reliable.
220 return true;
223 pending_messages_.push_back(message);
224 return true;
227 void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle(
228 scoped_ptr<ServiceWorkerHandle> handle) {
229 int handle_id = handle->handle_id();
230 handles_.AddWithID(handle.release(), handle_id);
233 void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationHandle(
234 scoped_ptr<ServiceWorkerRegistrationHandle> handle) {
235 int handle_id = handle->handle_id();
236 registration_handles_.AddWithID(handle.release(), handle_id);
239 ServiceWorkerHandle* ServiceWorkerDispatcherHost::FindServiceWorkerHandle(
240 int provider_id,
241 int64 version_id) {
242 for (IDMap<ServiceWorkerHandle, IDMapOwnPointer>::iterator iter(&handles_);
243 !iter.IsAtEnd(); iter.Advance()) {
244 ServiceWorkerHandle* handle = iter.GetCurrentValue();
245 DCHECK(handle);
246 DCHECK(handle->version());
247 if (handle->provider_id() == provider_id &&
248 handle->version()->version_id() == version_id) {
249 return handle;
252 return NULL;
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());
262 if (handle) {
263 handle->IncrementRefCount();
264 return handle;
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());
272 return handle;
275 void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
276 int thread_id,
277 int request_id,
278 int provider_id,
279 const GURL& pattern,
280 const GURL& script_url) {
281 TRACE_EVENT0("ServiceWorker",
282 "ServiceWorkerDispatcherHost::OnRegisterServiceWorker");
283 if (!GetContext()) {
284 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
285 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
286 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
287 base::ASCIIToUTF16(kShutdownErrorMessage)));
288 return;
290 if (!pattern.is_valid() || !script_url.is_valid()) {
291 BadMessageReceived();
292 return;
295 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
296 render_process_id_, provider_id);
297 if (!provider_host) {
298 BadMessageReceived();
299 return;
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)));
306 return;
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)));
317 return;
320 if (!CanRegisterServiceWorker(
321 provider_host->document_url(), pattern, script_url)) {
322 BadMessageReceived();
323 return;
326 std::string error_message;
327 if (ServiceWorkerUtils::ContainsDisallowedCharacter(pattern, script_url,
328 &error_message)) {
329 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
330 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
331 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
332 base::UTF8ToUTF16(error_message)));
333 return;
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)));
342 return;
345 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
346 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
347 request_id,
348 "Pattern", pattern.spec(),
349 "Script URL", script_url.spec());
350 GetContext()->RegisterServiceWorker(
351 pattern,
352 script_url,
353 provider_host,
354 base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete,
355 this,
356 thread_id,
357 provider_id,
358 request_id));
361 void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
362 int thread_id,
363 int request_id,
364 int provider_id,
365 const GURL& pattern) {
366 TRACE_EVENT0("ServiceWorker",
367 "ServiceWorkerDispatcherHost::OnUnregisterServiceWorker");
368 if (!GetContext()) {
369 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
370 thread_id,
371 request_id,
372 blink::WebServiceWorkerError::ErrorTypeAbort,
373 base::ASCIIToUTF16(kShutdownErrorMessage)));
374 return;
376 if (!pattern.is_valid()) {
377 BadMessageReceived();
378 return;
381 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
382 render_process_id_, provider_id);
383 if (!provider_host) {
384 BadMessageReceived();
385 return;
387 if (!provider_host->IsContextAlive()) {
388 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
389 thread_id,
390 request_id,
391 blink::WebServiceWorkerError::ErrorTypeAbort,
392 base::ASCIIToUTF16(kShutdownErrorMessage)));
393 return;
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(
399 thread_id,
400 request_id,
401 WebServiceWorkerError::ErrorTypeSecurity,
402 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
403 return;
406 if (!CanUnregisterServiceWorker(provider_host->document_url(), pattern)) {
407 BadMessageReceived();
408 return;
411 if (!GetContentClient()->browser()->AllowServiceWorker(
412 pattern, provider_host->topmost_frame_url(), resource_context_)) {
413 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
414 thread_id,
415 request_id,
416 WebServiceWorkerError::ErrorTypeUnknown,
417 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
418 return;
421 TRACE_EVENT_ASYNC_BEGIN1(
422 "ServiceWorker",
423 "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
424 request_id,
425 "Pattern", pattern.spec());
426 GetContext()->UnregisterServiceWorker(
427 pattern,
428 base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete,
429 this,
430 thread_id,
431 request_id));
434 void ServiceWorkerDispatcherHost::OnGetRegistration(
435 int thread_id,
436 int request_id,
437 int provider_id,
438 const GURL& document_url) {
439 TRACE_EVENT0("ServiceWorker",
440 "ServiceWorkerDispatcherHost::OnGetRegistration");
441 if (!GetContext()) {
442 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
443 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
444 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
445 base::ASCIIToUTF16(kShutdownErrorMessage)));
446 return;
448 if (!document_url.is_valid()) {
449 BadMessageReceived();
450 return;
453 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
454 render_process_id_, provider_id);
455 if (!provider_host) {
456 BadMessageReceived();
457 return;
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)));
464 return;
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)));
473 return;
476 if (!CanGetRegistration(provider_host->document_url(), document_url)) {
477 BadMessageReceived();
478 return;
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)));
489 return;
492 DCHECK_CURRENTLY_ON(BrowserThread::IO);
493 if (GetContext()->storage()->IsDisabled()) {
494 SendGetRegistrationError(thread_id, request_id, SERVICE_WORKER_ERROR_ABORT);
495 return;
498 TRACE_EVENT_ASYNC_BEGIN1(
499 "ServiceWorker",
500 "ServiceWorkerDispatcherHost::GetRegistration",
501 request_id,
502 "Document URL", document_url.spec());
504 GetContext()->storage()->FindRegistrationForDocument(
505 document_url,
506 base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationComplete,
507 this,
508 thread_id,
509 provider_id,
510 request_id));
513 void ServiceWorkerDispatcherHost::OnGetRegistrationForReady(
514 int thread_id,
515 int request_id,
516 int provider_id) {
517 TRACE_EVENT0("ServiceWorker",
518 "ServiceWorkerDispatcherHost::OnGetRegistrationForReady");
519 if (!GetContext())
520 return;
521 ServiceWorkerProviderHost* provider_host =
522 GetContext()->GetProviderHost(render_process_id_, provider_id);
523 if (!provider_host) {
524 BadMessageReceived();
525 return;
527 if (!provider_host->IsContextAlive())
528 return;
530 TRACE_EVENT_ASYNC_BEGIN0(
531 "ServiceWorker",
532 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
533 request_id);
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(
543 int handle_id,
544 const base::string16& message,
545 const std::vector<TransferredMessagePort>& sent_message_ports) {
546 TRACE_EVENT0("ServiceWorker",
547 "ServiceWorkerDispatcherHost::OnPostMessageToWorker");
548 if (!GetContext())
549 return;
551 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
552 if (!handle) {
553 BadMessageReceived();
554 return;
557 handle->version()->DispatchMessageEvent(
558 message, sent_message_ports,
559 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
562 void ServiceWorkerDispatcherHost::OnProviderCreated(
563 int provider_id,
564 int render_frame_id,
565 ServiceWorkerProviderType provider_type) {
566 TRACE_EVENT0("ServiceWorker",
567 "ServiceWorkerDispatcherHost::OnProviderCreated");
568 if (!GetContext())
569 return;
570 if (GetContext()->GetProviderHost(render_process_id_, provider_id)) {
571 BadMessageReceived();
572 return;
574 scoped_ptr<ServiceWorkerProviderHost> provider_host(
575 new ServiceWorkerProviderHost(render_process_id_,
576 render_frame_id,
577 provider_id,
578 provider_type,
579 GetContext()->AsWeakPtr(),
580 this));
581 GetContext()->AddProviderHost(provider_host.Pass());
584 void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
585 TRACE_EVENT0("ServiceWorker",
586 "ServiceWorkerDispatcherHost::OnProviderDestroyed");
587 if (!GetContext())
588 return;
589 if (!GetContext()->GetProviderHost(render_process_id_, provider_id)) {
590 BadMessageReceived();
591 return;
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");
600 if (!GetContext())
601 return;
602 ServiceWorkerProviderHost* provider_host =
603 GetContext()->GetProviderHost(render_process_id_, provider_id);
604 if (!provider_host) {
605 BadMessageReceived();
606 return;
608 if (!provider_host->IsContextAlive())
609 return;
610 if (!provider_host->SetHostedVersionId(version_id))
611 BadMessageReceived();
613 ServiceWorkerVersion* version = GetContext()->GetLiveVersion(version_id);
614 if (!version)
615 return;
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.
623 if (!registration)
624 return;
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(&registration_handles_);
644 !iter.IsAtEnd();
645 iter.Advance()) {
646 ServiceWorkerRegistrationHandle* handle = iter.GetCurrentValue();
647 DCHECK(handle);
648 DCHECK(handle->registration());
649 if (handle->provider_id() == provider_id &&
650 handle->registration()->id() == registration_id) {
651 return handle;
654 return NULL;
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(
675 int thread_id,
676 int provider_id,
677 int request_id,
678 ServiceWorkerStatusCode status,
679 const std::string& status_message,
680 int64 registration_id) {
681 if (!GetContext())
682 return;
684 ServiceWorkerProviderHost* provider_host =
685 GetContext()->GetProviderHost(render_process_id_, provider_id);
686 if (!provider_host)
687 return; // The provider has already been destroyed.
689 if (status != SERVICE_WORKER_OK) {
690 SendRegistrationError(thread_id, request_id, status, status_message);
691 return;
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",
707 request_id,
708 "Registration ID",
709 registration_id);
712 void ServiceWorkerDispatcherHost::OnWorkerReadyForInspection(
713 int embedded_worker_id) {
714 TRACE_EVENT0("ServiceWorker",
715 "ServiceWorkerDispatcherHost::OnWorkerReadyForInspection");
716 if (!GetContext())
717 return;
718 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
719 if (!registry->CanHandle(embedded_worker_id))
720 return;
721 registry->OnWorkerReadyForInspection(render_process_id_, embedded_worker_id);
724 void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(
725 int embedded_worker_id,
726 int thread_id,
727 int provider_id) {
728 TRACE_EVENT0("ServiceWorker",
729 "ServiceWorkerDispatcherHost::OnWorkerScriptLoaded");
730 if (!GetContext())
731 return;
733 ServiceWorkerProviderHost* provider_host =
734 GetContext()->GetProviderHost(render_process_id_, provider_id);
735 if (!provider_host) {
736 BadMessageReceived();
737 return;
740 provider_host->SetReadyToSendMessagesToWorker(thread_id);
742 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
743 if (!registry->CanHandle(embedded_worker_id))
744 return;
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");
753 if (!GetContext())
754 return;
755 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
756 if (!registry->CanHandle(embedded_worker_id))
757 return;
758 registry->OnWorkerScriptLoadFailed(render_process_id_, embedded_worker_id);
761 void ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated(
762 int embedded_worker_id,
763 bool success) {
764 TRACE_EVENT0("ServiceWorker",
765 "ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated");
766 if (!GetContext())
767 return;
768 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
769 if (!registry->CanHandle(embedded_worker_id))
770 return;
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");
778 if (!GetContext())
779 return;
780 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
781 if (!registry->CanHandle(embedded_worker_id))
782 return;
783 registry->OnWorkerStarted(render_process_id_, embedded_worker_id);
786 void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) {
787 TRACE_EVENT0("ServiceWorker",
788 "ServiceWorkerDispatcherHost::OnWorkerStopped");
789 if (!GetContext())
790 return;
791 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
792 if (!registry->CanHandle(embedded_worker_id))
793 return;
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");
801 if (!GetContext())
802 return;
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,
810 int line_number,
811 int column_number,
812 const GURL& source_url) {
813 TRACE_EVENT0("ServiceWorker",
814 "ServiceWorkerDispatcherHost::OnReportException");
815 if (!GetContext())
816 return;
817 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
818 if (!registry->CanHandle(embedded_worker_id))
819 return;
820 registry->OnReportException(embedded_worker_id,
821 error_message,
822 line_number,
823 column_number,
824 source_url);
827 void ServiceWorkerDispatcherHost::OnReportConsoleMessage(
828 int embedded_worker_id,
829 const EmbeddedWorkerHostMsg_ReportConsoleMessage_Params& params) {
830 TRACE_EVENT0("ServiceWorker",
831 "ServiceWorkerDispatcherHost::OnReportConsoleMessage");
832 if (!GetContext())
833 return;
834 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
835 if (!registry->CanHandle(embedded_worker_id))
836 return;
837 registry->OnReportConsoleMessage(embedded_worker_id,
838 params.source_identifier,
839 params.message_level,
840 params.message,
841 params.line_number,
842 params.source_url);
845 void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
846 int handle_id) {
847 TRACE_EVENT0("ServiceWorker",
848 "ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount");
849 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
850 if (!handle) {
851 BadMessageReceived();
852 return;
854 handle->IncrementRefCount();
857 void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
858 int handle_id) {
859 TRACE_EVENT0("ServiceWorker",
860 "ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount");
861 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
862 if (!handle) {
863 BadMessageReceived();
864 return;
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);
877 if (!handle) {
878 BadMessageReceived();
879 return;
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);
890 if (!handle) {
891 BadMessageReceived();
892 return;
894 handle->DecrementRefCount();
895 if (handle->HasNoRefCount())
896 registration_handles_.Remove(registration_handle_id);
899 void ServiceWorkerDispatcherHost::UnregistrationComplete(
900 int thread_id,
901 int request_id,
902 ServiceWorkerStatusCode status) {
903 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
904 SendUnregistrationError(thread_id, request_id, status);
905 return;
907 const bool is_success = (status == SERVICE_WORKER_OK);
908 Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id,
909 request_id,
910 is_success));
911 TRACE_EVENT_ASYNC_END1(
912 "ServiceWorker",
913 "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
914 request_id,
915 "Status", status);
918 void ServiceWorkerDispatcherHost::GetRegistrationComplete(
919 int thread_id,
920 int provider_id,
921 int request_id,
922 ServiceWorkerStatusCode status,
923 const scoped_refptr<ServiceWorkerRegistration>& registration) {
924 TRACE_EVENT_ASYNC_END1("ServiceWorker",
925 "ServiceWorkerDispatcherHost::GetRegistration",
926 request_id,
927 "Registration ID",
928 registration.get() ? registration->id()
929 : kInvalidServiceWorkerRegistrationId);
931 if (!GetContext())
932 return;
934 ServiceWorkerProviderHost* provider_host =
935 GetContext()->GetProviderHost(render_process_id_, provider_id);
936 if (!provider_host)
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);
941 return;
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(
959 int thread_id,
960 int request_id,
961 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
962 ServiceWorkerRegistration* registration) {
963 DCHECK(registration);
964 TRACE_EVENT_ASYNC_END1("ServiceWorker",
965 "ServiceWorkerDispatcherHost::GetRegistrationForReady",
966 request_id,
967 "Registration ID",
968 registration ? registration->id()
969 : kInvalidServiceWorkerRegistrationId);
971 if (!GetContext())
972 return;
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(
983 int thread_id,
984 int request_id,
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(
997 int thread_id,
998 int request_id,
999 ServiceWorkerStatusCode status) {
1000 base::string16 error_message;
1001 blink::WebServiceWorkerError::ErrorType error_type;
1002 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
1003 &error_message);
1004 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
1005 thread_id, request_id, error_type,
1006 base::ASCIIToUTF16(kServiceWorkerUnregisterErrorPrefix) + error_message));
1009 void ServiceWorkerDispatcherHost::SendGetRegistrationError(
1010 int thread_id,
1011 int request_id,
1012 ServiceWorkerStatusCode status) {
1013 base::string16 error_message;
1014 blink::WebServiceWorkerError::ErrorType error_type;
1015 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
1016 &error_message);
1017 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
1018 thread_id, request_id, error_type,
1019 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
1020 error_message));
1023 ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
1024 if (!context_wrapper_.get())
1025 return nullptr;
1026 return context_wrapper_->context();
1029 void ServiceWorkerDispatcherHost::OnTerminateWorker(int handle_id) {
1030 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
1031 if (!handle) {
1032 BadMessageReceived();
1033 return;
1035 handle->version()->StopWorker(
1036 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
1039 } // namespace content