nsOfflineCacheUpdate.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef nsOfflineCacheUpdate_h__
  6. #define nsOfflineCacheUpdate_h__
  7. #include "nsIOfflineCacheUpdate.h"
  8. #include "nsAutoPtr.h"
  9. #include "nsCOMArray.h"
  10. #include "nsCOMPtr.h"
  11. #include "nsIChannelEventSink.h"
  12. #include "nsIDOMDocument.h"
  13. #include "nsIDOMNode.h"
  14. #include "nsIInterfaceRequestor.h"
  15. #include "nsIMutableArray.h"
  16. #include "nsIObserver.h"
  17. #include "nsIObserverService.h"
  18. #include "nsIApplicationCache.h"
  19. #include "nsIRequestObserver.h"
  20. #include "nsIRunnable.h"
  21. #include "nsIStreamListener.h"
  22. #include "nsIURI.h"
  23. #include "nsIWebProgressListener.h"
  24. #include "nsClassHashtable.h"
  25. #include "nsString.h"
  26. #include "nsTArray.h"
  27. #include "nsWeakReference.h"
  28. #include "nsICryptoHash.h"
  29. #include "mozilla/Attributes.h"
  30. #include "mozilla/WeakPtr.h"
  31. #include "nsTHashtable.h"
  32. #include "nsHashKeys.h"
  33. class nsOfflineCacheUpdate;
  34. class nsOfflineCacheUpdateItem : public nsIStreamListener
  35. , public nsIRunnable
  36. , public nsIInterfaceRequestor
  37. , public nsIChannelEventSink
  38. {
  39. public:
  40. NS_DECL_ISUPPORTS
  41. NS_DECL_NSIREQUESTOBSERVER
  42. NS_DECL_NSISTREAMLISTENER
  43. NS_DECL_NSIRUNNABLE
  44. NS_DECL_NSIINTERFACEREQUESTOR
  45. NS_DECL_NSICHANNELEVENTSINK
  46. nsOfflineCacheUpdateItem(nsIURI *aURI,
  47. nsIURI *aReferrerURI,
  48. nsIPrincipal* aLoadingPrincipal,
  49. nsIApplicationCache *aApplicationCache,
  50. nsIApplicationCache *aPreviousApplicationCache,
  51. uint32_t aType,
  52. uint32_t aLoadFlags);
  53. nsCOMPtr<nsIURI> mURI;
  54. nsCOMPtr<nsIURI> mReferrerURI;
  55. nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
  56. nsCOMPtr<nsIApplicationCache> mApplicationCache;
  57. nsCOMPtr<nsIApplicationCache> mPreviousApplicationCache;
  58. nsCString mCacheKey;
  59. uint32_t mItemType;
  60. uint32_t mLoadFlags;
  61. nsresult OpenChannel(nsOfflineCacheUpdate *aUpdate);
  62. nsresult Cancel();
  63. nsresult GetRequestSucceeded(bool * succeeded);
  64. bool IsInProgress();
  65. bool IsScheduled();
  66. bool IsCompleted();
  67. nsresult GetStatus(uint16_t *aStatus);
  68. private:
  69. enum LoadStatus : uint16_t {
  70. UNINITIALIZED = 0U,
  71. REQUESTED = 1U,
  72. RECEIVING = 2U,
  73. LOADED = 3U
  74. };
  75. RefPtr<nsOfflineCacheUpdate> mUpdate;
  76. nsCOMPtr<nsIChannel> mChannel;
  77. uint16_t mState;
  78. protected:
  79. virtual ~nsOfflineCacheUpdateItem();
  80. int64_t mBytesRead;
  81. };
  82. class nsOfflineManifestItem : public nsOfflineCacheUpdateItem
  83. {
  84. public:
  85. NS_DECL_NSISTREAMLISTENER
  86. NS_DECL_NSIREQUESTOBSERVER
  87. nsOfflineManifestItem(nsIURI *aURI,
  88. nsIURI *aReferrerURI,
  89. nsIPrincipal* aLoadingPrincipal,
  90. nsIApplicationCache *aApplicationCache,
  91. nsIApplicationCache *aPreviousApplicationCache);
  92. virtual ~nsOfflineManifestItem();
  93. nsCOMArray<nsIURI> &GetExplicitURIs() { return mExplicitURIs; }
  94. nsCOMArray<nsIURI> &GetAnonymousURIs() { return mAnonymousURIs; }
  95. nsCOMArray<nsIURI> &GetFallbackURIs() { return mFallbackURIs; }
  96. nsTArray<nsCString> &GetOpportunisticNamespaces()
  97. { return mOpportunisticNamespaces; }
  98. nsIArray *GetNamespaces()
  99. { return mNamespaces.get(); }
  100. bool ParseSucceeded()
  101. { return (mParserState != PARSE_INIT && mParserState != PARSE_ERROR); }
  102. bool NeedsUpdate() { return mParserState != PARSE_INIT && mNeedsUpdate; }
  103. void GetManifestHash(nsCString &aManifestHash)
  104. { aManifestHash = mManifestHashValue; }
  105. private:
  106. static nsresult ReadManifest(nsIInputStream *aInputStream,
  107. void *aClosure,
  108. const char *aFromSegment,
  109. uint32_t aOffset,
  110. uint32_t aCount,
  111. uint32_t *aBytesConsumed);
  112. nsresult AddNamespace(uint32_t namespaceType,
  113. const nsCString &namespaceSpec,
  114. const nsCString &data);
  115. nsresult HandleManifestLine(const nsCString::const_iterator &aBegin,
  116. const nsCString::const_iterator &aEnd);
  117. /**
  118. * Saves "offline-manifest-hash" meta data from the old offline cache
  119. * token to mOldManifestHashValue member to be compared on
  120. * successfull load.
  121. */
  122. nsresult GetOldManifestContentHash(nsIRequest *aRequest);
  123. /**
  124. * This method setups the mNeedsUpdate to false when hash value
  125. * of the just downloaded manifest file is the same as stored in cache's
  126. * "offline-manifest-hash" meta data. Otherwise stores the new value
  127. * to this meta data.
  128. */
  129. nsresult CheckNewManifestContentHash(nsIRequest *aRequest);
  130. void ReadStrictFileOriginPolicyPref();
  131. enum {
  132. PARSE_INIT,
  133. PARSE_CACHE_ENTRIES,
  134. PARSE_FALLBACK_ENTRIES,
  135. PARSE_BYPASS_ENTRIES,
  136. PARSE_UNKNOWN_SECTION,
  137. PARSE_ERROR
  138. } mParserState;
  139. nsCString mReadBuf;
  140. nsCOMArray<nsIURI> mExplicitURIs;
  141. nsCOMArray<nsIURI> mAnonymousURIs;
  142. nsCOMArray<nsIURI> mFallbackURIs;
  143. // All opportunistic caching namespaces. Used to decide whether
  144. // to include previously-opportunistically-cached entries.
  145. nsTArray<nsCString> mOpportunisticNamespaces;
  146. // Array of nsIApplicationCacheNamespace objects specified by the
  147. // manifest.
  148. nsCOMPtr<nsIMutableArray> mNamespaces;
  149. bool mNeedsUpdate;
  150. bool mStrictFileOriginPolicy;
  151. // manifest hash data
  152. nsCOMPtr<nsICryptoHash> mManifestHash;
  153. bool mManifestHashInitialized;
  154. nsCString mManifestHashValue;
  155. nsCString mOldManifestHashValue;
  156. };
  157. class nsOfflineCacheUpdateOwner
  158. : public mozilla::SupportsWeakPtr<nsOfflineCacheUpdateOwner>
  159. {
  160. public:
  161. MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsOfflineCacheUpdateOwner)
  162. virtual ~nsOfflineCacheUpdateOwner() {}
  163. virtual nsresult UpdateFinished(nsOfflineCacheUpdate *aUpdate) = 0;
  164. };
  165. class nsOfflineCacheUpdate final : public nsIOfflineCacheUpdate
  166. , public nsIOfflineCacheUpdateObserver
  167. , public nsIRunnable
  168. , public nsOfflineCacheUpdateOwner
  169. {
  170. public:
  171. NS_DECL_ISUPPORTS
  172. NS_DECL_NSIOFFLINECACHEUPDATE
  173. NS_DECL_NSIOFFLINECACHEUPDATEOBSERVER
  174. NS_DECL_NSIRUNNABLE
  175. nsOfflineCacheUpdate();
  176. static nsresult GetCacheKey(nsIURI *aURI, nsACString &aKey);
  177. nsresult Init();
  178. nsresult Begin();
  179. void LoadCompleted(nsOfflineCacheUpdateItem *aItem);
  180. void ManifestCheckCompleted(nsresult aStatus,
  181. const nsCString &aManifestHash);
  182. void StickDocument(nsIURI *aDocumentURI);
  183. void SetOwner(nsOfflineCacheUpdateOwner *aOwner);
  184. bool IsForGroupID(const nsCSubstring &groupID);
  185. bool IsForProfile(nsIFile* aCustomProfileDir);
  186. virtual nsresult UpdateFinished(nsOfflineCacheUpdate *aUpdate) override;
  187. protected:
  188. ~nsOfflineCacheUpdate();
  189. friend class nsOfflineCacheUpdateItem;
  190. void OnByteProgress(uint64_t byteIncrement);
  191. private:
  192. nsresult InitInternal(nsIURI *aManifestURI, nsIPrincipal* aPrincipal);
  193. nsresult HandleManifest(bool *aDoUpdate);
  194. nsresult AddURI(nsIURI *aURI, uint32_t aItemType, uint32_t aLoadFlags = 0);
  195. nsresult ProcessNextURI();
  196. // Adds items from the previous cache witha type matching aType.
  197. // If namespaceFilter is non-null, only items matching the
  198. // specified namespaces will be added.
  199. nsresult AddExistingItems(uint32_t aType,
  200. nsTArray<nsCString>* namespaceFilter = nullptr);
  201. nsresult ScheduleImplicit();
  202. void AssociateDocuments(nsIApplicationCache* cache);
  203. bool CheckUpdateAvailability();
  204. void NotifyUpdateAvailability(bool updateAvailable);
  205. void GatherObservers(nsCOMArray<nsIOfflineCacheUpdateObserver> &aObservers);
  206. void NotifyState(uint32_t state);
  207. nsresult Finish();
  208. nsresult FinishNoNotify();
  209. void AsyncFinishWithError();
  210. // Find one non-pinned cache group and evict it.
  211. nsresult EvictOneNonPinned();
  212. enum {
  213. STATE_UNINITIALIZED,
  214. STATE_INITIALIZED,
  215. STATE_CHECKING,
  216. STATE_DOWNLOADING,
  217. STATE_CANCELLED,
  218. STATE_FINISHED
  219. } mState;
  220. mozilla::WeakPtr<nsOfflineCacheUpdateOwner> mOwner;
  221. bool mAddedItems;
  222. bool mPartialUpdate;
  223. bool mOnlyCheckUpdate;
  224. bool mSucceeded;
  225. bool mObsolete;
  226. nsCString mUpdateDomain;
  227. nsCString mGroupID;
  228. nsCOMPtr<nsIURI> mManifestURI;
  229. nsCOMPtr<nsIURI> mDocumentURI;
  230. nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
  231. nsCOMPtr<nsIFile> mCustomProfileDir;
  232. nsCOMPtr<nsIObserver> mUpdateAvailableObserver;
  233. nsCOMPtr<nsIApplicationCache> mApplicationCache;
  234. nsCOMPtr<nsIApplicationCache> mPreviousApplicationCache;
  235. nsCOMPtr<nsIObserverService> mObserverService;
  236. RefPtr<nsOfflineManifestItem> mManifestItem;
  237. /* Items being updated */
  238. uint32_t mItemsInProgress;
  239. nsTArray<RefPtr<nsOfflineCacheUpdateItem> > mItems;
  240. /* Clients watching this update for changes */
  241. nsCOMArray<nsIWeakReference> mWeakObservers;
  242. nsCOMArray<nsIOfflineCacheUpdateObserver> mObservers;
  243. /* Documents that requested this update */
  244. nsCOMArray<nsIURI> mDocumentURIs;
  245. /* Reschedule count. When an update is rescheduled due to
  246. * mismatched manifests, the reschedule count will be increased. */
  247. uint32_t mRescheduleCount;
  248. /* Whena an entry for a pinned app is retried, retries count is
  249. * increaded. */
  250. uint32_t mPinnedEntryRetriesCount;
  251. RefPtr<nsOfflineCacheUpdate> mImplicitUpdate;
  252. bool mPinned;
  253. uint64_t mByteProgress;
  254. };
  255. class nsOfflineCacheUpdateService final : public nsIOfflineCacheUpdateService
  256. , public nsIObserver
  257. , public nsOfflineCacheUpdateOwner
  258. , public nsSupportsWeakReference
  259. {
  260. public:
  261. NS_DECL_ISUPPORTS
  262. NS_DECL_NSIOFFLINECACHEUPDATESERVICE
  263. NS_DECL_NSIOBSERVER
  264. nsOfflineCacheUpdateService();
  265. nsresult Init();
  266. nsresult ScheduleUpdate(nsOfflineCacheUpdate *aUpdate);
  267. nsresult FindUpdate(nsIURI *aManifestURI,
  268. nsACString const &aOriginSuffix,
  269. nsIFile *aCustomProfileDir,
  270. nsOfflineCacheUpdate **aUpdate);
  271. nsresult Schedule(nsIURI *aManifestURI,
  272. nsIURI *aDocumentURI,
  273. nsIPrincipal* aLoadingPrincipal,
  274. nsIDOMDocument *aDocument,
  275. nsPIDOMWindowInner* aWindow,
  276. nsIFile* aCustomProfileDir,
  277. nsIOfflineCacheUpdate **aUpdate);
  278. virtual nsresult UpdateFinished(nsOfflineCacheUpdate *aUpdate) override;
  279. /**
  280. * Returns the singleton nsOfflineCacheUpdateService without an addref, or
  281. * nullptr if the service couldn't be created.
  282. */
  283. static nsOfflineCacheUpdateService *EnsureService();
  284. /** Addrefs and returns the singleton nsOfflineCacheUpdateService. */
  285. static nsOfflineCacheUpdateService *GetInstance();
  286. static nsresult OfflineAppPinnedForURI(nsIURI *aDocumentURI,
  287. nsIPrefBranch *aPrefBranch,
  288. bool *aPinned);
  289. static nsTHashtable<nsCStringHashKey>* AllowedDomains();
  290. private:
  291. ~nsOfflineCacheUpdateService();
  292. nsresult ProcessNextUpdate();
  293. nsTArray<RefPtr<nsOfflineCacheUpdate> > mUpdates;
  294. static nsTHashtable<nsCStringHashKey>* mAllowedDomains;
  295. bool mDisabled;
  296. bool mUpdateRunning;
  297. };
  298. #endif