Commit a83e4009 authored by carlosk's avatar carlosk Committed by Commit bot

PlzNavigate: Improvements to RFHM commit logic.

Updates RFHM::CommitPendingIfNecessary to actually commit in a few more
cases and not crash when navigations happen simultaneously.

Also updates RFHM::CommitPending to make some logic clearer.

BUG=376094

Review URL: https://codereview.chromium.org/1036243003

Cr-Commit-Position: refs/heads/master@{#324234}
parent 1c8dbbf5
...@@ -455,46 +455,40 @@ void RenderFrameHostManager::DidNavigateFrame( ...@@ -455,46 +455,40 @@ void RenderFrameHostManager::DidNavigateFrame(
void RenderFrameHostManager::CommitPendingIfNecessary( void RenderFrameHostManager::CommitPendingIfNecessary(
RenderFrameHostImpl* render_frame_host, RenderFrameHostImpl* render_frame_host,
bool was_caused_by_user_gesture) { bool was_caused_by_user_gesture) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch( // Note: In PlzNavigate |cross_navigation_pending_| being false means there is
switches::kEnableBrowserSideNavigation)) { // *no* speculative RenderFrameHost set.
if (render_frame_host == speculative_render_frame_host_.get()) {
CommitPending();
} else if (render_frame_host == render_frame_host_.get()) {
// TODO(carlosk): this code doesn't properly handle in-page navigation or
// interwoven navigation requests.
DCHECK(!speculative_render_frame_host_);
} else {
// No one else should be sending us a DidNavigate in this state.
DCHECK(false);
}
DCHECK(!speculative_render_frame_host_);
return;
}
if (!cross_navigation_pending_) { if (!cross_navigation_pending_) {
DCHECK(!speculative_render_frame_host_);
DCHECK(!pending_render_frame_host_); DCHECK(!pending_render_frame_host_);
DCHECK_IMPLIES(should_reuse_web_ui_, web_ui_);
// We should only hear this from our current renderer. // We should only hear this from our current renderer.
DCHECK_EQ(render_frame_host_, render_frame_host); DCHECK_EQ(render_frame_host_, render_frame_host);
// Even when there is no pending RVH, there may be a pending Web UI. // Even when there is no pending RVH, there may be a pending Web UI.
if (pending_web_ui()) if (pending_web_ui() || speculative_web_ui_)
CommitPending(); CommitPending();
return; return;
} }
if (render_frame_host == pending_render_frame_host_) { if (render_frame_host == pending_render_frame_host_ ||
render_frame_host == speculative_render_frame_host_) {
// The pending cross-site navigation completed, so show the renderer. // The pending cross-site navigation completed, so show the renderer.
CommitPending(); CommitPending();
} else if (render_frame_host == render_frame_host_) { } else if (render_frame_host == render_frame_host_) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableBrowserSideNavigation)) {
CleanUpNavigation();
} else {
if (was_caused_by_user_gesture) { if (was_caused_by_user_gesture) {
// A navigation in the original page has taken place. Cancel the pending // A navigation in the original page has taken place. Cancel the
// one. Only do it for user gesture originated navigations to prevent // pending one. Only do it for user gesture originated navigations to
// page doing any shenanigans to prevent user from navigating. // prevent page doing any shenanigans to prevent user from navigating.
// See https://code.google.com/p/chromium/issues/detail?id=75195 // See https://code.google.com/p/chromium/issues/detail?id=75195
CancelPending(); CancelPending();
cross_navigation_pending_ = false; cross_navigation_pending_ = false;
} }
}
} else { } else {
// No one else should be sending us DidNavigate in this state. // No one else should be sending us DidNavigate in this state.
DCHECK(false); DCHECK(false);
...@@ -1680,26 +1674,27 @@ void RenderFrameHostManager::CommitPending() { ...@@ -1680,26 +1674,27 @@ void RenderFrameHostManager::CommitPending() {
// this triggers won't be able to figure out what's going on. // this triggers won't be able to figure out what's going on.
bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
if (!browser_side_navigation) {
DCHECK(!speculative_web_ui_);
// Next commit the Web UI, if any. Either replace |web_ui_| with // 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 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or
// leave |web_ui_| as is if reusing it. // leave |web_ui_| as is if reusing it.
DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get())); DCHECK(!(pending_web_ui_ && pending_and_current_web_ui_));
if (pending_web_ui_) { if (pending_web_ui_ || speculative_web_ui_) {
web_ui_.reset(pending_web_ui_.release()); DCHECK(!should_reuse_web_ui_);
} else if (!pending_and_current_web_ui_.get()) { web_ui_.reset(browser_side_navigation ? speculative_web_ui_.release()
web_ui_.reset(); : 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 { } else {
DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get()); DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get());
pending_and_current_web_ui_.reset(); pending_and_current_web_ui_.reset();
} }
} else { } else {
// PlzNavigate web_ui_.reset();
if (!should_reuse_web_ui_)
web_ui_.reset(speculative_web_ui_.release());
DCHECK(!speculative_web_ui_);
} }
DCHECK(!speculative_web_ui_);
DCHECK(!should_reuse_web_ui_);
// It's possible for the pending_render_frame_host_ to be nullptr when we // 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 // aren't crossing process boundaries. If so, we just needed to handle the Web
......
...@@ -1076,6 +1076,41 @@ TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) { ...@@ -1076,6 +1076,41 @@ TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) {
manager2->DidNavigateFrame(host2, true); manager2->DidNavigateFrame(host2, true);
} }
// Tests that a WebUI is correctly reused between chrome:// pages.
TEST_F(RenderFrameHostManagerTest, WebUIWasReused) {
set_should_create_webui(true);
// Navigate to a WebUI page.
const GURL kUrl1("chrome://foo");
contents()->NavigateAndCommit(kUrl1);
RenderFrameHostManager* manager =
main_test_rfh()->frame_tree_node()->render_manager();
WebUIImpl* web_ui = manager->web_ui();
EXPECT_TRUE(web_ui);
// Navigate to another WebUI page which should be same-site and keep the
// current WebUI.
const GURL kUrl2("chrome://foo/bar");
contents()->NavigateAndCommit(kUrl2);
EXPECT_EQ(web_ui, manager->web_ui());
}
// Tests that a WebUI is correctly cleaned up when navigating from a chrome://
// page to a non-chrome:// page.
TEST_F(RenderFrameHostManagerTest, WebUIWasCleared) {
set_should_create_webui(true);
// Navigate to a WebUI page.
const GURL kUrl1("chrome://foo");
contents()->NavigateAndCommit(kUrl1);
EXPECT_TRUE(main_test_rfh()->frame_tree_node()->render_manager()->web_ui());
// Navigate to a non-WebUI page.
const GURL kUrl2("http://www.google.com");
contents()->NavigateAndCommit(kUrl2);
EXPECT_FALSE(main_test_rfh()->frame_tree_node()->render_manager()->web_ui());
}
// Tests that we don't end up in an inconsistent state if a page does a back and // Tests that we don't end up in an inconsistent state if a page does a back and
// then reload. http://crbug.com/51680 // then reload. http://crbug.com/51680
// Also tests that only user-gesture navigations can interrupt cross-process // Also tests that only user-gesture navigations can interrupt cross-process
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment