| Index: chrome/browser/prerender/prerender_manager.cc
|
| diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
|
| index 2282f21a288c64f61f39568e07796d8d169d78f2..d2f782078ca83776321e3784d930fd60f637282c 100644
|
| --- a/chrome/browser/prerender/prerender_manager.cc
|
| +++ b/chrome/browser/prerender/prerender_manager.cc
|
| @@ -165,14 +165,24 @@ PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ =
|
| PRERENDER_MODE_ENABLED;
|
|
|
| struct PrerenderManager::NavigationRecord {
|
| - GURL url_;
|
| - base::TimeTicks time_;
|
| + GURL url;
|
| + base::TimeTicks time;
|
| +
|
| NavigationRecord(const GURL& url, base::TimeTicks time)
|
| - : url_(url),
|
| - time_(time) {
|
| + : url(url),
|
| + time(time) {
|
| }
|
| };
|
|
|
| +PrerenderManager::PrerenderedWebContentsData::
|
| +PrerenderedWebContentsData(Origin origin) : origin(origin) {
|
| +}
|
| +
|
| +PrerenderManager::WouldBePrerenderedWebContentsData::
|
| +WouldBePrerenderedWebContentsData(Origin origin) : origin(origin),
|
| + state(INITIAL_STATE) {
|
| +}
|
| +
|
| PrerenderManager::PrerenderManager(Profile* profile,
|
| PrerenderTracker* prerender_tracker)
|
| : enabled_(true),
|
| @@ -182,8 +192,7 @@ PrerenderManager::PrerenderManager(Profile* profile,
|
| last_prerender_start_time_(GetCurrentTimeTicks() -
|
| base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs)),
|
| weak_factory_(this),
|
| - prerender_history_(new PrerenderHistory(kHistoryLength)),
|
| - histograms_(new PrerenderHistograms()) {
|
| + prerender_history_(new PrerenderHistory(kHistoryLength)) {
|
| // There are some assumptions that the PrerenderManager is on the UI thread.
|
| // Any other checks simply make sure that the PrerenderManager is accessed on
|
| // the same thread that it was created on.
|
| @@ -200,6 +209,8 @@ PrerenderManager::PrerenderManager(Profile* profile,
|
| default:
|
| break;
|
| }
|
| +
|
| + histograms_.reset(new PrerenderHistograms(config_.time_to_live));
|
| }
|
|
|
| PrerenderManager::~PrerenderManager() {
|
| @@ -232,7 +243,7 @@ PrerenderHandle* PrerenderManager::AddPrerenderFromLinkRelPrerender(
|
| new PrerenderHandle(pending_prerender_list_.back().get());
|
| contents->AddPendingPrerender(
|
| prerender_handle->weak_ptr_factory_.GetWeakPtr(),
|
| - url, referrer, size);
|
| + ORIGIN_LINK_REL_PRERENDER, url, referrer, size);
|
| return prerender_handle;
|
| }
|
| }
|
| @@ -291,7 +302,7 @@ void PrerenderManager::CancelAllPrerenders() {
|
| bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents,
|
| const GURL& url) {
|
| DCHECK(CalledOnValidThread());
|
| - DCHECK(!IsWebContentsPrerendering(web_contents));
|
| + DCHECK(!IsWebContentsPrerendering(web_contents, NULL));
|
|
|
| DeleteOldEntries();
|
| DeletePendingDeleteEntries();
|
| @@ -328,7 +339,8 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents,
|
| // that prerendering hasn't even started yet), record that |web_contents| now
|
| // would be showing a prerendered contents, but otherwise, don't do anything.
|
| if (!prerender_contents->prerendering_has_started()) {
|
| - MarkWebContentsAsWouldBePrerendered(web_contents);
|
| + MarkWebContentsAsWouldBePrerendered(web_contents,
|
| + prerender_contents->origin());
|
| prerender_contents.release()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED);
|
| return false;
|
| }
|
| @@ -353,7 +365,8 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents,
|
| // For bookkeeping purposes, we need to mark this WebContents to
|
| // reflect that it would have been prerendered.
|
| if (GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP) {
|
| - MarkWebContentsAsWouldBePrerendered(web_contents);
|
| + MarkWebContentsAsWouldBePrerendered(web_contents,
|
| + prerender_contents->origin());
|
| prerender_contents.release()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED);
|
| return false;
|
| }
|
| @@ -372,11 +385,13 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents,
|
|
|
| if (!prerender_contents->load_start_time().is_null()) {
|
| histograms_->RecordTimeUntilUsed(
|
| + prerender_contents->origin(),
|
| GetCurrentTimeTicks() - prerender_contents->load_start_time(),
|
| config_.time_to_live);
|
| }
|
|
|
| - histograms_->RecordPerSessionCount(++prerenders_per_session_count_);
|
| + histograms_->RecordPerSessionCount(prerender_contents->origin(),
|
| + ++prerenders_per_session_count_);
|
| histograms_->RecordUsedPrerender(prerender_contents->origin());
|
| prerender_contents->set_final_status(FINAL_STATUS_USED);
|
|
|
| @@ -397,7 +412,8 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents,
|
| DCHECK(new_tab_contents);
|
| DCHECK(old_tab_contents);
|
|
|
| - MarkWebContentsAsPrerendered(new_tab_contents->web_contents());
|
| + MarkWebContentsAsPrerendered(new_tab_contents->web_contents(),
|
| + prerender_contents->origin());
|
|
|
| // Merge the browsing history.
|
| new_tab_contents->web_contents()->GetController().CopyStateFromAndPrune(
|
| @@ -511,18 +527,25 @@ void PrerenderManager::RecordPerceivedPageLoadTime(
|
| return;
|
| if (!prerender_manager->IsEnabled())
|
| return;
|
| + Origin prerender_origin = ORIGIN_NONE;
|
| bool was_prerender =
|
| - prerender_manager->IsWebContentsPrerendered(web_contents);
|
| + prerender_manager->IsWebContentsPrerendered(web_contents,
|
| + &prerender_origin);
|
| bool was_complete_prerender = was_prerender ||
|
| - prerender_manager->WouldWebContentsBePrerendered(web_contents);
|
| - if (prerender_manager->IsWebContentsPrerendering(web_contents)) {
|
| + prerender_manager->WouldWebContentsBePrerendered(web_contents,
|
| + &prerender_origin);
|
| + if (prerender_manager->IsWebContentsPrerendering(web_contents,
|
| + &prerender_origin)) {
|
| prerender_manager->histograms_->RecordPageLoadTimeNotSwappedIn(
|
| - perceived_page_load_time, url);
|
| + prerender_origin, perceived_page_load_time, url);
|
| } else {
|
| prerender_manager->histograms_->RecordPerceivedPageLoadTime(
|
| - perceived_page_load_time, was_prerender, was_complete_prerender, url);
|
| - prerender_manager->histograms_->RecordPercentLoadDoneAtSwapin(
|
| - fraction_plt_elapsed_at_swap_in);
|
| + prerender_origin, perceived_page_load_time, was_prerender,
|
| + was_complete_prerender, url);
|
| + if (was_prerender) {
|
| + prerender_manager->histograms_->RecordPercentLoadDoneAtSwapin(
|
| + prerender_origin, fraction_plt_elapsed_at_swap_in);
|
| + }
|
| if (prerender_manager->local_predictor_.get()) {
|
| prerender_manager->local_predictor_->
|
| OnPLTEventForURL(url, perceived_page_load_time);
|
| @@ -530,6 +553,14 @@ void PrerenderManager::RecordPerceivedPageLoadTime(
|
| }
|
| }
|
|
|
| +void PrerenderManager::RecordFractionPixelsFinalAtSwapin(
|
| + content::WebContents* web_contents,
|
| + double fraction) {
|
| + Origin origin = ORIGIN_NONE;
|
| + IsWebContentsPrerendered(web_contents, &origin);
|
| + histograms_->RecordFractionPixelsFinalAtSwapin(origin, fraction);
|
| +}
|
| +
|
| void PrerenderManager::set_enabled(bool enabled) {
|
| DCHECK(CalledOnValidThread());
|
| enabled_ = enabled;
|
| @@ -600,10 +631,15 @@ bool PrerenderManager::IsNoUseGroup() {
|
| }
|
|
|
| bool PrerenderManager::IsWebContentsPrerendering(
|
| - WebContents* web_contents) const {
|
| + WebContents* web_contents,
|
| + Origin* origin) const {
|
| DCHECK(CalledOnValidThread());
|
| - if (GetPrerenderContents(web_contents))
|
| + if (PrerenderContents* prerender_contents =
|
| + GetPrerenderContents(web_contents)) {
|
| + if (origin)
|
| + *origin = prerender_contents->origin();
|
| return true;
|
| + }
|
|
|
| // Also look through the pending-deletion list.
|
| for (std::list<PrerenderContents*>::const_iterator it =
|
| @@ -613,6 +649,8 @@ bool PrerenderManager::IsWebContentsPrerendering(
|
| TabContents* prerender_tab_contents = (*it)->prerender_contents();
|
| if (prerender_tab_contents &&
|
| prerender_tab_contents->web_contents() == web_contents)
|
| + if (origin)
|
| + *origin = (*it)->origin();
|
| return true;
|
| }
|
|
|
| @@ -636,27 +674,37 @@ PrerenderContents* PrerenderManager::GetPrerenderContents(
|
| return NULL;
|
| }
|
|
|
| -void PrerenderManager::MarkWebContentsAsPrerendered(WebContents* web_contents) {
|
| +void PrerenderManager::MarkWebContentsAsPrerendered(WebContents* web_contents,
|
| + Origin origin) {
|
| DCHECK(CalledOnValidThread());
|
| - prerendered_tab_contents_set_.insert(web_contents);
|
| + prerendered_web_contents_data_.insert(
|
| + base::hash_map<content::WebContents*,
|
| + PrerenderedWebContentsData>::value_type(
|
| + web_contents, PrerenderedWebContentsData(origin)));
|
| }
|
|
|
| void PrerenderManager::MarkWebContentsAsWouldBePrerendered(
|
| - WebContents* web_contents) {
|
| + WebContents* web_contents,
|
| + Origin origin) {
|
| DCHECK(CalledOnValidThread());
|
| - would_be_prerendered_map_[web_contents] = true;
|
| + would_be_prerendered_map_.insert(
|
| + base::hash_map<content::WebContents*,
|
| + WouldBePrerenderedWebContentsData>::value_type(
|
| + web_contents,
|
| + WouldBePrerenderedWebContentsData(origin)));
|
| }
|
|
|
| void PrerenderManager::MarkWebContentsAsNotPrerendered(
|
| WebContents* web_contents) {
|
| DCHECK(CalledOnValidThread());
|
| - prerendered_tab_contents_set_.erase(web_contents);
|
| - WouldBePrerenderedMap::iterator it =
|
| - would_be_prerendered_map_.find(web_contents);
|
| + prerendered_web_contents_data_.erase(web_contents);
|
| + base::hash_map<content::WebContents*, WouldBePrerenderedWebContentsData>::
|
| + iterator it = would_be_prerendered_map_.find(web_contents);
|
| if (it != would_be_prerendered_map_.end()) {
|
| - bool first_time = it->second;
|
| - if (first_time) {
|
| - it->second = false;
|
| + if (it->second.state ==
|
| + WouldBePrerenderedWebContentsData::WAITING_FOR_PROVISIONAL_LOAD) {
|
| + it->second.state =
|
| + WouldBePrerenderedWebContentsData::SEEN_PROVISIONAL_LOAD;
|
| } else {
|
| would_be_prerendered_map_.erase(it);
|
| }
|
| @@ -664,18 +712,33 @@ void PrerenderManager::MarkWebContentsAsNotPrerendered(
|
| }
|
|
|
| bool PrerenderManager::IsWebContentsPrerendered(
|
| - content::WebContents* web_contents) const {
|
| + content::WebContents* web_contents,
|
| + Origin* origin) const {
|
| DCHECK(CalledOnValidThread());
|
| - return prerendered_tab_contents_set_.count(web_contents) > 0;
|
| + base::hash_map<content::WebContents*, PrerenderedWebContentsData>::
|
| + const_iterator it = prerendered_web_contents_data_.find(web_contents);
|
| + if (it == prerendered_web_contents_data_.end())
|
| + return false;
|
| + if (origin)
|
| + *origin = it->second.origin;
|
| + return true;
|
| }
|
|
|
| bool PrerenderManager::WouldWebContentsBePrerendered(
|
| - WebContents* web_contents) const {
|
| + WebContents* web_contents,
|
| + Origin* origin) const {
|
| DCHECK(CalledOnValidThread());
|
| - return would_be_prerendered_map_.count(web_contents) > 0;
|
| + base::hash_map<content::WebContents*, WouldBePrerenderedWebContentsData>::
|
| + const_iterator it = would_be_prerendered_map_.find(web_contents);
|
| + if (it == would_be_prerendered_map_.end())
|
| + return false;
|
| + if (origin)
|
| + *origin = it->second.origin;
|
| + return true;
|
| }
|
|
|
| -bool PrerenderManager::HasRecentlyBeenNavigatedTo(const GURL& url) {
|
| +bool PrerenderManager::HasRecentlyBeenNavigatedTo(Origin origin,
|
| + const GURL& url) {
|
| DCHECK(CalledOnValidThread());
|
|
|
| CleanUpOldNavigations();
|
| @@ -684,9 +747,9 @@ bool PrerenderManager::HasRecentlyBeenNavigatedTo(const GURL& url) {
|
| navigations_.rbegin();
|
| it != end;
|
| ++it) {
|
| - if (it->url_ == url) {
|
| - base::TimeDelta delta = GetCurrentTimeTicks() - it->time_;
|
| - histograms_->RecordTimeSinceLastRecentVisit(delta);
|
| + if (it->url == url) {
|
| + base::TimeDelta delta = GetCurrentTimeTicks() - it->time;
|
| + histograms_->RecordTimeSinceLastRecentVisit(origin, delta);
|
| return true;
|
| }
|
| }
|
| @@ -968,7 +1031,7 @@ PrerenderHandle* PrerenderManager::AddPrerender(
|
| #endif
|
|
|
| // Check if enough time has passed since the last prerender.
|
| - if (!DoesRateLimitAllowPrerender()) {
|
| + if (!DoesRateLimitAllowPrerender(origin)) {
|
| // Cancel the prerender. We could add it to the pending prerender list but
|
| // this doesn't make sense as the next prerender request will be triggered
|
| // by a navigation and is unlikely to be the same site.
|
| @@ -1171,11 +1234,11 @@ PrerenderManager::FindIteratorForPrerenderContents(
|
| return active_prerender_list_.end();
|
| }
|
|
|
| -bool PrerenderManager::DoesRateLimitAllowPrerender() const {
|
| +bool PrerenderManager::DoesRateLimitAllowPrerender(Origin origin) const {
|
| DCHECK(CalledOnValidThread());
|
| base::TimeDelta elapsed_time =
|
| GetCurrentTimeTicks() - last_prerender_start_time_;
|
| - histograms_->RecordTimeBetweenPrerenderRequests(elapsed_time);
|
| + histograms_->RecordTimeBetweenPrerenderRequests(origin, elapsed_time);
|
| if (!config_.rate_limit_enabled)
|
| return true;
|
| return elapsed_time >
|
| @@ -1198,7 +1261,7 @@ void PrerenderManager::CleanUpOldNavigations() {
|
| base::TimeTicks cutoff = GetCurrentTimeTicks() -
|
| base::TimeDelta::FromMilliseconds(kNavigationRecordWindowMs);
|
| while (!navigations_.empty()) {
|
| - if (navigations_.front().time_ > cutoff)
|
| + if (navigations_.front().time > cutoff)
|
| break;
|
| navigations_.pop_front();
|
| }
|
|
|