1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// A UrlInfo object is used to store prediction related information about a host
6// port and scheme triplet.  When performing DNS pre-resolution of the host/port
7// pair, its state is monitored as it is resolved.
8// It includes progress, from placement in the Predictor's queue, to resolution
9// by the DNS service as either FOUND or NO_SUCH_NAME.  Each instance may also
10// hold records of previous resolution times, which might later be shown to be
11// savings relative to resolution time during a navigation.
12// UrlInfo objects are also used to describe frames, and additional instances
13// may describe associated subresources, for future speculative connections to
14// those expected subresources.
15
16#ifndef CHROME_BROWSER_NET_URL_INFO_H_
17#define CHROME_BROWSER_NET_URL_INFO_H_
18
19#include <string>
20#include <vector>
21
22#include "base/time/time.h"
23#include "net/base/host_port_pair.h"
24#include "url/gurl.h"
25
26namespace chrome_browser_net {
27
28// Use command line switch to enable detailed logging.
29void EnablePredictorDetailedLog(bool enable);
30
31class UrlInfo {
32 public:
33  // Reasons for a domain to be resolved.
34  enum ResolutionMotivation {
35    MOUSE_OVER_MOTIVATED,  // Mouse-over link induced resolution.
36    PAGE_SCAN_MOTIVATED,   // Scan of rendered page induced resolution.
37    UNIT_TEST_MOTIVATED,
38    LINKED_MAX_MOTIVATED,    // enum demarkation above motivation from links.
39    OMNIBOX_MOTIVATED,       // Omni-box suggested resolving this.
40    STARTUP_LIST_MOTIVATED,  // Startup list caused this resolution.
41    EARLY_LOAD_MOTIVATED,    // In some cases we use the prefetcher to warm up
42                             // the connection in advance of issuing the real
43                             // request.
44
45    NO_PREFETCH_MOTIVATION,  // Browser navigation info (not prefetch related).
46
47    // The following involve predictive prefetching, triggered by a navigation.
48    // The referrinrg_url_ is also set when these are used.
49    // TODO(jar): Support STATIC_REFERAL_MOTIVATED API and integration.
50    STATIC_REFERAL_MOTIVATED,  // External database suggested this resolution.
51    LEARNED_REFERAL_MOTIVATED,  // Prior navigation taught us this resolution.
52    SELF_REFERAL_MOTIVATED,  // Guess about need for a second connection.
53
54    MAX_MOTIVATED  // Beyond all enums, for use in histogram bounding.
55  };
56
57  enum DnsProcessingState {
58      // When processed by our prefetching system, the states are:
59      PENDING,       // Constructor has completed.
60      QUEUED,        // In name queue but not yet being resolved.
61      ASSIGNED,      // Being resolved (or being reset to earlier state)
62      ASSIGNED_BUT_MARKED,  // Needs to be deleted as soon as it's resolved.
63      FOUND,         // DNS resolution completed.
64      NO_SUCH_NAME,  // DNS resolution completed.
65  };
66
67  typedef std::vector<UrlInfo> UrlInfoTable;
68
69  static base::TimeDelta NullDuration() {
70    return base::TimeDelta::FromMilliseconds(-1);
71  }
72
73  // UrlInfo are usually made by the default constructor during
74  // initializing of the Predictor's map (of info for Hostnames).
75  UrlInfo();
76
77  ~UrlInfo();
78
79  // NeedDnsUpdate decides, based on our internal info,
80  // if it would be valuable to attempt to update (prefectch)
81  // DNS data for hostname.  This decision is based
82  // on how recently we've done DNS prefetching for hostname.
83  bool NeedsDnsUpdate();
84
85  // FOR TEST ONLY: The following access the otherwise constant values.
86  static void set_cache_expiration(base::TimeDelta time);
87  static base::TimeDelta get_cache_expiration();
88
89  // The prefetching lifecycle.
90  void SetQueuedState(ResolutionMotivation motivation);
91  void SetAssignedState();
92  void RemoveFromQueue();
93  void SetPendingDeleteState();
94  void SetFoundState();
95  void SetNoSuchNameState();
96
97  // Finish initialization. Must only be called once.
98  void SetUrl(const GURL& url);
99
100  bool was_linked() const { return was_linked_; }
101
102  GURL referring_url() const { return referring_url_; }
103  void SetReferringHostname(const GURL& url) {
104    referring_url_ = url;
105  }
106
107  bool was_found() const { return FOUND == state_; }
108  bool was_nonexistent() const { return NO_SUCH_NAME == state_; }
109  bool is_assigned() const {
110    return ASSIGNED == state_ || ASSIGNED_BUT_MARKED == state_;
111  }
112  bool is_marked_to_delete() const { return ASSIGNED_BUT_MARKED == state_; }
113
114  bool HasUrl(const GURL& url) const {
115    return url_ == url;
116  }
117
118  base::TimeDelta resolve_duration() const { return resolve_duration_;}
119  base::TimeDelta queue_duration() const { return queue_duration_;}
120
121  void DLogResultsStats(const char* message) const;
122
123  static void GetHtmlTable(const UrlInfoTable& host_infos,
124                           const char* description,
125                           bool brief,
126                           std::string* output);
127
128  // For testing, and use in printing tables of info, we sometimes need to
129  // adjust the time manually.  Usually, this value is maintained by state
130  // transition, and this call is not made.
131  void set_time(const base::TimeTicks& time) { time_ = time; }
132
133 private:
134  base::TimeDelta GetDuration() {
135    base::TimeTicks old_time = time_;
136    time_ = base::TimeTicks::Now();
137    return time_ - old_time;
138  }
139
140  // IsStillCached() guesses if the DNS cache still has IP data.
141  bool IsStillCached() const;
142
143  // Record why we created, or have updated (reqested pre-resolution) of this
144  // instance.
145  void SetMotivation(ResolutionMotivation motivation);
146
147  // Helper function for about:dns printing.
148  std::string GetAsciiMotivation() const;
149
150  // The current state of this instance.
151  DnsProcessingState state_;
152
153  // Record the state prior to going to a queued state, in case we have to back
154  // out of the queue.
155  DnsProcessingState old_prequeue_state_;
156
157  GURL url_;  // Host, port and scheme for this info.
158
159  // When was last state changed (usually lookup completed).
160  base::TimeTicks time_;
161  // Time needed for DNS to resolve.
162  base::TimeDelta resolve_duration_;
163  // Time spent in queue.
164  base::TimeDelta queue_duration_;
165
166  int sequence_number_;  // Used to calculate potential of cache eviction.
167  static int sequence_counter;  // Used to allocate sequence_number_'s.
168
169  // Motivation for creation of this instance.
170  ResolutionMotivation motivation_;
171
172  // Record if the motivation for prefetching was ever a page-link-scan.
173  bool was_linked_;
174
175  // If this instance holds data about a navigation, we store the referrer.
176  // If this instance hold data about a prefetch, and the prefetch was
177  // instigated by a referrer, we store it here (for use in about:dns).
178  GURL referring_url_;
179
180  // We put these objects into a std::map, and hence we
181  // need some "evil" constructors.
182  // DISALLOW_COPY_AND_ASSIGN(UrlInfo);
183};
184
185}  // namespace chrome_browser_net
186
187#endif  // CHROME_BROWSER_NET_URL_INFO_H_
188