Chromium Code Reviews| Index: chrome/browser/prerender/prerender_manager.cc |
| diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc |
| index 5d0409120bd9b15b85f9f769da5bb525017f5737..fd5a937b4166da24aca92670f4e527d894f5baa9 100644 |
| --- a/chrome/browser/prerender/prerender_manager.cc |
| +++ b/chrome/browser/prerender/prerender_manager.cc |
| @@ -4,6 +4,7 @@ |
| #include "chrome/browser/prerender/prerender_manager.h" |
| +#include <functional> |
| #include <set> |
| #include <string> |
| #include <vector> |
| @@ -24,6 +25,7 @@ |
| #include "chrome/browser/prerender/prerender_contents.h" |
| #include "chrome/browser/prerender/prerender_field_trial.h" |
| #include "chrome/browser/prerender/prerender_final_status.h" |
| +#include "chrome/browser/prerender/prerender_handle.h" |
|
dominich
2012/06/28 00:34:32
unnecessary include - included by header.
|
| #include "chrome/browser/prerender/prerender_histograms.h" |
| #include "chrome/browser/prerender/prerender_history.h" |
| #include "chrome/browser/prerender/prerender_local_predictor.h" |
| @@ -106,10 +108,8 @@ bool NeedMatchCompleteDummyForFinalStatus(FinalStatus final_status) { |
| final_status != FINAL_STATUS_MANAGER_SHUTDOWN && |
| final_status != FINAL_STATUS_APP_TERMINATING && |
| final_status != FINAL_STATUS_WINDOW_OPENER && |
| - final_status != FINAL_STATUS_FRAGMENT_MISMATCH && |
| final_status != FINAL_STATUS_CACHE_OR_HISTORY_CLEARED && |
| final_status != FINAL_STATUS_CANCELLED && |
| - final_status != FINAL_STATUS_SESSION_STORAGE_NAMESPACE_MISMATCH && |
| final_status != FINAL_STATUS_DEVTOOLS_ATTACHED && |
| final_status != FINAL_STATUS_CROSS_SITE_NAVIGATION_PENDING; |
| } |
| @@ -171,18 +171,6 @@ int PrerenderManager::prerenders_per_session_count_ = 0; |
| PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = |
| PRERENDER_MODE_ENABLED; |
| -struct PrerenderManager::PrerenderContentsData { |
| - PrerenderContents* contents_; |
| - base::Time start_time_; |
| - int active_count_; |
| - PrerenderContentsData(PrerenderContents* contents, base::Time start_time) |
| - : contents_(contents), |
| - start_time_(start_time), |
| - active_count_(1) { |
| - CHECK(contents); |
| - } |
| -}; |
| - |
| struct PrerenderManager::NavigationRecord { |
| GURL url_; |
| base::TimeTicks time_; |
| @@ -217,7 +205,7 @@ void PrerenderManager::Shutdown() { |
| DoShutdown(); |
| } |
| -bool PrerenderManager::AddPrerenderFromLinkRelPrerender( |
| +PrerenderHandle PrerenderManager::AddPrerenderFromLinkRelPrerender( |
| int process_id, |
| int route_id, |
| const GURL& url, |
| @@ -228,14 +216,12 @@ bool PrerenderManager::AddPrerenderFromLinkRelPrerender( |
| // link-prerender and enable omnibox-prerender only. |
| return false; |
| #else |
| - std::pair<int, int> child_route_id_pair(process_id, route_id); |
| - PrerenderContentsDataList::iterator it = |
| - FindPrerenderContentsForChildRouteIdPair(child_route_id_pair); |
| - if (it != prerender_list_.end()) { |
| + if (PrerenderHandleImpl* parent_prerender_handle = |
| + FindHandleForChildAndRoute(process_id, route_id)) { |
| // Instead of prerendering from inside of a running prerender, we will defer |
| // this request until its launcher is made visible. |
| - it->contents_->AddPendingPrerender(url, referrer, size); |
| - return true; |
| + return parent_prerender_handle->contents()-> |
| + AddPendingPrerender(url, referrer, size); |
| } |
| // Unit tests pass in a process_id == -1. |
| @@ -244,7 +230,7 @@ bool PrerenderManager::AddPrerenderFromLinkRelPrerender( |
| RenderViewHost* source_render_view_host = |
| RenderViewHost::FromID(process_id, route_id); |
| if (!source_render_view_host || !source_render_view_host->GetView()) |
| - return false; |
| + return PrerenderHandle(); |
| session_storage_namespace = |
| source_render_view_host->GetSessionStorageNamespace(); |
| @@ -266,44 +252,48 @@ bool PrerenderManager::AddPrerenderFromLinkRelPrerender( |
| #endif |
| } |
| -bool PrerenderManager::AddPrerenderFromOmnibox( |
| +PrerenderHandle PrerenderManager::AddPrerenderFromOmnibox( |
| const GURL& url, |
| SessionStorageNamespace* session_storage_namespace, |
| gfx::Size size) { |
| if (!IsOmniboxEnabled(profile_)) |
|
dominich
2012/06/28 00:34:32
nit:
return IsOmniboxEnabled(profile_) ? AddPrere
|
| - return false; |
| + return PrerenderHandle(); |
| return AddPrerender(ORIGIN_OMNIBOX, -1, url, |
| content::Referrer(), size, |
| session_storage_namespace); |
| } |
| -void PrerenderManager::MaybeCancelPrerender(const GURL& url) { |
| - PrerenderContentsDataList::iterator it = FindPrerenderContentsForURL(url); |
| - if (it == prerender_list_.end()) |
| - return; |
| - PrerenderContentsData& prerender_contents_data = *it; |
| - if (--prerender_contents_data.active_count_ == 0) |
| - prerender_contents_data.contents_->Destroy(FINAL_STATUS_CANCELLED); |
| +void PrerenderManager::StartPendingPrerender( |
| + PrerenderHandleImpl* existing_prerender_handle, |
| + Origin origin, |
| + int process_id, |
| + const GURL& url, |
| + const content::Referrer& referrer, |
| + const gfx::Size& size, |
| + content::SessionStorageNamespace* session_storage_namespace) { |
| + DCHECK(existing_prerender_handle); |
| + DCHECK(existing_prerender_handle->IsPending()); |
| + DCHECK(session_storage_namespace); |
| + PrerenderHandle new_prerender_handle = |
| + AddPrerender(origin, process_id, |
| + url, referrer, size, session_storage_namespace); |
| + new_prerender_handle->AddDuplicate(existing_prerender_handle); |
|
dominich
2012/06/28 00:34:32
shouldn't this be existing_prerender_handle->AddDu
mmenke
2012/06/28 16:01:28
Also, erm...What if a prerender is cancelled prior
|
| } |
| void PrerenderManager::DestroyPrerenderForRenderView( |
| int process_id, int view_id, FinalStatus final_status) { |
| DCHECK(CalledOnValidThread()); |
| - PrerenderContentsDataList::iterator it = |
| - FindPrerenderContentsForChildRouteIdPair( |
| - std::make_pair(process_id, view_id)); |
| - if (it != prerender_list_.end()) { |
| - PrerenderContents* prerender_contents = it->contents_; |
| - prerender_contents->Destroy(final_status); |
| + if (PrerenderHandleImpl* prerender_handle_impl = |
| + FindHandleForChildAndRoute(process_id, view_id)) { |
| + prerender_handle_impl->contents()->Destroy(final_status); |
| } |
| } |
| void PrerenderManager::CancelAllPrerenders() { |
| DCHECK(CalledOnValidThread()); |
| while (!prerender_list_.empty()) { |
| - PrerenderContentsData data = prerender_list_.front(); |
| - DCHECK(data.contents_); |
| - data.contents_->Destroy(FINAL_STATUS_CANCELLED); |
| + PrerenderContents* prerender_contents = prerender_list_.front()->contents(); |
| + prerender_contents->Destroy(FINAL_STATUS_CANCELLED); |
| } |
| } |
| @@ -312,10 +302,32 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, |
| DCHECK(CalledOnValidThread()); |
| DCHECK(!IsWebContentsPrerendering(web_contents)); |
| - scoped_ptr<PrerenderContents> prerender_contents( |
| - GetEntryButNotSpecifiedWC(url, web_contents)); |
| - if (prerender_contents.get() == NULL) |
| + RenderViewHost* old_render_view_host = web_contents->GetRenderViewHost(); |
| + |
| + DeleteOldEntries(); |
| + DeletePendingDeleteEntries(); |
| + PrerenderHandleImpl* prerender_handle_impl = |
| + FindHandle(url, old_render_view_host->GetSessionStorageNamespace()); |
| + if (!prerender_handle_impl) |
| return false; |
| + DCHECK(prerender_handle_impl->contents()); |
| + if (IsNoSwapInExperiment(prerender_handle_impl->contents()->experiment_id())) |
| + return false; |
| + |
| + if (TabContents* new_tab_contents = |
| + prerender_handle_impl->contents()->prerender_contents()) { |
| + if (web_contents == new_tab_contents->web_contents()) |
| + return false; // Do not swap in to ourself. |
| + } |
| + |
| + scoped_ptr<PrerenderContents> |
| + prerender_contents(prerender_handle_impl->contents()); |
| + PrerenderHandleList::iterator to_erase = std::find(prerender_list_.begin(), |
| + prerender_list_.end(), |
| + prerender_handle_impl); |
| + delete prerender_handle_impl; |
| + DCHECK(prerender_list_.end() != to_erase); |
| + prerender_list_.erase(to_erase); |
| // Do not use the prerendered version if there is an opener object. |
| if (web_contents->HasOpener()) { |
| @@ -323,16 +335,6 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, |
| return false; |
| } |
| - // Even if we match, the location.hash might be different. Record this as a |
| - // separate final status. |
| - GURL matching_url; |
| - bool url_matches = prerender_contents->MatchesURL(url, &matching_url); |
| - DCHECK(url_matches); |
| - if (url_matches && url.ref() != matching_url.ref()) { |
| - prerender_contents.release()->Destroy(FINAL_STATUS_FRAGMENT_MISMATCH); |
| - return false; |
| - } |
| - |
| // If we are just in the control group (which can be detected by noticing |
| // that prerendering hasn't even started yet), record that |web_contents| now |
| // would be showing a prerendered contents, but otherwise, don't do anything. |
| @@ -347,6 +349,7 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, |
| if (content::DevToolsAgentHostRegistry::IsDebuggerAttached(web_contents)) { |
| DestroyAndMarkMatchCompleteAsUsed(prerender_contents.release(), |
| FINAL_STATUS_DEVTOOLS_ATTACHED); |
| + DeletePendingDeleteEntries(); |
|
gavinp
2012/06/27 22:54:29
Remove this.
|
| return false; |
| } |
| @@ -359,22 +362,6 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, |
| return false; |
| } |
| - // If the session storage namespaces don't match, cancel the prerender. |
| - RenderViewHost* old_render_view_host = web_contents->GetRenderViewHost(); |
| - RenderViewHost* new_render_view_host = |
| - prerender_contents->prerender_contents()->web_contents()-> |
| - GetRenderViewHost(); |
| - DCHECK(old_render_view_host); |
| - DCHECK(new_render_view_host); |
| - if (old_render_view_host->GetSessionStorageNamespace() != |
| - new_render_view_host->GetSessionStorageNamespace()) { |
| - DestroyAndMarkMatchCompleteAsUsed( |
| - prerender_contents.release(), |
| - FINAL_STATUS_SESSION_STORAGE_NAMESPACE_MISMATCH); |
| - return false; |
| - } |
| - |
| - // If we don't want to use prerenders at all, we are done. |
| // 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) { |
| @@ -393,6 +380,8 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, |
| if (!prerender_tracker_->TryUse(child_id, route_id)) |
| return false; |
| + // At this point, we've determined that we will use the prerender. |
| + |
| if (!prerender_contents->load_start_time().is_null()) { |
| histograms_->RecordTimeUntilUsed(GetCurrentTimeTicks() - |
| prerender_contents->load_start_time(), |
| @@ -403,10 +392,17 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, |
| histograms_->RecordUsedPrerender(prerender_contents->origin()); |
| prerender_contents->set_final_status(FINAL_STATUS_USED); |
| + RenderViewHost* new_render_view_host = |
| + prerender_contents->prerender_contents()->web_contents()-> |
| + GetRenderViewHost(); |
| new_render_view_host->Send( |
| new PrerenderMsg_SetIsPrerendering(new_render_view_host->GetRoutingID(), |
| false)); |
| + // Start pending prerender requests from the PrerenderContents, if there are |
| + // any. |
| + prerender_contents->StartPendingPrerenders(); |
|
dominich
2012/06/28 00:34:32
any reason why this was moved earlier?
|
| + |
| TabContents* new_tab_contents = |
| prerender_contents->ReleasePrerenderContents(); |
| TabContents* old_tab_contents = TabContents::FromWebContents(web_contents); |
| @@ -439,10 +435,6 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, |
| DCHECK(prerender_tab_helper != NULL); |
| prerender_tab_helper->PrerenderSwappedIn(); |
| - // Start pending prerender requests from the PrerenderContents, if there are |
| - // any. |
| - prerender_contents->StartPendingPrerenders(); |
| - |
| if (old_tab_contents->web_contents()->NeedToFireBeforeUnload()) { |
| // Schedule the delete to occur after the tab has run its unload handlers. |
| on_close_tab_contents_deleters_.push_back( |
| @@ -469,50 +461,52 @@ void PrerenderManager::MoveEntryToPendingDelete(PrerenderContents* entry, |
| DCHECK_EQ(0, std::count(pending_delete_list_.begin(), |
| pending_delete_list_.end(), entry)); |
| - for (PrerenderContentsDataList::iterator it = prerender_list_.begin(); |
| - it != prerender_list_.end(); |
| - ++it) { |
| - if (it->contents_ == entry) { |
| - bool swapped_in_dummy_replacement = false; |
| - |
| - // If this PrerenderContents is being deleted due to a cancellation, |
| - // we need to create a dummy replacement for PPLT accounting purposes |
| - // for the Match Complete group. |
| - // This is the case if the cancellation is for any reason that would not |
| - // occur in the control group case. |
| - if (entry->match_complete_status() == |
| - PrerenderContents::MATCH_COMPLETE_DEFAULT && |
| - NeedMatchCompleteDummyForFinalStatus(final_status) && |
| - ActuallyPrerendering()) { |
| - // TODO(tburkard): I'd like to DCHECK that we are actually prerendering. |
| - // However, what if new conditions are added and |
| - // NeedMatchCompleteDummyForFinalStatus, is not being updated. Not sure |
| - // what's the best thing to do here. For now, I will just check whether |
| - // we are actually prerendering. |
| - entry->set_match_complete_status( |
| - PrerenderContents::MATCH_COMPLETE_REPLACED); |
| - if (PrerenderContents* dummy_replacement_prerender_contents = |
| - CreatePrerenderContents(entry->prerender_url(), |
| - entry->referrer(), |
| - entry->origin(), |
| - entry->experiment_id())) { |
| - dummy_replacement_prerender_contents->set_match_complete_status( |
| - PrerenderContents::MATCH_COMPLETE_REPLACEMENT_PENDING); |
| - if (!dummy_replacement_prerender_contents->Init()) |
| - break; |
| - dummy_replacement_prerender_contents-> |
| - AddAliasURLsFromOtherPrerenderContents(entry); |
| - dummy_replacement_prerender_contents->set_match_complete_status( |
| - PrerenderContents::MATCH_COMPLETE_REPLACEMENT); |
| - it->contents_ = dummy_replacement_prerender_contents; |
| - swapped_in_dummy_replacement = true; |
| - } |
| - } |
| - if (!swapped_in_dummy_replacement) |
| - prerender_list_.erase(it); |
| + PrerenderHandleList::iterator it; |
| + for (it = prerender_list_.begin(); it != prerender_list_.end(); ++it) { |
| + if ((*it)->contents() == entry) |
| break; |
| - } |
| } |
| + |
| + if (it == prerender_list_.end()) |
| + return; |
|
dominich
2012/06/28 00:34:32
i think this changes the logic. by returning early
|
| + |
| + // If this PrerenderContents is being deleted due to a cancellation, |
| + // we need to create a dummy replacement for PPLT accounting purposes |
| + // for the Match Complete group. |
| + // This is the case if the cancellation is for any reason that would not |
| + // occur in the control group case. |
| + if (entry->match_complete_status() == |
| + PrerenderContents::MATCH_COMPLETE_DEFAULT && |
| + NeedMatchCompleteDummyForFinalStatus(final_status) && |
| + ActuallyPrerendering()) { |
| + // TODO(tburkard): I'd like to DCHECK that we are actually prerendering. |
| + // However, what if new conditions are added and |
| + // NeedMatchCompleteDummyForFinalStatus, is not being updated. Not sure |
| + // what's the best thing to do here. For now, I will just check whether |
| + // we are actually prerendering. |
| + entry->set_match_complete_status( |
| + PrerenderContents::MATCH_COMPLETE_REPLACED); |
| + PrerenderContents* dummy_replacement_prerender_contents = |
| + CreatePrerenderContents(entry->prerender_url(), entry->referrer(), |
| + entry->origin(), entry->experiment_id()); |
| + dummy_replacement_prerender_contents->MakeIntoDummyReplacementOf(entry); |
| + |
| + DCHECK(dummy_replacement_prerender_contents); |
| + |
| + dummy_replacement_prerender_contents->set_match_complete_status( |
| + PrerenderContents::MATCH_COMPLETE_REPLACEMENT_PENDING); |
| + DCHECK(dummy_replacement_prerender_contents->Init()); |
| + dummy_replacement_prerender_contents-> |
| + AddAliasURLsFromOtherPrerenderContents(entry); |
| + dummy_replacement_prerender_contents->set_match_complete_status( |
| + PrerenderContents::MATCH_COMPLETE_REPLACEMENT); |
| + |
| + (*it)->SetContents(dummy_replacement_prerender_contents); |
| + } else { |
| + delete *it; |
| + prerender_list_.erase(it); |
| + } |
| + |
| AddToHistory(entry); |
| pending_delete_list_.push_back(entry); |
| @@ -623,10 +617,11 @@ bool PrerenderManager::IsNoUseGroup() { |
| bool PrerenderManager::IsWebContentsPrerendering( |
| WebContents* web_contents) const { |
| DCHECK(CalledOnValidThread()); |
| - for (PrerenderContentsDataList::const_iterator it = prerender_list_.begin(); |
| + for (PrerenderHandleList::const_iterator it = prerender_list_.begin(); |
| it != prerender_list_.end(); |
| ++it) { |
| - TabContents* prerender_tab_contents = it->contents_->prerender_contents(); |
| + TabContents* prerender_tab_contents = |
| + (*it)->contents()->prerender_contents(); |
| if (prerender_tab_contents && |
| prerender_tab_contents->web_contents() == web_contents) { |
| return true; |
| @@ -647,12 +642,6 @@ bool PrerenderManager::IsWebContentsPrerendering( |
| return false; |
| } |
| -bool PrerenderManager::DidPrerenderFinishLoading(const GURL& url) const { |
| - DCHECK(CalledOnValidThread()); |
| - PrerenderContents* contents = FindEntry(url); |
| - return contents ? contents->has_finished_loading() : false; |
| -} |
| - |
| void PrerenderManager::MarkWebContentsAsPrerendered(WebContents* web_contents) { |
| DCHECK(CalledOnValidThread()); |
| prerendered_tab_contents_set_.insert(web_contents); |
| @@ -768,22 +757,6 @@ void PrerenderManager::AddCondition(const PrerenderCondition* condition) { |
| prerender_conditions_.push_back(condition); |
| } |
| -bool PrerenderManager::IsPendingEntry(const GURL& url) const { |
| - DCHECK(CalledOnValidThread()); |
| - for (PrerenderContentsDataList::const_iterator it = prerender_list_.begin(); |
| - it != prerender_list_.end(); |
| - ++it) { |
| - if (it->contents_->IsPendingEntry(url)) |
| - return true; |
| - } |
| - return false; |
| -} |
| - |
| -bool PrerenderManager::IsPrerendering(const GURL& url) const { |
| - DCHECK(CalledOnValidThread()); |
| - return (FindEntry(url) != NULL); |
| -} |
| - |
| void PrerenderManager::RecordNavigation(const GURL& url) { |
| DCHECK(CalledOnValidThread()); |
| @@ -805,8 +778,30 @@ void PrerenderManager::DoShutdown() { |
| profile_ = NULL; |
| } |
| +PrerenderContents* PrerenderManager::FindEntry( |
| + const GURL& url, |
| + SessionStorageNamespace* session_storage_namespace) { |
| + DeleteOldEntries(); |
| + DeletePendingDeleteEntries(); |
| + if (PrerenderHandleImpl* handle = FindHandle(url, session_storage_namespace)) |
| + return handle->contents(); |
| + return NULL; |
| +} |
| + |
| +void PrerenderManager::TreatPrerenderAsUsedForTest( |
| + const GURL& url, |
| + SessionStorageNamespace* session_storage_namespace) { |
| + PrerenderHandleImpl* handle = FindHandle(url, session_storage_namespace); |
| + CHECK(handle); |
| + handle->contents()->set_final_status(FINAL_STATUS_USED); |
| + PrerenderHandleList::iterator to_erase = |
| + std::find(prerender_list_.begin(), prerender_list_.end(), handle); |
| + delete handle; |
| + prerender_list_.erase(to_erase); |
| +} |
| + |
| // private |
| -bool PrerenderManager::AddPrerender( |
| +PrerenderHandle PrerenderManager::AddPrerender( |
| Origin origin, |
| int process_id, |
| const GURL& url_arg, |
| @@ -816,7 +811,7 @@ bool PrerenderManager::AddPrerender( |
| DCHECK(CalledOnValidThread()); |
| if (!IsEnabled()) |
| - return false; |
| + return PrerenderHandle(); |
| if (origin == ORIGIN_LINK_REL_PRERENDER && |
| IsGoogleSearchResultURL(referrer.url)) { |
| @@ -840,10 +835,11 @@ bool PrerenderManager::AddPrerender( |
| // histogram tracking. |
| histograms_->RecordPrerender(origin, url_arg); |
| - if (PrerenderContentsData* prerender_contents_data = FindEntryData(url)) { |
| - ++prerender_contents_data->active_count_; |
| + if (PrerenderHandleImpl* preexisting_prerender_handle = |
| + FindHandle(url, session_storage_namespace)) { |
| RecordFinalStatus(origin, experiment, FINAL_STATUS_DUPLICATE); |
| - return true; |
| + preexisting_prerender_handle->AddClient(); |
| + return preexisting_prerender_handle->AsWeakPtr(); |
| } |
| // Do not prerender if there are too many render processes, and we would |
| @@ -861,7 +857,7 @@ bool PrerenderManager::AddPrerender( |
| profile_, url) && |
| !content::RenderProcessHost::run_renderer_in_process()) { |
| RecordFinalStatus(origin, experiment, FINAL_STATUS_TOO_MANY_PROCESSES); |
| - return false; |
| + return PrerenderHandle(); |
| } |
| #endif |
| @@ -871,64 +867,40 @@ bool PrerenderManager::AddPrerender( |
| // 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; |
| + return PrerenderHandle(); |
| } |
| PrerenderContents* prerender_contents = CreatePrerenderContents( |
| url, referrer, origin, experiment); |
| if (!prerender_contents || !prerender_contents->Init()) |
| - return false; |
| + return PrerenderHandle(); |
| histograms_->RecordPrerenderStarted(origin); |
| // TODO(cbentzel): Move invalid checks here instead of PrerenderContents? |
| - PrerenderContentsData data(prerender_contents, GetCurrentTime()); |
| - |
| - prerender_list_.push_back(data); |
| + PrerenderHandleImpl* prerender_handle_impl = new PrerenderHandleImpl; |
|
dominich
2012/06/28 00:34:32
a constructor that takes a PrerenderContents?
dominich
2012/06/28 00:34:32
() after the type to ensure initialization.
|
| + prerender_handle_impl->SetContents(prerender_contents); |
| + prerender_list_.push_back(prerender_handle_impl); |
| last_prerender_start_time_ = GetCurrentTimeTicks(); |
| if (size.IsEmpty()) |
| size = config_.default_tab_bounds.size(); |
| - data.contents_->StartPrerendering(process_id, size, session_storage_namespace, |
| - control_group_behavior); |
| + prerender_contents->StartPrerendering(process_id, size, |
| + session_storage_namespace, |
| + control_group_behavior); |
| while (prerender_list_.size() > config_.max_elements) { |
| - data = prerender_list_.front(); |
| - prerender_list_.pop_front(); |
| - data.contents_->Destroy(FINAL_STATUS_EVICTED); |
| + prerender_contents = prerender_list_.front()->contents(); |
| + DCHECK(prerender_contents); |
| + const size_t old_size = prerender_list_.size(); |
| + prerender_contents->Destroy(FINAL_STATUS_EVICTED); |
| + DCHECK_GT(old_size, prerender_list_.size()); |
|
dominich
2012/06/28 00:34:32
if you want to test that calling Destroy removes a
|
| } |
| - 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) && |
| - !IsNoSwapInExperiment(prerender_contents->experiment_id())) { |
| - 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; |
| + StartSchedulingPeriodicCleanups(); |
| + return prerender_handle_impl->AsWeakPtr(); |
| } |
| void PrerenderManager::StartSchedulingPeriodicCleanups() { |
| @@ -941,10 +913,7 @@ void PrerenderManager::StartSchedulingPeriodicCleanups() { |
| &PrerenderManager::PeriodicCleanup); |
| } |
| -void PrerenderManager::MaybeStopSchedulingPeriodicCleanups() { |
| - if (!prerender_list_.empty()) |
| - return; |
| - |
| +void PrerenderManager::StopSchedulingPeriodicCleanups() { |
| DCHECK(CalledOnValidThread()); |
| repeating_timer_.Stop(); |
| } |
| @@ -953,21 +922,16 @@ void PrerenderManager::PeriodicCleanup() { |
| DCHECK(CalledOnValidThread()); |
| DeleteOldTabContents(); |
| DeleteOldEntries(); |
| + if (prerender_list_.empty()) |
| + StopSchedulingPeriodicCleanups(); |
| // 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(); |
| + PrerenderHandleList prerender_list(prerender_list_); |
|
dominich
2012/06/28 00:34:32
Change comment to 'Grab a copy of the current Prer
|
| + for (PrerenderHandleList::iterator it = prerender_list_.begin(); |
| it != prerender_list_.end(); |
| - ++it) { |
| - DCHECK(it->contents_); |
| - prerender_contents.push_back(it->contents_); |
| - } |
| - for (std::vector<PrerenderContents*>::iterator it = |
| - prerender_contents.begin(); |
| - it != prerender_contents.end(); |
| - ++it) { |
| - (*it)->DestroyWhenUsingTooManyResources(); |
| + it++) { |
| + (*it)->contents()->DestroyWhenUsingTooManyResources(); |
| } |
| DeletePendingDeleteEntries(); |
| @@ -986,21 +950,22 @@ base::TimeDelta PrerenderManager::GetMaxAge() const { |
| base::TimeDelta::FromSeconds(300) : config_.max_age); |
| } |
| -bool PrerenderManager::IsPrerenderElementFresh(const base::Time start) const { |
| +bool PrerenderManager::IsPrerenderFresh(base::TimeTicks start) const { |
|
dominich
2012/06/28 00:34:32
can you write up a post for the dev.chromium.org s
|
| DCHECK(CalledOnValidThread()); |
| - base::Time now = GetCurrentTime(); |
| - return (now - start < GetMaxAge()); |
| + base::TimeTicks now = GetCurrentTimeTicks(); |
| + return now - start < GetMaxAge(); |
| } |
| void PrerenderManager::DeleteOldEntries() { |
| DCHECK(CalledOnValidThread()); |
| + |
| while (!prerender_list_.empty()) { |
| - PrerenderContentsData data = prerender_list_.front(); |
| - if (IsPrerenderElementFresh(data.start_time_)) |
| + PrerenderContents* contents = prerender_list_.front()->contents(); |
| + DCHECK(contents); |
| + if (IsPrerenderFresh(contents->load_start_time())) |
| return; |
| - data.contents_->Destroy(FINAL_STATUS_TIMED_OUT); |
| + contents->Destroy(FINAL_STATUS_TIMED_OUT); |
| } |
| - MaybeStopSchedulingPeriodicCleanups(); |
| } |
| base::Time PrerenderManager::GetCurrentTime() const { |
| @@ -1030,58 +995,37 @@ void PrerenderManager::DeletePendingDeleteEntries() { |
| } |
| } |
| -PrerenderManager::PrerenderContentsData* PrerenderManager::FindEntryData( |
| - const GURL& url) { |
| - DCHECK(CalledOnValidThread()); |
| - PrerenderContentsDataList::iterator it = FindPrerenderContentsForURL(url); |
| - if (it == prerender_list_.end()) |
| - return NULL; |
| - PrerenderContentsData& prerender_contents_data = *it; |
| - return &prerender_contents_data; |
| -} |
| - |
| -PrerenderContents* PrerenderManager::FindEntry(const GURL& url) const { |
| - DCHECK(CalledOnValidThread()); |
| - for (PrerenderContentsDataList::const_iterator it = prerender_list_.begin(); |
| +PrerenderHandleImpl* PrerenderManager::FindHandle( |
| + const GURL& url, |
| + const SessionStorageNamespace* session_storage_namespace) { |
| + for (PrerenderHandleList::iterator it = prerender_list_.begin(); |
| it != prerender_list_.end(); |
| ++it) { |
| - if (it->contents_->MatchesURL(url, NULL)) |
| - return it->contents_; |
| + PrerenderContents* prerender_contents = (*it)->contents(); |
| + if (prerender_contents->Matches(url, session_storage_namespace)) |
| + return *it; |
| } |
| - // Entry not found. |
| return NULL; |
| } |
| -PrerenderManager::PrerenderContentsDataList::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); |
| +PrerenderHandleImpl* PrerenderManager::FindHandleForChildAndRoute( |
| + const int child_id, const int route_id) { |
| + for (PrerenderHandleList::iterator it = prerender_list_.begin(); |
| + it != prerender_list_.end(); |
| + ++it) { |
| + PrerenderContents* prerender_contents = (*it)->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; |
| -} |
| + int contents_child_id; |
| + if (!prerender_contents->GetChildId(&contents_child_id)) |
| + continue; |
| + int contents_route_id; |
| + if (!prerender_contents->GetRouteId(&contents_route_id)) |
| + continue; |
| -PrerenderManager::PrerenderContentsDataList::iterator |
| - PrerenderManager::FindPrerenderContentsForURL(const GURL& url) { |
| - for (PrerenderContentsDataList::iterator it = prerender_list_.begin(); |
| - it != prerender_list_.end(); ++it) { |
| - if (it->contents_->MatchesURL(url, NULL)) |
| - return it; |
| + if (contents_child_id == child_id && contents_route_id == route_id) |
| + return *it; |
| } |
| - return prerender_list_.end(); |
| + return NULL; |
| } |
| bool PrerenderManager::DoesRateLimitAllowPrerender() const { |
| @@ -1143,13 +1087,11 @@ void PrerenderManager::AddToHistory(PrerenderContents* contents) { |
| Value* PrerenderManager::GetActivePrerendersAsValue() const { |
| ListValue* list_value = new ListValue(); |
| - for (PrerenderContentsDataList::const_iterator it = prerender_list_.begin(); |
| + for (PrerenderHandleList::const_iterator it = prerender_list_.begin(); |
| it != prerender_list_.end(); |
| ++it) { |
| - Value* prerender_value = it->contents_->GetAsValue(); |
| - if (!prerender_value) |
| - continue; |
| - list_value->Append(prerender_value); |
| + if (Value* prerender_value = (*it)->contents()->GetAsValue()) |
| + list_value->Append(prerender_value); |
| } |
| return list_value; |
| } |
| @@ -1157,9 +1099,10 @@ Value* PrerenderManager::GetActivePrerendersAsValue() const { |
| void PrerenderManager::DestroyAllContents(FinalStatus final_status) { |
| DeleteOldTabContents(); |
| while (!prerender_list_.empty()) { |
| - PrerenderContentsData data = prerender_list_.front(); |
| - prerender_list_.pop_front(); |
| - data.contents_->Destroy(final_status); |
| + PrerenderContents* contents = prerender_list_.front()->contents(); |
| + const size_t old_size = prerender_list_.size(); |
| + contents->Destroy(final_status); |
| + DCHECK_GT(old_size, prerender_list_.size()); |
|
dominich
2012/06/28 00:34:32
check Destroy removes items in a unit test, not in
|
| } |
| DeletePendingDeleteEntries(); |
| } |