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#ifndef CHROME_BROWSER_PRERENDER_PRERENDER_LOCAL_PREDICTOR_H_
6#define CHROME_BROWSER_PRERENDER_PRERENDER_LOCAL_PREDICTOR_H_
7
8#include <vector>
9
10#include "base/containers/hash_tables.h"
11#include "base/memory/scoped_vector.h"
12#include "base/memory/weak_ptr.h"
13#include "base/timer/timer.h"
14#include "chrome/browser/common/cancelable_request.h"
15#include "chrome/browser/history/visit_database.h"
16#include "url/gurl.h"
17
18class HistoryService;
19
20namespace content {
21class SessionStorageNamespace;
22class WebContents;
23}
24
25namespace gfx {
26class Size;
27}
28
29namespace prerender {
30
31class PrerenderHandle;
32class PrerenderManager;
33
34// PrerenderLocalPredictor maintains local browsing history to make prerender
35// predictions.
36// At this point, the class is not actually creating prerenders, but just
37// recording timing stats about the effect prerendering would have.
38class PrerenderLocalPredictor : public history::VisitDatabaseObserver {
39 public:
40  struct LocalPredictorURLInfo;
41  struct LocalPredictorURLLookupInfo;
42  enum Event {
43    EVENT_CONSTRUCTED = 0,
44    EVENT_INIT_SCHEDULED = 1,
45    EVENT_INIT_STARTED = 2,
46    EVENT_INIT_FAILED_NO_HISTORY = 3,
47    EVENT_INIT_SUCCEEDED = 4,
48    EVENT_ADD_VISIT = 5,
49    EVENT_ADD_VISIT_INITIALIZED = 6,
50    EVENT_ADD_VISIT_PRERENDER_IDENTIFIED = 7,
51    EVENT_ADD_VISIT_RELEVANT_TRANSITION = 8,
52    EVENT_ADD_VISIT_IDENTIFIED_PRERENDER_CANDIDATE = 9,
53    EVENT_ADD_VISIT_PRERENDERING = 10,
54    EVENT_GOT_PRERENDER_URL = 11,
55    EVENT_ERROR_NO_PRERENDER_URL_FOR_PLT = 12,
56    EVENT_ADD_VISIT_PRERENDERING_EXTENDED = 13,
57    EVENT_PRERENDER_URL_LOOKUP_RESULT = 14,
58    EVENT_PRERENDER_URL_LOOKUP_RESULT_ROOT_PAGE = 15,
59    EVENT_PRERENDER_URL_LOOKUP_RESULT_IS_HTTP = 16,
60    EVENT_PRERENDER_URL_LOOKUP_RESULT_HAS_QUERY_STRING = 17,
61    EVENT_PRERENDER_URL_LOOKUP_RESULT_CONTAINS_LOGOUT = 18,
62    EVENT_PRERENDER_URL_LOOKUP_RESULT_CONTAINS_LOGIN = 19,
63    EVENT_START_URL_LOOKUP = 20,
64    EVENT_ADD_VISIT_NOT_ROOTPAGE = 21,
65    EVENT_URL_WHITELIST_ERROR = 22,
66    EVENT_URL_WHITELIST_OK = 23,
67    EVENT_PRERENDER_URL_LOOKUP_RESULT_ON_WHITELIST = 24,
68    EVENT_PRERENDER_URL_LOOKUP_RESULT_ON_WHITELIST_ROOT_PAGE = 25,
69    EVENT_PRERENDER_URL_LOOKUP_RESULT_EXTENDED_ROOT_PAGE = 26,
70    EVENT_PRERENDER_URL_LOOKUP_RESULT_ROOT_PAGE_HTTP = 27,
71    EVENT_PRERENDER_URL_LOOKUP_FAILED = 28,
72    EVENT_PRERENDER_URL_LOOKUP_NO_SOURCE_WEBCONTENTS_FOUND = 29,
73    EVENT_PRERENDER_URL_LOOKUP_NO_LOGGED_IN_TABLE_FOUND = 30,
74    EVENT_PRERENDER_URL_LOOKUP_ISSUING_LOGGED_IN_LOOKUP = 31,
75    EVENT_CONTINUE_PRERENDER_CHECK_STARTED = 32,
76    EVENT_CONTINUE_PRERENDER_CHECK_NO_URL = 33,
77    EVENT_CONTINUE_PRERENDER_CHECK_PRIORITY_TOO_LOW = 34,
78    EVENT_CONTINUE_PRERENDER_CHECK_URLS_IDENTICAL_BUT_FRAGMENT = 35,
79    EVENT_CONTINUE_PRERENDER_CHECK_HTTPS = 36,
80    EVENT_CONTINUE_PRERENDER_CHECK_ROOT_PAGE = 37,
81    EVENT_CONTINUE_PRERENDER_CHECK_LOGOUT_URL = 38,
82    EVENT_CONTINUE_PRERENDER_CHECK_LOGIN_URL = 39,
83    EVENT_CONTINUE_PRERENDER_CHECK_NOT_LOGGED_IN = 40,
84    EVENT_CONTINUE_PRERENDER_CHECK_FALLTHROUGH_NOT_PRERENDERING = 41,
85    EVENT_CONTINUE_PRERENDER_CHECK_ISSUING_PRERENDER = 42,
86    EVENT_ISSUING_PRERENDER = 43,
87    EVENT_NO_PRERENDER_CANDIDATES = 44,
88    EVENT_GOT_HISTORY_ISSUING_LOOKUP = 45,
89    EVENT_TAB_HELPER_URL_SEEN = 46,
90    EVENT_TAB_HELPER_URL_SEEN_MATCH = 47,
91    EVENT_TAB_HELPER_URL_SEEN_NAMESPACE_MATCH = 48,
92    EVENT_PRERENDER_URL_LOOKUP_MULTIPLE_SOURCE_WEBCONTENTS_FOUND = 49,
93    EVENT_CONTINUE_PRERENDER_CHECK_ON_SIDE_EFFECT_FREE_WHITELIST = 50,
94    EVENT_CONTINUE_PRERENDER_CHECK_EXAMINE_NEXT_URL = 51,
95    EVENT_ISSUE_PRERENDER_ALREADY_PRERENDERING = 52,
96    EVENT_ISSUE_PRERENDER_NEW_PRERENDER = 53,
97    EVENT_ISSUE_PRERENDER_CANCELLED_OLD_PRERENDER = 54,
98    EVENT_CONTINUE_PRERENDER_CHECK_FALLTHROUGH_PRERENDERING = 55,
99    EVENT_MAX_VALUE
100  };
101
102  // A PrerenderLocalPredictor is owned by the PrerenderManager specified
103  // in the constructor.  It will be destoryed at the time its owning
104  // PrerenderManager is destroyed.
105  explicit PrerenderLocalPredictor(PrerenderManager* prerender_manager);
106  virtual ~PrerenderLocalPredictor();
107
108  void Shutdown();
109
110  // history::VisitDatabaseObserver implementation
111  virtual void OnAddVisit(const history::BriefVisitInfo& info) OVERRIDE;
112
113  void OnGetInitialVisitHistory(
114      scoped_ptr<std::vector<history::BriefVisitInfo> > visit_history);
115
116  void OnPLTEventForURL(const GURL& url, base::TimeDelta page_load_time);
117
118  void OnTabHelperURLSeen(const GURL& url, content::WebContents* web_contents);
119
120 private:
121  struct PrerenderProperties;
122  HistoryService* GetHistoryIfExists() const;
123  void Init();
124  bool IsPrerenderStillValid(PrerenderProperties* prerender) const;
125  bool DoesPrerenderMatchPLTRecord(PrerenderProperties* prerender,
126                                   const GURL& url,
127                                   base::TimeDelta plt) const;
128  void RecordEvent(Event event) const;
129
130  void OnLookupURL(scoped_ptr<LocalPredictorURLLookupInfo> info);
131
132  // Returns an element of issued_prerenders_, which should be replaced
133  // by a new prerender of the priority indicated, or NULL, if the priority
134  // is too low.
135  PrerenderProperties* GetIssuedPrerenderSlotForPriority(double priority);
136
137  void ContinuePrerenderCheck(
138      scoped_refptr<content::SessionStorageNamespace> session_storage_namespace,
139      scoped_ptr<gfx::Size> size,
140      scoped_ptr<LocalPredictorURLLookupInfo> info);
141  void LogCandidateURLStats(const GURL& url) const;
142  void IssuePrerender(scoped_refptr<content::SessionStorageNamespace>
143                      session_storage_namespace,
144                      scoped_ptr<gfx::Size> size,
145                      scoped_ptr<LocalPredictorURLInfo> info,
146                      PrerenderProperties* prerender_properties);
147  PrerenderManager* prerender_manager_;
148  base::OneShotTimer<PrerenderLocalPredictor> timer_;
149
150  // Delay after which to initialize, to avoid putting to much load on the
151  // database thread early on when Chrome is starting up.
152  static const int kInitDelayMs = 5 * 1000;
153
154  // Whether we're registered with the history service as a
155  // history::VisitDatabaseObserver.
156  bool is_visit_database_observer_;
157
158  CancelableRequestConsumer history_db_consumer_;
159
160  scoped_ptr<std::vector<history::BriefVisitInfo> > visit_history_;
161
162  scoped_ptr<PrerenderProperties> current_prerender_;
163  scoped_ptr<PrerenderProperties> last_swapped_in_prerender_;
164
165  ScopedVector<PrerenderProperties> issued_prerenders_;
166
167  base::hash_set<int64> url_whitelist_;
168
169  base::WeakPtrFactory<PrerenderLocalPredictor> weak_factory_;
170
171  DISALLOW_COPY_AND_ASSIGN(PrerenderLocalPredictor);
172};
173
174}  // namespace prerender
175
176#endif  // CHROME_BROWSER_PRERENDER_PRERENDER_LOCAL_PREDICTOR_H_
177