blob: 9038a10c6148c5ce9c9105ff6bff431b60314b4a [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/strings/string_number_conversions.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/test/browser_test_utils.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "weblayer/browser/browser_process.h"
#include "weblayer/browser/host_content_settings_map_factory.h"
#include "weblayer/browser/tab_impl.h"
#include "weblayer/shell/browser/shell.h"
#include "weblayer/test/weblayer_browser_test.h"
#include "weblayer/test/weblayer_browser_test_utils.h"
namespace weblayer {
class ClientHintsBrowserTest : public WebLayerBrowserTest {
public:
void SetUpOnMainThread() override {
WebLayerBrowserTest::SetUpOnMainThread();
BrowserProcess::GetInstance()
->GetNetworkQualityTracker()
->ReportRTTsAndThroughputForTesting(
base::TimeDelta::FromMilliseconds(500), 100);
EXPECT_TRUE(embedded_test_server()->Start());
}
void SetAcceptClientHints() {
NavigateAndWaitForCompletion(
embedded_test_server()->GetURL(
"/set-header?Accept-CH: device-memory,rtt&Accept-CH-Lifetime: "
"86400"),
shell());
}
void CheckNavigationHeaders() {
NavigateAndWaitForCompletion(
embedded_test_server()->GetURL("/echoheader?device-memory"), shell());
double device_memory = 0.0;
ASSERT_TRUE(base::StringToDouble(GetBody(), &device_memory));
EXPECT_GT(device_memory, 0.0);
NavigateAndWaitForCompletion(
embedded_test_server()->GetURL("/echoheader?rtt"), shell());
int rtt = 0;
ASSERT_TRUE(base::StringToInt(GetBody(), &rtt));
EXPECT_GT(rtt, 0);
}
void CheckSubresourceHeaders() {
double device_memory = 0.0;
ASSERT_TRUE(base::StringToDouble(GetSubresourceHeader("device-memory"),
&device_memory));
EXPECT_GT(device_memory, 0.0);
int rtt = 0;
ASSERT_TRUE(base::StringToInt(GetSubresourceHeader("rtt"), &rtt));
EXPECT_GT(rtt, 0);
}
void KillRenderer() {
content::RenderProcessHost* child_process =
static_cast<TabImpl*>(shell()->tab())
->web_contents()
->GetMainFrame()
->GetProcess();
content::RenderProcessHostWatcher crash_observer(
child_process,
content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
child_process->Shutdown(0);
crash_observer.Wait();
}
std::string GetSubresourceHeader(const std::string& header) {
constexpr char kScript[] = R"(
new Promise(function (resolve, reject) {
const xhr = new XMLHttpRequest();
xhr.open("GET", "/echoheader?" + $1);
xhr.onload = () => {
resolve(xhr.response);
};
xhr.send();
})
)";
content::WebContents* web_contents =
static_cast<TabImpl*>(shell()->tab())->web_contents();
return content::EvalJs(web_contents,
content::JsReplace(kScript, "device-memory"))
.ExtractString();
}
std::string GetBody() {
return ExecuteScript(shell(), "document.body.innerText", true).GetString();
}
};
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, Navigation) {
SetAcceptClientHints();
CheckNavigationHeaders();
}
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, Subresource) {
SetAcceptClientHints();
CheckSubresourceHeaders();
}
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, SubresourceInNewRenderer) {
SetAcceptClientHints();
KillRenderer();
NavigateAndWaitForCompletion(embedded_test_server()->GetURL("/echo"),
shell());
CheckSubresourceHeaders();
}
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
SubresourceAfterContentSettingUpdate) {
// Set accept client hints on the original server.
SetAcceptClientHints();
// Start a new server which will not accept client hints.
net::test_server::EmbeddedTestServer other_server;
net::test_server::RegisterDefaultHandlers(&other_server);
ASSERT_TRUE(other_server.Start());
NavigateAndWaitForCompletion(other_server.GetURL("/echo"), shell());
EXPECT_EQ(GetSubresourceHeader("device-memory"), "None");
// Copy client hints over to the other server.
auto* settings_map = HostContentSettingsMapFactory::GetForBrowserContext(
static_cast<TabImpl*>(shell()->tab())
->web_contents()
->GetBrowserContext());
std::unique_ptr<base::Value> setting = settings_map->GetWebsiteSetting(
embedded_test_server()->base_url(), GURL(),
ContentSettingsType::CLIENT_HINTS, nullptr);
ASSERT_TRUE(setting);
settings_map->SetWebsiteSettingDefaultScope(
other_server.base_url(), GURL(), ContentSettingsType::CLIENT_HINTS,
std::make_unique<base::Value>(setting->Clone()));
// Settings take affect after navigation only, so the header shouldn't be
// there yet.
EXPECT_EQ(GetSubresourceHeader("device-memory"), "None");
// After re-navigating, should have hints.
NavigateAndWaitForCompletion(other_server.GetURL("/echo"), shell());
CheckSubresourceHeaders();
}
} // namespace weblayer