Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 <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 16 matching lines...) Expand all Loading... | |
| 27 #include "chrome/browser/prerender/prerender_tracker.h" | 27 #include "chrome/browser/prerender/prerender_tracker.h" |
| 28 #include "chrome/browser/prerender/prerender_util.h" | 28 #include "chrome/browser/prerender/prerender_util.h" |
| 29 #include "chrome/browser/profiles/profile.h" | 29 #include "chrome/browser/profiles/profile.h" |
| 30 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 30 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 31 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.h" | 31 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.h" |
| 32 #include "chrome/common/chrome_notification_types.h" | 32 #include "chrome/common/chrome_notification_types.h" |
| 33 #include "chrome/common/chrome_switches.h" | 33 #include "chrome/common/chrome_switches.h" |
| 34 #include "chrome/common/render_messages.h" | 34 #include "chrome/common/render_messages.h" |
| 35 #include "content/browser/cancelable_request.h" | 35 #include "content/browser/cancelable_request.h" |
| 36 #include "content/browser/debugger/render_view_devtools_agent_host.h" | 36 #include "content/browser/debugger/render_view_devtools_agent_host.h" |
| 37 #include "content/browser/in_process_webkit/session_storage_namespace.h" | |
| 37 #include "content/browser/renderer_host/render_process_host.h" | 38 #include "content/browser/renderer_host/render_process_host.h" |
| 38 #include "content/browser/renderer_host/render_view_host.h" | 39 #include "content/browser/renderer_host/render_view_host.h" |
| 39 #include "content/browser/renderer_host/resource_dispatcher_host.h" | 40 #include "content/browser/renderer_host/resource_dispatcher_host.h" |
| 40 #include "content/browser/tab_contents/render_view_host_manager.h" | 41 #include "content/browser/tab_contents/render_view_host_manager.h" |
| 41 #include "content/browser/tab_contents/tab_contents.h" | 42 #include "content/browser/tab_contents/tab_contents.h" |
| 42 #include "content/browser/tab_contents/tab_contents_delegate.h" | 43 #include "content/browser/tab_contents/tab_contents_delegate.h" |
| 43 #include "content/public/browser/browser_thread.h" | 44 #include "content/public/browser/browser_thread.h" |
| 44 #include "content/public/browser/notification_observer.h" | 45 #include "content/public/browser/notification_observer.h" |
| 45 #include "content/public/browser/notification_registrar.h" | 46 #include "content/public/browser/notification_registrar.h" |
| 46 #include "content/public/browser/notification_source.h" | 47 #include "content/public/browser/notification_source.h" |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 265 } | 266 } |
| 266 | 267 |
| 267 bool PrerenderManager::AddPrerenderFromLinkRelPrerender(int process_id, | 268 bool PrerenderManager::AddPrerenderFromLinkRelPrerender(int process_id, |
| 268 int route_id, | 269 int route_id, |
| 269 const GURL& url, | 270 const GURL& url, |
| 270 const GURL& referrer) { | 271 const GURL& referrer) { |
| 271 std::pair<int, int> child_route_id_pair = std::make_pair(process_id, | 272 std::pair<int, int> child_route_id_pair = std::make_pair(process_id, |
| 272 route_id); | 273 route_id); |
| 273 | 274 |
| 274 return AddPrerender(ORIGIN_LINK_REL_PRERENDER, child_route_id_pair, | 275 return AddPrerender(ORIGIN_LINK_REL_PRERENDER, child_route_id_pair, |
| 275 url, referrer); | 276 url, referrer, NULL); |
| 276 } | 277 } |
| 277 | 278 |
| 278 bool PrerenderManager::AddPrerenderFromOmnibox(const GURL& url) { | 279 bool PrerenderManager::AddPrerenderFromOmnibox( |
| 280 const GURL& url, | |
| 281 SessionStorageNamespace* session_storage_namespace) { | |
| 282 DCHECK(session_storage_namespace); | |
| 279 if (!IsOmniboxEnabled(profile_)) | 283 if (!IsOmniboxEnabled(profile_)) |
| 280 return false; | 284 return false; |
| 281 | 285 |
| 282 Origin origin = ORIGIN_MAX; | 286 Origin origin = ORIGIN_MAX; |
| 283 switch (GetOmniboxHeuristicToUse()) { | 287 switch (GetOmniboxHeuristicToUse()) { |
| 284 case OMNIBOX_HEURISTIC_ORIGINAL: | 288 case OMNIBOX_HEURISTIC_ORIGINAL: |
| 285 origin = ORIGIN_OMNIBOX_ORIGINAL; | 289 origin = ORIGIN_OMNIBOX_ORIGINAL; |
| 286 break; | 290 break; |
| 287 | 291 |
| 288 case OMNIBOX_HEURISTIC_CONSERVATIVE: | 292 case OMNIBOX_HEURISTIC_CONSERVATIVE: |
| 289 origin = ORIGIN_OMNIBOX_CONSERVATIVE; | 293 origin = ORIGIN_OMNIBOX_CONSERVATIVE; |
| 290 break; | 294 break; |
| 291 | 295 |
| 292 default: | 296 default: |
| 293 NOTREACHED(); | 297 NOTREACHED(); |
| 294 break; | 298 break; |
| 295 }; | 299 }; |
| 296 | 300 |
| 297 return AddPrerender(origin, std::make_pair(-1, -1), url, GURL()); | 301 return AddPrerender(origin, std::make_pair(-1, -1), url, GURL(), |
| 302 session_storage_namespace); | |
| 298 } | 303 } |
| 299 | 304 |
| 300 bool PrerenderManager::AddPrerender( | 305 bool PrerenderManager::AddPrerender( |
| 301 Origin origin, | 306 Origin origin, |
| 302 const std::pair<int, int>& child_route_id_pair, | 307 const std::pair<int, int>& child_route_id_pair, |
| 303 const GURL& url_arg, | 308 const GURL& url_arg, |
| 304 const GURL& referrer) { | 309 const GURL& referrer, |
| 310 SessionStorageNamespace* session_storage_namespace) { | |
| 305 DCHECK(CalledOnValidThread()); | 311 DCHECK(CalledOnValidThread()); |
| 306 | 312 |
| 307 if (origin == ORIGIN_LINK_REL_PRERENDER && IsGoogleSearchResultURL(referrer)) | 313 if (origin == ORIGIN_LINK_REL_PRERENDER && IsGoogleSearchResultURL(referrer)) |
| 308 origin = ORIGIN_GWS_PRERENDER; | 314 origin = ORIGIN_GWS_PRERENDER; |
| 309 | 315 |
| 310 histograms_->RecordPrerender(origin, url_arg); | 316 histograms_->RecordPrerender(origin, url_arg); |
| 311 | 317 |
| 312 // If the referring page is prerendering, defer the prerender. | 318 // If the referring page is prerendering, defer the prerender. |
| 313 std::list<PrerenderContentsData>::iterator source_prerender = | 319 std::list<PrerenderContentsData>::iterator source_prerender = |
| 314 FindPrerenderContentsForChildRouteIdPair(child_route_id_pair); | 320 FindPrerenderContentsForChildRouteIdPair(child_route_id_pair); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 349 // Check if enough time has passed since the last prerender. | 355 // Check if enough time has passed since the last prerender. |
| 350 if (!DoesRateLimitAllowPrerender()) { | 356 if (!DoesRateLimitAllowPrerender()) { |
| 351 // Cancel the prerender. We could add it to the pending prerender list but | 357 // Cancel the prerender. We could add it to the pending prerender list but |
| 352 // this doesn't make sense as the next prerender request will be triggered | 358 // this doesn't make sense as the next prerender request will be triggered |
| 353 // by a navigation and is unlikely to be the same site. | 359 // by a navigation and is unlikely to be the same site. |
| 354 RecordFinalStatus(origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED); | 360 RecordFinalStatus(origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED); |
| 355 return false; | 361 return false; |
| 356 } | 362 } |
| 357 | 363 |
| 358 RenderViewHost* source_render_view_host = NULL; | 364 RenderViewHost* source_render_view_host = NULL; |
| 359 // This test should fail only during unit tests. | |
| 360 if (child_route_id_pair.first != -1) { | 365 if (child_route_id_pair.first != -1) { |
| 361 source_render_view_host = | 366 source_render_view_host = |
| 362 RenderViewHost::FromID(child_route_id_pair.first, | 367 RenderViewHost::FromID(child_route_id_pair.first, |
| 363 child_route_id_pair.second); | 368 child_route_id_pair.second); |
| 364 // Don't prerender page if parent RenderViewHost no longer exists, or it has | 369 // Don't prerender page if parent RenderViewHost no longer exists, or it has |
| 365 // no view. The latter should only happen when the RenderView has closed. | 370 // no view. The latter should only happen when the RenderView has closed. |
| 366 if (!source_render_view_host || !source_render_view_host->view()) { | 371 if (!source_render_view_host || !source_render_view_host->view()) { |
| 367 RecordFinalStatus(origin, experiment, | 372 RecordFinalStatus(origin, experiment, |
| 368 FINAL_STATUS_SOURCE_RENDER_VIEW_CLOSED); | 373 FINAL_STATUS_SOURCE_RENDER_VIEW_CLOSED); |
| 369 return false; | 374 return false; |
| 370 } | 375 } |
| 371 } | 376 } |
| 372 | 377 |
| 373 PrerenderContents* prerender_contents = | 378 if (!session_storage_namespace && source_render_view_host) { |
| 374 CreatePrerenderContents(url, referrer, origin, experiment); | 379 session_storage_namespace = |
| 380 source_render_view_host->session_storage_namespace(); | |
| 381 } | |
| 382 | |
| 383 PrerenderContents* prerender_contents = CreatePrerenderContents( | |
| 384 url, referrer, origin, experiment); | |
| 375 if (!prerender_contents || !prerender_contents->Init()) | 385 if (!prerender_contents || !prerender_contents->Init()) |
| 376 return false; | 386 return false; |
| 377 | 387 |
| 378 // TODO(cbentzel): Move invalid checks here instead of PrerenderContents? | 388 // TODO(cbentzel): Move invalid checks here instead of PrerenderContents? |
| 379 PrerenderContentsData data(prerender_contents, GetCurrentTime()); | 389 PrerenderContentsData data(prerender_contents, GetCurrentTime()); |
| 380 | 390 |
| 381 prerender_list_.push_back(data); | 391 prerender_list_.push_back(data); |
| 382 | 392 |
| 383 if (IsControlGroup()) { | 393 if (IsControlGroup()) { |
| 384 data.contents_->set_final_status(FINAL_STATUS_CONTROL_GROUP); | 394 data.contents_->set_final_status(FINAL_STATUS_CONTROL_GROUP); |
| 385 } else { | 395 } else { |
| 386 last_prerender_start_time_ = GetCurrentTimeTicks(); | 396 last_prerender_start_time_ = GetCurrentTimeTicks(); |
| 387 data.contents_->StartPrerendering(source_render_view_host); | 397 data.contents_->StartPrerendering(source_render_view_host, |
| 398 session_storage_namespace); | |
| 388 } | 399 } |
| 389 while (prerender_list_.size() > config_.max_elements) { | 400 while (prerender_list_.size() > config_.max_elements) { |
| 390 data = prerender_list_.front(); | 401 data = prerender_list_.front(); |
| 391 prerender_list_.pop_front(); | 402 prerender_list_.pop_front(); |
| 392 data.contents_->Destroy(FINAL_STATUS_EVICTED); | 403 data.contents_->Destroy(FINAL_STATUS_EVICTED); |
| 393 } | 404 } |
| 394 StartSchedulingPeriodicCleanups(); | 405 StartSchedulingPeriodicCleanups(); |
| 395 return true; | 406 return true; |
| 396 } | 407 } |
| 397 | 408 |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 528 } | 539 } |
| 529 | 540 |
| 530 // If the prerendered page is in the middle of a cross-site navigation, | 541 // If the prerendered page is in the middle of a cross-site navigation, |
| 531 // don't swap it in because there isn't a good way to merge histories. | 542 // don't swap it in because there isn't a good way to merge histories. |
| 532 if (prerender_contents->IsCrossSiteNavigationPending()) { | 543 if (prerender_contents->IsCrossSiteNavigationPending()) { |
| 533 prerender_contents.release()->Destroy( | 544 prerender_contents.release()->Destroy( |
| 534 FINAL_STATUS_CROSS_SITE_NAVIGATION_PENDING); | 545 FINAL_STATUS_CROSS_SITE_NAVIGATION_PENDING); |
| 535 return false; | 546 return false; |
| 536 } | 547 } |
| 537 | 548 |
| 549 // If the sessionStorage namespaces don't match, don't swap the site in and | |
|
mmenke
2011/11/02 16:19:17
nit: "session storage namespaces" or "SessionStor
cbentzel
2011/11/02 17:13:49
Removed the "don't swap the site in" and just said
| |
| 550 // cancel the prerender. | |
| 551 RenderViewHost* old_render_view_host = tab_contents->render_view_host(); | |
|
mmenke
2011/11/02 16:19:17
What happens if the old tab has crashed? I think
cbentzel
2011/11/02 16:55:52
It's old_render_view_host->view() which could be N
mmenke
2011/11/02 17:44:07
You're right. As you say, I was getting the Rende
| |
| 552 RenderViewHost* new_render_view_host = | |
| 553 prerender_contents->prerender_contents()->render_view_host(); | |
| 554 DCHECK(old_render_view_host); | |
| 555 DCHECK(new_render_view_host); | |
| 556 if (old_render_view_host->session_storage_namespace() != | |
| 557 new_render_view_host->session_storage_namespace()) { | |
| 558 prerender_contents.release()->Destroy( | |
| 559 FINAL_STATUS_SESSION_STORAGE_NAMESPACE_MISMATCH); | |
| 560 return false; | |
| 561 } | |
| 562 | |
| 538 int child_id, route_id; | 563 int child_id, route_id; |
| 539 CHECK(prerender_contents->GetChildId(&child_id)); | 564 CHECK(prerender_contents->GetChildId(&child_id)); |
| 540 CHECK(prerender_contents->GetRouteId(&route_id)); | 565 CHECK(prerender_contents->GetRouteId(&route_id)); |
| 541 | 566 |
| 542 // Try to set the prerendered page as used, so any subsequent attempts to | 567 // Try to set the prerendered page as used, so any subsequent attempts to |
| 543 // cancel on other threads will fail. If this fails because the prerender | 568 // cancel on other threads will fail. If this fails because the prerender |
| 544 // was already cancelled, possibly on another thread, fail. | 569 // was already cancelled, possibly on another thread, fail. |
| 545 if (!prerender_tracker_->TryUse(child_id, route_id)) | 570 if (!prerender_tracker_->TryUse(child_id, route_id)) |
| 546 return false; | 571 return false; |
| 547 | 572 |
| 548 if (!prerender_contents->load_start_time().is_null()) { | 573 if (!prerender_contents->load_start_time().is_null()) { |
| 549 histograms_->RecordTimeUntilUsed(GetCurrentTimeTicks() - | 574 histograms_->RecordTimeUntilUsed(GetCurrentTimeTicks() - |
| 550 prerender_contents->load_start_time(), | 575 prerender_contents->load_start_time(), |
| 551 config_.max_age); | 576 config_.max_age); |
| 552 } | 577 } |
| 553 | 578 |
| 554 histograms_->RecordPerSessionCount(++prerenders_per_session_count_); | 579 histograms_->RecordPerSessionCount(++prerenders_per_session_count_); |
| 555 prerender_contents->set_final_status(FINAL_STATUS_USED); | 580 prerender_contents->set_final_status(FINAL_STATUS_USED); |
| 556 | 581 |
| 557 RenderViewHost* render_view_host = | 582 new_render_view_host->Send( |
| 558 prerender_contents->prerender_contents()->render_view_host(); | 583 new ChromeViewMsg_SetIsPrerendering(new_render_view_host->routing_id(), |
| 559 DCHECK(render_view_host); | |
| 560 render_view_host->Send( | |
| 561 new ChromeViewMsg_SetIsPrerendering(render_view_host->routing_id(), | |
| 562 false)); | 584 false)); |
| 563 | 585 |
| 564 TabContentsWrapper* new_tab_contents = | 586 TabContentsWrapper* new_tab_contents = |
| 565 prerender_contents->ReleasePrerenderContents(); | 587 prerender_contents->ReleasePrerenderContents(); |
| 566 TabContentsWrapper* old_tab_contents = | 588 TabContentsWrapper* old_tab_contents = |
| 567 TabContentsWrapper::GetCurrentWrapperForContents(tab_contents); | 589 TabContentsWrapper::GetCurrentWrapperForContents(tab_contents); |
| 568 DCHECK(new_tab_contents); | 590 DCHECK(new_tab_contents); |
| 569 DCHECK(old_tab_contents); | 591 DCHECK(old_tab_contents); |
| 570 | 592 |
| 571 MarkTabContentsAsPrerendered(new_tab_contents->tab_contents()); | 593 MarkTabContentsAsPrerendered(new_tab_contents->tab_contents()); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 647 return (now - start < config_.max_age); | 669 return (now - start < config_.max_age); |
| 648 } | 670 } |
| 649 | 671 |
| 650 PrerenderContents* PrerenderManager::CreatePrerenderContents( | 672 PrerenderContents* PrerenderManager::CreatePrerenderContents( |
| 651 const GURL& url, | 673 const GURL& url, |
| 652 const GURL& referrer, | 674 const GURL& referrer, |
| 653 Origin origin, | 675 Origin origin, |
| 654 uint8 experiment_id) { | 676 uint8 experiment_id) { |
| 655 DCHECK(CalledOnValidThread()); | 677 DCHECK(CalledOnValidThread()); |
| 656 return prerender_contents_factory_->CreatePrerenderContents( | 678 return prerender_contents_factory_->CreatePrerenderContents( |
| 657 this, prerender_tracker_, profile_, url, referrer, origin, experiment_id); | 679 this, prerender_tracker_, profile_, url, |
| 680 referrer, origin, experiment_id); | |
| 658 } | 681 } |
| 659 | 682 |
| 660 bool PrerenderManager::IsPendingDelete(PrerenderContents* entry) const { | 683 bool PrerenderManager::IsPendingDelete(PrerenderContents* entry) const { |
| 661 DCHECK(CalledOnValidThread()); | 684 DCHECK(CalledOnValidThread()); |
| 662 for (std::list<PrerenderContents*>::const_iterator it = | 685 for (std::list<PrerenderContents*>::const_iterator it = |
| 663 pending_delete_list_.begin(); | 686 pending_delete_list_.begin(); |
| 664 it != pending_delete_list_.end(); | 687 it != pending_delete_list_.end(); |
| 665 ++it) { | 688 ++it) { |
| 666 if (*it == entry) | 689 if (*it == entry) |
| 667 return true; | 690 return true; |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1011 if (!render_process_host || !render_process_host->browser_context()) | 1034 if (!render_process_host || !render_process_host->browser_context()) |
| 1012 return NULL; | 1035 return NULL; |
| 1013 Profile* profile = Profile::FromBrowserContext( | 1036 Profile* profile = Profile::FromBrowserContext( |
| 1014 render_process_host->browser_context()); | 1037 render_process_host->browser_context()); |
| 1015 if (!profile) | 1038 if (!profile) |
| 1016 return NULL; | 1039 return NULL; |
| 1017 return PrerenderManagerFactory::GetInstance()->GetForProfile(profile); | 1040 return PrerenderManagerFactory::GetInstance()->GetForProfile(profile); |
| 1018 } | 1041 } |
| 1019 | 1042 |
| 1020 } // namespace prerender | 1043 } // namespace prerender |
| OLD | NEW |