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

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

Issue 9226037: Cancel prerenders from Omnibox if we navigate to a different URL than predicted (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Reorg prerender_manager.cc to match header. Add tests for cancellation. Created 8 years, 11 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) 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 <string> 7 #include <string>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 DISALLOW_COPY_AND_ASSIGN(OnCloseTabContentsDeleter); 146 DISALLOW_COPY_AND_ASSIGN(OnCloseTabContentsDeleter);
147 }; 147 };
148 148
149 // static 149 // static
150 int PrerenderManager::prerenders_per_session_count_ = 0; 150 int PrerenderManager::prerenders_per_session_count_ = 0;
151 151
152 // static 152 // static
153 PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = 153 PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ =
154 PRERENDER_MODE_ENABLED; 154 PRERENDER_MODE_ENABLED;
155 155
156 // static
157 PrerenderManager::PrerenderManagerMode PrerenderManager::GetMode() {
158 return mode_;
159 }
160
161 // static
162 void PrerenderManager::SetMode(PrerenderManagerMode mode) {
163 mode_ = mode;
164 }
165
166 // static
167 bool PrerenderManager::IsPrerenderingPossible() {
168 return GetMode() == PRERENDER_MODE_ENABLED ||
169 GetMode() == PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP ||
170 GetMode() == PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP ||
171 GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP;
172 }
173
174 // static
175 bool PrerenderManager::ActuallyPrerendering() {
176 return IsPrerenderingPossible() && !IsControlGroup();
177 }
178
179 // static
180 bool PrerenderManager::IsControlGroup() {
181 return GetMode() == PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP;
182 }
183
184 // static
185 bool PrerenderManager::IsNoUseGroup() {
186 return GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP;
187 }
188
189 // static
190 bool PrerenderManager::IsValidHttpMethod(const std::string& method) {
191 // method has been canonicalized to upper case at this point so we can just
192 // compare them.
193 DCHECK_EQ(method, StringToUpperASCII(method));
194 for (size_t i = 0; i < arraysize(kValidHttpMethods); ++i) {
195 if (method.compare(kValidHttpMethods[i]) == 0)
196 return true;
197 }
198
199 return false;
200 }
201
202 struct PrerenderManager::PrerenderContentsData { 156 struct PrerenderManager::PrerenderContentsData {
203 PrerenderContents* contents_; 157 PrerenderContents* contents_;
204 base::Time start_time_; 158 base::Time start_time_;
205 PrerenderContentsData(PrerenderContents* contents, base::Time start_time) 159 PrerenderContentsData(PrerenderContents* contents, base::Time start_time)
206 : contents_(contents), 160 : contents_(contents),
207 start_time_(start_time) { 161 start_time_(start_time) {
208 CHECK(contents); 162 CHECK(contents);
209 } 163 }
210 }; 164 };
211 165
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 return profile_->GetTopSites(); 219 return profile_->GetTopSites();
266 return NULL; 220 return NULL;
267 } 221 }
268 222
269 CancelableRequestConsumer topsites_consumer_; 223 CancelableRequestConsumer topsites_consumer_;
270 Profile* profile_; 224 Profile* profile_;
271 content::NotificationRegistrar registrar_; 225 content::NotificationRegistrar registrar_;
272 std::set<GURL> urls_; 226 std::set<GURL> urls_;
273 }; 227 };
274 228
275 bool PrerenderManager::IsTopSite(const GURL& url) {
276 if (!most_visited_.get())
277 most_visited_.reset(new MostVisitedSites(profile_));
278 return most_visited_->IsTopSite(url);
279 }
280
281 bool PrerenderManager::IsPendingEntry(const GURL& url) const {
282 DCHECK(CalledOnValidThread());
283 for (std::list<PrerenderContentsData>::const_iterator it =
284 prerender_list_.begin();
285 it != prerender_list_.end();
286 ++it) {
287 if (it->contents_->IsPendingEntry(url))
288 return true;
289 }
290 return false;
291 }
292
293 PrerenderManager::PrerenderManager(Profile* profile, 229 PrerenderManager::PrerenderManager(Profile* profile,
294 PrerenderTracker* prerender_tracker) 230 PrerenderTracker* prerender_tracker)
295 : enabled_(true), 231 : enabled_(true),
296 profile_(profile), 232 profile_(profile),
297 prerender_tracker_(prerender_tracker), 233 prerender_tracker_(prerender_tracker),
298 prerender_contents_factory_(PrerenderContents::CreateFactory()), 234 prerender_contents_factory_(PrerenderContents::CreateFactory()),
299 last_prerender_start_time_(GetCurrentTimeTicks() - 235 last_prerender_start_time_(GetCurrentTimeTicks() -
300 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs)), 236 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs)),
301 weak_factory_(this), 237 weak_factory_(this),
302 prerender_history_(new PrerenderHistory(kHistoryLength)), 238 prerender_history_(new PrerenderHistory(kHistoryLength)),
303 histograms_(new PrerenderHistograms()) { 239 histograms_(new PrerenderHistograms()) {
304 // There are some assumptions that the PrerenderManager is on the UI thread. 240 // There are some assumptions that the PrerenderManager is on the UI thread.
305 // Any other checks simply make sure that the PrerenderManager is accessed on 241 // Any other checks simply make sure that the PrerenderManager is accessed on
306 // the same thread that it was created on. 242 // the same thread that it was created on.
307 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
308 } 244 }
309 245
310 PrerenderManager::~PrerenderManager() { 246 PrerenderManager::~PrerenderManager() {
311 } 247 }
312 248
313 void PrerenderManager::Shutdown() { 249 void PrerenderManager::Shutdown() {
314 DoShutdown(); 250 DoShutdown();
315 } 251 }
316 252
317 void PrerenderManager::SetPrerenderContentsFactory(
318 PrerenderContents::Factory* prerender_contents_factory) {
319 DCHECK(CalledOnValidThread());
320 prerender_contents_factory_.reset(prerender_contents_factory);
321 }
322
323 bool PrerenderManager::AddPrerenderFromLinkRelPrerender( 253 bool PrerenderManager::AddPrerenderFromLinkRelPrerender(
324 int process_id, 254 int process_id,
325 int route_id, 255 int route_id,
326 const GURL& url, 256 const GURL& url,
327 const content::Referrer& referrer) { 257 const content::Referrer& referrer) {
328 std::pair<int, int> child_route_id_pair = std::make_pair(process_id, 258 std::pair<int, int> child_route_id_pair = std::make_pair(process_id,
329 route_id); 259 route_id);
330 260
331 return AddPrerender(ORIGIN_LINK_REL_PRERENDER, child_route_id_pair, 261 return AddPrerender(ORIGIN_LINK_REL_PRERENDER, child_route_id_pair,
332 url, referrer, NULL); 262 url, referrer, NULL);
333 } 263 }
334 264
335 bool PrerenderManager::AddPrerenderFromOmnibox( 265 bool PrerenderManager::AddPrerenderFromOmnibox(
336 const GURL& url, 266 const GURL& url,
337 SessionStorageNamespace* session_storage_namespace) { 267 SessionStorageNamespace* session_storage_namespace) {
338 DCHECK(session_storage_namespace);
cbentzel 2012/01/25 12:14:01 Why was this removed?
339 if (!IsOmniboxEnabled(profile_)) 268 if (!IsOmniboxEnabled(profile_))
340 return false; 269 return false;
341 return AddPrerender(ORIGIN_OMNIBOX, std::make_pair(-1, -1), url, 270 return AddPrerender(ORIGIN_OMNIBOX, std::make_pair(-1, -1), url,
342 content::Referrer(), session_storage_namespace); 271 content::Referrer(), session_storage_namespace);
343 } 272 }
344 273
345 bool PrerenderManager::AddPrerender(
346 Origin origin,
347 const std::pair<int, int>& child_route_id_pair,
348 const GURL& url_arg,
349 const content::Referrer& referrer,
350 SessionStorageNamespace* session_storage_namespace) {
351 DCHECK(CalledOnValidThread());
352
353 if (origin == ORIGIN_LINK_REL_PRERENDER &&
354 IsGoogleSearchResultURL(referrer.url)) {
355 origin = ORIGIN_GWS_PRERENDER;
356 }
357
358 // If the referring page is prerendering, defer the prerender.
359 std::list<PrerenderContentsData>::iterator source_prerender =
360 FindPrerenderContentsForChildRouteIdPair(child_route_id_pair);
361 if (source_prerender != prerender_list_.end()) {
362 source_prerender->contents_->AddPendingPrerender(
363 origin, url_arg, referrer);
364 return true;
365 }
366
367 DeleteOldEntries();
368 DeletePendingDeleteEntries();
369
370 GURL url = url_arg;
371 GURL alias_url;
372 if (IsControlGroup() && MaybeGetQueryStringBasedAliasURL(url, &alias_url))
373 url = alias_url;
374
375 // From here on, we will record a FinalStatus so we need to register with the
376 // histogram tracking.
377 histograms_->RecordPrerender(origin, url_arg);
378
379 uint8 experiment = GetQueryStringBasedExperiment(url_arg);
380
381 if (FindEntry(url)) {
382 RecordFinalStatus(origin, experiment, FINAL_STATUS_DUPLICATE);
383 return false;
384 }
385
386 // Do not prerender if there are too many render processes, and we would
387 // have to use an existing one. We do not want prerendering to happen in
388 // a shared process, so that we can always reliably lower the CPU
389 // priority for prerendering.
390 // In single-process mode, ShouldTryToUseExistingProcessHost() always returns
391 // true, so that case needs to be explicitly checked for.
392 // TODO(tburkard): Figure out how to cancel prerendering in the opposite
393 // case, when a new tab is added to a process used for prerendering.
394 if (content::RenderProcessHost::ShouldTryToUseExistingProcessHost() &&
395 !content::RenderProcessHost::run_renderer_in_process()) {
396 RecordFinalStatus(origin, experiment, FINAL_STATUS_TOO_MANY_PROCESSES);
397 return false;
398 }
399
400 // Check if enough time has passed since the last prerender.
401 if (!DoesRateLimitAllowPrerender()) {
402 // Cancel the prerender. We could add it to the pending prerender list but
403 // this doesn't make sense as the next prerender request will be triggered
404 // by a navigation and is unlikely to be the same site.
405 RecordFinalStatus(origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED);
406 return false;
407 }
408
409 RenderViewHost* source_render_view_host = NULL;
410 if (child_route_id_pair.first != -1) {
411 source_render_view_host =
412 RenderViewHost::FromID(child_route_id_pair.first,
413 child_route_id_pair.second);
414 // Don't prerender page if parent RenderViewHost no longer exists, or it has
415 // no view. The latter should only happen when the RenderView has closed.
416 if (!source_render_view_host || !source_render_view_host->view()) {
417 RecordFinalStatus(origin, experiment,
418 FINAL_STATUS_SOURCE_RENDER_VIEW_CLOSED);
419 return false;
420 }
421 }
422
423 if (!session_storage_namespace && source_render_view_host) {
424 session_storage_namespace =
425 source_render_view_host->session_storage_namespace();
426 }
427
428 PrerenderContents* prerender_contents = CreatePrerenderContents(
429 url, referrer, origin, experiment);
430 if (!prerender_contents || !prerender_contents->Init())
431 return false;
432
433 histograms_->RecordPrerenderStarted(origin);
434
435 // TODO(cbentzel): Move invalid checks here instead of PrerenderContents?
436 PrerenderContentsData data(prerender_contents, GetCurrentTime());
437
438 prerender_list_.push_back(data);
439
440 if (IsControlGroup()) {
441 data.contents_->set_final_status(FINAL_STATUS_CONTROL_GROUP);
442 } else {
443 last_prerender_start_time_ = GetCurrentTimeTicks();
444 data.contents_->StartPrerendering(source_render_view_host,
445 session_storage_namespace);
446 }
447 while (prerender_list_.size() > config_.max_elements) {
448 data = prerender_list_.front();
449 prerender_list_.pop_front();
450 data.contents_->Destroy(FINAL_STATUS_EVICTED);
451 }
452 StartSchedulingPeriodicCleanups();
453 return true;
454 }
455
456 std::list<PrerenderManager::PrerenderContentsData>::iterator
457 PrerenderManager::FindPrerenderContentsForChildRouteIdPair(
458 const std::pair<int, int>& child_route_id_pair) {
459 std::list<PrerenderContentsData>::iterator it = prerender_list_.begin();
460 for (; it != prerender_list_.end(); ++it) {
461 PrerenderContents* prerender_contents = it->contents_;
462
463 int child_id;
464 int route_id;
465 bool has_child_id = prerender_contents->GetChildId(&child_id);
466 bool has_route_id = has_child_id &&
467 prerender_contents->GetRouteId(&route_id);
468
469 if (has_child_id && has_route_id &&
470 child_id == child_route_id_pair.first &&
471 route_id == child_route_id_pair.second) {
472 break;
473 }
474 }
475 return it;
476 }
477
478 void PrerenderManager::DestroyPrerenderForRenderView( 274 void PrerenderManager::DestroyPrerenderForRenderView(
479 int process_id, int view_id, FinalStatus final_status) { 275 int process_id, int view_id, FinalStatus final_status) {
480 DCHECK(CalledOnValidThread()); 276 DCHECK(CalledOnValidThread());
481 std::list<PrerenderContentsData>::iterator it = 277 std::list<PrerenderContentsData>::iterator it =
482 FindPrerenderContentsForChildRouteIdPair( 278 FindPrerenderContentsForChildRouteIdPair(
483 std::make_pair(process_id, view_id)); 279 std::make_pair(process_id, view_id));
484 if (it != prerender_list_.end()) { 280 if (it != prerender_list_.end()) {
485 PrerenderContents* prerender_contents = it->contents_; 281 PrerenderContents* prerender_contents = it->contents_;
486 prerender_contents->Destroy(final_status); 282 prerender_contents->Destroy(final_status);
487 } 283 }
488 } 284 }
489 285
490 void PrerenderManager::CancelAllPrerenders() { 286 void PrerenderManager::CancelAllPrerenders() {
491 DCHECK(CalledOnValidThread()); 287 DCHECK(CalledOnValidThread());
492 while (!prerender_list_.empty()) { 288 while (!prerender_list_.empty()) {
493 PrerenderContentsData data = prerender_list_.front(); 289 PrerenderContentsData data = prerender_list_.front();
494 DCHECK(data.contents_); 290 DCHECK(data.contents_);
495 data.contents_->Destroy(FINAL_STATUS_CANCELLED); 291 data.contents_->Destroy(FINAL_STATUS_CANCELLED);
496 } 292 }
497 } 293 }
498 294
499 void PrerenderManager::DeleteOldEntries() { 295 void PrerenderManager::CancelOmniboxPrerenders() {
500 DCHECK(CalledOnValidThread()); 296 DCHECK(CalledOnValidThread());
501 while (!prerender_list_.empty()) { 297 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin();
Peter Kasting 2012/01/24 03:36:59 Nit: I wonder if a typedef for this might be usefu
502 PrerenderContentsData data = prerender_list_.front(); 298 it != prerender_list_.end(); ) {
503 if (IsPrerenderElementFresh(data.start_time_)) 299 std::list<PrerenderContentsData>::iterator cur = it++;
504 return; 300 if (cur->contents_->origin() == ORIGIN_OMNIBOX)
505 data.contents_->Destroy(FINAL_STATUS_TIMED_OUT); 301 cur->contents_->Destroy(FINAL_STATUS_CANCELLED);
506 } 302 }
507 MaybeStopSchedulingPeriodicCleanups();
508 }
509
510 PrerenderContents* PrerenderManager::GetEntryButNotSpecifiedWC(
511 const GURL& url,
512 WebContents* wc) {
513 DCHECK(CalledOnValidThread());
514 DeleteOldEntries();
515 DeletePendingDeleteEntries();
516 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin();
517 it != prerender_list_.end();
518 ++it) {
519 PrerenderContents* prerender_contents = it->contents_;
520 if (prerender_contents->MatchesURL(url, NULL)) {
521 if (!prerender_contents->prerender_contents() ||
522 !wc ||
523 prerender_contents->prerender_contents()->web_contents() != wc) {
524 prerender_list_.erase(it);
525 return prerender_contents;
526 }
527 }
528 }
529 // Entry not found.
530 return NULL;
531 }
532
533 PrerenderContents* PrerenderManager::GetEntry(const GURL& url) {
534 return GetEntryButNotSpecifiedWC(url, NULL);
535 } 303 }
536 304
537 bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, 305 bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents,
538 const GURL& url, 306 const GURL& url,
539 const GURL& opener_url) { 307 const GURL& opener_url) {
540 DCHECK(CalledOnValidThread()); 308 DCHECK(CalledOnValidThread());
541 RecordNavigation(url); 309 RecordNavigation(url);
542 310
543 scoped_ptr<PrerenderContents> prerender_contents( 311 scoped_ptr<PrerenderContents> prerender_contents(
544 GetEntryButNotSpecifiedWC(url, web_contents)); 312 GetEntryButNotSpecifiedWC(url, web_contents));
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 } 502 }
735 } 503 }
736 AddToHistory(entry); 504 AddToHistory(entry);
737 pending_delete_list_.push_back(entry); 505 pending_delete_list_.push_back(entry);
738 506
739 // Destroy the old TabContents relatively promptly to reduce resource usage, 507 // Destroy the old TabContents relatively promptly to reduce resource usage,
740 // and in the case of HTML5 media, reduce the change of playing any sound. 508 // and in the case of HTML5 media, reduce the change of playing any sound.
741 PostCleanupTask(); 509 PostCleanupTask();
742 } 510 }
743 511
744 base::Time PrerenderManager::GetCurrentTime() const {
745 return base::Time::Now();
746 }
747
748 base::TimeTicks PrerenderManager::GetCurrentTimeTicks() const {
749 return base::TimeTicks::Now();
750 }
751
752 bool PrerenderManager::IsPrerenderElementFresh(const base::Time start) const {
753 DCHECK(CalledOnValidThread());
754 base::Time now = GetCurrentTime();
755 return (now - start < config_.max_age);
756 }
757
758 PrerenderContents* PrerenderManager::CreatePrerenderContents(
759 const GURL& url,
760 const content::Referrer& referrer,
761 Origin origin,
762 uint8 experiment_id) {
763 DCHECK(CalledOnValidThread());
764 return prerender_contents_factory_->CreatePrerenderContents(
765 this, prerender_tracker_, profile_, url,
766 referrer, origin, experiment_id);
767 }
768
769 bool PrerenderManager::IsPendingDelete(PrerenderContents* entry) const {
770 DCHECK(CalledOnValidThread());
771 for (std::list<PrerenderContents*>::const_iterator it =
772 pending_delete_list_.begin();
773 it != pending_delete_list_.end();
774 ++it) {
775 if (*it == entry)
776 return true;
777 }
778
779 return false;
780 }
781
782 void PrerenderManager::DeletePendingDeleteEntries() {
783 while (!pending_delete_list_.empty()) {
784 PrerenderContents* contents = pending_delete_list_.front();
785 pending_delete_list_.pop_front();
786 delete contents;
787 }
788 }
789
790 // static 512 // static
791 void PrerenderManager::RecordPerceivedPageLoadTime( 513 void PrerenderManager::RecordPerceivedPageLoadTime(
792 base::TimeDelta perceived_page_load_time, 514 base::TimeDelta perceived_page_load_time,
793 WebContents* web_contents, 515 WebContents* web_contents,
794 const GURL& url) { 516 const GURL& url) {
795 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 517 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
796 PrerenderManager* prerender_manager = 518 PrerenderManager* prerender_manager =
797 PrerenderManagerFactory::GetForProfile( 519 PrerenderManagerFactory::GetForProfile(
798 Profile::FromBrowserContext(web_contents->GetBrowserContext())); 520 Profile::FromBrowserContext(web_contents->GetBrowserContext()));
799 if (!prerender_manager) 521 if (!prerender_manager)
(...skipping 21 matching lines...) Expand all
821 return false; 543 return false;
822 } 544 }
823 return true; 545 return true;
824 } 546 }
825 547
826 void PrerenderManager::set_enabled(bool enabled) { 548 void PrerenderManager::set_enabled(bool enabled) {
827 DCHECK(CalledOnValidThread()); 549 DCHECK(CalledOnValidThread());
828 enabled_ = enabled; 550 enabled_ = enabled;
829 } 551 }
830 552
831 void PrerenderManager::AddCondition(const PrerenderCondition* condition) { 553 // static
832 prerender_conditions_.push_back(condition); 554 PrerenderManager::PrerenderManagerMode PrerenderManager::GetMode() {
555 return mode_;
833 } 556 }
834 557
835 PrerenderContents* PrerenderManager::FindEntry(const GURL& url) { 558 // static
836 DCHECK(CalledOnValidThread()); 559 void PrerenderManager::SetMode(PrerenderManagerMode mode) {
837 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); 560 mode_ = mode;
838 it != prerender_list_.end();
839 ++it) {
840 if (it->contents_->MatchesURL(url, NULL))
841 return it->contents_;
842 }
843 // Entry not found.
844 return NULL;
845 } 561 }
846 562
847 void PrerenderManager::DoShutdown() { 563 // static
848 DestroyAllContents(FINAL_STATUS_MANAGER_SHUTDOWN); 564 bool PrerenderManager::IsPrerenderingPossible() {
849 STLDeleteElements(&prerender_conditions_); 565 return GetMode() == PRERENDER_MODE_ENABLED ||
850 profile_ = NULL; 566 GetMode() == PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP ||
567 GetMode() == PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP ||
568 GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP;
851 } 569 }
852 570
853 bool PrerenderManager::DoesRateLimitAllowPrerender() const { 571 // static
854 DCHECK(CalledOnValidThread()); 572 bool PrerenderManager::ActuallyPrerendering() {
855 base::TimeDelta elapsed_time = 573 return IsPrerenderingPossible() && !IsControlGroup();
856 GetCurrentTimeTicks() - last_prerender_start_time_;
857 histograms_->RecordTimeBetweenPrerenderRequests(elapsed_time);
858 if (!config_.rate_limit_enabled)
859 return true;
860 return elapsed_time >
861 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs);
862 } 574 }
863 575
864 void PrerenderManager::StartSchedulingPeriodicCleanups() { 576 // static
865 DCHECK(CalledOnValidThread()); 577 bool PrerenderManager::IsControlGroup() {
866 if (repeating_timer_.IsRunning()) 578 return GetMode() == PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP;
867 return;
868 repeating_timer_.Start(FROM_HERE,
869 base::TimeDelta::FromMilliseconds(kPeriodicCleanupIntervalMs),
870 this,
871 &PrerenderManager::PeriodicCleanup);
872 } 579 }
873 580
874 void PrerenderManager::MaybeStopSchedulingPeriodicCleanups() { 581 // static
875 if (!prerender_list_.empty()) 582 bool PrerenderManager::IsNoUseGroup() {
876 return; 583 return GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP;
877
878 DCHECK(CalledOnValidThread());
879 repeating_timer_.Stop();
880 }
881
882 void PrerenderManager::DeleteOldTabContents() {
883 while (!old_tab_contents_list_.empty()) {
884 TabContentsWrapper* tab_contents = old_tab_contents_list_.front();
885 old_tab_contents_list_.pop_front();
886 // TODO(dominich): should we use Instant Unload Handler here?
887 delete tab_contents;
888 }
889 }
890
891 bool PrerenderManager::IsOldRenderViewHost(
892 const RenderViewHost* render_view_host) const {
893 for (std::list<TabContentsWrapper*>::const_iterator it =
894 old_tab_contents_list_.begin();
895 it != old_tab_contents_list_.end();
896 ++it) {
897 if ((*it)->web_contents()->GetRenderViewHost() == render_view_host)
898 return true;
899 }
900 return false;
901 }
902
903 void PrerenderManager::PeriodicCleanup() {
904 DCHECK(CalledOnValidThread());
905 DeleteOldTabContents();
906 DeleteOldEntries();
907
908 // Grab a copy of the current PrerenderContents pointers, so that we
909 // will not interfere with potential deletions of the list.
910 std::vector<PrerenderContents*> prerender_contents;
911 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin();
912 it != prerender_list_.end();
913 ++it) {
914 DCHECK(it->contents_);
915 prerender_contents.push_back(it->contents_);
916 }
917 for (std::vector<PrerenderContents*>::iterator it =
918 prerender_contents.begin();
919 it != prerender_contents.end();
920 ++it) {
921 (*it)->DestroyWhenUsingTooManyResources();
922 }
923
924 DeletePendingDeleteEntries();
925 }
926
927 void PrerenderManager::PostCleanupTask() {
928 DCHECK(CalledOnValidThread());
929 MessageLoop::current()->PostTask(
930 FROM_HERE,
931 base::Bind(&PrerenderManager::PeriodicCleanup,
932 weak_factory_.GetWeakPtr()));
933 } 584 }
934 585
935 bool PrerenderManager::IsWebContentsPrerendering( 586 bool PrerenderManager::IsWebContentsPrerendering(
936 WebContents* web_contents) const { 587 WebContents* web_contents) const {
937 DCHECK(CalledOnValidThread()); 588 DCHECK(CalledOnValidThread());
938 for (std::list<PrerenderContentsData>::const_iterator it = 589 for (std::list<PrerenderContentsData>::const_iterator it =
939 prerender_list_.begin(); 590 prerender_list_.begin();
940 it != prerender_list_.end(); 591 it != prerender_list_.end();
941 ++it) { 592 ++it) {
942 TabContentsWrapper* prerender_tab_contents_wrapper = 593 TabContentsWrapper* prerender_tab_contents_wrapper =
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
985 DCHECK(CalledOnValidThread()); 636 DCHECK(CalledOnValidThread());
986 return prerendered_tab_contents_set_.count(web_contents) > 0; 637 return prerendered_tab_contents_set_.count(web_contents) > 0;
987 } 638 }
988 639
989 bool PrerenderManager::WouldWebContentsBePrerendered( 640 bool PrerenderManager::WouldWebContentsBePrerendered(
990 WebContents* web_contents) const { 641 WebContents* web_contents) const {
991 DCHECK(CalledOnValidThread()); 642 DCHECK(CalledOnValidThread());
992 return would_be_prerendered_tab_contents_set_.count(web_contents) > 0; 643 return would_be_prerendered_tab_contents_set_.count(web_contents) > 0;
993 } 644 }
994 645
646 bool PrerenderManager::IsOldRenderViewHost(
647 const RenderViewHost* render_view_host) const {
648 for (std::list<TabContentsWrapper*>::const_iterator it =
649 old_tab_contents_list_.begin();
650 it != old_tab_contents_list_.end();
651 ++it) {
652 if ((*it)->web_contents()->GetRenderViewHost() == render_view_host)
653 return true;
654 }
655 return false;
656 }
657
995 bool PrerenderManager::HasRecentlyBeenNavigatedTo(const GURL& url) { 658 bool PrerenderManager::HasRecentlyBeenNavigatedTo(const GURL& url) {
996 DCHECK(CalledOnValidThread()); 659 DCHECK(CalledOnValidThread());
997 660
998 CleanUpOldNavigations(); 661 CleanUpOldNavigations();
999 for (std::list<NavigationRecord>::const_iterator it = navigations_.begin(); 662 for (std::list<NavigationRecord>::const_iterator it = navigations_.begin();
1000 it != navigations_.end(); 663 it != navigations_.end();
1001 ++it) { 664 ++it) {
1002 if (it->url_ == url) 665 if (it->url_ == url)
1003 return true; 666 return true;
1004 } 667 }
1005 668
1006 return false; 669 return false;
1007 } 670 }
1008 671
1009 void PrerenderManager::CleanUpOldNavigations() { 672 // static
1010 DCHECK(CalledOnValidThread()); 673 bool PrerenderManager::IsValidHttpMethod(const std::string& method) {
674 // method has been canonicalized to upper case at this point so we can just
675 // compare them.
676 DCHECK_EQ(method, StringToUpperASCII(method));
677 for (size_t i = 0; i < arraysize(kValidHttpMethods); ++i) {
678 if (method.compare(kValidHttpMethods[i]) == 0)
679 return true;
680 }
1011 681
1012 // Cutoff. Navigations before this cutoff can be discarded. 682 return false;
1013 base::TimeTicks cutoff = GetCurrentTimeTicks() -
1014 base::TimeDelta::FromMilliseconds(kNavigationRecordWindowMs);
1015 while (!navigations_.empty()) {
1016 if (navigations_.front().time_ > cutoff)
1017 break;
1018 navigations_.pop_front();
1019 }
1020 }
1021
1022 void PrerenderManager::ScheduleDeleteOldTabContents(
1023 TabContentsWrapper* tab,
1024 OnCloseTabContentsDeleter* deleter) {
1025 old_tab_contents_list_.push_back(tab);
1026 PostCleanupTask();
1027
1028 if (deleter) {
1029 ScopedVector<OnCloseTabContentsDeleter>::iterator i = std::find(
1030 on_close_tab_contents_deleters_.begin(),
1031 on_close_tab_contents_deleters_.end(),
1032 deleter);
1033 DCHECK(i != on_close_tab_contents_deleters_.end());
1034 on_close_tab_contents_deleters_.erase(i);
1035 }
1036 } 683 }
1037 684
1038 DictionaryValue* PrerenderManager::GetAsValue() const { 685 DictionaryValue* PrerenderManager::GetAsValue() const {
1039 DCHECK(CalledOnValidThread()); 686 DCHECK(CalledOnValidThread());
1040 DictionaryValue* dict_value = new DictionaryValue(); 687 DictionaryValue* dict_value = new DictionaryValue();
1041 dict_value->Set("history", prerender_history_->GetEntriesAsValue()); 688 dict_value->Set("history", prerender_history_->GetEntriesAsValue());
1042 dict_value->Set("active", GetActivePrerendersAsValue()); 689 dict_value->Set("active", GetActivePrerendersAsValue());
1043 dict_value->SetBoolean("enabled", enabled_); 690 dict_value->SetBoolean("enabled", enabled_);
1044 dict_value->SetBoolean("omnibox_enabled", IsOmniboxEnabled(profile_)); 691 dict_value->SetBoolean("omnibox_enabled", IsOmniboxEnabled(profile_));
1045 // If prerender is disabled via a flag this method is not even called. 692 // If prerender is disabled via a flag this method is not even called.
1046 if (IsControlGroup()) 693 if (IsControlGroup())
1047 dict_value->SetString("disabled_reason", "(Disabled for testing)"); 694 dict_value->SetString("disabled_reason", "(Disabled for testing)");
1048 if (IsNoUseGroup()) 695 if (IsNoUseGroup())
1049 dict_value->SetString("disabled_reason", "(Not using prerendered pages)"); 696 dict_value->SetString("disabled_reason", "(Not using prerendered pages)");
1050 return dict_value; 697 return dict_value;
1051 } 698 }
1052 699
1053 void PrerenderManager::ClearData(int clear_flags) { 700 void PrerenderManager::ClearData(int clear_flags) {
1054 DCHECK_GE(clear_flags, 0); 701 DCHECK_GE(clear_flags, 0);
1055 DCHECK_LT(clear_flags, CLEAR_MAX); 702 DCHECK_LT(clear_flags, CLEAR_MAX);
1056 if (clear_flags & CLEAR_PRERENDER_CONTENTS) 703 if (clear_flags & CLEAR_PRERENDER_CONTENTS)
1057 DestroyAllContents(FINAL_STATUS_CACHE_OR_HISTORY_CLEARED); 704 DestroyAllContents(FINAL_STATUS_CACHE_OR_HISTORY_CLEARED);
1058 // This has to be second, since destroying prerenders can add to the history. 705 // This has to be second, since destroying prerenders can add to the history.
1059 if (clear_flags & CLEAR_PRERENDER_HISTORY) 706 if (clear_flags & CLEAR_PRERENDER_HISTORY)
1060 prerender_history_->Clear(); 707 prerender_history_->Clear();
1061 } 708 }
1062 709
710 void PrerenderManager::RecordFinalStatus(Origin origin,
711 uint8 experiment_id,
712 FinalStatus final_status) const {
713 histograms_->RecordFinalStatus(origin, experiment_id, final_status);
714 }
715
716 void PrerenderManager::AddCondition(const PrerenderCondition* condition) {
717 prerender_conditions_.push_back(condition);
718 }
719
720 bool PrerenderManager::IsTopSite(const GURL& url) {
721 if (!most_visited_.get())
722 most_visited_.reset(new MostVisitedSites(profile_));
723 return most_visited_->IsTopSite(url);
724 }
725
726 bool PrerenderManager::IsPendingEntry(const GURL& url) const {
727 DCHECK(CalledOnValidThread());
728 for (std::list<PrerenderContentsData>::const_iterator it =
729 prerender_list_.begin();
730 it != prerender_list_.end();
731 ++it) {
732 if (it->contents_->IsPendingEntry(url))
733 return true;
734 }
735 return false;
736 }
737
738 bool PrerenderManager::IsPrerendering(const GURL& url) {
739 DCHECK(CalledOnValidThread());
740 return (FindEntry(url) != NULL);
741 }
742
743 // protected
744 void PrerenderManager::SetPrerenderContentsFactory(
745 PrerenderContents::Factory* prerender_contents_factory) {
746 DCHECK(CalledOnValidThread());
747 prerender_contents_factory_.reset(prerender_contents_factory);
748 }
749
750 void PrerenderManager::DoShutdown() {
751 DestroyAllContents(FINAL_STATUS_MANAGER_SHUTDOWN);
752 STLDeleteElements(&prerender_conditions_);
753 profile_ = NULL;
754 }
755
756 // private
cbentzel 2012/01/25 12:14:01 Nit: I haven't really seen the // private comment
757 bool PrerenderManager::AddPrerender(
758 Origin origin,
759 const std::pair<int, int>& child_route_id_pair,
760 const GURL& url_arg,
761 const content::Referrer& referrer,
762 SessionStorageNamespace* session_storage_namespace) {
763 DCHECK(CalledOnValidThread());
764
765 if (origin == ORIGIN_LINK_REL_PRERENDER &&
766 IsGoogleSearchResultURL(referrer.url)) {
767 origin = ORIGIN_GWS_PRERENDER;
768 }
769
770 // If the referring page is prerendering, defer the prerender.
771 std::list<PrerenderContentsData>::iterator source_prerender =
772 FindPrerenderContentsForChildRouteIdPair(child_route_id_pair);
773 if (source_prerender != prerender_list_.end()) {
774 source_prerender->contents_->AddPendingPrerender(
775 origin, url_arg, referrer);
776 return true;
777 }
778
779 DeleteOldEntries();
780 DeletePendingDeleteEntries();
781
782 GURL url = url_arg;
783 GURL alias_url;
784 if (IsControlGroup() && MaybeGetQueryStringBasedAliasURL(url, &alias_url))
785 url = alias_url;
786
787 // From here on, we will record a FinalStatus so we need to register with the
788 // histogram tracking.
789 histograms_->RecordPrerender(origin, url_arg);
790
791 uint8 experiment = GetQueryStringBasedExperiment(url_arg);
792
793 if (FindEntry(url)) {
794 RecordFinalStatus(origin, experiment, FINAL_STATUS_DUPLICATE);
795 return false;
796 }
797
798 // Do not prerender if there are too many render processes, and we would
799 // have to use an existing one. We do not want prerendering to happen in
800 // a shared process, so that we can always reliably lower the CPU
801 // priority for prerendering.
802 // In single-process mode, ShouldTryToUseExistingProcessHost() always returns
803 // true, so that case needs to be explicitly checked for.
804 // TODO(tburkard): Figure out how to cancel prerendering in the opposite
805 // case, when a new tab is added to a process used for prerendering.
806 if (content::RenderProcessHost::ShouldTryToUseExistingProcessHost() &&
807 !content::RenderProcessHost::run_renderer_in_process()) {
808 RecordFinalStatus(origin, experiment, FINAL_STATUS_TOO_MANY_PROCESSES);
809 return false;
810 }
811
812 // Check if enough time has passed since the last prerender.
813 if (!DoesRateLimitAllowPrerender()) {
814 // Cancel the prerender. We could add it to the pending prerender list but
815 // this doesn't make sense as the next prerender request will be triggered
816 // by a navigation and is unlikely to be the same site.
817 RecordFinalStatus(origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED);
818 return false;
819 }
820
821 RenderViewHost* source_render_view_host = NULL;
822 if (child_route_id_pair.first != -1) {
823 source_render_view_host =
824 RenderViewHost::FromID(child_route_id_pair.first,
825 child_route_id_pair.second);
826 // Don't prerender page if parent RenderViewHost no longer exists, or it has
827 // no view. The latter should only happen when the RenderView has closed.
828 if (!source_render_view_host || !source_render_view_host->view()) {
829 RecordFinalStatus(origin, experiment,
830 FINAL_STATUS_SOURCE_RENDER_VIEW_CLOSED);
831 return false;
832 }
833 }
834
835 if (!session_storage_namespace && source_render_view_host) {
836 session_storage_namespace =
837 source_render_view_host->session_storage_namespace();
838 }
839
840 PrerenderContents* prerender_contents = CreatePrerenderContents(
841 url, referrer, origin, experiment);
842 if (!prerender_contents || !prerender_contents->Init())
843 return false;
844
845 histograms_->RecordPrerenderStarted(origin);
846
847 // TODO(cbentzel): Move invalid checks here instead of PrerenderContents?
848 PrerenderContentsData data(prerender_contents, GetCurrentTime());
849
850 prerender_list_.push_back(data);
851
852 if (IsControlGroup()) {
853 data.contents_->set_final_status(FINAL_STATUS_CONTROL_GROUP);
854 } else {
855 last_prerender_start_time_ = GetCurrentTimeTicks();
856 data.contents_->StartPrerendering(source_render_view_host,
857 session_storage_namespace);
858 }
859 while (prerender_list_.size() > config_.max_elements) {
860 data = prerender_list_.front();
861 prerender_list_.pop_front();
862 data.contents_->Destroy(FINAL_STATUS_EVICTED);
863 }
864 StartSchedulingPeriodicCleanups();
865 return true;
866 }
867
868 PrerenderContents* PrerenderManager::GetEntry(const GURL& url) {
cbentzel 2012/01/25 12:14:01 I didn't check if all of the methods in this block
869 return GetEntryButNotSpecifiedWC(url, NULL);
870 }
871
872 PrerenderContents* PrerenderManager::GetEntryButNotSpecifiedWC(
873 const GURL& url,
874 WebContents* wc) {
875 DCHECK(CalledOnValidThread());
876 DeleteOldEntries();
877 DeletePendingDeleteEntries();
878 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin();
879 it != prerender_list_.end();
880 ++it) {
881 PrerenderContents* prerender_contents = it->contents_;
882 if (prerender_contents->MatchesURL(url, NULL)) {
883 if (!prerender_contents->prerender_contents() ||
884 !wc ||
885 prerender_contents->prerender_contents()->web_contents() != wc) {
886 prerender_list_.erase(it);
887 return prerender_contents;
888 }
889 }
890 }
891 // Entry not found.
892 return NULL;
893 }
894
895 void PrerenderManager::StartSchedulingPeriodicCleanups() {
896 DCHECK(CalledOnValidThread());
897 if (repeating_timer_.IsRunning())
898 return;
899 repeating_timer_.Start(FROM_HERE,
900 base::TimeDelta::FromMilliseconds(kPeriodicCleanupIntervalMs),
901 this,
902 &PrerenderManager::PeriodicCleanup);
903 }
904
905 void PrerenderManager::MaybeStopSchedulingPeriodicCleanups() {
906 if (!prerender_list_.empty())
907 return;
908
909 DCHECK(CalledOnValidThread());
910 repeating_timer_.Stop();
911 }
912
913 void PrerenderManager::PeriodicCleanup() {
914 DCHECK(CalledOnValidThread());
915 DeleteOldTabContents();
916 DeleteOldEntries();
917
918 // Grab a copy of the current PrerenderContents pointers, so that we
919 // will not interfere with potential deletions of the list.
920 std::vector<PrerenderContents*> prerender_contents;
921 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin();
922 it != prerender_list_.end();
923 ++it) {
924 DCHECK(it->contents_);
925 prerender_contents.push_back(it->contents_);
926 }
927 for (std::vector<PrerenderContents*>::iterator it =
928 prerender_contents.begin();
929 it != prerender_contents.end();
930 ++it) {
931 (*it)->DestroyWhenUsingTooManyResources();
932 }
933
934 DeletePendingDeleteEntries();
935 }
936
937 void PrerenderManager::PostCleanupTask() {
938 DCHECK(CalledOnValidThread());
939 MessageLoop::current()->PostTask(
940 FROM_HERE,
941 base::Bind(&PrerenderManager::PeriodicCleanup,
942 weak_factory_.GetWeakPtr()));
943 }
944
945 bool PrerenderManager::IsPrerenderElementFresh(const base::Time start) const {
946 DCHECK(CalledOnValidThread());
947 base::Time now = GetCurrentTime();
948 return (now - start < config_.max_age);
949 }
950
951 void PrerenderManager::DeleteOldEntries() {
952 DCHECK(CalledOnValidThread());
953 while (!prerender_list_.empty()) {
954 PrerenderContentsData data = prerender_list_.front();
955 if (IsPrerenderElementFresh(data.start_time_))
956 return;
957 data.contents_->Destroy(FINAL_STATUS_TIMED_OUT);
958 }
959 MaybeStopSchedulingPeriodicCleanups();
960 }
961
962 base::Time PrerenderManager::GetCurrentTime() const {
963 return base::Time::Now();
964 }
965
966 base::TimeTicks PrerenderManager::GetCurrentTimeTicks() const {
967 return base::TimeTicks::Now();
968 }
969
970 PrerenderContents* PrerenderManager::CreatePrerenderContents(
971 const GURL& url,
972 const content::Referrer& referrer,
973 Origin origin,
974 uint8 experiment_id) {
975 DCHECK(CalledOnValidThread());
976 return prerender_contents_factory_->CreatePrerenderContents(
977 this, prerender_tracker_, profile_, url,
978 referrer, origin, experiment_id);
979 }
980
981 bool PrerenderManager::IsPendingDelete(PrerenderContents* entry) const {
982 DCHECK(CalledOnValidThread());
983 for (std::list<PrerenderContents*>::const_iterator it =
984 pending_delete_list_.begin();
985 it != pending_delete_list_.end();
986 ++it) {
987 if (*it == entry)
988 return true;
989 }
990
991 return false;
992 }
993
994 void PrerenderManager::DeletePendingDeleteEntries() {
995 while (!pending_delete_list_.empty()) {
996 PrerenderContents* contents = pending_delete_list_.front();
997 pending_delete_list_.pop_front();
998 delete contents;
999 }
1000 }
1001
1002 PrerenderContents* PrerenderManager::FindEntry(const GURL& url) {
1003 DCHECK(CalledOnValidThread());
1004 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin();
1005 it != prerender_list_.end();
1006 ++it) {
1007 if (it->contents_->MatchesURL(url, NULL))
1008 return it->contents_;
1009 }
1010 // Entry not found.
1011 return NULL;
1012 }
1013
1014 std::list<PrerenderManager::PrerenderContentsData>::iterator
1015 PrerenderManager::FindPrerenderContentsForChildRouteIdPair(
1016 const std::pair<int, int>& child_route_id_pair) {
1017 std::list<PrerenderContentsData>::iterator it = prerender_list_.begin();
1018 for (; it != prerender_list_.end(); ++it) {
1019 PrerenderContents* prerender_contents = it->contents_;
1020
1021 int child_id;
1022 int route_id;
1023 bool has_child_id = prerender_contents->GetChildId(&child_id);
1024 bool has_route_id = has_child_id &&
1025 prerender_contents->GetRouteId(&route_id);
1026
1027 if (has_child_id && has_route_id &&
1028 child_id == child_route_id_pair.first &&
1029 route_id == child_route_id_pair.second) {
1030 break;
1031 }
1032 }
1033 return it;
1034 }
1035
1036 bool PrerenderManager::DoesRateLimitAllowPrerender() const {
1037 DCHECK(CalledOnValidThread());
1038 base::TimeDelta elapsed_time =
1039 GetCurrentTimeTicks() - last_prerender_start_time_;
1040 histograms_->RecordTimeBetweenPrerenderRequests(elapsed_time);
1041 if (!config_.rate_limit_enabled)
1042 return true;
1043 return elapsed_time >
1044 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs);
1045 }
1046
1047 void PrerenderManager::DeleteOldTabContents() {
1048 while (!old_tab_contents_list_.empty()) {
1049 TabContentsWrapper* tab_contents = old_tab_contents_list_.front();
1050 old_tab_contents_list_.pop_front();
1051 // TODO(dominich): should we use Instant Unload Handler here?
1052 delete tab_contents;
1053 }
1054 }
1055
1056 void PrerenderManager::CleanUpOldNavigations() {
1057 DCHECK(CalledOnValidThread());
1058
1059 // Cutoff. Navigations before this cutoff can be discarded.
1060 base::TimeTicks cutoff = GetCurrentTimeTicks() -
1061 base::TimeDelta::FromMilliseconds(kNavigationRecordWindowMs);
1062 while (!navigations_.empty()) {
1063 if (navigations_.front().time_ > cutoff)
1064 break;
1065 navigations_.pop_front();
1066 }
1067 }
1068
1069 void PrerenderManager::ScheduleDeleteOldTabContents(
1070 TabContentsWrapper* tab,
1071 OnCloseTabContentsDeleter* deleter) {
1072 old_tab_contents_list_.push_back(tab);
1073 PostCleanupTask();
1074
1075 if (deleter) {
1076 ScopedVector<OnCloseTabContentsDeleter>::iterator i = std::find(
1077 on_close_tab_contents_deleters_.begin(),
1078 on_close_tab_contents_deleters_.end(),
1079 deleter);
1080 DCHECK(i != on_close_tab_contents_deleters_.end());
1081 on_close_tab_contents_deleters_.erase(i);
1082 }
1083 }
1084
1063 void PrerenderManager::AddToHistory(PrerenderContents* contents) { 1085 void PrerenderManager::AddToHistory(PrerenderContents* contents) {
1064 PrerenderHistory::Entry entry(contents->prerender_url(), 1086 PrerenderHistory::Entry entry(contents->prerender_url(),
1065 contents->final_status(), 1087 contents->final_status(),
1066 contents->origin(), 1088 contents->origin(),
1067 base::Time::Now()); 1089 base::Time::Now());
1068 prerender_history_->AddEntry(entry); 1090 prerender_history_->AddEntry(entry);
1069 } 1091 }
1070 1092
1071 void PrerenderManager::RecordNavigation(const GURL& url) { 1093 void PrerenderManager::RecordNavigation(const GURL& url) {
1072 DCHECK(CalledOnValidThread()); 1094 DCHECK(CalledOnValidThread());
(...skipping 19 matching lines...) Expand all
1092 void PrerenderManager::DestroyAllContents(FinalStatus final_status) { 1114 void PrerenderManager::DestroyAllContents(FinalStatus final_status) {
1093 DeleteOldTabContents(); 1115 DeleteOldTabContents();
1094 while (!prerender_list_.empty()) { 1116 while (!prerender_list_.empty()) {
1095 PrerenderContentsData data = prerender_list_.front(); 1117 PrerenderContentsData data = prerender_list_.front();
1096 prerender_list_.pop_front(); 1118 prerender_list_.pop_front();
1097 data.contents_->Destroy(final_status); 1119 data.contents_->Destroy(final_status);
1098 } 1120 }
1099 DeletePendingDeleteEntries(); 1121 DeletePendingDeleteEntries();
1100 } 1122 }
1101 1123
1102 void PrerenderManager::RecordFinalStatus(Origin origin,
1103 uint8 experiment_id,
1104 FinalStatus final_status) const {
1105 histograms_->RecordFinalStatus(origin, experiment_id, final_status);
1106 }
1107
1108 PrerenderManager* FindPrerenderManagerUsingRenderProcessId( 1124 PrerenderManager* FindPrerenderManagerUsingRenderProcessId(
1109 int render_process_id) { 1125 int render_process_id) {
1110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1111 content::RenderProcessHost* render_process_host = 1127 content::RenderProcessHost* render_process_host =
1112 content::RenderProcessHost::FromID(render_process_id); 1128 content::RenderProcessHost::FromID(render_process_id);
1113 // Each render process is guaranteed to only hold RenderViews owned by the 1129 // Each render process is guaranteed to only hold RenderViews owned by the
1114 // same BrowserContext. This is enforced by 1130 // same BrowserContext. This is enforced by
1115 // RenderProcessHost::GetExistingProcessHost. 1131 // RenderProcessHost::GetExistingProcessHost.
1116 if (!render_process_host || !render_process_host->GetBrowserContext()) 1132 if (!render_process_host || !render_process_host->GetBrowserContext())
1117 return NULL; 1133 return NULL;
1118 Profile* profile = Profile::FromBrowserContext( 1134 Profile* profile = Profile::FromBrowserContext(
1119 render_process_host->GetBrowserContext()); 1135 render_process_host->GetBrowserContext());
1120 if (!profile) 1136 if (!profile)
1121 return NULL; 1137 return NULL;
1122 return PrerenderManagerFactory::GetInstance()->GetForProfile(profile); 1138 return PrerenderManagerFactory::GetInstance()->GetForProfile(profile);
1123 } 1139 }
1124 1140
1125 } // namespace prerender 1141 } // namespace prerender
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698