Home | History | Annotate | Download | only in service_worker
      1 // Copyright 2014 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/child/service_worker/service_worker_provider_context.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/message_loop/message_loop_proxy.h"
      9 #include "base/stl_util.h"
     10 #include "content/child/child_thread.h"
     11 #include "content/child/service_worker/service_worker_dispatcher.h"
     12 #include "content/child/service_worker/service_worker_handle_reference.h"
     13 #include "content/child/service_worker/service_worker_registration_handle_reference.h"
     14 #include "content/child/thread_safe_sender.h"
     15 #include "content/child/worker_task_runner.h"
     16 #include "content/common/service_worker/service_worker_messages.h"
     17 
     18 namespace content {
     19 
     20 ServiceWorkerProviderContext::ServiceWorkerProviderContext(int provider_id)
     21     : provider_id_(provider_id),
     22       main_thread_loop_proxy_(base::MessageLoopProxy::current()) {
     23   if (!ChildThread::current())
     24     return;  // May be null in some tests.
     25   thread_safe_sender_ = ChildThread::current()->thread_safe_sender();
     26   ServiceWorkerDispatcher* dispatcher =
     27       ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
     28           thread_safe_sender_.get());
     29   DCHECK(dispatcher);
     30   dispatcher->AddProviderContext(this);
     31 }
     32 
     33 ServiceWorkerProviderContext::~ServiceWorkerProviderContext() {
     34   if (ServiceWorkerDispatcher* dispatcher =
     35           ServiceWorkerDispatcher::GetThreadSpecificInstance()) {
     36     dispatcher->RemoveProviderContext(this);
     37   }
     38 }
     39 
     40 ServiceWorkerHandleReference* ServiceWorkerProviderContext::installing() {
     41   DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
     42   return installing_.get();
     43 }
     44 
     45 ServiceWorkerHandleReference* ServiceWorkerProviderContext::waiting() {
     46   DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
     47   return waiting_.get();
     48 }
     49 
     50 ServiceWorkerHandleReference* ServiceWorkerProviderContext::active() {
     51   DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
     52   return active_.get();
     53 }
     54 
     55 ServiceWorkerHandleReference* ServiceWorkerProviderContext::controller() {
     56   DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
     57   return controller_.get();
     58 }
     59 
     60 ServiceWorkerRegistrationHandleReference*
     61 ServiceWorkerProviderContext::registration() {
     62   DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
     63   return registration_.get();
     64 }
     65 
     66 ServiceWorkerVersionAttributes
     67 ServiceWorkerProviderContext::GetVersionAttributes() {
     68   ServiceWorkerVersionAttributes attrs;
     69   if (installing())
     70     attrs.installing = installing()->info();
     71   if (waiting())
     72     attrs.waiting = waiting()->info();
     73   if (active())
     74     attrs.active = active()->info();
     75   return attrs;
     76 }
     77 
     78 void ServiceWorkerProviderContext::OnAssociateRegistration(
     79     const ServiceWorkerRegistrationObjectInfo& info,
     80     const ServiceWorkerVersionAttributes& attrs) {
     81   DCHECK(!registration_);
     82   DCHECK_NE(kInvalidServiceWorkerRegistrationHandleId, info.handle_id);
     83   registration_ = ServiceWorkerRegistrationHandleReference::Adopt(
     84       info, thread_safe_sender_.get());
     85   installing_ = ServiceWorkerHandleReference::Adopt(
     86       attrs.installing, thread_safe_sender_.get());
     87   waiting_ = ServiceWorkerHandleReference::Adopt(
     88       attrs.waiting, thread_safe_sender_.get());
     89   active_ = ServiceWorkerHandleReference::Adopt(
     90       attrs.active, thread_safe_sender_.get());
     91 }
     92 
     93 void ServiceWorkerProviderContext::OnDisassociateRegistration() {
     94   controller_.reset();
     95   active_.reset();
     96   waiting_.reset();
     97   installing_.reset();
     98   registration_.reset();
     99 }
    100 
    101 void ServiceWorkerProviderContext::OnServiceWorkerStateChanged(
    102     int handle_id,
    103     blink::WebServiceWorkerState state) {
    104   ServiceWorkerHandleReference* which = NULL;
    105   if (handle_id == controller_handle_id())
    106     which = controller_.get();
    107   else if (handle_id == active_handle_id())
    108     which = active_.get();
    109   else if (handle_id == waiting_handle_id())
    110     which = waiting_.get();
    111   else if (handle_id == installing_handle_id())
    112     which = installing_.get();
    113 
    114   // We should only get messages for ServiceWorkers associated with
    115   // this provider.
    116   DCHECK(which);
    117 
    118   which->set_state(state);
    119 
    120   // TODO(kinuko): We can forward the message to other threads here
    121   // when we support navigator.serviceWorker in dedicated workers.
    122 }
    123 
    124 void ServiceWorkerProviderContext::OnSetInstallingServiceWorker(
    125     int registration_handle_id,
    126     const ServiceWorkerObjectInfo& info) {
    127   DCHECK(IsAssociatedWithRegistration(registration_handle_id));
    128   installing_ =
    129       ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
    130 }
    131 
    132 void ServiceWorkerProviderContext::OnSetWaitingServiceWorker(
    133     int registration_handle_id,
    134     const ServiceWorkerObjectInfo& info) {
    135   DCHECK(IsAssociatedWithRegistration(registration_handle_id));
    136   waiting_ =
    137       ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
    138 }
    139 
    140 void ServiceWorkerProviderContext::OnSetActiveServiceWorker(
    141     int registration_handle_id,
    142     const ServiceWorkerObjectInfo& info) {
    143   DCHECK(IsAssociatedWithRegistration(registration_handle_id));
    144   active_ =
    145       ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
    146 }
    147 
    148 void ServiceWorkerProviderContext::OnSetControllerServiceWorker(
    149     int registration_handle_id,
    150     const ServiceWorkerObjectInfo& info) {
    151   DCHECK(IsAssociatedWithRegistration(registration_handle_id));
    152 
    153   // This context is is the primary owner of this handle, keeps the
    154   // initial reference until it goes away.
    155   controller_ =
    156       ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
    157 
    158   // TODO(kinuko): We can forward the message to other threads here
    159   // when we support navigator.serviceWorker in dedicated workers.
    160 }
    161 
    162 int ServiceWorkerProviderContext::installing_handle_id() const {
    163   DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
    164   return installing_ ? installing_->info().handle_id
    165                      : kInvalidServiceWorkerHandleId;
    166 }
    167 
    168 int ServiceWorkerProviderContext::waiting_handle_id() const {
    169   DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
    170   return waiting_ ? waiting_->info().handle_id
    171                   : kInvalidServiceWorkerHandleId;
    172 }
    173 
    174 int ServiceWorkerProviderContext::active_handle_id() const {
    175   DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
    176   return active_ ? active_->info().handle_id
    177                  : kInvalidServiceWorkerHandleId;
    178 }
    179 
    180 int ServiceWorkerProviderContext::controller_handle_id() const {
    181   DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
    182   return controller_ ? controller_->info().handle_id
    183                      : kInvalidServiceWorkerHandleId;
    184 }
    185 
    186 int ServiceWorkerProviderContext::registration_handle_id() const {
    187   DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
    188   return registration_ ? registration_->info().handle_id
    189                        : kInvalidServiceWorkerRegistrationHandleId;
    190 }
    191 
    192 bool ServiceWorkerProviderContext::IsAssociatedWithRegistration(
    193     int registration_handle_id) const {
    194   if (!registration_)
    195     return false;
    196   if (registration_handle_id == kInvalidServiceWorkerRegistrationHandleId)
    197     return false;
    198   return registration_->info().handle_id == registration_handle_id;
    199 }
    200 
    201 }  // namespace content
    202