diff options
author | anthonyvd <anthonyvd@chromium.org> | 2016-03-07 14:03:57 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-07 22:05:33 +0000 |
commit | 5b168c11bb7e574c6386f1857d58e5e4cad5e25a (patch) | |
tree | aef7addfa6b6c88f655994975c79180d608dde17 | |
parent | 7e6264ce0f355de7894f8bbc525b55cd85ccfbb9 (diff) | |
download | chromium_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}
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( ¶ms->parse_alternative_services); globals.enable_alternative_service_with_different_host.CopyToIfSet( ¶ms->enable_alternative_service_with_different_host); + globals.alternative_service_probability_threshold.CopyToIfSet( + ¶ms->alternative_service_probability_threshold); globals.enable_npn.CopyToIfSet(¶ms->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(¶ms); + EXPECT_EQ(.5, params.alternative_service_probability_threshold); +} + +TEST_F(IOThreadTest, AlternativeServiceProbabilityThresholdFromEnableQuicFlag) { + command_line_.AppendSwitch("enable-quic"); + + ConfigureQuicGlobals(); + net::HttpNetworkSession::Params params; + InitializeNetworkSessionParams(¶ms); + 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(¶ms); + 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(¶ms); + 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( ¶ms->parse_alternative_services); globals.enable_alternative_service_with_different_host.CopyToIfSet( ¶ms->enable_alternative_service_with_different_host); + globals.alternative_service_probability_threshold.CopyToIfSet( + ¶ms->alternative_service_probability_threshold); globals.enable_npn.CopyToIfSet(¶ms->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); } } |