prerender_local_predictor.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/timer.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_database.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_db_task.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_service.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_service_factory.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_histograms.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_manager.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/page_transition_types.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/secure_hash.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/browser_resources.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::PageTransition; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using history::URLID; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace prerender { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kURLHashSize = 5; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Task to lookup the URL for a given URLID. 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class GetURLForURLIDTask : public history::HistoryDBTask { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetURLForURLIDTask(URLID url_id, base::Callback<void(const GURL&)> callback) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : url_id_(url_id), 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success_(false), 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_(callback), 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time_(base::Time::Now()) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool RunOnDBThread(history::HistoryBackend* backend, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::HistoryDatabase* db) OVERRIDE { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::URLRow url_row; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success_ = db->GetURLRow(url_id_, &url_row); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success_) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_ = url_row.url(); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void DoneRunOnMainThread() OVERRIDE { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success_) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_.Run(url_); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_TIMES("Prerender.LocalPredictorURLLookupTime", 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time::Now() - start_time_, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(10), 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(10), 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 50); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~GetURLForURLIDTask() {} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id_; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success_; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Callback<void(const GURL&)> callback_; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time start_time_; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url_; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(GetURLForURLIDTask); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Task to load history from the visit database on startup. 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class GetVisitHistoryTask : public history::HistoryDBTask { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetVisitHistoryTask(PrerenderLocalPredictor* local_predictor, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_visits) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : local_predictor_(local_predictor), 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_visits_(max_visits), 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_history_(new std::vector<history::BriefVisitInfo>) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool RunOnDBThread(history::HistoryBackend* backend, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::HistoryDatabase* db) OVERRIDE { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db->GetBriefVisitInfoOfMostRecentVisits(max_visits_, visit_history_.get()); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void DoneRunOnMainThread() OVERRIDE { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_predictor_->OnGetInitialVisitHistory(visit_history_.Pass()); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~GetVisitHistoryTask() {} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrerenderLocalPredictor* local_predictor_; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_visits_; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<std::vector<history::BriefVisitInfo> > visit_history_; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(GetVisitHistoryTask); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum visit history to retrieve from the visit database. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxVisitHistory = 100 * 1000; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Visit history size at which to trigger pruning, and number of items to prune. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kVisitHistoryPruneThreshold = 120 * 1000; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kVisitHistoryPruneAmount = 20 * 1000; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxLocalPredictionTimeMs = 300 * 1000; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinLocalPredictionTimeMs = 500; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsBackForward(PageTransition transition) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (transition & content::PAGE_TRANSITION_FORWARD_BACK) != 0; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsHomePage(PageTransition transition) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (transition & content::PAGE_TRANSITION_HOME_PAGE) != 0; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsIntermediateRedirect(PageTransition transition) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (transition & content::PAGE_TRANSITION_CHAIN_END) == 0; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShouldExcludeTransitionForPrediction(PageTransition transition) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return IsBackForward(transition) || IsHomePage(transition) || 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsIntermediateRedirect(transition); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::Time GetCurrentTime() { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::Time::Now(); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool StrCaseStr(std::string haystack, std::string needle) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::transform(haystack.begin(), haystack.end(), haystack.begin(), ::tolower); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::transform(needle.begin(), needle.end(), needle.begin(), ::tolower); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return haystack.find(needle) != std::string::npos; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsExtendedRootURL(const GURL& url) { 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& path = url.path(); 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return path == "/index.html" || path == "/home.html" || 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path == "/main.html" || 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path == "/index.htm" || path == "/home.htm" || path == "/main.htm" || 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path == "/index.php" || path == "/home.php" || path == "/main.php" || 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path == "/index.asp" || path == "/home.asp" || path == "/main.asp" || 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path == "/index.py" || path == "/home.py" || path == "/main.py" || 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path == "/index.pl" || path == "/home.pl" || path == "/main.pl"; 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsRootPageURL(const GURL& url) { 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (url.path() == "/" || url.path() == "" || IsExtendedRootURL(url)) && 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (!url.has_query()) && (!url.has_ref()); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 URLHashToInt64(const unsigned char* data) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COMPILE_ASSERT(kURLHashSize < sizeof(int64), url_hash_must_fit_in_int64); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 value = 0; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&value, data, kURLHashSize); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 GetInt64URLHashForURL(const GURL& url) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COMPILE_ASSERT(kURLHashSize < sizeof(int64), url_hash_must_fit_in_int64); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<crypto::SecureHash> hash( 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::SecureHash::Create(crypto::SecureHash::SHA256)); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 hash_value = 0; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* url_string = url.spec().c_str(); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hash->Update(url_string, strlen(url_string)); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hash->Finish(&hash_value, kURLHashSize); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hash_value; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct PrerenderLocalPredictor::PrerenderData { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrerenderData(URLID url_id, const GURL& url, double priority, 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time start_time) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : url_id(url_id), 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url(url), 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) priority(priority), 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time(start_time) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double priority; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For expiration purposes, this is a synthetic start time consisting either 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the actual start time, or of the last time the page was re-requested 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for prerendering - 10 seconds (unless the original request came after 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that). This is to emulate the effect of re-prerendering a page that is 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // about to expire, because it was re-requested for prerendering a second 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time after the actual prerender being kept around. 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time start_time; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The actual time this page was last requested for prerendering. 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time actual_start_time; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_IMPLICIT_CONSTRUCTORS(PrerenderData); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrerenderLocalPredictor::PrerenderLocalPredictor( 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrerenderManager* prerender_manager) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : prerender_manager_(prerender_manager), 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_visit_database_observer_(false) { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_CONSTRUCTED); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MessageLoop::current()) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_.Start(FROM_HERE, 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kInitDelayMs), 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &PrerenderLocalPredictor::Init); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_INIT_SCHEDULED); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const size_t kChecksumHashSize = 32; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::RefCountedStaticMemory* url_whitelist_data = 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceBundle::GetSharedInstance().LoadDataResourceBytes( 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_PRERENDER_URL_WHITELIST); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size = url_whitelist_data->size(); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned char* front = url_whitelist_data->front(); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size < kChecksumHashSize || 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (size - kChecksumHashSize) % kURLHashSize != 0) { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_URL_WHITELIST_ERROR); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<crypto::SecureHash> hash( 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::SecureHash::Create(crypto::SecureHash::SHA256)); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hash->Update(front + kChecksumHashSize, size - kChecksumHashSize); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char hash_value[kChecksumHashSize]; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hash->Finish(hash_value, kChecksumHashSize); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (memcmp(hash_value, front, kChecksumHashSize)) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_URL_WHITELIST_ERROR); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (const unsigned char* p = front + kChecksumHashSize; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p < front + size; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p += kURLHashSize) { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_whitelist_.insert(URLHashToInt64(p)); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_URL_WHITELIST_OK); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrerenderLocalPredictor::~PrerenderLocalPredictor() { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Shutdown(); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderLocalPredictor::Shutdown() { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_.Stop(); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_visit_database_observer_) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryService* history = GetHistoryIfExists(); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(history); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history->RemoveVisitDatabaseObserver(this); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_visit_database_observer_ = false; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderLocalPredictor::OnAddVisit(const history::BriefVisitInfo& info) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_ADD_VISIT); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!visit_history_.get()) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_history_->push_back(info); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (static_cast<int>(visit_history_->size()) > kVisitHistoryPruneThreshold) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_history_->erase(visit_history_->begin(), 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_history_->begin() + kVisitHistoryPruneAmount); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_ADD_VISIT_INITIALIZED); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_prerender_.get() && 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_prerender_->url_id == info.url_id && 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsPrerenderStillValid(current_prerender_.get())) { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_TIMES( 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Prerender.LocalPredictorTimeUntilUsed", 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCurrentTime() - current_prerender_->actual_start_time, 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(10), 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kMaxLocalPredictionTimeMs), 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 50); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_swapped_in_prerender_.reset(current_prerender_.release()); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_ADD_VISIT_PRERENDER_IDENTIFIED); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShouldExcludeTransitionForPrediction(info.transition)) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_ADD_VISIT_RELEVANT_TRANSITION); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta max_age = 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kMaxLocalPredictionTimeMs); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta min_age = 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kMinLocalPredictionTimeMs); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<URLID> next_urls_currently_found; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<URLID, int> next_urls_num_found; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_occurrences_of_current_visit = 0; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time last_visited; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID best_next_url = 0; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int best_next_url_count = 0; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<history::BriefVisitInfo>& visits = *(visit_history_.get()); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < static_cast<int>(visits.size()); i++) { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ShouldExcludeTransitionForPrediction(visits[i].transition)) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits[i].url_id == info.url_id) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_visited = visits[i].time; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_occurrences_of_current_visit++; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_urls_currently_found.clear(); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!last_visited.is_null() && 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_visited > visits[i].time - max_age && 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_visited < visits[i].time - min_age) { 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_urls_currently_found.insert(visits[i].url_id); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == static_cast<int>(visits.size()) - 1 || 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits[i+1].url_id == info.url_id) { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<URLID>::iterator it = next_urls_currently_found.begin(); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != next_urls_currently_found.end(); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<std::map<URLID, int>::iterator, bool> insert_ret = 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_urls_num_found.insert(std::pair<URLID, int>(*it, 0)); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<URLID, int>::iterator num_found_it = insert_ret.first; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_found_it->second++; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (num_found_it->second > best_next_url_count) { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_next_url_count = num_found_it->second; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_next_url = *it; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only consider a candidate next page for prerendering if it was viewed 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // at least twice, and at least 10% of the time. 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (num_occurrences_of_current_visit > 0 && 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_next_url_count > 1 && 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_next_url_count * 10 >= num_occurrences_of_current_visit) { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_ADD_VISIT_IDENTIFIED_PRERENDER_CANDIDATE); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double priority = static_cast<double>(best_next_url_count) / 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<double>(num_occurrences_of_current_visit); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShouldReplaceCurrentPrerender(priority)) { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_START_URL_LOOKUP); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryService* history = GetHistoryIfExists(); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (history) { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history->ScheduleDBTask( 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new GetURLForURLIDTask( 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_next_url, 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&PrerenderLocalPredictor::OnLookupURL, 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this), 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_next_url, 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) priority)), 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &history_db_consumer_); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderLocalPredictor::OnLookupURL(history::URLID url_id, 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double priority, 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time current_time = GetCurrentTime(); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShouldReplaceCurrentPrerender(priority)) { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsRootPageURL(url)) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_ADD_VISIT_PRERENDERING); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_prerender_.get() && current_prerender_->url_id == url_id) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_ADD_VISIT_PRERENDERING_EXTENDED); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (priority > current_prerender_->priority) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_prerender_->priority = priority; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the prerender already existed, we want to extend it. However, 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we do not want to set its start_time to the current time to 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // disadvantage PLT computations when the prerender is swapped in. 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // So we set the new start time to current_time - 10s (since the vast 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // majority of PLTs are < 10s), provided that is not before the actual 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time the prerender was started (so as to not artificially advantage 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the PLT computation). 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time simulated_new_start_time = 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_time - base::TimeDelta::FromSeconds(10); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (simulated_new_start_time > current_prerender_->start_time) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_prerender_->start_time = simulated_new_start_time; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_prerender_.reset( 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new PrerenderData(url_id, url, priority, current_time)); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_prerender_->actual_start_time = current_time; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_ADD_VISIT_NOT_ROOTPAGE); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_whitelist_.count(GetInt64URLHashForURL(url)) > 0) { 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_ON_WHITELIST); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsRootPageURL(url)) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_ON_WHITELIST_ROOT_PAGE); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsRootPageURL(url)) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_ROOT_PAGE); 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsExtendedRootURL(url)) 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_EXTENDED_ROOT_PAGE); 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsRootPageURL(url) && url.SchemeIs("http")) 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_ROOT_PAGE_HTTP); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url.SchemeIs("http")) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_IS_HTTP); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url.has_query()) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_HAS_QUERY_STRING); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (StrCaseStr(url.spec().c_str(), "logout") || 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StrCaseStr(url.spec().c_str(), "signout")) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_CONTAINS_LOGOUT); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (StrCaseStr(url.spec().c_str(), "login") || 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StrCaseStr(url.spec().c_str(), "signin")) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT_CONTAINS_LOGIN); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderLocalPredictor::OnGetInitialVisitHistory( 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<std::vector<history::BriefVisitInfo> > visit_history) { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!visit_history_.get()); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_INIT_SUCCEEDED); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since the visit history has descending timestamps, we must reverse it. 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_history_.reset(new std::vector<history::BriefVisitInfo>( 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_history->rbegin(), visit_history->rend())); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistoryService* PrerenderLocalPredictor::GetHistoryIfExists() const { 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = prerender_manager_->profile(); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!profile) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HistoryServiceFactory::GetForProfileWithoutCreating(profile); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderLocalPredictor::Init() { 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_INIT_STARTED); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryService* history = GetHistoryIfExists(); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (history) { 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!is_visit_database_observer_); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history->ScheduleDBTask( 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new GetVisitHistoryTask(this, kMaxVisitHistory), 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &history_db_consumer_); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history->AddVisitDatabaseObserver(this); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_visit_database_observer_ = true; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_INIT_FAILED_NO_HISTORY); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderLocalPredictor::OnPLTEventForURL(const GURL& url, 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta page_load_time) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<PrerenderData> prerender; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (DoesPrerenderMatchPLTRecord(last_swapped_in_prerender_.get(), 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url, page_load_time)) { 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prerender.reset(last_swapped_in_prerender_.release()); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (DoesPrerenderMatchPLTRecord(current_prerender_.get(), 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url, page_load_time)) { 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prerender.reset(current_prerender_.release()); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!prerender.get()) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsPrerenderStillValid(prerender.get())) { 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_TIMES("Prerender.SimulatedLocalBrowsingBaselinePLT", 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) page_load_time, 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(10), 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(60), 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta prerender_age = GetCurrentTime() - prerender->start_time; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prerender_age > page_load_time) { 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta new_plt; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prerender_age < 2 * page_load_time) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_plt = 2 * page_load_time - prerender_age; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_TIMES("Prerender.SimulatedLocalBrowsingPLT", 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_plt, 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(10), 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(60), 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrerenderLocalPredictor::IsPrerenderStillValid( 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrerenderLocalPredictor::PrerenderData* prerender) const { 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (prerender && 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (prerender->start_time + 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kMaxLocalPredictionTimeMs)) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) > GetCurrentTime()); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderLocalPredictor::RecordEvent( 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrerenderLocalPredictor::Event event) const { 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION( 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::FieldTrial::MakeName("Prerender.LocalPredictorEvent", "Prerender"), 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event, PrerenderLocalPredictor::EVENT_MAX_VALUE); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrerenderLocalPredictor::DoesPrerenderMatchPLTRecord( 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrerenderData* prerender, const GURL& url, base::TimeDelta plt) const { 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prerender && prerender->start_time < GetCurrentTime() - plt) { 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prerender->url.is_empty()) 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordEvent(EVENT_ERROR_NO_PRERENDER_URL_FOR_PLT); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (prerender->url == url); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrerenderLocalPredictor::ShouldReplaceCurrentPrerender( 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double priority) const { 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta max_age = 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kMaxLocalPredictionTimeMs); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (!current_prerender_.get()) || 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_prerender_->priority < priority || 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_prerender_->start_time < GetCurrentTime() - max_age; 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace prerender 518