15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_local_predictor.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ctype.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/field_trial.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h" 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/browser_process.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_database.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_db_task.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_service.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_service_factory.h" 237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chrome/browser/prerender/prerender_field_trial.h" 24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/browser/prerender/prerender_handle.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_histograms.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_manager.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/safe_browsing/database_manager.h" 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/safe_browsing/safe_browsing_service.h" 30b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 32b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "content/public/browser/navigation_controller.h" 33b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "content/public/browser/session_storage_namespace.h" 34b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "content/public/browser/web_contents.h" 35b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "content/public/browser/web_contents_view.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/page_transition_types.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/secure_hash.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/browser_resources.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/url_canon.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::PageTransition; 44b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)using content::SessionStorageNamespace; 45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)using content::WebContents; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using history::URLID; 47b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)using predictors::LoggedInPredictorTable; 48b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)using std::string; 49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)using std::vector; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace prerender { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kURLHashSize = 5; 56b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)static const int kNumPrerenderCandidates = 5; 57b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} // namespace 59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 60b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// When considering a candidate URL to be prerendered, we need to collect the 61b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// data in this struct to make the determination whether we should issue the 62b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// prerender or not. 63b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)struct PrerenderLocalPredictor::LocalPredictorURLInfo { 64b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) URLID id; 65b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) GURL url; 66b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) bool url_lookup_success; 67b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) bool logged_in; 68b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) bool logged_in_lookup_ok; 69b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) double priority; 70b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}; 71b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 72b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// A struct consisting of everything needed for launching a potential prerender 73b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// on a navigation: The navigation URL (source) triggering potential prerenders, 74b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// and a set of candidate URLs. 75b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)struct PrerenderLocalPredictor::LocalPredictorURLLookupInfo { 76b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) LocalPredictorURLInfo source_url_; 77b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) vector<LocalPredictorURLInfo> candidate_urls_; 78b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) explicit LocalPredictorURLLookupInfo(URLID source_id) { 79b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) source_url_.id = source_id; 80b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) void MaybeAddCandidateURL(URLID id, double priority) { 82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // TODO(tburkard): clean up this code, potentially using a list or a heap 83b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) LocalPredictorURLInfo info; 84b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) info.id = id; 85b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) info.priority = priority; 86b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int insert_pos = candidate_urls_.size(); 87b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (insert_pos < kNumPrerenderCandidates) 88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) candidate_urls_.push_back(info); 89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while (insert_pos > 0 && 90b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) candidate_urls_[insert_pos - 1].priority < info.priority) { 91b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (insert_pos < kNumPrerenderCandidates) 92b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) candidate_urls_[insert_pos] = candidate_urls_[insert_pos - 1]; 93b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) insert_pos--; 94b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 95b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (insert_pos < kNumPrerenderCandidates) 96b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) candidate_urls_[insert_pos] = info; 97b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 98b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}; 99b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 100b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Task to lookup the URL for a given URLID. 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class GetURLForURLIDTask : public history::HistoryDBTask { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) GetURLForURLIDTask( 106b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) PrerenderLocalPredictor::LocalPredictorURLLookupInfo* request, 107b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const base::Closure& callback) 108b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) : request_(request), 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_(callback), 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time_(base::Time::Now()) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool RunOnDBThread(history::HistoryBackend* backend, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::HistoryDatabase* db) OVERRIDE { 115b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DoURLLookup(db, &request_->source_url_); 116b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (int i = 0; i < static_cast<int>(request_->candidate_urls_.size()); i++) 117b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DoURLLookup(db, &request_->candidate_urls_[i]); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void DoneRunOnMainThread() OVERRIDE { 122b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) callback_.Run(); 123b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) UMA_HISTOGRAM_CUSTOM_TIMES("Prerender.LocalPredictorURLLookupTime", 124b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::Time::Now() - start_time_, 125b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::TimeDelta::FromMilliseconds(10), 126b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::TimeDelta::FromSeconds(10), 127b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 50); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~GetURLForURLIDTask() {} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 133b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) void DoURLLookup(history::HistoryDatabase* db, 134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) PrerenderLocalPredictor::LocalPredictorURLInfo* request) { 135b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) history::URLRow url_row; 136b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) request->url_lookup_success = db->GetURLRow(request->id, &url_row); 137b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (request->url_lookup_success) 138b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) request->url = url_row.url(); 139b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 141b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) PrerenderLocalPredictor::LocalPredictorURLLookupInfo* request_; 142b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::Closure callback_; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time start_time_; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(GetURLForURLIDTask); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Task to load history from the visit database on startup. 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class GetVisitHistoryTask : public history::HistoryDBTask { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetVisitHistoryTask(PrerenderLocalPredictor* local_predictor, 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_visits) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : local_predictor_(local_predictor), 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_visits_(max_visits), 154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) visit_history_(new vector<history::BriefVisitInfo>) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool RunOnDBThread(history::HistoryBackend* backend, 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::HistoryDatabase* db) OVERRIDE { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db->GetBriefVisitInfoOfMostRecentVisits(max_visits_, visit_history_.get()); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void DoneRunOnMainThread() OVERRIDE { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_predictor_->OnGetInitialVisitHistory(visit_history_.Pass()); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~GetVisitHistoryTask() {} 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrerenderLocalPredictor* local_predictor_; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_visits_; 172b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<vector<history::BriefVisitInfo> > visit_history_; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(GetVisitHistoryTask); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum visit history to retrieve from the visit database. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxVisitHistory = 100 * 1000; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Visit history size at which to trigger pruning, and number of items to prune. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kVisitHistoryPruneThreshold = 120 * 1000; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kVisitHistoryPruneAmount = 20 * 1000; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinLocalPredictionTimeMs = 500; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)int GetMaxLocalPredictionTimeMs() { 1867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return GetLocalPredictorTTLSeconds() * 1000; 1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 1887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsBackForward(PageTransition transition) { 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (transition & content::PAGE_TRANSITION_FORWARD_BACK) != 0; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsHomePage(PageTransition transition) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (transition & content::PAGE_TRANSITION_HOME_PAGE) != 0; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsIntermediateRedirect(PageTransition transition) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (transition & content::PAGE_TRANSITION_CHAIN_END) == 0; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochbool IsFormSubmit(PageTransition transition) { 20258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch return (transition & content::PAGE_TRANSITION_FORM_SUBMIT) != 0; 20358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch} 20458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShouldExcludeTransitionForPrediction(PageTransition transition) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return IsBackForward(transition) || IsHomePage(transition) || 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsIntermediateRedirect(transition); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::Time GetCurrentTime() { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::Time::Now(); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 214b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool StringContainsIgnoringCase(string haystack, string needle) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::transform(haystack.begin(), haystack.end(), haystack.begin(), ::tolower); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::transform(needle.begin(), needle.end(), needle.begin(), ::tolower); 217b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return haystack.find(needle) != string::npos; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsExtendedRootURL(const GURL& url) { 221b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const string& path = url.path(); 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return path == "/index.html" || path == "/home.html" || 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path == "/main.html" || 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path == "/index.htm" || path == "/home.htm" || path == "/main.htm" || 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path == "/index.php" || path == "/home.php" || path == "/main.php" || 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path == "/index.asp" || path == "/home.asp" || path == "/main.asp" || 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path == "/index.py" || path == "/home.py" || path == "/main.py" || 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path == "/index.pl" || path == "/home.pl" || path == "/main.pl"; 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsRootPageURL(const GURL& url) { 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (url.path() == "/" || url.path() == "" || IsExtendedRootURL(url)) && 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (!url.has_query()) && (!url.has_ref()); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 236b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool IsLogInURL(const GURL& url) { 237b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return StringContainsIgnoringCase(url.spec().c_str(), "login") || 238b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) StringContainsIgnoringCase(url.spec().c_str(), "signin"); 239b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 240b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 241b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool IsLogOutURL(const GURL& url) { 242b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return StringContainsIgnoringCase(url.spec().c_str(), "logout") || 243b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) StringContainsIgnoringCase(url.spec().c_str(), "signout"); 244b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 245b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 URLHashToInt64(const unsigned char* data) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COMPILE_ASSERT(kURLHashSize < sizeof(int64), url_hash_must_fit_in_int64); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 value = 0; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&value, data, kURLHashSize); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 GetInt64URLHashForURL(const GURL& url) { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COMPILE_ASSERT(kURLHashSize < sizeof(int64), url_hash_must_fit_in_int64); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<crypto::SecureHash> hash( 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::SecureHash::Create(crypto::SecureHash::SHA256)); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 hash_value = 0; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* url_string = url.spec().c_str(); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hash->Update(url_string, strlen(url_string)); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hash->Finish(&hash_value, kURLHashSize); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hash_value; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 264b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool URLsIdenticalIgnoringFragments(const GURL& url1, const GURL& url2) { 265b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) url_canon::Replacements<char> replacement; 266b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) replacement.ClearRef(); 267b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) GURL u1 = url1.ReplaceComponents(replacement); 268b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) GURL u2 = url2.ReplaceComponents(replacement); 269b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return (u1 == u2); 270b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 271b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 272b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void LookupLoggedInStatesOnDBThread( 273b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_refptr<LoggedInPredictorTable> logged_in_predictor_table, 274b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) PrerenderLocalPredictor::LocalPredictorURLLookupInfo* request_) { 275b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); 276b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (int i = 0; i < static_cast<int>(request_->candidate_urls_.size()); i++) { 277b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) PrerenderLocalPredictor::LocalPredictorURLInfo* info = 278b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) &request_->candidate_urls_[i]; 279b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (info->url_lookup_success) { 280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) logged_in_predictor_table->HasUserLoggedIn( 281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) info->url, &info->logged_in, &info->logged_in_lookup_ok); 282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } else { 283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) info->logged_in_lookup_ok = false; 284b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 285b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 287b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)struct PrerenderLocalPredictor::PrerenderProperties { 291b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) PrerenderProperties(URLID url_id, const GURL& url, double priority, 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time start_time) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : url_id(url_id), 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url(url), 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) priority(priority), 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time(start_time) { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Default constructor for dummy element 3007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) PrerenderProperties() 3017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) : priority(0.0) { 3027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) double GetCurrentDecayedPriority() { 3057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // If we are no longer prerendering, the priority is 0. 3067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!prerender_handle || !prerender_handle->IsPrerendering()) 3077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return 0.0; 3087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) int half_life_time_seconds = 3097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) GetLocalPredictorPrerenderPriorityHalfLifeTimeSeconds(); 3107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (half_life_time_seconds < 1) 3117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return priority; 3127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) double multiple_elapsed = 3137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) (GetCurrentTime() - actual_start_time).InMillisecondsF() / 3147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::TimeDelta::FromSeconds(half_life_time_seconds).InMillisecondsF(); 3157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Decay factor: 2 ^ (-multiple_elapsed) 3167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) double decay_factor = exp(- multiple_elapsed * log(2.0)); 3177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return priority * decay_factor; 3187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double priority; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For expiration purposes, this is a synthetic start time consisting either 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the actual start time, or of the last time the page was re-requested 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for prerendering - 10 seconds (unless the original request came after 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that). This is to emulate the effect of re-prerendering a page that is 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // about to expire, because it was re-requested for prerendering a second 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time after the actual prerender being kept around. 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time start_time; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The actual time this page was last requested for prerendering. 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time actual_start_time; 3327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<PrerenderHandle> prerender_handle; 3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Indicates whether this prerender would have matched a URL navigated to, 3347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // but was not swapped in for some reason. 3357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool would_have_matched; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrerenderLocalPredictor::PrerenderLocalPredictor( 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrerenderManager* prerender_manager) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : prerender_manager_(prerender_manager), 341b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) is_visit_database_observer_(false), 3427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) weak_factory_(this) { 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_CONSTRUCTED); 34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (base::MessageLoop::current()) { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_.Start(FROM_HERE, 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kInitDelayMs), 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &PrerenderLocalPredictor::Init); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_INIT_SCHEDULED); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const size_t kChecksumHashSize = 32; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::RefCountedStaticMemory* url_whitelist_data = 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceBundle::GetSharedInstance().LoadDataResourceBytes( 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_PRERENDER_URL_WHITELIST); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size = url_whitelist_data->size(); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned char* front = url_whitelist_data->front(); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size < kChecksumHashSize || 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (size - kChecksumHashSize) % kURLHashSize != 0) { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_URL_WHITELIST_ERROR); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<crypto::SecureHash> hash( 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::SecureHash::Create(crypto::SecureHash::SHA256)); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hash->Update(front + kChecksumHashSize, size - kChecksumHashSize); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char hash_value[kChecksumHashSize]; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hash->Finish(hash_value, kChecksumHashSize); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (memcmp(hash_value, front, kChecksumHashSize)) { 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_URL_WHITELIST_ERROR); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (const unsigned char* p = front + kChecksumHashSize; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p < front + size; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p += kURLHashSize) { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_whitelist_.insert(URLHashToInt64(p)); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_URL_WHITELIST_OK); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrerenderLocalPredictor::~PrerenderLocalPredictor() { 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Shutdown(); 3827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) for (int i = 0; i < static_cast<int>(issued_prerenders_.size()); i++) { 3837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) PrerenderProperties* p = issued_prerenders_[i]; 3847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK(p != NULL); 3857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (p->prerender_handle) 3867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) p->prerender_handle->OnCancel(); 3877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderLocalPredictor::Shutdown() { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_.Stop(); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_visit_database_observer_) { 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryService* history = GetHistoryIfExists(); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(history); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history->RemoveVisitDatabaseObserver(this); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_visit_database_observer_ = false; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderLocalPredictor::OnAddVisit(const history::BriefVisitInfo& info) { 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_ADD_VISIT); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!visit_history_.get()) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_history_->push_back(info); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (static_cast<int>(visit_history_->size()) > kVisitHistoryPruneThreshold) { 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_history_->erase(visit_history_->begin(), 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_history_->begin() + kVisitHistoryPruneAmount); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_ADD_VISIT_INITIALIZED); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_prerender_.get() && 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_prerender_->url_id == info.url_id && 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsPrerenderStillValid(current_prerender_.get())) { 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_TIMES( 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Prerender.LocalPredictorTimeUntilUsed", 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCurrentTime() - current_prerender_->actual_start_time, 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(10), 4187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::TimeDelta::FromMilliseconds(GetMaxLocalPredictionTimeMs()), 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 50); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_swapped_in_prerender_.reset(current_prerender_.release()); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_ADD_VISIT_PRERENDER_IDENTIFIED); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShouldExcludeTransitionForPrediction(info.transition)) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_ADD_VISIT_RELEVANT_TRANSITION); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta max_age = 4277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::TimeDelta::FromMilliseconds(GetMaxLocalPredictionTimeMs()); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta min_age = 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kMinLocalPredictionTimeMs); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<URLID> next_urls_currently_found; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<URLID, int> next_urls_num_found; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_occurrences_of_current_visit = 0; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time last_visited; 434b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<LocalPredictorURLLookupInfo> lookup_info( 435b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) new LocalPredictorURLLookupInfo(info.url_id)); 436b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const vector<history::BriefVisitInfo>& visits = *(visit_history_.get()); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < static_cast<int>(visits.size()); i++) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ShouldExcludeTransitionForPrediction(visits[i].transition)) { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits[i].url_id == info.url_id) { 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_visited = visits[i].time; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_occurrences_of_current_visit++; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_urls_currently_found.clear(); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!last_visited.is_null() && 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_visited > visits[i].time - max_age && 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_visited < visits[i].time - min_age) { 44858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch if (!IsFormSubmit(visits[i].transition)) 44958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch next_urls_currently_found.insert(visits[i].url_id); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == static_cast<int>(visits.size()) - 1 || 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits[i+1].url_id == info.url_id) { 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<URLID>::iterator it = next_urls_currently_found.begin(); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != next_urls_currently_found.end(); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<std::map<URLID, int>::iterator, bool> insert_ret = 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_urls_num_found.insert(std::pair<URLID, int>(*it, 0)); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<URLID, int>::iterator num_found_it = insert_ret.first; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_found_it->second++; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (std::map<URLID, int>::const_iterator it = next_urls_num_found.begin(); 466b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) it != next_urls_num_found.end(); 467b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ++it) { 468b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Only consider a candidate next page for prerendering if it was viewed 469b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // at least twice, and at least 10% of the time. 470b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (num_occurrences_of_current_visit > 0 && 471b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) it->second > 1 && 472b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) it->second * 10 >= num_occurrences_of_current_visit) { 473b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_ADD_VISIT_IDENTIFIED_PRERENDER_CANDIDATE); 474b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) double priority = static_cast<double>(it->second) / 475b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) static_cast<double>(num_occurrences_of_current_visit); 476b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lookup_info->MaybeAddCandidateURL(it->first, priority); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 479b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 480b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (lookup_info->candidate_urls_.size() == 0) { 481b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_NO_PRERENDER_CANDIDATES); 482b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; 483b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 484b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 485b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_START_URL_LOOKUP); 486b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) HistoryService* history = GetHistoryIfExists(); 487b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (history) { 488b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_GOT_HISTORY_ISSUING_LOOKUP); 489b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) LocalPredictorURLLookupInfo* lookup_info_ptr = lookup_info.get(); 490b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) history->ScheduleDBTask( 491b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) new GetURLForURLIDTask( 492b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lookup_info_ptr, 493b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::Bind(&PrerenderLocalPredictor::OnLookupURL, 494b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::Unretained(this), 495b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::Passed(&lookup_info))), 496b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) &history_db_consumer_); 497b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 500b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void PrerenderLocalPredictor::OnLookupURL( 501b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<LocalPredictorURLLookupInfo> info) { 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 504b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK_GE(static_cast<int>(info->candidate_urls_.size()), 1); 505b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 506b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!info->source_url_.url_lookup_success) { 507b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_FAILED); 508b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; 509b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 510b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 511b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) LogCandidateURLStats(info->candidate_urls_[0].url); 512b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 513b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) WebContents* source_web_contents = NULL; 514a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) bool multiple_source_web_contents_candidates = false; 515b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 516b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#if !defined(OS_ANDROID) 517b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // We need to figure out what tab launched the prerender. We do this by 518b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // comparing URLs. This may not always work: the URL may occur in two 519b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // tabs, and we pick the wrong one, or the tab we should have picked 520b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // may have navigated elsewhere. Hopefully, this doesn't happen too often, 521b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // so we ignore these cases for now. 522b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // TODO(tburkard): Reconsider this, potentially measure it, and fix this 523b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // in the future. 524b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (TabContentsIterator it; !it.done(); it.Next()) { 525b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (it->GetURL() == info->source_url_.url) { 526a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!source_web_contents) 527a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) source_web_contents = *it; 528a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) else 529a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) multiple_source_web_contents_candidates = true; 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 532b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#endif 533b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 534b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!source_web_contents) { 535b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_NO_SOURCE_WEBCONTENTS_FOUND); 536b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; 537b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 538b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 539a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (multiple_source_web_contents_candidates) 540a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_MULTIPLE_SOURCE_WEBCONTENTS_FOUND); 541a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 542a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 543b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_refptr<SessionStorageNamespace> session_storage_namespace = 544ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch source_web_contents->GetController().GetDefaultSessionStorageNamespace(); 545b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 546b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) gfx::Rect container_bounds; 547b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) source_web_contents->GetView()->GetContainerBounds(&container_bounds); 548b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<gfx::Size> size(new gfx::Size(container_bounds.size())); 549b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 550b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_refptr<LoggedInPredictorTable> logged_in_table = 551b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) prerender_manager_->logged_in_predictor_table(); 552b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 553b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!logged_in_table.get()) { 554b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_NO_LOGGED_IN_TABLE_FOUND); 555b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; 556b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 557b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 558b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_ISSUING_LOGGED_IN_LOOKUP); 559b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 560b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) LocalPredictorURLLookupInfo* info_ptr = info.get(); 561b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) BrowserThread::PostTaskAndReply( 562b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) BrowserThread::DB, FROM_HERE, 563b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::Bind(&LookupLoggedInStatesOnDBThread, 564b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) logged_in_table, 565b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) info_ptr), 566b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::Bind(&PrerenderLocalPredictor::ContinuePrerenderCheck, 567b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) weak_factory_.GetWeakPtr(), 568b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) session_storage_namespace, 569b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::Passed(&size), 570b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::Passed(&info))); 571b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 573b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void PrerenderLocalPredictor::LogCandidateURLStats(const GURL& url) const { 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_whitelist_.count(GetInt64URLHashForURL(url)) > 0) { 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_ON_WHITELIST); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsRootPageURL(url)) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_ON_WHITELIST_ROOT_PAGE); 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsRootPageURL(url)) 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_ROOT_PAGE); 5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsExtendedRootURL(url)) 5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_EXTENDED_ROOT_PAGE); 5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsRootPageURL(url) && url.SchemeIs("http")) 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_ROOT_PAGE_HTTP); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url.SchemeIs("http")) 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_IS_HTTP); 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url.has_query()) 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_HAS_QUERY_STRING); 589b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (IsLogOutURL(url)) 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_CONTAINS_LOGOUT); 591b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (IsLogInURL(url)) 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_CONTAINS_LOGIN); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderLocalPredictor::OnGetInitialVisitHistory( 596b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<vector<history::BriefVisitInfo> > visit_history) { 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!visit_history_.get()); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_INIT_SUCCEEDED); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since the visit history has descending timestamps, we must reverse it. 601b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) visit_history_.reset(new vector<history::BriefVisitInfo>( 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_history->rbegin(), visit_history->rend())); 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistoryService* PrerenderLocalPredictor::GetHistoryIfExists() const { 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = prerender_manager_->profile(); 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!profile) 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HistoryServiceFactory::GetForProfileWithoutCreating(profile); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderLocalPredictor::Init() { 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_INIT_STARTED); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryService* history = GetHistoryIfExists(); 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (history) { 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!is_visit_database_observer_); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history->ScheduleDBTask( 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new GetVisitHistoryTask(this, kMaxVisitHistory), 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &history_db_consumer_); 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history->AddVisitDatabaseObserver(this); 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_visit_database_observer_ = true; 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_INIT_FAILED_NO_HISTORY); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderLocalPredictor::OnPLTEventForURL(const GURL& url, 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta page_load_time) { 630b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<PrerenderProperties> prerender; 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (DoesPrerenderMatchPLTRecord(last_swapped_in_prerender_.get(), 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url, page_load_time)) { 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prerender.reset(last_swapped_in_prerender_.release()); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (DoesPrerenderMatchPLTRecord(current_prerender_.get(), 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url, page_load_time)) { 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prerender.reset(current_prerender_.release()); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!prerender.get()) 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsPrerenderStillValid(prerender.get())) { 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_TIMES("Prerender.SimulatedLocalBrowsingBaselinePLT", 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) page_load_time, 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(10), 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(60), 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100); 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta prerender_age = GetCurrentTime() - prerender->start_time; 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prerender_age > page_load_time) { 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta new_plt; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prerender_age < 2 * page_load_time) 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_plt = 2 * page_load_time - prerender_age; 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_TIMES("Prerender.SimulatedLocalBrowsingPLT", 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_plt, 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(10), 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(60), 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrerenderLocalPredictor::IsPrerenderStillValid( 663b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) PrerenderLocalPredictor::PrerenderProperties* prerender) const { 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (prerender && 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (prerender->start_time + 6667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::TimeDelta::FromMilliseconds(GetMaxLocalPredictionTimeMs())) 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) > GetCurrentTime()); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderLocalPredictor::RecordEvent( 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrerenderLocalPredictor::Event event) const { 672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Prerender.LocalPredictorEvent", 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event, PrerenderLocalPredictor::EVENT_MAX_VALUE); 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrerenderLocalPredictor::DoesPrerenderMatchPLTRecord( 677b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) PrerenderProperties* prerender, 678b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const GURL& url, 679b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::TimeDelta plt) const { 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prerender && prerender->start_time < GetCurrentTime() - plt) { 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prerender->url.is_empty()) 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_ERROR_NO_PRERENDER_URL_FOR_PLT); 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (prerender->url == url); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)PrerenderLocalPredictor::PrerenderProperties* 6907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)PrerenderLocalPredictor::GetIssuedPrerenderSlotForPriority(double priority) { 6917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) int num_prerenders = GetLocalPredictorMaxConcurrentPrerenders(); 6927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) while (static_cast<int>(issued_prerenders_.size()) < num_prerenders) 6937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) issued_prerenders_.push_back(new PrerenderProperties()); 6947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) PrerenderProperties* lowest_priority_prerender = NULL; 6957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) for (int i = 0; i < static_cast<int>(issued_prerenders_.size()); i++) { 6967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) PrerenderProperties* p = issued_prerenders_[i]; 6977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK(p != NULL); 6987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!p->prerender_handle || !p->prerender_handle->IsPrerendering()) 6997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return p; 7007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) double decayed_priority = p->GetCurrentDecayedPriority(); 7017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (decayed_priority > priority) 7027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) continue; 7037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (lowest_priority_prerender == NULL || 7047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) lowest_priority_prerender->GetCurrentDecayedPriority() > 7057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) decayed_priority) { 7067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) lowest_priority_prerender = p; 7077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 7087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 7097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return lowest_priority_prerender; 710b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 711b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 712b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void PrerenderLocalPredictor::ContinuePrerenderCheck( 713b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_refptr<SessionStorageNamespace> session_storage_namespace, 714b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<gfx::Size> size, 715b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<LocalPredictorURLLookupInfo> info) { 716b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_STARTED); 717b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<LocalPredictorURLInfo> url_info; 71890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_refptr<SafeBrowsingDatabaseManager> sb_db_manager = 71990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) g_browser_process->safe_browsing_service()->database_manager(); 7207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) PrerenderProperties* prerender_properties = NULL; 72190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 722b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (int i = 0; i < static_cast<int>(info->candidate_urls_.size()); i++) { 72358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_EXAMINE_NEXT_URL); 724b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) url_info.reset(new LocalPredictorURLInfo(info->candidate_urls_[i])); 725b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 726b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // We need to check whether we can issue a prerender for this URL. 727b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // We test a set of conditions. Each condition can either rule out 728b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // a prerender (in which case we reset url_info, so that it will not 729b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // be prerendered, and we continue, which means try the next candidate 730b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // URL), or it can be sufficient to issue the prerender without any 731b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // further checks (in which case we just break). 732b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // The order of the checks is critical, because it prescribes the logic 733b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // we use here to decide what to prerender. 734b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!url_info->url_lookup_success) { 735b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_NO_URL); 736b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) url_info.reset(NULL); 737b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) continue; 738b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 7397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) prerender_properties = 7407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) GetIssuedPrerenderSlotForPriority(url_info->priority); 7417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!prerender_properties) { 742b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_PRIORITY_TOO_LOW); 743b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) url_info.reset(NULL); 744b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) continue; 745b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 7462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (!SkipLocalPredictorFragment() && 7472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch URLsIdenticalIgnoringFragments(info->source_url_.url, 748b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) url_info->url)) { 749b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_URLS_IDENTICAL_BUT_FRAGMENT); 750b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) url_info.reset(NULL); 751b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) continue; 752b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 7532385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (!SkipLocalPredictorHTTPS() && url_info->url.SchemeIs("https")) { 754b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_HTTPS); 755b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) url_info.reset(NULL); 756b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) continue; 757b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 758b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (IsRootPageURL(url_info->url)) { 759b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // For root pages, we assume that they are reasonably safe, and we 760b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // will just prerender them without any additional checks. 761b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_ROOT_PAGE); 762b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break; 763b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 764b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (IsLogOutURL(url_info->url)) { 765b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_LOGOUT_URL); 766b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) url_info.reset(NULL); 767b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) continue; 768b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 769b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (IsLogInURL(url_info->url)) { 770b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_LOGIN_URL); 771b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) url_info.reset(NULL); 772b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) continue; 773b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 7742385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (!SkipLocalPredictorWhitelist() && 7752385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch sb_db_manager->CheckSideEffectFreeWhitelistUrl(url_info->url)) { 77690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // If a page is on the side-effect free whitelist, we will just prerender 77790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // it without any additional checks. 77890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_ON_SIDE_EFFECT_FREE_WHITELIST); 77990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 78090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 7812385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (!SkipLocalPredictorLoggedIn() && 7822385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch !url_info->logged_in && url_info->logged_in_lookup_ok) { 783b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_NOT_LOGGED_IN); 784b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break; 785b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 7862385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (!SkipLocalPredictorDefaultNoPrerender()) { 7872385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_FALLTHROUGH_NOT_PRERENDERING); 7882385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch url_info.reset(NULL); 7892385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch } else { 7902385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_FALLTHROUGH_PRERENDERING); 7912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch } 792b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 793b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!url_info.get()) 794b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; 795b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_ISSUING_PRERENDER); 7967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK(prerender_properties != NULL); 7977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (IsLocalPredictorPrerenderLaunchEnabled()) { 7987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) IssuePrerender(session_storage_namespace, size.Pass(), 7997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) url_info.Pass(), prerender_properties); 8007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 801b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 802b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 803b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void PrerenderLocalPredictor::IssuePrerender( 804b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_refptr<SessionStorageNamespace> session_storage_namespace, 805b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<gfx::Size> size, 8067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<LocalPredictorURLInfo> info, 8077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) PrerenderProperties* prerender_properties) { 808b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) URLID url_id = info->id; 809b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const GURL& url = info->url; 810b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) double priority = info->priority; 811b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::Time current_time = GetCurrentTime(); 812b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_ISSUING_PRERENDER); 813b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 8147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Issue the prerender and obtain a new handle. 8157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<prerender::PrerenderHandle> new_prerender_handle( 8167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) prerender_manager_->AddPrerenderFromLocalPredictor( 8177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) url, session_storage_namespace.get(), *size)); 8187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 8197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Check if this is a duplicate of an existing prerender. If yes, clean up 8207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // the new handle. 8217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) for (int i = 0; i < static_cast<int>(issued_prerenders_.size()); i++) { 8227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) PrerenderProperties* p = issued_prerenders_[i]; 8237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK(p != NULL); 8247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (new_prerender_handle && 8257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) new_prerender_handle->RepresentingSamePrerenderAs( 8267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) p->prerender_handle.get())) { 8277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) new_prerender_handle->OnCancel(); 8287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) new_prerender_handle.reset(NULL); 82958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch RecordEvent(EVENT_ISSUE_PRERENDER_ALREADY_PRERENDERING); 8307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) break; 8317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 8327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 8337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 8347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (new_prerender_handle.get()) { 83558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch RecordEvent(EVENT_ISSUE_PRERENDER_NEW_PRERENDER); 8367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // The new prerender does not match any existing prerenders. Update 8377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // prerender_properties so that it reflects the new entry. 8387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) prerender_properties->url_id = url_id; 8397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) prerender_properties->url = url; 8407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) prerender_properties->priority = priority; 8417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) prerender_properties->start_time = current_time; 8427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) prerender_properties->actual_start_time = current_time; 8437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) prerender_properties->would_have_matched = false; 8447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) prerender_properties->prerender_handle.swap(new_prerender_handle); 8457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // new_prerender_handle now represents the old previou prerender that we 8467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // are replacing. So we need to cancel it. 84758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch if (new_prerender_handle) { 8487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) new_prerender_handle->OnCancel(); 84958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch RecordEvent(EVENT_ISSUE_PRERENDER_CANCELLED_OLD_PRERENDER); 85058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch } 8517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 852b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 853b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_ADD_VISIT_PRERENDERING); 854b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (current_prerender_.get() && current_prerender_->url_id == url_id) { 855b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RecordEvent(EVENT_ADD_VISIT_PRERENDERING_EXTENDED); 856b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (priority > current_prerender_->priority) 857b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) current_prerender_->priority = priority; 858b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // If the prerender already existed, we want to extend it. However, 859b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // we do not want to set its start_time to the current time to 860b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // disadvantage PLT computations when the prerender is swapped in. 861b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // So we set the new start time to current_time - 10s (since the vast 862b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // majority of PLTs are < 10s), provided that is not before the actual 863b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // time the prerender was started (so as to not artificially advantage 864b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // the PLT computation). 865b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::Time simulated_new_start_time = 866b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) current_time - base::TimeDelta::FromSeconds(10); 867b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (simulated_new_start_time > current_prerender_->start_time) 868b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) current_prerender_->start_time = simulated_new_start_time; 869b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } else { 870b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) current_prerender_.reset( 871b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) new PrerenderProperties(url_id, url, priority, current_time)); 872b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 873b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) current_prerender_->actual_start_time = current_time; 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 876a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void PrerenderLocalPredictor::OnTabHelperURLSeen( 877a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const GURL& url, WebContents* web_contents) { 878a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) RecordEvent(EVENT_TAB_HELPER_URL_SEEN); 8797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 880a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // If the namespace matches and the URL matches, we might be able to swap 881a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // in. However, the actual code initating the swapin is in the renderer 882a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // and is checking for other criteria (such as POSTs). There may 883a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // also be conditions when a swapin should happen but does not. By recording 884a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // the two previous events, we can keep an eye on the magnitude of the 885a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // discrepancy. 8867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 8877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) PrerenderProperties* best_matched_prerender = NULL; 8887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool session_storage_namespace_matches = false; 8897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) for (int i = 0; i < static_cast<int>(issued_prerenders_.size()); i++) { 8907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) PrerenderProperties* p = issued_prerenders_[i]; 8917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK(p != NULL); 8927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!p->prerender_handle.get() || 8937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) !p->prerender_handle->Matches(url, NULL) || 8947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) p->would_have_matched) { 8957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) continue; 8967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 8977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!best_matched_prerender || !session_storage_namespace_matches) { 8987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) best_matched_prerender = p; 8997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) session_storage_namespace_matches = 9007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) p->prerender_handle->Matches( 9017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) url, 9027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) web_contents->GetController(). 903ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch GetDefaultSessionStorageNamespace()); 9047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 9057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 9067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (best_matched_prerender) { 9077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RecordEvent(EVENT_TAB_HELPER_URL_SEEN_MATCH); 9087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) best_matched_prerender->would_have_matched = true; 9097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (session_storage_namespace_matches) 9107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RecordEvent(EVENT_TAB_HELPER_URL_SEEN_NAMESPACE_MATCH); 9117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 912a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 913a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace prerender 915