OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "content/browser/frame_host/render_view_host_manager.h" | 5 #include "content/browser/frame_host/render_view_host_manager.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
484 return | 484 return |
485 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) && | 485 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) && |
486 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab); | 486 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab); |
487 } | 487 } |
488 | 488 |
489 bool RenderViewHostManager::ShouldSwapProcessesForNavigation( | 489 bool RenderViewHostManager::ShouldSwapProcessesForNavigation( |
490 const NavigationEntry* curr_entry, | 490 const NavigationEntry* curr_entry, |
491 const NavigationEntryImpl* new_entry) const { | 491 const NavigationEntryImpl* new_entry) const { |
492 DCHECK(new_entry); | 492 DCHECK(new_entry); |
493 | 493 |
494 // If new_entry already has a SiteInstance, assume it is correct and use it. | |
495 if (new_entry->site_instance()) | |
496 return false; | |
497 | |
494 // Check for reasons to swap processes even if we are in a process model that | 498 // Check for reasons to swap processes even if we are in a process model that |
495 // doesn't usually swap (e.g., process-per-tab). | 499 // doesn't usually swap (e.g., process-per-tab). |
496 | 500 |
497 // For security, we should transition between processes when one is a Web UI | 501 // We use the effective URL here, since that's what is used in the |
498 // page and one isn't. If there's no curr_entry, check the current RVH's | 502 // SiteInstance's site and when we later call IsSameWebSite. If there is no |
499 // site, which might already be committed to a Web UI URL (such as the NTP). | 503 // curr_entry, check the current SiteInstance's site, which might already be |
500 const GURL& current_url = (curr_entry) ? curr_entry->GetURL() : | 504 // committed to a Web UI URL (such as the NTP). |
501 render_view_host_->GetSiteInstance()->GetSiteURL(); | |
502 BrowserContext* browser_context = | 505 BrowserContext* browser_context = |
503 delegate_->GetControllerForRenderManager().GetBrowserContext(); | 506 delegate_->GetControllerForRenderManager().GetBrowserContext(); |
507 const GURL& current_url = (curr_entry) ? | |
508 SiteInstanceImpl::GetEffectiveURL(browser_context, curr_entry->GetURL()) : | |
509 render_view_host_->GetSiteInstance()->GetSiteURL(); | |
510 const GURL& new_url = SiteInstanceImpl::GetEffectiveURL(browser_context, | |
511 new_entry->GetURL()); | |
512 | |
513 // For security, we should transition between processes when one is a Web UI | |
514 // page and one isn't. | |
504 if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL( | 515 if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL( |
505 browser_context, current_url)) { | 516 browser_context, current_url)) { |
506 // Force swap if it's not an acceptable URL for Web UI. | 517 // Force swap if it's not an acceptable URL for Web UI. |
507 // Here, data URLs are never allowed. | 518 // Here, data URLs are never allowed. |
508 if (!WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI( | 519 if (!WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI( |
509 browser_context, new_entry->GetURL(), false)) { | 520 browser_context, new_url, false)) { |
510 return true; | 521 return true; |
511 } | 522 } |
512 } else { | 523 } else { |
513 // Force swap if it's a Web UI URL. | 524 // Force swap if it's a Web UI URL. |
514 if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL( | 525 if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL( |
515 browser_context, new_entry->GetURL())) { | 526 browser_context, new_url)) { |
516 return true; | 527 return true; |
517 } | 528 } |
518 } | 529 } |
519 | 530 |
531 // Check with the content client as well. Important to pass current_url here, | |
532 // which uses the SiteInstance's site if there is no curr_entry. | |
520 if (GetContentClient()->browser()->ShouldSwapProcessesForNavigation( | 533 if (GetContentClient()->browser()->ShouldSwapProcessesForNavigation( |
521 render_view_host_->GetSiteInstance(), | 534 render_view_host_->GetSiteInstance(), current_url, new_url)) { |
522 curr_entry ? curr_entry->GetURL() : GURL(), | |
523 new_entry->GetURL())) { | |
524 return true; | 535 return true; |
525 } | 536 } |
526 | 537 |
527 if (!curr_entry) | 538 if (!curr_entry) |
528 return false; | 539 return false; |
529 | 540 |
530 // We can't switch a RenderView between view source and non-view source mode | 541 // We can't switch a RenderView between view source and non-view source mode |
531 // without screwing up the session history sometimes (when navigating between | 542 // without screwing up the session history sometimes (when navigating between |
532 // "view-source:http://foo.com/" and "http://foo.com/", WebKit doesn't treat | 543 // "view-source:http://foo.com/" and "http://foo.com/", WebKit doesn't treat |
533 // it as a new navigation). So require a view switch. | 544 // it as a new navigation). So require a view switch. |
(...skipping 10 matching lines...) Expand all Loading... | |
544 delegate_->GetControllerForRenderManager(); | 555 delegate_->GetControllerForRenderManager(); |
545 return curr_entry && web_ui_.get() && | 556 return curr_entry && web_ui_.get() && |
546 (WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( | 557 (WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( |
547 controller.GetBrowserContext(), curr_entry->GetURL()) == | 558 controller.GetBrowserContext(), curr_entry->GetURL()) == |
548 WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( | 559 WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( |
549 controller.GetBrowserContext(), new_entry->GetURL())); | 560 controller.GetBrowserContext(), new_entry->GetURL())); |
550 } | 561 } |
551 | 562 |
552 SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry( | 563 SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry( |
553 const NavigationEntryImpl& entry, | 564 const NavigationEntryImpl& entry, |
554 SiteInstance* curr_instance) { | 565 SiteInstance* curr_instance, |
555 // NOTE: This is only called when ShouldTransitionCrossSite is true. | 566 bool force_swap) { |
556 | 567 // Determine which SiteInstance to use for navigating to |entry|. |
557 const GURL& dest_url = entry.GetURL(); | 568 const GURL& dest_url = entry.GetURL(); |
558 NavigationControllerImpl& controller = | 569 NavigationControllerImpl& controller = |
559 delegate_->GetControllerForRenderManager(); | 570 delegate_->GetControllerForRenderManager(); |
560 BrowserContext* browser_context = controller.GetBrowserContext(); | 571 BrowserContext* browser_context = controller.GetBrowserContext(); |
561 | 572 |
573 // If a swap is required, we need to force the SiteInstance AND | |
574 // BrowsingInstance to be different ones, using CreateForURL. | |
nasko
2013/11/05 18:41:00
Why is that? Are we guaranteed in this case that t
Charlie Reis
2013/11/05 19:13:15
Yep, that's what the poorly named ShouldSwapProces
| |
575 if (force_swap) { | |
576 // We shouldn't be forcing a swap if an entry already has a SiteInstance. | |
577 CHECK(!entry.site_instance()); | |
578 return SiteInstance::CreateForURL(browser_context, dest_url); | |
579 } | |
580 | |
562 // If the entry has an instance already we should use it. | 581 // If the entry has an instance already we should use it. |
563 if (entry.site_instance()) | 582 if (entry.site_instance()) |
564 return entry.site_instance(); | 583 return entry.site_instance(); |
565 | 584 |
566 // (UGLY) HEURISTIC, process-per-site only: | 585 // (UGLY) HEURISTIC, process-per-site only: |
567 // | 586 // |
568 // If this navigation is generated, then it probably corresponds to a search | 587 // If this navigation is generated, then it probably corresponds to a search |
569 // query. Given that search results typically lead to users navigating to | 588 // query. Given that search results typically lead to users navigating to |
570 // other sites, we don't really want to use the search engine hostname to | 589 // other sites, we don't really want to use the search engine hostname to |
571 // determine the site instance for this navigation. | 590 // determine the site instance for this navigation. |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
678 return SiteInstance::CreateForURL(browser_context, dest_url); | 697 return SiteInstance::CreateForURL(browser_context, dest_url); |
679 } | 698 } |
680 | 699 |
681 // Use the current SiteInstance for same site navigations, as long as the | 700 // Use the current SiteInstance for same site navigations, as long as the |
682 // process type is correct. (The URL may have been installed as an app since | 701 // process type is correct. (The URL may have been installed as an app since |
683 // the last time we visited it.) | 702 // the last time we visited it.) |
684 if (SiteInstance::IsSameWebSite(browser_context, current_url, dest_url) && | 703 if (SiteInstance::IsSameWebSite(browser_context, current_url, dest_url) && |
685 !static_cast<SiteInstanceImpl*>(curr_instance)->HasWrongProcessForURL( | 704 !static_cast<SiteInstanceImpl*>(curr_instance)->HasWrongProcessForURL( |
686 dest_url)) { | 705 dest_url)) { |
687 return curr_instance; | 706 return curr_instance; |
688 } else if (ShouldSwapProcessesForNavigation(curr_entry, &entry)) { | |
689 // When we're swapping, we need to force the site instance AND browsing | |
690 // instance to be different ones. This addresses special cases where we use | |
691 // a single BrowsingInstance for all pages of a certain type (e.g., New Tab | |
692 // Pages), keeping them in the same process. When you navigate away from | |
693 // that page, we want to explicity ignore that BrowsingInstance and group | |
694 // this page into the appropriate SiteInstance for its URL. | |
695 return SiteInstance::CreateForURL(browser_context, dest_url); | |
696 } else { | |
697 // Start the new renderer in a new SiteInstance, but in the current | |
698 // BrowsingInstance. It is important to immediately give this new | |
699 // SiteInstance to a RenderViewHost (if it is different than our current | |
700 // SiteInstance), so that it is ref counted. This will happen in | |
701 // CreateRenderView. | |
702 return curr_instance->GetRelatedSiteInstance(dest_url); | |
703 } | 707 } |
708 | |
709 // Start the new renderer in a new SiteInstance, but in the current | |
710 // BrowsingInstance. It is important to immediately give this new | |
711 // SiteInstance to a RenderViewHost (if it is different than our current | |
712 // SiteInstance), so that it is ref counted. This will happen in | |
713 // CreateRenderView. | |
714 return curr_instance->GetRelatedSiteInstance(dest_url); | |
704 } | 715 } |
705 | 716 |
706 int RenderViewHostManager::CreateRenderView( | 717 int RenderViewHostManager::CreateRenderView( |
707 SiteInstance* instance, | 718 SiteInstance* instance, |
708 int opener_route_id, | 719 int opener_route_id, |
709 bool swapped_out, | 720 bool swapped_out, |
710 bool hidden) { | 721 bool hidden) { |
711 CHECK(instance); | 722 CHECK(instance); |
712 DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden. | 723 DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden. |
713 | 724 |
725 // We are creating a pending or swapped out RVH here. We should never create | |
726 // it in the same SiteInstance as our current RVH. | |
727 CHECK_NE(render_view_host_->GetSiteInstance(), instance); | |
728 | |
714 // Check if we've already created an RVH for this SiteInstance. If so, try | 729 // Check if we've already created an RVH for this SiteInstance. If so, try |
715 // to re-use the existing one, which has already been initialized. We'll | 730 // to re-use the existing one, which has already been initialized. We'll |
716 // remove it from the list of swapped out hosts if it commits. | 731 // remove it from the list of swapped out hosts if it commits. |
717 RenderViewHostImpl* new_render_view_host = static_cast<RenderViewHostImpl*>( | 732 RenderViewHostImpl* new_render_view_host = static_cast<RenderViewHostImpl*>( |
718 GetSwappedOutRenderViewHost(instance)); | 733 GetSwappedOutRenderViewHost(instance)); |
719 if (new_render_view_host) { | 734 if (new_render_view_host) { |
720 // Prevent the process from exiting while we're trying to use it. | 735 // Prevent the process from exiting while we're trying to use it. |
721 if (!swapped_out) | 736 if (!swapped_out) |
722 new_render_view_host->GetProcess()->AddPendingView(); | 737 new_render_view_host->GetProcess()->AddPendingView(); |
723 } else { | 738 } else { |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
911 // don't have to worry about this SiteInstance's ref count dropping to zero. | 926 // don't have to worry about this SiteInstance's ref count dropping to zero. |
912 SiteInstance* curr_instance = render_view_host_->GetSiteInstance(); | 927 SiteInstance* curr_instance = render_view_host_->GetSiteInstance(); |
913 | 928 |
914 // Determine if we need a new SiteInstance for this entry. | 929 // Determine if we need a new SiteInstance for this entry. |
915 // Again, new_instance won't be deleted before the end of this method, so it | 930 // Again, new_instance won't be deleted before the end of this method, so it |
916 // is safe to use a normal pointer here. | 931 // is safe to use a normal pointer here. |
917 SiteInstance* new_instance = curr_instance; | 932 SiteInstance* new_instance = curr_instance; |
918 const NavigationEntry* curr_entry = | 933 const NavigationEntry* curr_entry = |
919 delegate_->GetLastCommittedNavigationEntryForRenderManager(); | 934 delegate_->GetLastCommittedNavigationEntryForRenderManager(); |
920 bool is_guest_scheme = curr_instance->GetSiteURL().SchemeIs(kGuestScheme); | 935 bool is_guest_scheme = curr_instance->GetSiteURL().SchemeIs(kGuestScheme); |
921 bool force_swap = ShouldSwapProcessesForNavigation(curr_entry, &entry); | 936 bool force_swap = !is_guest_scheme && |
937 ShouldSwapProcessesForNavigation(curr_entry, &entry); | |
922 if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap)) | 938 if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap)) |
923 new_instance = GetSiteInstanceForEntry(entry, curr_instance); | 939 new_instance = GetSiteInstanceForEntry(entry, curr_instance, force_swap); |
924 | 940 |
925 if (!is_guest_scheme && (new_instance != curr_instance || force_swap)) { | 941 // If force_swap is true, we must use a different SiteInstance. If we didn't, |
942 // we would have two RenderViewHosts in the same SiteInstance and the same | |
943 // tab, resulting in page_id conflicts for their NavigationEntries. | |
944 if (force_swap) | |
945 CHECK_NE(new_instance, curr_instance); | |
946 | |
947 if (new_instance != curr_instance) { | |
926 // New SiteInstance. | 948 // New SiteInstance. |
927 DCHECK(!cross_navigation_pending_); | 949 DCHECK(!cross_navigation_pending_); |
928 | 950 |
929 // This will possibly create (set to NULL) a Web UI object for the pending | 951 // This will possibly create (set to NULL) a Web UI object for the pending |
930 // page. We'll use this later to give the page special access. This must | 952 // page. We'll use this later to give the page special access. This must |
931 // happen before the new renderer is created below so it will get bindings. | 953 // happen before the new renderer is created below so it will get bindings. |
932 // It must also happen after the above conditional call to CancelPending(), | 954 // It must also happen after the above conditional call to CancelPending(), |
933 // otherwise CancelPending may clear the pending_web_ui_ and the page will | 955 // otherwise CancelPending may clear the pending_web_ui_ and the page will |
934 // not have its bindings set appropriately. | 956 // not have its bindings set appropriately. |
935 SetPendingWebUI(entry); | 957 SetPendingWebUI(entry); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1110 RenderViewHostImpl* RenderViewHostManager::GetSwappedOutRenderViewHost( | 1132 RenderViewHostImpl* RenderViewHostManager::GetSwappedOutRenderViewHost( |
1111 SiteInstance* instance) { | 1133 SiteInstance* instance) { |
1112 RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId()); | 1134 RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId()); |
1113 if (iter != swapped_out_hosts_.end()) | 1135 if (iter != swapped_out_hosts_.end()) |
1114 return iter->second; | 1136 return iter->second; |
1115 | 1137 |
1116 return NULL; | 1138 return NULL; |
1117 } | 1139 } |
1118 | 1140 |
1119 } // namespace content | 1141 } // namespace content |
OLD | NEW |