summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbengr@chromium.org <bengr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-26 09:43:28 +0000
committerbengr@chromium.org <bengr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-26 09:43:28 +0000
commit1b949c1ca1c6aed354b0600184d7437f2fa88c44 (patch)
tree8347b3887fb5454bcae9028f48a645faf82b4aab
parenta08bc7d5e9c2668fe3d29cbfff1abc1b72ebb899 (diff)
downloadchromium_src-1b949c1ca1c6aed354b0600184d7437f2fa88c44.zip
chromium_src-1b949c1ca1c6aed354b0600184d7437f2fa88c44.tar.gz
chromium_src-1b949c1ca1c6aed354b0600184d7437f2fa88c44.tar.bz2
Client Hints
Client Hints can be used as input to proactive content negotiation; just as the Accept header allowed clients to indicate what formats they prefer, Client Hints allow clients to indicate a list of device and agent specific preferences. See: https://github.com/igrigorik/http-client-hints/blob/draft2/draft-grigorik-http-client-hints-01.txt Patched from https://codereview.chromium.org/23654014/, which was patched from https://codereview.chromium.org/11970002 BUG=170388 CONTRIBUTOR=yoav@yoav.ws Review URL: https://codereview.chromium.org/24451003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@225425 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--AUTHORS1
-rw-r--r--chrome/browser/io_thread.cc2
-rw-r--r--chrome/browser/net/chrome_network_delegate.cc12
-rw-r--r--chrome/browser/net/chrome_network_delegate.h7
-rw-r--r--chrome/browser/net/client_hints.cc70
-rw-r--r--chrome/browser/net/client_hints.h44
-rw-r--r--chrome/browser/net/client_hints_unittest.cc49
-rw-r--r--chrome/browser/profiles/profile_io_data.cc2
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_tests_unit.gypi1
-rw-r--r--chrome/common/chrome_switches.cc3
-rw-r--r--chrome/common/chrome_switches.h1
12 files changed, 194 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
index a7cc2ae..fe98bcf 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -285,6 +285,7 @@ Yael Aharon <yael.aharon@intel.com>
Yair Yogev <progame@chromium.org>
Yang Gu <yang.gu@intel.com>
Yarin Kaul <yarin.kaul@gmail.com>
+Yoav Weiss <yoav@yoav.ws>
Yoav Zilberberg <yoav.zilberberg@gmail.com>
Yong Shin <sy3620@gmail.com>
Yongsheng Zhu <yongsheng.zhu@intel.com>
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index 13f71ce..ccad1f5 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -511,6 +511,8 @@ void IOThread::InitAsync() {
ChromeNetworkDelegate* network_delegate =
new ChromeNetworkDelegate(extension_event_router_forwarder_,
&system_enable_referrers_);
+ if (command_line.HasSwitch(switches::kEnableClientHints))
+ network_delegate->SetEnableClientHints();
if (command_line.HasSwitch(switches::kDisableExtensionsHttpThrottling))
network_delegate->NeverThrottleRequests();
globals_->system_network_delegate.reset(network_delegate);
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc
index 11a211f..6ecac3d 100644
--- a/chrome/browser/net/chrome_network_delegate.cc
+++ b/chrome/browser/net/chrome_network_delegate.cc
@@ -30,6 +30,7 @@
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/google/google_util.h"
#include "chrome/browser/net/chrome_network_data_saving_metrics.h"
+#include "chrome/browser/net/client_hints.h"
#include "chrome/browser/net/connect_interceptor.h"
#include "chrome/browser/net/load_time_stats.h"
#include "chrome/browser/performance_monitor/performance_monitor.h"
@@ -334,6 +335,11 @@ void ChromeNetworkDelegate::set_predictor(
new chrome_browser_net::ConnectInterceptor(predictor));
}
+void ChromeNetworkDelegate::SetEnableClientHints() {
+ client_hints_.reset(new ClientHints());
+ client_hints_->Init();
+}
+
// static
void ChromeNetworkDelegate::NeverThrottleRequests() {
g_never_throttle_requests_ = true;
@@ -418,6 +424,12 @@ int ChromeNetworkDelegate::OnBeforeURLRequest(
if (enable_do_not_track_ && enable_do_not_track_->GetValue())
request->SetExtraRequestHeaderByName(kDNTHeader, "1", true /* override */);
+ if (client_hints_) {
+ request->SetExtraRequestHeaderByName(
+ ClientHints::kDevicePixelRatioHeader,
+ client_hints_->GetDevicePixelRatioHeader(), true);
+ }
+
bool force_safe_search = force_google_safe_search_ &&
force_google_safe_search_->GetValue();
diff --git a/chrome/browser/net/chrome_network_delegate.h b/chrome/browser/net/chrome_network_delegate.h
index e9bf978..ea5ddbb 100644
--- a/chrome/browser/net/chrome_network_delegate.h
+++ b/chrome/browser/net/chrome_network_delegate.h
@@ -10,9 +10,11 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/values.h"
#include "net/base/network_delegate.h"
+class ClientHints;
class CookieSettings;
class ExtensionInfoMap;
class PrefService;
@@ -90,6 +92,9 @@ class ChromeNetworkDelegate : public net::NetworkDelegate {
force_google_safe_search_ = force_google_safe_search;
}
+ // Adds the Client Hints header to HTTP requests.
+ void SetEnableClientHints();
+
// Causes |OnCanThrottleRequest| to always return false, for all
// instances of this object.
static void NeverThrottleRequests();
@@ -207,6 +212,8 @@ class ChromeNetworkDelegate : public net::NetworkDelegate {
// Total original size of all content before it was transferred.
int64 original_content_length_;
+ scoped_ptr<ClientHints> client_hints_;
+
DISALLOW_COPY_AND_ASSIGN(ChromeNetworkDelegate);
};
diff --git a/chrome/browser/net/client_hints.cc b/chrome/browser/net/client_hints.cc
new file mode 100644
index 0000000..af22726
--- /dev/null
+++ b/chrome/browser/net/client_hints.cc
@@ -0,0 +1,70 @@
+// Copyright 2013 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 "chrome/browser/net/client_hints.h"
+
+#include <locale>
+
+#include "base/bind.h"
+#include "base/strings/stringprintf.h"
+#include "base/task_runner_util.h"
+#include "content/public/browser/browser_thread.h"
+#include "ui/gfx/screen.h"
+
+namespace {
+
+float FetchScreenInfoOnUIThread() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ // TODO(bengr): Consider multi-display scenarios.
+ gfx::Display display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
+ return display.device_scale_factor();
+}
+
+} // namespace
+
+const char ClientHints::kDevicePixelRatioHeader[] = "CH-DPR";
+
+ClientHints::ClientHints()
+ : weak_ptr_factory_(this) {
+}
+
+ClientHints::~ClientHints() {
+}
+
+void ClientHints::Init() {
+ // TODO(bengr): Observe the device pixel ratio in case it changes during
+ // the Chrome session.
+ RetrieveScreenInfo();
+}
+
+bool ClientHints::RetrieveScreenInfo() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ return content::BrowserThread::PostTaskAndReplyWithResult(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&FetchScreenInfoOnUIThread),
+ base::Bind(
+ &ClientHints::UpdateScreenInfo, weak_ptr_factory_.GetWeakPtr()));
+}
+
+const std::string& ClientHints::GetDevicePixelRatioHeader() const {
+ return screen_hints_;
+}
+
+void ClientHints::UpdateScreenInfo(float device_pixel_ratio_value) {
+ if (device_pixel_ratio_value <= 0.0)
+ return;
+ std::string device_pixel_ratio = base::StringPrintf("%.2f",
+ device_pixel_ratio_value);
+ // Make sure the Client Hints value doesn't change
+ // according to the machine's locale
+ std::locale locale;
+ for (std::string::iterator it = device_pixel_ratio.begin();
+ it != device_pixel_ratio.end(); ++it) {
+ if (!std::isdigit(*it, locale))
+ *it = '.';
+ }
+ screen_hints_ = device_pixel_ratio;
+}
+
diff --git a/chrome/browser/net/client_hints.h b/chrome/browser/net/client_hints.h
new file mode 100644
index 0000000..c4beb39
--- /dev/null
+++ b/chrome/browser/net/client_hints.h
@@ -0,0 +1,44 @@
+// Copyright 2013 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.
+
+#ifndef CHROME_BROWSER_NET_CLIENT_HINTS_H_
+#define CHROME_BROWSER_NET_CLIENT_HINTS_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/weak_ptr.h"
+
+// ClientHints is a repository in Chrome for information used
+// to create the Client-Hints request header. For more information, see:
+// https://github.com/igrigorik/http-client-hints/blob/draft2/draft-grigorik-http-client-hints-01.txt
+class ClientHints {
+ public:
+ static const char kDevicePixelRatioHeader[];
+
+ ClientHints();
+ ~ClientHints();
+
+ void Init();
+
+ // Returns the device pixel ratio as a string. Its value is the same as
+ // window.devicePixelRatio in Javascript.
+ const std::string& GetDevicePixelRatioHeader() const;
+
+ private:
+ friend class ClientHintsTest;
+
+ // Retrieves and updates screen information for use on the IO thread.
+ bool RetrieveScreenInfo();
+
+ void UpdateScreenInfo(float device_pixel_ratio_value);
+
+ std::string screen_hints_;
+
+ base::WeakPtrFactory<ClientHints> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ClientHints);
+};
+
+#endif // CHROME_BROWSER_NET_CLIENT_HINTS_H_
diff --git a/chrome/browser/net/client_hints_unittest.cc b/chrome/browser/net/client_hints_unittest.cc
new file mode 100644
index 0000000..c93b3b6
--- /dev/null
+++ b/chrome/browser/net/client_hints_unittest.cc
@@ -0,0 +1,49 @@
+// Copyright 2013 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 "chrome/browser/net/client_hints.h"
+
+#include <locale.h>
+
+#include "base/logging.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class ClientHintsTest : public testing::Test {
+ public:
+ void UpdateScreenInfo(float pixel_ratio) {
+ client_hints_.UpdateScreenInfo(pixel_ratio);
+ };
+
+ protected:
+ ClientHints client_hints_;
+};
+
+TEST_F(ClientHintsTest, HintsWellFormatted) {
+ UpdateScreenInfo(1.567f);
+ std::string hint = client_hints_.GetDevicePixelRatioHeader();
+ EXPECT_EQ("1.57", hint);
+}
+
+TEST_F(ClientHintsTest, HintsWellFormattedWithNonEnLocale) {
+ setlocale(LC_ALL, "fr_FR.UTF-8");
+ UpdateScreenInfo(1.567f);
+ std::string hint = client_hints_.GetDevicePixelRatioHeader();
+ EXPECT_EQ("1.57", hint);
+}
+
+TEST_F(ClientHintsTest, HintsHaveNonbogusValues) {
+ UpdateScreenInfo(-1.567f);
+ std::string hint = client_hints_.GetDevicePixelRatioHeader();
+ EXPECT_EQ("", hint);
+
+ UpdateScreenInfo(1.567f);
+ hint = client_hints_.GetDevicePixelRatioHeader();
+ EXPECT_EQ("1.57", hint);
+
+ UpdateScreenInfo(0.0f);
+ hint = client_hints_.GetDevicePixelRatioHeader();
+ // Hints should be last known good values.
+ EXPECT_EQ("1.57", hint);
+}
+
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index 8caf7f3..f45977a 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -772,6 +772,8 @@ void ProfileIOData::Init(content::ProtocolHandlerMap* protocol_handlers) const {
new ChromeNetworkDelegate(
io_thread_globals->extension_event_router_forwarder.get(),
&enable_referrers_);
+ if (command_line.HasSwitch(switches::kEnableClientHints))
+ network_delegate->SetEnableClientHints();
network_delegate->set_extension_info_map(
profile_params_->extension_info_map.get());
network_delegate->set_url_blacklist_manager(url_blacklist_manager_.get());
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 2e7657f..050c8e2 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1184,6 +1184,8 @@
'browser/net/chrome_network_delegate.h',
'browser/net/chrome_url_request_context.cc',
'browser/net/chrome_url_request_context.h',
+ 'browser/net/client_hints.cc',
+ 'browser/net/client_hints.h',
'browser/net/connect_interceptor.cc',
'browser/net/connect_interceptor.h',
'browser/net/connection_tester.cc',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index cb16621..246134a 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -1001,6 +1001,7 @@
'browser/net/chrome_fraudulent_certificate_reporter_unittest.cc',
'browser/net/chrome_network_data_saving_metrics_unittest.cc',
'browser/net/chrome_network_delegate_unittest.cc',
+ 'browser/net/client_hints_unittest.cc',
'browser/net/connection_tester_unittest.cc',
'browser/net/dns_probe_runner_unittest.cc',
'browser/net/dns_probe_service_unittest.cc',
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 2a6f133..15fb191 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -559,6 +559,9 @@ const char kEnableBatchedShutdown[] = "enable-batched-shutdown";
// Enables the benchmarking extensions.
const char kEnableBenchmarking[] = "enable-benchmarking";
+// Enables client hints, which adds hints about browser state to HTTP requests.
+const char kEnableClientHints[] = "enable-client-hints";
+
// Enables pushing cloud policy to Chrome using an invalidation service.
const char kEnableCloudPolicyPush[] = "enable-cloud-policy-push";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 8015e3d..58d7ffa 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -166,6 +166,7 @@ extern const char kEnableAuthNegotiatePort[];
extern const char kEnableAutologin[];
extern const char kEnableBatchedShutdown[];
extern const char kEnableBenchmarking[];
+extern const char kEnableClientHints[];
extern const char kEnableCloudPolicyPush[];
extern const char kEnableCloudPrintProxy[];
extern const char kEnableComponentCloudPolicy[];