Coverage Report

Created: 2018-09-25 14:53

/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