Commit 6ab8be24 authored by pmarko's avatar pmarko Committed by Commit bot

Respect QuicAllowed policy for new streams

Introduce a mechanism for an incoming QuicAllowed cloud policy
to control QUIC protocol usage for new streams even after
IOThread initialization.
NetPrefObserver has been re-introduced to observe the change
(after it was removed in crrev.com/2140733002 and
crrev.com/2172543003).

BUG=658454
TEST=browser_tests --gtest_filter=*QuicAllowed*
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:closure_compilation

Review-Url: https://codereview.chromium.org/2546533003
Cr-Commit-Position: refs/heads/master@{#442866}
parent 16e3f3b7
......@@ -1004,6 +1004,8 @@ split_static_library("browser") {
"profiles/incognito_helpers.h",
"profiles/incognito_mode_policy_handler.cc",
"profiles/incognito_mode_policy_handler.h",
"profiles/net_http_session_params_observer.cc",
"profiles/net_http_session_params_observer.h",
"profiles/off_the_record_profile_impl.cc",
"profiles/off_the_record_profile_impl.h",
"profiles/off_the_record_profile_io_data.cc",
......
......@@ -797,6 +797,16 @@ const net::HttpNetworkSession::Params& IOThread::NetworkSessionParams() const {
return params_;
}
void IOThread::DisableQuic() {
params_.enable_quic = false;
if (globals_->system_http_network_session)
globals_->system_http_network_session->DisableQuic();
if (globals_->proxy_script_fetcher_http_network_session)
globals_->proxy_script_fetcher_http_network_session->DisableQuic();
}
base::TimeTicks IOThread::creation_time() const {
return creation_time_;
}
......
......@@ -236,6 +236,12 @@ class IOThread : public content::BrowserThreadDelegate {
const net::HttpNetworkSession::Params& NetworkSessionParams() const;
// Dynamically disables QUIC for HttpNetworkSessions owned by io_thread, and
// to HttpNetworkSession::Params which are used for the creation of new
// HttpNetworkSessions. Not that re-enabling Quic dynamically is not
// supported for simplicity and requires a browser restart.
void DisableQuic();
base::TimeTicks creation_time() const;
// Returns the callback for updating data use prefs.
......
......@@ -116,6 +116,7 @@ const PolicyToPreferenceMapEntry kSimplePolicyMap[] = {
base::Value::Type::BOOLEAN},
{key::kPacHttpsUrlStrippingEnabled, prefs::kPacHttpsUrlStrippingEnabled,
base::Value::Type::BOOLEAN},
{key::kQuicAllowed, prefs::kQuicAllowed, base::Value::Type::BOOLEAN},
{key::kSafeBrowsingEnabled, prefs::kSafeBrowsingEnabled,
base::Value::Type::BOOLEAN},
{key::kForceGoogleSafeSearch, prefs::kForceGoogleSafeSearch,
......
......@@ -44,6 +44,7 @@
#include "chrome/browser/prefs/origin_trial_prefs.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/browser/profiles/chrome_version_service.h"
#include "chrome/browser/profiles/net_http_session_params_observer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_impl.h"
#include "chrome/browser/profiles/profile_info_cache.h"
......@@ -492,6 +493,7 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
MediaCaptureDevicesDispatcher::RegisterProfilePrefs(registry);
MediaDeviceIDSalt::RegisterProfilePrefs(registry);
MediaStreamDevicesController::RegisterProfilePrefs(registry);
NetHttpSessionParamsObserver::RegisterProfilePrefs(registry);
NotifierStateTracker::RegisterProfilePrefs(registry);
ntp_snippets::BookmarkSuggestionsProvider::RegisterProfilePrefs(registry);
ntp_snippets::ContentSuggestionsService::RegisterProfilePrefs(registry);
......
// Copyright 2017 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/profiles/net_http_session_params_observer.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/io_thread.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_thread.h"
using content::BrowserThread;
namespace {
// Called on IOThread to disable QUIC for globally-owned HttpNetworkSessions
// and for the profile (thrpugh |disable_quic_callback|). Note that re-enabling
// QUIC dynamically is not supported for simpliciy and requires a browser
// restart.
void DisableQuicOnIOThread(
NetHttpSessionParamsObserver::DisableQuicCallback disable_quic_callback,
IOThread* io_thread,
safe_browsing::SafeBrowsingService* safe_browsing_service) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Disable QUIC for globally-owned objects.
io_thread->DisableQuic();
safe_browsing_service->DisableQuicOnIOThread();
// Call profile's disable QUIC callback.
disable_quic_callback.Run();
}
} // namespace
NetHttpSessionParamsObserver::NetHttpSessionParamsObserver(
PrefService* prefs,
DisableQuicCallback disable_quic_callback)
: disable_quic_callback_(disable_quic_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(prefs);
base::Closure prefs_callback = base::Bind(
&NetHttpSessionParamsObserver::ApplySettings, base::Unretained(this));
quic_allowed_.Init(prefs::kQuicAllowed, prefs, prefs_callback);
// Apply the initial settings, in case QUIC is disallowed by policy on profile
// initialization time. Note that even if this may not affect the profile
// which is being initialized directly (as its URLRequestContext will not be
// constructed yet), it still applies to globally-owned HttpNetworkSessions
// and to IOThread's HttpNetworkSession Params, which will in turn be used as
// a base for the new profile's URLRequestContext.
ApplySettings();
}
NetHttpSessionParamsObserver::~NetHttpSessionParamsObserver() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
void NetHttpSessionParamsObserver::ApplySettings() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
bool quic_allowed_for_profile = true;
if (quic_allowed_.IsManaged())
quic_allowed_for_profile = *quic_allowed_;
// We only support disabling QUIC.
if (quic_allowed_for_profile)
return;
// Disabling QUIC for a profile also disables QUIC for globally-owned
// HttpNetworkSessions. As a side effect, new Profiles will also have QUIC
// disabled (because they inherit IOThread's HttpNetworkSession Params).
IOThread* io_thread = g_browser_process->io_thread();
safe_browsing::SafeBrowsingService* safe_browsing_service =
g_browser_process->safe_browsing_service();
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&DisableQuicOnIOThread, disable_quic_callback_, io_thread,
base::Unretained(safe_browsing_service)));
}
// static
void NetHttpSessionParamsObserver::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterBooleanPref(prefs::kQuicAllowed, true);
}
// Copyright 2017 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_PROFILES_NET_HTTP_SESSION_PARAMS_OBSERVER_H_
#define CHROME_BROWSER_PROFILES_NET_HTTP_SESSION_PARAMS_OBSERVER_H_
#include "base/callback_forward.h"
#include "base/macros.h"
#include "components/prefs/pref_member.h"
class PrefService;
namespace user_prefs {
class PrefRegistrySyncable;
}
// Monitors network-related preferences for changes and applies them to
// globally owned HttpNetworkSessions.
// Profile-owned HttpNetworkSessions are taken care of by a
// UpdateNetParamsCallback passed to the constructor.
// The supplied PrefService must outlive this NetHttpSessionParamsObserver.
// Must be used only on the UI thread.
class NetHttpSessionParamsObserver {
public:
// Type of callback which will be called when QUIC is disabled. This
// callback will be called on the IO thread.
typedef base::Callback<void()> DisableQuicCallback;
// |prefs| must be non-NULL and |*prefs| must outlive this.
// |update_net_params_callback| will be invoked on the IO thread when an
// observed network parmeter is changed.
NetHttpSessionParamsObserver(PrefService* prefs,
DisableQuicCallback disable_quic_callback);
~NetHttpSessionParamsObserver();
// Register user preferences which NetHttpSessionParamsObserver uses into
// |registry|.
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
private:
// Called on UI thread when an observed net pref changes
void ApplySettings();
BooleanPrefMember quic_allowed_;
DisableQuicCallback disable_quic_callback_;
DISALLOW_COPY_AND_ASSIGN(NetHttpSessionParamsObserver);
};
#endif // CHROME_BROWSER_PROFILES_NET_HTTP_SESSION_PARAMS_OBSERVER_H_
......@@ -46,6 +46,7 @@
#include "chrome/browser/policy/policy_helpers.h"
#include "chrome/browser/predictors/resource_prefetch_predictor.h"
#include "chrome/browser/predictors/resource_prefetch_predictor_factory.h"
#include "chrome/browser/profiles/net_http_session_params_observer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ssl/chrome_expect_ct_reporter.h"
......@@ -469,6 +470,13 @@ void ProfileIOData::InitializeOnUIThread(Profile* profile) {
&allowed_domains_for_apps_,
pref_service);
DCHECK(!net_http_session_params_observer_);
NetHttpSessionParamsObserver::DisableQuicCallback disable_quic_callback =
base::Bind(&ProfileIOData::DisableQuicOnIOThread, base::Unretained(this));
net_http_session_params_observer_ =
base::MakeUnique<NetHttpSessionParamsObserver>(pref_service,
disable_quic_callback);
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
......@@ -919,6 +927,18 @@ std::unique_ptr<net::ClientCertStore> ProfileIOData::CreateClientCertStore() {
#endif
}
void ProfileIOData::DisableQuicOnIOThread() {
// If the URLRequestContext has not been created yet, it will not be updated
// here. Instead, it will inherit its QUIC enablement from IOThread on
// construction, which is fine, as NetHttpSessionParamsObserver also disables
// QUIC there.
if (!main_request_context_storage_ ||
!main_request_context_storage_->http_network_session())
return;
main_request_context_storage_->http_network_session()->DisableQuic();
}
void ProfileIOData::set_data_reduction_proxy_io_data(
std::unique_ptr<data_reduction_proxy::DataReductionProxyIOData>
data_reduction_proxy_io_data) const {
......@@ -1226,6 +1246,7 @@ void ProfileIOData::ShutdownOnUIThread(
if (chrome_http_user_agent_settings_)
chrome_http_user_agent_settings_->CleanupOnUIThread();
incognito_availibility_pref_.Destroy();
net_http_session_params_observer_.reset();
if (!context_getters->empty()) {
if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) {
......
......@@ -44,6 +44,7 @@ class ChromeURLRequestContextGetter;
class ChromeExpectCTReporter;
class HostContentSettingsMap;
class MediaDeviceIDSalt;
class NetHttpSessionParamsObserver;
class ProtocolHandlerRegistry;
class SupervisedUserURLFilter;
......@@ -252,6 +253,9 @@ class ProfileIOData {
// Get platform ClientCertStore. May return nullptr.
std::unique_ptr<net::ClientCertStore> CreateClientCertStore();
// Called on IO thread thread to disable QUIC.
void DisableQuicOnIOThread();
protected:
// A URLRequestContext for media that owns its HTTP factory, to ensure
// it is deleted.
......@@ -535,6 +539,11 @@ class ProfileIOData {
BooleanPrefMember enable_metrics_;
// Observes profile's preference for changes to prefs which affect
// HttpNetworkSession params.
std::unique_ptr<NetHttpSessionParamsObserver>
net_http_session_params_observer_;
// Pointed to by NetworkDelegate.
mutable std::unique_ptr<policy::URLBlacklistManager> url_blacklist_manager_;
mutable std::unique_ptr<policy::PolicyHeaderIOHelper> policy_header_helper_;
......
......@@ -139,6 +139,10 @@ class SafeBrowsingURLRequestContextGetter
// true.
void ServiceShuttingDown();
// Disables QUIC. This should not be necessary anymore when
// http://crbug.com/678653 is implemented.
void DisableQuicOnIOThread();
protected:
~SafeBrowsingURLRequestContextGetter() override;
......@@ -239,6 +243,13 @@ void SafeBrowsingURLRequestContextGetter::ServiceShuttingDown() {
safe_browsing_request_context_.reset();
}
void SafeBrowsingURLRequestContextGetter::DisableQuicOnIOThread() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (http_network_session_)
http_network_session_->DisableQuic();
}
SafeBrowsingURLRequestContextGetter::~SafeBrowsingURLRequestContextGetter() {}
// static
......@@ -393,6 +404,12 @@ SafeBrowsingService::url_request_context() {
return url_request_context_getter_;
}
void SafeBrowsingService::DisableQuicOnIOThread() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
url_request_context_getter_->DisableQuicOnIOThread();
}
const scoped_refptr<SafeBrowsingUIManager>&
SafeBrowsingService::ui_manager() const {
return ui_manager_;
......
......@@ -124,6 +124,11 @@ class SafeBrowsingService : public base::RefCountedThreadSafe<
scoped_refptr<net::URLRequestContextGetter> url_request_context();
// Called on IO thread thread when QUIC should be disabled (e.g. because of
// policy). This should not be necessary anymore when http://crbug.com/678653
// is implemented.
void DisableQuicOnIOThread();
const scoped_refptr<SafeBrowsingUIManager>& ui_manager() const;
// This returns either the v3 or the v4 database manager, depending on
......
......@@ -439,6 +439,9 @@ const char kDnsPrefetchingStartupList[] = "dns_prefetching.startup_list";
const char kDnsPrefetchingHostReferralList[] =
"dns_prefetching.host_referral_list";
// Controls if the QUIC protocol is allowed.
const char kQuicAllowed[] = "net.quic_allowed";
// Prefs for persisting HttpServerProperties.
const char kHttpServerProperties[] = "net.http_server_properties";
......
......@@ -176,6 +176,7 @@ extern const char kPromptForDownload[];
extern const char kAlternateErrorPagesEnabled[];
extern const char kDnsPrefetchingStartupList[];
extern const char kDnsPrefetchingHostReferralList[];
extern const char kQuicAllowed[];
extern const char kHttpServerProperties[];
extern const char kNetworkQualities[];
#if defined(OS_ANDROID)
......
......@@ -319,7 +319,7 @@ void ConnectionFactoryImpl::StartConnection() {
connecting_ = true;
GURL current_endpoint = GetCurrentEndpoint();
recorder_->RecordConnectionInitiated(current_endpoint.host());
RebuildNetworkSessionAuthCache();
UpdateFromHttpNetworkSession();
int status = gcm_network_session_->proxy_service()->ResolveProxy(
current_endpoint,
std::string(),
......@@ -590,12 +590,15 @@ void ConnectionFactoryImpl::CloseSocket() {
socket_handle_.Reset();
}
void ConnectionFactoryImpl::RebuildNetworkSessionAuthCache() {
void ConnectionFactoryImpl::UpdateFromHttpNetworkSession() {
if (!http_network_session_ || !http_network_session_->http_auth_cache())
return;
gcm_network_session_->http_auth_cache()->UpdateAllFrom(
*http_network_session_->http_auth_cache());
if (!http_network_session_->IsQuicEnabled())
gcm_network_session_->DisableQuic();
}
} // namespace gcm
......@@ -132,9 +132,10 @@ class GCM_EXPORT ConnectionFactoryImpl :
// Closes the local socket if one is present, and resets connection handler.
void CloseSocket();
// Updates the GCM Network Session's HttpAuthCache with the HTTP Network
// Session's cache, if available.
void RebuildNetworkSessionAuthCache();
// Updates the GCM Network Session's with current data from HTTP Network
// Session's, if available.
// Specifically, HttpAuthCache and IsQuicEnabled are updated.
void UpdateFromHttpNetworkSession();
// The tracker will maintain a list of all connection attempts with GCM,
// whether they succeeded, and their duration.
......
......@@ -99,19 +99,19 @@ SettingsMap AddDefaultHttp2Settings(SettingsMap http2_settings) {
} // unnamed namespace
HttpNetworkSession::Params::Params()
: client_socket_factory(NULL),
host_resolver(NULL),
cert_verifier(NULL),
channel_id_service(NULL),
transport_security_state(NULL),
cert_transparency_verifier(NULL),
ct_policy_enforcer(NULL),
proxy_service(NULL),
ssl_config_service(NULL),
http_auth_handler_factory(NULL),
net_log(NULL),
host_mapping_rules(NULL),
socket_performance_watcher_factory(NULL),
: client_socket_factory(nullptr),
host_resolver(nullptr),
cert_verifier(nullptr),
channel_id_service(nullptr),
transport_security_state(nullptr),
cert_transparency_verifier(nullptr),
ct_policy_enforcer(nullptr),
proxy_service(nullptr),
ssl_config_service(nullptr),
http_auth_handler_factory(nullptr),
net_log(nullptr),
host_mapping_rules(nullptr),
socket_performance_watcher_factory(nullptr),
ignore_certificate_errors(false),
testing_fixed_http_port(0),
testing_fixed_https_port(0),
......@@ -134,8 +134,8 @@ HttpNetworkSession::Params::Params()
quic_socket_receive_buffer_size(kQuicSocketReceiveBufferSize),
quic_delay_tcp_race(true),
quic_max_server_configs_stored_in_properties(0u),
quic_clock(NULL),
quic_random(NULL),
quic_clock(nullptr),
quic_random(nullptr),
quic_max_packet_length(kDefaultMaxPacketSize),
enable_user_alternate_protocol_ports(false),
quic_crypto_client_stream_factory(
......@@ -153,7 +153,7 @@ HttpNetworkSession::Params::Params()
quic_force_hol_blocking(false),
quic_race_cert_verification(false),
quic_do_not_fragment(false),
proxy_delegate(NULL),
proxy_delegate(nullptr),
enable_token_binding(false),
http_09_on_non_default_ports_enabled(false),
restrict_to_one_preconnect_for_proxies(false) {
......@@ -318,7 +318,7 @@ std::unique_ptr<base::Value> HttpNetworkSession::SpdySessionPoolInfoToValue()
std::unique_ptr<base::Value> HttpNetworkSession::QuicInfoToValue() const {
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
dict->Set("sessions", quic_stream_factory_.QuicStreamFactoryInfoToValue());
dict->SetBoolean("quic_enabled", params_.enable_quic);
dict->SetBoolean("quic_enabled", IsQuicEnabled());
std::unique_ptr<base::ListValue> connection_options(new base::ListValue);
for (QuicTagVector::const_iterator it =
params_.quic_connection_options.begin();
......@@ -384,7 +384,7 @@ bool HttpNetworkSession::IsProtocolEnabled(NextProto protocol) const {
case kProtoHTTP2:
return params_.enable_http2;
case kProtoQUIC:
return params_.enable_quic;
return IsQuicEnabled();
}
NOTREACHED();
return false;
......@@ -438,6 +438,14 @@ void HttpNetworkSession::DumpMemoryStats(
http_network_session_dump->guid());
}
bool HttpNetworkSession::IsQuicEnabled() const {
return params_.enable_quic;
}
void HttpNetworkSession::DisableQuic() {
params_.enable_quic = false;
}
ClientSocketPoolManager* HttpNetworkSession::GetSocketPoolManager(
SocketPoolType pool_type) {
switch (pool_type) {
......
......@@ -298,6 +298,12 @@ class NET_EXPORT HttpNetworkSession
void DumpMemoryStats(base::trace_event::ProcessMemoryDump* pmd,
const std::string& parent_absolute_name) const;
// Evaluates if QUIC is enabled for new streams.
bool IsQuicEnabled() const;
// Disable QUIC for new streams.
void DisableQuic();
private:
friend class HttpNetworkSessionPeer;
......
......@@ -231,7 +231,7 @@ HttpStreamFactoryImpl::Job::Job(Delegate* delegate,
DCHECK(origin_url_.SchemeIs(url::kHttpsScheme));
}
if (IsQuicAlternative()) {
DCHECK(session_->params().enable_quic);
DCHECK(session_->IsQuicEnabled());
using_quic_ = true;
}
}
......@@ -737,7 +737,7 @@ int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
ProxyServer::SCHEME_HTTPS | ProxyServer::SCHEME_SOCKS4 |
ProxyServer::SCHEME_SOCKS5;
if (session_->params().enable_quic)
if (session_->IsQuicEnabled())
supported_proxies |= ProxyServer::SCHEME_QUIC;
proxy_info_.RemoveProxiesWithoutScheme(supported_proxies);
......@@ -768,7 +768,7 @@ int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
}
bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const {
return session_->params().enable_quic &&
return session_->IsQuicEnabled() &&
(base::ContainsKey(session_->params().origins_to_force_quic_on,
HostPortPair()) ||
base::ContainsKey(session_->params().origins_to_force_quic_on,
......@@ -819,11 +819,11 @@ int HttpStreamFactoryImpl::Job::DoInitConnectionImpl() {
if (ShouldForceQuic())
using_quic_ = true;
DCHECK(!using_quic_ || session_->params().enable_quic);
DCHECK(!using_quic_ || session_->IsQuicEnabled());
if (proxy_info_.is_quic()) {
using_quic_ = true;
DCHECK(session_->params().enable_quic);
DCHECK(session_->IsQuicEnabled());
}
if (proxy_info_.is_https() || proxy_info_.is_quic()) {
......
......@@ -956,7 +956,7 @@ HttpStreamFactoryImpl::JobController::GetAlternativeServiceForInternal(
}
quic_all_broken = false;
if (!session_->params().enable_quic)
if (!session_->IsQuicEnabled())
continue;
if (!IsQuicWhitelistedForHost(origin.host()))
......@@ -1056,7 +1056,7 @@ bool HttpStreamFactoryImpl::JobController::
if (alternative_proxy_server->is_quic()) {
// Check that QUIC is enabled globally, and it is not disabled.
if (!session_->params().enable_quic ||
if (!session_->IsQuicEnabled() ||
session_->quic_stream_factory()->IsQuicDisabled()) {
return false;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment