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