Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(121)

Side by Side Diff: trunk/src/components/data_reduction_proxy/browser/data_reduction_proxy_settings.cc

Issue 307013003: Revert 273810 "Added alternative configuration for the data redu..." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/data_reduction_proxy/browser/data_reduction_proxy_settings. h" 5 #include "components/data_reduction_proxy/browser/data_reduction_proxy_settings. h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/metrics/field_trial.h" 9 #include "base/metrics/field_trial.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "base/prefs/pref_member.h" 11 #include "base/prefs/pref_member.h"
12 #include "base/prefs/pref_service.h" 12 #include "base/prefs/pref_service.h"
13 #include "base/prefs/scoped_user_pref_update.h" 13 #include "base/prefs/scoped_user_pref_update.h"
14 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h" 15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h" 16 #include "base/strings/stringprintf.h"
17 #include "base/strings/utf_string_conversions.h" 17 #include "base/strings/utf_string_conversions.h"
18 #include "components/data_reduction_proxy/browser/data_reduction_proxy_configura tor.h" 18 #include "components/data_reduction_proxy/browser/data_reduction_proxy_configura tor.h"
19 #include "components/data_reduction_proxy/browser/data_reduction_proxy_params.h"
20 #include "components/data_reduction_proxy/common/data_reduction_proxy_pref_names .h" 19 #include "components/data_reduction_proxy/common/data_reduction_proxy_pref_names .h"
21 #include "components/data_reduction_proxy/common/data_reduction_proxy_switches.h " 20 #include "components/data_reduction_proxy/common/data_reduction_proxy_switches.h "
22 #include "crypto/random.h" 21 #include "crypto/random.h"
23 #include "net/base/auth.h" 22 #include "net/base/auth.h"
24 #include "net/base/host_port_pair.h" 23 #include "net/base/host_port_pair.h"
25 #include "net/base/load_flags.h" 24 #include "net/base/load_flags.h"
26 #include "net/base/net_errors.h" 25 #include "net/base/net_errors.h"
27 #include "net/http/http_auth.h" 26 #include "net/http/http_auth.h"
28 #include "net/http/http_auth_cache.h" 27 #include "net/http/http_auth_cache.h"
29 #include "net/http/http_network_session.h" 28 #include "net/http/http_network_session.h"
30 #include "net/http/http_response_headers.h" 29 #include "net/http/http_response_headers.h"
31 #include "net/url_request/url_fetcher.h" 30 #include "net/url_request/url_fetcher.h"
32 #include "net/url_request/url_fetcher_delegate.h" 31 #include "net/url_request/url_fetcher_delegate.h"
33 #include "net/url_request/url_request_context_getter.h" 32 #include "net/url_request/url_request_context_getter.h"
34 #include "net/url_request/url_request_status.h" 33 #include "net/url_request/url_request_status.h"
35 #include "url/gurl.h" 34 #include "url/gurl.h"
36 35
37 36 using base::FieldTrialList;
38 using base::StringPrintf; 37 using base::StringPrintf;
39 38
40 namespace { 39 namespace {
41 40
42 // Key of the UMA DataReductionProxy.StartupState histogram. 41 // Key of the UMA DataReductionProxy.StartupState histogram.
43 const char kUMAProxyStartupStateHistogram[] = 42 const char kUMAProxyStartupStateHistogram[] =
44 "DataReductionProxy.StartupState"; 43 "DataReductionProxy.StartupState";
45 44
46 // Key of the UMA DataReductionProxy.ProbeURL histogram. 45 // Key of the UMA DataReductionProxy.ProbeURL histogram.
47 const char kUMAProxyProbeURL[] = "DataReductionProxy.ProbeURL"; 46 const char kUMAProxyProbeURL[] = "DataReductionProxy.ProbeURL";
48 47
48 const char kEnabled[] = "Enabled";
49
49 // TODO(marq): Factor this string out into a constant here and in 50 // TODO(marq): Factor this string out into a constant here and in
50 // http_auth_handler_spdyproxy. 51 // http_auth_handler_spdyproxy.
51 const char kAuthenticationRealmName[] = "SpdyProxy"; 52 const char kAuthenticationRealmName[] = "SpdyProxy";
52 53
53 int64 GetInt64PrefValue(const base::ListValue& list_value, size_t index) { 54 int64 GetInt64PrefValue(const base::ListValue& list_value, size_t index) {
54 int64 val = 0; 55 int64 val = 0;
55 std::string pref_value; 56 std::string pref_value;
56 bool rv = list_value.GetString(index, &pref_value); 57 bool rv = list_value.GetString(index, &pref_value);
57 DCHECK(rv); 58 DCHECK(rv);
58 if (rv) { 59 if (rv) {
59 rv = base::StringToInt64(pref_value, &val); 60 rv = base::StringToInt64(pref_value, &val);
60 DCHECK(rv); 61 DCHECK(rv);
61 } 62 }
62 return val; 63 return val;
63 } 64 }
64 65
65 } // namespace 66 } // namespace
66 67
67 namespace data_reduction_proxy { 68 namespace data_reduction_proxy {
68 69
69 DataReductionProxySettings::DataReductionProxySettings( 70 bool DataReductionProxySettings::allowed_;
70 DataReductionProxyParams* params) 71 bool DataReductionProxySettings::promo_allowed_;
72
73 // static
74 bool DataReductionProxySettings::IsProxyOriginSetOnCommandLine() {
75 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
76 return command_line.HasSwitch(
77 data_reduction_proxy::switches::kDataReductionProxy);
78 }
79
80 // static
81 bool DataReductionProxySettings::IsProxyKeySetOnCommandLine() {
82 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
83 return command_line.HasSwitch(
84 data_reduction_proxy::switches::kEnableDataReductionProxy);
85 }
86
87 // static
88 bool DataReductionProxySettings::IsIncludedInFieldTrialOrFlags() {
89 return (base::FieldTrialList::FindFullName(
90 "DataCompressionProxyRollout") == kEnabled ||
91 IsProxyOriginSetOnCommandLine());
92 }
93
94 // static
95 void DataReductionProxySettings::SetAllowed(bool allowed) {
96 allowed_ = allowed;
97 }
98
99 // static
100 void DataReductionProxySettings::SetPromoAllowed(bool promo_allowed) {
101 promo_allowed_ = promo_allowed;
102 }
103
104 DataReductionProxySettings::DataReductionProxySettings()
71 : restricted_by_carrier_(false), 105 : restricted_by_carrier_(false),
72 enabled_by_user_(false), 106 enabled_by_user_(false),
73 prefs_(NULL), 107 prefs_(NULL),
74 local_state_prefs_(NULL), 108 local_state_prefs_(NULL),
75 url_request_context_getter_(NULL) { 109 url_request_context_getter_(NULL),
76 DCHECK(params); 110 fallback_allowed_(true) {
77 params_.reset(params);
78 } 111 }
79 112
80 DataReductionProxySettings::~DataReductionProxySettings() { 113 DataReductionProxySettings::~DataReductionProxySettings() {
81 if (params_->allowed()) 114 if (IsDataReductionProxyAllowed())
82 spdy_proxy_auth_enabled_.Destroy(); 115 spdy_proxy_auth_enabled_.Destroy();
83 } 116 }
84 117
85 void DataReductionProxySettings::InitPrefMembers() { 118 void DataReductionProxySettings::InitPrefMembers() {
86 DCHECK(thread_checker_.CalledOnValidThread()); 119 DCHECK(thread_checker_.CalledOnValidThread());
87 spdy_proxy_auth_enabled_.Init( 120 spdy_proxy_auth_enabled_.Init(
88 prefs::kDataReductionProxyEnabled, 121 prefs::kDataReductionProxyEnabled,
89 GetOriginalProfilePrefs(), 122 GetOriginalProfilePrefs(),
90 base::Bind(&DataReductionProxySettings::OnProxyEnabledPrefChange, 123 base::Bind(&DataReductionProxySettings::OnProxyEnabledPrefChange,
91 base::Unretained(this))); 124 base::Unretained(this)));
92 data_reduction_proxy_alternative_enabled_.Init(
93 prefs::kDataReductionProxyAltEnabled,
94 GetOriginalProfilePrefs(),
95 base::Bind(
96 &DataReductionProxySettings::OnProxyAlternativeEnabledPrefChange,
97 base::Unretained(this)));
98 } 125 }
99 126
100 void DataReductionProxySettings::InitDataReductionProxySettings( 127 void DataReductionProxySettings::InitDataReductionProxySettings(
101 PrefService* prefs, 128 PrefService* prefs,
102 PrefService* local_state_prefs, 129 PrefService* local_state_prefs,
103 net::URLRequestContextGetter* url_request_context_getter) { 130 net::URLRequestContextGetter* url_request_context_getter) {
104 DCHECK(thread_checker_.CalledOnValidThread()); 131 DCHECK(thread_checker_.CalledOnValidThread());
105 DCHECK(prefs); 132 DCHECK(prefs);
106 DCHECK(local_state_prefs); 133 DCHECK(local_state_prefs);
107 DCHECK(url_request_context_getter); 134 DCHECK(url_request_context_getter);
108 prefs_ = prefs; 135 prefs_ = prefs;
109 local_state_prefs_ = local_state_prefs; 136 local_state_prefs_ = local_state_prefs;
110 url_request_context_getter_ = url_request_context_getter; 137 url_request_context_getter_ = url_request_context_getter;
111 InitPrefMembers(); 138 InitPrefMembers();
112 RecordDataReductionInit(); 139 RecordDataReductionInit();
113 140
114 // Disable the proxy if it is not allowed to be used. 141 // Disable the proxy if it is not allowed to be used.
115 if (!params_->allowed()) 142 if (!IsDataReductionProxyAllowed())
116 return; 143 return;
117 144
118 AddDefaultProxyBypassRules(); 145 AddDefaultProxyBypassRules();
119 net::NetworkChangeNotifier::AddIPAddressObserver(this); 146 net::NetworkChangeNotifier::AddIPAddressObserver(this);
120 147
121 // We set or reset the proxy pref at startup. 148 // We set or reset the proxy pref at startup.
122 MaybeActivateDataReductionProxy(true); 149 MaybeActivateDataReductionProxy(true);
123 } 150 }
124 151
125 void DataReductionProxySettings::InitDataReductionProxySettings( 152 void DataReductionProxySettings::InitDataReductionProxySettings(
126 PrefService* prefs, 153 PrefService* prefs,
127 PrefService* local_state_prefs, 154 PrefService* local_state_prefs,
128 net::URLRequestContextGetter* url_request_context_getter, 155 net::URLRequestContextGetter* url_request_context_getter,
129 scoped_ptr<DataReductionProxyConfigurator> configurator) { 156 scoped_ptr<DataReductionProxyConfigurator> config) {
130 InitDataReductionProxySettings(prefs, 157 InitDataReductionProxySettings(prefs,
131 local_state_prefs, 158 local_state_prefs,
132 url_request_context_getter); 159 url_request_context_getter);
133 SetProxyConfigurator(configurator.Pass()); 160 SetProxyConfigurator(config.Pass());
134 } 161 }
135 162
136 void DataReductionProxySettings::SetProxyConfigurator( 163 void DataReductionProxySettings::SetProxyConfigurator(
137 scoped_ptr<DataReductionProxyConfigurator> configurator) { 164 scoped_ptr<DataReductionProxyConfigurator> configurator) {
138 DCHECK(configurator); 165 DCHECK(configurator);
139 configurator_ = configurator.Pass(); 166 config_ = configurator.Pass();
140 } 167 }
141 168
142 // static 169 // static
143 void DataReductionProxySettings::InitDataReductionProxySession( 170 void DataReductionProxySettings::InitDataReductionProxySession(
144 net::HttpNetworkSession* session, 171 net::HttpNetworkSession* session,
145 const DataReductionProxyParams* params) { 172 const std::string& key) {
146 // This is a no-op unless the authentication parameters are compiled in. 173 // This is a no-op unless the key is set. (even though values for them may be
147 // (even though values for them may be specified on the command line). 174 // specified on the command line). Authentication will still work if the
148 // Authentication will still work if the command line parameters are used, 175 // command line parameters are used, however there will be a round-trip
149 // however there will be a round-trip overhead for each challenge/response 176 // overhead for each challenge/response (typically once per session).
150 // (typically once per session). 177 // TODO(bengr):Pass a configuration struct into
151 // TODO(bengr):Pass a configuration struct into DataReductionProxyConfigurator's 178 // DataReductionProxyConfigurator's constructor.
152 // constructor. The struct would carry everything in the preprocessor flags. 179 if (key.empty())
180 return;
153 DCHECK(session); 181 DCHECK(session);
154 net::HttpAuthCache* auth_cache = session->http_auth_cache(); 182 net::HttpAuthCache* auth_cache = session->http_auth_cache();
155 DCHECK(auth_cache); 183 DCHECK(auth_cache);
156 InitDataReductionAuthentication(auth_cache, params); 184 InitDataReductionAuthentication(auth_cache, key);
157 } 185 }
158 186
159 // static 187 // static
160 void DataReductionProxySettings::InitDataReductionAuthentication( 188 void DataReductionProxySettings::InitDataReductionAuthentication(
161 net::HttpAuthCache* auth_cache, 189 net::HttpAuthCache* auth_cache,
162 const DataReductionProxyParams* params) { 190 const std::string& key) {
163 DCHECK(auth_cache); 191 DCHECK(auth_cache);
164 DCHECK(params);
165 int64 timestamp = 192 int64 timestamp =
166 (base::Time::Now() - base::Time::UnixEpoch()).InMilliseconds() / 1000; 193 (base::Time::Now() - base::Time::UnixEpoch()).InMilliseconds() / 1000;
167 194
168 DataReductionProxyParams::DataReductionProxyList proxies = 195 DataReductionProxyList proxies = GetDataReductionProxies();
169 params->GetAllowedProxies(); 196 for (DataReductionProxyList::iterator it = proxies.begin();
170 for (DataReductionProxyParams::DataReductionProxyList::iterator it = 197 it != proxies.end(); ++it) {
171 proxies.begin();
172 it != proxies.end(); ++it) {
173 GURL auth_origin = (*it).GetOrigin(); 198 GURL auth_origin = (*it).GetOrigin();
174
175 int32 rand[3]; 199 int32 rand[3];
176 crypto::RandBytes(rand, 3 * sizeof(rand[0])); 200 crypto::RandBytes(rand, 3 * sizeof(rand[0]));
177 201
178 std::string realm = 202 std::string realm =
179 base::StringPrintf("%s%lld", kAuthenticationRealmName, 203 base::StringPrintf("%s%lld", kAuthenticationRealmName,
180 static_cast<long long>(timestamp)); 204 static_cast<long long>(timestamp));
181 std::string challenge = base::StringPrintf( 205 std::string challenge = base::StringPrintf(
182 "%s realm=\"%s\", ps=\"%lld-%u-%u-%u\"", 206 "%s realm=\"%s\", ps=\"%lld-%u-%u-%u\"",
183 kAuthenticationRealmName, 207 kAuthenticationRealmName,
184 realm.data(), 208 realm.data(),
185 static_cast<long long>(timestamp), 209 static_cast<long long>(timestamp),
186 rand[0], 210 rand[0],
187 rand[1], 211 rand[1],
188 rand[2]); 212 rand[2]);
189 base::string16 password = AuthHashForSalt(timestamp, params->key()); 213 base::string16 password = AuthHashForSalt(timestamp, key);
190 214
191 DVLOG(1) << "origin: [" << auth_origin << "] realm: [" << realm 215 DVLOG(1) << "origin: [" << auth_origin << "] realm: [" << realm
192 << "] challenge: [" << challenge << "] password: [" << password << "]"; 216 << "] challenge: [" << challenge << "] password: [" << password << "]";
193 217
194 net::AuthCredentials credentials(base::string16(), password); 218 net::AuthCredentials credentials(base::string16(), password);
195 // |HttpAuthController| searches this cache by origin and path, the latter 219 // |HttpAuthController| searches this cache by origin and path, the latter
196 // being '/' in the case of the data reduction proxy. 220 // being '/' in the case of the data reduction proxy.
197 auth_cache->Add(auth_origin, 221 auth_cache->Add(auth_origin,
198 realm, 222 realm,
199 net::HttpAuth::AUTH_SCHEME_SPDYPROXY, 223 net::HttpAuth::AUTH_SCHEME_SPDYPROXY,
200 challenge, 224 challenge,
201 credentials, 225 credentials,
202 std::string("/")); 226 std::string("/"));
203 } 227 }
204 } 228 }
205 229
230 // TODO(bengr): Use a configuration struct to carry field trial state as well.
231 // static
232 bool DataReductionProxySettings::IsDataReductionProxyAllowed() {
233 return allowed_;
234 }
235
236 // static
237 bool DataReductionProxySettings::IsDataReductionProxyPromoAllowed() {
238 return IsProxyOriginSetOnCommandLine() ||
239 (IsDataReductionProxyAllowed() && promo_allowed_);
240 }
241
242 // static
243 bool DataReductionProxySettings::IsPreconnectHintingAllowed() {
244 if (!IsDataReductionProxyAllowed())
245 return false;
246 return FieldTrialList::FindFullName("DataCompressionProxyPreconnectHints") ==
247 kEnabled;
248 }
249
250 // static
251 std::string DataReductionProxySettings::GetDataReductionProxyOrigin() {
252 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
253 if (command_line.HasSwitch(switches::kDataReductionProxyDev))
254 return command_line.GetSwitchValueASCII(switches::kDataReductionProxyDev);
255 if (command_line.HasSwitch(switches::kDataReductionProxy))
256 return command_line.GetSwitchValueASCII(switches::kDataReductionProxy);
257 #if defined(DATA_REDUCTION_DEV_HOST)
258 if (FieldTrialList::FindFullName("DataCompressionProxyDevRollout") ==
259 kEnabled) {
260 return DATA_REDUCTION_DEV_HOST;
261 }
262 #endif
263 #if defined(SPDY_PROXY_AUTH_ORIGIN)
264 return SPDY_PROXY_AUTH_ORIGIN;
265 #else
266 return std::string();
267 #endif
268 }
269
270 // static
271 std::string DataReductionProxySettings::GetDataReductionProxyFallback() {
272 // Regardless of what else is defined, only return a value if the main proxy
273 // origin is defined.
274 if (GetDataReductionProxyOrigin().empty())
275 return std::string();
276 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
277 if (command_line.HasSwitch(switches::kDataReductionProxyFallback)) {
278 return command_line.GetSwitchValueASCII(
279 switches::kDataReductionProxyFallback);
280 }
281 #if defined(DATA_REDUCTION_FALLBACK_HOST)
282 return DATA_REDUCTION_FALLBACK_HOST;
283 #else
284 return std::string();
285 #endif
286 }
287
288 // static
206 bool DataReductionProxySettings::IsAcceptableAuthChallenge( 289 bool DataReductionProxySettings::IsAcceptableAuthChallenge(
207 net::AuthChallengeInfo* auth_info) { 290 net::AuthChallengeInfo* auth_info) {
208 // Challenge realm must start with the authentication realm name. 291 // Challenge realm must start with the authentication realm name.
209 std::string realm_prefix = 292 std::string realm_prefix =
210 auth_info->realm.substr(0, strlen(kAuthenticationRealmName)); 293 auth_info->realm.substr(0, strlen(kAuthenticationRealmName));
211 if (realm_prefix != kAuthenticationRealmName) 294 if (realm_prefix != kAuthenticationRealmName)
212 return false; 295 return false;
213 296
214 // The challenger must be one of the configured proxies. 297 // The challenger must be one of the configured proxies.
215 DataReductionProxyParams::DataReductionProxyList proxies = 298 DataReductionProxyList proxies = GetDataReductionProxies();
216 params_->GetAllowedProxies(); 299 for (DataReductionProxyList::iterator it = proxies.begin();
217 for (DataReductionProxyParams::DataReductionProxyList::iterator it =
218 proxies.begin();
219 it != proxies.end(); ++it) { 300 it != proxies.end(); ++it) {
220 net::HostPortPair origin_host = net::HostPortPair::FromURL(*it); 301 net::HostPortPair origin_host = net::HostPortPair::FromURL(*it);
221 if (origin_host.Equals(auth_info->challenger)) 302 if (origin_host.Equals(auth_info->challenger))
222 return true; 303 return true;
223 } 304 }
224 return false; 305 return false;
225 } 306 }
226 307
227 base::string16 DataReductionProxySettings::GetTokenForAuthChallenge( 308 base::string16 DataReductionProxySettings::GetTokenForAuthChallenge(
228 net::AuthChallengeInfo* auth_info) { 309 net::AuthChallengeInfo* auth_info) {
229 if (auth_info->realm.length() > strlen(kAuthenticationRealmName)) { 310 if (auth_info->realm.length() > strlen(kAuthenticationRealmName)) {
230 int64 salt; 311 int64 salt;
231 std::string realm_suffix = 312 std::string realm_suffix =
232 auth_info->realm.substr(strlen(kAuthenticationRealmName)); 313 auth_info->realm.substr(strlen(kAuthenticationRealmName));
233 if (base::StringToInt64(realm_suffix, &salt)) { 314 if (base::StringToInt64(realm_suffix, &salt)) {
234 return AuthHashForSalt(salt, params_->key()); 315 return AuthHashForSalt(salt, key_);
235 } else { 316 } else {
236 DVLOG(1) << "Unable to parse realm name " << auth_info->realm 317 DVLOG(1) << "Unable to parse realm name " << auth_info->realm
237 << "into an int for salting."; 318 << "into an int for salting.";
238 return base::string16(); 319 return base::string16();
239 } 320 }
240 } else { 321 } else {
241 return base::string16(); 322 return base::string16();
242 } 323 }
243 } 324 }
244 325
245 bool DataReductionProxySettings::IsDataReductionProxyEnabled() { 326 bool DataReductionProxySettings::IsDataReductionProxyEnabled() {
246 return spdy_proxy_auth_enabled_.GetValue() || 327 return spdy_proxy_auth_enabled_.GetValue() ||
247 DataReductionProxyParams::IsKeySetOnCommandLine(); 328 IsProxyKeySetOnCommandLine();
248 }
249
250 bool DataReductionProxySettings::IsDataReductionProxyAlternativeEnabled() {
251 return data_reduction_proxy_alternative_enabled_.GetValue();
252 } 329 }
253 330
254 bool DataReductionProxySettings::IsDataReductionProxyManaged() { 331 bool DataReductionProxySettings::IsDataReductionProxyManaged() {
255 return spdy_proxy_auth_enabled_.IsManaged(); 332 return spdy_proxy_auth_enabled_.IsManaged();
256 } 333 }
257 334
335 // static
336 DataReductionProxySettings::DataReductionProxyList
337 DataReductionProxySettings::GetDataReductionProxies() {
338 DataReductionProxyList proxies;
339 std::string proxy = GetDataReductionProxyOrigin();
340 std::string fallback = GetDataReductionProxyFallback();
341
342 if (!proxy.empty())
343 proxies.push_back(GURL(proxy));
344
345 if (!fallback.empty()) {
346 // Sanity check: fallback isn't the only proxy.
347 DCHECK(!proxies.empty());
348 proxies.push_back(GURL(fallback));
349 }
350
351 return proxies;
352 }
353
258 void DataReductionProxySettings::SetDataReductionProxyEnabled(bool enabled) { 354 void DataReductionProxySettings::SetDataReductionProxyEnabled(bool enabled) {
259 DCHECK(thread_checker_.CalledOnValidThread()); 355 DCHECK(thread_checker_.CalledOnValidThread());
260 // Prevent configuring the proxy when it is not allowed to be used. 356 // Prevent configuring the proxy when it is not allowed to be used.
261 if (!params_->allowed()) 357 if (!IsDataReductionProxyAllowed())
262 return; 358 return;
263 359
264 if (spdy_proxy_auth_enabled_.GetValue() != enabled) { 360 if (spdy_proxy_auth_enabled_.GetValue() != enabled) {
265 spdy_proxy_auth_enabled_.SetValue(enabled); 361 spdy_proxy_auth_enabled_.SetValue(enabled);
266 OnProxyEnabledPrefChange(); 362 OnProxyEnabledPrefChange();
267 } 363 }
268 } 364 }
269 365
270 void DataReductionProxySettings::SetDataReductionProxyAlternativeEnabled(
271 bool enabled) {
272 DCHECK(thread_checker_.CalledOnValidThread());
273 // Prevent configuring the proxy when it is not allowed to be used.
274 if (!params_->alternative_allowed())
275 return;
276 if (data_reduction_proxy_alternative_enabled_.GetValue() != enabled) {
277 data_reduction_proxy_alternative_enabled_.SetValue(enabled);
278 OnProxyAlternativeEnabledPrefChange();
279 }
280 }
281
282 int64 DataReductionProxySettings::GetDataReductionLastUpdateTime() { 366 int64 DataReductionProxySettings::GetDataReductionLastUpdateTime() {
283 DCHECK(thread_checker_.CalledOnValidThread()); 367 DCHECK(thread_checker_.CalledOnValidThread());
284 PrefService* local_state = GetLocalStatePrefs(); 368 PrefService* local_state = GetLocalStatePrefs();
285 int64 last_update_internal = 369 int64 last_update_internal =
286 local_state->GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate); 370 local_state->GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate);
287 base::Time last_update = base::Time::FromInternalValue(last_update_internal); 371 base::Time last_update = base::Time::FromInternalValue(last_update_internal);
288 return static_cast<int64>(last_update.ToJsTime()); 372 return static_cast<int64>(last_update.ToJsTime());
289 } 373 }
290 374
291 DataReductionProxySettings::ContentLengthList 375 DataReductionProxySettings::ContentLengthList
(...skipping 24 matching lines...) Expand all
316 if ("OK" == response.substr(0, 2)) { 400 if ("OK" == response.substr(0, 2)) {
317 DVLOG(1) << "The data reduction proxy is unrestricted."; 401 DVLOG(1) << "The data reduction proxy is unrestricted.";
318 402
319 if (enabled_by_user_) { 403 if (enabled_by_user_) {
320 if (restricted_by_carrier_) { 404 if (restricted_by_carrier_) {
321 // The user enabled the proxy, but sometime previously in the session, 405 // The user enabled the proxy, but sometime previously in the session,
322 // the network operator had blocked the canary and restricted the user. 406 // the network operator had blocked the canary and restricted the user.
323 // The current network doesn't block the canary, so don't restrict the 407 // The current network doesn't block the canary, so don't restrict the
324 // proxy configurations. 408 // proxy configurations.
325 SetProxyConfigs(true /* enabled */, 409 SetProxyConfigs(true /* enabled */,
326 IsDataReductionProxyAlternativeEnabled(),
327 false /* restricted */, 410 false /* restricted */,
328 false /* at_startup */); 411 false /* at_startup */);
329 RecordProbeURLFetchResult(SUCCEEDED_PROXY_ENABLED); 412 RecordProbeURLFetchResult(SUCCEEDED_PROXY_ENABLED);
330 } else { 413 } else {
331 RecordProbeURLFetchResult(SUCCEEDED_PROXY_ALREADY_ENABLED); 414 RecordProbeURLFetchResult(SUCCEEDED_PROXY_ALREADY_ENABLED);
332 } 415 }
333 } 416 }
334 restricted_by_carrier_ = false; 417 restricted_by_carrier_ = false;
335 return; 418 return;
336 } 419 }
337 DVLOG(1) << "The data reduction proxy is restricted to the configured " 420 DVLOG(1) << "The data reduction proxy is restricted to the configured "
338 << "fallback proxy."; 421 << "fallback proxy.";
339 if (enabled_by_user_) { 422 if (enabled_by_user_) {
340 if (!restricted_by_carrier_) { 423 if (!restricted_by_carrier_) {
341 // Restrict the proxy. 424 // Restrict the proxy.
342 SetProxyConfigs(true /* enabled */, 425 SetProxyConfigs(true /* enabled */,
343 IsDataReductionProxyAlternativeEnabled(),
344 true /* restricted */, 426 true /* restricted */,
345 false /* at_startup */); 427 false /* at_startup */);
346 RecordProbeURLFetchResult(FAILED_PROXY_DISABLED); 428 RecordProbeURLFetchResult(FAILED_PROXY_DISABLED);
347 } else { 429 } else {
348 RecordProbeURLFetchResult(FAILED_PROXY_ALREADY_DISABLED); 430 RecordProbeURLFetchResult(FAILED_PROXY_ALREADY_DISABLED);
349 } 431 }
350 } 432 }
351 restricted_by_carrier_ = true; 433 restricted_by_carrier_ = true;
352 } 434 }
353 435
354 PrefService* DataReductionProxySettings::GetOriginalProfilePrefs() { 436 void DataReductionProxySettings::OnIPAddressChanged() {
355 DCHECK(thread_checker_.CalledOnValidThread()); 437 DCHECK(thread_checker_.CalledOnValidThread());
356 return prefs_; 438 if (enabled_by_user_) {
439 DCHECK(IsDataReductionProxyAllowed());
440 ProbeWhetherDataReductionProxyIsAvailable();
441 }
357 } 442 }
358 443
359 PrefService* DataReductionProxySettings::GetLocalStatePrefs() { 444 void DataReductionProxySettings::OnProxyEnabledPrefChange() {
360 DCHECK(thread_checker_.CalledOnValidThread()); 445 DCHECK(thread_checker_.CalledOnValidThread());
361 return local_state_prefs_; 446 if (!DataReductionProxySettings::IsDataReductionProxyAllowed())
447 return;
448 MaybeActivateDataReductionProxy(false);
362 } 449 }
363 450
364 void DataReductionProxySettings::AddDefaultProxyBypassRules() { 451 void DataReductionProxySettings::AddDefaultProxyBypassRules() {
365 // localhost 452 // localhost
366 configurator_->AddHostPatternToBypass("<local>"); 453 config_->AddHostPatternToBypass("<local>");
367 // RFC1918 private addresses. 454 // RFC1918 private addresses.
368 configurator_->AddHostPatternToBypass("10.0.0.0/8"); 455 config_->AddHostPatternToBypass("10.0.0.0/8");
369 configurator_->AddHostPatternToBypass("172.16.0.0/12"); 456 config_->AddHostPatternToBypass("172.16.0.0/12");
370 configurator_->AddHostPatternToBypass("192.168.0.0/16"); 457 config_->AddHostPatternToBypass("192.168.0.0/16");
371 // RFC4193 private addresses. 458 // RFC4193 private addresses.
372 configurator_->AddHostPatternToBypass("fc00::/7"); 459 config_->AddHostPatternToBypass("fc00::/7");
373 // IPV6 probe addresses. 460 // IPV6 probe addresses.
374 configurator_->AddHostPatternToBypass("*-ds.metric.gstatic.com"); 461 config_->AddHostPatternToBypass("*-ds.metric.gstatic.com");
375 configurator_->AddHostPatternToBypass("*-v4.metric.gstatic.com"); 462 config_->AddHostPatternToBypass("*-v4.metric.gstatic.com");
376 } 463 }
377 464
378 void DataReductionProxySettings::LogProxyState( 465 void DataReductionProxySettings::LogProxyState(
379 bool enabled, bool restricted, bool at_startup) { 466 bool enabled, bool restricted, bool at_startup) {
380 // This must stay a LOG(WARNING); the output is used in processing customer 467 // This must stay a LOG(WARNING); the output is used in processing customer
381 // feedback. 468 // feedback.
382 const char kAtStartup[] = "at startup"; 469 const char kAtStartup[] = "at startup";
383 const char kByUser[] = "by user action"; 470 const char kByUser[] = "by user action";
384 const char kOn[] = "ON"; 471 const char kOn[] = "ON";
385 const char kOff[] = "OFF"; 472 const char kOff[] = "OFF";
386 const char kRestricted[] = "(Restricted)"; 473 const char kRestricted[] = "(Restricted)";
387 const char kUnrestricted[] = "(Unrestricted)"; 474 const char kUnrestricted[] = "(Unrestricted)";
388 475
389 std::string annotated_on = 476 std::string annotated_on =
390 kOn + std::string(" ") + (restricted ? kRestricted : kUnrestricted); 477 kOn + std::string(" ") + (restricted ? kRestricted : kUnrestricted);
391 478
392 LOG(WARNING) << "SPDY proxy " << (enabled ? annotated_on : kOff) 479 LOG(WARNING) << "SPDY proxy " << (enabled ? annotated_on : kOff)
393 << " " << (at_startup ? kAtStartup : kByUser); 480 << " " << (at_startup ? kAtStartup : kByUser);
394 } 481 }
395 482
396 void DataReductionProxySettings::OnIPAddressChanged() { 483 PrefService* DataReductionProxySettings::GetOriginalProfilePrefs() {
397 DCHECK(thread_checker_.CalledOnValidThread()); 484 DCHECK(thread_checker_.CalledOnValidThread());
398 if (enabled_by_user_) { 485 return prefs_;
399 DCHECK(params_->allowed());
400 ProbeWhetherDataReductionProxyIsAvailable();
401 }
402 } 486 }
403 487
404 void DataReductionProxySettings::OnProxyEnabledPrefChange() { 488 PrefService* DataReductionProxySettings::GetLocalStatePrefs() {
405 DCHECK(thread_checker_.CalledOnValidThread()); 489 DCHECK(thread_checker_.CalledOnValidThread());
406 if (!params_->allowed()) 490 return local_state_prefs_;
407 return;
408 MaybeActivateDataReductionProxy(false);
409 }
410
411 void DataReductionProxySettings::OnProxyAlternativeEnabledPrefChange() {
412 DCHECK(thread_checker_.CalledOnValidThread());
413 if (!params_->alternative_allowed())
414 return;
415 MaybeActivateDataReductionProxy(false);
416 } 491 }
417 492
418 void DataReductionProxySettings::ResetDataReductionStatistics() { 493 void DataReductionProxySettings::ResetDataReductionStatistics() {
419 DCHECK(thread_checker_.CalledOnValidThread()); 494 DCHECK(thread_checker_.CalledOnValidThread());
420 PrefService* prefs = GetLocalStatePrefs(); 495 PrefService* prefs = GetLocalStatePrefs();
421 if (!prefs) 496 if (!prefs)
422 return; 497 return;
423 ListPrefUpdate original_update(prefs, prefs::kDailyHttpOriginalContentLength); 498 ListPrefUpdate original_update(prefs, prefs::kDailyHttpOriginalContentLength);
424 ListPrefUpdate received_update(prefs, prefs::kDailyHttpReceivedContentLength); 499 ListPrefUpdate received_update(prefs, prefs::kDailyHttpReceivedContentLength);
425 original_update->Clear(); 500 original_update->Clear();
426 received_update->Clear(); 501 received_update->Clear();
427 for (size_t i = 0; i < kNumDaysInHistory; ++i) { 502 for (size_t i = 0; i < kNumDaysInHistory; ++i) {
428 original_update->AppendString(base::Int64ToString(0)); 503 original_update->AppendString(base::Int64ToString(0));
429 received_update->AppendString(base::Int64ToString(0)); 504 received_update->AppendString(base::Int64ToString(0));
430 } 505 }
431 } 506 }
432 507
433 void DataReductionProxySettings::MaybeActivateDataReductionProxy( 508 void DataReductionProxySettings::MaybeActivateDataReductionProxy(
434 bool at_startup) { 509 bool at_startup) {
435 DCHECK(thread_checker_.CalledOnValidThread()); 510 DCHECK(thread_checker_.CalledOnValidThread());
436 PrefService* prefs = GetOriginalProfilePrefs(); 511 PrefService* prefs = GetOriginalProfilePrefs();
437 // TODO(marq): Consider moving this so stats are wiped the first time the 512 // TODO(marq): Consider moving this so stats are wiped the first time the
438 // proxy settings are actually (not maybe) turned on. 513 // proxy settings are actually (not maybe) turned on.
439 if (spdy_proxy_auth_enabled_.GetValue() && 514 if (spdy_proxy_auth_enabled_.GetValue() &&
440 !prefs->GetBoolean(prefs::kDataReductionProxyWasEnabledBefore)) { 515 !prefs->GetBoolean(prefs::kDataReductionProxyWasEnabledBefore)) {
441 prefs->SetBoolean(prefs::kDataReductionProxyWasEnabledBefore, true); 516 prefs->SetBoolean(prefs::kDataReductionProxyWasEnabledBefore, true);
442 ResetDataReductionStatistics(); 517 ResetDataReductionStatistics();
443 } 518 }
444 519
445 // Configure use of the data reduction proxy if it is enabled. 520 std::string proxy = GetDataReductionProxyOrigin();
446 enabled_by_user_= IsDataReductionProxyEnabled(); 521 // Configure use of the data reduction proxy if it is enabled and the proxy
447 SetProxyConfigs(enabled_by_user_, 522 // origin is non-empty.
448 IsDataReductionProxyAlternativeEnabled(), 523 enabled_by_user_= IsDataReductionProxyEnabled() && !proxy.empty();
449 restricted_by_carrier_, 524 SetProxyConfigs(enabled_by_user_, restricted_by_carrier_, at_startup);
450 at_startup);
451 525
452 // Check if the proxy has been restricted explicitly by the carrier. 526 // Check if the proxy has been restricted explicitly by the carrier.
453 if (enabled_by_user_) 527 if (enabled_by_user_)
454 ProbeWhetherDataReductionProxyIsAvailable(); 528 ProbeWhetherDataReductionProxyIsAvailable();
455 } 529 }
456 530
457 void DataReductionProxySettings::SetProxyConfigs(bool enabled, 531 void DataReductionProxySettings::SetProxyConfigs(
458 bool alternative_enabled, 532 bool enabled, bool restricted, bool at_startup) {
459 bool restricted,
460 bool at_startup) {
461 DCHECK(thread_checker_.CalledOnValidThread()); 533 DCHECK(thread_checker_.CalledOnValidThread());
534 // If |restricted| is true and there is no defined fallback proxy.
535 // treat this as a disable.
536 std::string fallback = GetDataReductionProxyFallback();
537 if (fallback.empty() && enabled && restricted)
538 enabled = false;
539
462 LogProxyState(enabled, restricted, at_startup); 540 LogProxyState(enabled, restricted, at_startup);
463 // The alternative is only configured if the standard configuration is
464 // is enabled.
465 if (enabled) { 541 if (enabled) {
466 if (alternative_enabled) { 542 config_->Enable(restricted,
467 configurator_->Enable(restricted, 543 !fallback_allowed_,
468 !params_->fallback_allowed(), 544 GetDataReductionProxyOrigin(),
469 params_->alt_origin().spec(), 545 fallback);
470 params_->alt_fallback_origin().spec(),
471 params_->ssl_origin().spec());
472 } else {
473 configurator_->Enable(restricted,
474 !params_->fallback_allowed(),
475 params_->origin().spec(),
476 params_->fallback_origin().spec(),
477 std::string());
478 }
479 } else { 546 } else {
480 configurator_->Disable(); 547 config_->Disable();
481 } 548 }
482 } 549 }
483 550
484 // Metrics methods 551 // Metrics methods
485 void DataReductionProxySettings::RecordDataReductionInit() { 552 void DataReductionProxySettings::RecordDataReductionInit() {
486 DCHECK(thread_checker_.CalledOnValidThread()); 553 DCHECK(thread_checker_.CalledOnValidThread());
487 ProxyStartupState state = PROXY_NOT_AVAILABLE; 554 ProxyStartupState state = PROXY_NOT_AVAILABLE;
488 if (params_->allowed()) { 555 if (IsDataReductionProxyAllowed()) {
489 if (IsDataReductionProxyEnabled()) 556 if (IsDataReductionProxyEnabled())
490 state = PROXY_ENABLED; 557 state = PROXY_ENABLED;
491 else 558 else
492 state = PROXY_DISABLED; 559 state = PROXY_DISABLED;
493 } 560 }
494 561
495 RecordStartupState(state); 562 RecordStartupState(state);
496 } 563 }
497 564
498 void DataReductionProxySettings::RecordProbeURLFetchResult( 565 void DataReductionProxySettings::RecordProbeURLFetchResult(
499 ProbeURLFetchResult result) { 566 ProbeURLFetchResult result) {
500 UMA_HISTOGRAM_ENUMERATION(kUMAProxyProbeURL, 567 UMA_HISTOGRAM_ENUMERATION(kUMAProxyProbeURL,
501 result, 568 result,
502 PROBE_URL_FETCH_RESULT_COUNT); 569 PROBE_URL_FETCH_RESULT_COUNT);
503 } 570 }
504 571
505 void DataReductionProxySettings::RecordStartupState(ProxyStartupState state) { 572 void DataReductionProxySettings::RecordStartupState(ProxyStartupState state) {
506 UMA_HISTOGRAM_ENUMERATION(kUMAProxyStartupStateHistogram, 573 UMA_HISTOGRAM_ENUMERATION(kUMAProxyStartupStateHistogram,
507 state, 574 state,
508 PROXY_STARTUP_STATE_COUNT); 575 PROXY_STARTUP_STATE_COUNT);
509 } 576 }
510 577
511 void DataReductionProxySettings::ResetParamsForTest(
512 DataReductionProxyParams* params) {
513 params_.reset(params);
514 }
515
516 DataReductionProxySettings::ContentLengthList 578 DataReductionProxySettings::ContentLengthList
517 DataReductionProxySettings::GetDailyContentLengths(const char* pref_name) { 579 DataReductionProxySettings::GetDailyContentLengths(const char* pref_name) {
518 DCHECK(thread_checker_.CalledOnValidThread()); 580 DCHECK(thread_checker_.CalledOnValidThread());
519 DataReductionProxySettings::ContentLengthList content_lengths; 581 DataReductionProxySettings::ContentLengthList content_lengths;
520 const base::ListValue* list_value = GetLocalStatePrefs()->GetList(pref_name); 582 const base::ListValue* list_value = GetLocalStatePrefs()->GetList(pref_name);
521 if (list_value->GetSize() == kNumDaysInHistory) { 583 if (list_value->GetSize() == kNumDaysInHistory) {
522 for (size_t i = 0; i < kNumDaysInHistory; ++i) { 584 for (size_t i = 0; i < kNumDaysInHistory; ++i) {
523 content_lengths.push_back(GetInt64PrefValue(*list_value, i)); 585 content_lengths.push_back(GetInt64PrefValue(*list_value, i));
524 } 586 }
525 } 587 }
526 return content_lengths; 588 return content_lengths;
527 } 589 }
528 590
529 void DataReductionProxySettings::GetContentLengths( 591 void DataReductionProxySettings::GetContentLengths(
530 unsigned int days, 592 unsigned int days,
531 int64* original_content_length, 593 int64* original_content_length,
532 int64* received_content_length, 594 int64* received_content_length,
533 int64* last_update_time) { 595 int64* last_update_time) {
534 DCHECK(thread_checker_.CalledOnValidThread()); 596 DCHECK(thread_checker_.CalledOnValidThread());
535 DCHECK_LE(days, kNumDaysInHistory); 597 DCHECK_LE(days, kNumDaysInHistory);
536 PrefService* local_state = GetLocalStatePrefs(); 598 PrefService* local_state = GetLocalStatePrefs();
537 if (!local_state) { 599 if (!local_state) {
(...skipping 23 matching lines...) Expand all
561 i < kNumDaysInHistory; ++i) { 623 i < kNumDaysInHistory; ++i) {
562 orig += GetInt64PrefValue(*original_list, i); 624 orig += GetInt64PrefValue(*original_list, i);
563 recv += GetInt64PrefValue(*received_list, i); 625 recv += GetInt64PrefValue(*received_list, i);
564 } 626 }
565 *original_content_length = orig; 627 *original_content_length = orig;
566 *received_content_length = recv; 628 *received_content_length = recv;
567 *last_update_time = 629 *last_update_time =
568 local_state->GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate); 630 local_state->GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate);
569 } 631 }
570 632
633 std::string DataReductionProxySettings::GetProxyCheckURL() {
634 if (!IsDataReductionProxyAllowed())
635 return std::string();
636 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
637 if (command_line.HasSwitch(switches::kDataReductionProxyProbeURL)) {
638 return command_line.GetSwitchValueASCII(
639 switches::kDataReductionProxyProbeURL);
640 }
641 #if defined(DATA_REDUCTION_PROXY_PROBE_URL)
642 return DATA_REDUCTION_PROXY_PROBE_URL;
643 #else
644 return std::string();
645 #endif
646 }
647
571 // static 648 // static
572 base::string16 DataReductionProxySettings::AuthHashForSalt( 649 base::string16 DataReductionProxySettings::AuthHashForSalt(
573 int64 salt, 650 int64 salt,
574 const std::string& key) { 651 const std::string& key) {
652 std::string active_key;
653
654 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
655 if (command_line.HasSwitch(switches::kDataReductionProxy)) {
656 // If an origin is provided via a switch, then only consider the value
657 // that is provided by a switch. Do not use the preprocessor constant.
658 // Don't expose |key_| to a proxy passed in via the command line.
659 if (!command_line.HasSwitch(switches::kDataReductionProxyKey))
660 return base::string16();
661 active_key = command_line.GetSwitchValueASCII(
662 switches::kDataReductionProxyKey);
663 } else {
664 active_key = key;
665 }
666 DCHECK(!active_key.empty());
667
575 std::string salted_key = 668 std::string salted_key =
576 base::StringPrintf("%lld%s%lld", 669 base::StringPrintf("%lld%s%lld",
577 static_cast<long long>(salt), 670 static_cast<long long>(salt),
578 key.c_str(), 671 active_key.c_str(),
579 static_cast<long long>(salt)); 672 static_cast<long long>(salt));
580 return base::UTF8ToUTF16(base::MD5String(salted_key)); 673 return base::UTF8ToUTF16(base::MD5String(salted_key));
581 } 674 }
582 675
583 net::URLFetcher* DataReductionProxySettings::GetURLFetcher() { 676 net::URLFetcher* DataReductionProxySettings::GetURLFetcher() {
584 DCHECK(url_request_context_getter_); 677 DCHECK(url_request_context_getter_);
585 net::URLFetcher* fetcher = net::URLFetcher::Create(params_->probe_url(), 678 std::string url = GetProxyCheckURL();
679 if (url.empty())
680 return NULL;
681 net::URLFetcher* fetcher = net::URLFetcher::Create(GURL(url),
586 net::URLFetcher::GET, 682 net::URLFetcher::GET,
587 this); 683 this);
588 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE | net::LOAD_BYPASS_PROXY); 684 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE | net::LOAD_BYPASS_PROXY);
589 fetcher->SetRequestContext(url_request_context_getter_); 685 fetcher->SetRequestContext(url_request_context_getter_);
590 // Configure max retries to be at most kMaxRetries times for 5xx errors. 686 // Configure max retries to be at most kMaxRetries times for 5xx errors.
591 static const int kMaxRetries = 5; 687 static const int kMaxRetries = 5;
592 fetcher->SetMaxRetriesOn5xx(kMaxRetries); 688 fetcher->SetMaxRetriesOn5xx(kMaxRetries);
593 return fetcher; 689 return fetcher;
594 } 690 }
595 691
596 void DataReductionProxySettings::ProbeWhetherDataReductionProxyIsAvailable() { 692 void DataReductionProxySettings::ProbeWhetherDataReductionProxyIsAvailable() {
597 net::URLFetcher* fetcher = GetURLFetcher(); 693 net::URLFetcher* fetcher = GetURLFetcher();
598 if (!fetcher) 694 if (!fetcher)
599 return; 695 return;
600 fetcher_.reset(fetcher); 696 fetcher_.reset(fetcher);
601 fetcher_->Start(); 697 fetcher_->Start();
602 } 698 }
603 699
604 } // namespace data_reduction_proxy 700 } // namespace data_reduction_proxy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698