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 #ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_VERSION_H_
      6 #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_VERSION_H_
      7 
      8 #include <map>
      9 #include <string>
     10 #include <vector>
     11 
     12 #include "base/basictypes.h"
     13 #include "base/callback.h"
     14 #include "base/gtest_prod_util.h"
     15 #include "base/id_map.h"
     16 #include "base/memory/ref_counted.h"
     17 #include "base/memory/scoped_ptr.h"
     18 #include "base/observer_list.h"
     19 #include "base/timer/timer.h"
     20 #include "content/browser/service_worker/embedded_worker_instance.h"
     21 #include "content/browser/service_worker/service_worker_cache_listener.h"
     22 #include "content/browser/service_worker/service_worker_script_cache_map.h"
     23 #include "content/common/content_export.h"
     24 #include "content/common/service_worker/service_worker_status_code.h"
     25 #include "content/common/service_worker/service_worker_types.h"
     26 #include "third_party/WebKit/public/platform/WebServiceWorkerEventResult.h"
     27 
     28 class GURL;
     29 
     30 namespace content {
     31 
     32 class EmbeddedWorkerRegistry;
     33 class ServiceWorkerContextCore;
     34 class ServiceWorkerProviderHost;
     35 class ServiceWorkerRegistration;
     36 class ServiceWorkerVersionInfo;
     37 
     38 // This class corresponds to a specific version of a ServiceWorker
     39 // script for a given pattern. When a script is upgraded, there may be
     40 // more than one ServiceWorkerVersion "running" at a time, but only
     41 // one of them is activated. This class connects the actual script with a
     42 // running worker.
     43 class CONTENT_EXPORT ServiceWorkerVersion
     44     : NON_EXPORTED_BASE(public base::RefCounted<ServiceWorkerVersion>),
     45       public EmbeddedWorkerInstance::Listener {
     46  public:
     47   typedef base::Callback<void(ServiceWorkerStatusCode)> StatusCallback;
     48   typedef base::Callback<void(ServiceWorkerStatusCode,
     49                               const IPC::Message& message)> MessageCallback;
     50   typedef base::Callback<void(ServiceWorkerStatusCode,
     51                               ServiceWorkerFetchEventResult,
     52                               const ServiceWorkerResponse&)> FetchCallback;
     53 
     54   enum RunningStatus {
     55     STOPPED = EmbeddedWorkerInstance::STOPPED,
     56     STARTING = EmbeddedWorkerInstance::STARTING,
     57     RUNNING = EmbeddedWorkerInstance::RUNNING,
     58     STOPPING = EmbeddedWorkerInstance::STOPPING,
     59   };
     60 
     61   // Current version status; some of the status (e.g. INSTALLED and ACTIVATED)
     62   // should be persisted unlike running status.
     63   enum Status {
     64     NEW,         // The version is just created.
     65     INSTALLING,  // Install event is dispatched and being handled.
     66     INSTALLED,   // Install event is finished and is ready to be activated.
     67     ACTIVATING,  // Activate event is dispatched and being handled.
     68     ACTIVATED,   // Activation is finished and can run as activated.
     69     REDUNDANT,   // The version is no longer running as activated, due to
     70                  // unregistration or replace.
     71   };
     72 
     73   class Listener {
     74    public:
     75     virtual void OnWorkerStarted(ServiceWorkerVersion* version) {}
     76     virtual void OnWorkerStopped(ServiceWorkerVersion* version) {}
     77     virtual void OnVersionStateChanged(ServiceWorkerVersion* version) {}
     78     virtual void OnErrorReported(ServiceWorkerVersion* version,
     79                                  const base::string16& error_message,
     80                                  int line_number,
     81                                  int column_number,
     82                                  const GURL& source_url) {}
     83     virtual void OnReportConsoleMessage(ServiceWorkerVersion* version,
     84                                         int source_identifier,
     85                                         int message_level,
     86                                         const base::string16& message,
     87                                         int line_number,
     88                                         const GURL& source_url) {}
     89     // Fires when a version transitions from having a controllee to not.
     90     virtual void OnNoControllees(ServiceWorkerVersion* version) {}
     91 
     92    protected:
     93     virtual ~Listener() {}
     94   };
     95 
     96   ServiceWorkerVersion(
     97       ServiceWorkerRegistration* registration,
     98       const GURL& script_url,
     99       int64 version_id,
    100       base::WeakPtr<ServiceWorkerContextCore> context);
    101 
    102   int64 version_id() const { return version_id_; }
    103   int64 registration_id() const { return registration_id_; }
    104   const GURL& script_url() const { return script_url_; }
    105   const GURL& scope() const { return scope_; }
    106   RunningStatus running_status() const {
    107     return static_cast<RunningStatus>(embedded_worker_->status());
    108   }
    109   ServiceWorkerVersionInfo GetInfo();
    110   Status status() const { return status_; }
    111 
    112   // This sets the new status and also run status change callbacks
    113   // if there're any (see RegisterStatusChangeCallback).
    114   void SetStatus(Status status);
    115 
    116   // Registers status change callback. (This is for one-off observation,
    117   // the consumer needs to re-register if it wants to continue observing
    118   // status changes)
    119   void RegisterStatusChangeCallback(const base::Closure& callback);
    120 
    121   // Starts an embedded worker for this version.
    122   // This returns OK (success) if the worker is already running.
    123   void StartWorker(const StatusCallback& callback);
    124 
    125   // Starts an embedded worker for this version.
    126   // |pause_after_download| notifies worker to pause after download finished
    127   // which could be resumed by EmbeddedWorkerInstance::ResumeAfterDownload.
    128   // This returns OK (success) if the worker is already running.
    129   void StartWorker(bool pause_after_download,
    130                    const StatusCallback& callback);
    131 
    132   // Stops an embedded worker for this version.
    133   // This returns OK (success) if the worker is already stopped.
    134   void StopWorker(const StatusCallback& callback);
    135 
    136   // Schedules an update to be run 'soon'.
    137   void ScheduleUpdate();
    138 
    139   // If an update is scheduled but not yet started, this resets the timer
    140   // delaying the start time by a 'small' amount.
    141   void DeferScheduledUpdate();
    142 
    143   // Starts an update now.
    144   void StartUpdate();
    145 
    146   // Sends an IPC message to the worker.
    147   // If the worker is not running this first tries to start it by
    148   // calling StartWorker internally.
    149   // |callback| can be null if the sender does not need to know if the
    150   // message is successfully sent or not.
    151   void SendMessage(const IPC::Message& message, const StatusCallback& callback);
    152 
    153   // Sends install event to the associated embedded worker and asynchronously
    154   // calls |callback| when it errors out or it gets response from the worker
    155   // to notify install completion.
    156   // |active_version_id| must be a valid positive ID
    157   // if there's an activated (previous) version running.
    158   //
    159   // This must be called when the status() is NEW. Calling this changes
    160   // the version's status to INSTALLING.
    161   // Upon completion, the version's status will be changed to INSTALLED
    162   // on success, or back to NEW on failure.
    163   void DispatchInstallEvent(int active_version_id,
    164                             const StatusCallback& callback);
    165 
    166   // Sends activate event to the associated embedded worker and asynchronously
    167   // calls |callback| when it errors out or it gets response from the worker
    168   // to notify activation completion.
    169   //
    170   // This must be called when the status() is INSTALLED. Calling this changes
    171   // the version's status to ACTIVATING.
    172   // Upon completion, the version's status will be changed to ACTIVATED
    173   // on success, or back to INSTALLED on failure.
    174   void DispatchActivateEvent(const StatusCallback& callback);
    175 
    176   // Sends fetch event to the associated embedded worker and calls
    177   // |callback| with the response from the worker.
    178   //
    179   // This must be called when the status() is ACTIVATED. Calling this in other
    180   // statuses will result in an error SERVICE_WORKER_ERROR_FAILED.
    181   void DispatchFetchEvent(const ServiceWorkerFetchRequest& request,
    182                           const base::Closure& prepare_callback,
    183                           const FetchCallback& fetch_callback);
    184 
    185   // Sends sync event to the associated embedded worker and asynchronously calls
    186   // |callback| when it errors out or it gets response from the worker to notify
    187   // completion.
    188   //
    189   // This must be called when the status() is ACTIVATED.
    190   void DispatchSyncEvent(const StatusCallback& callback);
    191 
    192   // Sends push event to the associated embedded worker and asynchronously calls
    193   // |callback| when it errors out or it gets response from the worker to notify
    194   // completion.
    195   //
    196   // This must be called when the status() is ACTIVATED.
    197   void DispatchPushEvent(const StatusCallback& callback,
    198                          const std::string& data);
    199 
    200   // Adds and removes |provider_host| as a controllee of this ServiceWorker.
    201   // A potential controllee is a host having the version as its .installing
    202   // or .waiting version.
    203   void AddControllee(ServiceWorkerProviderHost* provider_host);
    204   void RemoveControllee(ServiceWorkerProviderHost* provider_host);
    205 
    206   // Returns if it has controllee.
    207   bool HasControllee() const { return !controllee_map_.empty(); }
    208 
    209   // Adds and removes Listeners.
    210   void AddListener(Listener* listener);
    211   void RemoveListener(Listener* listener);
    212 
    213   ServiceWorkerScriptCacheMap* script_cache_map() { return &script_cache_map_; }
    214   EmbeddedWorkerInstance* embedded_worker() { return embedded_worker_.get(); }
    215 
    216   // Dooms this version to have REDUNDANT status and its resources deleted.  If
    217   // the version is controlling a page, these changes will happen when the
    218   // version no longer controls any pages.
    219   void Doom();
    220   bool is_doomed() const { return is_doomed_; }
    221 
    222  private:
    223   friend class base::RefCounted<ServiceWorkerVersion>;
    224   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTest,
    225                            ActivateWaitingVersion);
    226   typedef ServiceWorkerVersion self;
    227   typedef std::map<ServiceWorkerProviderHost*, int> ControlleeMap;
    228   typedef IDMap<ServiceWorkerProviderHost> ControlleeByIDMap;
    229   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, ScheduleStopWorker);
    230 
    231   virtual ~ServiceWorkerVersion();
    232 
    233   // EmbeddedWorkerInstance::Listener overrides:
    234   virtual void OnStarted() OVERRIDE;
    235   virtual void OnStopped() OVERRIDE;
    236   virtual void OnReportException(const base::string16& error_message,
    237                                  int line_number,
    238                                  int column_number,
    239                                  const GURL& source_url) OVERRIDE;
    240   virtual void OnReportConsoleMessage(int source_identifier,
    241                                       int message_level,
    242                                       const base::string16& message,
    243                                       int line_number,
    244                                       const GURL& source_url) OVERRIDE;
    245   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
    246 
    247   void RunStartWorkerCallbacksOnError(ServiceWorkerStatusCode status);
    248 
    249   void DispatchInstallEventAfterStartWorker(int active_version_id,
    250                                             const StatusCallback& callback);
    251   void DispatchActivateEventAfterStartWorker(const StatusCallback& callback);
    252 
    253   // Message handlers.
    254   void OnGetClientDocuments(int request_id);
    255   void OnActivateEventFinished(int request_id,
    256                                blink::WebServiceWorkerEventResult result);
    257   void OnInstallEventFinished(int request_id,
    258                               blink::WebServiceWorkerEventResult result);
    259   void OnFetchEventFinished(int request_id,
    260                             ServiceWorkerFetchEventResult result,
    261                             const ServiceWorkerResponse& response);
    262   void OnSyncEventFinished(int request_id);
    263   void OnPushEventFinished(int request_id);
    264   void OnPostMessageToDocument(int client_id,
    265                                const base::string16& message,
    266                                const std::vector<int>& sent_message_port_ids);
    267 
    268   void ScheduleStopWorker();
    269   void DoomInternal();
    270 
    271   const int64 version_id_;
    272   int64 registration_id_;
    273   GURL script_url_;
    274   GURL scope_;
    275   Status status_;
    276   scoped_ptr<EmbeddedWorkerInstance> embedded_worker_;
    277   scoped_ptr<ServiceWorkerCacheListener> cache_listener_;
    278   std::vector<StatusCallback> start_callbacks_;
    279   std::vector<StatusCallback> stop_callbacks_;
    280   std::vector<base::Closure> status_change_callbacks_;
    281 
    282   // Message callbacks.
    283   IDMap<StatusCallback, IDMapOwnPointer> activate_callbacks_;
    284   IDMap<StatusCallback, IDMapOwnPointer> install_callbacks_;
    285   IDMap<FetchCallback, IDMapOwnPointer> fetch_callbacks_;
    286   IDMap<StatusCallback, IDMapOwnPointer> sync_callbacks_;
    287   IDMap<StatusCallback, IDMapOwnPointer> push_callbacks_;
    288 
    289   ControlleeMap controllee_map_;
    290   ControlleeByIDMap controllee_by_id_;
    291   base::WeakPtr<ServiceWorkerContextCore> context_;
    292   ObserverList<Listener> listeners_;
    293   ServiceWorkerScriptCacheMap script_cache_map_;
    294   base::OneShotTimer<ServiceWorkerVersion> stop_worker_timer_;
    295   base::OneShotTimer<ServiceWorkerVersion> update_timer_;
    296   bool is_doomed_;
    297 
    298   base::WeakPtrFactory<ServiceWorkerVersion> weak_factory_;
    299 
    300   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersion);
    301 };
    302 
    303 }  // namespace content
    304 
    305 #endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_VERSION_H_
    306