summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorcarlosk <carlosk@chromium.org>2015-11-05 06:18:36 -0800
committerCommit bot <commit-bot@chromium.org>2015-11-05 14:19:22 +0000
commite5c678bf5b084988a60a4636342414f2831c1695 (patch)
tree6596699c4b38202be97b92d648591b6bddee3d38 /content
parentbc1a48d97b535993c8644acc89fd761da7cd99c2 (diff)
downloadchromium_src-e5c678bf5b084988a60a4636342414f2831c1695.zip
chromium_src-e5c678bf5b084988a60a4636342414f2831c1695.tar.gz
chromium_src-e5c678bf5b084988a60a4636342414f2831c1695.tar.bz2
Move WebUI ownership from the RenderFrameHostManager to the RenderFrameHost.
This change refactors the current ownership of the WebUI instance, moving it from the RenderFrameHostManager to the RenderFrameHost which is directly associated with the WebUI. The design document for this change is here: https://docs.google.com/a/chromium.org/document/d/1jrge5ulZ1YtqSR3WkNXzrtxhd3JXcWm8_zWBhEjaJtI BUG=508850 Review URL: https://codereview.chromium.org/1352813006 Cr-Commit-Position: refs/heads/master@{#358050}
Diffstat (limited to 'content')
-rw-r--r--content/browser/frame_host/frame_tree.cc3
-rw-r--r--content/browser/frame_host/render_frame_host_delegate.cc5
-rw-r--r--content/browser/frame_host/render_frame_host_delegate.h5
-rw-r--r--content/browser/frame_host/render_frame_host_impl.cc72
-rw-r--r--content/browser/frame_host/render_frame_host_impl.h25
-rw-r--r--content/browser/frame_host/render_frame_host_manager.cc362
-rw-r--r--content/browser/frame_host/render_frame_host_manager.h128
-rw-r--r--content/browser/frame_host/render_frame_host_manager_browsertest.cc8
-rw-r--r--content/browser/frame_host/render_frame_host_manager_unittest.cc28
-rw-r--r--content/browser/web_contents/web_contents_impl.cc26
-rw-r--r--content/browser/web_contents/web_contents_impl.h2
11 files changed, 343 insertions, 321 deletions
diff --git a/content/browser/frame_host/frame_tree.cc b/content/browser/frame_host/frame_tree.cc
index 911ae0d..26fbefe 100644
--- a/content/browser/frame_host/frame_tree.cc
+++ b/content/browser/frame_host/frame_tree.cc
@@ -244,8 +244,7 @@ void FrameTree::CreateProxiesForSiteInstance(
root()->render_manager()->CreateRenderFrameProxy(site_instance);
} else {
root()->render_manager()->CreateRenderFrame(
- site_instance, nullptr, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN,
- nullptr);
+ site_instance, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN, nullptr);
}
} else {
root()->render_manager()->EnsureRenderViewInitialized(render_view_host,
diff --git a/content/browser/frame_host/render_frame_host_delegate.cc b/content/browser/frame_host/render_frame_host_delegate.cc
index 69b9e98..f33dc2c 100644
--- a/content/browser/frame_host/render_frame_host_delegate.cc
+++ b/content/browser/frame_host/render_frame_host_delegate.cc
@@ -76,6 +76,11 @@ bool RenderFrameHostDelegate::ShouldRouteMessageEvent(
return false;
}
+scoped_ptr<WebUIImpl> RenderFrameHostDelegate::CreateWebUIForRenderFrameHost(
+ const GURL& url) {
+ return nullptr;
+}
+
#if defined(OS_WIN)
gfx::NativeViewAccessible
RenderFrameHostDelegate::GetParentNativeViewAccessible() {
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h
index 13f78d9..5c59b90 100644
--- a/content/browser/frame_host/render_frame_host_delegate.h
+++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -9,6 +9,7 @@
#include "base/basictypes.h"
#include "base/i18n/rtl.h"
+#include "content/browser/webui/web_ui_impl.h"
#include "content/common/content_export.h"
#include "content/common/frame_message_enums.h"
#include "content/public/browser/site_instance.h"
@@ -172,6 +173,10 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
// https://crbug.com/330264.
virtual void EnsureOpenerProxiesExist(RenderFrameHost* source_rfh) {}
+ // Creates a WebUI object for a frame navigating to the given URL. If no WebUI
+ // applies, returns null.
+ virtual scoped_ptr<WebUIImpl> CreateWebUIForRenderFrameHost(const GURL& url);
+
#if defined(OS_WIN)
// Returns the frame's parent's NativeViewAccessible.
virtual gfx::NativeViewAccessible GetParentNativeViewAccessible();
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 53033a1..5d5be24 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -16,6 +16,7 @@
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/frame_host/cross_process_frame_connector.h"
#include "content/browser/frame_host/cross_site_transferring_request.h"
@@ -42,6 +43,7 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/wake_lock/wake_lock_service_context.h"
+#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/common/accessibility_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/input_messages.h"
@@ -194,6 +196,7 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
accessibility_reset_token_(0),
accessibility_reset_count_(0),
no_create_browser_accessibility_manager_for_testing_(false),
+ web_ui_type_(WebUI::kNoWebUI),
weak_ptr_factory_(this) {
bool is_swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT);
bool hidden = !!(flags & CREATE_RF_HIDDEN);
@@ -233,6 +236,10 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
}
RenderFrameHostImpl::~RenderFrameHostImpl() {
+ // Release the WebUI before all else as the WebUI accesses the RenderFrameHost
+ // during cleanup.
+ ResetWebUI();
+
GetProcess()->RemoveRoute(routing_id_);
g_routing_id_frame_map.Get().erase(
RenderFrameHostID(GetProcess()->GetID(), routing_id_));
@@ -1216,6 +1223,7 @@ void RenderFrameHostImpl::OnSwappedOut() {
TRACE_EVENT_ASYNC_END0("navigation", "RenderFrameHostImpl::SwapOut", this);
swapout_event_monitor_timeout_->Stop();
+ ResetWebUI();
// If this is a main frame RFH that's about to be deleted, update its RVH's
// swapped-out state here, since SetState won't be called once this RFH is
@@ -2047,6 +2055,65 @@ bool RenderFrameHostImpl::IsFocused() {
frame_tree_->GetFocusedFrame()->IsDescendantOf(frame_tree_node()));
}
+bool RenderFrameHostImpl::UpdateWebUI(const GURL& dest_url,
+ int entry_bindings) {
+ WebUI::TypeID new_web_ui_type = WebUI::kNoWebUI;
+ if (dest_url.is_valid()) {
+ new_web_ui_type =
+ WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
+ GetSiteInstance()->GetBrowserContext(), dest_url);
+ }
+
+ WebUIImpl* prev_web_ui = web_ui_.get();
+ if (new_web_ui_type == WebUI::kNoWebUI) {
+ ResetWebUI();
+ } else {
+ // The current WebUI should be reused when dest_url requires a WebUI and its
+ // type matches the current. Otherwise replace it with a new one.
+ if (web_ui_type_ != new_web_ui_type) {
+ web_ui_ = delegate_->CreateWebUIForRenderFrameHost(dest_url);
+ DCHECK(web_ui_);
+ web_ui_type_ = new_web_ui_type;
+
+ // If we have assigned (zero or more) bindings to the NavigationEntry in
+ // the past, make sure we're not granting it different bindings than it
+ // had before. If so, note it and don't give it any bindings, to avoid a
+ // potential privilege escalation.
+ if (entry_bindings != NavigationEntryImpl::kInvalidBindings &&
+ web_ui_->GetBindings() != entry_bindings) {
+ RecordAction(
+ base::UserMetricsAction("ProcessSwapBindingsMismatch_RVHM"));
+ ResetWebUI();
+ return !!prev_web_ui;
+ }
+ }
+ }
+ DCHECK_EQ(!web_ui_, web_ui_type_ == WebUI::kNoWebUI);
+
+ // Check RenderViewHost for proper bindings.
+ if (web_ui_ && !render_view_host_->GetProcess()->IsForGuestsOnly()) {
+ // If a WebUI was created for the URL and the RenderView is not in a guest
+ // process, then enable missing bindings with the RenderViewHost.
+ int new_bindings = web_ui_->GetBindings();
+ if ((render_view_host_->GetEnabledBindings() & new_bindings) !=
+ new_bindings) {
+ render_view_host_->AllowBindings(new_bindings);
+ }
+ } else if (render_view_host_->is_active()) {
+ // If the ongoing navigation is not to a WebUI or the RenderView is in a
+ // guest process, ensure that we don't create an unprivileged RenderView in
+ // a WebUI-enabled process unless it's swapped out.
+ bool url_acceptable_for_webui =
+ WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI(
+ GetSiteInstance()->GetBrowserContext(), dest_url);
+ if (!url_acceptable_for_webui) {
+ CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ GetProcess()->GetID()));
+ }
+ }
+ return prev_web_ui != web_ui_.get();
+}
+
const image_downloader::ImageDownloaderPtr&
RenderFrameHostImpl::GetMojoImageDownloader() {
if (!mojo_image_downloader_.get() && GetServiceRegistry()) {
@@ -2358,4 +2425,9 @@ void RenderFrameHostImpl::AXContentTreeDataToAXTreeData(
dst->parent_tree_id = RoutingIDToAXTreeID(src.parent_routing_id);
}
+void RenderFrameHostImpl::ResetWebUI() {
+ web_ui_type_ = WebUI::kNoWebUI;
+ web_ui_.reset();
+}
+
} // namespace content
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 41f0bce..1afa161 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -17,6 +17,7 @@
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/bad_message.h"
#include "content/browser/site_instance_impl.h"
+#include "content/browser/webui/web_ui_impl.h"
#include "content/common/accessibility_mode_enums.h"
#include "content/common/ax_content_node_data.h"
#include "content/common/content_export.h"
@@ -218,6 +219,12 @@ class CONTENT_EXPORT RenderFrameHostImpl
RenderFrameHostDelegate* delegate() { return delegate_; }
FrameTreeNode* frame_tree_node() { return frame_tree_node_; }
+ // Returns the associated WebUI or null if none applies.
+ WebUIImpl* web_ui() const { return web_ui_.get(); }
+
+ // Returns the associated WebUI type.
+ WebUI::TypeID web_ui_type() const { return web_ui_type_; }
+
// Returns this RenderFrameHost's loading state. This method is only used by
// FrameTreeNode. The proper way to check whether a frame is loading is to
// call FrameTreeNode::IsLoading.
@@ -478,6 +485,15 @@ class CONTENT_EXPORT RenderFrameHostImpl
// addition, its associated RenderWidgetHost has to be focused.
bool IsFocused();
+ // Updates the WebUI of this RenderFrameHost based on the provided |dest_url|,
+ // setting it to either none, a new instance or simply reuses the currently
+ // existing one. Returns true if a WebUI change occurred.
+ // If this is a history navigation its NavigationEntry bindings should be
+ // provided through |entry_bindings| to allow verifying that they are not
+ // being set differently this time around. Otherwise |entry_bindings| should
+ // be set to NavigationEntryImpl::kInvalidBindings so that no checks are done.
+ bool UpdateWebUI(const GURL& dest_url, int entry_bindings);
+
// Returns the Mojo ImageDownloader service.
const image_downloader::ImageDownloaderPtr& GetMojoImageDownloader();
@@ -648,6 +664,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
FrameTreeNode* FindAndVerifyChild(
int32 child_frame_routing_id, bad_message::BadMessageReason reason);
+ // Resets all WebUI related fields.
+ void ResetWebUI();
+
// For now, RenderFrameHosts indirectly keep RenderViewHosts alive via a
// refcount that calls Shutdown when it reaches zero. This allows each
// RenderFrameHostManager to just care about RenderFrameHosts, while ensuring
@@ -823,6 +842,12 @@ class CONTENT_EXPORT RenderFrameHostImpl
// NavigationHandle for it is owned by the NavigationRequest.
scoped_ptr<NavigationHandleImpl> navigation_handle_;
+ // The associated WebUIImpl and its type. They will be set if the current
+ // document or the one being navigated to is from WebUI source. Otherwise they
+ // will be null and WebUI::kNoWebUI, respectively.
+ scoped_ptr<WebUIImpl> web_ui_;
+ WebUI::TypeID web_ui_type_;
+
// NOTE: This must be the last member.
base::WeakPtrFactory<RenderFrameHostImpl> weak_ptr_factory_;
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index 1f6101d..e4c7fd7 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -30,7 +30,6 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
-#include "content/browser/webui/web_ui_impl.h"
#include "content/common/frame_messages.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/view_messages.h"
@@ -39,7 +38,6 @@
#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/user_metrics.h"
-#include "content/public/browser/web_ui_controller.h"
#include "content/public/common/browser_plugin_guest_mode.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/referrer.h"
@@ -220,7 +218,7 @@ RenderFrameHostManager::RenderFrameHostManager(
render_widget_delegate_(render_widget_delegate),
proxy_hosts_(new RenderFrameProxyHostMap(this)),
interstitial_page_(nullptr),
- should_reuse_web_ui_(false),
+ current_web_ui_is_navigating_(false),
weak_factory_(this) {
DCHECK(frame_tree_node_);
}
@@ -245,10 +243,6 @@ RenderFrameHostManager::~RenderFrameHostManager() {
// the current RenderFrameHost and uses it during its destructor.
ResetProxyHosts();
- // Release the WebUI prior to resetting the current RenderFrameHost, as the
- // WebUI accesses the RenderFrameHost during cleanup.
- web_ui_.reset();
-
// We should always have a current RenderFrameHost except in some tests.
SetRenderFrameHost(scoped_ptr<RenderFrameHostImpl>());
}
@@ -289,6 +283,21 @@ RenderViewHostImpl* RenderFrameHostManager::pending_render_view_host() const {
return pending_render_frame_host_->render_view_host();
}
+WebUIImpl* RenderFrameHostManager::GetNavigatingWebUI() const {
+ if (current_web_ui_is_navigating_)
+ return render_frame_host_->web_ui();
+
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation)) {
+ if (speculative_render_frame_host_)
+ return speculative_render_frame_host_->web_ui();
+ } else {
+ if (pending_render_frame_host_)
+ return pending_render_frame_host_->web_ui();
+ }
+ return nullptr;
+}
+
RenderWidgetHostView* RenderFrameHostManager::GetRenderWidgetHostView() const {
if (interstitial_page_)
return interstitial_page_->GetView();
@@ -357,27 +366,6 @@ void RenderFrameHostManager::RemoveOuterDelegateFrame() {
outer_delegate_frame_tree_node);
}
-void RenderFrameHostManager::SetPendingWebUI(const GURL& url, int bindings) {
- pending_web_ui_ = CreateWebUI(url, bindings);
- pending_and_current_web_ui_.reset();
-}
-
-scoped_ptr<WebUIImpl> RenderFrameHostManager::CreateWebUI(const GURL& url,
- int bindings) {
- scoped_ptr<WebUIImpl> new_web_ui(delegate_->CreateWebUIForRenderManager(url));
-
- // If we have assigned (zero or more) bindings to this NavigationEntry in the
- // past, make sure we're not granting it different bindings than it had
- // before. If so, note it and don't give it any bindings, to avoid a
- // potential privilege escalation.
- if (new_web_ui && bindings != NavigationEntryImpl::kInvalidBindings &&
- new_web_ui->GetBindings() != bindings) {
- RecordAction(base::UserMetricsAction("ProcessSwapBindingsMismatch_RVHM"));
- return nullptr;
- }
- return new_web_ui.Pass();
-}
-
RenderFrameHostImpl* RenderFrameHostManager::Navigate(
const GURL& dest_url,
const FrameNavigationEntry& frame_entry,
@@ -426,6 +414,11 @@ RenderFrameHostImpl* RenderFrameHostManager::Navigate(
if (!InitRenderView(dest_render_frame_host->render_view_host(), nullptr))
return nullptr;
+ if (GetNavigatingWebUI()) {
+ GetNavigatingWebUI()->RenderViewCreated(
+ dest_render_frame_host->render_view_host());
+ }
+
// Now that we've created a new renderer, be sure to hide it if it isn't
// our primary one. Otherwise, we might crash if we try to call Show()
// on it later.
@@ -676,13 +669,14 @@ void RenderFrameHostManager::CommitPendingIfNecessary(
RenderFrameHostImpl* render_frame_host,
bool was_caused_by_user_gesture) {
if (!pending_render_frame_host_ && !speculative_render_frame_host_) {
- DCHECK(!should_reuse_web_ui_ || web_ui_);
+ DCHECK(!current_web_ui_is_navigating_ || render_frame_host_->web_ui());
// We should only hear this from our current renderer.
DCHECK_EQ(render_frame_host_, render_frame_host);
- // Even when there is no pending RVH, there may be a pending Web UI.
- if (pending_web_ui() || speculative_web_ui_)
+ // A commit is required if there is a navigating WebUI, even without a
+ // pending or speculative RenderFrameHost.
+ if (GetNavigatingWebUI())
CommitPending();
return;
}
@@ -1025,41 +1019,44 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
(!request.browser_initiated() && is_main_frame) ||
(!is_main_frame && !dest_site_instance->RequiresDedicatedProcess() &&
!current_site_instance->RequiresDedicatedProcess())) {
- // Reuse the current RFH if its SiteInstance matches the the navigation's
- // or if this is a subframe navigation. We only swap RFHs for subframes when
- // --site-per-process is enabled.
+ // Reuse the current RenderFrameHost if its SiteInstance matches the the
+ // navigation's or if this is a subframe navigation. We only swap RFHs for
+ // subframes when --site-per-process is enabled.
CleanUpNavigation();
navigation_rfh = render_frame_host_.get();
- // As SiteInstances are the same, check if the WebUI should be reused.
- const NavigationEntry* current_navigation_entry =
- delegate_->GetLastCommittedNavigationEntryForRenderManager();
- should_reuse_web_ui_ = ShouldReuseWebUI(current_navigation_entry,
- request.common_params().url);
- if (!should_reuse_web_ui_) {
- speculative_web_ui_ = CreateWebUI(request.common_params().url,
- request.bindings());
- // Make sure the current RenderViewHost has the right bindings.
- if (speculative_web_ui() &&
- !render_frame_host_->GetProcess()->IsForGuestsOnly()) {
- render_frame_host_->render_view_host()->AllowBindings(
- speculative_web_ui()->GetBindings());
- }
- }
+ UpdateWebUIOnCurrentFrameHost(
+ request.common_params().url,
+ request.restore_type() != NavigationEntryImpl::RESTORE_NONE,
+ request.bindings());
+
+ DCHECK(!speculative_render_frame_host_);
} else {
- // If the SiteInstance for the final URL doesn't match the one from the
- // speculatively created RenderFrameHost, create a new RenderFrameHost using
- // this new SiteInstance.
+ // If the current RenderFrameHost cannot be used a new speculative one is
+ // created with the SiteInstance for the current URL.
+
+ // Check if an existing speculative RenderFrameHost can be reused.
if (!speculative_render_frame_host_ ||
speculative_render_frame_host_->GetSiteInstance() !=
dest_site_instance.get()) {
+ // If a previous speculative RenderFrameHost didn't exist or if its
+ // SiteInstace differs from the one for the current URL, a new one needs
+ // to be created.
CleanUpNavigation();
- bool success = CreateSpeculativeRenderFrameHost(
- request.common_params().url, current_site_instance,
- dest_site_instance.get(), request.bindings());
+ bool success = CreateSpeculativeRenderFrameHost(current_site_instance,
+ dest_site_instance.get());
DCHECK(success);
}
+
+ bool changed_web_ui = speculative_render_frame_host_->UpdateWebUI(
+ request.common_params().url, request.bindings());
+ if (changed_web_ui && speculative_render_frame_host_->web_ui()) {
+ speculative_render_frame_host_->web_ui()->RenderViewCreated(
+ speculative_render_frame_host_->render_view_host());
+ }
DCHECK(speculative_render_frame_host_);
+ DCHECK_EQ(GetNavigatingWebUI(), speculative_render_frame_host_->web_ui());
+
navigation_rfh = speculative_render_frame_host_.get();
// Check if our current RFH is live.
@@ -1071,6 +1068,7 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
// RFH isn't live.)
CommitPending();
}
+ DCHECK(!current_web_ui_is_navigating_);
}
DCHECK(navigation_rfh &&
(navigation_rfh == render_frame_host_.get() ||
@@ -1081,8 +1079,12 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
if (!navigation_rfh->IsRenderFrameLive()) {
// Recreate the opener chain.
CreateOpenerProxies(navigation_rfh->GetSiteInstance(), frame_tree_node_);
- if (!InitRenderView(navigation_rfh->render_view_host(), nullptr)) {
+ if (!InitRenderView(navigation_rfh->render_view_host(), nullptr))
return nullptr;
+
+ if (GetNavigatingWebUI()) {
+ GetNavigatingWebUI()->RenderViewCreated(
+ navigation_rfh->render_view_host());
}
if (navigation_rfh == render_frame_host_) {
@@ -1104,8 +1106,9 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
void RenderFrameHostManager::CleanUpNavigation() {
CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableBrowserSideNavigation));
- speculative_web_ui_.reset();
- should_reuse_web_ui_ = false;
+ // TODO(carlosk): the discarding of the current RFH WebUI and the cleanup of
+ // the speculative RFH should not always happen together.
+ current_web_ui_is_navigating_ = false;
if (speculative_render_frame_host_)
DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost());
}
@@ -1298,18 +1301,6 @@ bool RenderFrameHostManager::ShouldSwapBrowsingInstancesForNavigation(
return false;
}
-bool RenderFrameHostManager::ShouldReuseWebUI(
- const NavigationEntry* current_entry,
- const GURL& new_url) const {
- NavigationControllerImpl& controller =
- delegate_->GetControllerForRenderManager();
- return current_entry && web_ui_ &&
- (WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
- controller.GetBrowserContext(), current_entry->GetURL()) ==
- WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
- controller.GetBrowserContext(), new_url));
-}
-
SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation(
const GURL& dest_url,
SiteInstance* source_instance,
@@ -1642,8 +1633,8 @@ void RenderFrameHostManager::CreatePendingRenderFrameHost(
CreateProxiesForNewRenderFrameHost(old_instance, new_instance);
// Create a non-swapped-out RFH with the given opener.
- pending_render_frame_host_ = CreateRenderFrame(
- new_instance, pending_web_ui(), create_render_frame_flags, nullptr);
+ pending_render_frame_host_ =
+ CreateRenderFrame(new_instance, create_render_frame_flags, nullptr);
}
void RenderFrameHostManager::CreateProxiesForNewRenderFrameHost(
@@ -1739,18 +1730,11 @@ scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost(
// PlzNavigate
bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost(
- const GURL& url,
SiteInstance* old_instance,
- SiteInstance* new_instance,
- int bindings) {
+ SiteInstance* new_instance) {
CHECK(new_instance);
CHECK_NE(old_instance, new_instance);
- CHECK(!should_reuse_web_ui_);
-
- // Note: |speculative_web_ui_| must be initialized before starting the
- // |speculative_render_frame_host_| creation steps otherwise the WebUI
- // won't be properly initialized.
- speculative_web_ui_ = CreateWebUI(url, bindings);
+ CHECK(!current_web_ui_is_navigating_);
// The process for the new SiteInstance may (if we're sharing a process with
// another host that already initialized it) or may not (we have our own
@@ -1765,19 +1749,13 @@ bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost(
if (delegate_->IsHidden())
create_render_frame_flags |= CREATE_RF_HIDDEN;
speculative_render_frame_host_ =
- CreateRenderFrame(new_instance, speculative_web_ui_.get(),
- create_render_frame_flags, nullptr);
+ CreateRenderFrame(new_instance, create_render_frame_flags, nullptr);
- if (!speculative_render_frame_host_) {
- speculative_web_ui_.reset();
- return false;
- }
- return true;
+ return !!speculative_render_frame_host_;
}
scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame(
SiteInstance* instance,
- WebUIImpl* web_ui,
int flags,
int* view_routing_id_ptr) {
bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT);
@@ -1895,21 +1873,6 @@ scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame(
}
}
- // When a new RenderView is created by the renderer process, the new
- // WebContents gets a RenderViewHost in the SiteInstance of its opener
- // WebContents. If not used in the first navigation, this RVH is swapped out
- // and is not granted bindings, so we may need to grant them when swapping it
- // in.
- if (web_ui && !new_render_frame_host->GetProcess()->IsForGuestsOnly()) {
- int required_bindings = web_ui->GetBindings();
- RenderViewHost* render_view_host =
- new_render_frame_host->render_view_host();
- if ((render_view_host->GetEnabledBindings() & required_bindings) !=
- required_bindings) {
- render_view_host->AllowBindings(required_bindings);
- }
- }
-
// Returns the new RFH if it isn't swapped out.
if (success && !swapped_out) {
DCHECK(new_render_frame_host->GetSiteInstance() == instance);
@@ -2028,31 +1991,6 @@ bool RenderFrameHostManager::InitRenderView(
if (render_view_host->IsRenderViewLive())
return true;
- // If |render_view_host| is not for a proxy and the navigation is to a WebUI,
- // and if the RenderView is not in a guest process, tell |render_view_host|
- // about any bindings it will need enabled.
- // TODO(carlosk): Move WebUI to RenderFrameHost in https://crbug.com/508850.
- WebUIImpl* dest_web_ui = nullptr;
- if (!proxy) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserSideNavigation)) {
- dest_web_ui =
- should_reuse_web_ui_ ? web_ui_.get() : speculative_web_ui_.get();
- } else {
- dest_web_ui = pending_web_ui();
- }
- }
- if (dest_web_ui && !render_view_host->GetProcess()->IsForGuestsOnly()) {
- render_view_host->AllowBindings(dest_web_ui->GetBindings());
- } else {
- // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled
- // process unless it's swapped out.
- if (render_view_host->is_active()) {
- CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
- render_view_host->GetProcess()->GetID()));
- }
- }
-
int opener_frame_routing_id =
GetOpenerRoutingID(render_view_host->GetSiteInstance());
@@ -2144,42 +2082,17 @@ int RenderFrameHostManager::GetRoutingIdForSiteInstance(
void RenderFrameHostManager::CommitPending() {
TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending",
"FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
- bool browser_side_navigation =
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserSideNavigation);
-
// First check whether we're going to want to focus the location bar after
// this commit. We do this now because the navigation hasn't formally
- // committed yet, so if we've already cleared |pending_web_ui_| the call chain
+ // committed yet, so if we've already cleared the pending WebUI the call chain
// this triggers won't be able to figure out what's going on.
bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
- // Next commit the Web UI, if any. Either replace |web_ui_| with
- // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or
- // leave |web_ui_| as is if reusing it.
- DCHECK(!(pending_web_ui_ && pending_and_current_web_ui_));
- if (pending_web_ui_ || speculative_web_ui_) {
- DCHECK(!should_reuse_web_ui_);
- web_ui_.reset(browser_side_navigation ? speculative_web_ui_.release()
- : pending_web_ui_.release());
- } else if (pending_and_current_web_ui_ || should_reuse_web_ui_) {
- if (browser_side_navigation) {
- DCHECK(web_ui_);
- should_reuse_web_ui_ = false;
- } else {
- DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get());
- pending_and_current_web_ui_.reset();
- }
- } else {
- web_ui_.reset();
- }
- DCHECK(!speculative_web_ui_);
- DCHECK(!should_reuse_web_ui_);
-
- // It's possible for the pending_render_frame_host_ to be nullptr when we
- // aren't crossing process boundaries. If so, we just needed to handle the Web
- // UI committing above and we're done.
if (!pending_render_frame_host_ && !speculative_render_frame_host_) {
+ DCHECK_EQ(current_web_ui_is_navigating_, !!render_frame_host_->web_ui());
+ current_web_ui_is_navigating_ = false;
+ // If there's no pending/speculative RenderFrameHost then the current
+ // RenderFrameHost is committing.
if (will_focus_location_bar)
delegate_->SetFocusToLocationBar(false);
return;
@@ -2196,7 +2109,8 @@ void RenderFrameHostManager::CommitPending() {
// Swap in the pending or speculative frame and make it active. Also ensure
// the FrameTree stays in sync.
scoped_ptr<RenderFrameHostImpl> old_render_frame_host;
- if (!browser_side_navigation) {
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation)) {
DCHECK(!speculative_render_frame_host_);
old_render_frame_host =
SetRenderFrameHost(pending_render_frame_host_.Pass());
@@ -2366,9 +2280,6 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
dest_url, source_instance, dest_instance, nullptr, transition,
dest_is_restore, dest_is_view_source_mode);
- const NavigationEntry* current_entry =
- delegate_->GetLastCommittedNavigationEntryForRenderManager();
-
DCHECK(!pending_render_frame_host_);
if (new_instance.get() != current_instance) {
@@ -2381,17 +2292,21 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
// New SiteInstance: create a pending RFH to navigate.
- // This will possibly create (set to nullptr) a Web UI object for the
- // pending page. We'll use this later to give the page special access. This
- // must happen before the new renderer is created below so it will get
- // bindings. It must also happen after the above conditional call to
- // CancelPending(), otherwise CancelPending may clear the pending_web_ui_
- // and the page will not have its bindings set appropriately.
- SetPendingWebUI(dest_url, bindings);
+ current_web_ui_is_navigating_ = false;
CreatePendingRenderFrameHost(current_instance, new_instance.get());
+ DCHECK(pending_render_frame_host_);
if (!pending_render_frame_host_)
return nullptr;
+ pending_render_frame_host_->UpdateWebUI(dest_url, bindings);
+ if (pending_render_frame_host_->web_ui()) {
+ pending_render_frame_host_->web_ui()->RenderViewCreated(
+ pending_render_frame_host_->render_view_host());
+ }
+
+ // We now have a pending RFH and possibly an associated pending WebUI.
+ DCHECK_EQ(GetNavigatingWebUI(), pending_render_frame_host_->web_ui());
+
// Check if our current RFH is live before we set up a transition.
if (!render_frame_host_->IsRenderFrameLive()) {
// The current RFH is not live. There's no reason to sit around with a
@@ -2404,16 +2319,12 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
}
// Otherwise, it's safe to treat this as a pending cross-process transition.
- // We now have a pending RFH.
- DCHECK(pending_render_frame_host_);
-
// We need to wait until the beforeunload handler has run, unless we are
// transferring an existing request (in which case it has already run).
// Suspend the new render view (i.e., don't let it send the cross-process
// Navigate message) until we hear back from the old renderer's
// beforeunload handler. If the handler returns false, we'll have to
// cancel the request.
- //
DCHECK(!pending_render_frame_host_->are_navigations_suspended());
bool is_transfer = transferred_request_id != GlobalRequestID();
if (is_transfer) {
@@ -2448,23 +2359,7 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
// delete the proxy.
proxy_hosts_->Remove(new_instance.get()->GetId());
- if (ShouldReuseWebUI(current_entry, dest_url)) {
- pending_web_ui_.reset();
- pending_and_current_web_ui_ = web_ui_->AsWeakPtr();
- } else {
- SetPendingWebUI(dest_url, bindings);
- // Make sure the new RenderViewHost has the right bindings.
- if (pending_web_ui() &&
- !render_frame_host_->GetProcess()->IsForGuestsOnly()) {
- render_frame_host_->render_view_host()->AllowBindings(
- pending_web_ui()->GetBindings());
- }
- }
-
- if (pending_web_ui() && render_frame_host_->IsRenderFrameLive()) {
- pending_web_ui()->RenderViewReused(render_frame_host_->render_view_host(),
- frame_tree_node_->IsMainFrame());
- }
+ UpdateWebUIOnCurrentFrameHost(dest_url, dest_is_restore, bindings);
// The renderer can exit view source mode when any error or cancellation
// happen. We must overwrite to recover the mode.
@@ -2477,9 +2372,39 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
return render_frame_host_.get();
}
+void RenderFrameHostManager::UpdateWebUIOnCurrentFrameHost(const GURL& dest_url,
+ bool dest_is_restore,
+ int bindings) {
+ WebUI::TypeID previous_web_ui_type = render_frame_host_->web_ui_type();
+ bool changed_web_ui = render_frame_host_->UpdateWebUI(dest_url, bindings);
+
+ // If a change in WebUI happened, check this is an acceptable case.
+ if (changed_web_ui)
+ CheckWebUITransition(previous_web_ui_type, dest_url, dest_is_restore);
+
+ // If there is a WebUI in the current RenderFrameHost, it will navigate.
+ current_web_ui_is_navigating_ = !!render_frame_host_->web_ui();
+ DCHECK_EQ(GetNavigatingWebUI(), render_frame_host_->web_ui());
+
+ // If the current RenderFrameHost has a WebUI and the associated RenderFrame
+ // is alive, notify to the WebUI that the RenderView is being created or
+ // reused depending on whether the WebUI was changed or not.
+ if (GetNavigatingWebUI() && render_frame_host_->IsRenderFrameLive()) {
+ if (changed_web_ui) {
+ GetNavigatingWebUI()->RenderViewCreated(
+ render_frame_host_->render_view_host());
+ } else {
+ GetNavigatingWebUI()->RenderViewReused(
+ render_frame_host_->render_view_host(),
+ frame_tree_node_->IsMainFrame());
+ }
+ }
+}
+
void RenderFrameHostManager::CancelPending() {
TRACE_EVENT1("navigation", "RenderFrameHostManager::CancelPending",
"FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
+ current_web_ui_is_navigating_ = false;
DiscardUnusedFrame(UnsetPendingRenderFrameHost());
}
@@ -2492,12 +2417,11 @@ RenderFrameHostManager::UnsetPendingRenderFrameHost() {
pending_render_frame_host.get(),
render_frame_host_.get());
+ current_web_ui_is_navigating_ = false;
+
// We no longer need to prevent the process from exiting.
pending_render_frame_host->GetProcess()->RemovePendingView();
- pending_web_ui_.reset();
- pending_and_current_web_ui_.reset();
-
return pending_render_frame_host.Pass();
}
@@ -2672,8 +2596,7 @@ void RenderFrameHostManager::CreateOpenerProxiesForFrameTree(
frame_tree->root()->render_manager()->CreateRenderFrameProxy(instance);
} else {
frame_tree->root()->render_manager()->CreateRenderFrame(
- instance, nullptr, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN,
- nullptr);
+ instance, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN, nullptr);
}
}
}
@@ -2688,4 +2611,51 @@ int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) {
->GetRoutingIdForSiteInstance(instance);
}
+void RenderFrameHostManager::CheckWebUITransition(
+ WebUI::TypeID previous_web_ui_type,
+ const GURL& dest_url,
+ bool dest_is_restore) {
+ // There are a few navigation cases that allow for changes to the WebUI of
+ // the current RenderFrameHost.
+ BrowserContext* browser_context =
+ delegate_->GetControllerForRenderManager().GetBrowserContext();
+ if (render_frame_host_->web_ui()) {
+ // Switching WebUI from one type to another while keeping the
+ // RenderFrameHost is never acceptable.
+ CHECK(previous_web_ui_type == WebUI::kNoWebUI);
+
+ // Going from not having to having a WebUI is acceptable for:
+ // - The first navigation of this frame.
+ const NavigationEntry* current_entry =
+ delegate_->GetLastCommittedNavigationEntryForRenderManager();
+ bool is_first_navigation_for_frame = !current_entry;
+
+ // - A restore navigation to a WebUI URL.
+ const GURL& current_effective_url =
+ current_entry ? SiteInstanceImpl::GetEffectiveURL(
+ browser_context, current_entry->GetURL())
+ : render_frame_host_->GetSiteInstance()->GetSiteURL();
+ bool is_webui_restore =
+ dest_is_restore &&
+ WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
+ browser_context, current_effective_url);
+
+ // - Navigating back from a special renderer URL.
+ bool is_back_from_renderer_url =
+ current_entry && IsRendererDebugURL(current_entry->GetURL());
+
+ // - Navigating in webview tag guest.
+ bool is_webview_tag_guest =
+ render_frame_host_->GetSiteInstance()->GetSiteURL().SchemeIs(
+ kGuestScheme);
+ CHECK(is_first_navigation_for_frame || is_webui_restore ||
+ is_back_from_renderer_url || is_webview_tag_guest);
+ } else {
+ // Going from having to not having a WebUI is acceptable when Navigating to
+ // a special renderer URL.
+ CHECK(IsRendererDebugURL(
+ SiteInstanceImpl::GetEffectiveURL(browser_context, dest_url)));
+ }
+}
+
} // namespace content
diff --git a/content/browser/frame_host/render_frame_host_manager.h b/content/browser/frame_host/render_frame_host_manager.h
index ae64247..1c6c405d 100644
--- a/content/browser/frame_host/render_frame_host_manager.h
+++ b/content/browser/frame_host/render_frame_host_manager.h
@@ -12,6 +12,7 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/site_instance_impl.h"
#include "content/common/content_export.h"
@@ -33,9 +34,7 @@ class NavigationEntryImpl;
class NavigationHandleImpl;
class NavigationRequest;
class NavigatorTestWithBrowserSideNavigation;
-class RenderFrameHost;
class RenderFrameHostDelegate;
-class RenderFrameHostImpl;
class RenderFrameHostManagerTest;
class RenderFrameProxyHost;
class RenderViewHost;
@@ -148,12 +147,6 @@ class CONTENT_EXPORT RenderFrameHostManager {
virtual NavigationControllerImpl&
GetControllerForRenderManager() = 0;
- // Creates a WebUI object for the given URL if one applies. Ownership of the
- // returned pointer will be passed to the caller. If no WebUI applies,
- // returns NULL.
- virtual scoped_ptr<WebUIImpl> CreateWebUIForRenderManager(
- const GURL& url) = 0;
-
// Returns the navigation entry of the current navigation, or NULL if there
// is none.
virtual NavigationEntry*
@@ -249,7 +242,7 @@ class CONTENT_EXPORT RenderFrameHostManager {
// somehwere else.
void RemoveOuterDelegateFrame();
- // Returns the pending RenderFrameHost, or NULL if there is no pending one.
+ // Returns the pending RenderFrameHost, or null if there is no pending one.
RenderFrameHostImpl* pending_frame_host() const {
return pending_render_frame_host_.get();
}
@@ -263,21 +256,12 @@ class CONTENT_EXPORT RenderFrameHostManager {
// TODO(creis): Remove this when we no longer use RVH for navigation.
RenderViewHostImpl* pending_render_view_host() const;
- // Returns the current committed Web UI or NULL if none applies.
- WebUIImpl* web_ui() const { return web_ui_.get(); }
+ // Returns the current committed WebUI or null if none applies.
+ WebUIImpl* web_ui() const { return render_frame_host_->web_ui(); }
- // Returns the Web UI for the pending navigation, or NULL of none applies.
- WebUIImpl* pending_web_ui() const {
- return pending_web_ui_.get() ? pending_web_ui_.get() :
- pending_and_current_web_ui_.get();
- }
-
- // PlzNavigate
- // Returns the speculative WebUI for the navigation (a newly created one or
- // the current one if it should be reused). If none is set returns nullptr.
- WebUIImpl* speculative_web_ui() const {
- return should_reuse_web_ui_ ? web_ui_.get() : speculative_web_ui_.get();
- }
+ // Returns the WebUI associated with the RenderFrameHost that is currently
+ // navigating or null if none applies.
+ WebUIImpl* GetNavigatingWebUI() const;
// Called when we want to instruct the renderer to navigate to the given
// navigation entry. It may create a new RenderFrameHost or re-use an existing
@@ -353,19 +337,12 @@ class CONTENT_EXPORT RenderFrameHostManager {
void DidChangeOpener(int opener_routing_id,
SiteInstance* source_site_instance);
- // Sets the pending Web UI for the pending navigation, ensuring that the
- // bindings are appropriate compared to |bindings|.
- void SetPendingWebUI(const GURL& url, int bindings);
-
- // Creates and initializes a RenderFrameHost. The |web_ui| is an optional
- // input parameter used to double check bindings when swapping back in a
- // previously existing RenderFrameHost. If |flags| has the
+ // Creates and initializes a RenderFrameHost. If |flags| has the
// CREATE_RF_SWAPPED_OUT bit set from the CreateRenderFrameFlags enum, it will
// initially be placed on the swapped out hosts list. If |view_routing_id_ptr|
// is not nullptr it will be set to the routing id of the view associated with
// the frame.
scoped_ptr<RenderFrameHostImpl> CreateRenderFrame(SiteInstance* instance,
- WebUIImpl* web_ui,
int flags,
int* view_routing_id_ptr);
@@ -568,16 +545,6 @@ class CONTENT_EXPORT RenderFrameHostManager {
const GURL& new_effective_url,
bool new_is_view_source_mode) const;
- // Creates a new Web UI, ensuring that the bindings are appropriate compared
- // to |bindings|.
- scoped_ptr<WebUIImpl> CreateWebUI(const GURL& url, int bindings);
-
- // Returns true if it is safe to reuse the current WebUI when navigating from
- // |current_entry| to |new_url|.
- bool ShouldReuseWebUI(
- const NavigationEntry* current_entry,
- const GURL& new_url) const;
-
// Returns the SiteInstance to use for the navigation.
SiteInstance* GetSiteInstanceForNavigation(const GURL& dest_url,
SiteInstance* source_instance,
@@ -664,13 +631,11 @@ class CONTENT_EXPORT RenderFrameHostManager {
int flags);
// PlzNavigate
- // Creates and initializes a speculative RenderFrameHost and/or WebUI for an
- // ongoing navigation. They might be destroyed and re-created later if the
- // navigation is redirected to a different SiteInstance.
- bool CreateSpeculativeRenderFrameHost(const GURL& url,
- SiteInstance* old_instance,
- SiteInstance* new_instance,
- int bindings);
+ // Create and initialize a speculative RenderFrameHost for an ongoing
+ // navigation. It might be destroyed and re-created later if the navigation
+ // is redirected to a different SiteInstance.
+ bool CreateSpeculativeRenderFrameHost(SiteInstance* old_instance,
+ SiteInstance* new_instance);
// Sets up the necessary state for a new RenderViewHost. If |proxy| is not
// null, it creates a RenderFrameProxy in the target renderer process which is
@@ -683,9 +648,8 @@ class CONTENT_EXPORT RenderFrameHostManager {
// above.
bool InitRenderFrame(RenderFrameHostImpl* render_frame_host);
- // Sets the pending RenderFrameHost/WebUI to be the active one. Note that this
- // doesn't require the pending render_frame_host_ pointer to be non-NULL,
- // since there could be Web UI switching as well. Call this for every commit.
+ // Sets the pending RenderFrameHost to be the active one. Call this for every
+ // commit.
// If PlzNavigate is enabled the method will set the speculative (not pending)
// RenderFrameHost to be the active one.
void CommitPending();
@@ -741,10 +705,22 @@ class CONTENT_EXPORT RenderFrameHostManager {
const GlobalRequestID& transferred_request_id,
int bindings);
+ // Updates the WebUI of the current RenderFrameHost for same-site navigations.
+ void UpdateWebUIOnCurrentFrameHost(const GURL& dest_url,
+ bool dest_is_restore,
+ int bindings);
+
// Called when a renderer process is starting to close. We should not
// schedule new navigations in its swapped out RenderFrameHosts after this.
void RendererProcessClosing(RenderProcessHost* render_process_host);
+ // Checks that the current navigation case justifies a WebUI change in the
+ // current RenderFrameHost. Will crash the browser if the transition is
+ // considered not acceptable.
+ void CheckWebUITransition(WebUI::TypeID previous_web_ui_type,
+ const GURL& dest_url,
+ bool dest_is_restore);
+
// For use in creating RenderFrameHosts.
FrameTreeNode* frame_tree_node_;
@@ -757,25 +733,15 @@ class CONTENT_EXPORT RenderFrameHostManager {
RenderViewHostDelegate* render_view_delegate_;
RenderWidgetHostDelegate* render_widget_delegate_;
- // Our RenderFrameHost and its associated Web UI (if any, will be NULL for
- // non-WebUI pages). This object is responsible for all communication with
- // a child RenderFrame instance.
+ // Our RenderFrameHost which is responsible for all communication with a child
+ // RenderFrame instance.
// For now, RenderFrameHost keeps a RenderViewHost in its SiteInstance alive.
// Eventually, RenderViewHost will be replaced with a page context.
scoped_ptr<RenderFrameHostImpl> render_frame_host_;
- scoped_ptr<WebUIImpl> web_ui_;
// A RenderFrameHost used to load a cross-site page. This remains hidden
- // while a cross-site request is pending until it calls DidNavigate. It may
- // have an associated Web UI, in which case the Web UI pointer will be non-
- // NULL.
- //
- // The |pending_web_ui_| may be non-NULL even when the
- // |pending_render_frame_host_| is NULL. This will happen when we're
- // transitioning between two Web UI pages: the RFH won't be swapped, so the
- // pending pointer will be unused, but there will be a pending Web UI
- // associated with the navigation.
- // Note: This is not used in PlzNavigate.
+ // while a cross-site request is pending until it calls DidNavigate.
+ // Note: This member is not used in PlzNavigate.
scoped_ptr<RenderFrameHostImpl> pending_render_frame_host_;
// If a pending request needs to be transferred to another process, this
@@ -791,14 +757,6 @@ class CONTENT_EXPORT RenderFrameHostManager {
// navigations in PlzNavigate.
scoped_ptr<NavigationHandleImpl> transfer_navigation_handle_;
- // If either of these is non-NULL, the pending navigation is to a chrome:
- // page. The scoped_ptr is used if pending_web_ui_ != web_ui_, the WeakPtr is
- // used for when they reference the same object. If either is non-NULL, the
- // other should be NULL.
- // Note: These are not used in PlzNavigate.
- scoped_ptr<WebUIImpl> pending_web_ui_;
- base::WeakPtr<WebUIImpl> pending_and_current_web_ui_;
-
class RenderFrameProxyHostMap;
scoped_ptr<RenderFrameProxyHostMap> proxy_hosts_;
@@ -813,21 +771,19 @@ class CONTENT_EXPORT RenderFrameHostManager {
InterstitialPageImpl* interstitial_page_;
// PlzNavigate
- // These members store a speculative RenderFrameHost and WebUI. They are
- // created early in a navigation so a renderer process can be started in
- // parallel, if needed. This is purely a performance optimization and is not
- // required for correct behavior. The created RenderFrameHost might be
- // discarded later on if the final URL's SiteInstance isn't compatible with
- // what was used to create it.
- // Note: PlzNavigate only uses speculative RenderFrameHost and WebUI, not
- // the pending ones.
+ // Stores a speculative RenderFrameHost which is created early in a navigation
+ // so a renderer process can be started in parallel, if needed.
+ // This is purely a performance optimization and is not required for correct
+ // behavior. The speculative RenderFrameHost might be discarded later on if
+ // the final URL's SiteInstance isn't compatible with the one used to create
+ // it.
+ // Note: PlzNavigate only uses the speculative RenderFrameHost, not the
+ // pending one.
scoped_ptr<RenderFrameHostImpl> speculative_render_frame_host_;
- scoped_ptr<WebUIImpl> speculative_web_ui_;
- // PlzNavigate
- // If true at navigation commit time the current WebUI will be kept instead of
- // creating a new one.
- bool should_reuse_web_ui_;
+ // Indicates that the WebUI from the current RenderFrameHost is being used for
+ // an ongoing navigation and will be kept at navigation commit time.
+ bool current_web_ui_is_navigating_;
base::WeakPtrFactory<RenderFrameHostManager> weak_factory_;
diff --git a/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
index d06b2ff..5e7ac64 100644
--- a/content/browser/frame_host/render_frame_host_manager_browsertest.cc
+++ b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -1546,14 +1546,16 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
shell()->web_contents());
WebUIImpl* webui = web_contents->GetRenderManagerForTesting()->web_ui();
EXPECT_TRUE(webui);
- EXPECT_FALSE(web_contents->GetRenderManagerForTesting()->pending_web_ui());
+ EXPECT_FALSE(
+ web_contents->GetRenderManagerForTesting()->GetNavigatingWebUI());
// Navigate to another WebUI URL that reuses the WebUI object. Make sure we
- // clear pending_web_ui() when it commits.
+ // clear GetNavigatingWebUI() when it commits.
GURL webui_url2(webui_url.spec() + "#foo");
NavigateToURL(shell(), webui_url2);
EXPECT_EQ(webui, web_contents->GetRenderManagerForTesting()->web_ui());
- EXPECT_FALSE(web_contents->GetRenderManagerForTesting()->pending_web_ui());
+ EXPECT_FALSE(
+ web_contents->GetRenderManagerForTesting()->GetNavigatingWebUI());
}
class RFHMProcessPerTabTest : public RenderFrameHostManagerTest {
diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc
index e1d2b5b..47530a8 100644
--- a/content/browser/frame_host/render_frame_host_manager_unittest.cc
+++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -81,13 +81,21 @@ class RenderFrameHostManagerTestWebUIControllerFactory
// WebUIFactory implementation.
WebUIController* CreateWebUIControllerForURL(WebUI* web_ui,
const GURL& url) const override {
- if (!(should_create_webui_ && HasWebUIScheme(url)))
- return NULL;
- return new WebUIController(web_ui);
+ // If WebUI creation is enabled for the test and this is a WebUI URL,
+ // returns a new instance.
+ if (should_create_webui_ && HasWebUIScheme(url))
+ return new WebUIController(web_ui);
+ return nullptr;
}
WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
const GURL& url) const override {
+ // If WebUI creation is enabled for the test and this is a WebUI URL,
+ // returns a mock WebUI type.
+ if (should_create_webui_ && HasWebUIScheme(url)) {
+ return const_cast<RenderFrameHostManagerTestWebUIControllerFactory*>(
+ this);
+ }
return WebUI::kNoWebUI;
}
@@ -1116,12 +1124,7 @@ TEST_F(RenderFrameHostManagerTest, WebUI) {
// The Web UI is committed immediately because the RenderViewHost has not been
// used yet. UpdateStateForNavigate() took the short cut path.
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserSideNavigation)) {
- EXPECT_FALSE(manager->speculative_web_ui());
- } else {
- EXPECT_FALSE(manager->pending_web_ui());
- }
+ EXPECT_FALSE(manager->GetNavigatingWebUI());
EXPECT_TRUE(manager->web_ui());
// Commit.
@@ -1191,12 +1194,7 @@ TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) {
// No cross-process transition happens because we are already in the right
// SiteInstance. We should grant bindings immediately.
EXPECT_EQ(host2, manager2->current_frame_host());
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserSideNavigation)) {
- EXPECT_TRUE(manager2->speculative_web_ui());
- } else {
- EXPECT_TRUE(manager2->pending_web_ui());
- }
+ EXPECT_TRUE(manager2->GetNavigatingWebUI());
EXPECT_TRUE(
host2->render_view_host()->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI);
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 0a9956f..bf45da9 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -840,8 +840,9 @@ WebUI* WebContentsImpl::CreateSubframeWebUI(const GURL& url,
}
WebUI* WebContentsImpl::GetWebUI() const {
- return GetRenderManager()->web_ui() ? GetRenderManager()->web_ui()
- : GetRenderManager()->pending_web_ui();
+ return GetRenderManager()->web_ui()
+ ? GetRenderManager()->web_ui()
+ : GetRenderManager()->GetNavigatingWebUI();
}
WebUI* WebContentsImpl::GetCommittedWebUI() const {
@@ -912,8 +913,9 @@ const base::string16& WebContentsImpl::GetTitle() const {
if (entry) {
return entry->GetTitleForDisplay(accept_languages);
}
- WebUI* our_web_ui = GetRenderManager()->pending_web_ui() ?
- GetRenderManager()->pending_web_ui() : GetRenderManager()->web_ui();
+ WebUI* our_web_ui = GetRenderManager()->GetNavigatingWebUI()
+ ? GetRenderManager()->GetNavigatingWebUI()
+ : GetRenderManager()->web_ui();
if (our_web_ui) {
// Don't override the title in view source mode.
entry = controller_.GetVisibleEntry();
@@ -3779,18 +3781,6 @@ void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) {
Source<WebContents>(this),
Details<RenderViewHost>(render_view_host));
- // When we're creating views, we're still doing initial setup, so we always
- // use the pending Web UI rather than any possibly existing committed one.
- if (GetRenderManager()->pending_web_ui())
- GetRenderManager()->pending_web_ui()->RenderViewCreated(render_view_host);
-
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserSideNavigation) &&
- GetRenderManager()->speculative_web_ui()) {
- GetRenderManager()->speculative_web_ui()->RenderViewCreated(
- render_view_host);
- }
-
NavigationEntry* entry = controller_.GetPendingEntry();
if (entry && entry->IsViewSourceMode()) {
// Put the renderer in view source mode.
@@ -4199,7 +4189,7 @@ int WebContentsImpl::CreateSwappedOutRenderView(
GetRenderManager()->CreateRenderFrameProxy(instance);
} else {
GetRenderManager()->CreateRenderFrame(
- instance, nullptr, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN,
+ instance, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN,
&render_view_routing_id);
}
return render_view_routing_id;
@@ -4366,7 +4356,7 @@ NavigationControllerImpl& WebContentsImpl::GetControllerForRenderManager() {
return GetController();
}
-scoped_ptr<WebUIImpl> WebContentsImpl::CreateWebUIForRenderManager(
+scoped_ptr<WebUIImpl> WebContentsImpl::CreateWebUIForRenderFrameHost(
const GURL& url) {
return scoped_ptr<WebUIImpl>(static_cast<WebUIImpl*>(CreateWebUI(
url, std::string())));
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 779dd38..ea8095d 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -439,6 +439,7 @@ class CONTENT_EXPORT WebContentsImpl
RenderFrameHost* target_rfh,
SiteInstance* source_site_instance) const override;
void EnsureOpenerProxiesExist(RenderFrameHost* source_rfh) override;
+ scoped_ptr<WebUIImpl> CreateWebUIForRenderFrameHost(const GURL& url) override;
#if defined(OS_WIN)
gfx::NativeViewAccessible GetParentNativeViewAccessible() override;
#endif
@@ -626,7 +627,6 @@ class CONTENT_EXPORT WebContentsImpl
RenderViewHost* old_host,
RenderViewHost* new_host) override;
NavigationControllerImpl& GetControllerForRenderManager() override;
- scoped_ptr<WebUIImpl> CreateWebUIForRenderManager(const GURL& url) override;
NavigationEntry* GetLastCommittedNavigationEntryForRenderManager() override;
bool FocusLocationBarByDefault() override;
void SetFocusToLocationBar(bool select_all) override;