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