client_hints_browsertest.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/strings/string_number_conversions.h"
  5. #include "components/content_settings/core/browser/host_content_settings_map.h"
  6. #include "content/public/browser/render_process_host.h"
  7. #include "content/public/test/browser_test_utils.h"
  8. #include "net/test/embedded_test_server/default_handlers.h"
  9. #include "net/test/embedded_test_server/embedded_test_server.h"
  10. #include "weblayer/browser/browser_process.h"
  11. #include "weblayer/browser/host_content_settings_map_factory.h"
  12. #include "weblayer/browser/tab_impl.h"
  13. #include "weblayer/shell/browser/shell.h"
  14. #include "weblayer/test/weblayer_browser_test.h"
  15. #include "weblayer/test/weblayer_browser_test_utils.h"
  16. namespace weblayer {
  17. class ClientHintsBrowserTest : public WebLayerBrowserTest {
  18. public:
  19. void SetUpOnMainThread() override {
  20. WebLayerBrowserTest::SetUpOnMainThread();
  21. BrowserProcess::GetInstance()
  22. ->GetNetworkQualityTracker()
  23. ->ReportRTTsAndThroughputForTesting(base::Milliseconds(500), 100);
  24. EXPECT_TRUE(embedded_test_server()->Start());
  25. }
  26. void SetAcceptClientHints() {
  27. NavigateAndWaitForCompletion(
  28. embedded_test_server()->GetURL(
  29. "/set-header?Accept-CH: device-memory,rtt"),
  30. shell());
  31. }
  32. void CheckNavigationHeaders() {
  33. NavigateAndWaitForCompletion(
  34. embedded_test_server()->GetURL("/echoheader?device-memory"), shell());
  35. double device_memory = 0.0;
  36. ASSERT_TRUE(base::StringToDouble(GetBody(), &device_memory));
  37. EXPECT_GT(device_memory, 0.0);
  38. NavigateAndWaitForCompletion(
  39. embedded_test_server()->GetURL("/echoheader?rtt"), shell());
  40. int rtt = 0;
  41. ASSERT_TRUE(base::StringToInt(GetBody(), &rtt));
  42. EXPECT_GT(rtt, 0);
  43. }
  44. void CheckSubresourceHeaders() {
  45. double device_memory = 0.0;
  46. ASSERT_TRUE(base::StringToDouble(GetSubresourceHeader("device-memory"),
  47. &device_memory));
  48. EXPECT_GT(device_memory, 0.0);
  49. int rtt = 0;
  50. ASSERT_TRUE(base::StringToInt(GetSubresourceHeader("rtt"), &rtt));
  51. EXPECT_GT(rtt, 0);
  52. }
  53. void KillRenderer() {
  54. content::RenderProcessHost* child_process =
  55. static_cast<TabImpl*>(shell()->tab())
  56. ->web_contents()
  57. ->GetPrimaryMainFrame()
  58. ->GetProcess();
  59. content::RenderProcessHostWatcher crash_observer(
  60. child_process,
  61. content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
  62. child_process->Shutdown(0);
  63. crash_observer.Wait();
  64. }
  65. std::string GetSubresourceHeader(const std::string& header) {
  66. constexpr char kScript[] = R"(
  67. new Promise(function (resolve, reject) {
  68. const xhr = new XMLHttpRequest();
  69. xhr.open("GET", "/echoheader?" + $1);
  70. xhr.onload = () => {
  71. resolve(xhr.response);
  72. };
  73. xhr.send();
  74. })
  75. )";
  76. content::WebContents* web_contents =
  77. static_cast<TabImpl*>(shell()->tab())->web_contents();
  78. return content::EvalJs(web_contents,
  79. content::JsReplace(kScript, "device-memory"))
  80. .ExtractString();
  81. }
  82. std::string GetBody() {
  83. return ExecuteScript(shell(), "document.body.innerText", true).GetString();
  84. }
  85. };
  86. IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, Navigation) {
  87. SetAcceptClientHints();
  88. CheckNavigationHeaders();
  89. }
  90. IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, Subresource) {
  91. SetAcceptClientHints();
  92. CheckSubresourceHeaders();
  93. }
  94. IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, SubresourceInNewRenderer) {
  95. SetAcceptClientHints();
  96. KillRenderer();
  97. NavigateAndWaitForCompletion(embedded_test_server()->GetURL("/echo"),
  98. shell());
  99. CheckSubresourceHeaders();
  100. }
  101. IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
  102. SubresourceAfterContentSettingUpdate) {
  103. // Set accept client hints on the original server.
  104. SetAcceptClientHints();
  105. // Start a new server which will not accept client hints.
  106. net::test_server::EmbeddedTestServer other_server;
  107. net::test_server::RegisterDefaultHandlers(&other_server);
  108. ASSERT_TRUE(other_server.Start());
  109. NavigateAndWaitForCompletion(other_server.GetURL("/echo"), shell());
  110. EXPECT_EQ(GetSubresourceHeader("device-memory"), "None");
  111. // Copy client hints over to the other server.
  112. auto* settings_map = HostContentSettingsMapFactory::GetForBrowserContext(
  113. static_cast<TabImpl*>(shell()->tab())
  114. ->web_contents()
  115. ->GetBrowserContext());
  116. base::Value setting = settings_map->GetWebsiteSetting(
  117. embedded_test_server()->base_url(), GURL(),
  118. ContentSettingsType::CLIENT_HINTS, nullptr);
  119. ASSERT_FALSE(setting.is_none());
  120. settings_map->SetWebsiteSettingDefaultScope(other_server.base_url(), GURL(),
  121. ContentSettingsType::CLIENT_HINTS,
  122. setting.Clone());
  123. // Settings take affect after navigation only, so the header shouldn't be
  124. // there yet.
  125. EXPECT_EQ(GetSubresourceHeader("device-memory"), "None");
  126. // After re-navigating, should have hints.
  127. NavigateAndWaitForCompletion(other_server.GetURL("/echo"), shell());
  128. CheckSubresourceHeaders();
  129. }
  130. } // namespace weblayer