diff options
author | bengr@chromium.org <bengr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-26 09:43:28 +0000 |
---|---|---|
committer | bengr@chromium.org <bengr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-26 09:43:28 +0000 |
commit | 1b949c1ca1c6aed354b0600184d7437f2fa88c44 (patch) | |
tree | 8347b3887fb5454bcae9028f48a645faf82b4aab | |
parent | a08bc7d5e9c2668fe3d29cbfff1abc1b72ebb899 (diff) | |
download | chromium_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-- | AUTHORS | 1 | ||||
-rw-r--r-- | chrome/browser/io_thread.cc | 2 | ||||
-rw-r--r-- | chrome/browser/net/chrome_network_delegate.cc | 12 | ||||
-rw-r--r-- | chrome/browser/net/chrome_network_delegate.h | 7 | ||||
-rw-r--r-- | chrome/browser/net/client_hints.cc | 70 | ||||
-rw-r--r-- | chrome/browser/net/client_hints.h | 44 | ||||
-rw-r--r-- | chrome/browser/net/client_hints_unittest.cc | 49 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_io_data.cc | 2 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/chrome_tests_unit.gypi | 1 | ||||
-rw-r--r-- | chrome/common/chrome_switches.cc | 3 | ||||
-rw-r--r-- | chrome/common/chrome_switches.h | 1 |
12 files changed, 194 insertions, 0 deletions
@@ -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[]; |