blob: da7e7840df6a5de79588a8570e7a732537017443 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/loader/keep_alive_request_browsertest_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/ui/browser.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "content/public/test/back_forward_cache_util.h"
#include "content/public/test/browser_test_base.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/keep_alive_url_loader_utils.h"
#include "content/public/test/test_utils.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_status_code.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "url/url_util.h"
std::string EncodeRelativeURL(std::string_view relative_url) {
CHECK(relative_url.starts_with("/")) << relative_url;
url::RawCanonOutputT<char> buffer;
url::EncodeURIComponent(relative_url, &buffer);
return std::string(buffer.view());
}
ChromeKeepAliveRequestBrowserTestBase::ChromeKeepAliveRequestBrowserTestBase()
: https_test_server_(std::make_unique<net::EmbeddedTestServer>(
net::EmbeddedTestServer::TYPE_HTTPS)) {}
ChromeKeepAliveRequestBrowserTestBase::
~ChromeKeepAliveRequestBrowserTestBase() = default;
void ChromeKeepAliveRequestBrowserTestBase::SetUpOnMainThread() {
PlatformBrowserTest::SetUpOnMainThread();
host_resolver()->AddRule("*", "127.0.0.1");
// Initialize an HTTPS server, as some in-browser throttles like
// `variations::VariationsURLLoaderThrottle` only works in secure context.
https_test_server_->AddDefaultHandlers(GetChromeTestDataDir());
loaders_observer_ =
std::make_unique<content::KeepAliveURLLoadersTestObserver>(
web_contents()->GetBrowserContext());
}
void ChromeKeepAliveRequestBrowserTestBase::TearDownOnMainThread() {
ASSERT_TRUE(server()->ShutdownAndWaitUntilComplete());
}
void ChromeKeepAliveRequestBrowserTestBase::SetUpCommandLine(
base::CommandLine* command_line) {
// Ignore all HTTPS certificate errors, as
// `variations::VariationsURLLoaderThrottle` only works with google
// domains, which are not covered by
// `net::EmbeddedTestServer::CERT_TEST_NAMES`.
command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
}
void ChromeKeepAliveRequestBrowserTestBase::InitFeatureList(
const std::vector<base::test::FeatureRefAndParams>&
additional_features_and_params) {
feature_list_.InitWithFeaturesAndParameters(
content::GetDefaultEnabledBackForwardCacheFeaturesForTesting(
additional_features_and_params),
content::GetDefaultDisabledBackForwardCacheFeaturesForTesting());
}
void ChromeKeepAliveRequestBrowserTestBase::
LoadPageWithKeepAliveRequestAndSendResponseAfterUnload(
const GURL& keepalive_page_url,
net::test_server::ControllableHttpResponse* keepalive_request_handler,
const std::string& response) {
ASSERT_TRUE(content::NavigateToURL(web_contents(), keepalive_page_url));
content::RenderFrameHostWrapper rfh_1(current_frame_host());
// Ensure the current page can be unloaded instead of being cached.
DisableBackForwardCache(web_contents());
// Ensure the keepalive request is sent before leaving the current page.
keepalive_request_handler->WaitForRequest();
// Navigate to cross-origin page to ensure the 1st page can be unloaded.
ASSERT_TRUE(content::NavigateToURL(web_contents(), GetCrossOriginPageURL()));
// Ensure the 1st page has been unloaded.
ASSERT_TRUE(rfh_1.WaitUntilRenderFrameDeleted());
// The disconnected loader is still pending to receive response.
// Sends back response to terminate in-browser request handling.
keepalive_request_handler->Send(response);
keepalive_request_handler->Done();
}
std::vector<std::unique_ptr<net::test_server::ControllableHttpResponse>>
ChromeKeepAliveRequestBrowserTestBase::RegisterRequestHandlers(
const std::vector<std::string>& relative_urls) {
std::vector<std::unique_ptr<net::test_server::ControllableHttpResponse>>
handlers;
for (const auto& relative_url : relative_urls) {
handlers.emplace_back(
std::make_unique<net::test_server::ControllableHttpResponse>(
server(), relative_url));
}
return handlers;
}
GURL ChromeKeepAliveRequestBrowserTestBase::GetKeepAlivePageURL(
const std::string& host,
const std::string& target_relative_url,
const std::string& method) {
std::string url = base::StringPrintf(
"/fetch-keepalive.html?target_url=%s&method=%s",
EncodeRelativeURL(target_relative_url).c_str(), method.c_str());
return server()->GetURL(host, url);
}
GURL ChromeKeepAliveRequestBrowserTestBase::GetCrossOriginPageURL() {
return server()->GetURL(kSecondaryHost, "/title2.html");
}
void ChromeKeepAliveRequestBrowserTestBase::DisableBackForwardCache(
content::WebContents* web_contents) {
content::DisableBackForwardCacheForTesting(
web_contents, content::BackForwardCache::TEST_REQUIRES_NO_CACHING);
}
void ChromeKeepAliveRequestBrowserTestBase::SetUseHttps() {
use_https_ = true;
}
content::WebContents* ChromeKeepAliveRequestBrowserTestBase::web_contents() {
return browser()->tab_strip_model()->GetActiveWebContents();
}
content::RenderFrameHost*
ChromeKeepAliveRequestBrowserTestBase::current_frame_host() {
return web_contents()->GetPrimaryMainFrame();
}
net::EmbeddedTestServer* ChromeKeepAliveRequestBrowserTestBase::server() {
return use_https_ ? https_test_server_.get() : embedded_test_server();
}
content::KeepAliveURLLoadersTestObserver&
ChromeKeepAliveRequestBrowserTestBase::loaders_observer() {
return *loaders_observer_;
}