ServiceWorkerRegistrationInfo.h (9220B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_serviceworkerregistrationinfo_h 8 #define mozilla_dom_serviceworkerregistrationinfo_h 9 10 #include <functional> 11 12 #include "mozilla/dom/IPCNavigationPreloadState.h" 13 #include "mozilla/dom/ServiceWorkerInfo.h" 14 #include "mozilla/dom/ServiceWorkerLifetimeExtension.h" 15 #include "mozilla/dom/ServiceWorkerRegistrationBinding.h" 16 #include "mozilla/dom/ServiceWorkerRegistrationDescriptor.h" 17 #include "nsProxyRelease.h" 18 #include "nsTObserverArray.h" 19 20 namespace mozilla::dom { 21 22 class ServiceWorkerRegistrationListener; 23 24 class ServiceWorkerRegistrationInfo final 25 : public nsIServiceWorkerRegistrationInfo { 26 nsCOMPtr<nsIPrincipal> mPrincipal; 27 ServiceWorkerRegistrationDescriptor mDescriptor; 28 nsTArray<nsCOMPtr<nsIServiceWorkerRegistrationInfoListener>> mListeners; 29 nsTObserverArray<ServiceWorkerRegistrationListener*> mInstanceList; 30 31 struct VersionEntry { 32 const ServiceWorkerRegistrationDescriptor mDescriptor; 33 TimeStamp mTimeStamp; 34 35 explicit VersionEntry( 36 const ServiceWorkerRegistrationDescriptor& aDescriptor) 37 : mDescriptor(aDescriptor), mTimeStamp(TimeStamp::Now()) {} 38 }; 39 nsTArray<UniquePtr<VersionEntry>> mVersionList; 40 41 const nsID mAgentClusterId = nsID::GenerateUUID(); 42 43 uint32_t mControlledClientsCounter; 44 uint32_t mDelayMultiplier; 45 46 enum { NoUpdate, NeedTimeCheckAndUpdate, NeedUpdate } mUpdateState; 47 48 // Timestamp to track SWR's last update time 49 PRTime mCreationTime; 50 TimeStamp mCreationTimeStamp; 51 // The time of update is 0, if SWR've never been updated yet. 52 PRTime mLastUpdateTime; 53 54 RefPtr<ServiceWorkerInfo> mEvaluatingWorker; 55 RefPtr<ServiceWorkerInfo> mActiveWorker; 56 RefPtr<ServiceWorkerInfo> mWaitingWorker; 57 RefPtr<ServiceWorkerInfo> mInstallingWorker; 58 59 virtual ~ServiceWorkerRegistrationInfo(); 60 61 // When unregister() is called on a registration, it is removed from the 62 // "scope to registration map" but not immediately "cleared" (i.e. its workers 63 // terminated, updated to the redundant state, etc.) because it may still be 64 // controlling clients. It is marked as unregistered and when all controlled 65 // clients go away, cleared. This way we can tell if a registration 66 // is unregistered by querying the object itself rather than incurring a table 67 // lookup (in the case when the registrations are passed around as pointers). 68 bool mUnregistered; 69 70 bool mCorrupt; 71 72 IPCNavigationPreloadState mNavigationPreloadState; 73 int64_t mNumberOfAttemptedActivations{0}; 74 bool mIsBroken{false}; 75 int64_t mCacheAPIId{-1}; 76 77 public: 78 NS_DECL_ISUPPORTS 79 NS_DECL_NSISERVICEWORKERREGISTRATIONINFO 80 81 using TryToActivateCallback = std::function<void()>; 82 83 ServiceWorkerRegistrationInfo( 84 const nsACString& aScope, WorkerType aType, nsIPrincipal* aPrincipal, 85 ServiceWorkerUpdateViaCache aUpdateViaCache, 86 IPCNavigationPreloadState&& aNavigationPreloadState); 87 88 int64_t GetNumberOfAttemptedActivations() const { 89 return mNumberOfAttemptedActivations; 90 } 91 92 bool IsBroken() const { return mIsBroken; } 93 94 int64_t GetCacheAPIId() const { return mCacheAPIId; } 95 96 void AddInstance(ServiceWorkerRegistrationListener* aInstance, 97 const ServiceWorkerRegistrationDescriptor& aDescriptor); 98 99 void RemoveInstance(ServiceWorkerRegistrationListener* aInstance); 100 101 const nsCString& Scope() const; 102 103 WorkerType Type() const; 104 105 nsIPrincipal* Principal() const; 106 107 bool IsUnregistered() const; 108 109 void SetUnregistered(); 110 111 already_AddRefed<ServiceWorkerInfo> Newest() const { 112 RefPtr<ServiceWorkerInfo> newest; 113 if (mInstallingWorker) { 114 newest = mInstallingWorker; 115 } else if (mWaitingWorker) { 116 newest = mWaitingWorker; 117 } else { 118 newest = mActiveWorker; 119 } 120 121 return newest.forget(); 122 } 123 124 already_AddRefed<ServiceWorkerInfo> NewestIncludingEvaluating() const { 125 if (mEvaluatingWorker) { 126 RefPtr<ServiceWorkerInfo> newest = mEvaluatingWorker; 127 return newest.forget(); 128 } 129 return Newest(); 130 } 131 132 already_AddRefed<ServiceWorkerInfo> GetServiceWorkerInfoById(uint64_t aId); 133 134 void StartControllingClient() { 135 ++mControlledClientsCounter; 136 mDelayMultiplier = 0; 137 } 138 139 void StopControllingClient() { 140 MOZ_ASSERT(mControlledClientsCounter); 141 --mControlledClientsCounter; 142 } 143 144 bool IsControllingClients() const { 145 return mActiveWorker && mControlledClientsCounter; 146 } 147 148 // As a side effect, this nullifies 149 // `m{Evaluating,Installing,Waiting,Active}Worker`s. 150 void ShutdownWorkers(); 151 152 void Clear(); 153 154 void ClearAsCorrupt(); 155 156 bool IsCorrupt() const; 157 158 void TryToActivateAsync( 159 const ServiceWorkerLifetimeExtension& aLifetimeExtension, 160 TryToActivateCallback&& aCallback = nullptr); 161 162 void TryToActivate(ServiceWorkerLifetimeExtension&& aLifetimeExtension, 163 TryToActivateCallback&& aCallback); 164 165 void Activate(const ServiceWorkerLifetimeExtension& aLifetimeExtension); 166 167 void FinishActivate(bool aSuccess); 168 169 void RefreshLastUpdateCheckTime(); 170 171 bool IsLastUpdateCheckTimeOverOneDay() const; 172 173 void MaybeScheduleTimeCheckAndUpdate(); 174 175 void MaybeScheduleUpdate(); 176 177 bool CheckAndClearIfUpdateNeeded(); 178 179 ServiceWorkerInfo* GetEvaluating() const; 180 181 ServiceWorkerInfo* GetInstalling() const; 182 183 ServiceWorkerInfo* GetWaiting() const; 184 185 ServiceWorkerInfo* GetActive() const; 186 187 ServiceWorkerInfo* GetByDescriptor( 188 const ServiceWorkerDescriptor& aDescriptor) const; 189 190 ServiceWorkerInfo* GetByClientInfo(const ClientInfo& aClientInfo) const; 191 192 // Set the given worker as the evaluating service worker. The worker 193 // state is not changed. 194 void SetEvaluating(ServiceWorkerInfo* aServiceWorker); 195 196 // Remove an existing evaluating worker, if present. The worker will 197 // be transitioned to the Redundant state. 198 void ClearEvaluating(); 199 200 // Remove an existing installing worker, if present. The worker will 201 // be transitioned to the Redundant state. 202 void ClearInstalling(); 203 204 // Transition the current evaluating worker to be the installing worker. The 205 // worker's state is update to Installing. 206 void TransitionEvaluatingToInstalling(); 207 208 // Transition the current installing worker to be the waiting worker. The 209 // worker's state is updated to Installed. 210 void TransitionInstallingToWaiting(); 211 212 // Override the current active worker. This is used during browser 213 // initialization to load persisted workers. Its also used to propagate 214 // active workers across child processes in e10s. This second use will 215 // go away once the ServiceWorkerManager moves to the parent process. 216 // The worker is transitioned to the Activated state. 217 void SetActive(ServiceWorkerInfo* aServiceWorker); 218 219 // Transition the current waiting worker to be the new active worker. The 220 // worker is updated to the Activating state. 221 void TransitionWaitingToActive(); 222 223 // Determine if the registration is actively performing work. 224 bool IsIdle() const; 225 226 ServiceWorkerUpdateViaCache GetUpdateViaCache() const; 227 228 void SetOptions(ServiceWorkerUpdateViaCache aUpdateViaCache, 229 WorkerType aType); 230 231 int64_t GetLastUpdateTime() const; 232 233 void SetLastUpdateTime(const int64_t aTime); 234 235 const ServiceWorkerRegistrationDescriptor& Descriptor() const; 236 237 uint64_t Id() const; 238 239 uint64_t Version() const; 240 241 uint32_t GetUpdateDelay(const bool aWithMultiplier = true); 242 243 void FireUpdateFound(); 244 245 void NotifyCleared(); 246 247 void ClearWhenIdle(); 248 249 const nsID& AgentClusterId() const; 250 251 void SetNavigationPreloadEnabled(const bool& aEnabled); 252 253 void SetNavigationPreloadHeader(const nsCString& aHeader); 254 255 IPCNavigationPreloadState GetNavigationPreloadState() const; 256 257 private: 258 // Roughly equivalent to [[Update Registration State algorithm]]. Make sure 259 // this is called *before* updating SW instances' state, otherwise they 260 // may get CC-ed. 261 void UpdateRegistrationState(); 262 263 void UpdateRegistrationState(ServiceWorkerUpdateViaCache aUpdateViaCache, 264 WorkerType aType); 265 266 // Used by devtools to track changes to the properties of 267 // *nsIServiceWorkerRegistrationInfo*. Note, this doesn't necessarily need to 268 // be in sync with the DOM registration objects, but it does need to be called 269 // in the same task that changed |mInstallingWorker|, |mWaitingWorker| or 270 // |mActiveWorker|. 271 void NotifyChromeRegistrationListeners(); 272 273 static uint64_t GetNextId(); 274 275 static uint64_t GetNextVersion(); 276 277 // `aFunc`'s argument will be a reference to 278 // `m{Evaluating,Installing,Waiting,Active}Worker` (not to copy of them). 279 // Additionally, a null check will be performed for each worker before each 280 // call to `aFunc`, so `aFunc` will always get a reference to a non-null 281 // pointer. 282 void ForEachWorker(void (*aFunc)(RefPtr<ServiceWorkerInfo>&)); 283 284 void CheckQuotaUsage(); 285 }; 286 287 } // namespace mozilla::dom 288 289 #endif // mozilla_dom_serviceworkerregistrationinfo_h