| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <functional> | 10 #include <functional> |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 | 168 |
| 169 PrerenderManager::PrerenderManager(Profile* profile) | 169 PrerenderManager::PrerenderManager(Profile* profile) |
| 170 : profile_(profile), | 170 : profile_(profile), |
| 171 prerender_contents_factory_(PrerenderContents::CreateFactory()), | 171 prerender_contents_factory_(PrerenderContents::CreateFactory()), |
| 172 prerender_history_(new PrerenderHistory(kHistoryLength)), | 172 prerender_history_(new PrerenderHistory(kHistoryLength)), |
| 173 histograms_(new PrerenderHistograms()), | 173 histograms_(new PrerenderHistograms()), |
| 174 profile_network_bytes_(0), | 174 profile_network_bytes_(0), |
| 175 last_recorded_profile_network_bytes_(0), | 175 last_recorded_profile_network_bytes_(0), |
| 176 clock_(new base::DefaultClock()), | 176 clock_(new base::DefaultClock()), |
| 177 tick_clock_(new base::DefaultTickClock()), | 177 tick_clock_(new base::DefaultTickClock()), |
| 178 page_load_metric_observer_disabled_(false), |
| 178 weak_factory_(this) { | 179 weak_factory_(this) { |
| 179 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 180 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 180 | 181 |
| 181 last_prerender_start_time_ = | 182 last_prerender_start_time_ = |
| 182 GetCurrentTimeTicks() - | 183 GetCurrentTimeTicks() - |
| 183 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs); | 184 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs); |
| 184 | 185 |
| 185 notification_registrar_.Add( | 186 notification_registrar_.Add( |
| 186 this, chrome::NOTIFICATION_PROFILE_DESTROYED, | 187 this, chrome::NOTIFICATION_PROFILE_DESTROYED, |
| 187 content::Source<Profile>(profile_)); | 188 content::Source<Profile>(profile_)); |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 is_redirect, is_no_store); | 560 is_redirect, is_no_store); |
| 560 } | 561 } |
| 561 | 562 |
| 562 void PrerenderManager::RecordPrefetchRedirectCount(Origin origin, | 563 void PrerenderManager::RecordPrefetchRedirectCount(Origin origin, |
| 563 bool is_main_resource, | 564 bool is_main_resource, |
| 564 int redirect_count) { | 565 int redirect_count) { |
| 565 histograms_->RecordPrefetchRedirectCount(origin, is_main_resource, | 566 histograms_->RecordPrefetchRedirectCount(origin, is_main_resource, |
| 566 redirect_count); | 567 redirect_count); |
| 567 } | 568 } |
| 568 | 569 |
| 569 void PrerenderManager::RecordFirstContentfulPaint(const GURL& url, | 570 void PrerenderManager::RecordNoStateFirstContentfulPaint(const GURL& url, |
| 570 bool is_no_store, | 571 bool is_no_store, |
| 571 base::TimeDelta time) { | 572 bool was_hidden, |
| 572 CleanUpOldNavigations(&prefetches_, base::TimeDelta::FromMinutes(30)); | 573 base::TimeDelta time) { |
| 574 base::TimeDelta prefetch_age; |
| 575 Origin origin; |
| 576 GetPrefetchInformation(url, &prefetch_age, &origin); |
| 573 | 577 |
| 574 // Compute the prefetch age. | 578 histograms_->RecordPrefetchFirstContentfulPaintTime( |
| 579 origin, is_no_store, was_hidden, time, prefetch_age); |
| 580 |
| 581 for (auto& observer : observers_) { |
| 582 observer->OnFirstContentfulPaint(); |
| 583 } |
| 584 } |
| 585 |
| 586 void PrerenderManager::RecordPrerenderFirstContentfulPaint( |
| 587 const GURL& url, |
| 588 content::WebContents* web_contents, |
| 589 bool is_no_store, |
| 590 bool was_hidden, |
| 591 base::TimeTicks first_contentful_paint) { |
| 592 PrerenderTabHelper* tab_helper = |
| 593 PrerenderTabHelper::FromWebContents(web_contents); |
| 594 DCHECK(tab_helper); |
| 595 |
| 575 base::TimeDelta prefetch_age; | 596 base::TimeDelta prefetch_age; |
| 576 Origin origin = ORIGIN_NONE; | 597 // The prefetch origin may not be relevant to the prerender. |
| 577 for (auto it = prefetches_.crbegin(); it != prefetches_.crend(); ++it) { | 598 Origin unused_origin; |
| 578 if (it->url == url) { | 599 GetPrefetchInformation(url, &prefetch_age, &unused_origin); |
| 579 prefetch_age = GetCurrentTimeTicks() - it->time; | 600 |
| 580 origin = it->origin; | 601 base::TimeTicks last_swap = tab_helper->last_swap(); |
| 581 break; | 602 if (!last_swap.is_null() && !first_contentful_paint.is_null()) { |
| 582 } | 603 histograms_->RecordPrefetchFirstContentfulPaintTime( |
| 604 tab_helper->origin(), is_no_store, was_hidden, |
| 605 first_contentful_paint - last_swap, prefetch_age); |
| 606 histograms_->RecordPerceivedFirstContentfulPaintStatus(tab_helper->origin(), |
| 607 true, was_hidden); |
| 608 } else { |
| 609 histograms_->RecordPerceivedFirstContentfulPaintStatus(tab_helper->origin(), |
| 610 false, was_hidden); |
| 583 } | 611 } |
| 584 | 612 |
| 585 histograms_->RecordFirstContentfulPaint(origin, is_no_store, time, | 613 for (auto& observer : observers_) { |
| 586 prefetch_age); | 614 observer->OnFirstContentfulPaint(); |
| 587 | 615 } |
| 588 // Loading a prefetched URL resets the revalidation bypass. Remove the url | |
| 589 // from the prefetch list for more accurate metrics. | |
| 590 prefetches_.erase( | |
| 591 std::remove_if(prefetches_.begin(), prefetches_.end(), | |
| 592 [url](const NavigationRecord& r) { return r.url == url; }), | |
| 593 prefetches_.end()); | |
| 594 } | 616 } |
| 595 | 617 |
| 596 // static | 618 // static |
| 597 PrerenderManager::PrerenderManagerMode PrerenderManager::GetMode() { | 619 PrerenderManager::PrerenderManagerMode PrerenderManager::GetMode() { |
| 598 return mode_; | 620 return mode_; |
| 599 } | 621 } |
| 600 | 622 |
| 601 // static | 623 // static |
| 602 void PrerenderManager::SetMode(PrerenderManagerMode mode) { | 624 void PrerenderManager::SetMode(PrerenderManagerMode mode) { |
| 603 mode_ = mode; | 625 mode_ = mode; |
| (...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1032 base::ElapsedTimer cleanup_timer; | 1054 base::ElapsedTimer cleanup_timer; |
| 1033 | 1055 |
| 1034 // Perform deferred cleanup work. | 1056 // Perform deferred cleanup work. |
| 1035 DeleteOldWebContents(); | 1057 DeleteOldWebContents(); |
| 1036 DeleteOldEntries(); | 1058 DeleteOldEntries(); |
| 1037 if (active_prerenders_.empty()) | 1059 if (active_prerenders_.empty()) |
| 1038 StopSchedulingPeriodicCleanups(); | 1060 StopSchedulingPeriodicCleanups(); |
| 1039 | 1061 |
| 1040 to_delete_prerenders_.clear(); | 1062 to_delete_prerenders_.clear(); |
| 1041 | 1063 |
| 1064 CleanUpOldNavigations(&prefetches_, base::TimeDelta::FromMinutes(30)); |
| 1065 |
| 1042 // Measure how long a the various cleanup tasks took. http://crbug.com/305419. | 1066 // Measure how long a the various cleanup tasks took. http://crbug.com/305419. |
| 1043 UMA_HISTOGRAM_TIMES("Prerender.PeriodicCleanupDeleteContentsTime", | 1067 UMA_HISTOGRAM_TIMES("Prerender.PeriodicCleanupDeleteContentsTime", |
| 1044 cleanup_timer.Elapsed()); | 1068 cleanup_timer.Elapsed()); |
| 1045 } | 1069 } |
| 1046 | 1070 |
| 1047 void PrerenderManager::PostCleanupTask() { | 1071 void PrerenderManager::PostCleanupTask() { |
| 1048 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1072 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1049 base::ThreadTaskRunnerHandle::Get()->PostTask( | 1073 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 1050 FROM_HERE, base::Bind(&PrerenderManager::PeriodicCleanup, | 1074 FROM_HERE, base::Bind(&PrerenderManager::PeriodicCleanup, |
| 1051 weak_factory_.GetWeakPtr())); | 1075 weak_factory_.GetWeakPtr())); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1085 void PrerenderManager::SetClockForTesting( | 1109 void PrerenderManager::SetClockForTesting( |
| 1086 std::unique_ptr<base::SimpleTestClock> clock) { | 1110 std::unique_ptr<base::SimpleTestClock> clock) { |
| 1087 clock_ = std::move(clock); | 1111 clock_ = std::move(clock); |
| 1088 } | 1112 } |
| 1089 | 1113 |
| 1090 void PrerenderManager::SetTickClockForTesting( | 1114 void PrerenderManager::SetTickClockForTesting( |
| 1091 std::unique_ptr<base::SimpleTestTickClock> tick_clock) { | 1115 std::unique_ptr<base::SimpleTestTickClock> tick_clock) { |
| 1092 tick_clock_ = std::move(tick_clock); | 1116 tick_clock_ = std::move(tick_clock); |
| 1093 } | 1117 } |
| 1094 | 1118 |
| 1119 void PrerenderManager::AddObserver( |
| 1120 std::unique_ptr<PrerenderManagerObserver> observer) { |
| 1121 observers_.push_back(std::move(observer)); |
| 1122 } |
| 1123 |
| 1095 std::unique_ptr<PrerenderContents> PrerenderManager::CreatePrerenderContents( | 1124 std::unique_ptr<PrerenderContents> PrerenderManager::CreatePrerenderContents( |
| 1096 const GURL& url, | 1125 const GURL& url, |
| 1097 const content::Referrer& referrer, | 1126 const content::Referrer& referrer, |
| 1098 Origin origin) { | 1127 Origin origin) { |
| 1099 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1128 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1100 return base::WrapUnique(prerender_contents_factory_->CreatePrerenderContents( | 1129 return base::WrapUnique(prerender_contents_factory_->CreatePrerenderContents( |
| 1101 this, profile_, url, referrer, origin)); | 1130 this, profile_, url, referrer, origin)); |
| 1102 } | 1131 } |
| 1103 | 1132 |
| 1104 void PrerenderManager::SortActivePrerenders() { | 1133 void PrerenderManager::SortActivePrerenders() { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1147 | 1176 |
| 1148 void PrerenderManager::DeleteOldWebContents() { | 1177 void PrerenderManager::DeleteOldWebContents() { |
| 1149 for (WebContents* web_contents : old_web_contents_list_) { | 1178 for (WebContents* web_contents : old_web_contents_list_) { |
| 1150 // TODO(dominich): should we use Instant Unload Handler here? | 1179 // TODO(dominich): should we use Instant Unload Handler here? |
| 1151 // Or should |old_web_contents_list_| contain unique_ptrs? | 1180 // Or should |old_web_contents_list_| contain unique_ptrs? |
| 1152 delete web_contents; | 1181 delete web_contents; |
| 1153 } | 1182 } |
| 1154 old_web_contents_list_.clear(); | 1183 old_web_contents_list_.clear(); |
| 1155 } | 1184 } |
| 1156 | 1185 |
| 1186 void PrerenderManager::GetPrefetchInformation(const GURL& url, |
| 1187 base::TimeDelta* prefetch_age, |
| 1188 Origin* origin) { |
| 1189 DCHECK(prefetch_age); |
| 1190 DCHECK(origin); |
| 1191 CleanUpOldNavigations(&prefetches_, base::TimeDelta::FromMinutes(30)); |
| 1192 |
| 1193 *prefetch_age = base::TimeDelta(); |
| 1194 *origin = ORIGIN_NONE; |
| 1195 for (auto it = prefetches_.crbegin(); it != prefetches_.crend(); ++it) { |
| 1196 if (it->url == url) { |
| 1197 *prefetch_age = GetCurrentTimeTicks() - it->time; |
| 1198 *origin = it->origin; |
| 1199 break; |
| 1200 } |
| 1201 } |
| 1202 |
| 1203 // Loading a prefetched URL resets the revalidation bypass. Remove all |
| 1204 // matching urls from the prefetch list for more accurate metrics. |
| 1205 prefetches_.erase( |
| 1206 std::remove_if(prefetches_.begin(), prefetches_.end(), |
| 1207 [url](const NavigationRecord& r) { return r.url == url; }), |
| 1208 prefetches_.end()); |
| 1209 } |
| 1210 |
| 1157 void PrerenderManager::CleanUpOldNavigations( | 1211 void PrerenderManager::CleanUpOldNavigations( |
| 1158 std::vector<NavigationRecord>* navigations, | 1212 std::vector<NavigationRecord>* navigations, |
| 1159 base::TimeDelta max_age) { | 1213 base::TimeDelta max_age) { |
| 1160 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1214 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1161 | 1215 |
| 1162 // Cutoff. Navigations before this cutoff can be discarded. | 1216 // Cutoff. Navigations before this cutoff can be discarded. |
| 1163 base::TimeTicks cutoff = GetCurrentTimeTicks() - max_age; | 1217 base::TimeTicks cutoff = GetCurrentTimeTicks() - max_age; |
| 1164 auto it = navigations->begin(); | 1218 auto it = navigations->begin(); |
| 1165 for (; it != navigations->end(); ++it) { | 1219 for (; it != navigations->end(); ++it) { |
| 1166 if (it->time > cutoff) | 1220 if (it->time > cutoff) |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1361 return weak_factory_.GetWeakPtr(); | 1415 return weak_factory_.GetWeakPtr(); |
| 1362 } | 1416 } |
| 1363 | 1417 |
| 1364 void PrerenderManager::SetPrerenderContentsFactoryForTest( | 1418 void PrerenderManager::SetPrerenderContentsFactoryForTest( |
| 1365 PrerenderContents::Factory* prerender_contents_factory) { | 1419 PrerenderContents::Factory* prerender_contents_factory) { |
| 1366 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1420 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1367 prerender_contents_factory_.reset(prerender_contents_factory); | 1421 prerender_contents_factory_.reset(prerender_contents_factory); |
| 1368 } | 1422 } |
| 1369 | 1423 |
| 1370 } // namespace prerender | 1424 } // namespace prerender |
| OLD | NEW |