Line data Source code
1 : /* vim: set ts=2 sts=2 et sw=2: */
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 mozilla_net_Predictor_h
7 : #define mozilla_net_Predictor_h
8 :
9 : #include "nsINetworkPredictor.h"
10 : #include "nsINetworkPredictorVerifier.h"
11 :
12 : #include "nsCOMPtr.h"
13 : #include "nsICacheEntry.h"
14 : #include "nsICacheEntryOpenCallback.h"
15 : #include "nsICacheStorageService.h"
16 : #include "nsICacheStorageVisitor.h"
17 : #include "nsIDNSListener.h"
18 : #include "nsIInterfaceRequestor.h"
19 : #include "nsIObserver.h"
20 : #include "nsISpeculativeConnect.h"
21 : #include "nsIStreamListener.h"
22 : #include "mozilla/RefPtr.h"
23 : #include "nsString.h"
24 : #include "nsTArray.h"
25 :
26 : #include "mozilla/TimeStamp.h"
27 :
28 : class nsICacheStorage;
29 : class nsIDNSService;
30 : class nsIIOService;
31 : class nsILoadContextInfo;
32 : class nsITimer;
33 :
34 : namespace mozilla {
35 : namespace net {
36 :
37 : class nsHttpRequestHead;
38 : class nsHttpResponseHead;
39 :
40 : class Predictor : public nsINetworkPredictor
41 : , public nsIObserver
42 : , public nsISpeculativeConnectionOverrider
43 : , public nsIInterfaceRequestor
44 : , public nsICacheEntryMetaDataVisitor
45 : , public nsINetworkPredictorVerifier
46 : {
47 : public:
48 : NS_DECL_ISUPPORTS
49 : NS_DECL_NSINETWORKPREDICTOR
50 : NS_DECL_NSIOBSERVER
51 : NS_DECL_NSISPECULATIVECONNECTIONOVERRIDER
52 : NS_DECL_NSIINTERFACEREQUESTOR
53 : NS_DECL_NSICACHEENTRYMETADATAVISITOR
54 : NS_DECL_NSINETWORKPREDICTORVERIFIER
55 :
56 : Predictor();
57 :
58 : nsresult Init();
59 : void Shutdown();
60 : static nsresult Create(nsISupports *outer, const nsIID& iid, void **result);
61 :
62 : // Used to update whether a particular URI was cacheable or not.
63 : // sourceURI and targetURI are the same as the arguments to Learn
64 : // and httpStatus is the status code we got while loading targetURI.
65 : static void UpdateCacheability(nsIURI *sourceURI, nsIURI *targetURI,
66 : uint32_t httpStatus,
67 : nsHttpRequestHead &requestHead,
68 : nsHttpResponseHead *reqponseHead,
69 : nsILoadContextInfo *lci);
70 :
71 : private:
72 : virtual ~Predictor();
73 :
74 : // Stores callbacks for a child process predictor (for test purposes)
75 : nsCOMPtr<nsINetworkPredictorVerifier> mChildVerifier;
76 :
77 : union Reason {
78 : PredictorLearnReason mLearn;
79 : PredictorPredictReason mPredict;
80 : };
81 :
82 : class DNSListener : public nsIDNSListener
83 : {
84 : public:
85 : NS_DECL_THREADSAFE_ISUPPORTS
86 : NS_DECL_NSIDNSLISTENER
87 :
88 1 : DNSListener()
89 1 : { }
90 :
91 : private:
92 0 : virtual ~DNSListener()
93 0 : { }
94 : };
95 :
96 : class Action : public nsICacheEntryOpenCallback
97 : {
98 : public:
99 : NS_DECL_THREADSAFE_ISUPPORTS
100 : NS_DECL_NSICACHEENTRYOPENCALLBACK
101 :
102 : Action(bool fullUri, bool predict, Reason reason,
103 : nsIURI *targetURI, nsIURI *sourceURI,
104 : nsINetworkPredictorVerifier *verifier, Predictor *predictor);
105 : Action(bool fullUri, bool predict, Reason reason,
106 : nsIURI *targetURI, nsIURI *sourceURI,
107 : nsINetworkPredictorVerifier *verifier, Predictor *predictor,
108 : uint8_t stackCount);
109 :
110 : static const bool IS_FULL_URI = true;
111 : static const bool IS_ORIGIN = false;
112 :
113 : static const bool DO_PREDICT = true;
114 : static const bool DO_LEARN = false;
115 :
116 : private:
117 : virtual ~Action();
118 :
119 : bool mFullUri : 1;
120 : bool mPredict : 1;
121 : union {
122 : PredictorPredictReason mPredictReason;
123 : PredictorLearnReason mLearnReason;
124 : };
125 : nsCOMPtr<nsIURI> mTargetURI;
126 : nsCOMPtr<nsIURI> mSourceURI;
127 : nsCOMPtr<nsINetworkPredictorVerifier> mVerifier;
128 : TimeStamp mStartTime;
129 : uint8_t mStackCount;
130 : RefPtr<Predictor> mPredictor;
131 : };
132 :
133 : class CacheabilityAction : public nsICacheEntryOpenCallback
134 : , public nsICacheEntryMetaDataVisitor
135 : {
136 : public:
137 : NS_DECL_THREADSAFE_ISUPPORTS
138 : NS_DECL_NSICACHEENTRYOPENCALLBACK
139 : NS_DECL_NSICACHEENTRYMETADATAVISITOR
140 :
141 0 : CacheabilityAction(nsIURI *targetURI, uint32_t httpStatus,
142 : const nsCString &method, Predictor *predictor)
143 0 : :mTargetURI(targetURI)
144 : ,mHttpStatus(httpStatus)
145 : ,mMethod(method)
146 0 : ,mPredictor(predictor)
147 0 : { }
148 :
149 : private:
150 0 : virtual ~CacheabilityAction() { }
151 :
152 : nsCOMPtr<nsIURI> mTargetURI;
153 : uint32_t mHttpStatus;
154 : nsCString mMethod;
155 : RefPtr<Predictor> mPredictor;
156 : nsTArray<nsCString> mKeysToCheck;
157 : nsTArray<nsCString> mValuesToCheck;
158 : };
159 :
160 : class Resetter : public nsICacheEntryOpenCallback,
161 : public nsICacheEntryMetaDataVisitor,
162 : public nsICacheStorageVisitor
163 : {
164 : public:
165 : NS_DECL_THREADSAFE_ISUPPORTS
166 : NS_DECL_NSICACHEENTRYOPENCALLBACK
167 : NS_DECL_NSICACHEENTRYMETADATAVISITOR
168 : NS_DECL_NSICACHESTORAGEVISITOR
169 :
170 : explicit Resetter(Predictor *predictor);
171 :
172 : private:
173 0 : virtual ~Resetter() { }
174 :
175 : void Complete();
176 :
177 : uint32_t mEntriesToVisit;
178 : nsTArray<nsCString> mKeysToDelete;
179 : RefPtr<Predictor> mPredictor;
180 : nsTArray<nsCOMPtr<nsIURI>> mURIsToVisit;
181 : nsTArray<nsCOMPtr<nsILoadContextInfo>> mInfosToVisit;
182 : };
183 :
184 : class SpaceCleaner : public nsICacheEntryMetaDataVisitor
185 : {
186 : public:
187 : NS_DECL_ISUPPORTS
188 : NS_DECL_NSICACHEENTRYMETADATAVISITOR
189 :
190 0 : explicit SpaceCleaner(Predictor *predictor)
191 0 : :mLRUStamp(0)
192 : ,mLRUKeyToDelete(nullptr)
193 0 : ,mPredictor(predictor)
194 0 : { }
195 :
196 : void Finalize(nsICacheEntry *entry);
197 :
198 : private:
199 0 : virtual ~SpaceCleaner() { }
200 : uint32_t mLRUStamp;
201 : const char *mLRUKeyToDelete;
202 : nsTArray<nsCString> mLongKeysToDelete;
203 : RefPtr<Predictor> mPredictor;
204 : };
205 :
206 : class PrefetchListener : public nsIStreamListener
207 : {
208 : public:
209 : NS_DECL_ISUPPORTS
210 : NS_DECL_NSIREQUESTOBSERVER
211 : NS_DECL_NSISTREAMLISTENER
212 :
213 0 : PrefetchListener(nsINetworkPredictorVerifier *verifier, nsIURI *uri,
214 : Predictor *predictor)
215 0 : :mVerifier(verifier)
216 : ,mURI(uri)
217 0 : ,mPredictor(predictor)
218 0 : { }
219 :
220 : private:
221 0 : virtual ~PrefetchListener() { }
222 :
223 : nsCOMPtr<nsINetworkPredictorVerifier> mVerifier;
224 : nsCOMPtr<nsIURI> mURI;
225 : RefPtr<Predictor> mPredictor;
226 : TimeStamp mStartTime;
227 : };
228 :
229 : // Observer-related stuff
230 : nsresult InstallObserver();
231 : void RemoveObserver();
232 :
233 : // Service startup utilities
234 : void MaybeCleanupOldDBFiles();
235 :
236 : // The guts of prediction
237 :
238 : // This is the top-level driver for doing any prediction that needs
239 : // information from the cache. Returns true if any predictions were queued up
240 : // * reason - What kind of prediction this is/why this prediction is
241 : // happening (pageload, startup)
242 : // * entry - the cache entry with the information we need
243 : // * isNew - whether or not the cache entry is brand new and empty
244 : // * fullUri - whether we are doing predictions based on a full page URI, or
245 : // just the origin of the page
246 : // * targetURI - the URI that we are predicting based upon - IOW, the URI
247 : // that is being loaded or being redirected to
248 : // * verifier - used for testing to verify the expected predictions happen
249 : // * stackCount - used to ensure we don't recurse too far trying to find the
250 : // final redirection in a redirect chain
251 : bool PredictInternal(PredictorPredictReason reason, nsICacheEntry *entry,
252 : bool isNew, bool fullUri, nsIURI *targetURI,
253 : nsINetworkPredictorVerifier *verifier,
254 : uint8_t stackCount);
255 :
256 : // Used when predicting because the user's mouse hovered over a link
257 : // * targetURI - the URI target of the link
258 : // * sourceURI - the URI of the page on which the link appears
259 : // * originAttributes - the originAttributes for this prediction
260 : // * verifier - used for testing to verify the expected predictions happen
261 : void PredictForLink(nsIURI *targetURI,
262 : nsIURI *sourceURI,
263 : const OriginAttributes& originAttributes,
264 : nsINetworkPredictorVerifier *verifier);
265 :
266 : // Used when predicting because a page is being loaded (which may include
267 : // being the target of a redirect). All arguments are the same as for
268 : // PredictInternal. Returns true if any predictions were queued up.
269 : bool PredictForPageload(nsICacheEntry *entry,
270 : nsIURI *targetURI,
271 : uint8_t stackCount,
272 : bool fullUri,
273 : nsINetworkPredictorVerifier *verifier);
274 :
275 : // Used when predicting pages that will be used near browser startup. All
276 : // arguments are the same as for PredictInternal. Returns true if any
277 : // predictions were queued up.
278 : bool PredictForStartup(nsICacheEntry *entry,
279 : bool fullUri,
280 : nsINetworkPredictorVerifier *verifier);
281 :
282 : // Utilities related to prediction
283 :
284 : // Used to update our rolling load count (how many of the last n loads was a
285 : // partular resource loaded on?)
286 : // * entry - cache entry of page we're loading
287 : // * flags - value that contains our rolling count as the top 20 bits (but
288 : // we may use fewer than those 20 bits for calculations)
289 : // * key - metadata key that we will update on entry
290 : // * hitCount - part of the metadata we need to preserve
291 : // * lastHit - part of the metadata we need to preserve
292 : void UpdateRollingLoadCount(nsICacheEntry *entry, const uint32_t flags,
293 : const char *key, const uint32_t hitCount,
294 : const uint32_t lastHit);
295 :
296 : // Used to calculate how much to degrade our confidence for all resources
297 : // on a particular page, because of how long ago the most recent load of that
298 : // page was. Returns a value between 0 (very recent most recent load) and 100
299 : // (very distant most recent load)
300 : // * lastLoad - time stamp of most recent load of a page
301 : int32_t CalculateGlobalDegradation(uint32_t lastLoad);
302 :
303 : // Used to calculate how confident we are that a particular resource will be
304 : // used. Returns a value between 0 (no confidence) and 100 (very confident)
305 : // * hitCount - number of times this resource has been seen when loading
306 : // this page
307 : // * hitsPossible - number of times this page has been loaded
308 : // * lastHit - timestamp of the last time this resource was seen when
309 : // loading this page
310 : // * lastPossible - timestamp of the last time this page was loaded
311 : // * globalDegradation - value calculated by CalculateGlobalDegradation for
312 : // this page
313 : int32_t CalculateConfidence(uint32_t hitCount, uint32_t hitsPossible,
314 : uint32_t lastHit, uint32_t lastPossible,
315 : int32_t globalDegradation);
316 :
317 : // Used to calculate all confidence values for all resources associated with a
318 : // page.
319 : // * entry - the cache entry with all necessary information about this page
320 : // * referrer - the URI that we are loading (may be null)
321 : // * lastLoad - timestamp of the last time this page was loaded
322 : // * loadCount - number of times this page has been loaded
323 : // * gloablDegradation - value calculated by CalculateGlobalDegradation for
324 : // this page
325 : // * fullUri - whether we're predicting for a full URI or origin-only
326 : void CalculatePredictions(nsICacheEntry *entry, nsIURI *referrer,
327 : uint32_t lastLoad, uint32_t loadCount,
328 : int32_t globalDegradation, bool fullUri);
329 :
330 : // Used to prepare any necessary prediction for a resource on a page
331 : // * confidence - value calculated by CalculateConfidence for this resource
332 : // * flags - the flags taken from the resource
333 : // * uri - the URI of the resource
334 : void SetupPrediction(int32_t confidence, uint32_t flags, nsIURI *uri);
335 :
336 : // Used to kick off a prefetch from RunPredictions if necessary
337 : // * uri - the URI to prefetch
338 : // * referrer - the URI of the referring page
339 : // * originAttributes - the originAttributes of this prefetch
340 : // * verifier - used for testing to ensure the expected prefetch happens
341 : nsresult Prefetch(nsIURI *uri, nsIURI *referrer,
342 : const OriginAttributes& originAttributes,
343 : nsINetworkPredictorVerifier *verifier);
344 :
345 : // Used to actually perform any predictions set up via SetupPrediction.
346 : // Returns true if any predictions were performed.
347 : // * referrer - the URI we are predicting from
348 : // * originAttributs - the originAttributes we are predicting from
349 : // * verifier - used for testing to ensure the expected predictions happen
350 : bool RunPredictions(nsIURI *referrer,
351 : const OriginAttributes& originAttributes,
352 : nsINetworkPredictorVerifier *verifier);
353 :
354 : // Used to guess whether a page will redirect to another page or not. Returns
355 : // true if a redirection is likely.
356 : // * entry - cache entry with all necessary information about this page
357 : // * loadCount - number of times this page has been loaded
358 : // * lastLoad - timestamp of the last time this page was loaded
359 : // * globalDegradation - value calculated by CalculateGlobalDegradation for
360 : // this page
361 : // * redirectURI - if this returns true, the URI that is likely to be
362 : // redirected to, otherwise null
363 : bool WouldRedirect(nsICacheEntry *entry, uint32_t loadCount,
364 : uint32_t lastLoad, int32_t globalDegradation,
365 : nsIURI **redirectURI);
366 :
367 : // The guts of learning information
368 :
369 : // This is the top-level driver for doing any updating of our information in
370 : // the cache
371 : // * reason - why this learn is happening (pageload, startup, redirect)
372 : // * entry - the cache entry with the information we need
373 : // * isNew - whether or not the cache entry is brand new and empty
374 : // * fullUri - whether we are doing predictions based on a full page URI, or
375 : // just the origin of the page
376 : // * targetURI - the URI that we are adding to our data - most often a
377 : // resource loaded by a page the user navigated to
378 : // * sourceURI - the URI that caused targetURI to be loaded, usually the
379 : // page the user navigated to
380 : void LearnInternal(PredictorLearnReason reason, nsICacheEntry *entry,
381 : bool isNew, bool fullUri, nsIURI *targetURI,
382 : nsIURI *sourceURI);
383 :
384 : // Used when learning about a resource loaded by a page
385 : // * entry - the cache entry with information that needs updating
386 : // * targetURI - the URI of the resource that was loaded by the page
387 : void LearnForSubresource(nsICacheEntry *entry, nsIURI *targetURI);
388 :
389 : // Used when learning about a redirect from one page to another
390 : // * entry - the cache entry of the page that was redirected from
391 : // * targetURI - the URI of the redirect target
392 : void LearnForRedirect(nsICacheEntry *entry, nsIURI *targetURI);
393 :
394 : // Used to learn about pages loaded close to browser startup. This results in
395 : // LearnForStartup being called if we are, in fact, near browser startup
396 : // * uri - the URI of a page that has been loaded (may not have been near
397 : // browser startup)
398 : // * fullUri - true if this is a full page uri, false if it's an origin
399 : // * originAttributes - the originAttributes for this learning.
400 : void MaybeLearnForStartup(nsIURI *uri, bool fullUri,
401 : const OriginAttributes& originAttributes);
402 :
403 : // Used in conjunction with MaybeLearnForStartup to learn about pages loaded
404 : // close to browser startup
405 : // * entry - the cache entry that stores the startup page list
406 : // * targetURI - the URI of a page that was loaded near browser startup
407 : void LearnForStartup(nsICacheEntry *entry, nsIURI *targetURI);
408 :
409 : // Used to parse the data we store in cache metadata
410 : // * key - the cache metadata key
411 : // * value - the cache metadata value
412 : // * uri - (out) the URI this metadata entry was about
413 : // * hitCount - (out) the number of times this URI has been seen
414 : // * lastHit - (out) timestamp of the last time this URI was seen
415 : // * flags - (out) flags for this metadata entry
416 : bool ParseMetaDataEntry(const char *key, const char *value, nsIURI **uri,
417 : uint32_t &hitCount, uint32_t &lastHit,
418 : uint32_t &flags);
419 :
420 : // Used to update whether a particular URI was cacheable or not.
421 : // sourceURI and targetURI are the same as the arguments to Learn
422 : // and httpStatus is the status code we got while loading targetURI.
423 : void UpdateCacheabilityInternal(nsIURI *sourceURI, nsIURI *targetURI,
424 : uint32_t httpStatus, const nsCString &method,
425 : const OriginAttributes& originAttributes);
426 :
427 : // Make sure our prefs are in their expected range of values
428 : void SanitizePrefs();
429 :
430 : // Our state
431 : bool mInitialized;
432 :
433 : bool mEnabled;
434 : bool mEnableHoverOnSSL;
435 : bool mEnablePrefetch;
436 :
437 : int32_t mPageDegradationDay;
438 : int32_t mPageDegradationWeek;
439 : int32_t mPageDegradationMonth;
440 : int32_t mPageDegradationYear;
441 : int32_t mPageDegradationMax;
442 :
443 : int32_t mSubresourceDegradationDay;
444 : int32_t mSubresourceDegradationWeek;
445 : int32_t mSubresourceDegradationMonth;
446 : int32_t mSubresourceDegradationYear;
447 : int32_t mSubresourceDegradationMax;
448 :
449 : int32_t mPrefetchRollingLoadCount;
450 : int32_t mPrefetchMinConfidence;
451 : int32_t mPreconnectMinConfidence;
452 : int32_t mPreresolveMinConfidence;
453 : int32_t mRedirectLikelyConfidence;
454 :
455 : int32_t mPrefetchForceValidFor;
456 :
457 : int32_t mMaxResourcesPerEntry;
458 :
459 : bool mCleanedUp;
460 : nsCOMPtr<nsITimer> mCleanupTimer;
461 :
462 : nsTArray<nsCString> mKeysToOperateOn;
463 : nsTArray<nsCString> mValuesToOperateOn;
464 :
465 : nsCOMPtr<nsICacheStorageService> mCacheStorageService;
466 :
467 : nsCOMPtr<nsIIOService> mIOService;
468 : nsCOMPtr<nsISpeculativeConnect> mSpeculativeService;
469 :
470 : nsCOMPtr<nsIURI> mStartupURI;
471 : uint32_t mStartupTime;
472 : uint32_t mLastStartupTime;
473 : int32_t mStartupCount;
474 :
475 : uint32_t mMaxURILength;
476 :
477 : nsCOMPtr<nsIDNSService> mDnsService;
478 :
479 : RefPtr<DNSListener> mDNSListener;
480 :
481 : nsTArray<nsCOMPtr<nsIURI>> mPrefetches;
482 : nsTArray<nsCOMPtr<nsIURI>> mPreconnects;
483 : nsTArray<nsCOMPtr<nsIURI>> mPreresolves;
484 :
485 : bool mDoingTests;
486 :
487 : static Predictor *sSelf;
488 : };
489 :
490 : } // namespace net
491 : } // namespace mozilla
492 :
493 : #endif // mozilla_net_Predictor_h
|