Home | History | Annotate | Download | only in browser
      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 kProbeURLWithOKResponse[] = "http://ok.org/";
     24 const char kProbeURLWithBadResponse[] = "http://bad.org/";
     25 const char kProbeURLWithNoResponse[] = "http://no.org/";
     26 
     27 }  // namespace
     28 
     29 namespace data_reduction_proxy {
     30 
     31 class DataReductionProxySettingsTest
     32     : public ConcreteDataReductionProxySettingsTest<
     33           DataReductionProxySettings> {
     34 };
     35 
     36 TEST_F(DataReductionProxySettingsTest, TestGetDataReductionProxyOrigin) {
     37   // SetUp() adds the origin to the command line, which should be returned here.
     38   std::string result =
     39       settings_->params()->origin().spec();
     40   EXPECT_EQ(GURL(expected_params_->DefaultOrigin()), GURL(result));
     41 }
     42 
     43 TEST_F(DataReductionProxySettingsTest, TestGetDataReductionProxyDevOrigin) {
     44   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
     45       switches::kDataReductionProxyDev, expected_params_->DefaultDevOrigin());
     46   ResetSettings(true, true, false, true, false);
     47   std::string result =
     48       settings_->params()->origin().spec();
     49   EXPECT_EQ(GURL(expected_params_->DefaultDevOrigin()), GURL(result));
     50 }
     51 
     52 
     53 TEST_F(DataReductionProxySettingsTest, TestGetDataReductionProxies) {
     54   DataReductionProxyParams::DataReductionProxyList proxies =
     55       expected_params_->GetAllowedProxies();
     56 
     57   unsigned int expected_proxy_size = 2u;
     58   EXPECT_EQ(expected_proxy_size, proxies.size());
     59 
     60   net::HostPortPair expected_origin =
     61       net::HostPortPair::FromURL(GURL(expected_params_->DefaultOrigin()));
     62   net::HostPortPair expected_fallback_origin =
     63       net::HostPortPair::FromURL(
     64           GURL(expected_params_->DefaultFallbackOrigin()));
     65   EXPECT_EQ(expected_origin.host(), proxies[0].host());
     66   EXPECT_EQ(expected_origin.port() ,proxies[0].EffectiveIntPort());
     67   EXPECT_EQ(expected_fallback_origin.host(), proxies[1].host());
     68   EXPECT_EQ(expected_fallback_origin.port(), proxies[1].EffectiveIntPort());
     69 }
     70 
     71 TEST_F(DataReductionProxySettingsTest, TestSetProxyConfigs) {
     72   TestDataReductionProxyParams drp_params(
     73       DataReductionProxyParams::kAllowed |
     74       DataReductionProxyParams::kFallbackAllowed |
     75       DataReductionProxyParams::kPromoAllowed,
     76       TestDataReductionProxyParams::HAS_EVERYTHING &
     77       ~TestDataReductionProxyParams::HAS_DEV_ORIGIN &
     78       ~TestDataReductionProxyParams::HAS_DEV_FALLBACK_ORIGIN);
     79   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
     80       switches::kDataReductionProxyAlt, drp_params.DefaultAltOrigin());
     81   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
     82       switches::kDataReductionProxyAltFallback,
     83       drp_params.DefaultAltFallbackOrigin());
     84   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
     85       switches::kDataReductionSSLProxy, drp_params.DefaultSSLOrigin());
     86   ResetSettings(true, true, true, true, false);
     87   TestDataReductionProxyConfig* config =
     88       static_cast<TestDataReductionProxyConfig*>(
     89           settings_->configurator());
     90 
     91   settings_->SetProxyConfigs(true, true, false, false);
     92   EXPECT_TRUE(config->enabled_);
     93   EXPECT_TRUE(net::HostPortPair::FromString(
     94       expected_params_->DefaultAltOrigin()).Equals(
     95           net::HostPortPair::FromString(config->origin_)));
     96   EXPECT_TRUE(net::HostPortPair::FromString(
     97       expected_params_->DefaultAltFallbackOrigin()).Equals(
     98           net::HostPortPair::FromString(config->fallback_origin_)));
     99   EXPECT_TRUE(net::HostPortPair::FromString(
    100       expected_params_->DefaultSSLOrigin()).Equals(
    101           net::HostPortPair::FromString(config->ssl_origin_)));
    102 
    103   settings_->SetProxyConfigs(true, false, false, false);
    104   EXPECT_TRUE(config->enabled_);
    105   EXPECT_TRUE(net::HostPortPair::FromString(drp_params.DefaultOrigin()).Equals(
    106       net::HostPortPair::FromString(config->origin_)));
    107   EXPECT_TRUE(net::HostPortPair::FromString(
    108       drp_params.DefaultFallbackOrigin()).Equals(
    109           net::HostPortPair::FromString(config->fallback_origin_)));
    110   EXPECT_EQ("", config->ssl_origin_);
    111 
    112   settings_->SetProxyConfigs(false, true, false, false);
    113   EXPECT_FALSE(config->enabled_);
    114   EXPECT_EQ("", config->origin_);
    115   EXPECT_EQ("", config->fallback_origin_);
    116   EXPECT_EQ("", config->ssl_origin_);
    117 
    118   settings_->SetProxyConfigs(false, false, false, false);
    119   EXPECT_FALSE(config->enabled_);
    120   EXPECT_EQ("", config->origin_);
    121   EXPECT_EQ("", config->fallback_origin_);
    122   EXPECT_EQ("", config->ssl_origin_);
    123 }
    124 
    125 TEST_F(DataReductionProxySettingsTest, TestSetProxyConfigsHoldback) {
    126   ResetSettings(true, true, true, true, true);
    127   TestDataReductionProxyConfig* config =
    128       static_cast<TestDataReductionProxyConfig*>(
    129           settings_->configurator());
    130 
    131    // Holdback.
    132   settings_->SetProxyConfigs(true, true, false, false);
    133   EXPECT_FALSE(config->enabled_);
    134   EXPECT_EQ("", config->origin_);
    135   EXPECT_EQ("", config->fallback_origin_);
    136   EXPECT_EQ("", config->ssl_origin_);
    137 }
    138 
    139 TEST_F(DataReductionProxySettingsTest, TestIsProxyEnabledOrManaged) {
    140   settings_->InitPrefMembers();
    141   base::MessageLoopForUI loop;
    142   // The proxy is disabled initially.
    143   settings_->enabled_by_user_ = false;
    144   settings_->SetProxyConfigs(false, false, false, false);
    145 
    146   EXPECT_FALSE(settings_->IsDataReductionProxyEnabled());
    147   EXPECT_FALSE(settings_->IsDataReductionProxyManaged());
    148 
    149   CheckOnPrefChange(true, true, false);
    150   EXPECT_TRUE(settings_->IsDataReductionProxyEnabled());
    151   EXPECT_FALSE(settings_->IsDataReductionProxyManaged());
    152 
    153   CheckOnPrefChange(true, true, true);
    154   EXPECT_TRUE(settings_->IsDataReductionProxyEnabled());
    155   EXPECT_TRUE(settings_->IsDataReductionProxyManaged());
    156 
    157   base::MessageLoop::current()->RunUntilIdle();
    158 }
    159 
    160 TEST_F(DataReductionProxySettingsTest, TestResetDataReductionStatistics) {
    161   int64 original_content_length;
    162   int64 received_content_length;
    163   int64 last_update_time;
    164   settings_->ResetDataReductionStatistics();
    165   settings_->GetContentLengths(kNumDaysInHistory,
    166                                &original_content_length,
    167                                &received_content_length,
    168                                &last_update_time);
    169   EXPECT_EQ(0L, original_content_length);
    170   EXPECT_EQ(0L, received_content_length);
    171   EXPECT_EQ(last_update_time_.ToInternalValue(), last_update_time);
    172 }
    173 
    174 TEST_F(DataReductionProxySettingsTest, TestContentLengths) {
    175   int64 original_content_length;
    176   int64 received_content_length;
    177   int64 last_update_time;
    178 
    179   // Request |kNumDaysInHistory| days.
    180   settings_->GetContentLengths(kNumDaysInHistory,
    181                                &original_content_length,
    182                                &received_content_length,
    183                                &last_update_time);
    184   const unsigned int days = kNumDaysInHistory;
    185   // Received content length history values are 0 to |kNumDaysInHistory - 1|.
    186   int64 expected_total_received_content_length = (days - 1L) * days / 2;
    187   // Original content length history values are 0 to
    188   // |2 * (kNumDaysInHistory - 1)|.
    189   long expected_total_original_content_length = (days - 1L) * days;
    190   EXPECT_EQ(expected_total_original_content_length, original_content_length);
    191   EXPECT_EQ(expected_total_received_content_length, received_content_length);
    192   EXPECT_EQ(last_update_time_.ToInternalValue(), last_update_time);
    193 
    194   // Request |kNumDaysInHistory - 1| days.
    195   settings_->GetContentLengths(kNumDaysInHistory - 1,
    196                                &original_content_length,
    197                                &received_content_length,
    198                                &last_update_time);
    199   expected_total_received_content_length -= (days - 1);
    200   expected_total_original_content_length -= 2 * (days - 1);
    201   EXPECT_EQ(expected_total_original_content_length, original_content_length);
    202   EXPECT_EQ(expected_total_received_content_length, received_content_length);
    203 
    204   // Request 0 days.
    205   settings_->GetContentLengths(0,
    206                                &original_content_length,
    207                                &received_content_length,
    208                                &last_update_time);
    209   expected_total_received_content_length = 0;
    210   expected_total_original_content_length = 0;
    211   EXPECT_EQ(expected_total_original_content_length, original_content_length);
    212   EXPECT_EQ(expected_total_received_content_length, received_content_length);
    213 
    214   // Request 1 day. First day had 0 bytes so should be same as 0 days.
    215   settings_->GetContentLengths(1,
    216                                &original_content_length,
    217                                &received_content_length,
    218                                &last_update_time);
    219   EXPECT_EQ(expected_total_original_content_length, original_content_length);
    220   EXPECT_EQ(expected_total_received_content_length, received_content_length);
    221 }
    222 
    223 // TODO(marq): Add a test to verify that MaybeActivateDataReductionProxy
    224 // is called when the pref in |settings_| is enabled.
    225 TEST_F(DataReductionProxySettingsTest, TestMaybeActivateDataReductionProxy) {
    226   // Initialize the pref member in |settings_| without the usual callback
    227   // so it won't trigger MaybeActivateDataReductionProxy when the pref value
    228   // is set.
    229   settings_->spdy_proxy_auth_enabled_.Init(
    230       prefs::kDataReductionProxyEnabled,
    231       settings_->GetOriginalProfilePrefs());
    232   settings_->data_reduction_proxy_alternative_enabled_.Init(
    233       prefs::kDataReductionProxyAltEnabled,
    234       settings_->GetOriginalProfilePrefs());
    235 
    236   // TODO(bengr): Test enabling/disabling while a probe is outstanding.
    237   base::MessageLoopForUI loop;
    238   // The proxy is enabled and unrestructed initially.
    239   // Request succeeded but with bad response, expect proxy to be restricted.
    240   CheckProbe(true,
    241              kProbeURLWithBadResponse,
    242              "Bad",
    243              true,
    244              true,
    245              true,
    246              false);
    247   // Request succeeded with valid response, expect proxy to be unrestricted.
    248   CheckProbe(true,
    249              kProbeURLWithOKResponse,
    250              "OK",
    251              true,
    252              true,
    253              false,
    254              false);
    255   // Request failed, expect proxy to be enabled but restricted.
    256   CheckProbe(true,
    257              kProbeURLWithNoResponse,
    258              "",
    259              false,
    260              true,
    261              true,
    262              false);
    263   // The proxy is disabled initially. Probes should not be emitted to change
    264   // state.
    265   CheckProbe(false,
    266              kProbeURLWithOKResponse,
    267              "OK",
    268              true,
    269              false,
    270              false,
    271              false);
    272 }
    273 
    274 TEST_F(DataReductionProxySettingsTest, TestOnIPAddressChanged) {
    275   base::MessageLoopForUI loop;
    276   // The proxy is enabled initially.
    277   pref_service_.SetBoolean(prefs::kDataReductionProxyEnabled, true);
    278   settings_->spdy_proxy_auth_enabled_.Init(
    279       prefs::kDataReductionProxyEnabled,
    280       settings_->GetOriginalProfilePrefs());
    281   settings_->data_reduction_proxy_alternative_enabled_.Init(
    282       prefs::kDataReductionProxyAltEnabled,
    283       settings_->GetOriginalProfilePrefs());
    284   settings_->enabled_by_user_ = true;
    285   settings_->restricted_by_carrier_ = false;
    286   settings_->SetProxyConfigs(true, false, false, true);
    287   // IP address change triggers a probe that succeeds. Proxy remains
    288   // unrestricted.
    289   CheckProbeOnIPChange(kProbeURLWithOKResponse,
    290                        "OK",
    291                        true,
    292                        false,
    293                        false);
    294   // IP address change triggers a probe that fails. Proxy is restricted.
    295   CheckProbeOnIPChange(kProbeURLWithBadResponse,
    296                        "Bad",
    297                        true,
    298                        true,
    299                        false);
    300   // IP address change triggers a probe that fails. Proxy remains restricted.
    301   CheckProbeOnIPChange(kProbeURLWithBadResponse,
    302                        "Bad",
    303                        true,
    304                        true,
    305                        false);
    306   // IP address change triggers a probe that succeeds. Proxy is unrestricted.
    307   CheckProbeOnIPChange(kProbeURLWithOKResponse,
    308                        "OK",
    309                        true,
    310                        false,
    311                        false);
    312   // Simulate a VPN connection. The proxy should be disabled.
    313   MockSettings* settings = static_cast<MockSettings*>(settings_.get());
    314   settings->network_interfaces_.reset(new net::NetworkInterfaceList());
    315   settings->network_interfaces_->push_back(net::NetworkInterface(
    316       "tun0", /* network interface name */
    317       "tun0", /* network interface friendly name */
    318       0,      /* interface index */
    319       net::NetworkChangeNotifier::CONNECTION_WIFI,
    320       net::IPAddressNumber(),        /* IP address */
    321       0,                             /* network prefix */
    322       net::IP_ADDRESS_ATTRIBUTE_NONE /* ip address attribute */
    323       ));
    324   settings_->OnIPAddressChanged();
    325   base::MessageLoop::current()->RunUntilIdle();
    326   CheckProxyConfigs(false, false, false);
    327 
    328   // Check that the proxy is re-enabled if a non-VPN connection is later used.
    329   settings->network_interfaces_.reset(new net::NetworkInterfaceList());
    330   settings->network_interfaces_->push_back(net::NetworkInterface(
    331       "eth0", /* network interface name */
    332       "eth0", /* network interface friendly name */
    333       0,      /* interface index */
    334       net::NetworkChangeNotifier::CONNECTION_WIFI,
    335       net::IPAddressNumber(),
    336       0,                             /* network prefix */
    337       net::IP_ADDRESS_ATTRIBUTE_NONE /* ip address attribute */
    338       ));
    339   CheckProbeOnIPChange(kProbeURLWithOKResponse,
    340                        "OK",
    341                        true,
    342                        false,
    343                        false);
    344 }
    345 
    346 TEST_F(DataReductionProxySettingsTest, TestOnProxyEnabledPrefChange) {
    347   settings_->InitPrefMembers();
    348   base::MessageLoopForUI loop;
    349   // The proxy is enabled initially.
    350   settings_->enabled_by_user_ = true;
    351   settings_->SetProxyConfigs(true, false, false, true);
    352   // The pref is disabled, so correspondingly should be the proxy.
    353   CheckOnPrefChange(false, false, false);
    354   // The pref is enabled, so correspondingly should be the proxy.
    355   CheckOnPrefChange(true, true, false);
    356 }
    357 
    358 TEST_F(DataReductionProxySettingsTest, TestInitDataReductionProxyOn) {
    359   MockSettings* settings = static_cast<MockSettings*>(settings_.get());
    360   EXPECT_CALL(*settings, RecordStartupState(PROXY_ENABLED));
    361 
    362   pref_service_.SetBoolean(prefs::kDataReductionProxyEnabled, true);
    363   CheckInitDataReductionProxy(true);
    364 }
    365 
    366 TEST_F(DataReductionProxySettingsTest, TestInitDataReductionProxyOff) {
    367   // InitDataReductionProxySettings with the preference off will directly call
    368   // LogProxyState.
    369   MockSettings* settings = static_cast<MockSettings*>(settings_.get());
    370   EXPECT_CALL(*settings, RecordStartupState(PROXY_DISABLED));
    371 
    372   pref_service_.SetBoolean(prefs::kDataReductionProxyEnabled, false);
    373   CheckInitDataReductionProxy(false);
    374 }
    375 
    376 TEST_F(DataReductionProxySettingsTest, TestEnableProxyFromCommandLine) {
    377   MockSettings* settings = static_cast<MockSettings*>(settings_.get());
    378   EXPECT_CALL(*settings, RecordStartupState(PROXY_ENABLED));
    379 
    380   CommandLine::ForCurrentProcess()->AppendSwitch(
    381       switches::kEnableDataReductionProxy);
    382   CheckInitDataReductionProxy(true);
    383 }
    384 
    385 TEST_F(DataReductionProxySettingsTest, TestGetDailyContentLengths) {
    386   DataReductionProxySettings::ContentLengthList result =
    387       settings_->GetDailyContentLengths(prefs::kDailyHttpOriginalContentLength);
    388 
    389   ASSERT_FALSE(result.empty());
    390   ASSERT_EQ(kNumDaysInHistory, result.size());
    391 
    392   for (size_t i = 0; i < kNumDaysInHistory; ++i) {
    393     long expected_length =
    394         static_cast<long>((kNumDaysInHistory - 1 - i) * 2);
    395     ASSERT_EQ(expected_length, result[i]);
    396   }
    397 }
    398 
    399 TEST_F(DataReductionProxySettingsTest, CheckInitMetricsWhenNotAllowed) {
    400   // No call to |AddProxyToCommandLine()| was made, so the proxy feature
    401   // should be unavailable.
    402   base::MessageLoopForUI loop;
    403   // Clear the command line. Setting flags can force the proxy to be allowed.
    404   CommandLine::ForCurrentProcess()->InitFromArgv(0, NULL);
    405 
    406   ResetSettings(false, false, false, false, false);
    407   MockSettings* settings = static_cast<MockSettings*>(settings_.get());
    408   EXPECT_FALSE(settings->params()->allowed());
    409   EXPECT_CALL(*settings, RecordStartupState(PROXY_NOT_AVAILABLE));
    410 
    411   scoped_ptr<DataReductionProxyConfigurator> configurator(
    412       new TestDataReductionProxyConfig());
    413   settings_->SetProxyConfigurator(configurator.get());
    414   scoped_refptr<net::TestURLRequestContextGetter> request_context =
    415       new net::TestURLRequestContextGetter(base::MessageLoopProxy::current());
    416   settings_->InitDataReductionProxySettings(
    417       &pref_service_,
    418       request_context.get());
    419   settings_->SetOnDataReductionEnabledCallback(
    420       base::Bind(&DataReductionProxySettingsTestBase::
    421                  RegisterSyntheticFieldTrialCallback,
    422                  base::Unretained(this)));
    423 
    424   base::MessageLoop::current()->RunUntilIdle();
    425 }
    426 
    427 }  // namespace data_reduction_proxy
    428