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

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

Issue 6677005: Limit prerender by only allowing one every X ms (X currently set to 500). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix license header Created 9 years, 9 months 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "base/logging.h" 7 #include "base/logging.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/time.h" 9 #include "base/time.h"
10 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 struct PrerenderManager::PrerenderContentsData { 54 struct PrerenderManager::PrerenderContentsData {
55 PrerenderContents* contents_; 55 PrerenderContents* contents_;
56 base::Time start_time_; 56 base::Time start_time_;
57 PrerenderContentsData(PrerenderContents* contents, base::Time start_time) 57 PrerenderContentsData(PrerenderContents* contents, base::Time start_time)
58 : contents_(contents), 58 : contents_(contents),
59 start_time_(start_time) { 59 start_time_(start_time) {
60 } 60 }
61 }; 61 };
62 62
63 PrerenderManager::PrerenderManager(Profile* profile) 63 PrerenderManager::PrerenderManager(Profile* profile)
64 : profile_(profile), 64 : rate_limit_enabled_(true),
65 profile_(profile),
65 max_prerender_age_(base::TimeDelta::FromSeconds( 66 max_prerender_age_(base::TimeDelta::FromSeconds(
66 kDefaultMaxPrerenderAgeSeconds)), 67 kDefaultMaxPrerenderAgeSeconds)),
67 max_elements_(kDefaultMaxPrerenderElements), 68 max_elements_(kDefaultMaxPrerenderElements),
68 prerender_contents_factory_(PrerenderContents::CreateFactory()) { 69 prerender_contents_factory_(PrerenderContents::CreateFactory()),
70 last_prerender_start_time_(GetCurrentTimeTicks() -
71 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs)) {
69 } 72 }
70 73
71 PrerenderManager::~PrerenderManager() { 74 PrerenderManager::~PrerenderManager() {
72 while (!prerender_list_.empty()) { 75 while (!prerender_list_.empty()) {
73 PrerenderContentsData data = prerender_list_.front(); 76 PrerenderContentsData data = prerender_list_.front();
74 prerender_list_.pop_front(); 77 prerender_list_.pop_front();
75 data.contents_->set_final_status(FINAL_STATUS_MANAGER_SHUTDOWN); 78 data.contents_->set_final_status(FINAL_STATUS_MANAGER_SHUTDOWN);
76 delete data.contents_; 79 delete data.contents_;
77 } 80 }
78 } 81 }
(...skipping 15 matching lines...) Expand all
94 // a shared process, so that we can always reliably lower the CPU 97 // a shared process, so that we can always reliably lower the CPU
95 // priority for prerendering. 98 // priority for prerendering.
96 // TODO(tburkard): Figure out how to cancel prerendering in the opposite 99 // TODO(tburkard): Figure out how to cancel prerendering in the opposite
97 // case, when a new tab is added to a process used for prerendering. 100 // case, when a new tab is added to a process used for prerendering.
98 if (RenderProcessHost::ShouldTryToUseExistingProcessHost()) { 101 if (RenderProcessHost::ShouldTryToUseExistingProcessHost()) {
99 // Only record the status if we are not in the control group. 102 // Only record the status if we are not in the control group.
100 if (!IsControlGroup()) 103 if (!IsControlGroup())
101 RecordFinalStatus(FINAL_STATUS_TOO_MANY_PROCESSES); 104 RecordFinalStatus(FINAL_STATUS_TOO_MANY_PROCESSES);
102 return false; 105 return false;
103 } 106 }
107
108 // Check if enough time has passed since the last prerender.
109 if (!DoesRateLimitAllowPrerender()) {
110 // Cancel the prerender. We could add it to the pending prerender list but
111 // this doesn't make sense as the next prerender request will be triggered
112 // by a navigation and is unlikely to be the same site.
113 RecordFinalStatus(FINAL_STATUS_RATE_LIMIT_EXCEEDED);
114 return false;
115 }
116
104 // TODO(cbentzel): Move invalid checks here instead of PrerenderContents? 117 // TODO(cbentzel): Move invalid checks here instead of PrerenderContents?
105 PrerenderContentsData data(CreatePrerenderContents(url, alias_urls, referrer), 118 PrerenderContentsData data(CreatePrerenderContents(url, alias_urls, referrer),
106 GetCurrentTime()); 119 GetCurrentTime());
107 prerender_list_.push_back(data); 120 prerender_list_.push_back(data);
108 if (!IsControlGroup()) 121 if (!IsControlGroup()) {
122 last_prerender_start_time_ = GetCurrentTimeTicks();
109 data.contents_->StartPrerendering(); 123 data.contents_->StartPrerendering();
124 }
110 while (prerender_list_.size() > max_elements_) { 125 while (prerender_list_.size() > max_elements_) {
111 data = prerender_list_.front(); 126 data = prerender_list_.front();
112 prerender_list_.pop_front(); 127 prerender_list_.pop_front();
113 data.contents_->set_final_status(FINAL_STATUS_EVICTED); 128 data.contents_->set_final_status(FINAL_STATUS_EVICTED);
114 delete data.contents_; 129 delete data.contents_;
115 } 130 }
116 StartSchedulingPeriodicCleanups(); 131 StartSchedulingPeriodicCleanups();
117 return true; 132 return true;
118 } 133 }
119 134
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 169
155 // If we are just in the control group (which can be detected by noticing 170 // If we are just in the control group (which can be detected by noticing
156 // that prerendering hasn't even started yet), record that this TC now would 171 // that prerendering hasn't even started yet), record that this TC now would
157 // be showing a prerendered contents, but otherwise, don't do anything. 172 // be showing a prerendered contents, but otherwise, don't do anything.
158 if (!pc->prerendering_has_started()) { 173 if (!pc->prerendering_has_started()) {
159 MarkTabContentsAsWouldBePrerendered(tc); 174 MarkTabContentsAsWouldBePrerendered(tc);
160 return false; 175 return false;
161 } 176 }
162 177
163 if (!pc->load_start_time().is_null()) 178 if (!pc->load_start_time().is_null())
164 RecordTimeUntilUsed(base::TimeTicks::Now() - pc->load_start_time()); 179 RecordTimeUntilUsed(GetCurrentTimeTicks() - pc->load_start_time());
165 pc->set_final_status(FINAL_STATUS_USED); 180 pc->set_final_status(FINAL_STATUS_USED);
166 181
167 RenderViewHost* rvh = pc->render_view_host(); 182 RenderViewHost* rvh = pc->render_view_host();
168 // RenderViewHosts in PrerenderContents start out hidden. 183 // RenderViewHosts in PrerenderContents start out hidden.
169 // Since we are actually using it now, restore it. 184 // Since we are actually using it now, restore it.
170 rvh->WasRestored(); 185 rvh->WasRestored();
171 pc->set_render_view_host(NULL); 186 pc->set_render_view_host(NULL);
172 rvh->Send(new ViewMsg_DisplayPrerenderedPage(rvh->routing_id())); 187 rvh->Send(new ViewMsg_DisplayPrerenderedPage(rvh->routing_id()));
173 tc->SwapInRenderViewHost(rvh); 188 tc->SwapInRenderViewHost(rvh);
174 MarkTabContentsAsPrerendered(tc); 189 MarkTabContentsAsPrerendered(tc);
(...skipping 26 matching lines...) Expand all
201 break; 216 break;
202 } 217 }
203 } 218 }
204 DeleteOldEntries(); 219 DeleteOldEntries();
205 } 220 }
206 221
207 base::Time PrerenderManager::GetCurrentTime() const { 222 base::Time PrerenderManager::GetCurrentTime() const {
208 return base::Time::Now(); 223 return base::Time::Now();
209 } 224 }
210 225
226 base::TimeTicks PrerenderManager::GetCurrentTimeTicks() const {
227 return base::TimeTicks::Now();
228 }
229
211 bool PrerenderManager::IsPrerenderElementFresh(const base::Time start) const { 230 bool PrerenderManager::IsPrerenderElementFresh(const base::Time start) const {
212 base::Time now = GetCurrentTime(); 231 base::Time now = GetCurrentTime();
213 return (now - start < max_prerender_age_); 232 return (now - start < max_prerender_age_);
214 } 233 }
215 234
216 PrerenderContents* PrerenderManager::CreatePrerenderContents( 235 PrerenderContents* PrerenderManager::CreatePrerenderContents(
217 const GURL& url, 236 const GURL& url,
218 const std::vector<GURL>& alias_urls, 237 const std::vector<GURL>& alias_urls,
219 const GURL& referrer) { 238 const GURL& referrer) {
220 return prerender_contents_factory_->CreatePrerenderContents( 239 return prerender_contents_factory_->CreatePrerenderContents(
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 // static 328 // static
310 bool PrerenderManager::ShouldRecordWindowedPPLT() { 329 bool PrerenderManager::ShouldRecordWindowedPPLT() {
311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
312 if (last_prefetch_seen_time_.is_null()) 331 if (last_prefetch_seen_time_.is_null())
313 return false; 332 return false;
314 base::TimeDelta elapsed_time = 333 base::TimeDelta elapsed_time =
315 base::TimeTicks::Now() - last_prefetch_seen_time_; 334 base::TimeTicks::Now() - last_prefetch_seen_time_;
316 return elapsed_time <= base::TimeDelta::FromSeconds(kWindowedPPLTSeconds); 335 return elapsed_time <= base::TimeDelta::FromSeconds(kWindowedPPLTSeconds);
317 } 336 }
318 337
338 bool PrerenderManager::DoesRateLimitAllowPrerender() const {
339 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
340 base::TimeDelta elapsed_time =
341 GetCurrentTimeTicks() - last_prerender_start_time_;
342 UMA_HISTOGRAM_TIMES("Prerender.TimeBetweenPrerenderRequests",
343 elapsed_time);
344 if (!rate_limit_enabled_)
345 return true;
346 return elapsed_time >
347 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs);
348 }
349
319 void PrerenderManager::StartSchedulingPeriodicCleanups() { 350 void PrerenderManager::StartSchedulingPeriodicCleanups() {
320 if (repeating_timer_.IsRunning()) 351 if (repeating_timer_.IsRunning())
321 return; 352 return;
322 repeating_timer_.Start( 353 repeating_timer_.Start(
323 base::TimeDelta::FromMilliseconds(kPeriodicCleanupIntervalMs), 354 base::TimeDelta::FromMilliseconds(kPeriodicCleanupIntervalMs),
324 this, 355 this,
325 &PrerenderManager::PeriodicCleanup); 356 &PrerenderManager::PeriodicCleanup);
326 } 357 }
327 358
328 void PrerenderManager::StopSchedulingPeriodicCleanups() { 359 void PrerenderManager::StopSchedulingPeriodicCleanups() {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 393
363 bool PrerenderManager::IsTabContentsPrerendered(TabContents* tc) const { 394 bool PrerenderManager::IsTabContentsPrerendered(TabContents* tc) const {
364 return prerendered_tc_set_.count(tc) > 0; 395 return prerendered_tc_set_.count(tc) > 0;
365 } 396 }
366 397
367 bool PrerenderManager::WouldTabContentsBePrerendered(TabContents* tc) const { 398 bool PrerenderManager::WouldTabContentsBePrerendered(TabContents* tc) const {
368 return would_be_prerendered_tc_set_.count(tc) > 0; 399 return would_be_prerendered_tc_set_.count(tc) > 0;
369 } 400 }
370 401
371 } // namespace prerender 402 } // namespace prerender
OLDNEW
« no previous file with comments | « chrome/browser/prerender/prerender_manager.h ('k') | chrome/browser/prerender/prerender_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698