Chromium Code Reviews| Index: chrome/browser/net/spdyproxy/data_reduction_proxy_settings.cc |
| diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_settings.cc b/chrome/browser/net/spdyproxy/data_reduction_proxy_settings.cc |
| index 4318d770545b5b7eb7818aaf49d33ad3db4b43d6..fe86a08257e5b895c50dde524a3158ce1413022c 100644 |
| --- a/chrome/browser/net/spdyproxy/data_reduction_proxy_settings.cc |
| +++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_settings.cc |
| @@ -21,9 +21,13 @@ |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/pref_names.h" |
| +#include "crypto/random.h" |
| +#include "net/base/auth.h" |
| #include "net/base/host_port_pair.h" |
| #include "net/base/load_flags.h" |
| #include "net/base/net_errors.h" |
| +#include "net/http/http_auth.h" |
| +#include "net/http/http_network_session.h" |
| #include "net/url_request/url_fetcher.h" |
| #include "net/url_request/url_fetcher_delegate.h" |
| #include "net/url_request/url_request_status.h" |
| @@ -47,6 +51,10 @@ enum ProxyStartupState { |
| const char kEnabled[] = "Enabled"; |
| +// TODO(marq): factor this string out into a constant here and in |
|
bengr
2013/10/22 17:49:30
Factor
marq (ping after 24h)
2013/10/22 21:18:01
Done.
|
| +// http_auth_handler_spdyproxy. |
| +const char kAuthenticationRealmName[] = "SpdyProxy"; |
| + |
| int64 GetInt64PrefValue(const ListValue& list_value, size_t index) { |
| int64 val = 0; |
| std::string pref_value; |
| @@ -107,6 +115,42 @@ void DataReductionProxySettings::InitDataReductionProxySettings() { |
| } |
| } |
| +void DataReductionProxySettings::InitDataReductionProxySession( |
| + net::HttpNetworkSession* session) { |
|
bengr
2013/10/22 17:49:30
indent +2
marq (ping after 24h)
2013/10/22 21:18:01
Done.
|
| +// This is a no-op unless the authentication params are compiled in. |
|
bengr
2013/10/22 17:49:30
parameters
marq (ping after 24h)
2013/10/22 21:18:01
Done.
|
| +// (even though values for them may be specified on the command line). |
|
bengr
2013/10/22 17:49:30
It's probably worth saying that when specified in
marq (ping after 24h)
2013/10/22 21:18:01
Done.
|
| +#if defined(SPDY_PROXY_AUTH_ORIGIN) && defined(SPDY_PROXY_AUTH_VALUE) |
| + DCHECK(session); |
| + int64 timestamp = |
| + (base::Time::Now() - base::Time::UnixEpoch()).InMilliseconds() / 1000; |
|
bengr
2013/10/22 17:49:30
indent -1
marq (ping after 24h)
2013/10/22 21:18:01
Done.
|
| + |
| + DataReductionProxyList proxies = GetDataReductionProxies(); |
| + for (DataReductionProxyList::iterator it = proxies.begin(); |
| + it != proxies.end(); ++it) { |
| + net::HostPortPair auth_origin = *it; |
|
bengr
2013/10/22 17:49:30
const ref?
marq (ping after 24h)
2013/10/22 21:18:01
Yes, but the code's changed slightly.
|
| + int32 rand1, rand2, rand3; |
| + crypto::RandBytes(&rand1, sizeof(rand1)); |
| + crypto::RandBytes(&rand2, sizeof(rand2)); |
| + crypto::RandBytes(&rand3, sizeof(rand3)); |
| + |
| + std::string realm = |
| + base::StringPrintf("%s%lld", kAuthenticationRealmName, timestamp); |
| + std::string challenge = base::StringPrintf( |
| + "%s realm=\"%s\", ps=\"%lld-%u-%u-%u\"", |
| + kAuthenticationRealmName, realm.data(), timestamp, rand1, rand2, rand3); |
| + base::string16 password = AuthHashForSalt(timestamp); |
| + |
| + DVLOG(1) << "origin: [" << auth_origin.ToString() << "] realm: [" << realm |
| + << "] challenge: [" << challenge << "] password: [" << password << "]"; |
| + |
| + net::AuthCredentials credentials(base::string16(), password); |
| + session->http_auth_cache()->Add(GURL(auth_origin.ToString()), realm, |
| + net::HttpAuth::AUTH_SCHEME_SPDYPROXY, |
| + challenge, credentials, std::string("/")); |
| + } |
| +#endif // defined(SPDY_PROXY_AUTH_ORIGIN) && defined(SPDY_PROXY_AUTH_VALUE) |
| +} |
| + |
| void DataReductionProxySettings::AddHostPatternToBypass( |
| const std::string& pattern) { |
| bypass_rules_.push_back(pattern); |
| @@ -143,31 +187,55 @@ std::string DataReductionProxySettings::GetDataReductionProxyOrigin() { |
| const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| if (command_line.HasSwitch(switches::kSpdyProxyAuthOrigin)) |
| return command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthOrigin); |
| -#if defined(SPDY_PROXY_AUTH_ORIGIN) |
| - return SPDY_PROXY_AUTH_ORIGIN; |
| -#else |
| - return std::string(); |
| -#endif |
| + return GetDefaultProxyHost(); |
| } |
| -std::string DataReductionProxySettings::GetDataReductionProxyAuth() { |
| - if (!IsDataReductionProxyAllowed()) |
| +std::string DataReductionProxySettings::GetDataReductionProxyFallback() { |
| + // Regardless of what else is defined, only return a value if the main proxy |
| + // origin is defined. |
| + if (GetDataReductionProxyOrigin().empty()) |
| return std::string(); |
| const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| - if (command_line.HasSwitch(switches::kSpdyProxyAuthOrigin)) { |
| - // If an origin is provided via a switch, then only consider the value |
| - // that is provided by a switch. Do not use the preprocessor constant. |
| - // Don't expose SPDY_PROXY_AUTH_VALUE to a proxy passed in via the command |
| - // line. |
| - if (command_line.HasSwitch(switches::kSpdyProxyAuthValue)) |
| - return command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthValue); |
| - return std::string(); |
| + if (command_line.HasSwitch(switches::kSpdyProxyAuthFallback)) |
| + return command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthFallback); |
| + return GetDefaultFallbackProxyHost(); |
| +} |
| + |
| +bool DataReductionProxySettings::IsAcceptableAuthChallenge( |
| + net::AuthChallengeInfo* auth_info) { |
| + // Challenge realm must start with the authentication realm name. |
| + std::string realm_prefix = |
| + auth_info->realm.substr(0, strlen(kAuthenticationRealmName)); |
| + if (realm_prefix != kAuthenticationRealmName) |
| + return false; |
| + |
| + // The challenger must be one of the configured proxies. |
| + DataReductionProxyList proxies = GetDataReductionProxies(); |
| + for (DataReductionProxyList::iterator it = proxies.begin(); |
| + it != proxies.end(); ++it) { |
| + net::HostPortPair origin_host = *it; |
| + if (origin_host.Equals(auth_info->challenger)) |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| +base::string16 DataReductionProxySettings::GetTokenForAuthChallenge( |
| + net::AuthChallengeInfo* auth_info) { |
| + if (auth_info->realm.length() > strlen(kAuthenticationRealmName)) { |
| + int64 salt; |
| + std::string realm_suffix = |
| + auth_info->realm.substr(strlen(kAuthenticationRealmName)); |
| + if (base::StringToInt64(realm_suffix, &salt)) { |
| + return AuthHashForSalt(salt); |
| + } else { |
| + DVLOG(1) << "Unable to parse realm name " << auth_info->realm |
| + << "into an int for salting."; |
| + return base::string16(); |
| + } |
| + } else { |
| + return base::string16(); |
| } |
| -#if defined(SPDY_PROXY_AUTH_VALUE) |
| - return SPDY_PROXY_AUTH_VALUE; |
| -#else |
| - return std::string(); |
| -#endif |
| } |
| bool DataReductionProxySettings::IsDataReductionProxyEnabled() { |
| @@ -178,6 +246,24 @@ bool DataReductionProxySettings::IsDataReductionProxyManaged() { |
| return spdy_proxy_auth_enabled_.IsManaged(); |
| } |
| +DataReductionProxySettings::DataReductionProxyList |
| +DataReductionProxySettings::GetDataReductionProxies() { |
| + DataReductionProxyList proxies; |
| + std::string proxy = GetDataReductionProxyOrigin(); |
| + std::string fallback = GetDataReductionProxyFallback(); |
| + |
| + if (!proxy.empty()) |
| + proxies.push_back(net::HostPortPair::FromURL(GURL(proxy))); |
| + |
| + if (!fallback.empty()) { |
| + // Sanity check: fallback isn't the only proxy. |
| + DCHECK(!proxies.empty()); |
| + proxies.push_back(net::HostPortPair::FromURL(GURL(fallback))); |
| + } |
| + |
| + return proxies; |
| +} |
| + |
| void DataReductionProxySettings::SetDataReductionProxyEnabled(bool enabled) { |
| // Prevent configuring the proxy when it is not allowed to be used. |
| if (!IsDataReductionProxyAllowed()) |
| @@ -195,12 +281,12 @@ int64 DataReductionProxySettings::GetDataReductionLastUpdateTime() { |
| return static_cast<int64>(last_update.ToJsTime()); |
| } |
| -std::vector<long long> |
| +DataReductionProxySettings::ContentLengthList |
| DataReductionProxySettings::GetDailyOriginalContentLengths() { |
| return GetDailyContentLengths(prefs::kDailyHttpOriginalContentLength); |
| } |
| -std::vector<long long> |
| +DataReductionProxySettings::ContentLengthList |
| DataReductionProxySettings::GetDailyReceivedContentLengths() { |
| return GetDailyContentLengths(prefs::kDailyHttpReceivedContentLength); |
| } |
| @@ -237,17 +323,6 @@ void DataReductionProxySettings::OnURLFetchComplete( |
| disabled_by_carrier_ = true; |
| } |
| -std::string DataReductionProxySettings::GetDataReductionProxyOriginHostPort() { |
| - std::string spdy_proxy = GetDataReductionProxyOrigin(); |
| - if (spdy_proxy.empty()) { |
| - DLOG(ERROR) << "A SPDY proxy has not been set."; |
| - return spdy_proxy; |
| - } |
| - // Remove a trailing slash from the proxy string if one exists as well as |
| - // leading HTTPS scheme. |
| - return net::HostPortPair::FromURL(GURL(spdy_proxy)).ToString(); |
| -} |
| - |
| void DataReductionProxySettings::OnIPAddressChanged() { |
| if (enabled_by_user_) { |
| DCHECK(IsDataReductionProxyAllowed()); |
| @@ -284,6 +359,22 @@ void DataReductionProxySettings::LogProxyState(bool enabled, bool at_startup) { |
| << " " << (at_startup ? kAtStartup : kByUser); |
| } |
| +std::string DataReductionProxySettings::GetDefaultProxyHost() { |
|
bengr
2013/10/22 17:49:30
Why isn't the handling of command line switch valu
marq (ping after 24h)
2013/10/22 21:18:01
These two methods are used so that unit tests can
|
| +#if defined(SPDY_PROXY_AUTH_ORIGIN) |
| + return SPDY_PROXY_AUTH_ORIGIN; |
| +#else |
| + return std::string(); |
| +#endif |
| +} |
| + |
| +std::string DataReductionProxySettings::GetDefaultFallbackProxyHost() { |
| +#if defined(DATA_REDUCTION_FALLBACK_HOST) |
| + return DATA_REDUCTION_FALLBACK_HOST; |
|
bengr
2013/10/22 17:49:30
why not check in this function if GetDefaultProxyH
marq (ping after 24h)
2013/10/22 21:18:01
I don't think the default value here is of necessi
|
| +#else |
| + return std::string(); |
| +#endif |
| +} |
| + |
| PrefService* DataReductionProxySettings::GetOriginalProfilePrefs() { |
| return g_browser_process->profile_manager()->GetLastUsedProfile()-> |
| GetOriginalProfile()->GetPrefs(); |
| @@ -324,12 +415,10 @@ void DataReductionProxySettings::MaybeActivateDataReductionProxy( |
| ResetDataReductionStatistics(); |
| } |
| - std::string spdy_proxy_origin = GetDataReductionProxyOriginHostPort(); |
| - |
| + std::string proxy = GetDataReductionProxyOrigin(); |
| // Configure use of the data reduction proxy if it is enabled and the proxy |
| // origin is non-empty. |
| - enabled_by_user_= |
| - spdy_proxy_auth_enabled_.GetValue() && !spdy_proxy_origin.empty(); |
| + enabled_by_user_= spdy_proxy_auth_enabled_.GetValue() && !proxy.empty(); |
| SetProxyConfigs(enabled_by_user_ && !disabled_by_carrier_, at_startup); |
| // Check if the proxy has been disabled explicitly by the carrier. |
| @@ -345,8 +434,11 @@ void DataReductionProxySettings::SetProxyConfigs(bool enabled, |
| DictionaryPrefUpdate update(prefs, prefs::kProxy); |
| base::DictionaryValue* dict = update.Get(); |
| if (enabled) { |
| + std::string fallback = GetDataReductionProxyFallback(); |
| std::string proxy_server_config = |
| - "http=" + GetDataReductionProxyOrigin() + ",direct://;"; |
| + "http=" + GetDataReductionProxyOrigin() + |
| + (fallback.empty() ? "" : "," + fallback) + |
| + ",direct://;"; |
| dict->SetString("server", proxy_server_config); |
| dict->SetString("mode", |
| ProxyModeToString(ProxyPrefs::MODE_FIXED_SERVERS)); |
| @@ -436,6 +528,36 @@ std::string DataReductionProxySettings::GetProxyCheckURL() { |
| #endif |
| } |
| +base::string16 DataReductionProxySettings::AuthHashForSalt(int64 salt) { |
| + if (!IsDataReductionProxyAllowed()) |
| + return base::string16(); |
| + |
| + std::string key; |
| + |
| + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| + if (command_line.HasSwitch(switches::kSpdyProxyAuthOrigin)) { |
| + // If an origin is provided via a switch, then only consider the value |
| + // that is provided by a switch. Do not use the preprocessor constant. |
| + // Don't expose SPDY_PROXY_AUTH_VALUE to a proxy passed in via the command |
| + // line. |
| + if (!command_line.HasSwitch(switches::kSpdyProxyAuthValue)) |
| + return base::string16(); |
| + key = command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthValue); |
| + } else { |
| +#if defined(SPDY_PROXY_AUTH_VALUE) |
| + key = SPDY_PROXY_AUTH_VALUE; |
| +#else |
| + return base::string16(); |
| +#endif |
| + } |
| + |
| + DCHECK(!key.empty()); |
| + |
| + std::string salted_key = |
| + base::StringPrintf("%lld%s%lld", salt, key.c_str(), salt); |
| + return UTF8ToUTF16(base::MD5String(salted_key)); |
| +} |
| + |
| net::URLFetcher* DataReductionProxySettings::GetURLFetcher() { |
| std::string url = GetProxyCheckURL(); |
| if (url.empty()) |