diff options
author | dominich@google.com <dominich@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-30 20:23:21 +0000 |
---|---|---|
committer | dominich@google.com <dominich@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-30 20:23:21 +0000 |
commit | 39bfdde0bb531c8f66fa9fc5147868162e411977 (patch) | |
tree | 8ee935f239ad240953eaaab8d978f88d02f21deb /chrome/browser | |
parent | 5e316190da50feaf1a24a8fc7e75ccf16cf42072 (diff) | |
download | chromium_src-39bfdde0bb531c8f66fa9fc5147868162e411977.zip chromium_src-39bfdde0bb531c8f66fa9fc5147868162e411977.tar.gz chromium_src-39bfdde0bb531c8f66fa9fc5147868162e411977.tar.bz2 |
Revert 119699 - Cancel prerenders from Omnibox if we navigate to a different URL than predicted.
I also took the opportunity to align the order of methods in prerender_manager.cc to that of the header (as it should be) and make a couple of methods const.
BUG=110799,111350
Review URL: http://codereview.chromium.org/9226037
TBR=dominich@chromium.org
Review URL: https://chromiumcodereview.appspot.com/9301012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@119720 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/autocomplete/network_action_predictor.cc | 12 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_manager.cc | 844 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_manager.h | 29 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_manager_unittest.cc | 74 |
4 files changed, 437 insertions, 522 deletions
diff --git a/chrome/browser/autocomplete/network_action_predictor.cc b/chrome/browser/autocomplete/network_action_predictor.cc index 11bf630..b43ee3c 100644 --- a/chrome/browser/autocomplete/network_action_predictor.cc +++ b/chrome/browser/autocomplete/network_action_predictor.cc @@ -20,8 +20,6 @@ #include "chrome/browser/history/history_notifications.h" #include "chrome/browser/history/in_memory_database.h" #include "chrome/browser/prerender/prerender_field_trial.h" -#include "chrome/browser/prerender/prerender_manager.h" -#include "chrome/browser/prerender/prerender_manager_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/guid.h" @@ -237,15 +235,6 @@ void NetworkActionPredictor::OnOmniboxOpenedUrl(const AutocompleteLog& log) { const GURL& opened_url = match.destination_url; - // If the Omnibox triggered a prerender but the URL doesn't match the one the - // user is navigating to, cancel the prerender. - prerender::PrerenderManager* prerender_manager = - prerender::PrerenderManagerFactory::GetForProfile(profile_); - // |prerender_manager| can be NULL in incognito mode or if prerendering is - // otherwise disabled. - if (prerender_manager && !prerender_manager->IsPrerendering(opened_url)) - prerender_manager->CancelOmniboxPrerenders(); - const string16 lower_user_text(base::i18n::ToLower(log.text)); BeginTransaction(); @@ -302,6 +291,7 @@ void NetworkActionPredictor::OnOmniboxOpenedUrl(const AutocompleteLog& log) { tracked_urls_.clear(); } + void NetworkActionPredictor::DeleteOldIdsFromCaches( history::URLDatabase* url_db, std::vector<NetworkActionPredictorDatabase::Row::Id>* id_list) { diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc index 0659eb7..63acab2 100644 --- a/chrome/browser/prerender/prerender_manager.cc +++ b/chrome/browser/prerender/prerender_manager.cc @@ -167,6 +167,52 @@ int PrerenderManager::prerenders_per_session_count_ = 0; PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = PRERENDER_MODE_ENABLED; +// static +PrerenderManager::PrerenderManagerMode PrerenderManager::GetMode() { + return mode_; +} + +// static +void PrerenderManager::SetMode(PrerenderManagerMode mode) { + mode_ = mode; +} + +// static +bool PrerenderManager::IsPrerenderingPossible() { + return GetMode() == PRERENDER_MODE_ENABLED || + GetMode() == PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP || + GetMode() == PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP || + GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP; +} + +// static +bool PrerenderManager::ActuallyPrerendering() { + return IsPrerenderingPossible() && !IsControlGroup(); +} + +// static +bool PrerenderManager::IsControlGroup() { + return GetMode() == PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP; +} + +// static +bool PrerenderManager::IsNoUseGroup() { + return GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP; +} + +// static +bool PrerenderManager::IsValidHttpMethod(const std::string& method) { + // method has been canonicalized to upper case at this point so we can just + // compare them. + DCHECK_EQ(method, StringToUpperASCII(method)); + for (size_t i = 0; i < arraysize(kValidHttpMethods); ++i) { + if (method.compare(kValidHttpMethods[i]) == 0) + return true; + } + + return false; +} + struct PrerenderManager::PrerenderContentsData { PrerenderContents* contents_; base::Time start_time_; @@ -240,6 +286,24 @@ class PrerenderManager::MostVisitedSites std::set<GURL> urls_; }; +bool PrerenderManager::IsTopSite(const GURL& url) { + if (!most_visited_.get()) + most_visited_.reset(new MostVisitedSites(profile_)); + return most_visited_->IsTopSite(url); +} + +bool PrerenderManager::IsPendingEntry(const GURL& url) const { + DCHECK(CalledOnValidThread()); + for (std::list<PrerenderContentsData>::const_iterator it = + prerender_list_.begin(); + it != prerender_list_.end(); + ++it) { + if (it->contents_->IsPendingEntry(url)) + return true; + } + return false; +} + PrerenderManager::PrerenderManager(Profile* profile, PrerenderTracker* prerender_tracker) : enabled_(true), @@ -264,6 +328,12 @@ void PrerenderManager::Shutdown() { DoShutdown(); } +void PrerenderManager::SetPrerenderContentsFactory( + PrerenderContents::Factory* prerender_contents_factory) { + DCHECK(CalledOnValidThread()); + prerender_contents_factory_.reset(prerender_contents_factory); +} + bool PrerenderManager::AddPrerenderFromLinkRelPrerender( int process_id, int route_id, @@ -279,16 +349,148 @@ bool PrerenderManager::AddPrerenderFromLinkRelPrerender( bool PrerenderManager::AddPrerenderFromOmnibox( const GURL& url, SessionStorageNamespace* session_storage_namespace) { + DCHECK(session_storage_namespace); if (!IsOmniboxEnabled(profile_)) return false; return AddPrerender(ORIGIN_OMNIBOX, std::make_pair(-1, -1), url, content::Referrer(), session_storage_namespace); } +bool PrerenderManager::AddPrerender( + Origin origin, + const std::pair<int, int>& child_route_id_pair, + const GURL& url_arg, + const content::Referrer& referrer, + SessionStorageNamespace* session_storage_namespace) { + DCHECK(CalledOnValidThread()); + + if (origin == ORIGIN_LINK_REL_PRERENDER && + IsGoogleSearchResultURL(referrer.url)) { + origin = ORIGIN_GWS_PRERENDER; + } + + // If the referring page is prerendering, defer the prerender. + std::list<PrerenderContentsData>::iterator source_prerender = + FindPrerenderContentsForChildRouteIdPair(child_route_id_pair); + if (source_prerender != prerender_list_.end()) { + source_prerender->contents_->AddPendingPrerender( + origin, url_arg, referrer); + return true; + } + + DeleteOldEntries(); + DeletePendingDeleteEntries(); + + GURL url = url_arg; + GURL alias_url; + if (IsControlGroup() && MaybeGetQueryStringBasedAliasURL(url, &alias_url)) + url = alias_url; + + // From here on, we will record a FinalStatus so we need to register with the + // histogram tracking. + histograms_->RecordPrerender(origin, url_arg); + + uint8 experiment = GetQueryStringBasedExperiment(url_arg); + + if (FindEntry(url)) { + RecordFinalStatus(origin, experiment, FINAL_STATUS_DUPLICATE); + return false; + } + + // Do not prerender if there are too many render processes, and we would + // have to use an existing one. We do not want prerendering to happen in + // a shared process, so that we can always reliably lower the CPU + // priority for prerendering. + // In single-process mode, ShouldTryToUseExistingProcessHost() always returns + // true, so that case needs to be explicitly checked for. + // TODO(tburkard): Figure out how to cancel prerendering in the opposite + // case, when a new tab is added to a process used for prerendering. + if (content::RenderProcessHost::ShouldTryToUseExistingProcessHost() && + !content::RenderProcessHost::run_renderer_in_process()) { + RecordFinalStatus(origin, experiment, FINAL_STATUS_TOO_MANY_PROCESSES); + return false; + } + + // Check if enough time has passed since the last prerender. + if (!DoesRateLimitAllowPrerender()) { + // 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. + RecordFinalStatus(origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED); + return false; + } + + RenderViewHost* source_render_view_host = NULL; + if (child_route_id_pair.first != -1) { + source_render_view_host = + RenderViewHost::FromID(child_route_id_pair.first, + child_route_id_pair.second); + // Don't prerender page if parent RenderViewHost no longer exists, or it has + // no view. The latter should only happen when the RenderView has closed. + if (!source_render_view_host || !source_render_view_host->view()) { + RecordFinalStatus(origin, experiment, + FINAL_STATUS_SOURCE_RENDER_VIEW_CLOSED); + return false; + } + } + + if (!session_storage_namespace && source_render_view_host) { + session_storage_namespace = + source_render_view_host->session_storage_namespace(); + } + + PrerenderContents* prerender_contents = CreatePrerenderContents( + url, referrer, origin, experiment); + if (!prerender_contents || !prerender_contents->Init()) + return false; + + histograms_->RecordPrerenderStarted(origin); + + // TODO(cbentzel): Move invalid checks here instead of PrerenderContents? + PrerenderContentsData data(prerender_contents, GetCurrentTime()); + + prerender_list_.push_back(data); + + if (!IsControlGroup()) { + last_prerender_start_time_ = GetCurrentTimeTicks(); + data.contents_->StartPrerendering(source_render_view_host, + session_storage_namespace); + } + while (prerender_list_.size() > config_.max_elements) { + data = prerender_list_.front(); + prerender_list_.pop_front(); + data.contents_->Destroy(FINAL_STATUS_EVICTED); + } + StartSchedulingPeriodicCleanups(); + return true; +} + +std::list<PrerenderManager::PrerenderContentsData>::iterator + PrerenderManager::FindPrerenderContentsForChildRouteIdPair( + const std::pair<int, int>& child_route_id_pair) { + std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); + for (; it != prerender_list_.end(); ++it) { + PrerenderContents* prerender_contents = it->contents_; + + int child_id; + int route_id; + bool has_child_id = prerender_contents->GetChildId(&child_id); + bool has_route_id = has_child_id && + prerender_contents->GetRouteId(&route_id); + + if (has_child_id && has_route_id && + child_id == child_route_id_pair.first && + route_id == child_route_id_pair.second) { + break; + } + } + return it; +} + void PrerenderManager::DestroyPrerenderForRenderView( int process_id, int view_id, FinalStatus final_status) { DCHECK(CalledOnValidThread()); - PrerenderContentsDataList::iterator it = + std::list<PrerenderContentsData>::iterator it = FindPrerenderContentsForChildRouteIdPair( std::make_pair(process_id, view_id)); if (it != prerender_list_.end()) { @@ -306,14 +508,54 @@ void PrerenderManager::CancelAllPrerenders() { } } -void PrerenderManager::CancelOmniboxPrerenders() { +void PrerenderManager::DeleteOldEntries() { + DCHECK(CalledOnValidThread()); + while (!prerender_list_.empty()) { + PrerenderContentsData data = prerender_list_.front(); + if (IsPrerenderElementFresh(data.start_time_)) + return; + data.contents_->Destroy(FINAL_STATUS_TIMED_OUT); + } + MaybeStopSchedulingPeriodicCleanups(); +} + +PrerenderContents* PrerenderManager::GetEntryButNotSpecifiedWC( + const GURL& url, + WebContents* wc) { DCHECK(CalledOnValidThread()); - for (PrerenderContentsDataList::iterator it = prerender_list_.begin(); - it != prerender_list_.end(); ) { - PrerenderContentsDataList::iterator cur = it++; - if (cur->contents_->origin() == ORIGIN_OMNIBOX) - cur->contents_->Destroy(FINAL_STATUS_CANCELLED); + DeleteOldEntries(); + DeletePendingDeleteEntries(); + for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); + it != prerender_list_.end(); + ++it) { + PrerenderContents* prerender_contents = it->contents_; + if (prerender_contents->MatchesURL(url, NULL)) { + if (!prerender_contents->prerender_contents() || + !wc || + prerender_contents->prerender_contents()->web_contents() != wc) { + prerender_list_.erase(it); + return prerender_contents; + } + } } + // Entry not found. + return NULL; +} + +PrerenderContents* PrerenderManager::GetEntry(const GURL& url) { + return GetEntryButNotSpecifiedWC(url, NULL); +} + +void PrerenderManager::DestroyAndMarkMatchCompleteAsUsed( + PrerenderContents* prerender_contents, + FinalStatus final_status) { + prerender_contents->set_match_complete_status( + PrerenderContents::MATCH_COMPLETE_REPLACED); + histograms_->RecordFinalStatus(prerender_contents->origin(), + prerender_contents->experiment_id(), + PrerenderContents::MATCH_COMPLETE_REPLACEMENT, + FINAL_STATUS_WOULD_HAVE_BEEN_USED); + prerender_contents->Destroy(final_status); } bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, @@ -480,7 +722,7 @@ void PrerenderManager::MoveEntryToPendingDelete(PrerenderContents* entry, DCHECK(entry); DCHECK(!IsPendingDelete(entry)); - for (PrerenderContentsDataList::iterator it = prerender_list_.begin(); + for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); it != prerender_list_.end(); ++it) { if (it->contents_ == entry) { @@ -532,6 +774,52 @@ void PrerenderManager::MoveEntryToPendingDelete(PrerenderContents* entry, PostCleanupTask(); } +base::Time PrerenderManager::GetCurrentTime() const { + return base::Time::Now(); +} + +base::TimeTicks PrerenderManager::GetCurrentTimeTicks() const { + return base::TimeTicks::Now(); +} + +bool PrerenderManager::IsPrerenderElementFresh(const base::Time start) const { + DCHECK(CalledOnValidThread()); + base::Time now = GetCurrentTime(); + return (now - start < config_.max_age); +} + +PrerenderContents* PrerenderManager::CreatePrerenderContents( + const GURL& url, + const content::Referrer& referrer, + Origin origin, + uint8 experiment_id) { + DCHECK(CalledOnValidThread()); + return prerender_contents_factory_->CreatePrerenderContents( + this, prerender_tracker_, profile_, url, + referrer, origin, experiment_id); +} + +bool PrerenderManager::IsPendingDelete(PrerenderContents* entry) const { + DCHECK(CalledOnValidThread()); + for (std::list<PrerenderContents*>::const_iterator it = + pending_delete_list_.begin(); + it != pending_delete_list_.end(); + ++it) { + if (*it == entry) + return true; + } + + return false; +} + +void PrerenderManager::DeletePendingDeleteEntries() { + while (!pending_delete_list_.empty()) { + PrerenderContents* contents = pending_delete_list_.front(); + pending_delete_list_.pop_front(); + delete contents; + } +} + // static void PrerenderManager::RecordPerceivedPageLoadTime( base::TimeDelta perceived_page_load_time, @@ -573,204 +861,20 @@ void PrerenderManager::set_enabled(bool enabled) { enabled_ = enabled; } -// static -PrerenderManager::PrerenderManagerMode PrerenderManager::GetMode() { - return mode_; -} - -// static -void PrerenderManager::SetMode(PrerenderManagerMode mode) { - mode_ = mode; -} - -// static -bool PrerenderManager::IsPrerenderingPossible() { - return GetMode() == PRERENDER_MODE_ENABLED || - GetMode() == PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP || - GetMode() == PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP || - GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP; -} - -// static -bool PrerenderManager::ActuallyPrerendering() { - return IsPrerenderingPossible() && !IsControlGroup(); -} - -// static -bool PrerenderManager::IsControlGroup() { - return GetMode() == PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP; -} - -// static -bool PrerenderManager::IsNoUseGroup() { - return GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP; -} - -bool PrerenderManager::IsWebContentsPrerendering( - WebContents* web_contents) const { - DCHECK(CalledOnValidThread()); - for (PrerenderContentsDataList::const_iterator it = prerender_list_.begin(); - it != prerender_list_.end(); - ++it) { - TabContentsWrapper* prerender_tab_contents_wrapper = - it->contents_->prerender_contents(); - if (prerender_tab_contents_wrapper && - prerender_tab_contents_wrapper->web_contents() == web_contents) { - return true; - } - } - - // Also look through the pending-deletion list. - for (std::list<PrerenderContents*>::const_iterator it = - pending_delete_list_.begin(); - it != pending_delete_list_.end(); - ++it) { - TabContentsWrapper* prerender_tab_contents_wrapper = - (*it)->prerender_contents(); - if (prerender_tab_contents_wrapper && - prerender_tab_contents_wrapper->web_contents() == web_contents) - return true; - } - - return false; -} - -void PrerenderManager::MarkWebContentsAsPrerendered(WebContents* web_contents) { - DCHECK(CalledOnValidThread()); - prerendered_tab_contents_set_.insert(web_contents); -} - -void PrerenderManager::MarkWebContentsAsWouldBePrerendered( - WebContents* web_contents) { - DCHECK(CalledOnValidThread()); - would_be_prerendered_tab_contents_set_.insert(web_contents); -} - -void PrerenderManager::MarkWebContentsAsNotPrerendered( - WebContents* web_contents) { - DCHECK(CalledOnValidThread()); - prerendered_tab_contents_set_.erase(web_contents); - would_be_prerendered_tab_contents_set_.erase(web_contents); -} - -bool PrerenderManager::IsWebContentsPrerendered( - content::WebContents* web_contents) const { - DCHECK(CalledOnValidThread()); - return prerendered_tab_contents_set_.count(web_contents) > 0; -} - -bool PrerenderManager::WouldWebContentsBePrerendered( - WebContents* web_contents) const { - DCHECK(CalledOnValidThread()); - return would_be_prerendered_tab_contents_set_.count(web_contents) > 0; -} - -bool PrerenderManager::IsOldRenderViewHost( - const RenderViewHost* render_view_host) const { - for (std::list<TabContentsWrapper*>::const_iterator it = - old_tab_contents_list_.begin(); - it != old_tab_contents_list_.end(); - ++it) { - if ((*it)->web_contents()->GetRenderViewHost() == render_view_host) - return true; - } - return false; -} - -bool PrerenderManager::HasRecentlyBeenNavigatedTo(const GURL& url) { - DCHECK(CalledOnValidThread()); - - CleanUpOldNavigations(); - for (std::list<NavigationRecord>::const_iterator it = navigations_.begin(); - it != navigations_.end(); - ++it) { - if (it->url_ == url) - return true; - } - - return false; -} - -// static -bool PrerenderManager::IsValidHttpMethod(const std::string& method) { - // method has been canonicalized to upper case at this point so we can just - // compare them. - DCHECK_EQ(method, StringToUpperASCII(method)); - for (size_t i = 0; i < arraysize(kValidHttpMethods); ++i) { - if (method.compare(kValidHttpMethods[i]) == 0) - return true; - } - - return false; -} - -DictionaryValue* PrerenderManager::GetAsValue() const { - DCHECK(CalledOnValidThread()); - DictionaryValue* dict_value = new DictionaryValue(); - dict_value->Set("history", prerender_history_->GetEntriesAsValue()); - dict_value->Set("active", GetActivePrerendersAsValue()); - dict_value->SetBoolean("enabled", enabled_); - dict_value->SetBoolean("omnibox_enabled", IsOmniboxEnabled(profile_)); - // If prerender is disabled via a flag this method is not even called. - if (IsControlGroup()) - dict_value->SetString("disabled_reason", "(Disabled for testing)"); - if (IsNoUseGroup()) - dict_value->SetString("disabled_reason", "(Not using prerendered pages)"); - return dict_value; -} - -void PrerenderManager::ClearData(int clear_flags) { - DCHECK_GE(clear_flags, 0); - DCHECK_LT(clear_flags, CLEAR_MAX); - if (clear_flags & CLEAR_PRERENDER_CONTENTS) - DestroyAllContents(FINAL_STATUS_CACHE_OR_HISTORY_CLEARED); - // This has to be second, since destroying prerenders can add to the history. - if (clear_flags & CLEAR_PRERENDER_HISTORY) - prerender_history_->Clear(); -} - -void PrerenderManager::RecordFinalStatusWithMatchCompleteStatus( - Origin origin, - uint8 experiment_id, - PrerenderContents::MatchCompleteStatus mc_status, - FinalStatus final_status) const { - histograms_->RecordFinalStatus(origin, - experiment_id, - mc_status, - final_status); -} - void PrerenderManager::AddCondition(const PrerenderCondition* condition) { prerender_conditions_.push_back(condition); } -bool PrerenderManager::IsTopSite(const GURL& url) { - if (!most_visited_.get()) - most_visited_.reset(new MostVisitedSites(profile_)); - return most_visited_->IsTopSite(url); -} - -bool PrerenderManager::IsPendingEntry(const GURL& url) const { +PrerenderContents* PrerenderManager::FindEntry(const GURL& url) { DCHECK(CalledOnValidThread()); - for (PrerenderContentsDataList::const_iterator it = prerender_list_.begin(); + for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); it != prerender_list_.end(); ++it) { - if (it->contents_->IsPendingEntry(url)) - return true; + if (it->contents_->MatchesURL(url, NULL)) + return it->contents_; } - return false; -} - -bool PrerenderManager::IsPrerendering(const GURL& url) const { - DCHECK(CalledOnValidThread()); - return (FindEntry(url) != NULL); -} - -// protected -void PrerenderManager::SetPrerenderContentsFactory( - PrerenderContents::Factory* prerender_contents_factory) { - DCHECK(CalledOnValidThread()); - prerender_contents_factory_.reset(prerender_contents_factory); + // Entry not found. + return NULL; } void PrerenderManager::DoShutdown() { @@ -779,141 +883,15 @@ void PrerenderManager::DoShutdown() { profile_ = NULL; } -// private -bool PrerenderManager::AddPrerender( - Origin origin, - const std::pair<int, int>& child_route_id_pair, - const GURL& url_arg, - const content::Referrer& referrer, - SessionStorageNamespace* session_storage_namespace) { +bool PrerenderManager::DoesRateLimitAllowPrerender() const { DCHECK(CalledOnValidThread()); - - if (origin == ORIGIN_LINK_REL_PRERENDER && - IsGoogleSearchResultURL(referrer.url)) { - origin = ORIGIN_GWS_PRERENDER; - } - - // If the referring page is prerendering, defer the prerender. - PrerenderContentsDataList::iterator source_prerender = - FindPrerenderContentsForChildRouteIdPair(child_route_id_pair); - if (source_prerender != prerender_list_.end()) { - source_prerender->contents_->AddPendingPrerender( - origin, url_arg, referrer); + base::TimeDelta elapsed_time = + GetCurrentTimeTicks() - last_prerender_start_time_; + histograms_->RecordTimeBetweenPrerenderRequests(elapsed_time); + if (!config_.rate_limit_enabled) return true; - } - - DeleteOldEntries(); - DeletePendingDeleteEntries(); - - GURL url = url_arg; - GURL alias_url; - if (IsControlGroup() && MaybeGetQueryStringBasedAliasURL(url, &alias_url)) - url = alias_url; - - // From here on, we will record a FinalStatus so we need to register with the - // histogram tracking. - histograms_->RecordPrerender(origin, url_arg); - - uint8 experiment = GetQueryStringBasedExperiment(url_arg); - - if (FindEntry(url)) { - RecordFinalStatus(origin, experiment, FINAL_STATUS_DUPLICATE); - return false; - } - - // Do not prerender if there are too many render processes, and we would - // have to use an existing one. We do not want prerendering to happen in - // a shared process, so that we can always reliably lower the CPU - // priority for prerendering. - // In single-process mode, ShouldTryToUseExistingProcessHost() always returns - // true, so that case needs to be explicitly checked for. - // TODO(tburkard): Figure out how to cancel prerendering in the opposite - // case, when a new tab is added to a process used for prerendering. - if (content::RenderProcessHost::ShouldTryToUseExistingProcessHost() && - !content::RenderProcessHost::run_renderer_in_process()) { - RecordFinalStatus(origin, experiment, FINAL_STATUS_TOO_MANY_PROCESSES); - return false; - } - - // Check if enough time has passed since the last prerender. - if (!DoesRateLimitAllowPrerender()) { - // 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. - RecordFinalStatus(origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED); - return false; - } - - RenderViewHost* source_render_view_host = NULL; - if (child_route_id_pair.first != -1) { - source_render_view_host = - RenderViewHost::FromID(child_route_id_pair.first, - child_route_id_pair.second); - // Don't prerender page if parent RenderViewHost no longer exists, or it has - // no view. The latter should only happen when the RenderView has closed. - if (!source_render_view_host || !source_render_view_host->view()) { - RecordFinalStatus(origin, experiment, - FINAL_STATUS_SOURCE_RENDER_VIEW_CLOSED); - return false; - } - } - - if (!session_storage_namespace && source_render_view_host) { - session_storage_namespace = - source_render_view_host->session_storage_namespace(); - } - - PrerenderContents* prerender_contents = CreatePrerenderContents( - url, referrer, origin, experiment); - if (!prerender_contents || !prerender_contents->Init()) - return false; - - histograms_->RecordPrerenderStarted(origin); - - // TODO(cbentzel): Move invalid checks here instead of PrerenderContents? - PrerenderContentsData data(prerender_contents, GetCurrentTime()); - - prerender_list_.push_back(data); - - if (!IsControlGroup()) { - last_prerender_start_time_ = GetCurrentTimeTicks(); - data.contents_->StartPrerendering(source_render_view_host, - session_storage_namespace); - } - while (prerender_list_.size() > config_.max_elements) { - data = prerender_list_.front(); - prerender_list_.pop_front(); - data.contents_->Destroy(FINAL_STATUS_EVICTED); - } - StartSchedulingPeriodicCleanups(); - return true; -} - -PrerenderContents* PrerenderManager::GetEntry(const GURL& url) { - return GetEntryButNotSpecifiedWC(url, NULL); -} - -PrerenderContents* PrerenderManager::GetEntryButNotSpecifiedWC( - const GURL& url, - WebContents* wc) { - DCHECK(CalledOnValidThread()); - DeleteOldEntries(); - DeletePendingDeleteEntries(); - for (PrerenderContentsDataList::iterator it = prerender_list_.begin(); - it != prerender_list_.end(); - ++it) { - PrerenderContents* prerender_contents = it->contents_; - if (prerender_contents->MatchesURL(url, NULL)) { - if (!prerender_contents->prerender_contents() || - !wc || - prerender_contents->prerender_contents()->web_contents() != wc) { - prerender_list_.erase(it); - return prerender_contents; - } - } - } - // Entry not found. - return NULL; + return elapsed_time > + base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs); } void PrerenderManager::StartSchedulingPeriodicCleanups() { @@ -934,6 +912,27 @@ void PrerenderManager::MaybeStopSchedulingPeriodicCleanups() { repeating_timer_.Stop(); } +void PrerenderManager::DeleteOldTabContents() { + while (!old_tab_contents_list_.empty()) { + TabContentsWrapper* tab_contents = old_tab_contents_list_.front(); + old_tab_contents_list_.pop_front(); + // TODO(dominich): should we use Instant Unload Handler here? + delete tab_contents; + } +} + +bool PrerenderManager::IsOldRenderViewHost( + const RenderViewHost* render_view_host) const { + for (std::list<TabContentsWrapper*>::const_iterator it = + old_tab_contents_list_.begin(); + it != old_tab_contents_list_.end(); + ++it) { + if ((*it)->web_contents()->GetRenderViewHost() == render_view_host) + return true; + } + return false; +} + void PrerenderManager::PeriodicCleanup() { DCHECK(CalledOnValidThread()); DeleteOldTabContents(); @@ -942,7 +941,7 @@ void PrerenderManager::PeriodicCleanup() { // Grab a copy of the current PrerenderContents pointers, so that we // will not interfere with potential deletions of the list. std::vector<PrerenderContents*> prerender_contents; - for (PrerenderContentsDataList::iterator it = prerender_list_.begin(); + for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); it != prerender_list_.end(); ++it) { DCHECK(it->contents_); @@ -966,115 +965,78 @@ void PrerenderManager::PostCleanupTask() { weak_factory_.GetWeakPtr())); } -bool PrerenderManager::IsPrerenderElementFresh(const base::Time start) const { - DCHECK(CalledOnValidThread()); - base::Time now = GetCurrentTime(); - return (now - start < config_.max_age); -} - -void PrerenderManager::DeleteOldEntries() { +bool PrerenderManager::IsWebContentsPrerendering( + WebContents* web_contents) const { DCHECK(CalledOnValidThread()); - while (!prerender_list_.empty()) { - PrerenderContentsData data = prerender_list_.front(); - if (IsPrerenderElementFresh(data.start_time_)) - return; - data.contents_->Destroy(FINAL_STATUS_TIMED_OUT); + for (std::list<PrerenderContentsData>::const_iterator it = + prerender_list_.begin(); + it != prerender_list_.end(); + ++it) { + TabContentsWrapper* prerender_tab_contents_wrapper = + it->contents_->prerender_contents(); + if (prerender_tab_contents_wrapper && + prerender_tab_contents_wrapper->web_contents() == web_contents) { + return true; + } } - MaybeStopSchedulingPeriodicCleanups(); -} -base::Time PrerenderManager::GetCurrentTime() const { - return base::Time::Now(); -} - -base::TimeTicks PrerenderManager::GetCurrentTimeTicks() const { - return base::TimeTicks::Now(); -} - -PrerenderContents* PrerenderManager::CreatePrerenderContents( - const GURL& url, - const content::Referrer& referrer, - Origin origin, - uint8 experiment_id) { - DCHECK(CalledOnValidThread()); - return prerender_contents_factory_->CreatePrerenderContents( - this, prerender_tracker_, profile_, url, - referrer, origin, experiment_id); -} - -bool PrerenderManager::IsPendingDelete(PrerenderContents* entry) const { - DCHECK(CalledOnValidThread()); + // Also look through the pending-deletion list. for (std::list<PrerenderContents*>::const_iterator it = - pending_delete_list_.begin(); + pending_delete_list_.begin(); it != pending_delete_list_.end(); ++it) { - if (*it == entry) + TabContentsWrapper* prerender_tab_contents_wrapper = + (*it)->prerender_contents(); + if (prerender_tab_contents_wrapper && + prerender_tab_contents_wrapper->web_contents() == web_contents) return true; } return false; } -void PrerenderManager::DeletePendingDeleteEntries() { - while (!pending_delete_list_.empty()) { - PrerenderContents* contents = pending_delete_list_.front(); - pending_delete_list_.pop_front(); - delete contents; - } +void PrerenderManager::MarkWebContentsAsPrerendered(WebContents* web_contents) { + DCHECK(CalledOnValidThread()); + prerendered_tab_contents_set_.insert(web_contents); } -PrerenderContents* PrerenderManager::FindEntry(const GURL& url) const { +void PrerenderManager::MarkWebContentsAsWouldBePrerendered( + WebContents* web_contents) { DCHECK(CalledOnValidThread()); - for (PrerenderContentsDataList::const_iterator it = prerender_list_.begin(); - it != prerender_list_.end(); - ++it) { - if (it->contents_->MatchesURL(url, NULL)) - return it->contents_; - } - // Entry not found. - return NULL; + would_be_prerendered_tab_contents_set_.insert(web_contents); } -std::list<PrerenderManager::PrerenderContentsData>::iterator - PrerenderManager::FindPrerenderContentsForChildRouteIdPair( - const std::pair<int, int>& child_route_id_pair) { - PrerenderContentsDataList::iterator it = prerender_list_.begin(); - for (; it != prerender_list_.end(); ++it) { - PrerenderContents* prerender_contents = it->contents_; - - int child_id; - int route_id; - bool has_child_id = prerender_contents->GetChildId(&child_id); - bool has_route_id = has_child_id && - prerender_contents->GetRouteId(&route_id); +void PrerenderManager::MarkWebContentsAsNotPrerendered( + WebContents* web_contents) { + DCHECK(CalledOnValidThread()); + prerendered_tab_contents_set_.erase(web_contents); + would_be_prerendered_tab_contents_set_.erase(web_contents); +} - if (has_child_id && has_route_id && - child_id == child_route_id_pair.first && - route_id == child_route_id_pair.second) { - break; - } - } - return it; +bool PrerenderManager::IsWebContentsPrerendered( + content::WebContents* web_contents) const { + DCHECK(CalledOnValidThread()); + return prerendered_tab_contents_set_.count(web_contents) > 0; } -bool PrerenderManager::DoesRateLimitAllowPrerender() const { +bool PrerenderManager::WouldWebContentsBePrerendered( + WebContents* web_contents) const { DCHECK(CalledOnValidThread()); - base::TimeDelta elapsed_time = - GetCurrentTimeTicks() - last_prerender_start_time_; - histograms_->RecordTimeBetweenPrerenderRequests(elapsed_time); - if (!config_.rate_limit_enabled) - return true; - return elapsed_time > - base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs); + return would_be_prerendered_tab_contents_set_.count(web_contents) > 0; } -void PrerenderManager::DeleteOldTabContents() { - while (!old_tab_contents_list_.empty()) { - TabContentsWrapper* tab_contents = old_tab_contents_list_.front(); - old_tab_contents_list_.pop_front(); - // TODO(dominich): should we use Instant Unload Handler here? - delete tab_contents; +bool PrerenderManager::HasRecentlyBeenNavigatedTo(const GURL& url) { + DCHECK(CalledOnValidThread()); + + CleanUpOldNavigations(); + for (std::list<NavigationRecord>::const_iterator it = navigations_.begin(); + it != navigations_.end(); + ++it) { + if (it->url_ == url) + return true; } + + return false; } void PrerenderManager::CleanUpOldNavigations() { @@ -1106,6 +1068,31 @@ void PrerenderManager::ScheduleDeleteOldTabContents( } } +DictionaryValue* PrerenderManager::GetAsValue() const { + DCHECK(CalledOnValidThread()); + DictionaryValue* dict_value = new DictionaryValue(); + dict_value->Set("history", prerender_history_->GetEntriesAsValue()); + dict_value->Set("active", GetActivePrerendersAsValue()); + dict_value->SetBoolean("enabled", enabled_); + dict_value->SetBoolean("omnibox_enabled", IsOmniboxEnabled(profile_)); + // If prerender is disabled via a flag this method is not even called. + if (IsControlGroup()) + dict_value->SetString("disabled_reason", "(Disabled for testing)"); + if (IsNoUseGroup()) + dict_value->SetString("disabled_reason", "(Not using prerendered pages)"); + return dict_value; +} + +void PrerenderManager::ClearData(int clear_flags) { + DCHECK_GE(clear_flags, 0); + DCHECK_LT(clear_flags, CLEAR_MAX); + if (clear_flags & CLEAR_PRERENDER_CONTENTS) + DestroyAllContents(FINAL_STATUS_CACHE_OR_HISTORY_CLEARED); + // This has to be second, since destroying prerenders can add to the history. + if (clear_flags & CLEAR_PRERENDER_HISTORY) + prerender_history_->Clear(); +} + void PrerenderManager::AddToHistory(PrerenderContents* contents) { PrerenderHistory::Entry entry(contents->prerender_url(), contents->final_status(), @@ -1123,7 +1110,8 @@ void PrerenderManager::RecordNavigation(const GURL& url) { Value* PrerenderManager::GetActivePrerendersAsValue() const { ListValue* list_value = new ListValue(); - for (PrerenderContentsDataList::const_iterator it = prerender_list_.begin(); + for (std::list<PrerenderContentsData>::const_iterator it = + prerender_list_.begin(); it != prerender_list_.end(); ++it) { Value* prerender_value = it->contents_->GetAsValue(); @@ -1144,16 +1132,15 @@ void PrerenderManager::DestroyAllContents(FinalStatus final_status) { DeletePendingDeleteEntries(); } -void PrerenderManager::DestroyAndMarkMatchCompleteAsUsed( - PrerenderContents* prerender_contents, - FinalStatus final_status) { - prerender_contents->set_match_complete_status( - PrerenderContents::MATCH_COMPLETE_REPLACED); - histograms_->RecordFinalStatus(prerender_contents->origin(), - prerender_contents->experiment_id(), - PrerenderContents::MATCH_COMPLETE_REPLACEMENT, - FINAL_STATUS_WOULD_HAVE_BEEN_USED); - prerender_contents->Destroy(final_status); +void PrerenderManager::RecordFinalStatusWithMatchCompleteStatus( + Origin origin, + uint8 experiment_id, + PrerenderContents::MatchCompleteStatus mc_status, + FinalStatus final_status) const { + histograms_->RecordFinalStatus(origin, + experiment_id, + mc_status, + final_status); } void PrerenderManager::RecordFinalStatus(Origin origin, @@ -1165,6 +1152,7 @@ void PrerenderManager::RecordFinalStatus(Origin origin, final_status); } + PrerenderManager* FindPrerenderManagerUsingRenderProcessId( int render_process_id) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h index 26d6e44..03f73f4 100644 --- a/chrome/browser/prerender/prerender_manager.h +++ b/chrome/browser/prerender/prerender_manager.h @@ -121,9 +121,6 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>, // Cancels all active prerenders. void CancelAllPrerenders(); - // Cancels all active prerenders with the ORIGIN_OMNIBOX origin. - void CancelOmniboxPrerenders(); - // For a given WebContents that wants to navigate to the URL supplied, // determines whether a prerendered version of the URL can be used, // and substitutes the prerendered RVH into the WebContents. |opener_url| is @@ -224,9 +221,6 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>, bool IsPendingEntry(const GURL& url) const; - // Returns true if |url| matches any URLs being prerendered. - bool IsPrerendering(const GURL& url) const; - protected: void SetPrerenderContentsFactory( PrerenderContents::Factory* prerender_contents_factory); @@ -243,8 +237,6 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>, // Test that needs needs access to internal functions. friend class PrerenderBrowserTest; FRIEND_TEST_ALL_PREFIXES(PrerenderManagerTest, AliasURLTest); - FRIEND_TEST_ALL_PREFIXES(PrerenderManagerTest, CancelAllTest); - FRIEND_TEST_ALL_PREFIXES(PrerenderManagerTest, CancelOmniboxTest); FRIEND_TEST_ALL_PREFIXES(PrerenderManagerTest, ClearTest); FRIEND_TEST_ALL_PREFIXES(PrerenderManagerTest, ControlGroup); FRIEND_TEST_ALL_PREFIXES(PrerenderManagerTest, DropOldestRequestTest); @@ -267,8 +259,6 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>, class MostVisitedSites; - typedef std::list<PrerenderContentsData> PrerenderContentsDataList; - // Adds a prerender for |url| from referrer |referrer| initiated from the // RenderViewHost specified by |child_route_id_pair|. The |origin| specifies // how the prerender was added. If the |session_storage_namespace| is NULL, @@ -281,6 +271,14 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>, const content::Referrer& referrer, SessionStorageNamespace* session_storage_namespace); + // Adds a pending preload issued by the prerendering RenderView identified by + // |child_route_id_pair|. If and when that prerendering RenderView is used, + // the specified prerender will start. + void AddPendingPrerender(Origin origin, + const std::pair<int, int>& child_route_id_pair, + const GURL& url, + const content::Referrer& referrer); + // Retrieves the PrerenderContents object for the specified URL, if it // has been prerendered. The caller will then have ownership of the // PrerenderContents object and is responsible for freeing it. @@ -330,14 +328,19 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>, // Finds the specified PrerenderContents and returns it, if it exists. // Returns NULL otherwise. Unlike GetEntry, the PrerenderManager maintains // ownership of the PrerenderContents. - PrerenderContents* FindEntry(const GURL& url) const; + PrerenderContents* FindEntry(const GURL& url); // Returns the iterator to the PrerenderContentsData entry that is being // prerendered from the given child route id pair. - PrerenderContentsDataList::iterator + std::list<PrerenderContentsData>::iterator FindPrerenderContentsForChildRouteIdPair( const std::pair<int, int>& child_route_id_pair); + // Returns whether the PrerenderManager is currently within the prerender + // window - effectively, up to 30 seconds after a prerender tag has been + // observed. + bool WithinWindow() const; + bool DoesRateLimitAllowPrerender() const; // Deletes old TabContents that have been replaced by prerendered ones. This @@ -396,7 +399,7 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>, PrerenderTracker* prerender_tracker_; // List of prerendered elements. - PrerenderContentsDataList prerender_list_; + std::list<PrerenderContentsData> prerender_list_; // List of recent navigations in this profile, sorted by ascending // navigate_time_. diff --git a/chrome/browser/prerender/prerender_manager_unittest.cc b/chrome/browser/prerender/prerender_manager_unittest.cc index 44f5a4f..bdedb0f 100644 --- a/chrome/browser/prerender/prerender_manager_unittest.cc +++ b/chrome/browser/prerender/prerender_manager_unittest.cc @@ -1,17 +1,14 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/command_line.h" #include "base/memory/scoped_vector.h" #include "base/message_loop.h" #include "base/time.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/prerender/prerender_manager.h" #include "chrome/browser/prerender/prerender_origin.h" -#include "chrome/common/chrome_switches.h" #include "chrome/test/base/testing_browser_process.h" -#include "chrome/test/base/testing_profile.h" #include "content/browser/renderer_host/render_view_host.h" #include "content/test/test_browser_thread.h" #include "googleurl/src/gurl.h" @@ -28,11 +25,11 @@ class DummyPrerenderContents : public PrerenderContents { DummyPrerenderContents(PrerenderManager* prerender_manager, PrerenderTracker* prerender_tracker, const GURL& url, - Origin origin, FinalStatus expected_final_status) : PrerenderContents(prerender_manager, prerender_tracker, NULL, url, content::Referrer(), - origin, PrerenderManager::kNoExperiment), + ORIGIN_LINK_REL_PRERENDER, + PrerenderManager::kNoExperiment), has_started_(false), expected_final_status_(expected_final_status) { } @@ -69,7 +66,7 @@ class DummyPrerenderContents : public PrerenderContents { class TestPrerenderManager : public PrerenderManager { public: explicit TestPrerenderManager(PrerenderTracker* prerender_tracker) - : PrerenderManager(&profile_, prerender_tracker), + : PrerenderManager(NULL, prerender_tracker), time_(base::Time::Now()), time_ticks_(base::TimeTicks::Now()), next_prerender_contents_(NULL), @@ -107,7 +104,6 @@ class TestPrerenderManager : public PrerenderManager { FinalStatus expected_final_status) { DummyPrerenderContents* prerender_contents = new DummyPrerenderContents(this, prerender_tracker_, url, - ORIGIN_LINK_REL_PRERENDER, expected_final_status); SetNextPrerenderContents(prerender_contents); return prerender_contents; @@ -115,22 +111,10 @@ class TestPrerenderManager : public PrerenderManager { DummyPrerenderContents* CreateNextPrerenderContents( const GURL& url, - Origin origin, - FinalStatus expected_final_status) { - DummyPrerenderContents* prerender_contents = - new DummyPrerenderContents(this, prerender_tracker_, url, - origin, expected_final_status); - SetNextPrerenderContents(prerender_contents); - return prerender_contents; - } - - DummyPrerenderContents* CreateNextPrerenderContents( - const GURL& url, const std::vector<GURL>& alias_urls, FinalStatus expected_final_status) { DummyPrerenderContents* prerender_contents = new DummyPrerenderContents(this, prerender_tracker_, url, - ORIGIN_LINK_REL_PRERENDER, expected_final_status); for (std::vector<GURL>::const_iterator it = alias_urls.begin(); it != alias_urls.end(); @@ -178,8 +162,6 @@ class TestPrerenderManager : public PrerenderManager { Origin origin, uint8 experiment_id) OVERRIDE { DCHECK(next_prerender_contents_.get()); - DCHECK_EQ(next_prerender_contents_->prerender_url(), url); - DCHECK_EQ(next_prerender_contents_->origin(), origin); return next_prerender_contents_.release(); } @@ -191,8 +173,6 @@ class TestPrerenderManager : public PrerenderManager { ScopedVector<PrerenderContents> used_prerender_contents_; PrerenderTracker* prerender_tracker_; - - TestingProfile profile_; }; class RestorePrerenderMode { @@ -212,10 +192,6 @@ class PrerenderManagerTest : public testing::Test { PrerenderManagerTest() : ui_thread_(BrowserThread::UI, &message_loop_), prerender_manager_( new TestPrerenderManager(prerender_tracker())) { - // Enable omnibox prerendering. - CommandLine::ForCurrentProcess()->AppendSwitchASCII( - switches::kPrerenderFromOmnibox, - switches::kPrerenderFromOmniboxSwitchValueEnabled); } TestPrerenderManager* prerender_manager() { @@ -553,46 +529,4 @@ TEST_F(PrerenderManagerTest, ClearTest) { EXPECT_EQ(null, prerender_manager()->GetEntry(url)); } -// Make sure canceling works as expected. -TEST_F(PrerenderManagerTest, CancelAllTest) { - const DummyPrerenderContents* null = NULL; - GURL url("http://www.google.com/"); - DummyPrerenderContents* prerender_contents = - prerender_manager()->CreateNextPrerenderContents( - url, FINAL_STATUS_CANCELLED); - EXPECT_TRUE(prerender_manager()->AddSimplePrerender(url)); - EXPECT_TRUE(prerender_contents->has_started()); - prerender_manager()->CancelAllPrerenders(); - EXPECT_EQ(null, prerender_manager()->GetEntry(url)); -} - -// Make sure canceling for omnibox works as expected. -TEST_F(PrerenderManagerTest, CancelOmniboxTest) { - const DummyPrerenderContents* null = NULL; - // Check canceling removes the Omnibox url. - { - GURL url("http://www.google.com/"); - DummyPrerenderContents* prerender_contents = - prerender_manager()->CreateNextPrerenderContents( - url, ORIGIN_OMNIBOX, FINAL_STATUS_CANCELLED); - EXPECT_TRUE(prerender_manager()->AddPrerenderFromOmnibox(url, NULL)); - EXPECT_TRUE(prerender_contents->has_started()); - prerender_manager()->CancelOmniboxPrerenders(); - EXPECT_EQ(null, prerender_manager()->GetEntry(url)); - } - - // Check canceling does not remove a Link url. - { - GURL url("http://www.google.com/"); - DummyPrerenderContents* prerender_contents = - prerender_manager()->CreateNextPrerenderContents( - url, ORIGIN_LINK_REL_PRERENDER, FINAL_STATUS_CANCELLED); - EXPECT_TRUE(prerender_manager()->AddSimplePrerender(url)); - EXPECT_TRUE(prerender_contents->has_started()); - prerender_manager()->CancelOmniboxPrerenders(); - EXPECT_NE(null, prerender_manager()->GetEntry(url)); - } - -} - } // namespace prerender |