Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(423)

Side by Side Diff: chrome/browser/prerender/prerender_manager.cc

Issue 11316311: Make PrerenderHandle an observer of PrerenderContents. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: prerender tracker test fix Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698