Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_dispatcher_host.cc
blobd20bbbeccb9632608427b84494cb44d8d74251b6
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"
22 #include "url/gurl.h"
24 using blink::WebServiceWorkerError;
26 namespace content {
28 namespace {
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,
42 const GURL& pattern,
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();
57 } // namespace
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() {
70 if (GetContext()) {
71 GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
72 GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
73 render_process_id_);
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)));
84 return;
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) {
107 bool handled = true;
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,
114 OnProviderCreated)
115 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed,
116 OnProviderDestroyed)
117 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetVersionId,
118 OnSetHostedVersionId)
119 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToWorker,
120 OnPostMessageToWorker)
121 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerReadyForInspection,
122 OnWorkerReadyForInspection)
123 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoaded,
124 OnWorkerScriptLoaded)
125 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoadFailed,
126 OnWorkerScriptLoadFailed)
127 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted,
128 OnWorkerStarted)
129 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped,
130 OnWorkerStopped)
131 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_DidPauseAfterDownload,
132 OnPausedAfterDownload)
133 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportException,
134 OnReportException)
135 IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportConsoleMessage,
136 OnReportConsoleMessage)
137 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount,
138 OnIncrementServiceWorkerRefCount)
139 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount,
140 OnDecrementServiceWorkerRefCount)
141 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementRegistrationRefCount,
142 OnIncrementRegistrationRefCount)
143 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
144 OnDecrementRegistrationRefCount)
145 IPC_MESSAGE_UNHANDLED(handled = false)
146 IPC_END_MESSAGE_MAP()
148 if (!handled && GetContext()) {
149 handled =
150 GetContext()->embedded_worker_registry()->OnMessageReceived(message);
151 if (!handled)
152 BadMessageReceived();
155 return handled;
158 bool ServiceWorkerDispatcherHost::Send(IPC::Message* message) {
159 if (channel_ready_) {
160 BrowserMessageFilter::Send(message);
161 // Don't bother passing through Send()'s result: it's not reliable.
162 return true;
165 pending_messages_.push_back(message);
166 return true;
169 void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle(
170 scoped_ptr<ServiceWorkerHandle> handle) {
171 int handle_id = handle->handle_id();
172 handles_.AddWithID(handle.release(), handle_id);
175 void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationHandle(
176 scoped_ptr<ServiceWorkerRegistrationHandle> handle) {
177 int handle_id = handle->handle_id();
178 registration_handles_.AddWithID(handle.release(), handle_id);
181 void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
182 int thread_id,
183 int request_id,
184 int provider_id,
185 const GURL& pattern,
186 const GURL& script_url) {
187 if (!GetContext()) {
188 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
189 thread_id,
190 request_id,
191 WebServiceWorkerError::ErrorTypeAbort,
192 base::ASCIIToUTF16(kShutdownErrorMessage)));
193 return;
196 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
197 render_process_id_, provider_id);
198 if (!provider_host) {
199 BadMessageReceived();
200 return;
202 if (!provider_host->IsContextAlive()) {
203 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
204 thread_id,
205 request_id,
206 WebServiceWorkerError::ErrorTypeAbort,
207 base::ASCIIToUTF16(kShutdownErrorMessage)));
208 return;
211 if (!CanRegisterServiceWorker(
212 provider_host->document_url(), pattern, script_url)) {
213 BadMessageReceived();
214 return;
216 GetContext()->RegisterServiceWorker(
217 pattern,
218 script_url,
219 render_process_id_,
220 provider_host,
221 base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete,
222 this,
223 thread_id,
224 provider_id,
225 request_id));
228 void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
229 int thread_id,
230 int request_id,
231 int provider_id,
232 const GURL& pattern) {
233 if (!GetContext()) {
234 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
235 thread_id,
236 request_id,
237 blink::WebServiceWorkerError::ErrorTypeAbort,
238 base::ASCIIToUTF16(kShutdownErrorMessage)));
239 return;
242 ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
243 render_process_id_, provider_id);
244 if (!provider_host) {
245 BadMessageReceived();
246 return;
248 if (!provider_host->IsContextAlive()) {
249 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
250 thread_id,
251 request_id,
252 blink::WebServiceWorkerError::ErrorTypeAbort,
253 base::ASCIIToUTF16(kShutdownErrorMessage)));
254 return;
257 if (!CanUnregisterServiceWorker(provider_host->document_url(), pattern)) {
258 BadMessageReceived();
259 return;
262 GetContext()->UnregisterServiceWorker(
263 pattern,
264 base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete,
265 this,
266 thread_id,
267 request_id));
270 void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
271 int handle_id,
272 const base::string16& message,
273 const std::vector<int>& sent_message_port_ids) {
274 if (!GetContext())
275 return;
277 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
278 if (!handle) {
279 BadMessageReceived();
280 return;
283 std::vector<int> new_routing_ids;
284 message_port_message_filter_->UpdateMessagePortsWithNewRoutes(
285 sent_message_port_ids, &new_routing_ids);
286 handle->version()->SendMessage(
287 ServiceWorkerMsg_MessageToWorker(message,
288 sent_message_port_ids,
289 new_routing_ids),
290 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
293 void ServiceWorkerDispatcherHost::OnProviderCreated(int provider_id) {
294 if (!GetContext())
295 return;
296 if (GetContext()->GetProviderHost(render_process_id_, provider_id)) {
297 BadMessageReceived();
298 return;
300 scoped_ptr<ServiceWorkerProviderHost> provider_host(
301 new ServiceWorkerProviderHost(
302 render_process_id_, provider_id, GetContext()->AsWeakPtr(), this));
303 GetContext()->AddProviderHost(provider_host.Pass());
306 void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
307 if (!GetContext())
308 return;
309 if (!GetContext()->GetProviderHost(render_process_id_, provider_id)) {
310 BadMessageReceived();
311 return;
313 GetContext()->RemoveProviderHost(render_process_id_, provider_id);
316 void ServiceWorkerDispatcherHost::OnSetHostedVersionId(
317 int provider_id, int64 version_id) {
318 if (!GetContext())
319 return;
320 ServiceWorkerProviderHost* provider_host =
321 GetContext()->GetProviderHost(render_process_id_, provider_id);
322 if (!provider_host) {
323 BadMessageReceived();
324 return;
326 if (!provider_host->IsContextAlive())
327 return;
328 if (!provider_host->SetHostedVersionId(version_id))
329 BadMessageReceived();
332 ServiceWorkerRegistrationHandle*
333 ServiceWorkerDispatcherHost::FindRegistrationHandle(int provider_id,
334 int64 registration_id) {
335 for (IDMap<ServiceWorkerRegistrationHandle, IDMapOwnPointer>::iterator
336 iter(&registration_handles_);
337 !iter.IsAtEnd();
338 iter.Advance()) {
339 ServiceWorkerRegistrationHandle* handle = iter.GetCurrentValue();
340 DCHECK(handle);
341 if (handle->provider_id() == provider_id && handle->registration() &&
342 handle->registration()->id() == registration_id) {
343 return handle;
346 return NULL;
349 void ServiceWorkerDispatcherHost::RegistrationComplete(
350 int thread_id,
351 int provider_id,
352 int request_id,
353 ServiceWorkerStatusCode status,
354 int64 registration_id,
355 int64 version_id) {
356 if (!GetContext())
357 return;
359 if (status != SERVICE_WORKER_OK) {
360 SendRegistrationError(thread_id, request_id, status);
361 return;
364 ServiceWorkerRegistration* registration =
365 GetContext()->GetLiveRegistration(registration_id);
366 DCHECK(registration);
368 ServiceWorkerRegistrationHandle* handle =
369 FindRegistrationHandle(provider_id, registration_id);
370 ServiceWorkerRegistrationObjectInfo info;
371 if (handle) {
372 handle->IncrementRefCount();
373 info = handle->GetObjectInfo();
374 } else {
375 scoped_ptr<ServiceWorkerRegistrationHandle> new_handle(
376 new ServiceWorkerRegistrationHandle(
377 GetContext()->AsWeakPtr(), this, provider_id, registration));
378 info = new_handle->GetObjectInfo();
379 RegisterServiceWorkerRegistrationHandle(new_handle.Pass());
382 Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
383 thread_id, request_id, info));
386 void ServiceWorkerDispatcherHost::OnWorkerReadyForInspection(
387 int embedded_worker_id) {
388 if (!GetContext())
389 return;
390 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
391 if (!registry->CanHandle(embedded_worker_id))
392 return;
393 registry->OnWorkerReadyForInspection(render_process_id_, embedded_worker_id);
396 void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(
397 int embedded_worker_id,
398 int thread_id) {
399 if (!GetContext())
400 return;
401 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
402 if (!registry->CanHandle(embedded_worker_id))
403 return;
404 registry->OnWorkerScriptLoaded(
405 render_process_id_, thread_id, embedded_worker_id);
408 void ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed(
409 int embedded_worker_id) {
410 if (!GetContext())
411 return;
412 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
413 if (!registry->CanHandle(embedded_worker_id))
414 return;
415 registry->OnWorkerScriptLoadFailed(render_process_id_, embedded_worker_id);
418 void ServiceWorkerDispatcherHost::OnWorkerStarted(int embedded_worker_id) {
419 if (!GetContext())
420 return;
421 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
422 if (!registry->CanHandle(embedded_worker_id))
423 return;
424 registry->OnWorkerStarted(render_process_id_, embedded_worker_id);
427 void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) {
428 if (!GetContext())
429 return;
430 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
431 if (!registry->CanHandle(embedded_worker_id))
432 return;
433 registry->OnWorkerStopped(render_process_id_, embedded_worker_id);
436 void ServiceWorkerDispatcherHost::OnPausedAfterDownload(
437 int embedded_worker_id) {
438 if (!GetContext())
439 return;
440 GetContext()->embedded_worker_registry()->OnPausedAfterDownload(
441 render_process_id_, embedded_worker_id);
444 void ServiceWorkerDispatcherHost::OnReportException(
445 int embedded_worker_id,
446 const base::string16& error_message,
447 int line_number,
448 int column_number,
449 const GURL& source_url) {
450 if (!GetContext())
451 return;
452 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
453 if (!registry->CanHandle(embedded_worker_id))
454 return;
455 registry->OnReportException(embedded_worker_id,
456 error_message,
457 line_number,
458 column_number,
459 source_url);
462 void ServiceWorkerDispatcherHost::OnReportConsoleMessage(
463 int embedded_worker_id,
464 const EmbeddedWorkerHostMsg_ReportConsoleMessage_Params& params) {
465 if (!GetContext())
466 return;
467 EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
468 if (!registry->CanHandle(embedded_worker_id))
469 return;
470 registry->OnReportConsoleMessage(embedded_worker_id,
471 params.source_identifier,
472 params.message_level,
473 params.message,
474 params.line_number,
475 params.source_url);
478 void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
479 int handle_id) {
480 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
481 if (!handle) {
482 BadMessageReceived();
483 return;
485 handle->IncrementRefCount();
488 void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
489 int handle_id) {
490 ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
491 if (!handle) {
492 BadMessageReceived();
493 return;
495 handle->DecrementRefCount();
496 if (handle->HasNoRefCount())
497 handles_.Remove(handle_id);
500 void ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount(
501 int registration_handle_id) {
502 ServiceWorkerRegistrationHandle* handle =
503 registration_handles_.Lookup(registration_handle_id);
504 if (!handle) {
505 BadMessageReceived();
506 return;
508 handle->IncrementRefCount();
511 void ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount(
512 int registration_handle_id) {
513 ServiceWorkerRegistrationHandle* handle =
514 registration_handles_.Lookup(registration_handle_id);
515 if (!handle) {
516 BadMessageReceived();
517 return;
519 handle->DecrementRefCount();
520 if (handle->HasNoRefCount())
521 registration_handles_.Remove(registration_handle_id);
524 void ServiceWorkerDispatcherHost::UnregistrationComplete(
525 int thread_id,
526 int request_id,
527 ServiceWorkerStatusCode status) {
528 if (status != SERVICE_WORKER_OK) {
529 SendRegistrationError(thread_id, request_id, status);
530 return;
533 Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id, request_id));
536 void ServiceWorkerDispatcherHost::SendRegistrationError(
537 int thread_id,
538 int request_id,
539 ServiceWorkerStatusCode status) {
540 base::string16 error_message;
541 blink::WebServiceWorkerError::ErrorType error_type;
542 GetServiceWorkerRegistrationStatusResponse(
543 status, &error_type, &error_message);
544 Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
545 thread_id, request_id, error_type, error_message));
548 ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
549 return context_wrapper_->context();
552 } // namespace content