172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Use of this source code is governed by a BSD-style license that can be 321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// found in the LICENSE file. 421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/prerender/prerender_manager.h" 621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/logging.h" 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/metrics/field_trial.h" 972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/metrics/histogram.h" 1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/time.h" 1121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/utf_string_conversions.h" 1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/prerender/prerender_contents.h" 13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/prerender/prerender_final_status.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/profiles/profile.h" 15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h" 17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_process_host.h" 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/renderer_host/resource_dispatcher_host.h" 19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/render_view_host_manager.h" 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/tab_contents/tab_contents.h" 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h" 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/view_messages.h" 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "googleurl/src/url_parse.h" 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "googleurl/src/url_canon.h" 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "googleurl/src/url_util.h" 26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace prerender { 2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint PrerenderManager::prerenders_per_session_count_ = 0; 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static 3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbase::TimeTicks PrerenderManager::last_prefetch_seen_time_; 3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static 3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenPrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = 3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PRERENDER_MODE_ENABLED; 3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static 4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenPrerenderManager::PrerenderManagerMode PrerenderManager::GetMode() { 4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return mode_; 4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 4372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static 4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid PrerenderManager::SetMode(PrerenderManagerMode mode) { 4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen mode_ = mode; 4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool PrerenderManager::IsPrerenderingPossible() { 5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return 5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GetMode() == PRERENDER_MODE_ENABLED || 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetMode() == PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP || 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetMode() == PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP; 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool PrerenderManager::IsControlGroup() { 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return GetMode() == PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP; 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool PrerenderManager::MaybeGetQueryStringBasedAliasURL( 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const GURL& url, GURL* alias_url) { 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(alias_url); 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url_parse::Parsed parsed; 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url_parse::ParseStandardURL(url.spec().c_str(), url.spec().length(), 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &parsed); 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url_parse::Component query = parsed.query; 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url_parse::Component key, value; 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen while (url_parse::ExtractQueryKeyValue(url.spec().c_str(), &query, &key, 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &value)) { 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (key.len != 3 || strncmp(url.spec().c_str() + key.begin, "url", key.len)) 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen continue; 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We found a url= query string component. 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (value.len < 1) 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen continue; 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url_canon::RawCanonOutputW<1024> decoded_url; 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url_util::DecodeURLEscapeSequences(url.spec().c_str() + value.begin, 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen value.len, &decoded_url); 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GURL new_url(string16(decoded_url.data(), decoded_url.length())); 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!new_url.is_empty() && new_url.is_valid()) { 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *alias_url = new_url; 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstruct PrerenderManager::PrerenderContentsData { 9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PrerenderContents* contents_; 9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::Time start_time_; 94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen PrerenderContentsData(PrerenderContents* contents, base::Time start_time) 9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : contents_(contents), 96dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen start_time_(start_time) { 9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}; 9921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstruct PrerenderManager::PendingContentsData { 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PendingContentsData(const GURL& url, const std::vector<GURL>& alias_urls, 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const GURL& referrer) 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : url_(url), alias_urls_(alias_urls), referrer_(referrer) { } 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ~PendingContentsData() {} 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GURL url_; 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<GURL> alias_urls_; 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GURL referrer_; 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenPrerenderManager::PrerenderManager(Profile* profile) 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : rate_limit_enabled_(true), 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen enabled_(true), 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile_(profile), 11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen max_prerender_age_(base::TimeDelta::FromSeconds( 11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen kDefaultMaxPrerenderAgeSeconds)), 11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen max_elements_(kDefaultMaxPrerenderElements), 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen prerender_contents_factory_(PrerenderContents::CreateFactory()), 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen last_prerender_start_time_(GetCurrentTimeTicks() - 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs)) { 12121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenPrerenderManager::~PrerenderManager() { 124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen while (!prerender_list_.empty()) { 12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PrerenderContentsData data = prerender_list_.front(); 12621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen prerender_list_.pop_front(); 127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen data.contents_->set_final_status(FINAL_STATUS_MANAGER_SHUTDOWN); 12821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen delete data.contents_; 12921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 13021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 13121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 13272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid PrerenderManager::SetPrerenderContentsFactory( 13372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PrerenderContents::Factory* prerender_contents_factory) { 13472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prerender_contents_factory_.reset(prerender_contents_factory); 13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool PrerenderManager::AddPreload(const GURL& url, 138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const std::vector<GURL>& alias_urls, 139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const GURL& referrer) { 14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 14121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DeleteOldEntries(); 142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (FindEntry(url)) 143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return false; 144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Local copy, since we may have to add an additional entry to it. 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<GURL> all_alias_urls = alias_urls; 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GURL additional_alias_url; 149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsControlGroup() && 150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PrerenderManager::MaybeGetQueryStringBasedAliasURL( 151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url, &additional_alias_url)) 152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen all_alias_urls.push_back(additional_alias_url); 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Do not prerender if there are too many render processes, and we would 155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // have to use an existing one. We do not want prerendering to happen in 156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // a shared process, so that we can always reliably lower the CPU 157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // priority for prerendering. 158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // In single-process mode, ShouldTryToUseExistingProcessHost() always returns 159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // true, so that case needs to be explicitly checked for. 160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // TODO(tburkard): Figure out how to cancel prerendering in the opposite 161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // case, when a new tab is added to a process used for prerendering. 162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (RenderProcessHost::ShouldTryToUseExistingProcessHost() && 163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen !RenderProcessHost::run_renderer_in_process()) { 164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Only record the status if we are not in the control group. 165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!IsControlGroup()) 166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RecordFinalStatus(FINAL_STATUS_TOO_MANY_PROCESSES); 167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Check if enough time has passed since the last prerender. 171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!DoesRateLimitAllowPrerender()) { 172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Cancel the prerender. We could add it to the pending prerender list but 173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // this doesn't make sense as the next prerender request will be triggered 174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // by a navigation and is unlikely to be the same site. 175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RecordFinalStatus(FINAL_STATUS_RATE_LIMIT_EXCEEDED); 176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 177dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return false; 17821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 180dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // TODO(cbentzel): Move invalid checks here instead of PrerenderContents? 181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PrerenderContentsData data(CreatePrerenderContents(url, all_alias_urls, 182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen referrer), 183dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GetCurrentTime()); 184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 18521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen prerender_list_.push_back(data); 186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsControlGroup()) { 187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen data.contents_->set_final_status(FINAL_STATUS_CONTROL_GROUP); 188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen last_prerender_start_time_ = GetCurrentTimeTicks(); 190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen data.contents_->StartPrerendering(); 191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 19221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen while (prerender_list_.size() > max_elements_) { 19321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen data = prerender_list_.front(); 19421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen prerender_list_.pop_front(); 195dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen data.contents_->set_final_status(FINAL_STATUS_EVICTED); 19621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen delete data.contents_; 19721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 198dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen StartSchedulingPeriodicCleanups(); 199dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return true; 20021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 20121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PrerenderManager::AddPendingPreload( 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::pair<int,int>& child_route_id_pair, 204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const GURL& url, 205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::vector<GURL>& alias_urls, 206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const GURL& referrer) { 207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Check if this is coming from a valid prerender rvh. 208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool is_valid_prerender = false; 209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); 210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen it != prerender_list_.end(); ++it) { 211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PrerenderContents* pc = it->contents_; 212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int child_id; 214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int route_id; 215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool has_child_id = pc->GetChildId(&child_id); 216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool has_route_id = has_child_id && pc->GetRouteId(&route_id); 217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (has_child_id && has_route_id && 219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen child_id == child_route_id_pair.first && 220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen route_id == child_route_id_pair.second) { 221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen is_valid_prerender = true; 222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If not, we could check to see if the RenderViewHost specified by the 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // child_route_id_pair exists and if so just start prerendering, as this 228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // suggests that the link was clicked, though this might prerender something 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // that the user has already navigated away from. For now, we'll be 230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // conservative and skip the prerender which will mean some prerender requests 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // from prerendered pages will be missed if the user navigates quickly. 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!is_valid_prerender) { 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RecordFinalStatus(FINAL_STATUS_PENDING_SKIPPED); 234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PendingPrerenderList::iterator it = 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_prerender_list_.find(child_route_id_pair); 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (it == pending_prerender_list_.end()) { 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PendingPrerenderList::value_type el = std::make_pair(child_route_id_pair, 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<PendingContentsData>()); 242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen it = pending_prerender_list_.insert(el).first; 243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen it->second.push_back(PendingContentsData(url, alias_urls, referrer)); 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 24821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid PrerenderManager::DeleteOldEntries() { 249dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen while (!prerender_list_.empty()) { 25021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PrerenderContentsData data = prerender_list_.front(); 25121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (IsPrerenderElementFresh(data.start_time_)) 25221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return; 25321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen prerender_list_.pop_front(); 254dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen data.contents_->set_final_status(FINAL_STATUS_TIMED_OUT); 25521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen delete data.contents_; 25621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (prerender_list_.empty()) 258dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen StopSchedulingPeriodicCleanups(); 25921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 26021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 26121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenPrerenderContents* PrerenderManager::GetEntry(const GURL& url) { 26221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DeleteOldEntries(); 26321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); 26421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen it != prerender_list_.end(); 26521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ++it) { 26672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PrerenderContents* pc = it->contents_; 26772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (pc->MatchesURL(url)) { 26821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen prerender_list_.erase(it); 26921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return pc; 27021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 27121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 27221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Entry not found. 27321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return NULL; 27421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 27521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 27621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool PrerenderManager::MaybeUsePreloadedPage(TabContents* tc, const GURL& url) { 27772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 27821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen scoped_ptr<PrerenderContents> pc(GetEntry(url)); 27921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (pc.get() == NULL) 28021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 28121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If we are just in the control group (which can be detected by noticing 283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // that prerendering hasn't even started yet), record that this TC now would 284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // be showing a prerendered contents, but otherwise, don't do anything. 285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!pc->prerendering_has_started()) { 286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MarkTabContentsAsWouldBePrerendered(tc); 287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 29072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!pc->load_start_time().is_null()) 291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RecordTimeUntilUsed(GetCurrentTimeTicks() - pc->load_start_time()); 292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UMA_HISTOGRAM_COUNTS("Prerender.PrerendersPerSessionCount", 294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ++prerenders_per_session_count_); 295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen pc->set_final_status(FINAL_STATUS_USED); 29672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int child_id; 298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int route_id; 299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CHECK(pc->GetChildId(&child_id)); 300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CHECK(pc->GetRouteId(&route_id)); 301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 30221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen RenderViewHost* rvh = pc->render_view_host(); 303dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // RenderViewHosts in PrerenderContents start out hidden. 304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Since we are actually using it now, restore it. 305dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen rvh->WasRestored(); 30621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen pc->set_render_view_host(NULL); 30772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rvh->Send(new ViewMsg_DisplayPrerenderedPage(rvh->routing_id())); 30821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen tc->SwapInRenderViewHost(rvh); 309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MarkTabContentsAsPrerendered(tc); 310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // See if we have any pending prerender requests for this routing id and start 312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // the preload if we do. 313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::pair<int, int> child_route_pair = std::make_pair(child_id, route_id); 314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PendingPrerenderList::iterator pending_it = 315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_prerender_list_.find(child_route_pair); 316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (pending_it != pending_prerender_list_.end()) { 317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (std::vector<PendingContentsData>::iterator content_it = 318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_it->second.begin(); 319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen content_it != pending_it->second.end(); ++content_it) { 320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen AddPreload(content_it->url_, content_it->alias_urls_, 321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen content_it->referrer_); 322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_prerender_list_.erase(pending_it); 324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NotificationService::current()->Notify( 327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NotificationType::PRERENDER_CONTENTS_USED, 328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Source<std::pair<int, int> >(&child_route_pair), 329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NotificationService::NoDetails()); 33021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 33121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ViewHostMsg_FrameNavigate_Params* p = pc->navigate_params(); 33221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (p != NULL) 33321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen tc->DidNavigate(rvh, *p); 33421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 33521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen string16 title = pc->title(); 33621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!title.empty()) 33721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen tc->UpdateTitle(rvh, pc->page_id(), UTF16ToWideHack(title)); 33821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 33972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GURL icon_url = pc->icon_url(); 340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!icon_url.is_empty()) { 341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<FaviconURL> urls; 342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen urls.push_back(FaviconURL(icon_url, FaviconURL::FAVICON)); 343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tc->favicon_helper().OnUpdateFaviconURL(pc->page_id(), urls); 344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 34572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 34672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (pc->has_stopped_loading()) 34772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen tc->DidStopLoading(); 34872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 34921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return true; 35021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 35121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 35221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid PrerenderManager::RemoveEntry(PrerenderContents* entry) { 35372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 35421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); 35521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen it != prerender_list_.end(); 35621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ++it) { 35721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (it->contents_ == entry) { 358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RemovePendingPreload(entry); 35921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen prerender_list_.erase(it); 36021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen break; 36121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 36221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 36321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DeleteOldEntries(); 36421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 36521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 36621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbase::Time PrerenderManager::GetCurrentTime() const { 36721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return base::Time::Now(); 36821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 36921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbase::TimeTicks PrerenderManager::GetCurrentTimeTicks() const { 371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return base::TimeTicks::Now(); 372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 37421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool PrerenderManager::IsPrerenderElementFresh(const base::Time start) const { 37521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::Time now = GetCurrentTime(); 37621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return (now - start < max_prerender_age_); 37721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 37821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 37972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenPrerenderContents* PrerenderManager::CreatePrerenderContents( 38072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const GURL& url, 381dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const std::vector<GURL>& alias_urls, 382dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const GURL& referrer) { 38372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return prerender_contents_factory_->CreatePrerenderContents( 384dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen this, profile_, url, alias_urls, referrer); 38572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 38672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 387ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Helper macro for histograms. 388ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#define RECORD_PLT(tag, perceived_page_load_time) { \ 389ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UMA_HISTOGRAM_CUSTOM_TIMES( \ 390ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::FieldTrial::MakeName(std::string("Prerender.") + tag, \ 391ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "Prefetch"), \ 392ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen perceived_page_load_time, \ 393ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::TimeDelta::FromMilliseconds(10), \ 394ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::TimeDelta::FromSeconds(60), \ 395ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 100); \ 396ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 397ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 398dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static 399ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PrerenderManager::RecordPerceivedPageLoadTime( 400ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::TimeDelta perceived_page_load_time, 401ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabContents* tab_contents) { 402ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool within_window = WithinWindow(); 403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PrerenderManager* prerender_manager = 404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_contents->profile()->GetPrerenderManager(); 405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!prerender_manager) 406ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 407ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!prerender_manager->is_enabled()) 408ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RECORD_PLT("PerceivedPLT", perceived_page_load_time); 410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (within_window) 411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RECORD_PLT("PerceivedPLTWindowed", perceived_page_load_time); 412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (prerender_manager && 413ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ((mode_ == PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP && 414ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen prerender_manager->WouldTabContentsBePrerendered(tab_contents)) || 415ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (mode_ == PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP && 416ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen prerender_manager->IsTabContentsPrerendered(tab_contents)))) { 417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RECORD_PLT("PerceivedPLTMatched", perceived_page_load_time); 418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (within_window) 420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RECORD_PLT("PerceivedPLTWindowNotMatched", perceived_page_load_time); 42172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 42272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 42372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 42472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid PrerenderManager::RecordTimeUntilUsed(base::TimeDelta time_until_used) { 425ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UMA_HISTOGRAM_CUSTOM_TIMES( 426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "Prerender.TimeUntilUsed", 427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen time_until_used, 428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::TimeDelta::FromMilliseconds(10), 429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::TimeDelta::FromSeconds(kDefaultMaxPrerenderAgeSeconds), 430ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 50); 431ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 432ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool PrerenderManager::is_enabled() const { 434ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return enabled_; 436ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 437ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 438ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PrerenderManager::set_enabled(bool enabled) { 439ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen enabled_ = enabled; 44172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 44272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 44372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenPrerenderContents* PrerenderManager::FindEntry(const GURL& url) { 44472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); 44572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen it != prerender_list_.end(); 44672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ++it) { 44772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (it->contents_->MatchesURL(url)) 44872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return it->contents_; 44972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 45072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Entry not found. 45172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return NULL; 45272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 45372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 454ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenPrerenderManager::PendingContentsData* 455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PrerenderManager::FindPendingEntry(const GURL& url) { 456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (PendingPrerenderList::iterator map_it = pending_prerender_list_.begin(); 457ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen map_it != pending_prerender_list_.end(); 458ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ++map_it) { 459ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (std::vector<PendingContentsData>::iterator content_it = 460ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen map_it->second.begin(); 461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen content_it != map_it->second.end(); 462ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ++content_it) { 463ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (content_it->url_ == url) { 464ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return &(*content_it); 465ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 467ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 468ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 469ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return NULL; 470ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 471ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 472dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static 47372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid PrerenderManager::RecordPrefetchTagObserved() { 47472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Ensure that we are in the UI thread, and post to the UI thread if 47572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // necessary. 47672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 47772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BrowserThread::PostTask( 47872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BrowserThread::UI, 47972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FROM_HERE, 48072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NewRunnableFunction( 48172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &PrerenderManager::RecordPrefetchTagObservedOnUIThread)); 48272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 48372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen RecordPrefetchTagObservedOnUIThread(); 48472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 48572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 48672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 487dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static 48872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid PrerenderManager::RecordPrefetchTagObservedOnUIThread() { 48972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Once we get here, we have to be on the UI thread. 49072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 49172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 49272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If we observe multiple tags within the 30 second window, we will still 49372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // reset the window to begin at the most recent occurrence, so that we will 49472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // always be in a window in the 30 seconds from each occurrence. 49572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen last_prefetch_seen_time_ = base::TimeTicks::Now(); 49672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 49772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 498ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PrerenderManager::RemovePendingPreload(PrerenderContents* entry) { 499ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int child_id; 500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int route_id; 501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool has_child_id = entry->GetChildId(&child_id); 502ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool has_route_id = has_child_id && entry->GetRouteId(&route_id); 503ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 504ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If the entry doesn't have a RenderViewHost then it didn't start 505ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // prerendering and there shouldn't be any pending preloads to remove. 506ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (has_child_id && has_route_id) { 507ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::pair<int, int> child_route_pair = std::make_pair(child_id, route_id); 508ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_prerender_list_.erase(child_route_pair); 509ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 512dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static 513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool PrerenderManager::WithinWindow() { 51472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 51572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (last_prefetch_seen_time_.is_null()) 51672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 51772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::TimeDelta elapsed_time = 51872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::TimeTicks::Now() - last_prefetch_seen_time_; 519ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return elapsed_time <= base::TimeDelta::FromSeconds(kWindowDurationSeconds); 520ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 521ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 522ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool PrerenderManager::DoesRateLimitAllowPrerender() const { 523ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::TimeDelta elapsed_time = 525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetCurrentTimeTicks() - last_prerender_start_time_; 526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UMA_HISTOGRAM_TIMES("Prerender.TimeBetweenPrerenderRequests", 527ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen elapsed_time); 528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!rate_limit_enabled_) 529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return elapsed_time > 531ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs); 53221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 533dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 534dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid PrerenderManager::StartSchedulingPeriodicCleanups() { 535dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (repeating_timer_.IsRunning()) 536dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 537dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen repeating_timer_.Start( 538dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen base::TimeDelta::FromMilliseconds(kPeriodicCleanupIntervalMs), 539dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen this, 540dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &PrerenderManager::PeriodicCleanup); 541dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 542dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 543dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid PrerenderManager::StopSchedulingPeriodicCleanups() { 544dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen repeating_timer_.Stop(); 545dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 546dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 547dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid PrerenderManager::PeriodicCleanup() { 548dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DeleteOldEntries(); 549dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Grab a copy of the current PrerenderContents pointers, so that we 550dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // will not interfere with potential deletions of the list. 551dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::vector<PrerenderContents*> prerender_contents; 552dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); 553dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen it != prerender_list_.end(); 554dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ++it) { 555dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen prerender_contents.push_back(it->contents_); 556dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 557dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen for (std::vector<PrerenderContents*>::iterator it = 558dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen prerender_contents.begin(); 559dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen it != prerender_contents.end(); 560dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ++it) { 561dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen (*it)->DestroyWhenUsingTooManyResources(); 562dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 563dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 564dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 565ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PrerenderManager::MarkTabContentsAsPrerendered(TabContents* tc) { 566ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen prerendered_tc_set_.insert(tc); 567ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 568ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 569ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PrerenderManager::MarkTabContentsAsWouldBePrerendered(TabContents* tc) { 570ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen would_be_prerendered_tc_set_.insert(tc); 571ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 572ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 573ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PrerenderManager::MarkTabContentsAsNotPrerendered(TabContents* tc) { 574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen prerendered_tc_set_.erase(tc); 575ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen would_be_prerendered_tc_set_.erase(tc); 576ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 577ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool PrerenderManager::IsTabContentsPrerendered(TabContents* tc) const { 579ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return prerendered_tc_set_.count(tc) > 0; 580ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 581ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 582ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool PrerenderManager::WouldTabContentsBePrerendered(TabContents* tc) const { 583ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return would_be_prerendered_tc_set_.count(tc) > 0; 584ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 585ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 586dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} // namespace prerender 587