Commit 37d91a91 authored by Matt Falkenhagen's avatar Matt Falkenhagen Committed by Chromium LUCI CQ

prerender: Preserve browsing history upon activation.

In the multi-WebContents implementation, history must be copied from
the old WebContents's NavigationController.

Also adjust a unittest to more fully simulate navigation, as it's
necessary to commit the navigation in order to copy the history.

Bug: 1132746
Change-Id: I0e2061451779d1fa9e4db2957aa06d0a05bef436
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2612291Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Commit-Queue: Matt Falkenhagen <falken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#841405}
parent 7ef7c9c5
...@@ -386,6 +386,30 @@ IN_PROC_BROWSER_TEST_P(PrerenderBrowserTest, Activation_PopUpWindow) { ...@@ -386,6 +386,30 @@ IN_PROC_BROWSER_TEST_P(PrerenderBrowserTest, Activation_PopUpWindow) {
EXPECT_EQ(GetRequestCount(kPrerenderingUrl), 2); EXPECT_EQ(GetRequestCount(kPrerenderingUrl), 2);
} }
// Tests that back-forward history is preserved after activation.
IN_PROC_BROWSER_TEST_P(PrerenderBrowserTest, HistoryAfterActivation) {
// This test is only meaningful with activation.
if (IsActivationDisabled())
return;
const GURL kInitialUrl = GetUrl("/prerender/add_prerender.html");
const GURL kPrerenderingUrl = GetUrl("/empty.html");
// Navigate to an initial page.
ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl));
// Make and activate a prerendered page.
AddPrerender(kPrerenderingUrl);
NavigateWithLocation(kPrerenderingUrl);
EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), kPrerenderingUrl);
// Navigate back to the initial page.
content::TestNavigationObserver observer(shell()->web_contents());
shell()->GoBackOrForward(-1);
observer.Wait();
EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), kInitialUrl);
}
// TODO(https://crbug.com/1132746): Test canceling prerendering. // TODO(https://crbug.com/1132746): Test canceling prerendering.
// TODO(https://crbug.com/1132746): Test prerendering for 404 page, redirection, // TODO(https://crbug.com/1132746): Test prerendering for 404 page, redirection,
......
...@@ -82,6 +82,10 @@ bool PrerenderHost::ActivatePrerenderedContents( ...@@ -82,6 +82,10 @@ bool PrerenderHost::ActivatePrerenderedContents(
if (!current_web_contents) if (!current_web_contents)
return false; return false;
// Merge browsing history.
prerendered_contents_->GetController().CopyStateFromAndPrune(
&current_web_contents->GetController(), /*replace_entry=*/false);
// Activate the prerendered contents. // Activate the prerendered contents.
WebContentsDelegate* delegate = current_web_contents->GetDelegate(); WebContentsDelegate* delegate = current_web_contents->GetDelegate();
DCHECK(delegate); DCHECK(delegate);
......
...@@ -47,7 +47,8 @@ class CONTENT_EXPORT PrerenderHost final : public WebContentsObserver { ...@@ -47,7 +47,8 @@ class CONTENT_EXPORT PrerenderHost final : public WebContentsObserver {
// Activates the prerendered contents. Returns false when activation didn't // Activates the prerendered contents. Returns false when activation didn't
// occur for some reason. This must be called after this host gets ready for // occur for some reason. This must be called after this host gets ready for
// activation. // activation. `current_render_frame_host` is the RenderFrameHost that will
// be swapped out and destroyed by the activation.
bool ActivatePrerenderedContents( bool ActivatePrerenderedContents(
RenderFrameHostImpl& current_render_frame_host); RenderFrameHostImpl& current_render_frame_host);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
#include "content/browser/site_instance_impl.h" #include "content/browser/site_instance_impl.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_browser_context.h" #include "content/public/test/test_browser_context.h"
#include "content/test/test_render_frame_host.h" #include "content/test/test_render_frame_host.h"
#include "content/test/test_render_view_host.h" #include "content/test/test_render_view_host.h"
...@@ -54,7 +55,7 @@ class PrerenderHostTest : public RenderViewHostImplTestHarness { ...@@ -54,7 +55,7 @@ class PrerenderHostTest : public RenderViewHostImplTestHarness {
std::unique_ptr<TestWebContentsDelegate> web_contents_delegate_; std::unique_ptr<TestWebContentsDelegate> web_contents_delegate_;
}; };
TEST_F(PrerenderHostTest, StartPrerendering) { TEST_F(PrerenderHostTest, PrerenderAndActivate) {
std::unique_ptr<TestWebContents> web_contents = std::unique_ptr<TestWebContents> web_contents =
CreateWebContents(GURL("https://example.com/")); CreateWebContents(GURL("https://example.com/"));
RenderFrameHostImpl* initiator_rfh = web_contents->GetMainFrame(); RenderFrameHostImpl* initiator_rfh = web_contents->GetMainFrame();
...@@ -67,17 +68,25 @@ TEST_F(PrerenderHostTest, StartPrerendering) { ...@@ -67,17 +68,25 @@ TEST_F(PrerenderHostTest, StartPrerendering) {
std::move(attributes), initiator_rfh->GetGlobalFrameRoutingId(), std::move(attributes), initiator_rfh->GetGlobalFrameRoutingId(),
initiator_rfh->GetLastCommittedOrigin()); initiator_rfh->GetLastCommittedOrigin());
// Start the prerendering navigation.
prerender_host->StartPrerendering(); prerender_host->StartPrerendering();
// Prepare a fake response so as to commit the navigation.
TestRenderFrameHost* prerendering_rfh = static_cast<TestRenderFrameHost*>(
prerender_host->GetPrerenderedMainFrameHostForTesting());
ASSERT_TRUE(prerendering_rfh);
prerendering_rfh->PrepareForCommit();
// Artificially finish navigation to make the prerender host ready to provide
// the prerendered contents.
prerender_host->DidFinishNavigation(nullptr);
// Finish the prerendering navigation. Normally we could use
// EmbeddedTestServer to provide a response, but this test uses
// RenderViewHostImplTestHarness so the load goes through a
// TestNavigationURLLoader which we don't have access to in order
// to complete. Use NavigationSimulator to finish the navigation on the
// WebContents.
WebContents* prerender_contents = WebContents::FromRenderFrameHost(
prerender_host->GetPrerenderedMainFrameHostForTesting());
ASSERT_TRUE(prerender_contents);
std::unique_ptr<NavigationSimulator> sim =
NavigationSimulator::CreateFromPending(prerender_contents);
sim->ReadyToCommit();
sim->Commit();
EXPECT_TRUE(prerender_host->is_ready_for_activation());
// Activate.
EXPECT_TRUE(prerender_host->ActivatePrerenderedContents(*initiator_rfh)); EXPECT_TRUE(prerender_host->ActivatePrerenderedContents(*initiator_rfh));
} }
......
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