• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "components/data_reduction_proxy/browser/data_reduction_proxy_settings.h"
6 
7 #include "base/command_line.h"
8 #include "base/md5.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "components/data_reduction_proxy/browser/data_reduction_proxy_params.h"
12 #include "components/data_reduction_proxy/browser/data_reduction_proxy_settings_test_utils.h"
13 #include "components/data_reduction_proxy/common/data_reduction_proxy_pref_names.h"
14 #include "components/data_reduction_proxy/common/data_reduction_proxy_switches.h"
15 #include "net/http/http_auth.h"
16 #include "net/http/http_auth_cache.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "url/gurl.h"
20 
21 namespace {
22 
23 const char kDataReductionProxy[] = "https://foo.com:443/";
24 const char kDataReductionProxyDev[] = "http://foo-dev.com:80";
25 const char kDataReductionProxyFallback[] = "http://bar.com:80";
26 const char kDataReductionProxyKey[] = "12345";
27 const char kDataReductionProxyAlt[] = "https://alt.com:443/";
28 const char kDataReductionProxyAltFallback[] = "http://alt2.com:80";
29 const char kDataReductionProxySSL[] = "http://ssl.com:80";
30 
31 const char kProbeURLWithOKResponse[] = "http://ok.org/";
32 const char kProbeURLWithBadResponse[] = "http://bad.org/";
33 const char kProbeURLWithNoResponse[] = "http://no.org/";
34 const char kWarmupURLWithNoContentResponse[] = "http://warm.org/";
35 
36 }  // namespace
37 
38 namespace data_reduction_proxy {
39 
40 class DataReductionProxySettingsTest
41     : public ConcreteDataReductionProxySettingsTest<
42           DataReductionProxySettings> {
43 };
44 
45 
TEST_F(DataReductionProxySettingsTest,TestAuthenticationInit)46 TEST_F(DataReductionProxySettingsTest, TestAuthenticationInit) {
47   net::HttpAuthCache cache;
48   DataReductionProxyParams drp_params(
49       DataReductionProxyParams::kAllowed |
50       DataReductionProxyParams::kFallbackAllowed |
51       DataReductionProxyParams::kPromoAllowed);
52   drp_params.set_key(kDataReductionProxyKey);
53   DataReductionProxySettings::InitDataReductionAuthentication(
54       &cache, &drp_params);
55   DataReductionProxyParams::DataReductionProxyList proxies =
56       drp_params.GetAllowedProxies();
57   for (DataReductionProxyParams::DataReductionProxyList::iterator it =
58            proxies.begin();  it != proxies.end(); ++it) {
59     net::HttpAuthCache::Entry* entry = cache.LookupByPath(*it,
60                                                           std::string("/"));
61     EXPECT_TRUE(entry != NULL);
62     EXPECT_EQ(net::HttpAuth::AUTH_SCHEME_SPDYPROXY, entry->scheme());
63     EXPECT_EQ("SpdyProxy", entry->auth_challenge().substr(0,9));
64   }
65   GURL bad_server = GURL("https://bad.proxy.com/");
66   net::HttpAuthCache::Entry* entry =
67       cache.LookupByPath(bad_server, std::string());
68   EXPECT_TRUE(entry == NULL);
69 }
70 
TEST_F(DataReductionProxySettingsTest,TestGetDataReductionProxyOrigin)71 TEST_F(DataReductionProxySettingsTest, TestGetDataReductionProxyOrigin) {
72   // SetUp() adds the origin to the command line, which should be returned here.
73   std::string result =
74       settings_->params()->origin().spec();
75   EXPECT_EQ(GURL(kDataReductionProxy), GURL(result));
76 }
77 
TEST_F(DataReductionProxySettingsTest,TestGetDataReductionProxyDevOrigin)78 TEST_F(DataReductionProxySettingsTest, TestGetDataReductionProxyDevOrigin) {
79   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
80       switches::kDataReductionProxyDev, kDataReductionProxyDev);
81   ResetSettings(true, true, false, true);
82   std::string result =
83       settings_->params()->origin().spec();
84   EXPECT_EQ(GURL(kDataReductionProxyDev), GURL(result));
85 }
86 
87 
TEST_F(DataReductionProxySettingsTest,TestGetDataReductionProxies)88 TEST_F(DataReductionProxySettingsTest, TestGetDataReductionProxies) {
89   DataReductionProxyParams drp_params(
90       DataReductionProxyParams::kAllowed |
91       DataReductionProxyParams::kFallbackAllowed |
92       DataReductionProxyParams::kPromoAllowed);
93   DataReductionProxyParams::DataReductionProxyList proxies =
94       drp_params.GetAllowedProxies();
95 
96   unsigned int expected_proxy_size = 2u;
97   EXPECT_EQ(expected_proxy_size, proxies.size());
98 
99   // Command line proxies have precedence, so even if there were other values
100   // compiled in, these should be the ones in the list.
101   EXPECT_EQ("foo.com", proxies[0].host());
102   EXPECT_EQ(443 ,proxies[0].EffectiveIntPort());
103   EXPECT_EQ("bar.com", proxies[1].host());
104   EXPECT_EQ(80, proxies[1].EffectiveIntPort());
105 }
106 
TEST_F(DataReductionProxySettingsTest,TestAuthHashGeneration)107 TEST_F(DataReductionProxySettingsTest, TestAuthHashGeneration) {
108   std::string salt = "8675309";  // Jenny's number to test the hash generator.
109   std::string salted_key = salt + kDataReductionProxyKey + salt;
110   base::string16 expected_hash = base::UTF8ToUTF16(base::MD5String(salted_key));
111   EXPECT_EQ(expected_hash,
112             DataReductionProxySettings::AuthHashForSalt(
113                 8675309, kDataReductionProxyKey));
114 }
115 
TEST_F(DataReductionProxySettingsTest,TestSetProxyConfigs)116 TEST_F(DataReductionProxySettingsTest, TestSetProxyConfigs) {
117   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
118       switches::kDataReductionProxyAlt, kDataReductionProxyAlt);
119   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
120       switches::kDataReductionProxyAltFallback, kDataReductionProxyAltFallback);
121   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
122       switches::kDataReductionSSLProxy, kDataReductionProxySSL);
123   ResetSettings(true, true, true, true);
124   TestDataReductionProxyConfig* config =
125       static_cast<TestDataReductionProxyConfig*>(
126           settings_->configurator());
127 
128   settings_->SetProxyConfigs(true, true, false, false);
129   EXPECT_TRUE(config->enabled_);
130   EXPECT_TRUE(net::HostPortPair::FromString(kDataReductionProxyAlt).Equals(
131                   net::HostPortPair::FromString(config->origin_)));
132   EXPECT_TRUE(
133       net::HostPortPair::FromString(kDataReductionProxyAltFallback).Equals(
134           net::HostPortPair::FromString(config->fallback_origin_)));
135   EXPECT_TRUE(net::HostPortPair::FromString(kDataReductionProxySSL).Equals(
136                   net::HostPortPair::FromString(config->ssl_origin_)));
137 
138   settings_->SetProxyConfigs(true, false, false, false);
139   EXPECT_TRUE(config->enabled_);
140   EXPECT_TRUE(net::HostPortPair::FromString(kDataReductionProxy).Equals(
141                   net::HostPortPair::FromString(config->origin_)));
142   EXPECT_TRUE(net::HostPortPair::FromString(kDataReductionProxyFallback).Equals(
143                   net::HostPortPair::FromString(config->fallback_origin_)));
144   EXPECT_EQ("", config->ssl_origin_);
145 
146   settings_->SetProxyConfigs(false, true, false, false);
147   EXPECT_FALSE(config->enabled_);
148   EXPECT_EQ("", config->origin_);
149   EXPECT_EQ("", config->fallback_origin_);
150   EXPECT_EQ("", config->ssl_origin_);
151 
152   settings_->SetProxyConfigs(false, false, false, false);
153   EXPECT_FALSE(config->enabled_);
154   EXPECT_EQ("", config->origin_);
155   EXPECT_EQ("", config->fallback_origin_);
156   EXPECT_EQ("", config->ssl_origin_);
157 }
158 
TEST_F(DataReductionProxySettingsTest,TestIsProxyEnabledOrManaged)159 TEST_F(DataReductionProxySettingsTest, TestIsProxyEnabledOrManaged) {
160   settings_->InitPrefMembers();
161   base::MessageLoopForUI loop;
162   // The proxy is disabled initially.
163   settings_->enabled_by_user_ = false;
164   settings_->SetProxyConfigs(false, false, false, false);
165 
166   EXPECT_FALSE(settings_->IsDataReductionProxyEnabled());
167   EXPECT_FALSE(settings_->IsDataReductionProxyManaged());
168 
169   CheckOnPrefChange(true, true, false);
170   EXPECT_TRUE(settings_->IsDataReductionProxyEnabled());
171   EXPECT_FALSE(settings_->IsDataReductionProxyManaged());
172 
173   CheckOnPrefChange(true, true, true);
174   EXPECT_TRUE(settings_->IsDataReductionProxyEnabled());
175   EXPECT_TRUE(settings_->IsDataReductionProxyManaged());
176 
177   base::MessageLoop::current()->RunUntilIdle();
178 }
179 
TEST_F(DataReductionProxySettingsTest,TestAcceptableChallenges)180 TEST_F(DataReductionProxySettingsTest, TestAcceptableChallenges) {
181   typedef struct {
182     std::string host;
183     std::string realm;
184     bool expected_to_succeed;
185   } challenge_test;
186 
187   challenge_test tests[] = {
188     {"foo.com:443", "", false},                 // 0. No realm.
189     {"foo.com:443", "xxx", false},              // 1. Wrong realm.
190     {"foo.com:443", "spdyproxy", false},        // 2. Case matters.
191     {"foo.com:443", "SpdyProxy", true},         // 3. OK.
192     {"foo.com:443", "SpdyProxy1234567", true},  // 4. OK
193     {"bar.com:80", "SpdyProxy1234567", true},   // 5. OK.
194     {"foo.com:443", "SpdyProxyxxx", true},      // 6. OK
195     {"", "SpdyProxy1234567", false},            // 7. No challenger.
196     {"xxx.net:443", "SpdyProxy1234567", false}, // 8. Wrong host.
197     {"foo.com", "SpdyProxy1234567", false},     // 9. No port.
198     {"foo.com:80", "SpdyProxy1234567", false},  // 10.Wrong port.
199     {"bar.com:81", "SpdyProxy1234567", false},  // 11.Wrong port.
200   };
201 
202   for (int i = 0; i <= 11; ++i) {
203     scoped_refptr<net::AuthChallengeInfo> auth_info(new net::AuthChallengeInfo);
204     auth_info->challenger = net::HostPortPair::FromString(tests[i].host);
205     auth_info->realm = tests[i].realm;
206     EXPECT_EQ(tests[i].expected_to_succeed,
207               settings_->IsAcceptableAuthChallenge(auth_info.get()));
208   }
209 }
210 
TEST_F(DataReductionProxySettingsTest,TestChallengeTokens)211 TEST_F(DataReductionProxySettingsTest, TestChallengeTokens) {
212   typedef struct {
213     std::string realm;
214     bool expected_empty_token;
215   } token_test;
216 
217   token_test tests[] = {
218     {"", true},                  // 0. No realm.
219     {"xxx", true},               // 1. realm too short.
220     {"spdyproxy", true},         // 2. no salt.
221     {"SpdyProxyxxx", true},      // 3. Salt not an int.
222     {"SpdyProxy1234567", false}, // 4. OK
223   };
224 
225   for (int i = 0; i <= 4; ++i) {
226     scoped_refptr<net::AuthChallengeInfo> auth_info(new net::AuthChallengeInfo);
227     auth_info->challenger =
228         net::HostPortPair::FromString(kDataReductionProxy);
229     auth_info->realm = tests[i].realm;
230     base::string16 token = settings_->GetTokenForAuthChallenge(auth_info.get());
231     EXPECT_EQ(tests[i].expected_empty_token, token.empty());
232   }
233 }
234 
TEST_F(DataReductionProxySettingsTest,TestResetDataReductionStatistics)235 TEST_F(DataReductionProxySettingsTest, TestResetDataReductionStatistics) {
236   int64 original_content_length;
237   int64 received_content_length;
238   int64 last_update_time;
239   settings_->ResetDataReductionStatistics();
240   settings_->GetContentLengths(kNumDaysInHistory,
241                                &original_content_length,
242                                &received_content_length,
243                                &last_update_time);
244   EXPECT_EQ(0L, original_content_length);
245   EXPECT_EQ(0L, received_content_length);
246   EXPECT_EQ(last_update_time_.ToInternalValue(), last_update_time);
247 }
248 
TEST_F(DataReductionProxySettingsTest,TestContentLengths)249 TEST_F(DataReductionProxySettingsTest, TestContentLengths) {
250   int64 original_content_length;
251   int64 received_content_length;
252   int64 last_update_time;
253 
254   // Request |kNumDaysInHistory| days.
255   settings_->GetContentLengths(kNumDaysInHistory,
256                                &original_content_length,
257                                &received_content_length,
258                                &last_update_time);
259   const unsigned int days = kNumDaysInHistory;
260   // Received content length history values are 0 to |kNumDaysInHistory - 1|.
261   int64 expected_total_received_content_length = (days - 1L) * days / 2;
262   // Original content length history values are 0 to
263   // |2 * (kNumDaysInHistory - 1)|.
264   long expected_total_original_content_length = (days - 1L) * days;
265   EXPECT_EQ(expected_total_original_content_length, original_content_length);
266   EXPECT_EQ(expected_total_received_content_length, received_content_length);
267   EXPECT_EQ(last_update_time_.ToInternalValue(), last_update_time);
268 
269   // Request |kNumDaysInHistory - 1| days.
270   settings_->GetContentLengths(kNumDaysInHistory - 1,
271                                &original_content_length,
272                                &received_content_length,
273                                &last_update_time);
274   expected_total_received_content_length -= (days - 1);
275   expected_total_original_content_length -= 2 * (days - 1);
276   EXPECT_EQ(expected_total_original_content_length, original_content_length);
277   EXPECT_EQ(expected_total_received_content_length, received_content_length);
278 
279   // Request 0 days.
280   settings_->GetContentLengths(0,
281                                &original_content_length,
282                                &received_content_length,
283                                &last_update_time);
284   expected_total_received_content_length = 0;
285   expected_total_original_content_length = 0;
286   EXPECT_EQ(expected_total_original_content_length, original_content_length);
287   EXPECT_EQ(expected_total_received_content_length, received_content_length);
288 
289   // Request 1 day. First day had 0 bytes so should be same as 0 days.
290   settings_->GetContentLengths(1,
291                                &original_content_length,
292                                &received_content_length,
293                                &last_update_time);
294   EXPECT_EQ(expected_total_original_content_length, original_content_length);
295   EXPECT_EQ(expected_total_received_content_length, received_content_length);
296 }
297 
298 // TODO(marq): Add a test to verify that MaybeActivateDataReductionProxy
299 // is called when the pref in |settings_| is enabled.
TEST_F(DataReductionProxySettingsTest,TestMaybeActivateDataReductionProxy)300 TEST_F(DataReductionProxySettingsTest, TestMaybeActivateDataReductionProxy) {
301   // Initialize the pref member in |settings_| without the usual callback
302   // so it won't trigger MaybeActivateDataReductionProxy when the pref value
303   // is set.
304   settings_->spdy_proxy_auth_enabled_.Init(
305       prefs::kDataReductionProxyEnabled,
306       settings_->GetOriginalProfilePrefs());
307   settings_->data_reduction_proxy_alternative_enabled_.Init(
308       prefs::kDataReductionProxyAltEnabled,
309       settings_->GetOriginalProfilePrefs());
310 
311   // TODO(bengr): Test enabling/disabling while a probe is outstanding.
312   base::MessageLoopForUI loop;
313   // The proxy is enabled and unrestructed initially.
314   // Request succeeded but with bad response, expect proxy to be restricted.
315   CheckProbe(true,
316              kProbeURLWithBadResponse,
317              kWarmupURLWithNoContentResponse,
318              "Bad",
319              true,
320              true,
321              true,
322              false);
323   // Request succeeded with valid response, expect proxy to be unrestricted.
324   CheckProbe(true,
325              kProbeURLWithOKResponse,
326              kWarmupURLWithNoContentResponse,
327              "OK",
328              true,
329              true,
330              false,
331              false);
332   // Request failed, expect proxy to be enabled but restricted.
333   CheckProbe(true,
334              kProbeURLWithNoResponse,
335              kWarmupURLWithNoContentResponse,
336              "",
337              false,
338              true,
339              true,
340              false);
341   // The proxy is disabled initially. Probes should not be emitted to change
342   // state.
343   CheckProbe(false,
344              kProbeURLWithOKResponse,
345              kWarmupURLWithNoContentResponse,
346              "OK",
347              true,
348              false,
349              false,
350              false);
351 }
352 
TEST_F(DataReductionProxySettingsTest,TestOnIPAddressChanged)353 TEST_F(DataReductionProxySettingsTest, TestOnIPAddressChanged) {
354   base::MessageLoopForUI loop;
355   // The proxy is enabled initially.
356   pref_service_.SetBoolean(prefs::kDataReductionProxyEnabled, true);
357   settings_->spdy_proxy_auth_enabled_.Init(
358       prefs::kDataReductionProxyEnabled,
359       settings_->GetOriginalProfilePrefs());
360   settings_->data_reduction_proxy_alternative_enabled_.Init(
361       prefs::kDataReductionProxyAltEnabled,
362       settings_->GetOriginalProfilePrefs());
363   settings_->enabled_by_user_ = true;
364   settings_->restricted_by_carrier_ = false;
365   settings_->SetProxyConfigs(true, false, false, true);
366   // IP address change triggers a probe that succeeds. Proxy remains
367   // unrestricted.
368   CheckProbeOnIPChange(kProbeURLWithOKResponse,
369                        kWarmupURLWithNoContentResponse,
370                        "OK",
371                        true,
372                        false,
373                        false);
374   // IP address change triggers a probe that fails. Proxy is restricted.
375   CheckProbeOnIPChange(kProbeURLWithBadResponse,
376                        kWarmupURLWithNoContentResponse,
377                        "Bad",
378                        true,
379                        true,
380                        false);
381   // IP address change triggers a probe that fails. Proxy remains restricted.
382   CheckProbeOnIPChange(kProbeURLWithBadResponse,
383                        kWarmupURLWithNoContentResponse,
384                        "Bad",
385                        true,
386                        true,
387                        false);
388   // IP address change triggers a probe that succeed. Proxy is unrestricted.
389   CheckProbeOnIPChange(kProbeURLWithBadResponse,
390                        kWarmupURLWithNoContentResponse,
391                        "OK",
392                        true,
393                        false,
394                        false);
395 }
396 
TEST_F(DataReductionProxySettingsTest,TestOnProxyEnabledPrefChange)397 TEST_F(DataReductionProxySettingsTest, TestOnProxyEnabledPrefChange) {
398   settings_->InitPrefMembers();
399   base::MessageLoopForUI loop;
400   // The proxy is enabled initially.
401   settings_->enabled_by_user_ = true;
402   settings_->SetProxyConfigs(true, false, false, true);
403   // The pref is disabled, so correspondingly should be the proxy.
404   CheckOnPrefChange(false, false, false);
405   // The pref is enabled, so correspondingly should be the proxy.
406   CheckOnPrefChange(true, true, false);
407 }
408 
TEST_F(DataReductionProxySettingsTest,TestInitDataReductionProxyOn)409 TEST_F(DataReductionProxySettingsTest, TestInitDataReductionProxyOn) {
410   MockSettings* settings = static_cast<MockSettings*>(settings_.get());
411   EXPECT_CALL(*settings, RecordStartupState(PROXY_ENABLED));
412 
413   pref_service_.SetBoolean(prefs::kDataReductionProxyEnabled, true);
414   CheckInitDataReductionProxy(true);
415 }
416 
TEST_F(DataReductionProxySettingsTest,TestInitDataReductionProxyOff)417 TEST_F(DataReductionProxySettingsTest, TestInitDataReductionProxyOff) {
418   // InitDataReductionProxySettings with the preference off will directly call
419   // LogProxyState.
420   MockSettings* settings = static_cast<MockSettings*>(settings_.get());
421   EXPECT_CALL(*settings, RecordStartupState(PROXY_DISABLED));
422 
423   pref_service_.SetBoolean(prefs::kDataReductionProxyEnabled, false);
424   CheckInitDataReductionProxy(false);
425 }
426 
TEST_F(DataReductionProxySettingsTest,TestSetProxyFromCommandLine)427 TEST_F(DataReductionProxySettingsTest, TestSetProxyFromCommandLine) {
428   MockSettings* settings = static_cast<MockSettings*>(settings_.get());
429   EXPECT_CALL(*settings, RecordStartupState(PROXY_ENABLED));
430 
431   CommandLine::ForCurrentProcess()->AppendSwitch(
432       switches::kEnableDataReductionProxy);
433   CheckInitDataReductionProxy(true);
434 }
435 
TEST_F(DataReductionProxySettingsTest,TestGetDailyContentLengths)436 TEST_F(DataReductionProxySettingsTest, TestGetDailyContentLengths) {
437   DataReductionProxySettings::ContentLengthList result =
438       settings_->GetDailyContentLengths(prefs::kDailyHttpOriginalContentLength);
439 
440   ASSERT_FALSE(result.empty());
441   ASSERT_EQ(kNumDaysInHistory, result.size());
442 
443   for (size_t i = 0; i < kNumDaysInHistory; ++i) {
444     long expected_length =
445         static_cast<long>((kNumDaysInHistory - 1 - i) * 2);
446     ASSERT_EQ(expected_length, result[i]);
447   }
448 }
449 
TEST_F(DataReductionProxySettingsTest,CheckInitMetricsWhenNotAllowed)450 TEST_F(DataReductionProxySettingsTest, CheckInitMetricsWhenNotAllowed) {
451   // No call to |AddProxyToCommandLine()| was made, so the proxy feature
452   // should be unavailable.
453   base::MessageLoopForUI loop;
454   // Clear the command line. Setting flags can force the proxy to be allowed.
455   CommandLine::ForCurrentProcess()->InitFromArgv(0, NULL);
456 
457   ResetSettings(false, false, false, false);
458   MockSettings* settings = static_cast<MockSettings*>(settings_.get());
459   EXPECT_FALSE(settings->params()->allowed());
460   EXPECT_CALL(*settings, RecordStartupState(PROXY_NOT_AVAILABLE));
461 
462   scoped_ptr<DataReductionProxyConfigurator> configurator(
463       new TestDataReductionProxyConfig());
464   settings_->SetProxyConfigurator(configurator.Pass());
465   scoped_refptr<net::TestURLRequestContextGetter> request_context =
466       new net::TestURLRequestContextGetter(base::MessageLoopProxy::current());
467   settings_->InitDataReductionProxySettings(&pref_service_,
468                                             &pref_service_,
469                                             request_context.get());
470 
471   base::MessageLoop::current()->RunUntilIdle();
472 }
473 
474 }  // namespace data_reduction_proxy
475