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 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
216 break; | 216 break; |
217 default: | 217 default: |
218 break; | 218 break; |
219 } | 219 } |
220 } | 220 } |
221 | 221 |
222 PrerenderManager::~PrerenderManager() { | 222 PrerenderManager::~PrerenderManager() { |
223 // The earlier call to ProfileKeyedService::Shutdown() should have emptied | 223 // The earlier call to ProfileKeyedService::Shutdown() should have emptied |
224 // these vectors already. | 224 // these vectors already. |
225 DCHECK(active_prerenders_.empty()); | 225 DCHECK(active_prerenders_.empty()); |
226 DCHECK(pending_prerenders_.empty()); | |
227 DCHECK(to_delete_prerenders_.empty()); | 226 DCHECK(to_delete_prerenders_.empty()); |
228 } | 227 } |
229 | 228 |
230 void PrerenderManager::Shutdown() { | 229 void PrerenderManager::Shutdown() { |
231 DestroyAllContents(FINAL_STATUS_MANAGER_SHUTDOWN); | 230 DestroyAllContents(FINAL_STATUS_MANAGER_SHUTDOWN); |
232 STLDeleteElements(&prerender_conditions_); | 231 STLDeleteElements(&prerender_conditions_); |
233 on_close_tab_contents_deleters_.clear(); | 232 on_close_tab_contents_deleters_.clear(); |
234 // Must happen before |profile_| is set to NULL as | 233 // Must happen before |profile_| is set to NULL as |
235 // |local_predictor_| accesses it. | 234 // |local_predictor_| accesses it. |
236 if (local_predictor_) | 235 if (local_predictor_) |
237 local_predictor_->Shutdown(); | 236 local_predictor_->Shutdown(); |
238 profile_ = NULL; | 237 profile_ = NULL; |
239 | 238 |
240 DCHECK(active_prerenders_.empty()); | 239 DCHECK(active_prerenders_.empty()); |
241 pending_prerenders_.clear(); | |
242 } | 240 } |
243 | 241 |
244 PrerenderHandle* PrerenderManager::AddPrerenderFromLinkRelPrerender( | 242 PrerenderHandle* PrerenderManager::AddPrerenderFromLinkRelPrerender( |
245 int process_id, | 243 int process_id, |
246 int route_id, | 244 int route_id, |
247 const GURL& url, | 245 const GURL& url, |
248 const content::Referrer& referrer, | 246 const content::Referrer& referrer, |
249 const gfx::Size& size) { | 247 const gfx::Size& size) { |
250 #if defined(OS_ANDROID) | 248 #if defined(OS_ANDROID) |
251 // TODO(jcivelli): http://crbug.com/113322 We should have an option to disable | 249 // TODO(jcivelli): http://crbug.com/113322 We should have an option to disable |
(...skipping 19 matching lines...) Expand all Loading... | |
271 session_storage_namespace = | 269 session_storage_namespace = |
272 source_web_contents->GetController() | 270 source_web_contents->GetController() |
273 .GetDefaultSessionStorageNamespace(); | 271 .GetDefaultSessionStorageNamespace(); |
274 } | 272 } |
275 | 273 |
276 if (PrerenderData* parent_prerender_data = | 274 if (PrerenderData* parent_prerender_data = |
277 FindPrerenderDataForChildAndRoute(process_id, route_id)) { | 275 FindPrerenderDataForChildAndRoute(process_id, route_id)) { |
278 // Instead of prerendering from inside of a running prerender, we will defer | 276 // Instead of prerendering from inside of a running prerender, we will defer |
279 // this request until its launcher is made visible. | 277 // this request until its launcher is made visible. |
280 if (PrerenderContents* contents = parent_prerender_data->contents()) { | 278 if (PrerenderContents* contents = parent_prerender_data->contents()) { |
281 pending_prerenders_.push_back(new PrerenderData(this)); | |
282 PrerenderHandle* prerender_handle = | 279 PrerenderHandle* prerender_handle = |
283 new PrerenderHandle(pending_prerenders_.back()); | 280 new PrerenderHandle(static_cast<PrerenderData*>(NULL)); |
284 DCHECK(prerender_handle->IsPending()); | |
285 | |
286 scoped_ptr<PrerenderContents::PendingPrerenderInfo> | 281 scoped_ptr<PrerenderContents::PendingPrerenderInfo> |
287 pending_prerender_info(new PrerenderContents::PendingPrerenderInfo( | 282 pending_prerender_info(new PrerenderContents::PendingPrerenderInfo( |
288 prerender_handle->weak_ptr_factory_.GetWeakPtr(), | 283 prerender_handle->weak_ptr_factory_.GetWeakPtr(), |
289 origin, url, referrer, size)); | 284 origin, url, referrer, size)); |
290 | 285 |
291 contents->AddPendingPrerender(pending_prerender_info.Pass()); | 286 contents->AddPendingPrerender(pending_prerender_info.Pass()); |
292 return prerender_handle; | 287 return prerender_handle; |
293 } | 288 } |
294 } | 289 } |
295 | 290 |
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
848 CleanUpOldNavigations(); | 843 CleanUpOldNavigations(); |
849 } | 844 } |
850 | 845 |
851 // protected | 846 // protected |
852 struct PrerenderManager::PrerenderData::OrderByExpiryTime { | 847 struct PrerenderManager::PrerenderData::OrderByExpiryTime { |
853 bool operator()(const PrerenderData* a, const PrerenderData* b) const { | 848 bool operator()(const PrerenderData* a, const PrerenderData* b) const { |
854 return a->expiry_time() < b->expiry_time(); | 849 return a->expiry_time() < b->expiry_time(); |
855 } | 850 } |
856 }; | 851 }; |
857 | 852 |
858 PrerenderManager::PrerenderData::PrerenderData(PrerenderManager* manager) | |
859 : manager_(manager), contents_(NULL), handle_count_(0) { | |
860 } | |
861 | |
862 PrerenderManager::PrerenderData::PrerenderData(PrerenderManager* manager, | 853 PrerenderManager::PrerenderData::PrerenderData(PrerenderManager* manager, |
863 PrerenderContents* contents, | 854 PrerenderContents* contents, |
864 base::TimeTicks expiry_time) | 855 base::TimeTicks expiry_time) |
865 : manager_(manager), | 856 : manager_(manager), |
866 contents_(contents), | 857 contents_(contents), |
867 handle_count_(0), | 858 handle_count_(0), |
868 expiry_time_(expiry_time) { | 859 expiry_time_(expiry_time) { |
869 } | 860 } |
870 | 861 |
871 PrerenderManager::PrerenderData::~PrerenderData() { | 862 PrerenderManager::PrerenderData::~PrerenderData() { |
872 } | 863 } |
873 | 864 |
874 void PrerenderManager::PrerenderData::MakeIntoMatchCompleteReplacement() { | 865 void PrerenderManager::PrerenderData::MakeIntoMatchCompleteReplacement() { |
875 DCHECK(contents_); | 866 DCHECK(contents_); |
876 contents_->set_match_complete_status( | 867 contents_->set_match_complete_status( |
877 PrerenderContents::MATCH_COMPLETE_REPLACED); | 868 PrerenderContents::MATCH_COMPLETE_REPLACED); |
878 PrerenderData* to_delete = new PrerenderData(manager_, contents_.release(), | 869 PrerenderData* to_delete = new PrerenderData(manager_, contents_.release(), |
879 expiry_time_); | 870 expiry_time_); |
880 contents_.reset(to_delete->contents_->CreateMatchCompleteReplacement()); | 871 contents_.reset(to_delete->contents_->CreateMatchCompleteReplacement()); |
881 manager_->to_delete_prerenders_.push_back(to_delete); | 872 manager_->to_delete_prerenders_.push_back(to_delete); |
882 } | 873 } |
883 | 874 |
884 void PrerenderManager::PrerenderData::OnNewHandle() { | 875 void PrerenderManager::PrerenderData::OnNewHandle(PrerenderHandle* handle) { |
885 DCHECK(contents_ || handle_count_ == 0) << | |
886 "Cannot create multiple handles to a pending prerender."; | |
887 ++handle_count_; | 876 ++handle_count_; |
877 if (contents_) | |
mmenke
2012/12/06 22:22:15
contents_ can no longer be null.
gavinp
2012/12/10 17:55:10
Done.
| |
878 contents_->AddObserver(handle); | |
888 } | 879 } |
889 | 880 |
890 void PrerenderManager::PrerenderData::OnNavigateAwayByHandle() { | 881 void PrerenderManager::PrerenderData::OnNavigateAwayByHandle( |
891 if (!contents_) { | 882 PrerenderHandle* handle) { |
892 DCHECK_EQ(1, handle_count_); | 883 DCHECK_LT(0, handle_count_); |
893 // Pending prerenders are not maintained in the active_prerenders_, so they | 884 // We intentionally don't decrement the handle count here, so that the |
894 // will not get normal expiry. Since this prerender hasn't even been | 885 // prerender won't be canceled until it times out. |
895 // launched yet, and it's held by a page that is being prerendered, we will | 886 manager_->SourceNavigatedAway(this); |
896 // just delete it. | |
897 manager_->DestroyPendingPrerenderData(this); | |
898 } else { | |
899 DCHECK_LE(0, handle_count_); | |
900 // We intentionally don't decrement the handle count here, so that the | |
901 // prerender won't be canceled until it times out. | |
902 manager_->SourceNavigatedAway(this); | |
903 } | |
904 } | 887 } |
905 | 888 |
906 void PrerenderManager::PrerenderData::OnCancelByHandle() { | 889 void PrerenderManager::PrerenderData::OnCancelByHandle( |
890 PrerenderHandle* handle) { | |
mmenke
2012/12/06 22:22:15
Why do we need the handle here? Just for consiste
gavinp
2012/12/10 17:55:10
Just for consistency.
| |
907 DCHECK_LE(1, handle_count_); | 891 DCHECK_LE(1, handle_count_); |
908 DCHECK(contents_ || handle_count_ == 1); | 892 DCHECK(contents_ || handle_count_ == 1) |
893 << "Pending prerenders should never have multiple prerenders"; | |
909 | 894 |
910 if (--handle_count_ == 0) { | 895 if (--handle_count_ == 0) { |
911 if (contents_) { | 896 if (contents_) { |
mmenke
2012/12/06 22:22:15
contents_ can't be null.
gavinp
2012/12/10 17:55:10
Done.
| |
912 // This will eventually remove this object from active_prerenders_. | 897 // This will eventually remove this object from active_prerenders_. |
913 contents_->Destroy(FINAL_STATUS_CANCELLED); | 898 contents_->Destroy(FINAL_STATUS_CANCELLED); |
914 } else { | |
915 manager_->DestroyPendingPrerenderData(this); | |
916 } | 899 } |
917 } | 900 } |
918 } | 901 } |
919 | 902 |
920 PrerenderContents* PrerenderManager::PrerenderData::ReleaseContents() { | 903 PrerenderContents* PrerenderManager::PrerenderData::ReleaseContents() { |
921 return contents_.release(); | 904 return contents_.release(); |
922 } | 905 } |
923 | 906 |
924 void PrerenderManager::SetPrerenderContentsFactory( | 907 void PrerenderManager::SetPrerenderContentsFactory( |
925 PrerenderContents::Factory* prerender_contents_factory) { | 908 PrerenderContents::Factory* prerender_contents_factory) { |
926 DCHECK(CalledOnValidThread()); | 909 DCHECK(CalledOnValidThread()); |
927 prerender_contents_factory_.reset(prerender_contents_factory); | 910 prerender_contents_factory_.reset(prerender_contents_factory); |
928 } | 911 } |
929 | 912 |
930 void PrerenderManager::StartPendingPrerenders( | 913 void PrerenderManager::StartPendingPrerenders( |
931 const int process_id, | 914 const int process_id, |
932 ScopedVector<PrerenderContents::PendingPrerenderInfo>* pending_prerenders, | 915 ScopedVector<PrerenderContents::PendingPrerenderInfo>* pending_prerenders, |
933 content::SessionStorageNamespace* session_storage_namespace) { | 916 content::SessionStorageNamespace* session_storage_namespace) { |
934 for (ScopedVector<PrerenderContents::PendingPrerenderInfo>::iterator | 917 for (ScopedVector<PrerenderContents::PendingPrerenderInfo>::iterator |
935 it = pending_prerenders->begin(); | 918 it = pending_prerenders->begin(); |
936 it != pending_prerenders->end(); ++it) { | 919 it != pending_prerenders->end(); ++it) { |
937 PrerenderContents::PendingPrerenderInfo* info = *it; | 920 PrerenderContents::PendingPrerenderInfo* info = *it; |
938 PrerenderHandle* existing_prerender_handle = | 921 PrerenderHandle* existing_prerender_handle = |
939 info->weak_prerender_handle.get(); | 922 info->weak_prerender_handle.get(); |
940 if (!existing_prerender_handle || !existing_prerender_handle->IsValid()) | 923 if (!existing_prerender_handle) |
924 continue; | |
925 if (existing_prerender_handle->has_been_canceled()) | |
941 continue; | 926 continue; |
942 | 927 |
943 DCHECK(existing_prerender_handle->IsPending()); | 928 DCHECK(!existing_prerender_handle->IsValid()); |
944 DCHECK(process_id == -1 || session_storage_namespace); | 929 DCHECK(process_id == -1 || session_storage_namespace); |
945 | 930 |
946 scoped_ptr<PrerenderHandle> swap_prerender_handle(AddPrerender( | 931 scoped_ptr<PrerenderHandle> new_prerender_handle(AddPrerender( |
947 info->origin, process_id, | 932 info->origin, process_id, |
948 info->url, info->referrer, info->size, | 933 info->url, info->referrer, info->size, |
949 session_storage_namespace)); | 934 session_storage_namespace)); |
mmenke
2012/12/07 16:46:08
optional (Or feel free to think about in a later C
gavinp
2012/12/10 17:55:10
Definitely a good idea, and I'm definitely punting
| |
950 if (swap_prerender_handle.get()) { | 935 if (new_prerender_handle.get()) { |
mmenke
2012/12/07 16:46:08
nit: Can remove the .get() while you're here.
gavinp
2012/12/10 17:55:10
enne is Awesome! Done.
| |
951 // AddPrerender has returned a new prerender handle to us. We want to make | 936 // AddPrerender has returned a new prerender handle to us. We want to make |
952 // |existing_prerender_handle| active, so swap the underlying | 937 // |existing_prerender_handle| active, so move the underlying |
953 // PrerenderData between the two handles, and delete our old handle (which | 938 // PrerenderData to our new handle. |
954 // will release our entry in the pending_prerender_list_). | 939 existing_prerender_handle->AdoptPrerenderDataFrom( |
955 existing_prerender_handle->SwapPrerenderDataWith( | 940 new_prerender_handle.get()); |
956 swap_prerender_handle.get()); | |
957 swap_prerender_handle->OnCancel(); | |
958 continue; | 941 continue; |
959 } | 942 } |
mmenke
2012/12/07 16:46:08
Random comment for the future - if a prerender is
gavinp
2012/12/13 13:38:03
I'm going to go with no. The launcher has no promi
| |
960 | |
961 // We could not start our Prerender. Canceling the existing handle will make | |
962 // it return false for PrerenderHandle::IsPending(), and will release the | |
963 // PrerenderData from pending_prerender_list_. | |
964 existing_prerender_handle->OnCancel(); | |
965 } | 943 } |
966 } | 944 } |
967 | 945 |
968 void PrerenderManager::SourceNavigatedAway(PrerenderData* prerender_data) { | 946 void PrerenderManager::SourceNavigatedAway(PrerenderData* prerender_data) { |
969 // The expiry time of our prerender data will likely change because of | 947 // The expiry time of our prerender data will likely change because of |
970 // this navigation. This requires a resort of active_prerenders_. | 948 // this navigation. This requires a resort of active_prerenders_. |
971 ScopedVector<PrerenderData>::iterator it = | 949 ScopedVector<PrerenderData>::iterator it = |
972 std::find(active_prerenders_.begin(), active_prerenders_.end(), | 950 std::find(active_prerenders_.begin(), active_prerenders_.end(), |
973 prerender_data); | 951 prerender_data); |
974 if (it == active_prerenders_.end()) | 952 if (it == active_prerenders_.end()) |
975 return; | 953 return; |
976 | 954 |
977 (*it)->set_expiry_time( | 955 (*it)->set_expiry_time( |
978 std::min((*it)->expiry_time(), | 956 std::min((*it)->expiry_time(), |
979 GetExpiryTimeForNavigatedAwayPrerender())); | 957 GetExpiryTimeForNavigatedAwayPrerender())); |
980 SortActivePrerenders(); | 958 SortActivePrerenders(); |
981 } | 959 } |
982 | 960 |
983 void PrerenderManager::DestroyPendingPrerenderData( | |
984 PrerenderData* pending_prerender_data) { | |
985 ScopedVector<PrerenderData>::iterator it = | |
986 std::find(pending_prerenders_.begin(), pending_prerenders_.end(), | |
987 pending_prerender_data); | |
988 if (it == pending_prerenders_.end()) | |
989 return; | |
990 pending_prerenders_.erase(it); | |
991 } | |
992 | |
993 // private | 961 // private |
994 PrerenderHandle* PrerenderManager::AddPrerender( | 962 PrerenderHandle* PrerenderManager::AddPrerender( |
995 Origin origin, | 963 Origin origin, |
996 int process_id, | 964 int process_id, |
997 const GURL& url_arg, | 965 const GURL& url_arg, |
998 const content::Referrer& referrer, | 966 const content::Referrer& referrer, |
999 const gfx::Size& size, | 967 const gfx::Size& size, |
1000 SessionStorageNamespace* session_storage_namespace) { | 968 SessionStorageNamespace* session_storage_namespace) { |
1001 DCHECK(CalledOnValidThread()); | 969 DCHECK(CalledOnValidThread()); |
1002 | 970 |
(...skipping 354 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 |