summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoranthonyvd <anthonyvd@chromium.org>2016-03-07 14:03:57 -0800
committerCommit bot <commit-bot@chromium.org>2016-03-07 22:05:33 +0000
commit5b168c11bb7e574c6386f1857d58e5e4cad5e25a (patch)
treeaef7addfa6b6c88f655994975c79180d608dde17
parent7e6264ce0f355de7894f8bbc525b55cd85ccfbb9 (diff)
downloadchromium_src-5b168c11bb7e574c6386f1857d58e5e4cad5e25a.zip
chromium_src-5b168c11bb7e574c6386f1857d58e5e4cad5e25a.tar.gz
chromium_src-5b168c11bb7e574c6386f1857d58e5e4cad5e25a.tar.bz2
Revert of Remove support for Alt-Svc/Alternate Protocol Probability (patchset #7 id:120001 of https://codereview.chromium.org/1699653002/ )
Reason for revert: This appears to have broken the following bot: https://build.chromium.org/p/chromium.mac/builders/iOS_Device_%28ninja%29/builds/43364 Original issue's description: > Remove support forAlt-Svc/Alternate Protocol Probability > > Committed: https://crrev.com/dced4c771d25317d26a0f6e258c7b7f64d4e8eea > Cr-Commit-Position: refs/heads/master@{#379652} TBR=bnc@chromium.org,eroman@chromium.org,mef@chromium.org,rch@chromium.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true Review URL: https://codereview.chromium.org/1773853003 Cr-Commit-Position: refs/heads/master@{#379658}
-rw-r--r--chrome/browser/io_thread.cc43
-rw-r--r--chrome/browser/io_thread_unittest.cc42
-rw-r--r--chrome/browser/resources/net_internals/quic_view.html6
-rw-r--r--chrome/common/chrome_switches.cc6
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--components/cronet/android/cronet_url_request_context_adapter.cc6
-rw-r--r--components/cronet/android/url_request_context_adapter.cc6
-rw-r--r--ios/chrome/browser/ios_chrome_io_thread.h6
-rw-r--r--ios/chrome/browser/ios_chrome_io_thread.mm30
-rw-r--r--ios/crnet/CrNet.h23
-rw-r--r--ios/crnet/CrNet.mm7
-rw-r--r--ios/crnet/crnet_environment.h7
-rw-r--r--ios/crnet/crnet_environment.mm2
-rw-r--r--net/http/http_network_session.cc5
-rw-r--r--net/http/http_network_session.h3
-rw-r--r--net/http/http_network_transaction_unittest.cc41
-rw-r--r--net/http/http_server_properties.cc9
-rw-r--r--net/http/http_server_properties.h20
-rw-r--r--net/http/http_server_properties_impl.cc36
-rw-r--r--net/http/http_server_properties_impl.h4
-rw-r--r--net/http/http_server_properties_impl_unittest.cc188
-rw-r--r--net/http/http_server_properties_manager.cc23
-rw-r--r--net/http/http_server_properties_manager.h2
-rw-r--r--net/http/http_server_properties_manager_unittest.cc49
-rw-r--r--net/http/http_stream_factory.cc21
-rw-r--r--net/http/http_stream_factory_impl_unittest.cc6
-rw-r--r--net/quic/quic_network_transaction_unittest.cc172
-rw-r--r--net/quic/quic_stream_factory_test.cc4
-rw-r--r--net/spdy/spdy_network_transaction_unittest.cc2
29 files changed, 649 insertions, 121 deletions
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index e1102549..5d4e3b3 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -1102,6 +1102,8 @@ void IOThread::InitializeNetworkSessionParamsFromGlobals(
&params->parse_alternative_services);
globals.enable_alternative_service_with_different_host.CopyToIfSet(
&params->enable_alternative_service_with_different_host);
+ globals.alternative_service_probability_threshold.CopyToIfSet(
+ &params->alternative_service_probability_threshold);
globals.enable_npn.CopyToIfSet(&params->enable_npn);
@@ -1328,6 +1330,14 @@ void IOThread::ConfigureQuicGlobals(
globals->quic_supported_versions.set(supported_versions);
}
+ double threshold = GetAlternativeProtocolProbabilityThreshold(
+ command_line, quic_trial_params);
+ if (threshold >=0 && threshold <= 1) {
+ globals->alternative_service_probability_threshold.set(threshold);
+ globals->http_server_properties->SetAlternativeServiceProbabilityThreshold(
+ threshold);
+ }
+
if (command_line.HasSwitch(switches::kOriginToForceQuicOn)) {
net::HostPortPair quic_origin =
net::HostPortPair::FromString(
@@ -1405,6 +1415,39 @@ net::QuicTagVector IOThread::GetQuicConnectionOptions(
return net::QuicUtils::ParseQuicConnectionOptions(it->second);
}
+double IOThread::GetAlternativeProtocolProbabilityThreshold(
+ const base::CommandLine& command_line,
+ const VariationParameters& quic_trial_params) {
+ double value;
+ if (command_line.HasSwitch(
+ switches::kAlternativeServiceProbabilityThreshold)) {
+ if (base::StringToDouble(
+ command_line.GetSwitchValueASCII(
+ switches::kAlternativeServiceProbabilityThreshold),
+ &value)) {
+ return value;
+ }
+ }
+ if (command_line.HasSwitch(switches::kEnableQuic)) {
+ return 0;
+ }
+ // TODO(bnc): Remove when new parameter name rolls out and server
+ // configuration is changed.
+ if (base::StringToDouble(
+ GetVariationParam(quic_trial_params,
+ "alternate_protocol_probability_threshold"),
+ &value)) {
+ return value;
+ }
+ if (base::StringToDouble(
+ GetVariationParam(quic_trial_params,
+ "alternative_service_probability_threshold"),
+ &value)) {
+ return value;
+ }
+ return -1;
+}
+
bool IOThread::ShouldQuicAlwaysRequireHandshakeConfirmation(
const VariationParameters& quic_trial_params) {
return base::LowerCaseEqualsASCII(
diff --git a/chrome/browser/io_thread_unittest.cc b/chrome/browser/io_thread_unittest.cc
index abf93c2..5383823 100644
--- a/chrome/browser/io_thread_unittest.cc
+++ b/chrome/browser/io_thread_unittest.cc
@@ -235,6 +235,7 @@ TEST_F(IOThreadTest, EnableQuicFromFieldTrialGroup) {
EXPECT_FALSE(params.disable_quic_on_timeout_with_open_streams);
EXPECT_TRUE(params.enable_quic_for_proxies);
EXPECT_EQ(1350u, params.quic_max_packet_length);
+ EXPECT_EQ(1.0, params.alternative_service_probability_threshold);
EXPECT_EQ(default_params.quic_supported_versions,
params.quic_supported_versions);
EXPECT_EQ(net::QuicTagVector(), params.quic_connection_options);
@@ -603,6 +604,47 @@ TEST_F(IOThreadTest, QuicDelayTcpConnection) {
EXPECT_TRUE(params.quic_delay_tcp_race);
}
+TEST_F(IOThreadTest, AlternativeServiceProbabilityThresholdFromFlag) {
+ command_line_.AppendSwitchASCII("alternative-service-probability-threshold",
+ "0.5");
+
+ ConfigureQuicGlobals();
+ net::HttpNetworkSession::Params params;
+ InitializeNetworkSessionParams(&params);
+ EXPECT_EQ(.5, params.alternative_service_probability_threshold);
+}
+
+TEST_F(IOThreadTest, AlternativeServiceProbabilityThresholdFromEnableQuicFlag) {
+ command_line_.AppendSwitch("enable-quic");
+
+ ConfigureQuicGlobals();
+ net::HttpNetworkSession::Params params;
+ InitializeNetworkSessionParams(&params);
+ EXPECT_EQ(0, params.alternative_service_probability_threshold);
+}
+
+// TODO(bnc): Remove when new parameter name rolls out and server configuration
+// is changed.
+TEST_F(IOThreadTest, AlternativeServiceProbabilityThresholdFromOldParams) {
+ field_trial_group_ = "Enabled";
+ field_trial_params_["alternate_protocol_probability_threshold"] = ".5";
+
+ ConfigureQuicGlobals();
+ net::HttpNetworkSession::Params params;
+ InitializeNetworkSessionParams(&params);
+ EXPECT_EQ(.5, params.alternative_service_probability_threshold);
+}
+
+TEST_F(IOThreadTest, AlternativeServiceProbabilityThresholdFromParams) {
+ field_trial_group_ = "Enabled";
+ field_trial_params_["alternative_service_probability_threshold"] = ".5";
+
+ ConfigureQuicGlobals();
+ net::HttpNetworkSession::Params params;
+ InitializeNetworkSessionParams(&params);
+ EXPECT_EQ(.5, params.alternative_service_probability_threshold);
+}
+
TEST_F(IOThreadTest, QuicWhitelistFromCommandLinet) {
command_line_.AppendSwitch("enable-quic");
command_line_.AppendSwitchASCII("quic-host-whitelist",
diff --git a/chrome/browser/resources/net_internals/quic_view.html b/chrome/browser/resources/net_internals/quic_view.html
index 399140c..df6d943 100644
--- a/chrome/browser/resources/net_internals/quic_view.html
+++ b/chrome/browser/resources/net_internals/quic_view.html
@@ -1,6 +1,12 @@
<div id=quic-view-tab-content class=content-box>
<ul style='margin-top:0'>
<li>QUIC Enabled: <span jscontent="!!quic_enabled"></span></li>
+ <!-- "alternative_service_probability_threshold" is used since release 44,
+ see https://crrev.com/1091283007.
+ "alternate_protocol_probability_threshold" is here to support importing
+ netlog json files from earlier browsers.
+ TODO(bnc): Deprecate around 2016 January. --!>
+ <li>Alternative Service Probability Threshold: <span jscontent="$this.alternative_service_probability_threshold || $this.alternate_protocol_probability_threshold"></span></li>
<li>Origin To Force QUIC On: <span jscontent="origin_to_force_quic_on"></span></li>
<li>Connection options: <span jscontent="connection_options"></span></li>
<li>Consistent Port Selection Enabled: <span jscontent="!!enable_quic_port_selection"></span></li>
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index d32a32f3..b1be5b9 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -66,6 +66,12 @@ const char kAllowOutdatedPlugins[] = "allow-outdated-plugins";
// URLs. This provides an override to get the old insecure behavior.
const char kAllowRunningInsecureContent[] = "allow-running-insecure-content";
+// Specifies the probability threshold for alternative services: an advertised
+// alternative service will only be honored if the advertised probability is
+// greater than or equal to this threshold.
+const char kAlternativeServiceProbabilityThreshold[] =
+ "alternative-service-probability-threshold";
+
// Prevents Chrome from requiring authorization to run certain widely installed
// but less commonly used plugins.
const char kAlwaysAuthorizePlugins[] = "always-authorize-plugins";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 7aff159..c3fb63f 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -31,6 +31,7 @@ extern const char kAllowHttpScreenCapture[];
extern const char kAllowInsecureLocalhost[];
extern const char kAllowOutdatedPlugins[];
extern const char kAllowRunningInsecureContent[];
+extern const char kAlternativeServiceProbabilityThreshold[];
extern const char kAlwaysAuthorizePlugins[];
extern const char kAppId[];
extern const char kApp[];
diff --git a/components/cronet/android/cronet_url_request_context_adapter.cc b/components/cronet/android/cronet_url_request_context_adapter.cc
index b02bd14..e42ed20 100644
--- a/components/cronet/android/cronet_url_request_context_adapter.cc
+++ b/components/cronet/android/cronet_url_request_context_adapter.cc
@@ -484,7 +484,10 @@ void CronetURLRequestContextAdapter::InitializeOnNetworkThread(
}
}
+ // Currently (circa M39) enabling QUIC requires setting probability threshold.
if (config->enable_quic) {
+ context_->http_server_properties()
+ ->SetAlternativeServiceProbabilityThreshold(0.0f);
for (auto hint = config->quic_hints.begin();
hint != config->quic_hints.end(); ++hint) {
const URLRequestContextConfig::QuicHint& quic_hint = **hint;
@@ -521,7 +524,8 @@ void CronetURLRequestContextAdapter::InitializeOnNetworkThread(
net::AlternateProtocol::QUIC, "",
static_cast<uint16_t>(quic_hint.alternate_port));
context_->http_server_properties()->SetAlternativeService(
- quic_hint_host_port_pair, alternative_service, base::Time::Max());
+ quic_hint_host_port_pair, alternative_service, 1.0f,
+ base::Time::Max());
}
}
diff --git a/components/cronet/android/url_request_context_adapter.cc b/components/cronet/android/url_request_context_adapter.cc
index 1a87d68..0d6179a 100644
--- a/components/cronet/android/url_request_context_adapter.cc
+++ b/components/cronet/android/url_request_context_adapter.cc
@@ -164,7 +164,10 @@ void URLRequestContextAdapter::InitRequestContextOnNetworkThread() {
new net::SdchOwner(context_->sdch_manager(), context_.get()));
}
+ // Currently (circa M39) enabling QUIC requires setting probability threshold.
if (config_->enable_quic) {
+ context_->http_server_properties()
+ ->SetAlternativeServiceProbabilityThreshold(0.0f);
for (size_t hint = 0; hint < config_->quic_hints.size(); ++hint) {
const URLRequestContextConfig::QuicHint& quic_hint =
*config_->quic_hints[hint];
@@ -201,7 +204,8 @@ void URLRequestContextAdapter::InitRequestContextOnNetworkThread() {
net::AlternateProtocol::QUIC, "",
static_cast<uint16_t>(quic_hint.alternate_port));
context_->http_server_properties()->SetAlternativeService(
- quic_hint_host_port_pair, alternative_service, base::Time::Max());
+ quic_hint_host_port_pair, alternative_service, 1.0f,
+ base::Time::Max());
}
}
load_disable_cache_ = config_->load_disable_cache;
diff --git a/ios/chrome/browser/ios_chrome_io_thread.h b/ios/chrome/browser/ios_chrome_io_thread.h
index 17c7faa..f300a7f 100644
--- a/ios/chrome/browser/ios_chrome_io_thread.h
+++ b/ios/chrome/browser/ios_chrome_io_thread.h
@@ -138,6 +138,7 @@ class IOSChromeIOThread : public web::WebThreadDelegate {
Optional<bool> enable_http2;
Optional<bool> parse_alternative_services;
Optional<bool> enable_alternative_service_with_different_host;
+ Optional<double> alternative_service_probability_threshold;
Optional<bool> enable_npn;
@@ -349,6 +350,11 @@ class IOSChromeIOThread : public web::WebThreadDelegate {
static net::QuicTagVector GetQuicConnectionOptions(
const VariationParameters& quic_trial_params);
+ // Returns the alternative service probability threshold specified by
+ // any flags in |quic_trial_params|.
+ static double GetAlternativeProtocolProbabilityThreshold(
+ const VariationParameters& quic_trial_params);
+
static net::URLRequestContext* ConstructSystemRequestContext(
Globals* globals,
net::NetLog* net_log);
diff --git a/ios/chrome/browser/ios_chrome_io_thread.mm b/ios/chrome/browser/ios_chrome_io_thread.mm
index 0fbdab0..ef492dc 100644
--- a/ios/chrome/browser/ios_chrome_io_thread.mm
+++ b/ios/chrome/browser/ios_chrome_io_thread.mm
@@ -634,6 +634,8 @@ void IOSChromeIOThread::InitializeNetworkSessionParamsFromGlobals(
&params->parse_alternative_services);
globals.enable_alternative_service_with_different_host.CopyToIfSet(
&params->enable_alternative_service_with_different_host);
+ globals.alternative_service_probability_threshold.CopyToIfSet(
+ &params->alternative_service_probability_threshold);
globals.enable_npn.CopyToIfSet(&params->enable_npn);
@@ -804,6 +806,14 @@ void IOSChromeIOThread::ConfigureQuicGlobals(
supported_versions.push_back(version);
globals->quic_supported_versions.set(supported_versions);
}
+
+ double threshold =
+ GetAlternativeProtocolProbabilityThreshold(quic_trial_params);
+ if (threshold >= 0 && threshold <= 1) {
+ globals->alternative_service_probability_threshold.set(threshold);
+ globals->http_server_properties->SetAlternativeServiceProbabilityThreshold(
+ threshold);
+ }
}
bool IOSChromeIOThread::ShouldEnableQuic(base::StringPiece quic_trial_group) {
@@ -832,6 +842,26 @@ net::QuicTagVector IOSChromeIOThread::GetQuicConnectionOptions(
return net::QuicUtils::ParseQuicConnectionOptions(it->second);
}
+double IOSChromeIOThread::GetAlternativeProtocolProbabilityThreshold(
+ const VariationParameters& quic_trial_params) {
+ double value;
+ // TODO(bnc): Remove when new parameter name rolls out and server
+ // configuration is changed.
+ if (base::StringToDouble(
+ GetVariationParam(quic_trial_params,
+ "alternate_protocol_probability_threshold"),
+ &value)) {
+ return value;
+ }
+ if (base::StringToDouble(
+ GetVariationParam(quic_trial_params,
+ "alternative_service_probability_threshold"),
+ &value)) {
+ return value;
+ }
+ return -1;
+}
+
bool IOSChromeIOThread::ShouldQuicAlwaysRequireHandshakeConfirmation(
const VariationParameters& quic_trial_params) {
return base::LowerCaseEqualsASCII(
diff --git a/ios/crnet/CrNet.h b/ios/crnet/CrNet.h
index 043ee6e..2fbb48f2 100644
--- a/ios/crnet/CrNet.h
+++ b/ios/crnet/CrNet.h
@@ -35,6 +35,29 @@ typedef void(^ClearCacheCallback)(int errorCode);
+ (void)setSDCHEnabled:(BOOL)sdchEnabled
withPrefStore:(NSString*)filename;
+// Set the alternate protocol threshold. Servers announce alternate protocols
+// with a probability value; any alternate protocol whose probability value is
+// greater than this value will be used, so |alternateProtocolThreshold| == 0
+// implies any announced alternate protocol will be used, and
+// |alternateProtocolThreshold| == 1 implies no alternate protocol will ever be
+// used. Note that individual alternate protocols must also be individually
+// enabled to be considered; currently the only alternate protocol is QUIC (SPDY
+// is not controlled by this mechanism).
+//
+// For example, imagine your service has two frontends a.service.com and
+// b.service.com, and you would like to divide your users into three classes:
+// Users who use QUIC for both a and b
+// Users who use QUIC for a but not b
+// Users who use QUIC for neither a nor b
+// You can achieve that effect with:
+// a.service.com advertises QUIC with p=0.67
+// b.service.com advertises QUIC with p=0.33
+// alternateProtocolThreshold set to a uniform random number in [0,1]
+// Now equal proportions of users will fall into the three experimental groups.
+//
+// The default for this value is 1.0, i.e. all alternate protocols disabled.
++ (void)setAlternateProtocolThreshold:(double)alternateProtocolThreshold;
+
// |userAgent| is expected to be of the form Product/Version.
// Example: Foo/3.0.0.0
//
diff --git a/ios/crnet/CrNet.mm b/ios/crnet/CrNet.mm
index 0347344..2c91094 100644
--- a/ios/crnet/CrNet.mm
+++ b/ios/crnet/CrNet.mm
@@ -16,6 +16,7 @@ static BOOL g_quic_enabled = NO;
static BOOL g_sdch_enabled = NO;
static NSString* g_user_agent = nil;
static NSString* g_sdch_pref_store_filename = nil;
+static double g_alternate_protocol_threshold = 1.0;
static RequestFilterBlock g_request_filter_block = nil;
@implementation CrNet
@@ -38,6 +39,10 @@ static RequestFilterBlock g_request_filter_block = nil;
g_user_agent = userAgent;
}
++ (void)setAlternateProtocolThreshold:(double)alternateProtocolThreshold {
+ g_alternate_protocol_threshold = alternateProtocolThreshold;
+}
+
+ (void)installInternal {
CrNetEnvironment::Initialize();
std::string partial_user_agent = base::SysNSStringToUTF8(g_user_agent);
@@ -50,6 +55,8 @@ static RequestFilterBlock g_request_filter_block = nil;
std::string filename = base::SysNSStringToUTF8(g_sdch_pref_store_filename);
g_chrome_net->set_sdch_pref_store_filename(filename);
}
+ g_chrome_net->set_alternate_protocol_threshold(
+ g_alternate_protocol_threshold);
g_chrome_net->Install();
g_chrome_net->SetHTTPProtocolHandlerRegistered(true);
diff --git a/ios/crnet/crnet_environment.h b/ios/crnet/crnet_environment.h
index 5a698897..a0b49c1 100644
--- a/ios/crnet/crnet_environment.h
+++ b/ios/crnet/crnet_environment.h
@@ -93,10 +93,16 @@ class CrNetEnvironment {
void set_sdch_pref_store_filename(const std::string& pref_store) {
sdch_pref_store_filename_ = pref_store;
}
+ void set_alternate_protocol_threshold(double threshold) {
+ alternate_protocol_threshold_ = threshold;
+ }
bool spdy_enabled() const { return spdy_enabled_; }
bool quic_enabled() const { return quic_enabled_; }
bool sdch_enabled() const { return sdch_enabled_; }
+ double alternate_protocol_threshold() const {
+ return alternate_protocol_threshold_;
+ }
// Clears the network stack's disk cache.
void ClearCache(ClearCacheCallback callback);
@@ -136,6 +142,7 @@ class CrNetEnvironment {
bool quic_enabled_;
bool sdch_enabled_;
std::string sdch_pref_store_filename_;
+ double alternate_protocol_threshold_;
static CrNetEnvironment* chrome_net_;
scoped_ptr<base::Thread> network_io_thread_;
diff --git a/ios/crnet/crnet_environment.mm b/ios/crnet/crnet_environment.mm
index 4b75a5a..128d76b 100644
--- a/ios/crnet/crnet_environment.mm
+++ b/ios/crnet/crnet_environment.mm
@@ -445,6 +445,8 @@ void CrNetEnvironment::InitializeOnNetworkThread() {
params.enable_http2 = spdy_enabled();
params.parse_alternative_services = false;
params.enable_quic = quic_enabled();
+ params.alternative_service_probability_threshold =
+ alternate_protocol_threshold_;
if (!params.channel_id_service) {
// The main context may not have a ChannelIDService, since it is lazily
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index c6ad481..35c06cb 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -98,6 +98,7 @@ HttpNetworkSession::Params::Params()
time_func(&base::TimeTicks::Now),
parse_alternative_services(false),
enable_alternative_service_with_different_host(false),
+ alternative_service_probability_threshold(1),
enable_npn(true),
enable_brotli(false),
enable_quic(false),
@@ -243,6 +244,8 @@ HttpNetworkSession::HttpNetworkSession(const Params& params)
next_protos_.push_back(kProtoHTTP11);
+ http_server_properties_->SetAlternativeServiceProbabilityThreshold(
+ params.alternative_service_probability_threshold);
http_server_properties_->SetMaxServerConfigsStoredInProperties(
params.quic_max_server_configs_stored_in_properties);
}
@@ -318,6 +321,8 @@ scoped_ptr<base::Value> HttpNetworkSession::QuicInfoToValue() const {
dict->Set("connection_options", std::move(connection_options));
dict->SetString("origin_to_force_quic_on",
params_.origin_to_force_quic_on.ToString());
+ dict->SetDouble("alternative_service_probability_threshold",
+ params_.alternative_service_probability_threshold);
dict->SetDouble("load_server_info_timeout_srtt_multiplier",
params_.quic_load_server_info_timeout_srtt_multiplier);
dict->SetBoolean("enable_connection_racing",
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index 3648a7a..30cec77 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -101,6 +101,9 @@ class NET_EXPORT HttpNetworkSession
// Whether to enable Alt-Svc entries with hostname different than that of
// the origin.
bool enable_alternative_service_with_different_host;
+ // Only honor alternative service entries which have a higher probability
+ // than this value.
+ double alternative_service_probability_threshold;
// Enables NPN support. Note that ALPN is always enabled.
bool enable_npn;
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 04b24d3..bc7f7b3 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -8809,7 +8809,8 @@ scoped_ptr<HttpNetworkSession> SetupSessionForGroupNameTests(
AlternateProtocolFromNextProto(next_proto), "", 443);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
- HostPortPair("host.with.alternate", 80), alternative_service, expiration);
+ HostPortPair("host.with.alternate", 80), alternative_service, 1.0,
+ expiration);
return session;
}
@@ -9736,8 +9737,8 @@ TEST_P(HttpNetworkTransactionTest, ClearAlternativeServices) {
HostPortPair http_host_port_pair("www.example.org", 80);
AlternativeService alternative_service(QUIC, "", 80);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
- http_server_properties.SetAlternativeService(http_host_port_pair,
- alternative_service, expiration);
+ http_server_properties.SetAlternativeService(
+ http_host_port_pair, alternative_service, 1.0, expiration);
AlternativeServiceVector alternative_service_vector =
http_server_properties.GetAlternativeServices(http_host_port_pair);
EXPECT_EQ(1u, alternative_service_vector.size());
@@ -9998,8 +9999,8 @@ TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
*session->http_server_properties();
AlternativeService alternative_service(QUIC, "", 80);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
- http_server_properties.SetAlternativeService(http_host_port_pair,
- alternative_service, expiration);
+ http_server_properties.SetAlternativeService(
+ http_host_port_pair, alternative_service, 1.0, expiration);
AlternativeServiceVector alternative_service_vector =
http_server_properties.GetAlternativeServices(http_host_port_pair);
@@ -10129,7 +10130,7 @@ TEST_P(HttpNetworkTransactionTest, DisableAlternativeServiceToDifferentHost) {
80);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
- HostPortPair::FromURL(request.url), alternative_service, expiration);
+ HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -10183,7 +10184,7 @@ TEST_P(HttpNetworkTransactionTest, IdentifyQuicBroken) {
AlternativeService alternative_service(QUIC, alternative);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(origin, alternative_service,
- expiration);
+ 1.0, expiration);
// Mark the QUIC alternative service as broken.
http_server_properties->MarkAlternativeServiceBroken(alternative_service);
@@ -10247,11 +10248,11 @@ TEST_P(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
AlternativeService alternative_service1(QUIC, alternative1);
- AlternativeServiceInfo alternative_service_info1(alternative_service1,
+ AlternativeServiceInfo alternative_service_info1(alternative_service1, 1.0,
expiration);
alternative_service_info_vector.push_back(alternative_service_info1);
AlternativeService alternative_service2(QUIC, alternative2);
- AlternativeServiceInfo alternative_service_info2(alternative_service2,
+ AlternativeServiceInfo alternative_service_info2(alternative_service2, 1.0,
expiration);
alternative_service_info_vector.push_back(alternative_service_info2);
@@ -10315,7 +10316,7 @@ TEST_P(HttpNetworkTransactionTest,
666); // Port is ignored by MockConnect anyway.
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
- host_port_pair, alternative_service, expiration);
+ host_port_pair, alternative_service, 1.0, expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -10381,7 +10382,7 @@ TEST_P(HttpNetworkTransactionTest,
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
HostPortPair::FromURL(restricted_port_request.url), alternative_service,
- expiration);
+ 1.0, expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -10434,7 +10435,7 @@ TEST_P(HttpNetworkTransactionTest,
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
HostPortPair::FromURL(restricted_port_request.url), alternative_service,
- expiration);
+ 1.0, expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -10486,7 +10487,7 @@ TEST_P(HttpNetworkTransactionTest,
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
HostPortPair::FromURL(restricted_port_request.url), alternative_service,
- expiration);
+ 1.0, expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -10539,7 +10540,7 @@ TEST_P(HttpNetworkTransactionTest,
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
- expiration);
+ 1.0, expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -10591,7 +10592,7 @@ TEST_P(HttpNetworkTransactionTest,
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
- expiration);
+ 1.0, expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -10637,7 +10638,7 @@ TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
kUnsafePort);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
- HostPortPair::FromURL(request.url), alternative_service, expiration);
+ HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -13369,7 +13370,7 @@ class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
AlternateProtocolFromNextProto(GetProtocol()), alternative);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(origin, alternative_service,
- expiration);
+ 1.0, expiration);
// First request to alternative.
if (pooling) {
@@ -13474,7 +13475,7 @@ TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
AlternateProtocolFromNextProto(GetProtocol()), alternative);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(origin, alternative_service,
- expiration);
+ 1.0, expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -13548,7 +13549,7 @@ TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
AlternateProtocolFromNextProto(GetProtocol()), alternative);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(origin, alternative_service,
- expiration);
+ 1.0, expiration);
HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
HttpRequestInfo request1;
@@ -13658,7 +13659,7 @@ TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
AlternateProtocolFromNextProto(GetProtocol()), alternative);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(origin, alternative_service,
- expiration);
+ 1.0, expiration);
// First transaction to alternative to open an HTTP/1.1 socket.
scoped_ptr<HttpTransaction> trans1(
diff --git a/net/http/http_server_properties.cc b/net/http/http_server_properties.cc
index 850418d..fc6281e 100644
--- a/net/http/http_server_properties.cc
+++ b/net/http/http_server_properties.cc
@@ -97,10 +97,11 @@ std::string AlternativeService::ToString() const {
std::string AlternativeServiceInfo::ToString() const {
base::Time::Exploded exploded;
expiration.LocalExplode(&exploded);
- return base::StringPrintf(
- "%s, expires %04d-%02d-%02d %02d:%02d:%02d",
- alternative_service.ToString().c_str(), exploded.year, exploded.month,
- exploded.day_of_month, exploded.hour, exploded.minute, exploded.second);
+ return base::StringPrintf("%s, p=%f, expires %04d-%02d-%02d %02d:%02d:%02d",
+ alternative_service.ToString().c_str(), probability,
+ exploded.year, exploded.month,
+ exploded.day_of_month, exploded.hour,
+ exploded.minute, exploded.second);
}
// static
diff --git a/net/http/http_server_properties.h b/net/http/http_server_properties.h
index 44224db..4b1f92e 100644
--- a/net/http/http_server_properties.h
+++ b/net/http/http_server_properties.h
@@ -138,18 +138,22 @@ struct NET_EXPORT AlternativeService {
};
struct NET_EXPORT AlternativeServiceInfo {
- AlternativeServiceInfo() : alternative_service() {}
+ AlternativeServiceInfo() : alternative_service(), probability(0.0) {}
AlternativeServiceInfo(const AlternativeService& alternative_service,
+ double probability,
base::Time expiration)
: alternative_service(alternative_service),
+ probability(probability),
expiration(expiration) {}
AlternativeServiceInfo(AlternateProtocol protocol,
const std::string& host,
uint16_t port,
+ double probability,
base::Time expiration)
: alternative_service(protocol, host, port),
+ probability(probability),
expiration(expiration) {}
AlternativeServiceInfo(
@@ -159,7 +163,7 @@ struct NET_EXPORT AlternativeServiceInfo {
bool operator==(const AlternativeServiceInfo& other) const {
return alternative_service == other.alternative_service &&
- expiration == other.expiration;
+ probability == other.probability && expiration == other.expiration;
}
bool operator!=(const AlternativeServiceInfo& other) const {
@@ -169,6 +173,7 @@ struct NET_EXPORT AlternativeServiceInfo {
std::string ToString() const;
AlternativeService alternative_service;
+ double probability;
base::Time expiration;
};
@@ -260,7 +265,8 @@ class NET_EXPORT HttpServerProperties {
virtual void MaybeForceHTTP11(const HostPortPair& server,
SSLConfig* ssl_config) = 0;
- // Return all alternative services for |origin|, including broken ones.
+ // Return all alternative services for |origin| with probability greater than
+ // or equal to the threshold, including broken ones.
// Returned alternative services never have empty hostnames.
virtual AlternativeServiceVector GetAlternativeServices(
const HostPortPair& origin) = 0;
@@ -272,6 +278,7 @@ class NET_EXPORT HttpServerProperties {
virtual bool SetAlternativeService(
const HostPortPair& origin,
const AlternativeService& alternative_service,
+ double alternative_probability,
base::Time expiration) = 0;
// Set alternative services for |origin|. Previous alternative services for
@@ -318,6 +325,13 @@ class NET_EXPORT HttpServerProperties {
// Empty alternative service hostnames will be printed as such.
virtual scoped_ptr<base::Value> GetAlternativeServiceInfoAsValue() const = 0;
+ // Sets the threshold to be used when evaluating alternative service
+ // advertisments. Only advertisements with a probability greater than or equal
+ // to |threshold| will be honored. |threshold| must be between 0.0 and 1.0
+ // inclusive. Hence, a threshold of 0.0 implies that all advertisements will
+ // be honored.
+ virtual void SetAlternativeServiceProbabilityThreshold(double threshold) = 0;
+
// Gets a reference to the SettingsMap stored for a host.
// If no settings are stored, returns an empty SettingsMap.
virtual const SettingsMap& GetSpdySettings(
diff --git a/net/http/http_server_properties_impl.cc b/net/http/http_server_properties_impl.cc
index a0a6bfe..ab2088f 100644
--- a/net/http/http_server_properties_impl.cc
+++ b/net/http/http_server_properties_impl.cc
@@ -32,6 +32,7 @@ HttpServerPropertiesImpl::HttpServerPropertiesImpl()
alternative_service_map_(AlternativeServiceMap::NO_AUTO_EVICT),
spdy_settings_map_(SpdySettingsMap::NO_AUTO_EVICT),
server_network_stats_map_(ServerNetworkStatsMap::NO_AUTO_EVICT),
+ alternative_service_probability_threshold_(1.0),
quic_server_info_map_(QuicServerInfoMap::NO_AUTO_EVICT),
max_server_configs_stored_in_properties_(kMaxQuicServersToPersist),
weak_ptr_factory_(this) {
@@ -322,8 +323,9 @@ std::string HttpServerPropertiesImpl::GetCanonicalSuffix(
AlternativeServiceVector HttpServerPropertiesImpl::GetAlternativeServices(
const HostPortPair& origin) {
- // Copy valid alternative services into |valid_alternative_services|.
- AlternativeServiceVector valid_alternative_services;
+ // Copy alternative services with probability greater than or equal to the
+ // threshold into |alternative_services_above_threshold|.
+ AlternativeServiceVector alternative_services_above_threshold;
const base::Time now = base::Time::Now();
AlternativeServiceMap::iterator map_it = alternative_service_map_.Get(origin);
if (map_it != alternative_service_map_.end()) {
@@ -333,6 +335,11 @@ AlternativeServiceVector HttpServerPropertiesImpl::GetAlternativeServices(
it = map_it->second.erase(it);
continue;
}
+ if (it->probability == 0 ||
+ it->probability < alternative_service_probability_threshold_) {
+ ++it;
+ continue;
+ }
AlternativeService alternative_service(it->alternative_service);
if (alternative_service.host.empty()) {
alternative_service.host = origin.host();
@@ -346,13 +353,13 @@ AlternativeServiceVector HttpServerPropertiesImpl::GetAlternativeServices(
++it;
continue;
}
- valid_alternative_services.push_back(alternative_service);
+ alternative_services_above_threshold.push_back(alternative_service);
++it;
}
if (map_it->second.empty()) {
alternative_service_map_.Erase(map_it);
}
- return valid_alternative_services;
+ return alternative_services_above_threshold;
}
CanonicalHostMap::const_iterator canonical = GetCanonicalHost(origin);
@@ -369,6 +376,10 @@ AlternativeServiceVector HttpServerPropertiesImpl::GetAlternativeServices(
it = map_it->second.erase(it);
continue;
}
+ if (it->probability < alternative_service_probability_threshold_) {
+ ++it;
+ continue;
+ }
AlternativeService alternative_service(it->alternative_service);
if (alternative_service.host.empty()) {
alternative_service.host = canonical->second.host();
@@ -381,23 +392,25 @@ AlternativeServiceVector HttpServerPropertiesImpl::GetAlternativeServices(
++it;
continue;
}
- valid_alternative_services.push_back(alternative_service);
+ alternative_services_above_threshold.push_back(alternative_service);
++it;
}
if (map_it->second.empty()) {
alternative_service_map_.Erase(map_it);
}
- return valid_alternative_services;
+ return alternative_services_above_threshold;
}
bool HttpServerPropertiesImpl::SetAlternativeService(
const HostPortPair& origin,
const AlternativeService& alternative_service,
+ double alternative_probability,
base::Time expiration) {
return SetAlternativeServices(
- origin,
- AlternativeServiceInfoVector(
- /*size=*/1, AlternativeServiceInfo(alternative_service, expiration)));
+ origin, AlternativeServiceInfoVector(
+ /*size=*/1,
+ AlternativeServiceInfo(alternative_service,
+ alternative_probability, expiration)));
}
bool HttpServerPropertiesImpl::SetAlternativeServices(
@@ -684,6 +697,11 @@ void HttpServerPropertiesImpl::SetMaxServerConfigsStoredInProperties(
quic_server_info_map_.Swap(temp_map);
}
+void HttpServerPropertiesImpl::SetAlternativeServiceProbabilityThreshold(
+ double threshold) {
+ alternative_service_probability_threshold_ = threshold;
+}
+
AlternativeServiceMap::const_iterator
HttpServerPropertiesImpl::GetAlternateProtocolIterator(
const HostPortPair& server) {
diff --git a/net/http/http_server_properties_impl.h b/net/http/http_server_properties_impl.h
index d668673..e42594a 100644
--- a/net/http/http_server_properties_impl.h
+++ b/net/http/http_server_properties_impl.h
@@ -90,6 +90,7 @@ class NET_EXPORT HttpServerPropertiesImpl
const HostPortPair& origin) override;
bool SetAlternativeService(const HostPortPair& origin,
const AlternativeService& alternative_service,
+ double alternative_probability,
base::Time expiration) override;
bool SetAlternativeServices(const HostPortPair& origin,
const AlternativeServiceInfoVector&
@@ -107,6 +108,7 @@ class NET_EXPORT HttpServerPropertiesImpl
void ClearAlternativeServices(const HostPortPair& origin) override;
const AlternativeServiceMap& alternative_service_map() const override;
scoped_ptr<base::Value> GetAlternativeServiceInfoAsValue() const override;
+ void SetAlternativeServiceProbabilityThreshold(double threshold) override;
const SettingsMap& GetSpdySettings(
const HostPortPair& host_port_pair) override;
bool SetSpdySetting(const HostPortPair& host_port_pair,
@@ -182,6 +184,8 @@ class NET_EXPORT HttpServerPropertiesImpl
// ".googlevideo.com", ".googleusercontent.com") of canonical hostnames.
CanonicalSufficList canonical_suffixes_;
+ double alternative_service_probability_threshold_;
+
QuicServerInfoMap quic_server_info_map_;
size_t max_server_configs_stored_in_properties_;
diff --git a/net/http/http_server_properties_impl_unittest.cc b/net/http/http_server_properties_impl_unittest.cc
index 2babe2e..d06574f 100644
--- a/net/http/http_server_properties_impl_unittest.cc
+++ b/net/http/http_server_properties_impl_unittest.cc
@@ -62,10 +62,12 @@ class HttpServerPropertiesImplTest : public testing::Test {
}
bool SetAlternativeService(const HostPortPair& origin,
- const AlternativeService& alternative_service) {
+ const AlternativeService& alternative_service,
+ double alternative_probability) {
const base::Time expiration =
base::Time::Now() + base::TimeDelta::FromDays(1);
- return impl_.SetAlternativeService(origin, alternative_service, expiration);
+ return impl_.SetAlternativeService(origin, alternative_service,
+ alternative_probability, expiration);
}
void InitializeSpdySettingsUploadBandwidth(SpdySettingsMap* spdy_settings_map,
@@ -221,14 +223,14 @@ TEST_F(SpdyServerPropertiesTest, SupportsRequestPriorityTest) {
// Add www.youtube.com:443 as supporting QUIC.
HostPortPair quic_server_youtube("www.youtube.com", 443);
const AlternativeService alternative_service1(QUIC, "www.youtube.com", 443);
- SetAlternativeService(quic_server_youtube, alternative_service1);
+ SetAlternativeService(quic_server_youtube, alternative_service1, 1.0);
EXPECT_TRUE(impl_.SupportsRequestPriority(quic_server_youtube));
// Add www.example.com:443 with two alternative services, one supporting QUIC.
HostPortPair quic_server_example("www.example.com", 443);
const AlternativeService alternative_service2(NPN_HTTP_2, "", 443);
- SetAlternativeService(quic_server_example, alternative_service2);
- SetAlternativeService(quic_server_example, alternative_service1);
+ SetAlternativeService(quic_server_example, alternative_service2, 1.0);
+ SetAlternativeService(quic_server_example, alternative_service1, 1.0);
EXPECT_TRUE(impl_.SupportsRequestPriority(quic_server_example));
// Verify all the entries are the same after additions.
@@ -356,7 +358,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, Basic) {
EXPECT_FALSE(HasAlternativeService(test_host_port_pair));
AlternativeService alternative_service(NPN_HTTP_2, "foo", 443);
- SetAlternativeService(test_host_port_pair, alternative_service);
+ SetAlternativeService(test_host_port_pair, alternative_service, 1.0);
const AlternativeServiceVector alternative_service_vector =
impl_.GetAlternativeServices(test_host_port_pair);
ASSERT_EQ(1u, alternative_service_vector.size());
@@ -372,19 +374,19 @@ TEST_F(AlternateProtocolServerPropertiesTest, ExcludeOrigin) {
// Same hostname, same port, TCP: should be ignored.
AlternativeService alternative_service1(NPN_HTTP_2, "foo", 443);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, expiration));
+ AlternativeServiceInfo(alternative_service1, 1.0, expiration));
// Different hostname: GetAlternativeServices should return this one.
AlternativeService alternative_service2(NPN_HTTP_2, "bar", 443);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service2, expiration));
+ AlternativeServiceInfo(alternative_service2, 1.0, expiration));
// Different port: GetAlternativeServices should return this one too.
AlternativeService alternative_service3(NPN_HTTP_2, "foo", 80);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service3, expiration));
+ AlternativeServiceInfo(alternative_service3, 1.0, expiration));
// QUIC: GetAlternativeServices should return this one too.
AlternativeService alternative_service4(QUIC, "foo", 443);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service4, expiration));
+ AlternativeServiceInfo(alternative_service4, 1.0, expiration));
HostPortPair test_host_port_pair("foo", 443);
impl_.SetAlternativeServices(test_host_port_pair,
@@ -398,6 +400,63 @@ TEST_F(AlternateProtocolServerPropertiesTest, ExcludeOrigin) {
EXPECT_EQ(alternative_service4, alternative_service_vector[2]);
}
+TEST_F(AlternateProtocolServerPropertiesTest, DefaultProbabilityExcluded) {
+ HostPortPair test_host_port_pair("foo", 80);
+ const AlternativeService alternative_service(NPN_HTTP_2, "foo", 443);
+ SetAlternativeService(test_host_port_pair, alternative_service, 0.99);
+
+ EXPECT_FALSE(HasAlternativeService(test_host_port_pair));
+}
+
+// GetAlternativeServices and HasAlternativeServices should only return the ones
+// with probability greater than or equal to the threshold.
+TEST_F(AlternateProtocolServerPropertiesTest, Probability) {
+ impl_.SetAlternativeServiceProbabilityThreshold(0.5);
+
+ AlternativeServiceInfoVector alternative_service_info_vector;
+ base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
+ const AlternativeService alternative_service1(NPN_HTTP_2, "foo", 443);
+ alternative_service_info_vector.push_back(
+ AlternativeServiceInfo(alternative_service1, 0.3, expiration));
+ const AlternativeService alternative_service2(QUIC, "bar", 123);
+ alternative_service_info_vector.push_back(
+ AlternativeServiceInfo(alternative_service2, 0.7, expiration));
+ const AlternativeService alternative_service3(NPN_SPDY_3_1, "baz", 443);
+ alternative_service_info_vector.push_back(
+ AlternativeServiceInfo(alternative_service3, 0.4, expiration));
+ const AlternativeService alternative_service4(NPN_HTTP_2, "qux", 1234);
+ alternative_service_info_vector.push_back(
+ AlternativeServiceInfo(alternative_service4, 0.6, expiration));
+
+ HostPortPair test_host_port_pair("foo", 80);
+ impl_.SetAlternativeServices(test_host_port_pair,
+ alternative_service_info_vector);
+
+ const AlternativeServiceVector alternative_service_vector =
+ impl_.GetAlternativeServices(test_host_port_pair);
+ ASSERT_EQ(2u, alternative_service_vector.size());
+ EXPECT_EQ(alternative_service2, alternative_service_vector[0]);
+ EXPECT_EQ(alternative_service4, alternative_service_vector[1]);
+}
+
+TEST_F(AlternateProtocolServerPropertiesTest, ProbabilityExcluded) {
+ impl_.SetAlternativeServiceProbabilityThreshold(0.75);
+
+ HostPortPair test_host_port_pair("foo", 80);
+ const AlternativeService alternative_service(NPN_HTTP_2, "foo", 443);
+ SetAlternativeService(test_host_port_pair, alternative_service, 0.5);
+ EXPECT_FALSE(HasAlternativeService(test_host_port_pair));
+}
+
+TEST_F(AlternateProtocolServerPropertiesTest, ZeroProbabilityAlwaysExcluded) {
+ impl_.SetAlternativeServiceProbabilityThreshold(0.0);
+
+ HostPortPair test_host_port_pair("foo", 80);
+ const AlternativeService alternative_service(NPN_HTTP_2, "foo", 443);
+ SetAlternativeService(test_host_port_pair, alternative_service, 0);
+ EXPECT_FALSE(HasAlternativeService(test_host_port_pair));
+}
+
TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
// |test_host_port_pair1| has an alternative service, which will not be
// affected by InitializeAlternativeServiceServers(), because
@@ -408,7 +467,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
const base::Time now = base::Time::Now();
base::Time expiration1 = now + base::TimeDelta::FromDays(1);
// 1st entry in the memory.
- impl_.SetAlternativeService(test_host_port_pair1, alternative_service1,
+ impl_.SetAlternativeService(test_host_port_pair1, alternative_service1, 1.0,
expiration1);
// |test_host_port_pair2| has an alternative service, which will be
@@ -419,7 +478,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
const AlternativeService alternative_service2(NPN_SPDY_3_1, "bar2", 443);
base::Time expiration2 = now + base::TimeDelta::FromDays(2);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service2, expiration2));
+ AlternativeServiceInfo(alternative_service2, 1.0, expiration2));
HostPortPair test_host_port_pair2("foo2", 80);
// 0th entry in the memory.
impl_.SetAlternativeServices(test_host_port_pair2,
@@ -432,7 +491,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
const AlternativeService alternative_service3(NPN_HTTP_2, "bar3", 123);
base::Time expiration3 = now + base::TimeDelta::FromDays(3);
const AlternativeServiceInfo alternative_service_info1(alternative_service3,
- expiration3);
+ 0.7, expiration3);
// Simulate updating data for 0th entry with data from Preferences.
alternative_service_map.Put(
test_host_port_pair2,
@@ -442,7 +501,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
const AlternativeService alternative_service4(NPN_HTTP_2, "bar4", 1234);
base::Time expiration4 = now + base::TimeDelta::FromDays(4);
const AlternativeServiceInfo alternative_service_info2(alternative_service4,
- expiration4);
+ 0.2, expiration4);
// Add an old entry from Preferences, this will be added to end of recency
// list.
alternative_service_map.Put(
@@ -461,16 +520,19 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
EXPECT_TRUE(map_it->first.Equals(test_host_port_pair2));
ASSERT_EQ(1u, map_it->second.size());
EXPECT_EQ(alternative_service3, map_it->second[0].alternative_service);
+ EXPECT_EQ(0.7, map_it->second[0].probability);
EXPECT_EQ(expiration3, map_it->second[0].expiration);
++map_it;
EXPECT_TRUE(map_it->first.Equals(test_host_port_pair1));
ASSERT_EQ(1u, map_it->second.size());
EXPECT_EQ(alternative_service1, map_it->second[0].alternative_service);
+ EXPECT_EQ(1.0, map_it->second[0].probability);
EXPECT_EQ(expiration1, map_it->second[0].expiration);
++map_it;
EXPECT_TRUE(map_it->first.Equals(test_host_port_pair3));
ASSERT_EQ(1u, map_it->second.size());
EXPECT_EQ(alternative_service4, map_it->second[0].alternative_service);
+ EXPECT_EQ(0.2, map_it->second[0].probability);
EXPECT_EQ(expiration4, map_it->second[0].expiration);
}
@@ -483,8 +545,8 @@ TEST_F(AlternateProtocolServerPropertiesTest, InitializeWithEmptyHostname) {
"", 1234);
const AlternativeService alternative_service_with_foo_hostname(NPN_HTTP_2,
"foo", 1234);
- SetAlternativeService(host_port_pair,
- alternative_service_with_empty_hostname);
+ SetAlternativeService(host_port_pair, alternative_service_with_empty_hostname,
+ 1.0);
impl_.MarkAlternativeServiceBroken(alternative_service_with_foo_hostname);
AlternativeServiceMap alternative_service_map(
@@ -508,7 +570,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, EmptyVector) {
const AlternativeService alternative_service(NPN_HTTP_2, "bar", 443);
base::Time expiration = base::Time::Now() - base::TimeDelta::FromDays(1);
const AlternativeServiceInfo alternative_service_info(alternative_service,
- expiration);
+ 1.0, expiration);
AlternativeServiceMap alternative_service_map(
AlternativeServiceMap::NO_AUTO_EVICT);
alternative_service_map.Put(
@@ -544,7 +606,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, EmptyVectorForCanonical) {
const AlternativeService alternative_service(NPN_HTTP_2, "", 443);
base::Time expiration = base::Time::Now() - base::TimeDelta::FromDays(1);
const AlternativeServiceInfo alternative_service_info(alternative_service,
- expiration);
+ 1.0, expiration);
AlternativeServiceMap alternative_service_map(
AlternativeServiceMap::NO_AUTO_EVICT);
alternative_service_map.Put(
@@ -579,10 +641,10 @@ TEST_F(AlternateProtocolServerPropertiesTest, EmptyVectorForCanonical) {
TEST_F(AlternateProtocolServerPropertiesTest, MRUOfGetAlternativeServices) {
HostPortPair test_host_port_pair1("foo1", 80);
const AlternativeService alternative_service1(NPN_SPDY_3_1, "foo1", 443);
- SetAlternativeService(test_host_port_pair1, alternative_service1);
+ SetAlternativeService(test_host_port_pair1, alternative_service1, 1.0);
HostPortPair test_host_port_pair2("foo2", 80);
const AlternativeService alternative_service2(NPN_HTTP_2, "foo2", 1234);
- SetAlternativeService(test_host_port_pair2, alternative_service2);
+ SetAlternativeService(test_host_port_pair2, alternative_service2, 1.0);
const AlternativeServiceMap& map = impl_.alternative_service_map();
AlternativeServiceMap::const_iterator it = map.begin();
@@ -605,7 +667,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, MRUOfGetAlternativeServices) {
TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) {
HostPortPair test_host_port_pair("foo", 80);
const AlternativeService alternative_service1(NPN_HTTP_2, "foo", 443);
- SetAlternativeService(test_host_port_pair, alternative_service1);
+ SetAlternativeService(test_host_port_pair, alternative_service1, 1.0);
AlternativeServiceVector alternative_service_vector =
impl_.GetAlternativeServices(test_host_port_pair);
ASSERT_EQ(1u, alternative_service_vector.size());
@@ -624,10 +686,10 @@ TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) {
AlternativeServiceInfoVector alternative_service_info_vector;
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, expiration));
+ AlternativeServiceInfo(alternative_service1, 1.0, expiration));
const AlternativeService alternative_service2(NPN_HTTP_2, "foo", 1234);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service2, expiration));
+ AlternativeServiceInfo(alternative_service2, 1.0, expiration));
impl_.SetAlternativeServices(test_host_port_pair,
alternative_service_info_vector);
alternative_service_vector =
@@ -639,7 +701,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) {
EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service_vector[1]));
// SetAlternativeService should add a broken alternative service to the map.
- SetAlternativeService(test_host_port_pair, alternative_service1);
+ SetAlternativeService(test_host_port_pair, alternative_service1, 1.0);
alternative_service_vector =
impl_.GetAlternativeServices(test_host_port_pair);
ASSERT_EQ(1u, alternative_service_vector.size());
@@ -656,13 +718,13 @@ TEST_F(AlternateProtocolServerPropertiesTest, MaxAge) {
// GetAlternativeServices().
const AlternativeService alternative_service1(NPN_SPDY_3_1, "foo", 443);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, now - one_day));
+ AlternativeServiceInfo(alternative_service1, 1.0, now - one_day));
// Second alterrnative service will expire one day from now, should be
// returned by GetAlternativeSerices().
const AlternativeService alternative_service2(NPN_HTTP_2, "bar", 1234);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service2, now + one_day));
+ AlternativeServiceInfo(alternative_service2, 1.0, now + one_day));
HostPortPair test_host_port_pair("foo", 80);
impl_.SetAlternativeServices(test_host_port_pair,
@@ -683,13 +745,13 @@ TEST_F(AlternateProtocolServerPropertiesTest, MaxAgeCanonical) {
// GetAlternativeServices().
const AlternativeService alternative_service1(NPN_SPDY_3_1, "foo", 443);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, now - one_day));
+ AlternativeServiceInfo(alternative_service1, 1.0, now - one_day));
// Second alterrnative service will expire one day from now, should be
// returned by GetAlternativeSerices().
const AlternativeService alternative_service2(NPN_HTTP_2, "bar", 1234);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service2, now + one_day));
+ AlternativeServiceInfo(alternative_service2, 1.0, now + one_day));
HostPortPair canonical_host_port_pair("bar.c.youtube.com", 80);
impl_.SetAlternativeServices(canonical_host_port_pair,
@@ -707,10 +769,10 @@ TEST_F(AlternateProtocolServerPropertiesTest, ClearAlternativeServices) {
const AlternativeService alternative_service1(NPN_SPDY_3_1, "foo", 443);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, expiration));
+ AlternativeServiceInfo(alternative_service1, 1.0, expiration));
const AlternativeService alternative_service2(NPN_HTTP_2, "bar", 1234);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service2, expiration));
+ AlternativeServiceInfo(alternative_service2, 1.0, expiration));
HostPortPair test_host_port_pair("foo", 80);
impl_.SetAlternativeServices(test_host_port_pair,
alternative_service_info_vector);
@@ -735,8 +797,8 @@ TEST_F(AlternateProtocolServerPropertiesTest, BrokenShadowsCanonical) {
HostPortPair canonical_host_port_pair("bar.c.youtube.com", 80);
AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com",
1234);
- SetAlternativeService(canonical_host_port_pair,
- canonical_alternative_service);
+ SetAlternativeService(canonical_host_port_pair, canonical_alternative_service,
+ 1.0);
AlternativeServiceVector alternative_service_vector =
impl_.GetAlternativeServices(test_host_port_pair);
ASSERT_EQ(1u, alternative_service_vector.size());
@@ -746,7 +808,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, BrokenShadowsCanonical) {
impl_.MarkAlternativeServiceBroken(broken_alternative_service);
EXPECT_TRUE(impl_.IsAlternativeServiceBroken(broken_alternative_service));
- SetAlternativeService(test_host_port_pair, broken_alternative_service);
+ SetAlternativeService(test_host_port_pair, broken_alternative_service, 1.0);
alternative_service_vector =
impl_.GetAlternativeServices(test_host_port_pair);
ASSERT_EQ(1u, alternative_service_vector.size());
@@ -757,7 +819,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, BrokenShadowsCanonical) {
TEST_F(AlternateProtocolServerPropertiesTest, ClearBroken) {
HostPortPair test_host_port_pair("foo", 80);
const AlternativeService alternative_service(NPN_HTTP_2, "foo", 443);
- SetAlternativeService(test_host_port_pair, alternative_service);
+ SetAlternativeService(test_host_port_pair, alternative_service, 1.0);
impl_.MarkAlternativeServiceBroken(alternative_service);
ASSERT_TRUE(HasAlternativeService(test_host_port_pair));
EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service));
@@ -770,7 +832,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, ClearBroken) {
TEST_F(AlternateProtocolServerPropertiesTest, MarkRecentlyBroken) {
HostPortPair host_port_pair("foo", 80);
const AlternativeService alternative_service(NPN_HTTP_2, "foo", 443);
- SetAlternativeService(host_port_pair, alternative_service);
+ SetAlternativeService(host_port_pair, alternative_service, 1.0);
EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service));
EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service));
@@ -796,10 +858,10 @@ TEST_F(AlternateProtocolServerPropertiesTest, Canonical) {
QUIC, "bar.c.youtube.com", 1234);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(canonical_alternative_service1, expiration));
+ AlternativeServiceInfo(canonical_alternative_service1, 1.0, expiration));
const AlternativeService canonical_alternative_service2(NPN_HTTP_2, "", 443);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(canonical_alternative_service2, expiration));
+ AlternativeServiceInfo(canonical_alternative_service2, 1.0, expiration));
impl_.SetAlternativeServices(canonical_host_port_pair,
alternative_service_info_vector);
@@ -826,14 +888,42 @@ TEST_F(AlternateProtocolServerPropertiesTest, Canonical) {
impl_.GetCanonicalSuffix(canonical_host_port_pair.host()));
}
+TEST_F(AlternateProtocolServerPropertiesTest, CanonicalBelowThreshold) {
+ impl_.SetAlternativeServiceProbabilityThreshold(0.02);
+
+ HostPortPair test_host_port_pair("foo.c.youtube.com", 80);
+ HostPortPair canonical_host_port_pair("bar.c.youtube.com", 80);
+ AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com",
+ 1234);
+
+ SetAlternativeService(canonical_host_port_pair, canonical_alternative_service,
+ 0.01);
+ EXPECT_FALSE(HasAlternativeService(canonical_host_port_pair));
+ EXPECT_FALSE(HasAlternativeService(test_host_port_pair));
+}
+
+TEST_F(AlternateProtocolServerPropertiesTest, CanonicalAboveThreshold) {
+ impl_.SetAlternativeServiceProbabilityThreshold(0.02);
+
+ HostPortPair test_host_port_pair("foo.c.youtube.com", 80);
+ HostPortPair canonical_host_port_pair("bar.c.youtube.com", 80);
+ AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com",
+ 1234);
+
+ SetAlternativeService(canonical_host_port_pair, canonical_alternative_service,
+ 0.03);
+ EXPECT_TRUE(HasAlternativeService(canonical_host_port_pair));
+ EXPECT_TRUE(HasAlternativeService(test_host_port_pair));
+}
+
TEST_F(AlternateProtocolServerPropertiesTest, ClearCanonical) {
HostPortPair test_host_port_pair("foo.c.youtube.com", 80);
HostPortPair canonical_host_port_pair("bar.c.youtube.com", 80);
AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com",
1234);
- SetAlternativeService(canonical_host_port_pair,
- canonical_alternative_service);
+ SetAlternativeService(canonical_host_port_pair, canonical_alternative_service,
+ 1.0);
impl_.ClearAlternativeServices(canonical_host_port_pair);
EXPECT_FALSE(HasAlternativeService(test_host_port_pair));
}
@@ -844,8 +934,8 @@ TEST_F(AlternateProtocolServerPropertiesTest, CanonicalBroken) {
AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com",
1234);
- SetAlternativeService(canonical_host_port_pair,
- canonical_alternative_service);
+ SetAlternativeService(canonical_host_port_pair, canonical_alternative_service,
+ 1.0);
impl_.MarkAlternativeServiceBroken(canonical_alternative_service);
EXPECT_FALSE(HasAlternativeService(test_host_port_pair));
}
@@ -855,7 +945,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, CanonicalOverride) {
HostPortPair test_host_port_pair("foo.c.youtube.com", 80);
HostPortPair bar_host_port_pair("bar.c.youtube.com", 80);
AlternativeService bar_alternative_service(QUIC, "bar.c.youtube.com", 1234);
- SetAlternativeService(bar_host_port_pair, bar_alternative_service);
+ SetAlternativeService(bar_host_port_pair, bar_alternative_service, 1.0);
AlternativeServiceVector alternative_service_vector =
impl_.GetAlternativeServices(test_host_port_pair);
ASSERT_EQ(1u, alternative_service_vector.size());
@@ -863,7 +953,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, CanonicalOverride) {
HostPortPair qux_host_port_pair("qux.c.youtube.com", 80);
AlternativeService qux_alternative_service(QUIC, "qux.c.youtube.com", 443);
- SetAlternativeService(qux_host_port_pair, qux_alternative_service);
+ SetAlternativeService(qux_host_port_pair, qux_alternative_service, 1.0);
alternative_service_vector =
impl_.GetAlternativeServices(test_host_port_pair);
ASSERT_EQ(1u, alternative_service_vector.size());
@@ -876,8 +966,8 @@ TEST_F(AlternateProtocolServerPropertiesTest, ClearWithCanonical) {
AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com",
1234);
- SetAlternativeService(canonical_host_port_pair,
- canonical_alternative_service);
+ SetAlternativeService(canonical_host_port_pair, canonical_alternative_service,
+ 1.0);
impl_.Clear();
EXPECT_FALSE(HasAlternativeService(test_host_port_pair));
}
@@ -886,7 +976,7 @@ TEST_F(AlternateProtocolServerPropertiesTest,
ExpireBrokenAlternateProtocolMappings) {
HostPortPair host_port_pair("foo", 443);
AlternativeService alternative_service(QUIC, "foo", 443);
- SetAlternativeService(host_port_pair, alternative_service);
+ SetAlternativeService(host_port_pair, alternative_service, 1.0);
EXPECT_TRUE(HasAlternativeService(host_port_pair));
EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service));
EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service));
@@ -907,17 +997,17 @@ TEST_F(AlternateProtocolServerPropertiesTest,
TEST_F(AlternateProtocolServerPropertiesTest, RemoveExpiredBrokenAltSvc) {
HostPortPair foo_host_port_pair("foo", 443);
AlternativeService bar_alternative_service(QUIC, "bar", 443);
- SetAlternativeService(foo_host_port_pair, bar_alternative_service);
+ SetAlternativeService(foo_host_port_pair, bar_alternative_service, 1.0);
EXPECT_TRUE(HasAlternativeService(foo_host_port_pair));
HostPortPair bar_host_port_pair1("bar", 80);
AlternativeService nohost_alternative_service(QUIC, "", 443);
- SetAlternativeService(bar_host_port_pair1, nohost_alternative_service);
+ SetAlternativeService(bar_host_port_pair1, nohost_alternative_service, 1.0);
EXPECT_TRUE(HasAlternativeService(bar_host_port_pair1));
HostPortPair bar_host_port_pair2("bar", 443);
AlternativeService baz_alternative_service(QUIC, "baz", 1234);
- SetAlternativeService(bar_host_port_pair2, baz_alternative_service);
+ SetAlternativeService(bar_host_port_pair2, baz_alternative_service, 1.0);
EXPECT_TRUE(HasAlternativeService(bar_host_port_pair2));
// Mark "bar:443" as broken.
diff --git a/net/http/http_server_properties_manager.cc b/net/http/http_server_properties_manager.cc
index a592f44..f8d133c 100644
--- a/net/http/http_server_properties_manager.cc
+++ b/net/http/http_server_properties_manager.cc
@@ -61,6 +61,7 @@ const char kAlternativeServiceKey[] = "alternative_service";
const char kProtocolKey[] = "protocol_str";
const char kHostKey[] = "host";
const char kPortKey[] = "port";
+const char kProbabilityKey[] = "probability";
const char kExpirationKey[] = "expiration";
const char kNetworkStatsKey[] = "network_stats";
const char kSrttKey[] = "srtt";
@@ -194,10 +195,11 @@ AlternativeServiceVector HttpServerPropertiesManager::GetAlternativeServices(
bool HttpServerPropertiesManager::SetAlternativeService(
const HostPortPair& origin,
const AlternativeService& alternative_service,
+ double alternative_probability,
base::Time expiration) {
DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
const bool changed = http_server_properties_impl_->SetAlternativeService(
- origin, alternative_service, expiration);
+ origin, alternative_service, alternative_probability, expiration);
if (changed) {
ScheduleUpdatePrefsOnNetworkThread(SET_ALTERNATIVE_SERVICES);
}
@@ -286,6 +288,13 @@ HttpServerPropertiesManager::GetAlternativeServiceInfoAsValue()
return http_server_properties_impl_->GetAlternativeServiceInfoAsValue();
}
+void HttpServerPropertiesManager::SetAlternativeServiceProbabilityThreshold(
+ double threshold) {
+ DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+ http_server_properties_impl_->SetAlternativeServiceProbabilityThreshold(
+ threshold);
+}
+
const SettingsMap& HttpServerPropertiesManager::GetSpdySettings(
const HostPortPair& host_port_pair) {
DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
@@ -653,6 +662,16 @@ bool HttpServerPropertiesManager::ParseAlternativeServiceDict(
alternative_service_info->alternative_service.port =
static_cast<uint32_t>(port);
+ // Probability is optional, defaults to 1.0.
+ alternative_service_info->probability = 1.0;
+ if (alternative_service_dict.HasKey(kProbabilityKey) &&
+ !alternative_service_dict.GetDoubleWithoutPathExpansion(
+ kProbabilityKey, &(alternative_service_info->probability))) {
+ DVLOG(1) << "Malformed alternative service probability for server: "
+ << server_str;
+ return false;
+ }
+
// Expiration is optional, defaults to one day.
base::Time expiration;
if (!alternative_service_dict.HasKey(kExpirationKey)) {
@@ -1177,6 +1196,8 @@ void HttpServerPropertiesManager::SaveAlternativeServiceToServerPrefs(
}
alternative_service_dict->SetString(
kProtocolKey, AlternateProtocolToString(alternative_service.protocol));
+ alternative_service_dict->SetDouble(kProbabilityKey,
+ alternative_service_info.probability);
// JSON cannot store int64_t, so expiration is converted to a string.
alternative_service_dict->SetString(
kExpirationKey,
diff --git a/net/http/http_server_properties_manager.h b/net/http/http_server_properties_manager.h
index a7ede48..1427852 100644
--- a/net/http/http_server_properties_manager.h
+++ b/net/http/http_server_properties_manager.h
@@ -119,6 +119,7 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties {
const HostPortPair& origin) override;
bool SetAlternativeService(const HostPortPair& origin,
const AlternativeService& alternative_service,
+ double alternative_probability,
base::Time expiration) override;
bool SetAlternativeServices(const HostPortPair& origin,
const AlternativeServiceInfoVector&
@@ -136,6 +137,7 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties {
void ClearAlternativeServices(const HostPortPair& origin) override;
const AlternativeServiceMap& alternative_service_map() const override;
scoped_ptr<base::Value> GetAlternativeServiceInfoAsValue() const override;
+ void SetAlternativeServiceProbabilityThreshold(double threshold) override;
const SettingsMap& GetSpdySettings(
const HostPortPair& host_port_pair) override;
bool SetSpdySetting(const HostPortPair& host_port_pair,
diff --git a/net/http/http_server_properties_manager_unittest.cc b/net/http/http_server_properties_manager_unittest.cc
index bf83ff78..5471fd1 100644
--- a/net/http/http_server_properties_manager_unittest.cc
+++ b/net/http/http_server_properties_manager_unittest.cc
@@ -684,10 +684,10 @@ TEST_P(HttpServerPropertiesManagerTest, GetAlternativeServices) {
const AlternativeService alternative_service(NPN_HTTP_2, "mail.google.com",
443);
http_server_props_manager_->SetAlternativeService(
- spdy_server_mail, alternative_service, one_day_from_now_);
+ spdy_server_mail, alternative_service, 1.0, one_day_from_now_);
// ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once.
http_server_props_manager_->SetAlternativeService(
- spdy_server_mail, alternative_service, one_day_from_now_);
+ spdy_server_mail, alternative_service, 1.0, one_day_from_now_);
// Run the task.
base::RunLoop().RunUntilIdle();
@@ -709,10 +709,10 @@ TEST_P(HttpServerPropertiesManagerTest, SetAlternativeServices) {
const AlternativeService alternative_service1(NPN_HTTP_2, "mail.google.com",
443);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, one_day_from_now_));
+ AlternativeServiceInfo(alternative_service1, 1.0, one_day_from_now_));
const AlternativeService alternative_service2(QUIC, "mail.google.com", 1234);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service2, one_day_from_now_));
+ AlternativeServiceInfo(alternative_service2, 1.0, one_day_from_now_));
http_server_props_manager_->SetAlternativeServices(
spdy_server_mail, alternative_service_info_vector);
// ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once.
@@ -754,7 +754,7 @@ TEST_P(HttpServerPropertiesManagerTest, ClearAlternativeServices) {
EXPECT_FALSE(HasAlternativeService(spdy_server_mail));
AlternativeService alternative_service(NPN_HTTP_2, "mail.google.com", 443);
http_server_props_manager_->SetAlternativeService(
- spdy_server_mail, alternative_service, one_day_from_now_);
+ spdy_server_mail, alternative_service, 1.0, one_day_from_now_);
ExpectScheduleUpdatePrefsOnNetworkThread();
http_server_props_manager_->ClearAlternativeServices(spdy_server_mail);
// ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once.
@@ -776,7 +776,7 @@ TEST_P(HttpServerPropertiesManagerTest, ConfirmAlternativeService) {
ExpectScheduleUpdatePrefsOnNetworkThread();
http_server_props_manager_->SetAlternativeService(
- spdy_server_mail, alternative_service, one_day_from_now_);
+ spdy_server_mail, alternative_service, 1.0, one_day_from_now_);
EXPECT_FALSE(http_server_props_manager_->IsAlternativeServiceBroken(
alternative_service));
@@ -886,7 +886,7 @@ TEST_P(HttpServerPropertiesManagerTest, Clear) {
http_server_props_manager_->SetSupportsSpdy(spdy_server_mail, true);
AlternativeService alternative_service(NPN_HTTP_2, "mail.google.com", 1234);
http_server_props_manager_->SetAlternativeService(
- spdy_server_mail, alternative_service, one_day_from_now_);
+ spdy_server_mail, alternative_service, 1.0, one_day_from_now_);
IPAddress actual_address(127, 0, 0, 1);
http_server_props_manager_->SetSupportsQuic(true, actual_address);
ServerNetworkStats stats;
@@ -1048,13 +1048,13 @@ TEST_P(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
base::Time expiration1;
ASSERT_TRUE(base::Time::FromUTCString("2036-12-01 10:00:00", &expiration1));
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(www_alternative_service1, expiration1));
+ AlternativeServiceInfo(www_alternative_service1, 1.0, expiration1));
AlternativeService www_alternative_service2(NPN_HTTP_2, "www.google.com",
1234);
base::Time expiration2;
ASSERT_TRUE(base::Time::FromUTCString("2036-12-31 10:00:00", &expiration2));
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(www_alternative_service2, expiration2));
+ AlternativeServiceInfo(www_alternative_service2, 0.7, expiration2));
http_server_props_manager_->SetAlternativeServices(
server_www, alternative_service_info_vector);
@@ -1062,7 +1062,7 @@ TEST_P(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
444);
base::Time expiration3 = base::Time::Max();
http_server_props_manager_->SetAlternativeService(
- server_mail, mail_alternative_service, expiration3);
+ server_mail, mail_alternative_service, 0.2, expiration3);
// Set ServerNetworkStats.
ServerNetworkStats stats;
@@ -1092,12 +1092,12 @@ TEST_P(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
"\"servers\":["
"{\"www.google.com:80\":{"
"\"alternative_service\":[{\"expiration\":\"13756212000000000\","
- "\"port\":443,\"protocol_str\":\"npn-h2\"},"
+ "\"port\":443,\"probability\":1.0,\"protocol_str\":\"npn-h2\"},"
"{\"expiration\":\"13758804000000000\",\"host\":\"www.google.com\","
- "\"port\":1234,\"protocol_str\":\"npn-h2\"}]}},"
+ "\"port\":1234,\"probability\":0.7,\"protocol_str\":\"npn-h2\"}]}},"
"{\"mail.google.com:80\":{\"alternative_service\":[{"
"\"expiration\":\"9223372036854775807\",\"host\":\"foo.google.com\","
- "\"port\":444,\"protocol_str\":\"npn-spdy/3.1\"}],"
+ "\"port\":444,\"probability\":0.2,\"protocol_str\":\"npn-spdy/3.1\"}],"
"\"network_stats\":{\"srtt\":42}}}"
"],"
"\"supports_quic\":{\"address\":\"127.0.0.1\",\"used_quic\":true},"
@@ -1114,9 +1114,9 @@ TEST_P(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
TEST_P(HttpServerPropertiesManagerTest, AddToAlternativeServiceMap) {
scoped_ptr<base::Value> server_value = base::JSONReader::Read(
"{\"alternative_service\":[{\"port\":443,\"protocol_str\":\"npn-h2\"},"
- "{\"port\":123,\"protocol_str\":\"quic\","
+ "{\"port\":123,\"protocol_str\":\"quic\",\"probability\":0.7,"
"\"expiration\":\"9223372036854775807\"},{\"host\":\"example.org\","
- "\"port\":1234,\"protocol_str\":\"npn-h2\","
+ "\"port\":1234,\"protocol_str\":\"npn-h2\",\"probability\":0.2,"
"\"expiration\":\"13758804000000000\"}]}");
ASSERT_TRUE(server_value);
base::DictionaryValue* server_dict;
@@ -1137,6 +1137,8 @@ TEST_P(HttpServerPropertiesManagerTest, AddToAlternativeServiceMap) {
alternative_service_info_vector[0].alternative_service.protocol);
EXPECT_EQ("", alternative_service_info_vector[0].alternative_service.host);
EXPECT_EQ(443, alternative_service_info_vector[0].alternative_service.port);
+ // Probability defaults to 1.0.
+ EXPECT_DOUBLE_EQ(1.0, alternative_service_info_vector[0].probability);
// Expiration defaults to one day from now, testing with tolerance.
const base::Time now = base::Time::Now();
const base::Time expiration = alternative_service_info_vector[0].expiration;
@@ -1147,6 +1149,7 @@ TEST_P(HttpServerPropertiesManagerTest, AddToAlternativeServiceMap) {
alternative_service_info_vector[1].alternative_service.protocol);
EXPECT_EQ("", alternative_service_info_vector[1].alternative_service.host);
EXPECT_EQ(123, alternative_service_info_vector[1].alternative_service.port);
+ EXPECT_DOUBLE_EQ(0.7, alternative_service_info_vector[1].probability);
// numeric_limits<int64_t>::max() represents base::Time::Max().
EXPECT_EQ(base::Time::Max(), alternative_service_info_vector[1].expiration);
@@ -1155,6 +1158,7 @@ TEST_P(HttpServerPropertiesManagerTest, AddToAlternativeServiceMap) {
EXPECT_EQ("example.org",
alternative_service_info_vector[2].alternative_service.host);
EXPECT_EQ(1234, alternative_service_info_vector[2].alternative_service.port);
+ EXPECT_DOUBLE_EQ(0.2, alternative_service_info_vector[2].probability);
base::Time expected_expiration;
ASSERT_TRUE(
base::Time::FromUTCString("2036-12-31 10:00:00", &expected_expiration));
@@ -1172,8 +1176,8 @@ TEST_P(HttpServerPropertiesManagerTest,
NPN_HTTP_2, "broken.example.com", 443);
const base::Time time_one_day_later =
base::Time::Now() + base::TimeDelta::FromDays(1);
- alternative_service_info_vector.push_back(
- AlternativeServiceInfo(broken_alternative_service, time_one_day_later));
+ alternative_service_info_vector.push_back(AlternativeServiceInfo(
+ broken_alternative_service, 1.0, time_one_day_later));
http_server_props_manager_->MarkAlternativeServiceBroken(
broken_alternative_service);
@@ -1181,13 +1185,13 @@ TEST_P(HttpServerPropertiesManagerTest,
NPN_HTTP_2, "expired.example.com", 443);
const base::Time time_one_day_ago =
base::Time::Now() - base::TimeDelta::FromDays(1);
- alternative_service_info_vector.push_back(
- AlternativeServiceInfo(expired_alternative_service, time_one_day_ago));
+ alternative_service_info_vector.push_back(AlternativeServiceInfo(
+ expired_alternative_service, 1.0, time_one_day_ago));
const AlternativeService valid_alternative_service(NPN_HTTP_2,
"valid.example.com", 443);
- alternative_service_info_vector.push_back(
- AlternativeServiceInfo(valid_alternative_service, time_one_day_later));
+ alternative_service_info_vector.push_back(AlternativeServiceInfo(
+ valid_alternative_service, 1.0, time_one_day_later));
const HostPortPair host_port_pair("www.example.com", 443);
http_server_props_manager_->SetAlternativeServices(
@@ -1232,6 +1236,7 @@ TEST_P(HttpServerPropertiesManagerTest, DoNotLoadExpiredAlternativeService) {
expired_dict->SetString("protocol_str", "npn-h2");
expired_dict->SetString("host", "expired.example.com");
expired_dict->SetInteger("port", 443);
+ expired_dict->SetDouble("probability", 1.0);
base::Time time_one_day_ago =
base::Time::Now() - base::TimeDelta::FromDays(1);
expired_dict->SetString(
@@ -1242,6 +1247,7 @@ TEST_P(HttpServerPropertiesManagerTest, DoNotLoadExpiredAlternativeService) {
valid_dict->SetString("protocol_str", "npn-h2");
valid_dict->SetString("host", "valid.example.com");
valid_dict->SetInteger("port", 443);
+ valid_dict->SetDouble("probability", 1.0);
valid_dict->SetString(
"expiration", base::Int64ToString(one_day_from_now_.ToInternalValue()));
alternative_service_list->Append(valid_dict);
@@ -1266,6 +1272,7 @@ TEST_P(HttpServerPropertiesManagerTest, DoNotLoadExpiredAlternativeService) {
EXPECT_EQ("valid.example.com",
alternative_service_info_vector[0].alternative_service.host);
EXPECT_EQ(443, alternative_service_info_vector[0].alternative_service.port);
+ EXPECT_DOUBLE_EQ(1.0, alternative_service_info_vector[0].probability);
EXPECT_EQ(one_day_from_now_, alternative_service_info_vector[0].expiration);
}
diff --git a/net/http/http_stream_factory.cc b/net/http/http_stream_factory.cc
index bc0212b..d6d76b4 100644
--- a/net/http/http_stream_factory.cc
+++ b/net/http/http_stream_factory.cc
@@ -79,8 +79,8 @@ void HttpStreamFactory::ProcessAlternativeService(
base::Time expiration =
base::Time::Now() +
base::TimeDelta::FromSeconds(alternative_service_entry.max_age);
- AlternativeServiceInfo alternative_service_info(alternative_service,
- expiration);
+ AlternativeServiceInfo alternative_service_info(
+ alternative_service, alternative_service_entry.probability, expiration);
alternative_service_info_vector.push_back(alternative_service_info);
}
@@ -95,9 +95,24 @@ void HttpStreamFactory::ProcessAlternateProtocol(
const HttpNetworkSession& session) {
AlternateProtocol protocol = UNINITIALIZED_ALTERNATE_PROTOCOL;
int port = 0;
+ double probability = 1;
bool is_valid = true;
for (size_t i = 0; i < alternate_protocol_values.size(); ++i) {
base::StringPiece alternate_protocol_str = alternate_protocol_values[i];
+ if (base::StartsWith(alternate_protocol_str, "p=",
+ base::CompareCase::SENSITIVE)) {
+ if (!base::StringToDouble(alternate_protocol_str.substr(2).as_string(),
+ &probability) ||
+ probability < 0 || probability > 1) {
+ DVLOG(1) << kAlternateProtocolHeader
+ << " header has unrecognizable probability: "
+ << alternate_protocol_values[i];
+ is_valid = false;
+ break;
+ }
+ continue;
+ }
+
std::vector<base::StringPiece> port_protocol_vector =
base::SplitStringPiece(alternate_protocol_str, ":",
base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
@@ -138,7 +153,7 @@ void HttpStreamFactory::ProcessAlternateProtocol(
http_server_properties->SetAlternativeService(
RewriteHost(http_host_port_pair),
AlternativeService(protocol, "", static_cast<uint16_t>(port)),
- base::Time::Now() + base::TimeDelta::FromDays(30));
+ probability, base::Time::Now() + base::TimeDelta::FromDays(30));
}
GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url,
diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc
index e94f9cc..002e360 100644
--- a/net/http/http_stream_factory_impl_unittest.cc
+++ b/net/http/http_stream_factory_impl_unittest.cc
@@ -808,7 +808,7 @@ TEST_P(HttpStreamFactoryTest, UsePreConnectIfNoZeroRTT) {
AlternativeServiceInfoVector alternative_service_info_vector;
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service, expiration));
+ AlternativeServiceInfo(alternative_service, 1.0, expiration));
HostPortPair host_port_pair(alternative_service.host_port_pair());
http_server_properties.SetAlternativeServices(
host_port_pair, alternative_service_info_vector);
@@ -852,7 +852,7 @@ TEST_P(HttpStreamFactoryTest, QuicDisablePreConnectIfZeroRtt) {
AlternativeServiceInfoVector alternative_service_info_vector;
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service, expiration));
+ AlternativeServiceInfo(alternative_service, 1.0, expiration));
HostPortPair host_port_pair(alternative_service.host_port_pair());
http_server_properties.SetAlternativeServices(
host_port_pair, alternative_service_info_vector);
@@ -1654,7 +1654,7 @@ TEST_P(HttpStreamFactoryTest, DISABLED_OrphanedWebSocketStream) {
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
session->http_server_properties()->SetAlternativeService(
HostPortPair("www.google.com", 8888),
- AlternativeService(NPN_HTTP_2, "www.google.com", 9999), expiration);
+ AlternativeService(NPN_HTTP_2, "www.google.com", 9999), 1.0, expiration);
SSLConfig ssl_config;
StreamRequestWaiter waiter;
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index 15a0702..b5a8d6d 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -61,10 +61,14 @@ namespace {
static const char kQuicAlternateProtocolHeader[] =
"Alternate-Protocol: 443:quic\r\n\r\n";
+static const char kQuicAlternateProtocol50pctHeader[] =
+ "Alternate-Protocol: 443:quic,p=.5\r\n\r\n";
static const char kQuicAlternateProtocolDifferentPortHeader[] =
"Alternate-Protocol: 137:quic\r\n\r\n";
static const char kQuicAlternativeServiceHeader[] =
"Alt-Svc: quic=\":443\"\r\n\r\n";
+static const char kQuicAlternativeService50pctHeader[] =
+ "Alt-Svc: quic=\":443\";p=\".5\"\r\n\r\n";
static const char kQuicAlternativeServiceDifferentPortHeader[] =
"Alt-Svc: quic=\":137\"\r\n\r\n";
@@ -513,7 +517,7 @@ class QuicNetworkTransactionTest
AlternativeService alternative_service(QUIC, host_port_pair.host(), 443);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties_.SetAlternativeService(
- host_port_pair, alternative_service, expiration);
+ host_port_pair, alternative_service, 1.0, expiration);
}
void AddQuicRemoteAlternativeServiceMapping(
@@ -525,7 +529,7 @@ class QuicNetworkTransactionTest
alternative.port());
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties_.SetAlternativeService(
- host_port_pair, alternative_service, expiration);
+ host_port_pair, alternative_service, 1.0, expiration);
}
void ExpectBrokenAlternateProtocolMapping() {
@@ -1348,6 +1352,84 @@ TEST_P(QuicNetworkTransactionTest, ConfirmAlternativeService) {
alternative_service));
}
+TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceProbabilityForQuic) {
+ MockRead http_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"),
+ MockRead(kQuicAlternativeService50pctHeader), MockRead("hello world"),
+ MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
+ MockRead(ASYNC, OK)};
+
+ StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
+ 0);
+ socket_factory_.AddSocketDataProvider(&http_data);
+ socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
+
+ MockQuicData mock_quic_data;
+ mock_quic_data.AddWrite(
+ ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/")));
+ mock_quic_data.AddRead(ConstructResponseHeadersPacket(
+ 1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
+ mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+ mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
+ mock_quic_data.AddRead(ASYNC, 0); // EOF
+
+ mock_quic_data.AddSocketDataToFactory(&socket_factory_);
+
+ AddHangingNonAlternateProtocolSocketData();
+ params_.alternative_service_probability_threshold = 0.25;
+ CreateSession();
+
+ SendRequestAndExpectHttpResponse("hello world");
+ SendRequestAndExpectQuicResponse("hello!");
+}
+
+TEST_P(QuicNetworkTransactionTest,
+ DontUseAlternativeServiceProbabilityForQuic) {
+ MockRead http_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"),
+ MockRead(kQuicAlternativeService50pctHeader), MockRead("hello world"),
+ MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
+ MockRead(ASYNC, OK)};
+
+ StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
+ 0);
+ socket_factory_.AddSocketDataProvider(&http_data);
+ socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
+ socket_factory_.AddSocketDataProvider(&http_data);
+ socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
+
+ params_.alternative_service_probability_threshold = 0.75;
+ CreateSession();
+
+ SendRequestAndExpectHttpResponse("hello world");
+ SendRequestAndExpectHttpResponse("hello world");
+}
+
+TEST_P(QuicNetworkTransactionTest,
+ DontUseAlternativeServiceWithBadProbabilityForQuic) {
+ MockRead http_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"),
+ MockRead("Alt-Svc: quic=\":443\";p=2\r\n\r\n"), MockRead("hello world"),
+ MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
+ MockRead(ASYNC, OK)};
+
+ StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
+ 0);
+ socket_factory_.AddSocketDataProvider(&http_data);
+ socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
+ socket_factory_.AddSocketDataProvider(&http_data);
+ socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
+
+ params_.alternative_service_probability_threshold = 0.75;
+ CreateSession();
+
+ SendRequestAndExpectHttpResponse("hello world");
+ SendRequestAndExpectHttpResponse("hello world");
+}
+
TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceForQuicForHttps) {
MockRead http_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"), MockRead(kQuicAlternativeServiceHeader),
@@ -1505,6 +1587,90 @@ TEST_P(QuicNetworkTransactionTest, ConfirmAlternateProtocol) {
alternative_service));
}
+TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolProbabilityForQuic) {
+ params_.parse_alternative_services = false;
+ MockRead http_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"),
+ MockRead(kQuicAlternateProtocol50pctHeader), MockRead("hello world"),
+ MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
+ MockRead(ASYNC, OK)};
+
+ StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
+ 0);
+ socket_factory_.AddSocketDataProvider(&http_data);
+
+ MockQuicData mock_quic_data;
+ mock_quic_data.AddWrite(
+ ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/")));
+ mock_quic_data.AddRead(ConstructResponseHeadersPacket(
+ 1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
+ mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+ mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
+ mock_quic_data.AddRead(ASYNC, 0); // EOF
+
+ mock_quic_data.AddSocketDataToFactory(&socket_factory_);
+
+ // The non-alternate protocol job needs to hang in order to guarantee that
+ // the alternate-protocol job will "win".
+ AddHangingNonAlternateProtocolSocketData();
+
+ params_.alternative_service_probability_threshold = .25;
+ params_.parse_alternative_services = false;
+ CreateSession();
+
+ SendRequestAndExpectHttpResponse("hello world");
+ SendRequestAndExpectQuicResponse("hello!");
+}
+
+TEST_P(QuicNetworkTransactionTest, DontUseAlternateProtocolProbabilityForQuic) {
+ params_.parse_alternative_services = false;
+ MockRead http_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"),
+ MockRead(kQuicAlternateProtocol50pctHeader), MockRead("hello world"),
+ MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
+ MockRead(ASYNC, OK)};
+
+ StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
+ 0);
+ socket_factory_.AddSocketDataProvider(&http_data);
+ socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
+ socket_factory_.AddSocketDataProvider(&http_data);
+ socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
+
+ params_.alternative_service_probability_threshold = .75;
+ CreateSession();
+
+ SendRequestAndExpectHttpResponse("hello world");
+ SendRequestAndExpectHttpResponse("hello world");
+}
+
+TEST_P(QuicNetworkTransactionTest,
+ DontUseAlternateProtocolWithBadProbabilityForQuic) {
+ params_.parse_alternative_services = false;
+ MockRead http_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"),
+ MockRead("Alternate-Protocol: 443:quic,p=2\r\n\r\n"),
+ MockRead("hello world"),
+ MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
+ MockRead(ASYNC, OK)};
+
+ StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
+ 0);
+ socket_factory_.AddSocketDataProvider(&http_data);
+ socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
+ socket_factory_.AddSocketDataProvider(&http_data);
+ socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
+
+ params_.alternative_service_probability_threshold = .75;
+ CreateSession();
+
+ SendRequestAndExpectHttpResponse("hello world");
+ SendRequestAndExpectHttpResponse("hello world");
+}
+
TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolForQuicForHttps) {
params_.parse_alternative_services = false;
MockRead http_reads[] = {
@@ -1591,7 +1757,7 @@ class QuicAltSvcCertificateVerificationTest
AlternativeService alternative_service(QUIC, alternative);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
session_->http_server_properties()->SetAlternativeService(
- origin, alternative_service, expiration);
+ origin, alternative_service, 1.0, expiration);
scoped_ptr<HttpNetworkTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
TestCompletionCallback callback;
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index 626a4d0..e5fcf95 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -2325,7 +2325,7 @@ TEST_P(QuicStreamFactoryTest, RacingConnections) {
AlternativeServiceInfoVector alternative_service_info_vector;
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, expiration));
+ AlternativeServiceInfo(alternative_service1, 1.0, expiration));
http_server_properties_.SetAlternativeServices(
host_port_pair_, alternative_service_info_vector);
@@ -3398,7 +3398,7 @@ TEST_P(QuicStreamFactoryTest, MaybeInitialize) {
AlternativeServiceInfoVector alternative_service_info_vector;
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, expiration));
+ AlternativeServiceInfo(alternative_service1, 1.0, expiration));
http_server_properties_.SetAlternativeServices(
host_port_pair_, alternative_service_info_vector);
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc
index 8307103..c5638680 100644
--- a/net/spdy/spdy_network_transaction_unittest.cc
+++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -112,7 +112,7 @@ void UpdateSpdySessionDependencies(SpdyNetworkTransactionTestParams test_params,
HostPortPair("www.example.org", 80),
AlternativeService(AlternateProtocolFromNextProto(test_params.protocol),
"www.example.org", 443),
- expiration);
+ 1.0, expiration);
}
}