Home | History | Annotate | Download | only in service_worker
      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 
     25 using blink::WebServiceWorkerError;
     26 
     27 namespace content {
     28 
     29 namespace {
     30 
     31 const char kShutdownErrorMessage[] =
     32     "The Service Worker system has shutdown.";
     33 
     34 const 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.
     42 bool 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 
     51 bool 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 
     58 bool 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 
     67 ServiceWorkerDispatcherHost::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 
     77 ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
     78   if (GetContext()) {
     79     GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
     80     GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
     81         render_process_id_);
     82   }
     83 }
     84 
     85 void 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 
     99 void 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 
    111 void ServiceWorkerDispatcherHost::OnDestruct() const {
    112   BrowserThread::DeleteOnIOThread::Destruct(this);
    113 }
    114 
    115 bool 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 
    170 bool 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 
    181 ServiceWorkerRegistrationHandle*
    182 ServiceWorkerDispatcherHost::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 
    200 void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle(
    201     scoped_ptr<ServiceWorkerHandle> handle) {
    202   int handle_id = handle->handle_id();
    203   handles_.AddWithID(handle.release(), handle_id);
    204 }
    205 
    206 void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationHandle(
    207     scoped_ptr<ServiceWorkerRegistrationHandle> handle) {
    208   int handle_id = handle->handle_id();
    209   registration_handles_.AddWithID(handle.release(), handle_id);
    210 }
    211 
    212 void 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 
    265 void 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 
    314 void 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 
    371 void 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 
    396 void 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 
    411 void 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 
    423 void 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 
    441 ServiceWorkerRegistrationHandle*
    442 ServiceWorkerDispatcherHost::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 
    458 void 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 
    475 void 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 
    508 void 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 
    520 void 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 
    534 void 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 
    546 void 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 
    557 void 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 
    568 void 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 
    578 void 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 
    598 void 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 
    616 void 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 
    628 void 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 
    642 void 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 
    655 void 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 
    670 void 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 
    689 void 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 
    720 void 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 
    732 void 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 
    744 void 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 
    756 ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
    757   return context_wrapper_->context();
    758 }
    759 
    760 }  // namespace content
    761