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 |