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.
4
5#include "content/browser/service_worker/service_worker_dispatcher_host.h"
6
7#include "base/debug/trace_event.h"
8#include "base/logging.h"
9#include "base/strings/utf_string_conversions.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 "ipc/ipc_message_macros.h"
22#include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
23#include "url/gurl.h"
24
25using blink::WebServiceWorkerError;
26
27namespace content {
28
29namespace {
30
31const char kShutdownErrorMessage[] =
32    "The Service Worker system has shutdown.";
33
34const uint32 kFilteredMessageClasses[] = {
35  ServiceWorkerMsgStart,
36  EmbeddedWorkerMsgStart,
37};
38
39// TODO(dominicc): When crbug.com/362214 is fixed, make
40// Can(R|Unr)egisterServiceWorker also check that these are secure
41// origins to defend against compromised renderers.
42bool CanRegisterServiceWorker(const GURL& document_url,
43                              const GURL& pattern,
44                              const GURL& script_url) {
45  // TODO: Respect Chrome's content settings, if we add a setting for
46  // controlling whether Service Worker is allowed.
47  return document_url.GetOrigin() == pattern.GetOrigin() &&
48         document_url.GetOrigin() == script_url.GetOrigin();
49}
50
51bool CanUnregisterServiceWorker(const GURL& document_url,
52                                const GURL& pattern) {
53  // TODO: Respect Chrome's content settings, if we add a setting for
54  // controlling whether Service Worker is allowed.
55  return document_url.GetOrigin() == pattern.GetOrigin();
56}
57
58bool CanGetRegistration(const GURL& document_url,
59                        const GURL& given_document_url) {
60  // TODO: Respect Chrome's content settings, if we add a setting for
61  // controlling whether Service Worker is allowed.
62  return document_url.GetOrigin() == given_document_url.GetOrigin();
63}
64
65}  // namespace
66
67ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
68    int render_process_id,
69    MessagePortMessageFilter* message_port_message_filter)
70    : BrowserMessageFilter(kFilteredMessageClasses,
71                           arraysize(kFilteredMessageClasses)),
72      render_process_id_(render_process_id),
73      message_port_message_filter_(message_port_message_filter),
74      channel_ready_(false) {
75}
76
77ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
78  if (GetContext()) {
79    GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
80    GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
81        render_process_id_);
82  }
83}
84
85void ServiceWorkerDispatcherHost::Init(
86    ServiceWorkerContextWrapper* context_wrapper) {
87  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
88    BrowserThread::PostTask(
89        BrowserThread::IO, FROM_HERE,
90        base::Bind(&ServiceWorkerDispatcherHost::Init,
91                   this, make_scoped_refptr(context_wrapper)));
92    return;
93  }
94  context_wrapper_ = context_wrapper;
95  GetContext()->embedded_worker_registry()->AddChildProcessSender(
96      render_process_id_, this);
97}
98
99void ServiceWorkerDispatcherHost::OnFilterAdded(IPC::Sender* sender) {
100  TRACE_EVENT0("ServiceWorker",
101               "ServiceWorkerDispatcherHost::OnFilterAdded");
102  BrowserMessageFilter::OnFilterAdded(sender);
103  channel_ready_ = true;
104  std::vector<IPC::Message*> messages;
105  pending_messages_.release(&messages);
106  for (size_t i = 0; i < messages.size(); ++i) {
107    BrowserMessageFilter::Send(messages[i]);
108  }
109}
110
111void ServiceWorkerDispatcherHost::OnDestruct() const {
112  BrowserThread::DeleteOnIOThread::Destruct(this);
113}
114
115bool ServiceWorkerDispatcherHost::OnMessageReceived(
116    const IPC::Message& message) {
117  bool handled = true;
118  IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcherHost, message)
119    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_RegisterServiceWorker,
120                        OnRegisterServiceWorker)
121    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_UnregisterServiceWorker,
122                        OnUnregisterServiceWorker)
123    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistration,
124                        OnGetRegistration)
125    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderCreated,
126                        OnProviderCreated)
127    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed,
128                        OnProviderDestroyed)
129    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetVersionId,
130                        OnSetHostedVersionId)
131    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToWorker,
132                        OnPostMessageToWorker)
133    IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerReadyForInspection,
134                        OnWorkerReadyForInspection)
135    IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoaded,
136                        OnWorkerScriptLoaded)
137    IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoadFailed,
138                        OnWorkerScriptLoadFailed)
139    IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted,
140                        OnWorkerStarted)
141    IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped,
142                        OnWorkerStopped)
143    IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_DidPauseAfterDownload,
144                        OnPausedAfterDownload)
145    IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportException,
146                        OnReportException)
147    IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportConsoleMessage,
148                        OnReportConsoleMessage)
149    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount,
150                        OnIncrementServiceWorkerRefCount)
151    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount,
152                        OnDecrementServiceWorkerRefCount)
153    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementRegistrationRefCount,
154                        OnIncrementRegistrationRefCount)
155    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
156                        OnDecrementRegistrationRefCount)
157    IPC_MESSAGE_UNHANDLED(handled = false)
158  IPC_END_MESSAGE_MAP()
159
160  if (!handled && GetContext()) {
161    handled =
162        GetContext()->embedded_worker_registry()->OnMessageReceived(message);
163    if (!handled)
164      BadMessageReceived();
165  }
166
167  return handled;
168}
169
170bool ServiceWorkerDispatcherHost::Send(IPC::Message* message) {
171  if (channel_ready_) {
172    BrowserMessageFilter::Send(message);
173    // Don't bother passing through Send()'s result: it's not reliable.
174    return true;
175  }
176
177  pending_messages_.push_back(message);
178  return true;
179}
180
181ServiceWorkerRegistrationHandle*
182ServiceWorkerDispatcherHost::GetOrCreateRegistrationHandle(
183    int provider_id,
184    ServiceWorkerRegistration* registration) {
185  ServiceWorkerRegistrationHandle* handle =
186      FindRegistrationHandle(provider_id, registration->id());
187  if (handle) {
188    handle->IncrementRefCount();
189    return handle;
190  }
191
192  scoped_ptr<ServiceWorkerRegistrationHandle> new_handle(
193      new ServiceWorkerRegistrationHandle(
194          GetContext()->AsWeakPtr(), this, provider_id, registration));
195  handle = new_handle.get();
196  RegisterServiceWorkerRegistrationHandle(new_handle.Pass());
197  return handle;
198}
199
200void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle(
201    scoped_ptr<ServiceWorkerHandle> handle) {
202  int handle_id = handle->handle_id();
203  handles_.AddWithID(handle.release(), handle_id);
204}
205
206void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationHandle(
207    scoped_ptr<ServiceWorkerRegistrationHandle> handle) {
208  int handle_id = handle->handle_id();
209  registration_handles_.AddWithID(handle.release(), handle_id);
210}
211
212void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
213    int thread_id,
214    int request_id,
215    int provider_id,
216    const GURL& pattern,
217    const GURL& script_url) {
218  TRACE_EVENT0("ServiceWorker",
219               "ServiceWorkerDispatcherHost::OnRegisterServiceWorker");
220  if (!GetContext()) {
221    Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
222        thread_id,
223        request_id,
224        WebServiceWorkerError::ErrorTypeAbort,
225        base::ASCIIToUTF16(kShutdownErrorMessage)));
226    return;
227  }
228
229  ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
230      render_process_id_, provider_id);
231  if (!provider_host) {
232    BadMessageReceived();
233    return;
234  }
235  if (!provider_host->IsContextAlive()) {
236    Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
237        thread_id,
238        request_id,
239        WebServiceWorkerError::ErrorTypeAbort,
240        base::ASCIIToUTF16(kShutdownErrorMessage)));
241    return;
242  }
243
244  if (!CanRegisterServiceWorker(
245      provider_host->document_url(), pattern, script_url)) {
246    BadMessageReceived();
247    return;
248  }
249  TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
250                           "ServiceWorkerDispatcherHost::RegisterServiceWorker",
251                           request_id,
252                           "Pattern", pattern.spec(),
253                           "Script URL", script_url.spec());
254  GetContext()->RegisterServiceWorker(
255      pattern,
256      script_url,
257      provider_host,
258      base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete,
259                 this,
260                 thread_id,
261                 provider_id,
262                 request_id));
263}
264
265void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
266    int thread_id,
267    int request_id,
268    int provider_id,
269    const GURL& pattern) {
270  TRACE_EVENT0("ServiceWorker",
271               "ServiceWorkerDispatcherHost::OnUnregisterServiceWorker");
272  if (!GetContext()) {
273    Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
274        thread_id,
275        request_id,
276        blink::WebServiceWorkerError::ErrorTypeAbort,
277        base::ASCIIToUTF16(kShutdownErrorMessage)));
278    return;
279  }
280
281  ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
282      render_process_id_, provider_id);
283  if (!provider_host) {
284    BadMessageReceived();
285    return;
286  }
287  if (!provider_host->IsContextAlive()) {
288    Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
289        thread_id,
290        request_id,
291        blink::WebServiceWorkerError::ErrorTypeAbort,
292        base::ASCIIToUTF16(kShutdownErrorMessage)));
293    return;
294  }
295
296  if (!CanUnregisterServiceWorker(provider_host->document_url(), pattern)) {
297    BadMessageReceived();
298    return;
299  }
300
301  TRACE_EVENT_ASYNC_BEGIN1(
302      "ServiceWorker",
303      "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
304      request_id,
305      "Pattern", pattern.spec());
306  GetContext()->UnregisterServiceWorker(
307      pattern,
308      base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete,
309                 this,
310                 thread_id,
311                 request_id));
312}
313
314void ServiceWorkerDispatcherHost::OnGetRegistration(
315    int thread_id,
316    int request_id,
317    int provider_id,
318    const GURL& document_url) {
319  TRACE_EVENT0("ServiceWorker",
320               "ServiceWorkerDispatcherHost::OnGetRegistration");
321  if (!GetContext()) {
322    Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
323        thread_id,
324        request_id,
325        blink::WebServiceWorkerError::ErrorTypeAbort,
326        base::ASCIIToUTF16(kShutdownErrorMessage)));
327    return;
328  }
329
330  ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
331      render_process_id_, provider_id);
332  if (!provider_host) {
333    BadMessageReceived();
334    return;
335  }
336  if (!provider_host->IsContextAlive()) {
337    Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
338        thread_id,
339        request_id,
340        blink::WebServiceWorkerError::ErrorTypeAbort,
341        base::ASCIIToUTF16(kShutdownErrorMessage)));
342    return;
343  }
344
345  if (!CanGetRegistration(provider_host->document_url(), document_url)) {
346    BadMessageReceived();
347    return;
348  }
349
350  DCHECK_CURRENTLY_ON(BrowserThread::IO);
351  if (GetContext()->storage()->IsDisabled()) {
352    SendGetRegistrationError(thread_id, request_id, SERVICE_WORKER_ERROR_ABORT);
353    return;
354  }
355
356  TRACE_EVENT_ASYNC_BEGIN1(
357      "ServiceWorker",
358      "ServiceWorkerDispatcherHost::GetRegistration",
359      request_id,
360      "Document URL", document_url.spec());
361
362  GetContext()->storage()->FindRegistrationForDocument(
363      document_url,
364      base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationComplete,
365                 this,
366                 thread_id,
367                 provider_id,
368                 request_id));
369}
370
371void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
372    int handle_id,
373    const base::string16& message,
374    const std::vector<int>& sent_message_port_ids) {
375  TRACE_EVENT0("ServiceWorker",
376               "ServiceWorkerDispatcherHost::OnPostMessageToWorker");
377  if (!GetContext())
378    return;
379
380  ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
381  if (!handle) {
382    BadMessageReceived();
383    return;
384  }
385
386  std::vector<int> new_routing_ids;
387  message_port_message_filter_->UpdateMessagePortsWithNewRoutes(
388      sent_message_port_ids, &new_routing_ids);
389  handle->version()->SendMessage(
390      ServiceWorkerMsg_MessageToWorker(message,
391                                       sent_message_port_ids,
392                                       new_routing_ids),
393      base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
394}
395
396void ServiceWorkerDispatcherHost::OnProviderCreated(int provider_id) {
397  TRACE_EVENT0("ServiceWorker",
398               "ServiceWorkerDispatcherHost::OnProviderCreated");
399  if (!GetContext())
400    return;
401  if (GetContext()->GetProviderHost(render_process_id_, provider_id)) {
402    BadMessageReceived();
403    return;
404  }
405  scoped_ptr<ServiceWorkerProviderHost> provider_host(
406      new ServiceWorkerProviderHost(
407          render_process_id_, provider_id, GetContext()->AsWeakPtr(), this));
408  GetContext()->AddProviderHost(provider_host.Pass());
409}
410
411void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
412  TRACE_EVENT0("ServiceWorker",
413               "ServiceWorkerDispatcherHost::OnProviderDestroyed");
414  if (!GetContext())
415    return;
416  if (!GetContext()->GetProviderHost(render_process_id_, provider_id)) {
417    BadMessageReceived();
418    return;
419  }
420  GetContext()->RemoveProviderHost(render_process_id_, provider_id);
421}
422
423void ServiceWorkerDispatcherHost::OnSetHostedVersionId(
424    int provider_id, int64 version_id) {
425  TRACE_EVENT0("ServiceWorker",
426               "ServiceWorkerDispatcherHost::OnSetHostedVersionId");
427  if (!GetContext())
428    return;
429  ServiceWorkerProviderHost* provider_host =
430      GetContext()->GetProviderHost(render_process_id_, provider_id);
431  if (!provider_host) {
432    BadMessageReceived();
433    return;
434  }
435  if (!provider_host->IsContextAlive())
436    return;
437  if (!provider_host->SetHostedVersionId(version_id))
438    BadMessageReceived();
439}
440
441ServiceWorkerRegistrationHandle*
442ServiceWorkerDispatcherHost::FindRegistrationHandle(int provider_id,
443                                                    int64 registration_id) {
444  for (IDMap<ServiceWorkerRegistrationHandle, IDMapOwnPointer>::iterator
445           iter(&registration_handles_);
446       !iter.IsAtEnd();
447       iter.Advance()) {
448    ServiceWorkerRegistrationHandle* handle = iter.GetCurrentValue();
449    DCHECK(handle);
450    if (handle->provider_id() == provider_id && handle->registration() &&
451        handle->registration()->id() == registration_id) {
452      return handle;
453    }
454  }
455  return NULL;
456}
457
458void ServiceWorkerDispatcherHost::GetRegistrationObjectInfoAndVersionAttributes(
459    int provider_id,
460    ServiceWorkerRegistration* registration,
461    ServiceWorkerRegistrationObjectInfo* info,
462    ServiceWorkerVersionAttributes* attrs) {
463  ServiceWorkerRegistrationHandle* handle =
464    GetOrCreateRegistrationHandle(provider_id, registration);
465  *info = handle->GetObjectInfo();
466
467  attrs->installing = handle->CreateServiceWorkerHandleAndPass(
468      registration->installing_version());
469  attrs->waiting = handle->CreateServiceWorkerHandleAndPass(
470      registration->waiting_version());
471  attrs->active = handle->CreateServiceWorkerHandleAndPass(
472      registration->active_version());
473}
474
475void ServiceWorkerDispatcherHost::RegistrationComplete(
476    int thread_id,
477    int provider_id,
478    int request_id,
479    ServiceWorkerStatusCode status,
480    int64 registration_id,
481    int64 version_id) {
482  if (!GetContext())
483    return;
484
485  if (status != SERVICE_WORKER_OK) {
486    SendRegistrationError(thread_id, request_id, status);
487    return;
488  }
489
490  ServiceWorkerRegistration* registration =
491      GetContext()->GetLiveRegistration(registration_id);
492  DCHECK(registration);
493
494  ServiceWorkerRegistrationObjectInfo info;
495  ServiceWorkerVersionAttributes attrs;
496  GetRegistrationObjectInfoAndVersionAttributes(
497      provider_id, registration, &info, &attrs);
498
499  Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
500      thread_id, request_id, info, attrs));
501  TRACE_EVENT_ASYNC_END2("ServiceWorker",
502                         "ServiceWorkerDispatcherHost::RegisterServiceWorker",
503                         request_id,
504                         "Registration ID", registration_id,
505                         "Version ID", version_id);
506}
507
508void ServiceWorkerDispatcherHost::OnWorkerReadyForInspection(
509    int embedded_worker_id) {
510  TRACE_EVENT0("ServiceWorker",
511               "ServiceWorkerDispatcherHost::OnWorkerReadyForInspection");
512  if (!GetContext())
513    return;
514  EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
515  if (!registry->CanHandle(embedded_worker_id))
516    return;
517  registry->OnWorkerReadyForInspection(render_process_id_, embedded_worker_id);
518}
519
520void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(
521    int embedded_worker_id,
522    int thread_id) {
523  TRACE_EVENT0("ServiceWorker",
524               "ServiceWorkerDispatcherHost::OnWorkerScriptLoaded");
525  if (!GetContext())
526    return;
527  EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
528  if (!registry->CanHandle(embedded_worker_id))
529    return;
530  registry->OnWorkerScriptLoaded(
531      render_process_id_, thread_id, embedded_worker_id);
532}
533
534void ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed(
535    int embedded_worker_id) {
536  TRACE_EVENT0("ServiceWorker",
537               "ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed");
538  if (!GetContext())
539    return;
540  EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
541  if (!registry->CanHandle(embedded_worker_id))
542    return;
543  registry->OnWorkerScriptLoadFailed(render_process_id_, embedded_worker_id);
544}
545
546void ServiceWorkerDispatcherHost::OnWorkerStarted(int embedded_worker_id) {
547  TRACE_EVENT0("ServiceWorker",
548               "ServiceWorkerDispatcherHost::OnWorkerStarted");
549  if (!GetContext())
550    return;
551  EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
552  if (!registry->CanHandle(embedded_worker_id))
553    return;
554  registry->OnWorkerStarted(render_process_id_, embedded_worker_id);
555}
556
557void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) {
558  TRACE_EVENT0("ServiceWorker",
559               "ServiceWorkerDispatcherHost::OnWorkerStopped");
560  if (!GetContext())
561    return;
562  EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
563  if (!registry->CanHandle(embedded_worker_id))
564    return;
565  registry->OnWorkerStopped(render_process_id_, embedded_worker_id);
566}
567
568void ServiceWorkerDispatcherHost::OnPausedAfterDownload(
569    int embedded_worker_id) {
570  TRACE_EVENT0("ServiceWorker",
571               "ServiceWorkerDispatcherHost::OnPausedAfterDownload");
572  if (!GetContext())
573    return;
574  GetContext()->embedded_worker_registry()->OnPausedAfterDownload(
575      render_process_id_, embedded_worker_id);
576}
577
578void ServiceWorkerDispatcherHost::OnReportException(
579    int embedded_worker_id,
580    const base::string16& error_message,
581    int line_number,
582    int column_number,
583    const GURL& source_url) {
584  TRACE_EVENT0("ServiceWorker",
585               "ServiceWorkerDispatcherHost::OnReportException");
586  if (!GetContext())
587    return;
588  EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
589  if (!registry->CanHandle(embedded_worker_id))
590    return;
591  registry->OnReportException(embedded_worker_id,
592                              error_message,
593                              line_number,
594                              column_number,
595                              source_url);
596}
597
598void ServiceWorkerDispatcherHost::OnReportConsoleMessage(
599    int embedded_worker_id,
600    const EmbeddedWorkerHostMsg_ReportConsoleMessage_Params& params) {
601  TRACE_EVENT0("ServiceWorker",
602               "ServiceWorkerDispatcherHost::OnReportConsoleMessage");
603  if (!GetContext())
604    return;
605  EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
606  if (!registry->CanHandle(embedded_worker_id))
607    return;
608  registry->OnReportConsoleMessage(embedded_worker_id,
609                                   params.source_identifier,
610                                   params.message_level,
611                                   params.message,
612                                   params.line_number,
613                                   params.source_url);
614}
615
616void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
617    int handle_id) {
618  TRACE_EVENT0("ServiceWorker",
619               "ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount");
620  ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
621  if (!handle) {
622    BadMessageReceived();
623    return;
624  }
625  handle->IncrementRefCount();
626}
627
628void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
629    int handle_id) {
630  TRACE_EVENT0("ServiceWorker",
631               "ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount");
632  ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
633  if (!handle) {
634    BadMessageReceived();
635    return;
636  }
637  handle->DecrementRefCount();
638  if (handle->HasNoRefCount())
639    handles_.Remove(handle_id);
640}
641
642void ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount(
643    int registration_handle_id) {
644  TRACE_EVENT0("ServiceWorker",
645               "ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount");
646  ServiceWorkerRegistrationHandle* handle =
647      registration_handles_.Lookup(registration_handle_id);
648  if (!handle) {
649    BadMessageReceived();
650    return;
651  }
652  handle->IncrementRefCount();
653}
654
655void ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount(
656    int registration_handle_id) {
657  TRACE_EVENT0("ServiceWorker",
658               "ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount");
659  ServiceWorkerRegistrationHandle* handle =
660      registration_handles_.Lookup(registration_handle_id);
661  if (!handle) {
662    BadMessageReceived();
663    return;
664  }
665  handle->DecrementRefCount();
666  if (handle->HasNoRefCount())
667    registration_handles_.Remove(registration_handle_id);
668}
669
670void ServiceWorkerDispatcherHost::UnregistrationComplete(
671    int thread_id,
672    int request_id,
673    ServiceWorkerStatusCode status) {
674  if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
675    SendUnregistrationError(thread_id, request_id, status);
676    return;
677  }
678  const bool is_success = (status == SERVICE_WORKER_OK);
679  Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id,
680                                                      request_id,
681                                                      is_success));
682  TRACE_EVENT_ASYNC_END1(
683      "ServiceWorker",
684      "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
685      request_id,
686      "Status", status);
687}
688
689void ServiceWorkerDispatcherHost::GetRegistrationComplete(
690    int thread_id,
691    int provider_id,
692    int request_id,
693    ServiceWorkerStatusCode status,
694    const scoped_refptr<ServiceWorkerRegistration>& registration) {
695  TRACE_EVENT_ASYNC_END1("ServiceWorker",
696                         "ServiceWorkerDispatcherHost::GetRegistration",
697                         request_id,
698                         "Registration ID",
699                         registration.get() ? registration->id()
700                             : kInvalidServiceWorkerRegistrationId);
701  if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
702    SendGetRegistrationError(thread_id, request_id, status);
703    return;
704  }
705
706  ServiceWorkerRegistrationObjectInfo info;
707  ServiceWorkerVersionAttributes attrs;
708  if (status == SERVICE_WORKER_OK) {
709    DCHECK(registration.get());
710    if (!registration->is_uninstalling()) {
711      GetRegistrationObjectInfoAndVersionAttributes(
712          provider_id, registration.get(), &info, &attrs);
713    }
714  }
715
716  Send(new ServiceWorkerMsg_DidGetRegistration(
717      thread_id, request_id, info, attrs));
718}
719
720void ServiceWorkerDispatcherHost::SendRegistrationError(
721    int thread_id,
722    int request_id,
723    ServiceWorkerStatusCode status) {
724  base::string16 error_message;
725  blink::WebServiceWorkerError::ErrorType error_type;
726  GetServiceWorkerRegistrationStatusResponse(
727      status, &error_type, &error_message);
728  Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
729      thread_id, request_id, error_type, error_message));
730}
731
732void ServiceWorkerDispatcherHost::SendUnregistrationError(
733    int thread_id,
734    int request_id,
735    ServiceWorkerStatusCode status) {
736  base::string16 error_message;
737  blink::WebServiceWorkerError::ErrorType error_type;
738  GetServiceWorkerRegistrationStatusResponse(
739      status, &error_type, &error_message);
740  Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
741      thread_id, request_id, error_type, error_message));
742}
743
744void ServiceWorkerDispatcherHost::SendGetRegistrationError(
745    int thread_id,
746    int request_id,
747    ServiceWorkerStatusCode status) {
748  base::string16 error_message;
749  blink::WebServiceWorkerError::ErrorType error_type;
750  GetServiceWorkerRegistrationStatusResponse(
751      status, &error_type, &error_message);
752  Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
753      thread_id, request_id, error_type, error_message));
754}
755
756ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
757  return context_wrapper_->context();
758}
759
760}  // namespace content
761