blob: 085066a743ea75ff6bc13b191d7c9d3557eb1e93 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/functional/bind.h"
#include "content/browser/renderer_host/document_service_echo_impl.h"
#include "content/public/browser/document_service.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "content/public/test/back_forward_cache_util.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/prerender_test_util.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "content/test/echo.test-mojom.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace content {
class DocumentServiceBrowserTest : public ContentBrowserTest {
public:
DocumentServiceBrowserTest() = default;
~DocumentServiceBrowserTest() override = default;
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
ASSERT_TRUE(test_server_handle_ =
embedded_test_server()->StartAndReturnHandle());
}
WebContents* web_contents() const { return shell()->web_contents(); }
private:
net::test_server::EmbeddedTestServerHandle test_server_handle_;
};
class DocumentServicePrerenderingBrowserTest
: public DocumentServiceBrowserTest {
public:
DocumentServicePrerenderingBrowserTest()
: prerender_helper_(base::BindRepeating(
&DocumentServicePrerenderingBrowserTest::web_contents,
base::Unretained(this))) {}
~DocumentServicePrerenderingBrowserTest() override = default;
void SetUp() override {
prerender_helper_.RegisterServerRequestMonitor(embedded_test_server());
DocumentServiceBrowserTest::SetUp();
}
test::PrerenderTestHelper* prerender_helper() { return &prerender_helper_; }
private:
test::PrerenderTestHelper prerender_helper_;
};
// Tests that DocumentService is not destroyed on prerendering activation.
IN_PROC_BROWSER_TEST_F(DocumentServicePrerenderingBrowserTest,
NotClosedInPrerenderingActivation) {
const GURL kInitialUrl = embedded_test_server()->GetURL("/empty.html");
const GURL kPrerenderingUrl = embedded_test_server()->GetURL("/title1.html");
// The test assumes documents and their DocumentServices get deleted after
// non-activation navigations. To ensure this, disable back/forward cache.
DisableBackForwardCacheForTesting(
shell()->web_contents(),
content::BackForwardCache::TEST_REQUIRES_NO_CACHING);
// Navigate to an initial page.
ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl));
FrameTreeNodeId host_id = prerender_helper()->AddPrerender(kPrerenderingUrl);
RenderFrameHost* prerendered_frame_host =
prerender_helper()->GetPrerenderedMainFrameHost(host_id);
mojo::Remote<mojom::Echo> echo_remote;
bool echo_deleted = false;
new DocumentServiceEchoImpl(
*prerendered_frame_host, echo_remote.BindNewPipeAndPassReceiver(),
base::BindOnce([](bool* deleted) { *deleted = true; }, &echo_deleted));
// Activate the prerendered page.
prerender_helper()->NavigatePrimaryPage(kPrerenderingUrl);
// DocumentService should not be destroyed.
EXPECT_FALSE(echo_deleted);
ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl));
// It should be destroyed on navigation.
EXPECT_TRUE(echo_deleted);
}
class DocumentServiceBFCacheBrowserTest : public DocumentServiceBrowserTest {
public:
DocumentServiceBFCacheBrowserTest() {
feature_list_.InitWithFeaturesAndParameters(
GetDefaultEnabledBackForwardCacheFeaturesForTesting(),
GetDefaultDisabledBackForwardCacheFeaturesForTesting());
}
~DocumentServiceBFCacheBrowserTest() override = default;
private:
base::test::ScopedFeatureList feature_list_;
};
IN_PROC_BROWSER_TEST_F(DocumentServiceBFCacheBrowserTest, DocumentService) {
GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
// 1) Navigate to A.
ASSERT_TRUE(NavigateToURL(shell(), url_a));
RenderFrameHost* rfh_a =
web_contents()->GetPrimaryMainFrame(); // current_frame_host();
RenderFrameDeletedObserver delete_observer_rfh_a(rfh_a);
mojo::Remote<mojom::Echo> echo_remote;
bool echo_deleted = false;
new DocumentServiceEchoImpl(
*rfh_a, echo_remote.BindNewPipeAndPassReceiver(),
base::BindOnce([](bool* deleted) { *deleted = true; }, &echo_deleted));
// 2) Navigate to B.
ASSERT_TRUE(NavigateToURL(shell(), url_b));
// - Page A should be in the cache.
ASSERT_FALSE(delete_observer_rfh_a.deleted());
EXPECT_EQ(rfh_a->GetLifecycleState(),
RenderFrameHost::LifecycleState::kInBackForwardCache);
EXPECT_FALSE(echo_deleted);
// 3) Go back.
web_contents()->GetController().GoBack();
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_FALSE(echo_deleted);
// 4) Prevent caching and navigate to B.
DisableBFCacheForRFHForTesting(rfh_a);
ASSERT_TRUE(NavigateToURL(shell(), url_b));
delete_observer_rfh_a.WaitUntilDeleted();
EXPECT_TRUE(echo_deleted);
}
} // namespace content