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 |