[Ozone-Gbm] Explicitly crash if trying software rendering on GBM
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_dispatcher_host.cc
blob6f1d95f078618c9c207087699ef8b185bcc20c84
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_ProviderCreated,
167 OnProviderCreated)
168 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed,
169 OnProviderDestroyed)
170 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetVersionId,
171 OnSetHostedVersionId)
172 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToWorker,
173 OnPostMessageToWorker)
174 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerReadyForInspection,
175 OnWorkerReadyForInspection)
176 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoaded,
177 OnWorkerScriptLoaded)
178 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoadFailed,
179 OnWorkerScriptLoadFailed)
180 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptEvaluated,
181 OnWorkerScriptEvaluated)
182 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted,
183 OnWorkerStarted)
184 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped,
185 OnWorkerStopped)
186 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_DidPauseAfterDownload,
187 OnPausedAfterDownload)
188 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportException,
189 OnReportException)
190 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportConsoleMessage,
191 OnReportConsoleMessage)
192 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount,
193 OnIncrementServiceWorkerRefCount)
194 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount,
195 OnDecrementServiceWorkerRefCount)
196 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementRegistrationRefCount,
197 OnIncrementRegistrationRefCount)
198 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
199 OnDecrementRegistrationRefCount)
200 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_TerminateWorker, OnTerminateWorker)
201 IPC_MESSAGE_UNHANDLED(handled = false)
202 IPC_END_MESSAGE_MAP()
204 if (!handled && GetContext()) {
205 handled = GetContext()->embedded_worker_registry()->OnMessageReceived(
206 message, render_process_id_);
207 if (!handled)
208 BadMessageReceived();
211 return handled;
214 bool ServiceWorkerDispatcherHost::Send(IPC::Message* message) {
215 if (channel_ready_) {
216 BrowserMessageFilter::Send(message);
217 // Don't bother passing through Send()'s result: it's not reliable.
218 return true;
221 pending_messages_.push_back(message);
222 return true;
225 void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle(
226 scoped_ptr<ServiceWorkerHandle> handle) {
227 int handle_id = handle->handle_id();
228 handles_.AddWithID(handle.release(), handle_id);
231 void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationHandle(
232 scoped_ptr<ServiceWorkerRegistrationHandle> handle) {
233 int handle_id = handle->handle_id();
234 registration_handles_.AddWithID(handle.release(), handle_id);
237 ServiceWorkerRegistrationHandle*
238 ServiceWorkerDispatcherHost::GetOrCreateRegistrationHandle(
239 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
240 ServiceWorkerRegistration* registration) {
241 DCHECK(provider_host);
242 ServiceWorkerRegistrationHandle* handle =
243 FindRegistrationHandle(provider_host->provider_id(), registration->id());
244 if (handle) {
245 handle->IncrementRefCount();
246 return handle;
249 scoped_ptr<ServiceWorkerRegistrationHandle> new_handle(
250 new ServiceWorkerRegistrationHandle(
251 GetContext()->AsWeakPtr(), provider_host, registration));
252 handle = new_handle.get();
253 RegisterServiceWorkerRegistrationHandle(new_handle.Pass());
254 return handle;
257 void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
258 int thread_id,
259 int request_id,
260 int provider_id,
261 const GURL& pattern,
262 const GURL& script_url) {
263 TRACE_EVENT0("ServiceWorker",
264 "ServiceWorkerDispatcherHost::OnRegisterServiceWorker");
265 if (!GetContext()) {
266 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
267 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
268 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
269 base::ASCIIToUTF16(kShutdownErrorMessage)));
270 return;
272 if (!pattern.is_valid() || !script_url.is_valid()) {
273 BadMessageReceived();
274 return;
277 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
278 render_process_id_, provider_id);
279 if (!provider_host) {
280 BadMessageReceived();
281 return;
283 if (!provider_host->IsContextAlive()) {
284 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
285 thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
286 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
287 base::ASCIIToUTF16(kShutdownErrorMessage)));
288 return;
291 // TODO(ksakamoto): Currently, document_url is empty if the document is in an
292 // IFRAME using frame.contentDocument.write(...). We can remove this check
293 // once crbug.com/439697 is fixed.
294 if (provider_host->document_url().is_empty()) {
295 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
296 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
297 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
298 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
299 return;
302 if (!CanRegisterServiceWorker(
303 provider_host->document_url(), pattern, script_url)) {
304 BadMessageReceived();
305 return;
308 std::string error_message;
309 if (ServiceWorkerUtils::ContainsDisallowedCharacter(pattern, script_url,
310 &error_message)) {
311 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
312 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
313 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
314 base::UTF8ToUTF16(error_message)));
315 return;
318 if (!GetContentClient()->browser()->AllowServiceWorker(
319 pattern, provider_host->topmost_frame_url(), resource_context_)) {
320 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
321 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
322 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
323 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
324 return;
327 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
328 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
329 request_id,
330 "Pattern", pattern.spec(),
331 "Script URL", script_url.spec());
332 GetContext()->RegisterServiceWorker(
333 pattern,
334 script_url,
335 provider_host,
336 base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete,
337 this,
338 thread_id,
339 provider_id,
340 request_id));
343 void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
344 int thread_id,
345 int request_id,
346 int provider_id,
347 const GURL& pattern) {
348 TRACE_EVENT0("ServiceWorker",
349 "ServiceWorkerDispatcherHost::OnUnregisterServiceWorker");
350 if (!GetContext()) {
351 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
352 thread_id,
353 request_id,
354 blink::WebServiceWorkerError::ErrorTypeAbort,
355 base::ASCIIToUTF16(kShutdownErrorMessage)));
356 return;
358 if (!pattern.is_valid()) {
359 BadMessageReceived();
360 return;
363 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
364 render_process_id_, provider_id);
365 if (!provider_host) {
366 BadMessageReceived();
367 return;
369 if (!provider_host->IsContextAlive()) {
370 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
371 thread_id,
372 request_id,
373 blink::WebServiceWorkerError::ErrorTypeAbort,
374 base::ASCIIToUTF16(kShutdownErrorMessage)));
375 return;
378 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
379 if (provider_host->document_url().is_empty()) {
380 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
381 thread_id,
382 request_id,
383 WebServiceWorkerError::ErrorTypeSecurity,
384 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
385 return;
388 if (!CanUnregisterServiceWorker(provider_host->document_url(), pattern)) {
389 BadMessageReceived();
390 return;
393 if (!GetContentClient()->browser()->AllowServiceWorker(
394 pattern, provider_host->topmost_frame_url(), resource_context_)) {
395 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
396 thread_id,
397 request_id,
398 WebServiceWorkerError::ErrorTypeUnknown,
399 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
400 return;
403 TRACE_EVENT_ASYNC_BEGIN1(
404 "ServiceWorker",
405 "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
406 request_id,
407 "Pattern", pattern.spec());
408 GetContext()->UnregisterServiceWorker(
409 pattern,
410 base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete,
411 this,
412 thread_id,
413 request_id));
416 void ServiceWorkerDispatcherHost::OnGetRegistration(
417 int thread_id,
418 int request_id,
419 int provider_id,
420 const GURL& document_url) {
421 TRACE_EVENT0("ServiceWorker",
422 "ServiceWorkerDispatcherHost::OnGetRegistration");
423 if (!GetContext()) {
424 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
425 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
426 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
427 base::ASCIIToUTF16(kShutdownErrorMessage)));
428 return;
430 if (!document_url.is_valid()) {
431 BadMessageReceived();
432 return;
435 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
436 render_process_id_, provider_id);
437 if (!provider_host) {
438 BadMessageReceived();
439 return;
441 if (!provider_host->IsContextAlive()) {
442 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
443 thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
444 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
445 base::ASCIIToUTF16(kShutdownErrorMessage)));
446 return;
449 // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
450 if (provider_host->document_url().is_empty()) {
451 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
452 thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
453 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
454 base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
455 return;
458 if (!CanGetRegistration(provider_host->document_url(), document_url)) {
459 BadMessageReceived();
460 return;
463 if (!GetContentClient()->browser()->AllowServiceWorker(
464 provider_host->document_url(),
465 provider_host->topmost_frame_url(),
466 resource_context_)) {
467 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
468 thread_id, request_id, WebServiceWorkerError::ErrorTypeUnknown,
469 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
470 base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
471 return;
474 DCHECK_CURRENTLY_ON(BrowserThread::IO);
475 if (GetContext()->storage()->IsDisabled()) {
476 SendGetRegistrationError(thread_id, request_id, SERVICE_WORKER_ERROR_ABORT);
477 return;
480 TRACE_EVENT_ASYNC_BEGIN1(
481 "ServiceWorker",
482 "ServiceWorkerDispatcherHost::GetRegistration",
483 request_id,
484 "Document URL", document_url.spec());
486 GetContext()->storage()->FindRegistrationForDocument(
487 document_url,
488 base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationComplete,
489 this,
490 thread_id,
491 provider_id,
492 request_id));
495 void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
496 int handle_id,
497 const base::string16& message,
498 const std::vector<TransferredMessagePort>& sent_message_ports) {
499 TRACE_EVENT0("ServiceWorker",
500 "ServiceWorkerDispatcherHost::OnPostMessageToWorker");
501 if (!GetContext())
502 return;
504 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
505 if (!handle) {
506 BadMessageReceived();
507 return;
510 handle->version()->DispatchMessageEvent(
511 message, sent_message_ports,
512 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
515 void ServiceWorkerDispatcherHost::OnProviderCreated(
516 int provider_id,
517 int render_frame_id,
518 ServiceWorkerProviderType provider_type) {
519 TRACE_EVENT0("ServiceWorker",
520 "ServiceWorkerDispatcherHost::OnProviderCreated");
521 if (!GetContext())
522 return;
523 if (GetContext()->GetProviderHost(render_process_id_, provider_id)) {
524 BadMessageReceived();
525 return;
527 scoped_ptr<ServiceWorkerProviderHost> provider_host(
528 new ServiceWorkerProviderHost(render_process_id_,
529 render_frame_id,
530 provider_id,
531 provider_type,
532 GetContext()->AsWeakPtr(),
533 this));
534 GetContext()->AddProviderHost(provider_host.Pass());
537 void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
538 TRACE_EVENT0("ServiceWorker",
539 "ServiceWorkerDispatcherHost::OnProviderDestroyed");
540 if (!GetContext())
541 return;
542 if (!GetContext()->GetProviderHost(render_process_id_, provider_id)) {
543 BadMessageReceived();
544 return;
546 GetContext()->RemoveProviderHost(render_process_id_, provider_id);
549 void ServiceWorkerDispatcherHost::OnSetHostedVersionId(
550 int provider_id, int64 version_id) {
551 TRACE_EVENT0("ServiceWorker",
552 "ServiceWorkerDispatcherHost::OnSetHostedVersionId");
553 if (!GetContext())
554 return;
555 ServiceWorkerProviderHost* provider_host =
556 GetContext()->GetProviderHost(render_process_id_, provider_id);
557 if (!provider_host) {
558 BadMessageReceived();
559 return;
561 if (!provider_host->IsContextAlive())
562 return;
563 if (!provider_host->SetHostedVersionId(version_id))
564 BadMessageReceived();
566 // Retrieve the registration associated with |version_id|.
567 ServiceWorkerVersion* version = GetContext()->GetLiveVersion(version_id);
568 if (!version)
569 return;
570 ServiceWorkerRegistration* registration =
571 GetContext()->GetLiveRegistration(version->registration_id());
572 DCHECK(registration);
574 // Set the document URL to the script url in order to allow
575 // register/unregister/getRegistration on ServiceWorkerGlobalScope.
576 provider_host->SetDocumentUrl(version->script_url());
578 ServiceWorkerRegistrationObjectInfo info;
579 ServiceWorkerVersionAttributes attrs;
580 GetRegistrationObjectInfoAndVersionAttributes(
581 provider_host->AsWeakPtr(), registration, &info, &attrs);
583 Send(new ServiceWorkerMsg_AssociateRegistrationWithServiceWorker(
584 kDocumentMainThreadId, provider_id, info, attrs));
587 ServiceWorkerRegistrationHandle*
588 ServiceWorkerDispatcherHost::FindRegistrationHandle(int provider_id,
589 int64 registration_id) {
590 for (IDMap<ServiceWorkerRegistrationHandle, IDMapOwnPointer>::iterator
591 iter(&registration_handles_);
592 !iter.IsAtEnd();
593 iter.Advance()) {
594 ServiceWorkerRegistrationHandle* handle = iter.GetCurrentValue();
595 DCHECK(handle);
596 if (handle->provider_id() == provider_id && handle->registration() &&
597 handle->registration()->id() == registration_id) {
598 return handle;
601 return NULL;
604 void ServiceWorkerDispatcherHost::GetRegistrationObjectInfoAndVersionAttributes(
605 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
606 ServiceWorkerRegistration* registration,
607 ServiceWorkerRegistrationObjectInfo* info,
608 ServiceWorkerVersionAttributes* attrs) {
609 ServiceWorkerRegistrationHandle* handle =
610 GetOrCreateRegistrationHandle(provider_host, registration);
611 *info = handle->GetObjectInfo();
613 attrs->installing =
614 provider_host->CreateAndRegisterServiceWorkerHandle(
615 registration->installing_version());
616 attrs->waiting =
617 provider_host->CreateAndRegisterServiceWorkerHandle(
618 registration->waiting_version());
619 attrs->active =
620 provider_host->CreateAndRegisterServiceWorkerHandle(
621 registration->active_version());
624 void ServiceWorkerDispatcherHost::RegistrationComplete(
625 int thread_id,
626 int provider_id,
627 int request_id,
628 ServiceWorkerStatusCode status,
629 const std::string& status_message,
630 int64 registration_id) {
631 if (!GetContext())
632 return;
634 ServiceWorkerProviderHost* provider_host =
635 GetContext()->GetProviderHost(render_process_id_, provider_id);
636 if (!provider_host)
637 return; // The provider has already been destroyed.
639 if (status != SERVICE_WORKER_OK) {
640 SendRegistrationError(thread_id, request_id, status, status_message);
641 return;
644 ServiceWorkerRegistration* registration =
645 GetContext()->GetLiveRegistration(registration_id);
646 DCHECK(registration);
648 ServiceWorkerRegistrationObjectInfo info;
649 ServiceWorkerVersionAttributes attrs;
650 GetRegistrationObjectInfoAndVersionAttributes(
651 provider_host->AsWeakPtr(), registration, &info, &attrs);
653 Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
654 thread_id, request_id, info, attrs));
655 TRACE_EVENT_ASYNC_END1("ServiceWorker",
656 "ServiceWorkerDispatcherHost::RegisterServiceWorker",
657 request_id,
658 "Registration ID",
659 registration_id);
662 void ServiceWorkerDispatcherHost::OnWorkerReadyForInspection(
663 int embedded_worker_id) {
664 TRACE_EVENT0("ServiceWorker",
665 "ServiceWorkerDispatcherHost::OnWorkerReadyForInspection");
666 if (!GetContext())
667 return;
668 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
669 if (!registry->CanHandle(embedded_worker_id))
670 return;
671 registry->OnWorkerReadyForInspection(render_process_id_, embedded_worker_id);
674 void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(
675 int embedded_worker_id,
676 int thread_id,
677 int provider_id) {
678 TRACE_EVENT0("ServiceWorker",
679 "ServiceWorkerDispatcherHost::OnWorkerScriptLoaded");
680 if (!GetContext())
681 return;
683 ServiceWorkerProviderHost* provider_host =
684 GetContext()->GetProviderHost(render_process_id_, provider_id);
685 if (!provider_host) {
686 BadMessageReceived();
687 return;
690 provider_host->SetReadyToSendMessagesToWorker(thread_id);
692 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
693 if (!registry->CanHandle(embedded_worker_id))
694 return;
695 registry->OnWorkerScriptLoaded(
696 render_process_id_, thread_id, embedded_worker_id);
699 void ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed(
700 int embedded_worker_id) {
701 TRACE_EVENT0("ServiceWorker",
702 "ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed");
703 if (!GetContext())
704 return;
705 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
706 if (!registry->CanHandle(embedded_worker_id))
707 return;
708 registry->OnWorkerScriptLoadFailed(render_process_id_, embedded_worker_id);
711 void ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated(
712 int embedded_worker_id,
713 bool success) {
714 TRACE_EVENT0("ServiceWorker",
715 "ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated");
716 if (!GetContext())
717 return;
718 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
719 if (!registry->CanHandle(embedded_worker_id))
720 return;
721 registry->OnWorkerScriptEvaluated(
722 render_process_id_, embedded_worker_id, success);
725 void ServiceWorkerDispatcherHost::OnWorkerStarted(int embedded_worker_id) {
726 TRACE_EVENT0("ServiceWorker",
727 "ServiceWorkerDispatcherHost::OnWorkerStarted");
728 if (!GetContext())
729 return;
730 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
731 if (!registry->CanHandle(embedded_worker_id))
732 return;
733 registry->OnWorkerStarted(render_process_id_, embedded_worker_id);
736 void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) {
737 TRACE_EVENT0("ServiceWorker",
738 "ServiceWorkerDispatcherHost::OnWorkerStopped");
739 if (!GetContext())
740 return;
741 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
742 if (!registry->CanHandle(embedded_worker_id))
743 return;
744 registry->OnWorkerStopped(render_process_id_, embedded_worker_id);
747 void ServiceWorkerDispatcherHost::OnPausedAfterDownload(
748 int embedded_worker_id) {
749 TRACE_EVENT0("ServiceWorker",
750 "ServiceWorkerDispatcherHost::OnPausedAfterDownload");
751 if (!GetContext())
752 return;
753 GetContext()->embedded_worker_registry()->OnPausedAfterDownload(
754 render_process_id_, embedded_worker_id);
757 void ServiceWorkerDispatcherHost::OnReportException(
758 int embedded_worker_id,
759 const base::string16& error_message,
760 int line_number,
761 int column_number,
762 const GURL& source_url) {
763 TRACE_EVENT0("ServiceWorker",
764 "ServiceWorkerDispatcherHost::OnReportException");
765 if (!GetContext())
766 return;
767 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
768 if (!registry->CanHandle(embedded_worker_id))
769 return;
770 registry->OnReportException(embedded_worker_id,
771 error_message,
772 line_number,
773 column_number,
774 source_url);
777 void ServiceWorkerDispatcherHost::OnReportConsoleMessage(
778 int embedded_worker_id,
779 const EmbeddedWorkerHostMsg_ReportConsoleMessage_Params& params) {
780 TRACE_EVENT0("ServiceWorker",
781 "ServiceWorkerDispatcherHost::OnReportConsoleMessage");
782 if (!GetContext())
783 return;
784 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
785 if (!registry->CanHandle(embedded_worker_id))
786 return;
787 registry->OnReportConsoleMessage(embedded_worker_id,
788 params.source_identifier,
789 params.message_level,
790 params.message,
791 params.line_number,
792 params.source_url);
795 void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
796 int handle_id) {
797 TRACE_EVENT0("ServiceWorker",
798 "ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount");
799 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
800 if (!handle) {
801 BadMessageReceived();
802 return;
804 handle->IncrementRefCount();
807 void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
808 int handle_id) {
809 TRACE_EVENT0("ServiceWorker",
810 "ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount");
811 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
812 if (!handle) {
813 BadMessageReceived();
814 return;
816 handle->DecrementRefCount();
817 if (handle->HasNoRefCount())
818 handles_.Remove(handle_id);
821 void ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount(
822 int registration_handle_id) {
823 TRACE_EVENT0("ServiceWorker",
824 "ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount");
825 ServiceWorkerRegistrationHandle* handle =
826 registration_handles_.Lookup(registration_handle_id);
827 if (!handle) {
828 BadMessageReceived();
829 return;
831 handle->IncrementRefCount();
834 void ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount(
835 int registration_handle_id) {
836 TRACE_EVENT0("ServiceWorker",
837 "ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount");
838 ServiceWorkerRegistrationHandle* handle =
839 registration_handles_.Lookup(registration_handle_id);
840 if (!handle) {
841 BadMessageReceived();
842 return;
844 handle->DecrementRefCount();
845 if (handle->HasNoRefCount())
846 registration_handles_.Remove(registration_handle_id);
849 void ServiceWorkerDispatcherHost::UnregistrationComplete(
850 int thread_id,
851 int request_id,
852 ServiceWorkerStatusCode status) {
853 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
854 SendUnregistrationError(thread_id, request_id, status);
855 return;
857 const bool is_success = (status == SERVICE_WORKER_OK);
858 Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id,
859 request_id,
860 is_success));
861 TRACE_EVENT_ASYNC_END1(
862 "ServiceWorker",
863 "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
864 request_id,
865 "Status", status);
868 void ServiceWorkerDispatcherHost::GetRegistrationComplete(
869 int thread_id,
870 int provider_id,
871 int request_id,
872 ServiceWorkerStatusCode status,
873 const scoped_refptr<ServiceWorkerRegistration>& registration) {
874 TRACE_EVENT_ASYNC_END1("ServiceWorker",
875 "ServiceWorkerDispatcherHost::GetRegistration",
876 request_id,
877 "Registration ID",
878 registration.get() ? registration->id()
879 : kInvalidServiceWorkerRegistrationId);
881 if (!GetContext())
882 return;
884 ServiceWorkerProviderHost* provider_host =
885 GetContext()->GetProviderHost(render_process_id_, provider_id);
886 if (!provider_host)
887 return; // The provider has already been destroyed.
889 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
890 SendGetRegistrationError(thread_id, request_id, status);
891 return;
894 ServiceWorkerRegistrationObjectInfo info;
895 ServiceWorkerVersionAttributes attrs;
896 if (status == SERVICE_WORKER_OK) {
897 DCHECK(registration.get());
898 if (!registration->is_uninstalling()) {
899 GetRegistrationObjectInfoAndVersionAttributes(
900 provider_host->AsWeakPtr(), registration.get(), &info, &attrs);
904 Send(new ServiceWorkerMsg_DidGetRegistration(
905 thread_id, request_id, info, attrs));
908 void ServiceWorkerDispatcherHost::SendRegistrationError(
909 int thread_id,
910 int request_id,
911 ServiceWorkerStatusCode status,
912 const std::string& status_message) {
913 base::string16 error_message;
914 blink::WebServiceWorkerError::ErrorType error_type;
915 GetServiceWorkerRegistrationStatusResponse(status, status_message,
916 &error_type, &error_message);
917 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
918 thread_id, request_id, error_type,
919 base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) + error_message));
922 void ServiceWorkerDispatcherHost::SendUnregistrationError(
923 int thread_id,
924 int request_id,
925 ServiceWorkerStatusCode status) {
926 base::string16 error_message;
927 blink::WebServiceWorkerError::ErrorType error_type;
928 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
929 &error_message);
930 Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
931 thread_id, request_id, error_type,
932 base::ASCIIToUTF16(kServiceWorkerUnregisterErrorPrefix) + error_message));
935 void ServiceWorkerDispatcherHost::SendGetRegistrationError(
936 int thread_id,
937 int request_id,
938 ServiceWorkerStatusCode status) {
939 base::string16 error_message;
940 blink::WebServiceWorkerError::ErrorType error_type;
941 GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
942 &error_message);
943 Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
944 thread_id, request_id, error_type,
945 base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
946 error_message));
949 ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
950 if (!context_wrapper_.get())
951 return nullptr;
952 return context_wrapper_->context();
955 void ServiceWorkerDispatcherHost::OnTerminateWorker(int handle_id) {
956 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
957 if (!handle) {
958 BadMessageReceived();
959 return;
961 handle->version()->StopWorker(
962 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
965 } // namespace content