Send DPR client hint on main frame requests
Compute DPR in the browser process and include it as a
client hint (if the origin requested it) on main
frame requests.
Bug: 821954
Change-Id: I73a2017d426cb6d9403d41bc89e3107da44034b2
Reviewed-on: https://chromium-review.googlesource.com/963315
Reviewed-by: Ryan Sturm <[email protected]>
Commit-Queue: Tarun Bansal <[email protected]>
Cr-Commit-Position: refs/heads/master@{#543209}
diff --git a/chrome/browser/client_hints/client_hints.cc b/chrome/browser/client_hints/client_hints.cc
index afc02919..eed74382 100644
--- a/chrome/browser/client_hints/client_hints.cc
+++ b/chrome/browser/client_hints/client_hints.cc
@@ -6,6 +6,7 @@
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
+#include "build/build_config.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/client_hints/client_hints.h"
@@ -21,8 +22,15 @@
#include "third_party/WebKit/public/common/client_hints/client_hints.h"
#include "third_party/WebKit/public/common/device_memory/approximated_device_memory.h"
#include "third_party/WebKit/public/platform/WebClientHintsType.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
#include "url/gurl.h"
+#if !defined(OS_ANDROID)
+#include "content/public/browser/host_zoom_map.h"
+#include "content/public/common/page_zoom.h"
+#endif // !OS_ANDROID
+
namespace {
bool IsJavaScriptAllowed(Profile* profile, const GURL& url) {
@@ -92,6 +100,42 @@
base::NumberToString(device_memory));
}
+ if (web_client_hints.IsEnabled(blink::mojom::WebClientHintsType::kDpr)) {
+ double device_scale_factor = 1.0;
+ if (display::Screen::GetScreen()) {
+ device_scale_factor = display::Screen::GetScreen()
+ ->GetPrimaryDisplay()
+ .device_scale_factor();
+ }
+
+ double zoom_factor = 1.0;
+
+// Android does not have the concept of zooming in like desktop.
+#if !defined(OS_ANDROID)
+ double zoom_level =
+ content::HostZoomMap::GetDefaultForBrowserContext(context)
+ ->GetZoomLevelForHostAndScheme(url.scheme(),
+ net::GetHostOrSpecFromURL(url));
+
+ double default_zoom_level =
+ content::HostZoomMap::GetDefaultForBrowserContext(context)
+ ->GetDefaultZoomLevel();
+
+ if (zoom_level <= 0.0)
+ zoom_level = default_zoom_level;
+
+ if (zoom_level > 0.0)
+ zoom_factor = content::ZoomLevelToZoomFactor(zoom_level);
+#endif // !OS_ANDROID
+
+ DCHECK_LT(0.0, device_scale_factor);
+
+ additional_headers->SetHeader(
+ blink::kClientHintsHeaderMapping[static_cast<int>(
+ blink::mojom::WebClientHintsType::kDpr)],
+ base::NumberToString(device_scale_factor * zoom_factor));
+ }
+
// Static assert that triggers if a new client hint header is added. If a new
// client hint header is added, the following assertion should be updated.
// If possible, logic should be added above so that the request headers for
diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc
index 6d87646..b96c11b 100644
--- a/chrome/browser/client_hints/client_hints_browsertest.cc
+++ b/chrome/browser/client_hints/client_hints_browsertest.cc
@@ -242,8 +242,8 @@
// device-memory header is attached to the main frame request.
EXPECT_EQ(expect_client_hints_on_main_frame_,
base::ContainsKey(request.headers, "device-memory"));
- // Currently, dpr header is never attached on the main frame request.
- EXPECT_FALSE(base::ContainsKey(request.headers, "dpr"));
+ EXPECT_EQ(expect_client_hints_on_main_frame_,
+ base::ContainsKey(request.headers, "dpr"));
}
if (!is_main_frame_navigation) {
@@ -350,8 +350,8 @@
SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
// Two client hints are attached to the image request, and the device-memory
- // header is attached to the main frame request.
- EXPECT_EQ(3u, count_client_hints_headers_seen());
+ // and dpr headers are attached to the main frame request.
+ EXPECT_EQ(4u, count_client_hints_headers_seen());
// Navigating to without_accept_ch_without_lifetime_img_foo_com() should not
// attach client hints to the image subresouce contained in that page since
@@ -362,8 +362,8 @@
content::FetchHistogramsFromChildProcesses();
SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
- // The device-memory header is attached to the main frame request.
- EXPECT_EQ(4u, count_client_hints_headers_seen());
+ // The device-memory and dprheader is attached to the main frame request.
+ EXPECT_EQ(6u, count_client_hints_headers_seen());
// Requests to third party servers should not have client hints attached.
EXPECT_EQ(1u, third_party_request_count_seen());
EXPECT_EQ(0u, third_party_client_hints_count_seen());
@@ -442,7 +442,7 @@
// Two client hints are attached to the image request, and the device-memory
// header is attached to the main frame request.
- EXPECT_EQ(3u, count_client_hints_headers_seen());
+ EXPECT_EQ(4u, count_client_hints_headers_seen());
}
// Loads a webpage that does not request persisting of client hints.
@@ -500,8 +500,8 @@
without_accept_ch_without_lifetime_url());
// Two client hints are attached to the image request, and the device-memory
- // header is attached to the main frame request.
- EXPECT_EQ(3u, count_client_hints_headers_seen());
+ // and dpr headers are attached to the main frame request.
+ EXPECT_EQ(4u, count_client_hints_headers_seen());
}
// Ensure that when cookies are blocked, client hint preferences are not
@@ -594,7 +594,7 @@
without_accept_ch_without_lifetime_url());
// Two client hints are attached to the image request, and the device-memory
// header is attached to the main frame request.
- EXPECT_EQ(3u, count_client_hints_headers_seen());
+ EXPECT_EQ(4u, count_client_hints_headers_seen());
// Clear settings.
HostContentSettingsMapFactory::GetForProfile(browser()->profile())
@@ -688,8 +688,8 @@
ui_test_utils::NavigateToURL(browser(),
without_accept_ch_without_lifetime_url());
// Two client hints are attached to the image request, and the device-memory
- // header is attached to the main frame request.
- EXPECT_EQ(3u, count_client_hints_headers_seen());
+ // and dpr headers are attached to the main frame request.
+ EXPECT_EQ(4u, count_client_hints_headers_seen());
// Clear settings.
HostContentSettingsMapFactory::GetForProfile(browser()->profile())