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

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: clear to land 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 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
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_web_contents_deleters_.clear(); 232 on_close_web_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
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 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 prerender_contents->SetFinalStatus(FINAL_STATUS_USED); 417 prerender_contents->SetFinalStatus(FINAL_STATUS_USED);
423 418
424 RenderViewHost* new_render_view_host = 419 RenderViewHost* new_render_view_host =
425 prerender_contents->prerender_contents()->GetRenderViewHost(); 420 prerender_contents->prerender_contents()->GetRenderViewHost();
426 new_render_view_host->Send( 421 new_render_view_host->Send(
427 new PrerenderMsg_SetIsPrerendering(new_render_view_host->GetRoutingID(), 422 new PrerenderMsg_SetIsPrerendering(new_render_view_host->GetRoutingID(),
428 false)); 423 false));
429 424
430 // Start pending prerender requests from the PrerenderContents, if there are 425 // Start pending prerender requests from the PrerenderContents, if there are
431 // any. 426 // any.
432 prerender_contents->StartPendingPrerenders(); 427 prerender_contents->PrepareForUse();
433 428
434 WebContents* new_web_contents = 429 WebContents* new_web_contents =
435 prerender_contents->ReleasePrerenderContents(); 430 prerender_contents->ReleasePrerenderContents();
436 WebContents* old_web_contents = web_contents; 431 WebContents* old_web_contents = web_contents;
437 DCHECK(new_web_contents); 432 DCHECK(new_web_contents);
438 DCHECK(old_web_contents); 433 DCHECK(old_web_contents);
439 434
440 MarkWebContentsAsPrerendered(new_web_contents, prerender_contents->origin()); 435 MarkWebContentsAsPrerendered(new_web_contents, prerender_contents->origin());
441 436
442 // Merge the browsing history. 437 // Merge the browsing history.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 // for PPLT accounting purposes for the Match Complete group. This is the case 489 // for PPLT accounting purposes for the Match Complete group. This is the case
495 // if the cancellation is for any reason that would not occur in the control 490 // if the cancellation is for any reason that would not occur in the control
496 // group case. 491 // group case.
497 if (entry->prerendering_has_started() && 492 if (entry->prerendering_has_started() &&
498 entry->match_complete_status() == 493 entry->match_complete_status() ==
499 PrerenderContents::MATCH_COMPLETE_DEFAULT && 494 PrerenderContents::MATCH_COMPLETE_DEFAULT &&
500 NeedMatchCompleteDummyForFinalStatus(final_status) && 495 NeedMatchCompleteDummyForFinalStatus(final_status) &&
501 ActuallyPrerendering()) { 496 ActuallyPrerendering()) {
502 // TODO(tburkard): I'd like to DCHECK that we are actually prerendering. 497 // TODO(tburkard): I'd like to DCHECK that we are actually prerendering.
503 // However, what if new conditions are added and 498 // However, what if new conditions are added and
504 // NeedMatchCompleteDummyForFinalStatus, is not being updated. Not sure 499 // NeedMatchCompleteDummyForFinalStatus is not being updated. Not sure
505 // what's the best thing to do here. For now, I will just check whether 500 // what's the best thing to do here. For now, I will just check whether
506 // we are actually prerendering. 501 // we are actually prerendering.
507 (*it)->MakeIntoMatchCompleteReplacement(); 502 (*it)->MakeIntoMatchCompleteReplacement();
508 } else { 503 } else {
509 to_delete_prerenders_.push_back(*it); 504 to_delete_prerenders_.push_back(*it);
510 active_prerenders_.weak_erase(it); 505 active_prerenders_.weak_erase(it);
511 } 506 }
512 507
513 // Destroy the old WebContents relatively promptly to reduce resource usage, 508 // Destroy the old WebContents relatively promptly to reduce resource usage,
514 // and in the case of HTML5 media, reduce the change of playing any sound. 509 // and in the case of HTML5 media, reduce the chance of playing any sound.
515 PostCleanupTask(); 510 PostCleanupTask();
516 } 511 }
517 512
518 // static 513 // static
519 void PrerenderManager::RecordPerceivedPageLoadTime( 514 void PrerenderManager::RecordPerceivedPageLoadTime(
520 base::TimeDelta perceived_page_load_time, 515 base::TimeDelta perceived_page_load_time,
521 double fraction_plt_elapsed_at_swap_in, 516 double fraction_plt_elapsed_at_swap_in,
522 WebContents* web_contents, 517 WebContents* web_contents,
523 const GURL& url) { 518 const GURL& url) {
524 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 519 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
844 CleanUpOldNavigations(); 839 CleanUpOldNavigations();
845 } 840 }
846 841
847 // protected 842 // protected
848 struct PrerenderManager::PrerenderData::OrderByExpiryTime { 843 struct PrerenderManager::PrerenderData::OrderByExpiryTime {
849 bool operator()(const PrerenderData* a, const PrerenderData* b) const { 844 bool operator()(const PrerenderData* a, const PrerenderData* b) const {
850 return a->expiry_time() < b->expiry_time(); 845 return a->expiry_time() < b->expiry_time();
851 } 846 }
852 }; 847 };
853 848
854 PrerenderManager::PrerenderData::PrerenderData(PrerenderManager* manager)
855 : manager_(manager), contents_(NULL), handle_count_(0) {
856 }
857
858 PrerenderManager::PrerenderData::PrerenderData(PrerenderManager* manager, 849 PrerenderManager::PrerenderData::PrerenderData(PrerenderManager* manager,
859 PrerenderContents* contents, 850 PrerenderContents* contents,
860 base::TimeTicks expiry_time) 851 base::TimeTicks expiry_time)
861 : manager_(manager), 852 : manager_(manager),
862 contents_(contents), 853 contents_(contents),
863 handle_count_(0), 854 handle_count_(0),
864 expiry_time_(expiry_time) { 855 expiry_time_(expiry_time) {
856 DCHECK_NE(static_cast<PrerenderContents*>(NULL), contents_);
865 } 857 }
866 858
867 PrerenderManager::PrerenderData::~PrerenderData() { 859 PrerenderManager::PrerenderData::~PrerenderData() {
868 } 860 }
869 861
870 void PrerenderManager::PrerenderData::MakeIntoMatchCompleteReplacement() { 862 void PrerenderManager::PrerenderData::MakeIntoMatchCompleteReplacement() {
871 DCHECK(contents_); 863 DCHECK(contents_);
872 contents_->set_match_complete_status( 864 contents_->set_match_complete_status(
873 PrerenderContents::MATCH_COMPLETE_REPLACED); 865 PrerenderContents::MATCH_COMPLETE_REPLACED);
874 PrerenderData* to_delete = new PrerenderData(manager_, contents_.release(), 866 PrerenderData* to_delete = new PrerenderData(manager_, contents_.release(),
875 expiry_time_); 867 expiry_time_);
876 contents_.reset(to_delete->contents_->CreateMatchCompleteReplacement()); 868 contents_.reset(to_delete->contents_->CreateMatchCompleteReplacement());
877 manager_->to_delete_prerenders_.push_back(to_delete); 869 manager_->to_delete_prerenders_.push_back(to_delete);
878 } 870 }
879 871
880 void PrerenderManager::PrerenderData::OnNewHandle() { 872 void PrerenderManager::PrerenderData::OnHandleCreated(PrerenderHandle* handle) {
881 DCHECK(contents_ || handle_count_ == 0) << 873 DCHECK_NE(static_cast<PrerenderContents*>(NULL), contents_);
882 "Cannot create multiple handles to a pending prerender.";
883 ++handle_count_; 874 ++handle_count_;
875 contents_->AddObserver(handle);
884 } 876 }
885 877
886 void PrerenderManager::PrerenderData::OnNavigateAwayByHandle() { 878 void PrerenderManager::PrerenderData::OnHandleNavigatedAway(
887 if (!contents_) { 879 PrerenderHandle* handle) {
888 DCHECK_EQ(1, handle_count_); 880 DCHECK_LT(0, handle_count_);
889 // Pending prerenders are not maintained in the active_prerenders_, so they 881 DCHECK_NE(static_cast<PrerenderContents*>(NULL), contents_);
890 // will not get normal expiry. Since this prerender hasn't even been 882 // We intentionally don't decrement the handle count here, so that the
891 // launched yet, and it's held by a page that is being prerendered, we will 883 // prerender won't be canceled until it times out.
892 // just delete it. 884 manager_->SourceNavigatedAway(this);
893 manager_->DestroyPendingPrerenderData(this); 885 }
894 } else { 886
895 DCHECK_LE(0, handle_count_); 887 void PrerenderManager::PrerenderData::OnHandleCanceled(
896 // We intentionally don't decrement the handle count here, so that the 888 PrerenderHandle* handle) {
897 // prerender won't be canceled until it times out. 889 DCHECK_LT(0, handle_count_);
898 manager_->SourceNavigatedAway(this); 890 DCHECK_NE(static_cast<PrerenderContents*>(NULL), contents_);
891
892 if (--handle_count_ == 0) {
893 // This will eventually remove this object from active_prerenders_.
894 contents_->Destroy(FINAL_STATUS_CANCELLED);
899 } 895 }
900 } 896 }
901 897
902 void PrerenderManager::PrerenderData::OnCancelByHandle() {
903 DCHECK_LE(1, handle_count_);
904 DCHECK(contents_ || handle_count_ == 1);
905
906 if (--handle_count_ == 0) {
907 if (contents_) {
908 // This will eventually remove this object from active_prerenders_.
909 contents_->Destroy(FINAL_STATUS_CANCELLED);
910 } else {
911 manager_->DestroyPendingPrerenderData(this);
912 }
913 }
914 }
915
916 PrerenderContents* PrerenderManager::PrerenderData::ReleaseContents() { 898 PrerenderContents* PrerenderManager::PrerenderData::ReleaseContents() {
917 return contents_.release(); 899 return contents_.release();
918 } 900 }
919 901
920 void PrerenderManager::SetPrerenderContentsFactory( 902 void PrerenderManager::SetPrerenderContentsFactory(
921 PrerenderContents::Factory* prerender_contents_factory) { 903 PrerenderContents::Factory* prerender_contents_factory) {
922 DCHECK(CalledOnValidThread()); 904 DCHECK(CalledOnValidThread());
923 prerender_contents_factory_.reset(prerender_contents_factory); 905 prerender_contents_factory_.reset(prerender_contents_factory);
924 } 906 }
925 907
926 void PrerenderManager::StartPendingPrerenders( 908 void PrerenderManager::StartPendingPrerenders(
927 const int process_id, 909 const int process_id,
928 ScopedVector<PrerenderContents::PendingPrerenderInfo>* pending_prerenders, 910 ScopedVector<PrerenderContents::PendingPrerenderInfo>* pending_prerenders,
929 content::SessionStorageNamespace* session_storage_namespace) { 911 content::SessionStorageNamespace* session_storage_namespace) {
930 for (ScopedVector<PrerenderContents::PendingPrerenderInfo>::iterator 912 for (ScopedVector<PrerenderContents::PendingPrerenderInfo>::iterator
931 it = pending_prerenders->begin(); 913 it = pending_prerenders->begin();
932 it != pending_prerenders->end(); ++it) { 914 it != pending_prerenders->end(); ++it) {
933 PrerenderContents::PendingPrerenderInfo* info = *it; 915 PrerenderContents::PendingPrerenderInfo* info = *it;
934 PrerenderHandle* existing_prerender_handle = 916 PrerenderHandle* existing_prerender_handle =
935 info->weak_prerender_handle.get(); 917 info->weak_prerender_handle.get();
936 if (!existing_prerender_handle || !existing_prerender_handle->IsValid()) 918 if (!existing_prerender_handle)
937 continue; 919 continue;
938 920
939 DCHECK(existing_prerender_handle->IsPending()); 921 DCHECK(!existing_prerender_handle->IsPrerendering());
940 DCHECK(process_id == -1 || session_storage_namespace); 922 DCHECK(process_id == -1 || session_storage_namespace);
941 923
942 scoped_ptr<PrerenderHandle> swap_prerender_handle(AddPrerender( 924 scoped_ptr<PrerenderHandle> new_prerender_handle(AddPrerender(
943 info->origin, process_id, 925 info->origin, process_id,
944 info->url, info->referrer, info->size, 926 info->url, info->referrer, info->size,
945 session_storage_namespace)); 927 session_storage_namespace));
946 if (swap_prerender_handle.get()) { 928 if (new_prerender_handle) {
947 // AddPrerender has returned a new prerender handle to us. We want to make 929 // AddPrerender has returned a new prerender handle to us. We want to make
948 // |existing_prerender_handle| active, so swap the underlying 930 // |existing_prerender_handle| active, so move the underlying
949 // PrerenderData between the two handles, and delete our old handle (which 931 // PrerenderData to our new handle.
950 // will release our entry in the pending_prerender_list_). 932 existing_prerender_handle->AdoptPrerenderDataFrom(
951 existing_prerender_handle->SwapPrerenderDataWith( 933 new_prerender_handle.get());
952 swap_prerender_handle.get());
953 swap_prerender_handle->OnCancel();
954 continue; 934 continue;
955 } 935 }
956
957 // We could not start our Prerender. Canceling the existing handle will make
958 // it return false for PrerenderHandle::IsPending(), and will release the
959 // PrerenderData from pending_prerender_list_.
960 existing_prerender_handle->OnCancel();
961 } 936 }
962 } 937 }
963 938
964 void PrerenderManager::SourceNavigatedAway(PrerenderData* prerender_data) { 939 void PrerenderManager::SourceNavigatedAway(PrerenderData* prerender_data) {
965 // The expiry time of our prerender data will likely change because of 940 // The expiry time of our prerender data will likely change because of
966 // this navigation. This requires a resort of active_prerenders_. 941 // this navigation. This requires a resort of active_prerenders_.
967 ScopedVector<PrerenderData>::iterator it = 942 ScopedVector<PrerenderData>::iterator it =
968 std::find(active_prerenders_.begin(), active_prerenders_.end(), 943 std::find(active_prerenders_.begin(), active_prerenders_.end(),
969 prerender_data); 944 prerender_data);
970 if (it == active_prerenders_.end()) 945 if (it == active_prerenders_.end())
971 return; 946 return;
972 947
973 (*it)->set_expiry_time( 948 (*it)->set_expiry_time(
974 std::min((*it)->expiry_time(), 949 std::min((*it)->expiry_time(),
975 GetExpiryTimeForNavigatedAwayPrerender())); 950 GetExpiryTimeForNavigatedAwayPrerender()));
976 SortActivePrerenders(); 951 SortActivePrerenders();
977 } 952 }
978 953
979 void PrerenderManager::DestroyPendingPrerenderData(
980 PrerenderData* pending_prerender_data) {
981 ScopedVector<PrerenderData>::iterator it =
982 std::find(pending_prerenders_.begin(), pending_prerenders_.end(),
983 pending_prerender_data);
984 if (it == pending_prerenders_.end())
985 return;
986 pending_prerenders_.erase(it);
987 }
988
989 // private 954 // private
990 PrerenderHandle* PrerenderManager::AddPrerender( 955 PrerenderHandle* PrerenderManager::AddPrerender(
991 Origin origin, 956 Origin origin,
992 int process_id, 957 int process_id,
993 const GURL& url_arg, 958 const GURL& url_arg,
994 const content::Referrer& referrer, 959 const content::Referrer& referrer,
995 const gfx::Size& size, 960 const gfx::Size& size,
996 SessionStorageNamespace* session_storage_namespace) { 961 SessionStorageNamespace* session_storage_namespace) {
997 DCHECK(CalledOnValidThread()); 962 DCHECK(CalledOnValidThread());
998 963
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after
1351 if (!render_process_host || !render_process_host->GetBrowserContext()) 1316 if (!render_process_host || !render_process_host->GetBrowserContext())
1352 return NULL; 1317 return NULL;
1353 Profile* profile = Profile::FromBrowserContext( 1318 Profile* profile = Profile::FromBrowserContext(
1354 render_process_host->GetBrowserContext()); 1319 render_process_host->GetBrowserContext());
1355 if (!profile) 1320 if (!profile)
1356 return NULL; 1321 return NULL;
1357 return PrerenderManagerFactory::GetInstance()->GetForProfile(profile); 1322 return PrerenderManagerFactory::GetInstance()->GetForProfile(profile);
1358 } 1323 }
1359 1324
1360 } // namespace prerender 1325 } // namespace prerender
OLDNEW
« no previous file with comments | « chrome/browser/prerender/prerender_manager.h ('k') | chrome/browser/prerender/prerender_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698