Chromium Code Reviews| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <functional> | 8 #include <functional> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 bool PrerenderManager::is_prefetch_enabled_ = false; | 158 bool PrerenderManager::is_prefetch_enabled_ = false; |
| 159 | 159 |
| 160 // static | 160 // static |
| 161 int PrerenderManager::prerenders_per_session_count_ = 0; | 161 int PrerenderManager::prerenders_per_session_count_ = 0; |
| 162 | 162 |
| 163 // static | 163 // static |
| 164 PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = | 164 PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = |
| 165 PRERENDER_MODE_ENABLED; | 165 PRERENDER_MODE_ENABLED; |
| 166 | 166 |
| 167 struct PrerenderManager::NavigationRecord { | 167 struct PrerenderManager::NavigationRecord { |
| 168 GURL url_; | |
| 169 base::TimeTicks time_; | |
| 170 NavigationRecord(const GURL& url, base::TimeTicks time) | 168 NavigationRecord(const GURL& url, base::TimeTicks time) |
| 171 : url_(url), | 169 : url(url), |
| 172 time_(time) { | 170 time(time) { |
| 173 } | 171 } |
| 172 | |
| 173 GURL url; | |
| 174 base::TimeTicks time; | |
| 174 }; | 175 }; |
| 175 | 176 |
| 177 PrerenderManager::PrerenderedWebContentsData:: | |
| 178 PrerenderedWebContentsData(Origin origin) : origin(origin) { | |
| 179 } | |
| 180 | |
| 181 PrerenderManager::WouldBePrerenderedWebContentsData:: | |
| 182 WouldBePrerenderedWebContentsData(Origin origin) | |
| 183 : origin(origin), | |
|
mmenke
2012/10/15 18:46:22
nit: 4 space indent.
gavinp
2012/10/16 13:52:01
Done.
| |
| 184 state(WAITING_FOR_PROVISIONAL_LOAD) { | |
| 185 } | |
| 186 | |
| 176 PrerenderManager::PrerenderManager(Profile* profile, | 187 PrerenderManager::PrerenderManager(Profile* profile, |
| 177 PrerenderTracker* prerender_tracker) | 188 PrerenderTracker* prerender_tracker) |
| 178 : enabled_(true), | 189 : enabled_(true), |
| 179 profile_(profile), | 190 profile_(profile), |
| 180 prerender_tracker_(prerender_tracker), | 191 prerender_tracker_(prerender_tracker), |
| 181 prerender_contents_factory_(PrerenderContents::CreateFactory()), | 192 prerender_contents_factory_(PrerenderContents::CreateFactory()), |
| 182 last_prerender_start_time_(GetCurrentTimeTicks() - | 193 last_prerender_start_time_(GetCurrentTimeTicks() - |
| 183 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs)), | 194 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs)), |
| 184 weak_factory_(this), | 195 weak_factory_(this), |
| 185 prerender_history_(new PrerenderHistory(kHistoryLength)), | 196 prerender_history_(new PrerenderHistory(kHistoryLength)), |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 FindPrerenderDataForChildAndRoute(process_id, route_id)) { | 236 FindPrerenderDataForChildAndRoute(process_id, route_id)) { |
| 226 // Instead of prerendering from inside of a running prerender, we will defer | 237 // Instead of prerendering from inside of a running prerender, we will defer |
| 227 // this request until its launcher is made visible. | 238 // this request until its launcher is made visible. |
| 228 if (PrerenderContents* contents = parent_prerender_data->contents_) { | 239 if (PrerenderContents* contents = parent_prerender_data->contents_) { |
| 229 pending_prerender_list_.push_back( | 240 pending_prerender_list_.push_back( |
| 230 linked_ptr<PrerenderData>(new PrerenderData(this))); | 241 linked_ptr<PrerenderData>(new PrerenderData(this))); |
| 231 PrerenderHandle* prerender_handle = | 242 PrerenderHandle* prerender_handle = |
| 232 new PrerenderHandle(pending_prerender_list_.back().get()); | 243 new PrerenderHandle(pending_prerender_list_.back().get()); |
| 233 contents->AddPendingPrerender( | 244 contents->AddPendingPrerender( |
| 234 prerender_handle->weak_ptr_factory_.GetWeakPtr(), | 245 prerender_handle->weak_ptr_factory_.GetWeakPtr(), |
| 235 url, referrer, size); | 246 ORIGIN_LINK_REL_PRERENDER, url, referrer, size); |
| 236 return prerender_handle; | 247 return prerender_handle; |
| 237 } | 248 } |
| 238 } | 249 } |
| 239 | 250 |
| 240 // Unit tests pass in a process_id == -1. | 251 // Unit tests pass in a process_id == -1. |
| 241 SessionStorageNamespace* session_storage_namespace = NULL; | 252 SessionStorageNamespace* session_storage_namespace = NULL; |
| 242 if (process_id != -1) { | 253 if (process_id != -1) { |
| 243 RenderViewHost* source_render_view_host = | 254 RenderViewHost* source_render_view_host = |
| 244 RenderViewHost::FromID(process_id, route_id); | 255 RenderViewHost::FromID(process_id, route_id); |
| 245 if (!source_render_view_host) | 256 if (!source_render_view_host) |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 284 while (!active_prerender_list_.empty()) { | 295 while (!active_prerender_list_.empty()) { |
| 285 PrerenderContents* prerender_contents = | 296 PrerenderContents* prerender_contents = |
| 286 active_prerender_list_.front()->contents(); | 297 active_prerender_list_.front()->contents(); |
| 287 prerender_contents->Destroy(FINAL_STATUS_CANCELLED); | 298 prerender_contents->Destroy(FINAL_STATUS_CANCELLED); |
| 288 } | 299 } |
| 289 } | 300 } |
| 290 | 301 |
| 291 bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, | 302 bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, |
| 292 const GURL& url) { | 303 const GURL& url) { |
| 293 DCHECK(CalledOnValidThread()); | 304 DCHECK(CalledOnValidThread()); |
| 294 DCHECK(!IsWebContentsPrerendering(web_contents)); | 305 DCHECK(!IsWebContentsPrerendering(web_contents, NULL)); |
| 295 | 306 |
| 296 DeleteOldEntries(); | 307 DeleteOldEntries(); |
| 297 DeletePendingDeleteEntries(); | 308 DeletePendingDeleteEntries(); |
| 298 // TODO(ajwong): This doesn't handle isolated apps correctly. | 309 // TODO(ajwong): This doesn't handle isolated apps correctly. |
| 299 PrerenderData* prerender_data = FindPrerenderData( | 310 PrerenderData* prerender_data = FindPrerenderData( |
| 300 url, | 311 url, |
| 301 web_contents->GetController().GetDefaultSessionStorageNamespace()); | 312 web_contents->GetController().GetDefaultSessionStorageNamespace()); |
| 302 if (!prerender_data) | 313 if (!prerender_data) |
| 303 return false; | 314 return false; |
| 304 DCHECK(prerender_data->contents_); | 315 DCHECK(prerender_data->contents_); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 321 // Do not use the prerendered version if there is an opener object. | 332 // Do not use the prerendered version if there is an opener object. |
| 322 if (web_contents->HasOpener()) { | 333 if (web_contents->HasOpener()) { |
| 323 prerender_contents.release()->Destroy(FINAL_STATUS_WINDOW_OPENER); | 334 prerender_contents.release()->Destroy(FINAL_STATUS_WINDOW_OPENER); |
| 324 return false; | 335 return false; |
| 325 } | 336 } |
| 326 | 337 |
| 327 // If we are just in the control group (which can be detected by noticing | 338 // If we are just in the control group (which can be detected by noticing |
| 328 // that prerendering hasn't even started yet), record that |web_contents| now | 339 // that prerendering hasn't even started yet), record that |web_contents| now |
| 329 // would be showing a prerendered contents, but otherwise, don't do anything. | 340 // would be showing a prerendered contents, but otherwise, don't do anything. |
| 330 if (!prerender_contents->prerendering_has_started()) { | 341 if (!prerender_contents->prerendering_has_started()) { |
| 331 MarkWebContentsAsWouldBePrerendered(web_contents); | 342 MarkWebContentsAsWouldBePrerendered(web_contents, |
| 343 prerender_contents->origin()); | |
| 332 prerender_contents.release()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); | 344 prerender_contents.release()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); |
| 333 return false; | 345 return false; |
| 334 } | 346 } |
| 335 | 347 |
| 336 // Don't use prerendered pages if debugger is attached to the tab. | 348 // Don't use prerendered pages if debugger is attached to the tab. |
| 337 // See http://crbug.com/98541 | 349 // See http://crbug.com/98541 |
| 338 if (content::DevToolsAgentHostRegistry::IsDebuggerAttached(web_contents)) { | 350 if (content::DevToolsAgentHostRegistry::IsDebuggerAttached(web_contents)) { |
| 339 DestroyAndMarkMatchCompleteAsUsed(prerender_contents.release(), | 351 DestroyAndMarkMatchCompleteAsUsed(prerender_contents.release(), |
| 340 FINAL_STATUS_DEVTOOLS_ATTACHED); | 352 FINAL_STATUS_DEVTOOLS_ATTACHED); |
| 341 return false; | 353 return false; |
| 342 } | 354 } |
| 343 | 355 |
| 344 // If the prerendered page is in the middle of a cross-site navigation, | 356 // If the prerendered page is in the middle of a cross-site navigation, |
| 345 // don't swap it in because there isn't a good way to merge histories. | 357 // don't swap it in because there isn't a good way to merge histories. |
| 346 if (prerender_contents->IsCrossSiteNavigationPending()) { | 358 if (prerender_contents->IsCrossSiteNavigationPending()) { |
| 347 DestroyAndMarkMatchCompleteAsUsed( | 359 DestroyAndMarkMatchCompleteAsUsed( |
| 348 prerender_contents.release(), | 360 prerender_contents.release(), |
| 349 FINAL_STATUS_CROSS_SITE_NAVIGATION_PENDING); | 361 FINAL_STATUS_CROSS_SITE_NAVIGATION_PENDING); |
| 350 return false; | 362 return false; |
| 351 } | 363 } |
| 352 | 364 |
| 353 // For bookkeeping purposes, we need to mark this WebContents to | 365 // For bookkeeping purposes, we need to mark this WebContents to |
| 354 // reflect that it would have been prerendered. | 366 // reflect that it would have been prerendered. |
| 355 if (GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP) { | 367 if (GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP) { |
| 356 MarkWebContentsAsWouldBePrerendered(web_contents); | 368 MarkWebContentsAsWouldBePrerendered(web_contents, |
| 369 prerender_contents->origin()); | |
| 357 prerender_contents.release()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); | 370 prerender_contents.release()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); |
| 358 return false; | 371 return false; |
| 359 } | 372 } |
| 360 | 373 |
| 361 int child_id, route_id; | 374 int child_id, route_id; |
| 362 CHECK(prerender_contents->GetChildId(&child_id)); | 375 CHECK(prerender_contents->GetChildId(&child_id)); |
| 363 CHECK(prerender_contents->GetRouteId(&route_id)); | 376 CHECK(prerender_contents->GetRouteId(&route_id)); |
| 364 | 377 |
| 365 // Try to set the prerendered page as used, so any subsequent attempts to | 378 // Try to set the prerendered page as used, so any subsequent attempts to |
| 366 // cancel on other threads will fail. If this fails because the prerender | 379 // cancel on other threads will fail. If this fails because the prerender |
| 367 // was already cancelled, possibly on another thread, fail. | 380 // was already cancelled, possibly on another thread, fail. |
| 368 if (!prerender_tracker_->TryUse(child_id, route_id)) | 381 if (!prerender_tracker_->TryUse(child_id, route_id)) |
| 369 return false; | 382 return false; |
| 370 | 383 |
| 371 // At this point, we've determined that we will use the prerender. | 384 // At this point, we've determined that we will use the prerender. |
| 372 | 385 |
| 373 if (!prerender_contents->load_start_time().is_null()) { | 386 if (!prerender_contents->load_start_time().is_null()) { |
| 374 histograms_->RecordTimeUntilUsed( | 387 histograms_->RecordTimeUntilUsed( |
| 388 prerender_contents->origin(), | |
| 375 GetCurrentTimeTicks() - prerender_contents->load_start_time(), | 389 GetCurrentTimeTicks() - prerender_contents->load_start_time(), |
| 376 config_.time_to_live); | 390 config_.time_to_live); |
| 377 } | 391 } |
| 378 | 392 |
| 379 histograms_->RecordPerSessionCount(++prerenders_per_session_count_); | 393 histograms_->RecordPerSessionCount(prerender_contents->origin(), |
| 394 ++prerenders_per_session_count_); | |
| 380 histograms_->RecordUsedPrerender(prerender_contents->origin()); | 395 histograms_->RecordUsedPrerender(prerender_contents->origin()); |
| 381 prerender_contents->set_final_status(FINAL_STATUS_USED); | 396 prerender_contents->set_final_status(FINAL_STATUS_USED); |
| 382 | 397 |
| 383 RenderViewHost* new_render_view_host = | 398 RenderViewHost* new_render_view_host = |
| 384 prerender_contents->prerender_contents()->web_contents()-> | 399 prerender_contents->prerender_contents()->web_contents()-> |
| 385 GetRenderViewHost(); | 400 GetRenderViewHost(); |
| 386 new_render_view_host->Send( | 401 new_render_view_host->Send( |
| 387 new PrerenderMsg_SetIsPrerendering(new_render_view_host->GetRoutingID(), | 402 new PrerenderMsg_SetIsPrerendering(new_render_view_host->GetRoutingID(), |
| 388 false)); | 403 false)); |
| 389 | 404 |
| 390 // Start pending prerender requests from the PrerenderContents, if there are | 405 // Start pending prerender requests from the PrerenderContents, if there are |
| 391 // any. | 406 // any. |
| 392 prerender_contents->StartPendingPrerenders(); | 407 prerender_contents->StartPendingPrerenders(); |
| 393 | 408 |
| 394 TabContents* new_tab_contents = | 409 TabContents* new_tab_contents = |
| 395 prerender_contents->ReleasePrerenderContents(); | 410 prerender_contents->ReleasePrerenderContents(); |
| 396 TabContents* old_tab_contents = TabContents::FromWebContents(web_contents); | 411 TabContents* old_tab_contents = TabContents::FromWebContents(web_contents); |
| 397 DCHECK(new_tab_contents); | 412 DCHECK(new_tab_contents); |
| 398 DCHECK(old_tab_contents); | 413 DCHECK(old_tab_contents); |
| 399 | 414 |
| 400 MarkWebContentsAsPrerendered(new_tab_contents->web_contents()); | 415 MarkWebContentsAsPrerendered(new_tab_contents->web_contents(), |
| 416 prerender_contents->origin()); | |
| 401 | 417 |
| 402 // Merge the browsing history. | 418 // Merge the browsing history. |
| 403 new_tab_contents->web_contents()->GetController().CopyStateFromAndPrune( | 419 new_tab_contents->web_contents()->GetController().CopyStateFromAndPrune( |
| 404 &old_tab_contents->web_contents()->GetController()); | 420 &old_tab_contents->web_contents()->GetController()); |
| 405 CoreTabHelper::FromWebContents(old_tab_contents->web_contents())->delegate()-> | 421 CoreTabHelper::FromWebContents(old_tab_contents->web_contents())->delegate()-> |
| 406 SwapTabContents(old_tab_contents->web_contents(), | 422 SwapTabContents(old_tab_contents->web_contents(), |
| 407 new_tab_contents->web_contents()); | 423 new_tab_contents->web_contents()); |
| 408 prerender_contents->CommitHistory(new_tab_contents); | 424 prerender_contents->CommitHistory(new_tab_contents); |
| 409 | 425 |
| 410 GURL icon_url = prerender_contents->icon_url(); | 426 GURL icon_url = prerender_contents->icon_url(); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 504 WebContents* web_contents, | 520 WebContents* web_contents, |
| 505 const GURL& url) { | 521 const GURL& url) { |
| 506 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 522 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 507 PrerenderManager* prerender_manager = | 523 PrerenderManager* prerender_manager = |
| 508 PrerenderManagerFactory::GetForProfile( | 524 PrerenderManagerFactory::GetForProfile( |
| 509 Profile::FromBrowserContext(web_contents->GetBrowserContext())); | 525 Profile::FromBrowserContext(web_contents->GetBrowserContext())); |
| 510 if (!prerender_manager) | 526 if (!prerender_manager) |
| 511 return; | 527 return; |
| 512 if (!prerender_manager->IsEnabled()) | 528 if (!prerender_manager->IsEnabled()) |
| 513 return; | 529 return; |
| 514 bool was_prerender = | 530 |
| 515 prerender_manager->IsWebContentsPrerendered(web_contents); | 531 Origin prerender_origin = ORIGIN_NONE; |
| 532 if (prerender_manager->IsWebContentsPrerendering(web_contents, | |
| 533 &prerender_origin)) { | |
| 534 prerender_manager->histograms_->RecordPageLoadTimeNotSwappedIn( | |
| 535 prerender_origin, perceived_page_load_time, url); | |
| 536 return; | |
| 537 } | |
| 538 | |
| 539 bool was_prerender = prerender_manager->IsWebContentsPrerendered( | |
| 540 web_contents, &prerender_origin); | |
| 516 bool was_complete_prerender = was_prerender || | 541 bool was_complete_prerender = was_prerender || |
| 517 prerender_manager->WouldWebContentsBePrerendered(web_contents); | 542 prerender_manager->WouldWebContentsBePrerendered(web_contents, |
| 518 if (prerender_manager->IsWebContentsPrerendering(web_contents)) { | 543 &prerender_origin); |
| 519 prerender_manager->histograms_->RecordPageLoadTimeNotSwappedIn( | 544 prerender_manager->histograms_->RecordPerceivedPageLoadTime( |
| 520 perceived_page_load_time, url); | 545 prerender_origin, perceived_page_load_time, was_prerender, |
| 521 } else { | 546 was_complete_prerender, url); |
| 522 prerender_manager->histograms_->RecordPerceivedPageLoadTime( | 547 |
| 523 perceived_page_load_time, was_prerender, was_complete_prerender, url); | 548 if (was_prerender) { |
| 524 prerender_manager->histograms_->RecordPercentLoadDoneAtSwapin( | 549 prerender_manager->histograms_->RecordPercentLoadDoneAtSwapin( |
| 525 fraction_plt_elapsed_at_swap_in); | 550 prerender_origin, fraction_plt_elapsed_at_swap_in); |
| 526 if (prerender_manager->local_predictor_.get()) { | |
| 527 prerender_manager->local_predictor_-> | |
| 528 OnPLTEventForURL(url, perceived_page_load_time); | |
| 529 } | |
| 530 } | 551 } |
| 552 if (prerender_manager->local_predictor_.get()) { | |
| 553 prerender_manager->local_predictor_-> | |
| 554 OnPLTEventForURL(url, perceived_page_load_time); | |
| 555 } | |
| 556 } | |
| 557 | |
| 558 void PrerenderManager::RecordFractionPixelsFinalAtSwapin( | |
| 559 content::WebContents* web_contents, | |
| 560 double fraction) { | |
| 561 Origin origin = ORIGIN_NONE; | |
| 562 bool is_prerendered = IsWebContentsPrerendered(web_contents, &origin); | |
| 563 DCHECK(is_prerendered); | |
| 564 histograms_->RecordFractionPixelsFinalAtSwapin(origin, fraction); | |
| 531 } | 565 } |
| 532 | 566 |
| 533 void PrerenderManager::set_enabled(bool enabled) { | 567 void PrerenderManager::set_enabled(bool enabled) { |
| 534 DCHECK(CalledOnValidThread()); | 568 DCHECK(CalledOnValidThread()); |
| 535 enabled_ = enabled; | 569 enabled_ = enabled; |
| 536 } | 570 } |
| 537 | 571 |
| 538 // static | 572 // static |
| 539 bool PrerenderManager::IsPrefetchEnabled() { | 573 bool PrerenderManager::IsPrefetchEnabled() { |
| 540 return is_prefetch_enabled_; | 574 return is_prefetch_enabled_; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 593 bool PrerenderManager::IsControlGroup() { | 627 bool PrerenderManager::IsControlGroup() { |
| 594 return GetMode() == PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP; | 628 return GetMode() == PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP; |
| 595 } | 629 } |
| 596 | 630 |
| 597 // static | 631 // static |
| 598 bool PrerenderManager::IsNoUseGroup() { | 632 bool PrerenderManager::IsNoUseGroup() { |
| 599 return GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP; | 633 return GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP; |
| 600 } | 634 } |
| 601 | 635 |
| 602 bool PrerenderManager::IsWebContentsPrerendering( | 636 bool PrerenderManager::IsWebContentsPrerendering( |
| 603 WebContents* web_contents) const { | 637 WebContents* web_contents, |
| 638 Origin* origin) const { | |
| 604 DCHECK(CalledOnValidThread()); | 639 DCHECK(CalledOnValidThread()); |
| 605 if (GetPrerenderContents(web_contents)) | 640 if (PrerenderContents* prerender_contents = |
| 641 GetPrerenderContents(web_contents)) { | |
| 642 if (origin) | |
| 643 *origin = prerender_contents->origin(); | |
| 606 return true; | 644 return true; |
| 645 } | |
| 607 | 646 |
| 608 // Also look through the pending-deletion list. | 647 // Also look through the pending-deletion list. |
| 609 for (std::list<PrerenderContents*>::const_iterator it = | 648 for (std::list<PrerenderContents*>::const_iterator it = |
| 610 pending_delete_list_.begin(); | 649 pending_delete_list_.begin(); |
| 611 it != pending_delete_list_.end(); | 650 it != pending_delete_list_.end(); |
| 612 ++it) { | 651 ++it) { |
| 613 TabContents* prerender_tab_contents = (*it)->prerender_contents(); | 652 TabContents* prerender_tab_contents = (*it)->prerender_contents(); |
| 614 if (prerender_tab_contents && | 653 if (prerender_tab_contents && |
| 615 prerender_tab_contents->web_contents() == web_contents) | 654 prerender_tab_contents->web_contents() == web_contents) { |
| 655 if (origin) | |
| 656 *origin = (*it)->origin(); | |
| 616 return true; | 657 return true; |
| 658 } | |
| 617 } | 659 } |
| 618 | 660 |
| 619 return false; | 661 return false; |
| 620 } | 662 } |
| 621 | 663 |
| 622 PrerenderContents* PrerenderManager::GetPrerenderContents( | 664 PrerenderContents* PrerenderManager::GetPrerenderContents( |
| 623 content::WebContents* web_contents) const { | 665 content::WebContents* web_contents) const { |
| 624 DCHECK(CalledOnValidThread()); | 666 DCHECK(CalledOnValidThread()); |
| 625 for (std::list<linked_ptr<PrerenderData> >::const_iterator it = | 667 for (std::list<linked_ptr<PrerenderData> >::const_iterator it = |
| 626 active_prerender_list_.begin(); | 668 active_prerender_list_.begin(); |
| 627 it != active_prerender_list_.end(); | 669 it != active_prerender_list_.end(); |
| 628 ++it) { | 670 ++it) { |
| 629 TabContents* prerender_tab_contents = | 671 TabContents* prerender_tab_contents = |
| 630 it->get()->contents_->prerender_contents(); | 672 it->get()->contents_->prerender_contents(); |
| 631 if (prerender_tab_contents && | 673 if (prerender_tab_contents && |
| 632 prerender_tab_contents->web_contents() == web_contents) { | 674 prerender_tab_contents->web_contents() == web_contents) { |
| 633 return it->get()->contents_; | 675 return it->get()->contents_; |
| 634 } | 676 } |
| 635 } | 677 } |
| 636 return NULL; | 678 return NULL; |
| 637 } | 679 } |
| 638 | 680 |
| 639 void PrerenderManager::MarkWebContentsAsPrerendered(WebContents* web_contents) { | 681 void PrerenderManager::MarkWebContentsAsPrerendered(WebContents* web_contents, |
| 682 Origin origin) { | |
| 640 DCHECK(CalledOnValidThread()); | 683 DCHECK(CalledOnValidThread()); |
| 641 prerendered_tab_contents_set_.insert(web_contents); | 684 prerendered_web_contents_data_.insert( |
| 685 base::hash_map<content::WebContents*, | |
| 686 PrerenderedWebContentsData>::value_type( | |
| 687 web_contents, PrerenderedWebContentsData(origin))); | |
| 642 } | 688 } |
| 643 | 689 |
| 644 void PrerenderManager::MarkWebContentsAsWouldBePrerendered( | 690 void PrerenderManager::MarkWebContentsAsWouldBePrerendered( |
| 645 WebContents* web_contents) { | 691 WebContents* web_contents, |
| 692 Origin origin) { | |
| 646 DCHECK(CalledOnValidThread()); | 693 DCHECK(CalledOnValidThread()); |
| 647 would_be_prerendered_map_[web_contents] = true; | 694 would_be_prerendered_map_.insert( |
| 695 base::hash_map<content::WebContents*, | |
| 696 WouldBePrerenderedWebContentsData>::value_type( | |
| 697 web_contents, | |
| 698 WouldBePrerenderedWebContentsData(origin))); | |
| 648 } | 699 } |
| 649 | 700 |
| 650 void PrerenderManager::MarkWebContentsAsNotPrerendered( | 701 void PrerenderManager::MarkWebContentsAsNotPrerendered( |
| 651 WebContents* web_contents) { | 702 WebContents* web_contents) { |
| 652 DCHECK(CalledOnValidThread()); | 703 DCHECK(CalledOnValidThread()); |
| 653 prerendered_tab_contents_set_.erase(web_contents); | 704 prerendered_web_contents_data_.erase(web_contents); |
| 654 WouldBePrerenderedMap::iterator it = | 705 base::hash_map<content::WebContents*, WouldBePrerenderedWebContentsData>:: |
| 655 would_be_prerendered_map_.find(web_contents); | 706 iterator it = would_be_prerendered_map_.find(web_contents); |
| 656 if (it != would_be_prerendered_map_.end()) { | 707 if (it != would_be_prerendered_map_.end()) { |
| 657 bool first_time = it->second; | 708 if (it->second.state == |
| 658 if (first_time) { | 709 WouldBePrerenderedWebContentsData::WAITING_FOR_PROVISIONAL_LOAD) { |
| 659 it->second = false; | 710 it->second.state = |
| 711 WouldBePrerenderedWebContentsData::SEEN_PROVISIONAL_LOAD; | |
| 660 } else { | 712 } else { |
| 661 would_be_prerendered_map_.erase(it); | 713 would_be_prerendered_map_.erase(it); |
| 662 } | 714 } |
| 663 } | 715 } |
| 664 } | 716 } |
| 665 | 717 |
| 666 bool PrerenderManager::IsWebContentsPrerendered( | 718 bool PrerenderManager::IsWebContentsPrerendered( |
| 667 content::WebContents* web_contents) const { | 719 content::WebContents* web_contents, |
| 720 Origin* origin) const { | |
| 668 DCHECK(CalledOnValidThread()); | 721 DCHECK(CalledOnValidThread()); |
| 669 return prerendered_tab_contents_set_.count(web_contents) > 0; | 722 base::hash_map<content::WebContents*, PrerenderedWebContentsData>:: |
| 723 const_iterator it = prerendered_web_contents_data_.find(web_contents); | |
| 724 if (it == prerendered_web_contents_data_.end()) | |
| 725 return false; | |
| 726 if (origin) | |
| 727 *origin = it->second.origin; | |
| 728 return true; | |
| 670 } | 729 } |
| 671 | 730 |
| 672 bool PrerenderManager::WouldWebContentsBePrerendered( | 731 bool PrerenderManager::WouldWebContentsBePrerendered( |
| 673 WebContents* web_contents) const { | 732 WebContents* web_contents, |
| 733 Origin* origin) const { | |
| 674 DCHECK(CalledOnValidThread()); | 734 DCHECK(CalledOnValidThread()); |
| 675 return would_be_prerendered_map_.count(web_contents) > 0; | 735 base::hash_map<content::WebContents*, WouldBePrerenderedWebContentsData>:: |
| 736 const_iterator it = would_be_prerendered_map_.find(web_contents); | |
| 737 if (it == would_be_prerendered_map_.end()) | |
| 738 return false; | |
| 739 if (origin) | |
| 740 *origin = it->second.origin; | |
| 741 return true; | |
| 676 } | 742 } |
| 677 | 743 |
| 678 bool PrerenderManager::HasRecentlyBeenNavigatedTo(const GURL& url) { | 744 bool PrerenderManager::HasRecentlyBeenNavigatedTo(Origin origin, |
| 745 const GURL& url) { | |
| 679 DCHECK(CalledOnValidThread()); | 746 DCHECK(CalledOnValidThread()); |
| 680 | 747 |
| 681 CleanUpOldNavigations(); | 748 CleanUpOldNavigations(); |
| 682 std::list<NavigationRecord>::const_reverse_iterator end = navigations_.rend(); | 749 std::list<NavigationRecord>::const_reverse_iterator end = navigations_.rend(); |
| 683 for (std::list<NavigationRecord>::const_reverse_iterator it = | 750 for (std::list<NavigationRecord>::const_reverse_iterator it = |
| 684 navigations_.rbegin(); | 751 navigations_.rbegin(); |
| 685 it != end; | 752 it != end; |
| 686 ++it) { | 753 ++it) { |
| 687 if (it->url_ == url) { | 754 if (it->url == url) { |
| 688 base::TimeDelta delta = GetCurrentTimeTicks() - it->time_; | 755 base::TimeDelta delta = GetCurrentTimeTicks() - it->time; |
| 689 histograms_->RecordTimeSinceLastRecentVisit(delta); | 756 histograms_->RecordTimeSinceLastRecentVisit(origin, delta); |
| 690 return true; | 757 return true; |
| 691 } | 758 } |
| 692 } | 759 } |
| 693 | 760 |
| 694 return false; | 761 return false; |
| 695 } | 762 } |
| 696 | 763 |
| 697 // static | 764 // static |
| 698 bool PrerenderManager::IsValidHttpMethod(const std::string& method) { | 765 bool PrerenderManager::IsValidHttpMethod(const std::string& method) { |
| 699 // method has been canonicalized to upper case at this point so we can just | 766 // method has been canonicalized to upper case at this point so we can just |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 961 #if !defined(OS_ANDROID) | 1028 #if !defined(OS_ANDROID) |
| 962 if (content::RenderProcessHost::ShouldTryToUseExistingProcessHost( | 1029 if (content::RenderProcessHost::ShouldTryToUseExistingProcessHost( |
| 963 profile_, url) && | 1030 profile_, url) && |
| 964 !content::RenderProcessHost::run_renderer_in_process()) { | 1031 !content::RenderProcessHost::run_renderer_in_process()) { |
| 965 RecordFinalStatus(origin, experiment, FINAL_STATUS_TOO_MANY_PROCESSES); | 1032 RecordFinalStatus(origin, experiment, FINAL_STATUS_TOO_MANY_PROCESSES); |
| 966 return NULL; | 1033 return NULL; |
| 967 } | 1034 } |
| 968 #endif | 1035 #endif |
| 969 | 1036 |
| 970 // Check if enough time has passed since the last prerender. | 1037 // Check if enough time has passed since the last prerender. |
| 971 if (!DoesRateLimitAllowPrerender()) { | 1038 if (!DoesRateLimitAllowPrerender(origin)) { |
| 972 // Cancel the prerender. We could add it to the pending prerender list but | 1039 // Cancel the prerender. We could add it to the pending prerender list but |
| 973 // this doesn't make sense as the next prerender request will be triggered | 1040 // this doesn't make sense as the next prerender request will be triggered |
| 974 // by a navigation and is unlikely to be the same site. | 1041 // by a navigation and is unlikely to be the same site. |
| 975 RecordFinalStatus(origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED); | 1042 RecordFinalStatus(origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED); |
| 976 return NULL; | 1043 return NULL; |
| 977 } | 1044 } |
| 978 | 1045 |
| 979 PrerenderContents* prerender_contents = CreatePrerenderContents( | 1046 PrerenderContents* prerender_contents = CreatePrerenderContents( |
| 980 url, referrer, origin, experiment); | 1047 url, referrer, origin, experiment); |
| 981 if (!prerender_contents || !prerender_contents->Init()) | 1048 if (!prerender_contents || !prerender_contents->Init()) |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1164 for (std::list<linked_ptr<PrerenderData> >::iterator | 1231 for (std::list<linked_ptr<PrerenderData> >::iterator |
| 1165 it = active_prerender_list_.begin(); | 1232 it = active_prerender_list_.begin(); |
| 1166 it != active_prerender_list_.end(); | 1233 it != active_prerender_list_.end(); |
| 1167 ++it) { | 1234 ++it) { |
| 1168 if (prerender_contents == it->get()->contents_) | 1235 if (prerender_contents == it->get()->contents_) |
| 1169 return it; | 1236 return it; |
| 1170 } | 1237 } |
| 1171 return active_prerender_list_.end(); | 1238 return active_prerender_list_.end(); |
| 1172 } | 1239 } |
| 1173 | 1240 |
| 1174 bool PrerenderManager::DoesRateLimitAllowPrerender() const { | 1241 bool PrerenderManager::DoesRateLimitAllowPrerender(Origin origin) const { |
| 1175 DCHECK(CalledOnValidThread()); | 1242 DCHECK(CalledOnValidThread()); |
| 1176 base::TimeDelta elapsed_time = | 1243 base::TimeDelta elapsed_time = |
| 1177 GetCurrentTimeTicks() - last_prerender_start_time_; | 1244 GetCurrentTimeTicks() - last_prerender_start_time_; |
| 1178 histograms_->RecordTimeBetweenPrerenderRequests(elapsed_time); | 1245 histograms_->RecordTimeBetweenPrerenderRequests(origin, elapsed_time); |
| 1179 if (!config_.rate_limit_enabled) | 1246 if (!config_.rate_limit_enabled) |
| 1180 return true; | 1247 return true; |
| 1181 return elapsed_time > | 1248 return elapsed_time > |
| 1182 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs); | 1249 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs); |
| 1183 } | 1250 } |
| 1184 | 1251 |
| 1185 void PrerenderManager::DeleteOldTabContents() { | 1252 void PrerenderManager::DeleteOldTabContents() { |
| 1186 while (!old_tab_contents_list_.empty()) { | 1253 while (!old_tab_contents_list_.empty()) { |
| 1187 TabContents* tab_contents = old_tab_contents_list_.front(); | 1254 TabContents* tab_contents = old_tab_contents_list_.front(); |
| 1188 old_tab_contents_list_.pop_front(); | 1255 old_tab_contents_list_.pop_front(); |
| 1189 // TODO(dominich): should we use Instant Unload Handler here? | 1256 // TODO(dominich): should we use Instant Unload Handler here? |
| 1190 delete tab_contents; | 1257 delete tab_contents; |
| 1191 } | 1258 } |
| 1192 } | 1259 } |
| 1193 | 1260 |
| 1194 void PrerenderManager::CleanUpOldNavigations() { | 1261 void PrerenderManager::CleanUpOldNavigations() { |
| 1195 DCHECK(CalledOnValidThread()); | 1262 DCHECK(CalledOnValidThread()); |
| 1196 | 1263 |
| 1197 // Cutoff. Navigations before this cutoff can be discarded. | 1264 // Cutoff. Navigations before this cutoff can be discarded. |
| 1198 base::TimeTicks cutoff = GetCurrentTimeTicks() - | 1265 base::TimeTicks cutoff = GetCurrentTimeTicks() - |
| 1199 base::TimeDelta::FromMilliseconds(kNavigationRecordWindowMs); | 1266 base::TimeDelta::FromMilliseconds(kNavigationRecordWindowMs); |
| 1200 while (!navigations_.empty()) { | 1267 while (!navigations_.empty()) { |
| 1201 if (navigations_.front().time_ > cutoff) | 1268 if (navigations_.front().time > cutoff) |
| 1202 break; | 1269 break; |
| 1203 navigations_.pop_front(); | 1270 navigations_.pop_front(); |
| 1204 } | 1271 } |
| 1205 } | 1272 } |
| 1206 | 1273 |
| 1207 void PrerenderManager::ScheduleDeleteOldTabContents( | 1274 void PrerenderManager::ScheduleDeleteOldTabContents( |
| 1208 TabContents* tab, | 1275 TabContents* tab, |
| 1209 OnCloseTabContentsDeleter* deleter) { | 1276 OnCloseTabContentsDeleter* deleter) { |
| 1210 old_tab_contents_list_.push_back(tab); | 1277 old_tab_contents_list_.push_back(tab); |
| 1211 PostCleanupTask(); | 1278 PostCleanupTask(); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1296 if (!render_process_host || !render_process_host->GetBrowserContext()) | 1363 if (!render_process_host || !render_process_host->GetBrowserContext()) |
| 1297 return NULL; | 1364 return NULL; |
| 1298 Profile* profile = Profile::FromBrowserContext( | 1365 Profile* profile = Profile::FromBrowserContext( |
| 1299 render_process_host->GetBrowserContext()); | 1366 render_process_host->GetBrowserContext()); |
| 1300 if (!profile) | 1367 if (!profile) |
| 1301 return NULL; | 1368 return NULL; |
| 1302 return PrerenderManagerFactory::GetInstance()->GetForProfile(profile); | 1369 return PrerenderManagerFactory::GetInstance()->GetForProfile(profile); |
| 1303 } | 1370 } |
| 1304 | 1371 |
| 1305 } // namespace prerender | 1372 } // namespace prerender |
| OLD | NEW |