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