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 "content/browser/message_port_message_filter.h"
10 #include "content/browser/message_port_service.h"
11 #include "content/browser/service_worker/embedded_worker_registry.h"
12 #include "content/browser/service_worker/service_worker_context_core.h"
13 #include "content/browser/service_worker/service_worker_context_wrapper.h"
14 #include "content/browser/service_worker/service_worker_handle.h"
15 #include "content/browser/service_worker/service_worker_registration.h"
16 #include "content/browser/service_worker/service_worker_registration_handle.h"
17 #include "content/browser/service_worker/service_worker_utils.h"
18 #include "content/common/service_worker/embedded_worker_messages.h"
19 #include "content/common/service_worker/service_worker_messages.h"
20 #include "ipc/ipc_message_macros.h"
21 #include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
24 using blink::WebServiceWorkerError;
30 const char kShutdownErrorMessage[] =
31 "The Service Worker system has shutdown.";
33 const uint32 kFilteredMessageClasses[] = {
34 ServiceWorkerMsgStart,
35 EmbeddedWorkerMsgStart,
38 // TODO(dominicc): When crbug.com/362214 is fixed, make
39 // Can(R|Unr)egisterServiceWorker also check that these are secure
40 // origins to defend against compromised renderers.
41 bool CanRegisterServiceWorker(const GURL& document_url,
43 const GURL& script_url) {
44 // TODO: Respect Chrome's content settings, if we add a setting for
45 // controlling whether Service Worker is allowed.
46 return document_url.GetOrigin() == pattern.GetOrigin() &&
47 document_url.GetOrigin() == script_url.GetOrigin();
50 bool CanUnregisterServiceWorker(const GURL& document_url,
51 const GURL& pattern) {
52 // TODO: Respect Chrome's content settings, if we add a setting for
53 // controlling whether Service Worker is allowed.
54 return document_url.GetOrigin() == pattern.GetOrigin();
59 ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
60 int render_process_id,
61 MessagePortMessageFilter* message_port_message_filter)
62 : BrowserMessageFilter(kFilteredMessageClasses,
63 arraysize(kFilteredMessageClasses)),
64 render_process_id_(render_process_id),
65 message_port_message_filter_(message_port_message_filter),
66 channel_ready_(false) {
69 ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
71 GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
72 GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
77 void ServiceWorkerDispatcherHost::Init(
78 ServiceWorkerContextWrapper* context_wrapper) {
79 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
80 BrowserThread::PostTask(
81 BrowserThread::IO, FROM_HERE,
82 base::Bind(&ServiceWorkerDispatcherHost::Init,
83 this, make_scoped_refptr(context_wrapper)));
86 context_wrapper_ = context_wrapper;
87 GetContext()->embedded_worker_registry()->AddChildProcessSender(
88 render_process_id_, this);
91 void ServiceWorkerDispatcherHost::OnFilterAdded(IPC::Sender* sender) {
92 BrowserMessageFilter::OnFilterAdded(sender);
93 channel_ready_ = true;
94 std::vector<IPC::Message*> messages;
95 pending_messages_.release(&messages);
96 for (size_t i = 0; i < messages.size(); ++i) {
97 BrowserMessageFilter::Send(messages[i]);
101 void ServiceWorkerDispatcherHost::OnDestruct() const {
102 BrowserThread::DeleteOnIOThread::Destruct(this);
105 bool ServiceWorkerDispatcherHost::OnMessageReceived(
106 const IPC::Message& message) {
108 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcherHost, message)
109 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_RegisterServiceWorker,
110 OnRegisterServiceWorker)
111 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_UnregisterServiceWorker,
112 OnUnregisterServiceWorker)
113 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderCreated,
115 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed,
117 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetVersionId,
118 OnSetHostedVersionId)
119 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToWorker,
120 OnPostMessageToWorker)
121 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoaded,
122 OnWorkerScriptLoaded)
123 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoadFailed,
124 OnWorkerScriptLoadFailed)
125 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted,
127 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped,
129 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_DidPauseAfterDownload,
130 OnPausedAfterDownload)
131 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportException,
133 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportConsoleMessage,
134 OnReportConsoleMessage)
135 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount,
136 OnIncrementServiceWorkerRefCount)
137 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount,
138 OnDecrementServiceWorkerRefCount)
139 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementRegistrationRefCount,
140 OnIncrementRegistrationRefCount)
141 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
142 OnDecrementRegistrationRefCount)
143 IPC_MESSAGE_UNHANDLED(handled = false)
144 IPC_END_MESSAGE_MAP()
146 if (!handled && GetContext()) {
148 GetContext()->embedded_worker_registry()->OnMessageReceived(message);
150 BadMessageReceived();
156 bool ServiceWorkerDispatcherHost::Send(IPC::Message* message) {
157 if (channel_ready_) {
158 BrowserMessageFilter::Send(message);
159 // Don't bother passing through Send()'s result: it's not reliable.
163 pending_messages_.push_back(message);
167 void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle(
168 scoped_ptr<ServiceWorkerHandle> handle) {
169 int handle_id = handle->handle_id();
170 handles_.AddWithID(handle.release(), handle_id);
173 void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationHandle(
174 scoped_ptr<ServiceWorkerRegistrationHandle> handle) {
175 int handle_id = handle->handle_id();
176 registration_handles_.AddWithID(handle.release(), handle_id);
179 void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
184 const GURL& script_url) {
186 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
189 WebServiceWorkerError::ErrorTypeAbort,
190 base::ASCIIToUTF16(kShutdownErrorMessage)));
194 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
195 render_process_id_, provider_id);
196 if (!provider_host) {
197 BadMessageReceived();
200 if (!provider_host->IsContextAlive()) {
201 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
204 WebServiceWorkerError::ErrorTypeAbort,
205 base::ASCIIToUTF16(kShutdownErrorMessage)));
209 if (!CanRegisterServiceWorker(
210 provider_host->document_url(), pattern, script_url)) {
211 BadMessageReceived();
214 GetContext()->RegisterServiceWorker(
219 base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete,
226 void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
230 const GURL& pattern) {
232 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
235 blink::WebServiceWorkerError::ErrorTypeAbort,
236 base::ASCIIToUTF16(kShutdownErrorMessage)));
240 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
241 render_process_id_, provider_id);
242 if (!provider_host) {
243 BadMessageReceived();
246 if (!provider_host->IsContextAlive()) {
247 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
250 blink::WebServiceWorkerError::ErrorTypeAbort,
251 base::ASCIIToUTF16(kShutdownErrorMessage)));
255 if (!CanUnregisterServiceWorker(provider_host->document_url(), pattern)) {
256 BadMessageReceived();
260 GetContext()->UnregisterServiceWorker(
262 base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete,
268 void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
270 const base::string16& message,
271 const std::vector<int>& sent_message_port_ids) {
275 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
277 BadMessageReceived();
281 std::vector<int> new_routing_ids;
282 message_port_message_filter_->UpdateMessagePortsWithNewRoutes(
283 sent_message_port_ids, &new_routing_ids);
284 handle->version()->SendMessage(
285 ServiceWorkerMsg_MessageToWorker(message,
286 sent_message_port_ids,
288 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
291 void ServiceWorkerDispatcherHost::OnProviderCreated(int provider_id) {
294 if (GetContext()->GetProviderHost(render_process_id_, provider_id)) {
295 BadMessageReceived();
298 scoped_ptr<ServiceWorkerProviderHost> provider_host(
299 new ServiceWorkerProviderHost(
300 render_process_id_, provider_id, GetContext()->AsWeakPtr(), this));
301 GetContext()->AddProviderHost(provider_host.Pass());
304 void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
307 if (!GetContext()->GetProviderHost(render_process_id_, provider_id)) {
308 BadMessageReceived();
311 GetContext()->RemoveProviderHost(render_process_id_, provider_id);
314 void ServiceWorkerDispatcherHost::OnSetHostedVersionId(
315 int provider_id, int64 version_id) {
318 ServiceWorkerProviderHost* provider_host =
319 GetContext()->GetProviderHost(render_process_id_, provider_id);
320 if (!provider_host) {
321 BadMessageReceived();
324 if (!provider_host->IsContextAlive())
326 if (!provider_host->SetHostedVersionId(version_id))
327 BadMessageReceived();
330 ServiceWorkerHandle* ServiceWorkerDispatcherHost::FindHandle(int provider_id,
332 for (IDMap<ServiceWorkerHandle, IDMapOwnPointer>::iterator iter(&handles_);
335 ServiceWorkerHandle* handle = iter.GetCurrentValue();
337 if (handle->provider_id() == provider_id && handle->version() &&
338 handle->version()->version_id() == version_id) {
345 ServiceWorkerRegistrationHandle*
346 ServiceWorkerDispatcherHost::FindRegistrationHandle(int provider_id,
347 int64 registration_id) {
348 for (IDMap<ServiceWorkerRegistrationHandle, IDMapOwnPointer>::iterator
349 iter(®istration_handles_);
352 ServiceWorkerRegistrationHandle* handle = iter.GetCurrentValue();
354 if (handle->provider_id() == provider_id && handle->registration() &&
355 handle->registration()->id() == registration_id) {
362 void ServiceWorkerDispatcherHost::RegistrationComplete(
366 ServiceWorkerStatusCode status,
367 int64 registration_id,
372 if (status != SERVICE_WORKER_OK) {
373 SendRegistrationError(thread_id, request_id, status);
377 ServiceWorkerVersion* version = GetContext()->GetLiveVersion(version_id);
379 DCHECK_EQ(registration_id, version->registration_id());
380 ServiceWorkerObjectInfo info;
382 ServiceWorkerHandle* handle = FindHandle(provider_id, version_id);
384 DCHECK_EQ(thread_id, handle->thread_id());
385 info = handle->GetObjectInfo();
386 handle->IncrementRefCount();
388 scoped_ptr<ServiceWorkerHandle> new_handle = ServiceWorkerHandle::Create(
389 GetContext()->AsWeakPtr(), this, thread_id, provider_id, version);
390 info = new_handle->GetObjectInfo();
391 RegisterServiceWorkerHandle(new_handle.Pass());
394 ServiceWorkerRegistration* registration =
395 GetContext()->GetLiveRegistration(registration_id);
396 DCHECK(registration);
398 ServiceWorkerRegistrationHandle* registration_handle =
399 FindRegistrationHandle(provider_id, registration_id);
400 int registration_handle_id = kInvalidServiceWorkerRegistrationHandleId;
401 if (registration_handle) {
402 registration_handle->IncrementRefCount();
403 registration_handle_id = registration_handle->handle_id();
405 scoped_ptr<ServiceWorkerRegistrationHandle> new_handle(
406 new ServiceWorkerRegistrationHandle(
407 GetContext()->AsWeakPtr(), this, provider_id, registration));
408 registration_handle_id = new_handle->handle_id();
409 RegisterServiceWorkerRegistrationHandle(new_handle.Pass());
412 Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
413 thread_id, request_id, registration_handle_id, info));
416 void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(int embedded_worker_id) {
419 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
420 if (!registry->CanHandle(embedded_worker_id))
422 registry->OnWorkerScriptLoaded(render_process_id_, embedded_worker_id);
425 void ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed(
426 int embedded_worker_id) {
429 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
430 if (!registry->CanHandle(embedded_worker_id))
432 registry->OnWorkerScriptLoadFailed(render_process_id_, embedded_worker_id);
435 void ServiceWorkerDispatcherHost::OnWorkerStarted(
436 int thread_id, int embedded_worker_id) {
439 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
440 if (!registry->CanHandle(embedded_worker_id))
442 registry->OnWorkerStarted(render_process_id_, thread_id, embedded_worker_id);
445 void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) {
448 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
449 if (!registry->CanHandle(embedded_worker_id))
451 registry->OnWorkerStopped(render_process_id_, embedded_worker_id);
454 void ServiceWorkerDispatcherHost::OnPausedAfterDownload(
455 int embedded_worker_id) {
458 GetContext()->embedded_worker_registry()->OnPausedAfterDownload(
459 render_process_id_, embedded_worker_id);
462 void ServiceWorkerDispatcherHost::OnReportException(
463 int embedded_worker_id,
464 const base::string16& error_message,
467 const GURL& source_url) {
470 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
471 if (!registry->CanHandle(embedded_worker_id))
473 registry->OnReportException(embedded_worker_id,
480 void ServiceWorkerDispatcherHost::OnReportConsoleMessage(
481 int embedded_worker_id,
482 const EmbeddedWorkerHostMsg_ReportConsoleMessage_Params& params) {
485 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
486 if (!registry->CanHandle(embedded_worker_id))
488 registry->OnReportConsoleMessage(embedded_worker_id,
489 params.source_identifier,
490 params.message_level,
496 void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
498 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
500 BadMessageReceived();
503 handle->IncrementRefCount();
506 void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
508 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
510 BadMessageReceived();
513 handle->DecrementRefCount();
514 if (handle->HasNoRefCount())
515 handles_.Remove(handle_id);
518 void ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount(
519 int registration_handle_id) {
520 ServiceWorkerRegistrationHandle* handle =
521 registration_handles_.Lookup(registration_handle_id);
523 BadMessageReceived();
526 handle->IncrementRefCount();
529 void ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount(
530 int registration_handle_id) {
531 ServiceWorkerRegistrationHandle* handle =
532 registration_handles_.Lookup(registration_handle_id);
534 BadMessageReceived();
537 handle->DecrementRefCount();
538 if (handle->HasNoRefCount())
539 registration_handles_.Remove(registration_handle_id);
542 void ServiceWorkerDispatcherHost::UnregistrationComplete(
545 ServiceWorkerStatusCode status) {
546 if (status != SERVICE_WORKER_OK) {
547 SendRegistrationError(thread_id, request_id, status);
551 Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id, request_id));
554 void ServiceWorkerDispatcherHost::SendRegistrationError(
557 ServiceWorkerStatusCode status) {
558 base::string16 error_message;
559 blink::WebServiceWorkerError::ErrorType error_type;
560 GetServiceWorkerRegistrationStatusResponse(
561 status, &error_type, &error_message);
562 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
563 thread_id, request_id, error_type, error_message));
566 ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
567 return context_wrapper_->context();
570 } // namespace content