| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/prerender/prerender_manager.h" | 5 #include "chrome/browser/prerender/prerender_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <functional> | 8 #include <functional> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 break; | 217 break; |
| 218 default: | 218 default: |
| 219 break; | 219 break; |
| 220 } | 220 } |
| 221 } | 221 } |
| 222 | 222 |
| 223 PrerenderManager::~PrerenderManager() { | 223 PrerenderManager::~PrerenderManager() { |
| 224 // The earlier call to ProfileKeyedService::Shutdown() should have emptied | 224 // The earlier call to ProfileKeyedService::Shutdown() should have emptied |
| 225 // these vectors already. | 225 // these vectors already. |
| 226 DCHECK(active_prerenders_.empty()); | 226 DCHECK(active_prerenders_.empty()); |
| 227 DCHECK(pending_prerenders_.empty()); | |
| 228 DCHECK(to_delete_prerenders_.empty()); | 227 DCHECK(to_delete_prerenders_.empty()); |
| 229 } | 228 } |
| 230 | 229 |
| 231 void PrerenderManager::Shutdown() { | 230 void PrerenderManager::Shutdown() { |
| 232 DestroyAllContents(FINAL_STATUS_MANAGER_SHUTDOWN); | 231 DestroyAllContents(FINAL_STATUS_MANAGER_SHUTDOWN); |
| 233 STLDeleteElements(&prerender_conditions_); | 232 STLDeleteElements(&prerender_conditions_); |
| 234 on_close_tab_contents_deleters_.clear(); | 233 on_close_tab_contents_deleters_.clear(); |
| 235 // Must happen before |profile_| is set to NULL as | 234 // Must happen before |profile_| is set to NULL as |
| 236 // |local_predictor_| accesses it. | 235 // |local_predictor_| accesses it. |
| 237 if (local_predictor_) | 236 if (local_predictor_) |
| 238 local_predictor_->Shutdown(); | 237 local_predictor_->Shutdown(); |
| 239 profile_ = NULL; | 238 profile_ = NULL; |
| 240 | 239 |
| 241 DCHECK(active_prerenders_.empty()); | 240 DCHECK(active_prerenders_.empty()); |
| 242 pending_prerenders_.clear(); | |
| 243 } | 241 } |
| 244 | 242 |
| 245 PrerenderHandle* PrerenderManager::AddPrerenderFromLinkRelPrerender( | 243 PrerenderHandle* PrerenderManager::AddPrerenderFromLinkRelPrerender( |
| 246 int process_id, | 244 int process_id, |
| 247 int route_id, | 245 int route_id, |
| 248 const GURL& url, | 246 const GURL& url, |
| 249 const content::Referrer& referrer, | 247 const content::Referrer& referrer, |
| 250 const gfx::Size& size) { | 248 const gfx::Size& size) { |
| 251 #if defined(OS_ANDROID) | 249 #if defined(OS_ANDROID) |
| 252 // TODO(jcivelli): http://crbug.com/113322 We should have an option to disable | 250 // TODO(jcivelli): http://crbug.com/113322 We should have an option to disable |
| (...skipping 19 matching lines...) Expand all Loading... |
| 272 session_storage_namespace = | 270 session_storage_namespace = |
| 273 source_web_contents->GetController() | 271 source_web_contents->GetController() |
| 274 .GetDefaultSessionStorageNamespace(); | 272 .GetDefaultSessionStorageNamespace(); |
| 275 } | 273 } |
| 276 | 274 |
| 277 if (PrerenderData* parent_prerender_data = | 275 if (PrerenderData* parent_prerender_data = |
| 278 FindPrerenderDataForChildAndRoute(process_id, route_id)) { | 276 FindPrerenderDataForChildAndRoute(process_id, route_id)) { |
| 279 // Instead of prerendering from inside of a running prerender, we will defer | 277 // Instead of prerendering from inside of a running prerender, we will defer |
| 280 // this request until its launcher is made visible. | 278 // this request until its launcher is made visible. |
| 281 if (PrerenderContents* contents = parent_prerender_data->contents()) { | 279 if (PrerenderContents* contents = parent_prerender_data->contents()) { |
| 282 pending_prerenders_.push_back(new PrerenderData(this)); | |
| 283 PrerenderHandle* prerender_handle = | 280 PrerenderHandle* prerender_handle = |
| 284 new PrerenderHandle(pending_prerenders_.back()); | 281 new PrerenderHandle(static_cast<PrerenderData*>(NULL)); |
| 285 DCHECK(prerender_handle->IsPending()); | |
| 286 | |
| 287 scoped_ptr<PrerenderContents::PendingPrerenderInfo> | 282 scoped_ptr<PrerenderContents::PendingPrerenderInfo> |
| 288 pending_prerender_info(new PrerenderContents::PendingPrerenderInfo( | 283 pending_prerender_info(new PrerenderContents::PendingPrerenderInfo( |
| 289 prerender_handle->weak_ptr_factory_.GetWeakPtr(), | 284 prerender_handle->weak_ptr_factory_.GetWeakPtr(), |
| 290 origin, url, referrer, size)); | 285 origin, url, referrer, size)); |
| 291 | 286 |
| 292 contents->AddPendingPrerender(pending_prerender_info.Pass()); | 287 contents->AddPendingPrerender(pending_prerender_info.Pass()); |
| 293 return prerender_handle; | 288 return prerender_handle; |
| 294 } | 289 } |
| 295 } | 290 } |
| 296 | 291 |
| (...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 CleanUpOldNavigations(); | 845 CleanUpOldNavigations(); |
| 851 } | 846 } |
| 852 | 847 |
| 853 // protected | 848 // protected |
| 854 struct PrerenderManager::PrerenderData::OrderByExpiryTime { | 849 struct PrerenderManager::PrerenderData::OrderByExpiryTime { |
| 855 bool operator()(const PrerenderData* a, const PrerenderData* b) const { | 850 bool operator()(const PrerenderData* a, const PrerenderData* b) const { |
| 856 return a->expiry_time() < b->expiry_time(); | 851 return a->expiry_time() < b->expiry_time(); |
| 857 } | 852 } |
| 858 }; | 853 }; |
| 859 | 854 |
| 860 PrerenderManager::PrerenderData::PrerenderData(PrerenderManager* manager) | |
| 861 : manager_(manager), contents_(NULL), handle_count_(0) { | |
| 862 } | |
| 863 | |
| 864 PrerenderManager::PrerenderData::PrerenderData(PrerenderManager* manager, | 855 PrerenderManager::PrerenderData::PrerenderData(PrerenderManager* manager, |
| 865 PrerenderContents* contents, | 856 PrerenderContents* contents, |
| 866 base::TimeTicks expiry_time) | 857 base::TimeTicks expiry_time) |
| 867 : manager_(manager), | 858 : manager_(manager), |
| 868 contents_(contents), | 859 contents_(contents), |
| 869 handle_count_(0), | 860 handle_count_(0), |
| 870 expiry_time_(expiry_time) { | 861 expiry_time_(expiry_time) { |
| 871 } | 862 } |
| 872 | 863 |
| 873 PrerenderManager::PrerenderData::~PrerenderData() { | 864 PrerenderManager::PrerenderData::~PrerenderData() { |
| 874 } | 865 } |
| 875 | 866 |
| 876 void PrerenderManager::PrerenderData::MakeIntoMatchCompleteReplacement() { | 867 void PrerenderManager::PrerenderData::MakeIntoMatchCompleteReplacement() { |
| 877 DCHECK(contents_); | 868 DCHECK(contents_); |
| 878 contents_->set_match_complete_status( | 869 contents_->set_match_complete_status( |
| 879 PrerenderContents::MATCH_COMPLETE_REPLACED); | 870 PrerenderContents::MATCH_COMPLETE_REPLACED); |
| 880 PrerenderData* to_delete = new PrerenderData(manager_, contents_.release(), | 871 PrerenderData* to_delete = new PrerenderData(manager_, contents_.release(), |
| 881 expiry_time_); | 872 expiry_time_); |
| 882 contents_.reset(to_delete->contents_->CreateMatchCompleteReplacement()); | 873 contents_.reset(to_delete->contents_->CreateMatchCompleteReplacement()); |
| 883 manager_->to_delete_prerenders_.push_back(to_delete); | 874 manager_->to_delete_prerenders_.push_back(to_delete); |
| 884 } | 875 } |
| 885 | 876 |
| 886 void PrerenderManager::PrerenderData::OnNewHandle() { | 877 void PrerenderManager::PrerenderData::OnNewHandle(PrerenderHandle* handle) { |
| 887 DCHECK(contents_ || handle_count_ == 0) << | |
| 888 "Cannot create multiple handles to a pending prerender."; | |
| 889 ++handle_count_; | 878 ++handle_count_; |
| 879 if (contents_) |
| 880 contents_->AddObserver(handle); |
| 890 } | 881 } |
| 891 | 882 |
| 892 void PrerenderManager::PrerenderData::OnNavigateAwayByHandle() { | 883 void PrerenderManager::PrerenderData::OnNavigateAwayByHandle( |
| 893 if (!contents_) { | 884 PrerenderHandle* handle) { |
| 894 DCHECK_EQ(1, handle_count_); | 885 DCHECK_LT(0, handle_count_); |
| 895 // Pending prerenders are not maintained in the active_prerenders_, so they | 886 // We intentionally don't decrement the handle count here, so that the |
| 896 // will not get normal expiry. Since this prerender hasn't even been | 887 // prerender won't be canceled until it times out. |
| 897 // launched yet, and it's held by a page that is being prerendered, we will | 888 manager_->SourceNavigatedAway(this); |
| 898 // just delete it. | |
| 899 manager_->DestroyPendingPrerenderData(this); | |
| 900 } else { | |
| 901 DCHECK_LE(0, handle_count_); | |
| 902 // We intentionally don't decrement the handle count here, so that the | |
| 903 // prerender won't be canceled until it times out. | |
| 904 manager_->SourceNavigatedAway(this); | |
| 905 } | |
| 906 } | 889 } |
| 907 | 890 |
| 908 void PrerenderManager::PrerenderData::OnCancelByHandle() { | 891 void PrerenderManager::PrerenderData::OnCancelByHandle( |
| 892 PrerenderHandle* handle) { |
| 909 DCHECK_LE(1, handle_count_); | 893 DCHECK_LE(1, handle_count_); |
| 910 DCHECK(contents_ || handle_count_ == 1); | 894 DCHECK(contents_ || handle_count_ == 1) |
| 895 << "Pending prerenders should never have multiple prerenders"; |
| 911 | 896 |
| 912 if (--handle_count_ == 0) { | 897 if (--handle_count_ == 0) { |
| 913 if (contents_) { | 898 if (contents_) { |
| 914 // This will eventually remove this object from active_prerenders_. | 899 // This will eventually remove this object from active_prerenders_. |
| 915 contents_->Destroy(FINAL_STATUS_CANCELLED); | 900 contents_->Destroy(FINAL_STATUS_CANCELLED); |
| 916 } else { | |
| 917 manager_->DestroyPendingPrerenderData(this); | |
| 918 } | 901 } |
| 919 } | 902 } |
| 920 } | 903 } |
| 921 | 904 |
| 922 PrerenderContents* PrerenderManager::PrerenderData::ReleaseContents() { | 905 PrerenderContents* PrerenderManager::PrerenderData::ReleaseContents() { |
| 923 return contents_.release(); | 906 return contents_.release(); |
| 924 } | 907 } |
| 925 | 908 |
| 926 void PrerenderManager::SetPrerenderContentsFactory( | 909 void PrerenderManager::SetPrerenderContentsFactory( |
| 927 PrerenderContents::Factory* prerender_contents_factory) { | 910 PrerenderContents::Factory* prerender_contents_factory) { |
| 928 DCHECK(CalledOnValidThread()); | 911 DCHECK(CalledOnValidThread()); |
| 929 prerender_contents_factory_.reset(prerender_contents_factory); | 912 prerender_contents_factory_.reset(prerender_contents_factory); |
| 930 } | 913 } |
| 931 | 914 |
| 932 void PrerenderManager::StartPendingPrerenders( | 915 void PrerenderManager::StartPendingPrerenders( |
| 933 const int process_id, | 916 const int process_id, |
| 934 ScopedVector<PrerenderContents::PendingPrerenderInfo>* pending_prerenders, | 917 ScopedVector<PrerenderContents::PendingPrerenderInfo>* pending_prerenders, |
| 935 content::SessionStorageNamespace* session_storage_namespace) { | 918 content::SessionStorageNamespace* session_storage_namespace) { |
| 936 for (ScopedVector<PrerenderContents::PendingPrerenderInfo>::iterator | 919 for (ScopedVector<PrerenderContents::PendingPrerenderInfo>::iterator |
| 937 it = pending_prerenders->begin(); | 920 it = pending_prerenders->begin(); |
| 938 it != pending_prerenders->end(); ++it) { | 921 it != pending_prerenders->end(); ++it) { |
| 939 PrerenderContents::PendingPrerenderInfo* info = *it; | 922 PrerenderContents::PendingPrerenderInfo* info = *it; |
| 940 PrerenderHandle* existing_prerender_handle = | 923 PrerenderHandle* existing_prerender_handle = |
| 941 info->weak_prerender_handle.get(); | 924 info->weak_prerender_handle.get(); |
| 942 if (!existing_prerender_handle || !existing_prerender_handle->IsValid()) | 925 if (!existing_prerender_handle) |
| 926 continue; |
| 927 if (existing_prerender_handle->has_been_canceled()) |
| 943 continue; | 928 continue; |
| 944 | 929 |
| 945 DCHECK(existing_prerender_handle->IsPending()); | 930 DCHECK(!existing_prerender_handle->IsValid()); |
| 946 DCHECK(process_id == -1 || session_storage_namespace); | 931 DCHECK(process_id == -1 || session_storage_namespace); |
| 947 | 932 |
| 948 scoped_ptr<PrerenderHandle> swap_prerender_handle(AddPrerender( | 933 scoped_ptr<PrerenderHandle> new_prerender_handle(AddPrerender( |
| 949 info->origin, process_id, | 934 info->origin, process_id, |
| 950 info->url, info->referrer, info->size, | 935 info->url, info->referrer, info->size, |
| 951 session_storage_namespace)); | 936 session_storage_namespace)); |
| 952 if (swap_prerender_handle.get()) { | 937 if (new_prerender_handle.get()) { |
| 953 // AddPrerender has returned a new prerender handle to us. We want to make | 938 // AddPrerender has returned a new prerender handle to us. We want to make |
| 954 // |existing_prerender_handle| active, so swap the underlying | 939 // |existing_prerender_handle| active, so move the underlying |
| 955 // PrerenderData between the two handles, and delete our old handle (which | 940 // PrerenderData to our new handle. |
| 956 // will release our entry in the pending_prerender_list_). | 941 existing_prerender_handle->AdoptPrerenderDataFrom( |
| 957 existing_prerender_handle->SwapPrerenderDataWith( | 942 new_prerender_handle.get()); |
| 958 swap_prerender_handle.get()); | |
| 959 swap_prerender_handle->OnCancel(); | |
| 960 continue; | 943 continue; |
| 961 } | 944 } |
| 962 | |
| 963 // We could not start our Prerender. Canceling the existing handle will make | |
| 964 // it return false for PrerenderHandle::IsPending(), and will release the | |
| 965 // PrerenderData from pending_prerender_list_. | |
| 966 existing_prerender_handle->OnCancel(); | |
| 967 } | 945 } |
| 968 } | 946 } |
| 969 | 947 |
| 970 void PrerenderManager::SourceNavigatedAway(PrerenderData* prerender_data) { | 948 void PrerenderManager::SourceNavigatedAway(PrerenderData* prerender_data) { |
| 971 // The expiry time of our prerender data will likely change because of | 949 // The expiry time of our prerender data will likely change because of |
| 972 // this navigation. This requires a resort of active_prerenders_. | 950 // this navigation. This requires a resort of active_prerenders_. |
| 973 ScopedVector<PrerenderData>::iterator it = | 951 ScopedVector<PrerenderData>::iterator it = |
| 974 std::find(active_prerenders_.begin(), active_prerenders_.end(), | 952 std::find(active_prerenders_.begin(), active_prerenders_.end(), |
| 975 prerender_data); | 953 prerender_data); |
| 976 if (it == active_prerenders_.end()) | 954 if (it == active_prerenders_.end()) |
| 977 return; | 955 return; |
| 978 | 956 |
| 979 (*it)->set_expiry_time( | 957 (*it)->set_expiry_time( |
| 980 std::min((*it)->expiry_time(), | 958 std::min((*it)->expiry_time(), |
| 981 GetExpiryTimeForNavigatedAwayPrerender())); | 959 GetExpiryTimeForNavigatedAwayPrerender())); |
| 982 SortActivePrerenders(); | 960 SortActivePrerenders(); |
| 983 } | 961 } |
| 984 | 962 |
| 985 void PrerenderManager::DestroyPendingPrerenderData( | |
| 986 PrerenderData* pending_prerender_data) { | |
| 987 ScopedVector<PrerenderData>::iterator it = | |
| 988 std::find(pending_prerenders_.begin(), pending_prerenders_.end(), | |
| 989 pending_prerender_data); | |
| 990 if (it == pending_prerenders_.end()) | |
| 991 return; | |
| 992 pending_prerenders_.erase(it); | |
| 993 } | |
| 994 | |
| 995 // private | 963 // private |
| 996 PrerenderHandle* PrerenderManager::AddPrerender( | 964 PrerenderHandle* PrerenderManager::AddPrerender( |
| 997 Origin origin, | 965 Origin origin, |
| 998 int process_id, | 966 int process_id, |
| 999 const GURL& url_arg, | 967 const GURL& url_arg, |
| 1000 const content::Referrer& referrer, | 968 const content::Referrer& referrer, |
| 1001 const gfx::Size& size, | 969 const gfx::Size& size, |
| 1002 SessionStorageNamespace* session_storage_namespace) { | 970 SessionStorageNamespace* session_storage_namespace) { |
| 1003 DCHECK(CalledOnValidThread()); | 971 DCHECK(CalledOnValidThread()); |
| 1004 | 972 |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1357 if (!render_process_host || !render_process_host->GetBrowserContext()) | 1325 if (!render_process_host || !render_process_host->GetBrowserContext()) |
| 1358 return NULL; | 1326 return NULL; |
| 1359 Profile* profile = Profile::FromBrowserContext( | 1327 Profile* profile = Profile::FromBrowserContext( |
| 1360 render_process_host->GetBrowserContext()); | 1328 render_process_host->GetBrowserContext()); |
| 1361 if (!profile) | 1329 if (!profile) |
| 1362 return NULL; | 1330 return NULL; |
| 1363 return PrerenderManagerFactory::GetInstance()->GetForProfile(profile); | 1331 return PrerenderManagerFactory::GetInstance()->GetForProfile(profile); |
| 1364 } | 1332 } |
| 1365 | 1333 |
| 1366 } // namespace prerender | 1334 } // namespace prerender |
| OLD | NEW |