summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbengr@chromium.org <bengr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-05 05:07:23 +0000
committerbengr@chromium.org <bengr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-05 05:07:23 +0000
commit3620bbccdc81bc4af00cd68747e45b18c617617c (patch)
treedf2bc1ff4924599c97561d7346fefec3ae9f3eda
parent0a7465e3c2aec71ebdec2a9569542adc3fbe2f30 (diff)
downloadchromium_src-3620bbccdc81bc4af00cd68747e45b18c617617c.zip
chromium_src-3620bbccdc81bc4af00cd68747e45b18c617617c.tar.gz
chromium_src-3620bbccdc81bc4af00cd68747e45b18c617617c.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 Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=225425 Review URL: https://codereview.chromium.org/24451003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@227178 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.cc56
-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, 201 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
index 83b837b..aea966d 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -291,6 +291,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 a72e5f3..b347651 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -514,6 +514,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 4de27d4..230b40b 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..d64fe53
--- /dev/null
+++ b/chrome/browser/net/client_hints_unittest.cc
@@ -0,0 +1,56 @@
+// 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"
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_IOS)
+#include "base/test/scoped_locale.h"
+#endif
+#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);
+}
+
+// Android and iOS do not support setLocale.
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_IOS)
+// TODO(bengr): Use ScopedLocal in Windows once it is supported.
+TEST_F(ClientHintsTest, HintsWellFormattedWithNonEnLocale) {
+ base::ScopedLocale locale("fr_FR.UTF-8");
+ UpdateScreenInfo(1.567f);
+ std::string hint = client_hints_.GetDevicePixelRatioHeader();
+ EXPECT_EQ("1.57", hint);
+}
+#endif // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_IOS)
+
+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 1b7267b..28a7868 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1200,6 +1200,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 dd7b6cf..3921ec7 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -1002,6 +1002,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 512c07a..7c4087b 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -567,6 +567,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 81a25d1..726293e 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -168,6 +168,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[];