1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/uriloader/prefetch/nsOfflineCacheUpdate.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,379 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef nsOfflineCacheUpdate_h__ 1.10 +#define nsOfflineCacheUpdate_h__ 1.11 + 1.12 +#include "nsIOfflineCacheUpdate.h" 1.13 + 1.14 +#include "nsAutoPtr.h" 1.15 +#include "nsCOMArray.h" 1.16 +#include "nsCOMPtr.h" 1.17 +#include "nsICacheService.h" 1.18 +#include "nsIChannelEventSink.h" 1.19 +#include "nsIDOMDocument.h" 1.20 +#include "nsIDOMNode.h" 1.21 +#include "nsIInterfaceRequestor.h" 1.22 +#include "nsIMutableArray.h" 1.23 +#include "nsIObserver.h" 1.24 +#include "nsIObserverService.h" 1.25 +#include "nsIApplicationCache.h" 1.26 +#include "nsIRequestObserver.h" 1.27 +#include "nsIRunnable.h" 1.28 +#include "nsIStreamListener.h" 1.29 +#include "nsIURI.h" 1.30 +#include "nsIWebProgressListener.h" 1.31 +#include "nsClassHashtable.h" 1.32 +#include "nsString.h" 1.33 +#include "nsTArray.h" 1.34 +#include "nsWeakReference.h" 1.35 +#include "nsICryptoHash.h" 1.36 +#include "mozilla/Attributes.h" 1.37 +#include "mozilla/WeakPtr.h" 1.38 +#include "nsTHashtable.h" 1.39 +#include "nsHashKeys.h" 1.40 + 1.41 +class nsOfflineCacheUpdate; 1.42 + 1.43 +class nsICacheEntryDescriptor; 1.44 +class nsIUTF8StringEnumerator; 1.45 +class nsILoadContext; 1.46 + 1.47 +class nsOfflineCacheUpdateItem : public nsIStreamListener 1.48 + , public nsIRunnable 1.49 + , public nsIInterfaceRequestor 1.50 + , public nsIChannelEventSink 1.51 +{ 1.52 +public: 1.53 + NS_DECL_ISUPPORTS 1.54 + NS_DECL_NSIREQUESTOBSERVER 1.55 + NS_DECL_NSISTREAMLISTENER 1.56 + NS_DECL_NSIRUNNABLE 1.57 + NS_DECL_NSIINTERFACEREQUESTOR 1.58 + NS_DECL_NSICHANNELEVENTSINK 1.59 + 1.60 + nsOfflineCacheUpdateItem(nsIURI *aURI, 1.61 + nsIURI *aReferrerURI, 1.62 + nsIApplicationCache *aApplicationCache, 1.63 + nsIApplicationCache *aPreviousApplicationCache, 1.64 + uint32_t aType); 1.65 + virtual ~nsOfflineCacheUpdateItem(); 1.66 + 1.67 + nsCOMPtr<nsIURI> mURI; 1.68 + nsCOMPtr<nsIURI> mReferrerURI; 1.69 + nsCOMPtr<nsIApplicationCache> mApplicationCache; 1.70 + nsCOMPtr<nsIApplicationCache> mPreviousApplicationCache; 1.71 + nsCString mCacheKey; 1.72 + uint32_t mItemType; 1.73 + 1.74 + nsresult OpenChannel(nsOfflineCacheUpdate *aUpdate); 1.75 + nsresult Cancel(); 1.76 + nsresult GetRequestSucceeded(bool * succeeded); 1.77 + 1.78 + bool IsInProgress(); 1.79 + bool IsScheduled(); 1.80 + bool IsCompleted(); 1.81 + 1.82 + nsresult GetStatus(uint16_t *aStatus); 1.83 + 1.84 +private: 1.85 + enum LoadStatus MOZ_ENUM_TYPE(uint16_t) { 1.86 + UNINITIALIZED = 0U, 1.87 + REQUESTED = 1U, 1.88 + RECEIVING = 2U, 1.89 + LOADED = 3U 1.90 + }; 1.91 + 1.92 + nsRefPtr<nsOfflineCacheUpdate> mUpdate; 1.93 + nsCOMPtr<nsIChannel> mChannel; 1.94 + uint16_t mState; 1.95 + 1.96 +protected: 1.97 + int64_t mBytesRead; 1.98 +}; 1.99 + 1.100 + 1.101 +class nsOfflineManifestItem : public nsOfflineCacheUpdateItem 1.102 +{ 1.103 +public: 1.104 + NS_DECL_NSISTREAMLISTENER 1.105 + NS_DECL_NSIREQUESTOBSERVER 1.106 + 1.107 + nsOfflineManifestItem(nsIURI *aURI, 1.108 + nsIURI *aReferrerURI, 1.109 + nsIApplicationCache *aApplicationCache, 1.110 + nsIApplicationCache *aPreviousApplicationCache); 1.111 + virtual ~nsOfflineManifestItem(); 1.112 + 1.113 + nsCOMArray<nsIURI> &GetExplicitURIs() { return mExplicitURIs; } 1.114 + nsCOMArray<nsIURI> &GetFallbackURIs() { return mFallbackURIs; } 1.115 + 1.116 + nsTArray<nsCString> &GetOpportunisticNamespaces() 1.117 + { return mOpportunisticNamespaces; } 1.118 + nsIArray *GetNamespaces() 1.119 + { return mNamespaces.get(); } 1.120 + 1.121 + bool ParseSucceeded() 1.122 + { return (mParserState != PARSE_INIT && mParserState != PARSE_ERROR); } 1.123 + bool NeedsUpdate() { return mParserState != PARSE_INIT && mNeedsUpdate; } 1.124 + 1.125 + void GetManifestHash(nsCString &aManifestHash) 1.126 + { aManifestHash = mManifestHashValue; } 1.127 + 1.128 +private: 1.129 + static NS_METHOD ReadManifest(nsIInputStream *aInputStream, 1.130 + void *aClosure, 1.131 + const char *aFromSegment, 1.132 + uint32_t aOffset, 1.133 + uint32_t aCount, 1.134 + uint32_t *aBytesConsumed); 1.135 + 1.136 + nsresult AddNamespace(uint32_t namespaceType, 1.137 + const nsCString &namespaceSpec, 1.138 + const nsCString &data); 1.139 + 1.140 + nsresult HandleManifestLine(const nsCString::const_iterator &aBegin, 1.141 + const nsCString::const_iterator &aEnd); 1.142 + 1.143 + /** 1.144 + * Saves "offline-manifest-hash" meta data from the old offline cache 1.145 + * token to mOldManifestHashValue member to be compared on 1.146 + * successfull load. 1.147 + */ 1.148 + nsresult GetOldManifestContentHash(nsIRequest *aRequest); 1.149 + /** 1.150 + * This method setups the mNeedsUpdate to false when hash value 1.151 + * of the just downloaded manifest file is the same as stored in cache's 1.152 + * "offline-manifest-hash" meta data. Otherwise stores the new value 1.153 + * to this meta data. 1.154 + */ 1.155 + nsresult CheckNewManifestContentHash(nsIRequest *aRequest); 1.156 + 1.157 + void ReadStrictFileOriginPolicyPref(); 1.158 + 1.159 + enum { 1.160 + PARSE_INIT, 1.161 + PARSE_CACHE_ENTRIES, 1.162 + PARSE_FALLBACK_ENTRIES, 1.163 + PARSE_BYPASS_ENTRIES, 1.164 + PARSE_UNKNOWN_SECTION, 1.165 + PARSE_ERROR 1.166 + } mParserState; 1.167 + 1.168 + nsCString mReadBuf; 1.169 + 1.170 + nsCOMArray<nsIURI> mExplicitURIs; 1.171 + nsCOMArray<nsIURI> mFallbackURIs; 1.172 + 1.173 + // All opportunistic caching namespaces. Used to decide whether 1.174 + // to include previously-opportunistically-cached entries. 1.175 + nsTArray<nsCString> mOpportunisticNamespaces; 1.176 + 1.177 + // Array of nsIApplicationCacheNamespace objects specified by the 1.178 + // manifest. 1.179 + nsCOMPtr<nsIMutableArray> mNamespaces; 1.180 + 1.181 + bool mNeedsUpdate; 1.182 + bool mStrictFileOriginPolicy; 1.183 + 1.184 + // manifest hash data 1.185 + nsCOMPtr<nsICryptoHash> mManifestHash; 1.186 + bool mManifestHashInitialized; 1.187 + nsCString mManifestHashValue; 1.188 + nsCString mOldManifestHashValue; 1.189 +}; 1.190 + 1.191 +class nsOfflineCacheUpdateOwner 1.192 + : public mozilla::SupportsWeakPtr<nsOfflineCacheUpdateOwner> 1.193 +{ 1.194 +public: 1.195 + MOZ_DECLARE_REFCOUNTED_TYPENAME(nsOfflineCacheUpdateOwner) 1.196 + virtual ~nsOfflineCacheUpdateOwner() {} 1.197 + virtual nsresult UpdateFinished(nsOfflineCacheUpdate *aUpdate) = 0; 1.198 +}; 1.199 + 1.200 +class nsOfflineCacheUpdate MOZ_FINAL : public nsIOfflineCacheUpdate 1.201 + , public nsIOfflineCacheUpdateObserver 1.202 + , public nsIRunnable 1.203 + , public nsOfflineCacheUpdateOwner 1.204 +{ 1.205 +public: 1.206 + MOZ_DECLARE_REFCOUNTED_TYPENAME(nsOfflineCacheUpdate) 1.207 + NS_DECL_ISUPPORTS 1.208 + NS_DECL_NSIOFFLINECACHEUPDATE 1.209 + NS_DECL_NSIOFFLINECACHEUPDATEOBSERVER 1.210 + NS_DECL_NSIRUNNABLE 1.211 + 1.212 + nsOfflineCacheUpdate(); 1.213 + ~nsOfflineCacheUpdate(); 1.214 + 1.215 + static nsresult GetCacheKey(nsIURI *aURI, nsACString &aKey); 1.216 + 1.217 + nsresult Init(); 1.218 + 1.219 + nsresult Begin(); 1.220 + 1.221 + void LoadCompleted(nsOfflineCacheUpdateItem *aItem); 1.222 + void ManifestCheckCompleted(nsresult aStatus, 1.223 + const nsCString &aManifestHash); 1.224 + void StickDocument(nsIURI *aDocumentURI); 1.225 + 1.226 + void SetOwner(nsOfflineCacheUpdateOwner *aOwner); 1.227 + 1.228 + bool IsForGroupID(const nsCSubstring &groupID); 1.229 + 1.230 + virtual nsresult UpdateFinished(nsOfflineCacheUpdate *aUpdate); 1.231 + 1.232 +protected: 1.233 + friend class nsOfflineCacheUpdateItem; 1.234 + void OnByteProgress(uint64_t byteIncrement); 1.235 + 1.236 +private: 1.237 + nsresult InitInternal(nsIURI *aManifestURI); 1.238 + nsresult HandleManifest(bool *aDoUpdate); 1.239 + nsresult AddURI(nsIURI *aURI, uint32_t aItemType); 1.240 + 1.241 + nsresult ProcessNextURI(); 1.242 + 1.243 + // Adds items from the previous cache witha type matching aType. 1.244 + // If namespaceFilter is non-null, only items matching the 1.245 + // specified namespaces will be added. 1.246 + nsresult AddExistingItems(uint32_t aType, 1.247 + nsTArray<nsCString>* namespaceFilter = nullptr); 1.248 + nsresult ScheduleImplicit(); 1.249 + void AssociateDocuments(nsIApplicationCache* cache); 1.250 + bool CheckUpdateAvailability(); 1.251 + void NotifyUpdateAvailability(bool updateAvailable); 1.252 + 1.253 + void GatherObservers(nsCOMArray<nsIOfflineCacheUpdateObserver> &aObservers); 1.254 + void NotifyState(uint32_t state); 1.255 + nsresult Finish(); 1.256 + nsresult FinishNoNotify(); 1.257 + 1.258 + void AsyncFinishWithError(); 1.259 + 1.260 + // Find one non-pinned cache group and evict it. 1.261 + nsresult EvictOneNonPinned(); 1.262 + 1.263 + enum { 1.264 + STATE_UNINITIALIZED, 1.265 + STATE_INITIALIZED, 1.266 + STATE_CHECKING, 1.267 + STATE_DOWNLOADING, 1.268 + STATE_CANCELLED, 1.269 + STATE_FINISHED 1.270 + } mState; 1.271 + 1.272 + mozilla::WeakPtr<nsOfflineCacheUpdateOwner> mOwner; 1.273 + 1.274 + bool mAddedItems; 1.275 + bool mPartialUpdate; 1.276 + bool mOnlyCheckUpdate; 1.277 + bool mSucceeded; 1.278 + bool mObsolete; 1.279 + 1.280 + nsCString mUpdateDomain; 1.281 + nsCString mGroupID; 1.282 + nsCOMPtr<nsIURI> mManifestURI; 1.283 + nsCOMPtr<nsIURI> mDocumentURI; 1.284 + nsCOMPtr<nsIFile> mCustomProfileDir; 1.285 + 1.286 + uint32_t mAppID; 1.287 + bool mInBrowser; 1.288 + 1.289 + nsCOMPtr<nsIObserver> mUpdateAvailableObserver; 1.290 + 1.291 + nsCOMPtr<nsIApplicationCache> mApplicationCache; 1.292 + nsCOMPtr<nsIApplicationCache> mPreviousApplicationCache; 1.293 + 1.294 + nsCOMPtr<nsIObserverService> mObserverService; 1.295 + 1.296 + nsRefPtr<nsOfflineManifestItem> mManifestItem; 1.297 + 1.298 + /* Items being updated */ 1.299 + uint32_t mItemsInProgress; 1.300 + nsTArray<nsRefPtr<nsOfflineCacheUpdateItem> > mItems; 1.301 + 1.302 + /* Clients watching this update for changes */ 1.303 + nsCOMArray<nsIWeakReference> mWeakObservers; 1.304 + nsCOMArray<nsIOfflineCacheUpdateObserver> mObservers; 1.305 + 1.306 + /* Documents that requested this update */ 1.307 + nsCOMArray<nsIURI> mDocumentURIs; 1.308 + 1.309 + /* Reschedule count. When an update is rescheduled due to 1.310 + * mismatched manifests, the reschedule count will be increased. */ 1.311 + uint32_t mRescheduleCount; 1.312 + 1.313 + /* Whena an entry for a pinned app is retried, retries count is 1.314 + * increaded. */ 1.315 + uint32_t mPinnedEntryRetriesCount; 1.316 + 1.317 + nsRefPtr<nsOfflineCacheUpdate> mImplicitUpdate; 1.318 + 1.319 + bool mPinned; 1.320 + 1.321 + uint64_t mByteProgress; 1.322 +}; 1.323 + 1.324 +class nsOfflineCacheUpdateService MOZ_FINAL : public nsIOfflineCacheUpdateService 1.325 + , public nsIObserver 1.326 + , public nsOfflineCacheUpdateOwner 1.327 + , public nsSupportsWeakReference 1.328 +{ 1.329 +public: 1.330 + NS_DECL_ISUPPORTS 1.331 + NS_DECL_NSIOFFLINECACHEUPDATESERVICE 1.332 + NS_DECL_NSIOBSERVER 1.333 + 1.334 + nsOfflineCacheUpdateService(); 1.335 + ~nsOfflineCacheUpdateService(); 1.336 + 1.337 + nsresult Init(); 1.338 + 1.339 + nsresult ScheduleUpdate(nsOfflineCacheUpdate *aUpdate); 1.340 + nsresult FindUpdate(nsIURI *aManifestURI, 1.341 + uint32_t aAppID, 1.342 + bool aInBrowser, 1.343 + nsOfflineCacheUpdate **aUpdate); 1.344 + 1.345 + nsresult Schedule(nsIURI *aManifestURI, 1.346 + nsIURI *aDocumentURI, 1.347 + nsIDOMDocument *aDocument, 1.348 + nsIDOMWindow* aWindow, 1.349 + nsIFile* aCustomProfileDir, 1.350 + uint32_t aAppID, 1.351 + bool aInBrowser, 1.352 + nsIOfflineCacheUpdate **aUpdate); 1.353 + 1.354 + virtual nsresult UpdateFinished(nsOfflineCacheUpdate *aUpdate); 1.355 + 1.356 + /** 1.357 + * Returns the singleton nsOfflineCacheUpdateService without an addref, or 1.358 + * nullptr if the service couldn't be created. 1.359 + */ 1.360 + static nsOfflineCacheUpdateService *EnsureService(); 1.361 + 1.362 + /** Addrefs and returns the singleton nsOfflineCacheUpdateService. */ 1.363 + static nsOfflineCacheUpdateService *GetInstance(); 1.364 + 1.365 + static nsresult OfflineAppPinnedForURI(nsIURI *aDocumentURI, 1.366 + nsIPrefBranch *aPrefBranch, 1.367 + bool *aPinned); 1.368 + 1.369 + static nsTHashtable<nsCStringHashKey>* AllowedDomains(); 1.370 + 1.371 +private: 1.372 + nsresult ProcessNextUpdate(); 1.373 + 1.374 + nsTArray<nsRefPtr<nsOfflineCacheUpdate> > mUpdates; 1.375 + static nsTHashtable<nsCStringHashKey>* mAllowedDomains; 1.376 + 1.377 + bool mDisabled; 1.378 + bool mUpdateRunning; 1.379 + bool mLowFreeSpace; 1.380 +}; 1.381 + 1.382 +#endif