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 18 class HistoryService; 19 20 namespace content { 21 class SessionStorageNamespace; 22 class WebContents; 23 } 24 25 namespace gfx { 26 class Size; 27 } 28 29 namespace prerender { 30 31 class PrerenderHandle; 32 class 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. 38 class 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