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