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 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
424 | 419 |
425 RenderViewHost* new_render_view_host = | 420 RenderViewHost* new_render_view_host = |
426 prerender_contents->prerender_contents()->web_contents()-> | 421 prerender_contents->prerender_contents()->web_contents()-> |
427 GetRenderViewHost(); | 422 GetRenderViewHost(); |
428 new_render_view_host->Send( | 423 new_render_view_host->Send( |
429 new PrerenderMsg_SetIsPrerendering(new_render_view_host->GetRoutingID(), | 424 new PrerenderMsg_SetIsPrerendering(new_render_view_host->GetRoutingID(), |
430 false)); | 425 false)); |
431 | 426 |
432 // Start pending prerender requests from the PrerenderContents, if there are | 427 // Start pending prerender requests from the PrerenderContents, if there are |
433 // any. | 428 // any. |
434 prerender_contents->StartPendingPrerenders(); | 429 prerender_contents->PrepareForUse(); |
435 | 430 |
436 TabContents* new_tab_contents = | 431 TabContents* new_tab_contents = |
437 prerender_contents->ReleasePrerenderContents(); | 432 prerender_contents->ReleasePrerenderContents(); |
438 TabContents* old_tab_contents = TabContents::FromWebContents(web_contents); | 433 TabContents* old_tab_contents = TabContents::FromWebContents(web_contents); |
439 DCHECK(new_tab_contents); | 434 DCHECK(new_tab_contents); |
440 DCHECK(old_tab_contents); | 435 DCHECK(old_tab_contents); |
441 | 436 |
442 MarkWebContentsAsPrerendered(new_tab_contents->web_contents(), | 437 MarkWebContentsAsPrerendered(new_tab_contents->web_contents(), |
443 prerender_contents->origin()); | 438 prerender_contents->origin()); |
444 | 439 |
(...skipping 405 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::OnHandleCreated(PrerenderHandle* handle) { |
887 DCHECK(contents_ || handle_count_ == 0) << | |
888 "Cannot create multiple handles to a pending prerender."; | |
889 ++handle_count_; | 878 ++handle_count_; |
879 DCHECK_NE(static_cast<PrerenderContents*>(NULL), contents_); | |
mmenke
2012/12/12 16:54:12
nit: DCHECKs are generally put at the start of fu
mmenke
2012/12/12 16:54:12
May want to put one of these in the constructor as
gavinp
2012/12/13 13:38:03
Done & Done.
| |
880 contents_->AddObserver(handle); | |
890 } | 881 } |
891 | 882 |
892 void PrerenderManager::PrerenderData::OnNavigateAwayByHandle() { | 883 void PrerenderManager::PrerenderData::OnHandleNavigatedAway( |
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 DCHECK_NE(static_cast<PrerenderContents*>(NULL), contents_); |
896 // will not get normal expiry. Since this prerender hasn't even been | 887 // We intentionally don't decrement the handle count here, so that the |
897 // launched yet, and it's held by a page that is being prerendered, we will | 888 // prerender won't be canceled until it times out. |
898 // just delete it. | 889 manager_->SourceNavigatedAway(this); |
899 manager_->DestroyPendingPrerenderData(this); | 890 } |
900 } else { | 891 |
901 DCHECK_LE(0, handle_count_); | 892 void PrerenderManager::PrerenderData::OnHandleCanceled( |
902 // We intentionally don't decrement the handle count here, so that the | 893 PrerenderHandle* handle) { |
903 // prerender won't be canceled until it times out. | 894 DCHECK_LE(1, handle_count_); |
904 manager_->SourceNavigatedAway(this); | 895 DCHECK_NE(static_cast<PrerenderContents*>(NULL), contents_); |
896 | |
897 if (--handle_count_ == 0) { | |
898 // This will eventually remove this object from active_prerenders_. | |
899 contents_->Destroy(FINAL_STATUS_CANCELLED); | |
905 } | 900 } |
906 } | 901 } |
907 | 902 |
908 void PrerenderManager::PrerenderData::OnCancelByHandle() { | |
909 DCHECK_LE(1, handle_count_); | |
910 DCHECK(contents_ || handle_count_ == 1); | |
911 | |
912 if (--handle_count_ == 0) { | |
913 if (contents_) { | |
914 // This will eventually remove this object from active_prerenders_. | |
915 contents_->Destroy(FINAL_STATUS_CANCELLED); | |
916 } else { | |
917 manager_->DestroyPendingPrerenderData(this); | |
918 } | |
919 } | |
920 } | |
921 | |
922 PrerenderContents* PrerenderManager::PrerenderData::ReleaseContents() { | 903 PrerenderContents* PrerenderManager::PrerenderData::ReleaseContents() { |
923 return contents_.release(); | 904 return contents_.release(); |
924 } | 905 } |
925 | 906 |
926 void PrerenderManager::SetPrerenderContentsFactory( | 907 void PrerenderManager::SetPrerenderContentsFactory( |
927 PrerenderContents::Factory* prerender_contents_factory) { | 908 PrerenderContents::Factory* prerender_contents_factory) { |
928 DCHECK(CalledOnValidThread()); | 909 DCHECK(CalledOnValidThread()); |
929 prerender_contents_factory_.reset(prerender_contents_factory); | 910 prerender_contents_factory_.reset(prerender_contents_factory); |
930 } | 911 } |
931 | 912 |
932 void PrerenderManager::StartPendingPrerenders( | 913 void PrerenderManager::StartPendingPrerenders( |
933 const int process_id, | 914 const int process_id, |
934 ScopedVector<PrerenderContents::PendingPrerenderInfo>* pending_prerenders, | 915 ScopedVector<PrerenderContents::PendingPrerenderInfo>* pending_prerenders, |
935 content::SessionStorageNamespace* session_storage_namespace) { | 916 content::SessionStorageNamespace* session_storage_namespace) { |
936 for (ScopedVector<PrerenderContents::PendingPrerenderInfo>::iterator | 917 for (ScopedVector<PrerenderContents::PendingPrerenderInfo>::iterator |
937 it = pending_prerenders->begin(); | 918 it = pending_prerenders->begin(); |
938 it != pending_prerenders->end(); ++it) { | 919 it != pending_prerenders->end(); ++it) { |
939 PrerenderContents::PendingPrerenderInfo* info = *it; | 920 PrerenderContents::PendingPrerenderInfo* info = *it; |
940 PrerenderHandle* existing_prerender_handle = | 921 PrerenderHandle* existing_prerender_handle = |
941 info->weak_prerender_handle.get(); | 922 info->weak_prerender_handle.get(); |
942 if (!existing_prerender_handle || !existing_prerender_handle->IsValid()) | 923 if (!existing_prerender_handle) |
924 continue; | |
925 if (existing_prerender_handle->has_been_canceled()) | |
mmenke
2012/12/12 16:54:12
Since we delete handles when cancelled, and don't
gavinp
2012/12/13 13:38:03
I think that's a good idea. It simplifies the hand
| |
943 continue; | 926 continue; |
944 | 927 |
945 DCHECK(existing_prerender_handle->IsPending()); | 928 DCHECK(!existing_prerender_handle->IsPrerendering()); |
946 DCHECK(process_id == -1 || session_storage_namespace); | 929 DCHECK(process_id == -1 || session_storage_namespace); |
947 | 930 |
948 scoped_ptr<PrerenderHandle> swap_prerender_handle(AddPrerender( | 931 scoped_ptr<PrerenderHandle> new_prerender_handle(AddPrerender( |
949 info->origin, process_id, | 932 info->origin, process_id, |
950 info->url, info->referrer, info->size, | 933 info->url, info->referrer, info->size, |
951 session_storage_namespace)); | 934 session_storage_namespace)); |
952 if (swap_prerender_handle.get()) { | 935 if (new_prerender_handle) { |
953 // 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 |
954 // |existing_prerender_handle| active, so swap the underlying | 937 // |existing_prerender_handle| active, so move the underlying |
955 // PrerenderData between the two handles, and delete our old handle (which | 938 // PrerenderData to our new handle. |
956 // will release our entry in the pending_prerender_list_). | 939 existing_prerender_handle->AdoptPrerenderDataFrom( |
957 existing_prerender_handle->SwapPrerenderDataWith( | 940 new_prerender_handle.get()); |
958 swap_prerender_handle.get()); | |
959 swap_prerender_handle->OnCancel(); | |
960 continue; | 941 continue; |
961 } | 942 } |
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 } | 943 } |
968 } | 944 } |
969 | 945 |
970 void PrerenderManager::SourceNavigatedAway(PrerenderData* prerender_data) { | 946 void PrerenderManager::SourceNavigatedAway(PrerenderData* prerender_data) { |
971 // 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 |
972 // this navigation. This requires a resort of active_prerenders_. | 948 // this navigation. This requires a resort of active_prerenders_. |
973 ScopedVector<PrerenderData>::iterator it = | 949 ScopedVector<PrerenderData>::iterator it = |
974 std::find(active_prerenders_.begin(), active_prerenders_.end(), | 950 std::find(active_prerenders_.begin(), active_prerenders_.end(), |
975 prerender_data); | 951 prerender_data); |
976 if (it == active_prerenders_.end()) | 952 if (it == active_prerenders_.end()) |
977 return; | 953 return; |
978 | 954 |
979 (*it)->set_expiry_time( | 955 (*it)->set_expiry_time( |
980 std::min((*it)->expiry_time(), | 956 std::min((*it)->expiry_time(), |
981 GetExpiryTimeForNavigatedAwayPrerender())); | 957 GetExpiryTimeForNavigatedAwayPrerender())); |
982 SortActivePrerenders(); | 958 SortActivePrerenders(); |
983 } | 959 } |
984 | 960 |
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 | 961 // private |
996 PrerenderHandle* PrerenderManager::AddPrerender( | 962 PrerenderHandle* PrerenderManager::AddPrerender( |
997 Origin origin, | 963 Origin origin, |
998 int process_id, | 964 int process_id, |
999 const GURL& url_arg, | 965 const GURL& url_arg, |
1000 const content::Referrer& referrer, | 966 const content::Referrer& referrer, |
1001 const gfx::Size& size, | 967 const gfx::Size& size, |
1002 SessionStorageNamespace* session_storage_namespace) { | 968 SessionStorageNamespace* session_storage_namespace) { |
1003 DCHECK(CalledOnValidThread()); | 969 DCHECK(CalledOnValidThread()); |
1004 | 970 |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1357 if (!render_process_host || !render_process_host->GetBrowserContext()) | 1323 if (!render_process_host || !render_process_host->GetBrowserContext()) |
1358 return NULL; | 1324 return NULL; |
1359 Profile* profile = Profile::FromBrowserContext( | 1325 Profile* profile = Profile::FromBrowserContext( |
1360 render_process_host->GetBrowserContext()); | 1326 render_process_host->GetBrowserContext()); |
1361 if (!profile) | 1327 if (!profile) |
1362 return NULL; | 1328 return NULL; |
1363 return PrerenderManagerFactory::GetInstance()->GetForProfile(profile); | 1329 return PrerenderManagerFactory::GetInstance()->GetForProfile(profile); |
1364 } | 1330 } |
1365 | 1331 |
1366 } // namespace prerender | 1332 } // namespace prerender |
OLD | NEW |