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