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