Chromium Code Reviews| 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 |