uriloader/prefetch/nsOfflineCacheUpdate.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial