Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / chromeos / proxy_config_service_impl_unittest.cc
blob8d2ac896e892db97e98dec2db8bdff8d5d80d1af
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/chromeos/proxy_config_service_impl.h"
7 #include <vector>
9 #include "base/format_macros.h"
10 #include "base/json/json_writer.h"
11 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/prefs/testing_pref_service.h"
14 #include "base/strings/stringprintf.h"
15 #include "chrome/browser/chromeos/net/proxy_config_handler.h"
16 #include "chrome/browser/chromeos/settings/cros_settings.h"
17 #include "chrome/browser/chromeos/settings/device_settings_service.h"
18 #include "chrome/browser/chromeos/ui_proxy_config.h"
19 #include "chrome/common/pref_names.h"
20 #include "chromeos/dbus/dbus_thread_manager.h"
21 #include "chromeos/dbus/shill_profile_client.h"
22 #include "chromeos/dbus/shill_service_client.h"
23 #include "chromeos/network/network_handler.h"
24 #include "chromeos/network/network_profile_handler.h"
25 #include "chromeos/network/network_state.h"
26 #include "chromeos/network/network_state_handler.h"
27 #include "chromeos/network/onc/onc_utils.h"
28 #include "components/pref_registry/testing_pref_service_syncable.h"
29 #include "components/proxy_config/proxy_config_pref_names.h"
30 #include "content/public/test/test_browser_thread.h"
31 #include "net/proxy/proxy_config.h"
32 #include "net/proxy/proxy_config_service_common_unittest.h"
33 #include "testing/gtest/include/gtest/gtest.h"
34 #include "third_party/cros_system_api/dbus/service_constants.h"
36 using content::BrowserThread;
38 namespace chromeos {
40 namespace {
42 struct Input {
43 UIProxyConfig::Mode mode;
44 std::string pac_url;
45 std::string server;
46 std::string bypass_rules;
49 // Builds an identifier for each test in an array.
50 #define TEST_DESC(desc) base::StringPrintf("at line %d <%s>", __LINE__, desc)
52 // Shortcuts to declare enums within chromeos's ProxyConfig.
53 #define MK_MODE(mode) UIProxyConfig::MODE_##mode
55 // Inspired from net/proxy/proxy_config_service_linux_unittest.cc.
56 const struct TestParams {
57 // Short description to identify the test
58 std::string description;
60 Input input;
62 // Expected outputs from fields of net::ProxyConfig (via IO).
63 bool auto_detect;
64 GURL pac_url;
65 net::ProxyRulesExpectation proxy_rules;
66 } tests[] = {
67 { // 0
68 TEST_DESC("No proxying"),
70 { // Input.
71 MK_MODE(DIRECT), // mode
74 // Expected result.
75 false, // auto_detect
76 GURL(), // pac_url
77 net::ProxyRulesExpectation::Empty(), // proxy_rules
80 { // 1
81 TEST_DESC("Auto detect"),
83 { // Input.
84 MK_MODE(AUTO_DETECT), // mode
87 // Expected result.
88 true, // auto_detect
89 GURL(), // pac_url
90 net::ProxyRulesExpectation::Empty(), // proxy_rules
93 { // 2
94 TEST_DESC("Valid PAC URL"),
96 { // Input.
97 MK_MODE(PAC_SCRIPT), // mode
98 "http://wpad/wpad.dat", // pac_url
101 // Expected result.
102 false, // auto_detect
103 GURL("http://wpad/wpad.dat"), // pac_url
104 net::ProxyRulesExpectation::Empty(), // proxy_rules
107 { // 3
108 TEST_DESC("Invalid PAC URL"),
110 { // Input.
111 MK_MODE(PAC_SCRIPT), // mode
112 "wpad.dat", // pac_url
115 // Expected result.
116 false, // auto_detect
117 GURL(), // pac_url
118 net::ProxyRulesExpectation::Empty(), // proxy_rules
121 { // 4
122 TEST_DESC("Single-host in proxy list"),
124 { // Input.
125 MK_MODE(SINGLE_PROXY), // mode
126 "", // pac_url
127 "www.google.com", // server
130 // Expected result.
131 false, // auto_detect
132 GURL(), // pac_url
133 net::ProxyRulesExpectation::Single( // proxy_rules
134 "www.google.com:80", // single proxy
135 "<local>"), // bypass rules
138 { // 5
139 TEST_DESC("Single-host, different port"),
141 { // Input.
142 MK_MODE(SINGLE_PROXY), // mode
143 "", // pac_url
144 "www.google.com:99", // server
147 // Expected result.
148 false, // auto_detect
149 GURL(), // pac_url
150 net::ProxyRulesExpectation::Single( // proxy_rules
151 "www.google.com:99", // single
152 "<local>"), // bypass rules
155 { // 6
156 TEST_DESC("Tolerate a scheme"),
158 { // Input.
159 MK_MODE(SINGLE_PROXY), // mode
160 "", // pac_url
161 "http://www.google.com:99", // server
164 // Expected result.
165 false, // auto_detect
166 GURL(), // pac_url
167 net::ProxyRulesExpectation::Single( // proxy_rules
168 "www.google.com:99", // single proxy
169 "<local>"), // bypass rules
172 { // 7
173 TEST_DESC("Per-scheme proxy rules"),
175 { // Input.
176 MK_MODE(PROXY_PER_SCHEME), // mode
177 "", // pac_url
178 "http=www.google.com:80;https=https://www.foo.com:110;"
179 "ftp=ftp.foo.com:121;socks=socks5://socks.com:888", // server
182 // Expected result.
183 false, // auto_detect
184 GURL(), // pac_url
185 net::ProxyRulesExpectation::PerSchemeWithSocks( // proxy_rules
186 "www.google.com:80", // http
187 "https://www.foo.com:110", // https
188 "ftp.foo.com:121", // ftp
189 "socks5://socks.com:888", // fallback proxy
190 "<local>"), // bypass rules
193 { // 8
194 TEST_DESC("Bypass rules"),
196 { // Input.
197 MK_MODE(SINGLE_PROXY), // mode
198 "", // pac_url
199 "www.google.com", // server
200 "*.google.com, *foo.com:99, 1.2.3.4:22, 127.0.0.1/8", // bypass_rules
203 // Expected result.
204 false, // auto_detect
205 GURL(), // pac_url
206 net::ProxyRulesExpectation::Single( // proxy_rules
207 "www.google.com:80", // single proxy
208 // bypass_rules
209 "*.google.com,*foo.com:99,1.2.3.4:22,127.0.0.1/8,<local>"),
211 }; // tests
213 const char kEthernetPolicy[] =
214 " { \"GUID\": \"{485d6076-dd44-6b6d-69787465725f5040}\","
215 " \"Type\": \"Ethernet\","
216 " \"Name\": \"MyEthernet\","
217 " \"Ethernet\": {"
218 " \"Authentication\": \"None\" },"
219 " \"ProxySettings\": {"
220 " \"PAC\": \"http://domain.com/x\","
221 " \"Type\": \"PAC\" }"
222 " }";
224 const char kUserProfilePath[] = "user_profile";
226 } // namespace
228 class ProxyConfigServiceImplTest : public testing::Test {
229 protected:
230 ProxyConfigServiceImplTest()
231 : ui_thread_(BrowserThread::UI, &loop_),
232 io_thread_(BrowserThread::IO, &loop_) {}
234 void SetUp() override {
235 DBusThreadManager::Initialize();
236 NetworkHandler::Initialize();
238 PrefProxyConfigTrackerImpl::RegisterPrefs(pref_service_.registry());
239 chromeos::proxy_config::RegisterPrefs(pref_service_.registry());
240 PrefProxyConfigTrackerImpl::RegisterProfilePrefs(profile_prefs_.registry());
241 chromeos::proxy_config::RegisterProfilePrefs(profile_prefs_.registry());
244 void SetUpProxyConfigService(PrefService* profile_prefs) {
245 config_service_impl_.reset(
246 new ProxyConfigServiceImpl(profile_prefs, &pref_service_));
247 proxy_config_service_ =
248 config_service_impl_->CreateTrackingProxyConfigService(
249 scoped_ptr<net::ProxyConfigService>());
251 // CreateTrackingProxyConfigService triggers update of initial prefs proxy
252 // config by tracker to chrome proxy config service, so flush all pending
253 // tasks so that tests start fresh.
254 loop_.RunUntilIdle();
257 void SetUpPrivateWiFi() {
258 ShillProfileClient::TestInterface* profile_test =
259 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface();
260 ShillServiceClient::TestInterface* service_test =
261 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
263 // Process any pending notifications before clearing services.
264 loop_.RunUntilIdle();
265 service_test->ClearServices();
267 // Sends a notification about the added profile.
268 profile_test->AddProfile(kUserProfilePath, "user_hash");
270 service_test->AddService("/service/stub_wifi2",
271 "stub_wifi2" /* guid */,
272 "wifi2_PSK",
273 shill::kTypeWifi, shill::kStateOnline,
274 true /* visible */);
275 profile_test->AddService(kUserProfilePath, "/service/stub_wifi2");
277 loop_.RunUntilIdle();
280 void SetUpSharedEthernet() {
281 ShillProfileClient::TestInterface* profile_test =
282 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface();
283 ShillServiceClient::TestInterface* service_test =
284 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
286 // Process any pending notifications before clearing services.
287 loop_.RunUntilIdle();
288 service_test->ClearServices();
290 // Sends a notification about the added profile.
291 profile_test->AddProfile(kUserProfilePath, "user_hash");
293 service_test->AddService("/service/ethernet", "stub_ethernet" /* guid */,
294 "eth0", shill::kTypeEthernet, shill::kStateOnline,
295 true /* visible */);
296 profile_test->AddService(NetworkProfileHandler::GetSharedProfilePath(),
297 "/service/ethernet");
299 loop_.RunUntilIdle();
302 void TearDown() override {
303 config_service_impl_->DetachFromPrefService();
304 loop_.RunUntilIdle();
305 config_service_impl_.reset();
306 proxy_config_service_.reset();
307 NetworkHandler::Shutdown();
308 DBusThreadManager::Shutdown();
311 void InitConfigWithTestInput(const Input& input,
312 base::DictionaryValue* result) {
313 scoped_ptr<base::DictionaryValue> new_config;
314 switch (input.mode) {
315 case MK_MODE(DIRECT):
316 new_config.reset(ProxyConfigDictionary::CreateDirect());
317 break;
318 case MK_MODE(AUTO_DETECT):
319 new_config.reset(ProxyConfigDictionary::CreateAutoDetect());
320 break;
321 case MK_MODE(PAC_SCRIPT):
322 new_config.reset(
323 ProxyConfigDictionary::CreatePacScript(input.pac_url, false));
324 break;
325 case MK_MODE(SINGLE_PROXY):
326 case MK_MODE(PROXY_PER_SCHEME):
327 new_config.reset(ProxyConfigDictionary::CreateFixedServers(
328 input.server, input.bypass_rules));
329 break;
331 result->Swap(new_config.get());
334 void SetUserConfigInShill(base::DictionaryValue* pref_proxy_config_dict) {
335 std::string proxy_config;
336 if (pref_proxy_config_dict)
337 base::JSONWriter::Write(*pref_proxy_config_dict, &proxy_config);
339 NetworkStateHandler* network_state_handler =
340 NetworkHandler::Get()->network_state_handler();
341 const NetworkState* network = network_state_handler->DefaultNetwork();
342 ASSERT_TRUE(network);
343 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()->
344 SetServiceProperty(network->path(),
345 shill::kProxyConfigProperty,
346 base::StringValue(proxy_config));
349 // Synchronously gets the latest proxy config.
350 void SyncGetLatestProxyConfig(net::ProxyConfig* config) {
351 *config = net::ProxyConfig();
352 // Let message loop process all messages. This will run
353 // ChromeProxyConfigService::UpdateProxyConfig, which is posted on IO from
354 // PrefProxyConfigTrackerImpl::OnProxyConfigChanged.
355 loop_.RunUntilIdle();
356 net::ProxyConfigService::ConfigAvailability availability =
357 proxy_config_service_->GetLatestProxyConfig(config);
359 EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID, availability);
362 base::MessageLoop loop_;
363 scoped_ptr<net::ProxyConfigService> proxy_config_service_;
364 scoped_ptr<ProxyConfigServiceImpl> config_service_impl_;
365 TestingPrefServiceSimple pref_service_;
366 user_prefs::TestingPrefServiceSyncable profile_prefs_;
368 private:
369 ScopedTestDeviceSettingsService test_device_settings_service_;
370 ScopedTestCrosSettings test_cros_settings_;
371 content::TestBrowserThread ui_thread_;
372 content::TestBrowserThread io_thread_;
375 TEST_F(ProxyConfigServiceImplTest, NetworkProxy) {
376 SetUpPrivateWiFi();
377 // Create a ProxyConfigServiceImpl like for the system request context.
378 SetUpProxyConfigService(nullptr /* no profile prefs */);
379 for (size_t i = 0; i < arraysize(tests); ++i) {
380 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i,
381 tests[i].description.c_str()));
383 base::DictionaryValue test_config;
384 InitConfigWithTestInput(tests[i].input, &test_config);
385 SetUserConfigInShill(&test_config);
387 net::ProxyConfig config;
388 SyncGetLatestProxyConfig(&config);
390 EXPECT_EQ(tests[i].auto_detect, config.auto_detect());
391 EXPECT_EQ(tests[i].pac_url, config.pac_url());
392 EXPECT_TRUE(tests[i].proxy_rules.Matches(config.proxy_rules()));
396 TEST_F(ProxyConfigServiceImplTest, DynamicPrefsOverride) {
397 SetUpPrivateWiFi();
398 // Create a ProxyConfigServiceImpl like for the system request context.
399 SetUpProxyConfigService(nullptr /* no profile prefs */);
400 // Groupings of 3 test inputs to use for managed, recommended and network
401 // proxies respectively. Only valid and non-direct test inputs are used.
402 const size_t proxies[][3] = {
403 { 1, 2, 4, },
404 { 1, 4, 2, },
405 { 4, 2, 1, },
406 { 2, 1, 4, },
407 { 2, 4, 5, },
408 { 2, 5, 4, },
409 { 5, 4, 2, },
410 { 4, 2, 5, },
411 { 4, 5, 6, },
412 { 4, 6, 5, },
413 { 6, 5, 4, },
414 { 5, 4, 6, },
415 { 5, 6, 7, },
416 { 5, 7, 6, },
417 { 7, 6, 5, },
418 { 6, 5, 7, },
419 { 6, 7, 8, },
420 { 6, 8, 7, },
421 { 8, 7, 6, },
422 { 7, 6, 8, },
424 for (size_t i = 0; i < arraysize(proxies); ++i) {
425 const TestParams& managed_params = tests[proxies[i][0]];
426 const TestParams& recommended_params = tests[proxies[i][1]];
427 const TestParams& network_params = tests[proxies[i][2]];
429 SCOPED_TRACE(base::StringPrintf(
430 "Test[%" PRIuS "] managed=[%s], recommended=[%s], network=[%s]", i,
431 managed_params.description.c_str(),
432 recommended_params.description.c_str(),
433 network_params.description.c_str()));
435 base::DictionaryValue managed_config;
436 InitConfigWithTestInput(managed_params.input, &managed_config);
437 base::DictionaryValue recommended_config;
438 InitConfigWithTestInput(recommended_params.input, &recommended_config);
439 base::DictionaryValue network_config;
440 InitConfigWithTestInput(network_params.input, &network_config);
442 // Managed proxy pref should take effect over recommended proxy and
443 // non-existent network proxy.
444 SetUserConfigInShill(nullptr);
445 pref_service_.SetManagedPref(::proxy_config::prefs::kProxy,
446 managed_config.DeepCopy());
447 pref_service_.SetRecommendedPref(::proxy_config::prefs::kProxy,
448 recommended_config.DeepCopy());
449 net::ProxyConfig actual_config;
450 SyncGetLatestProxyConfig(&actual_config);
451 EXPECT_EQ(managed_params.auto_detect, actual_config.auto_detect());
452 EXPECT_EQ(managed_params.pac_url, actual_config.pac_url());
453 EXPECT_TRUE(managed_params.proxy_rules.Matches(
454 actual_config.proxy_rules()));
456 // Recommended proxy pref should take effect when managed proxy pref is
457 // removed.
458 pref_service_.RemoveManagedPref(::proxy_config::prefs::kProxy);
459 SyncGetLatestProxyConfig(&actual_config);
460 EXPECT_EQ(recommended_params.auto_detect, actual_config.auto_detect());
461 EXPECT_EQ(recommended_params.pac_url, actual_config.pac_url());
462 EXPECT_TRUE(recommended_params.proxy_rules.Matches(
463 actual_config.proxy_rules()));
465 // Network proxy should take take effect over recommended proxy pref.
466 SetUserConfigInShill(&network_config);
467 SyncGetLatestProxyConfig(&actual_config);
468 EXPECT_EQ(network_params.auto_detect, actual_config.auto_detect());
469 EXPECT_EQ(network_params.pac_url, actual_config.pac_url());
470 EXPECT_TRUE(network_params.proxy_rules.Matches(
471 actual_config.proxy_rules()));
473 // Managed proxy pref should take effect over network proxy.
474 pref_service_.SetManagedPref(::proxy_config::prefs::kProxy,
475 managed_config.DeepCopy());
476 SyncGetLatestProxyConfig(&actual_config);
477 EXPECT_EQ(managed_params.auto_detect, actual_config.auto_detect());
478 EXPECT_EQ(managed_params.pac_url, actual_config.pac_url());
479 EXPECT_TRUE(managed_params.proxy_rules.Matches(
480 actual_config.proxy_rules()));
482 // Network proxy should take effect over recommended proxy pref when managed
483 // proxy pref is removed.
484 pref_service_.RemoveManagedPref(::proxy_config::prefs::kProxy);
485 SyncGetLatestProxyConfig(&actual_config);
486 EXPECT_EQ(network_params.auto_detect, actual_config.auto_detect());
487 EXPECT_EQ(network_params.pac_url, actual_config.pac_url());
488 EXPECT_TRUE(network_params.proxy_rules.Matches(
489 actual_config.proxy_rules()));
491 // Removing recommended proxy pref should have no effect on network proxy.
492 pref_service_.RemoveRecommendedPref(::proxy_config::prefs::kProxy);
493 SyncGetLatestProxyConfig(&actual_config);
494 EXPECT_EQ(network_params.auto_detect, actual_config.auto_detect());
495 EXPECT_EQ(network_params.pac_url, actual_config.pac_url());
496 EXPECT_TRUE(network_params.proxy_rules.Matches(
497 actual_config.proxy_rules()));
501 // Tests whether the proxy settings from user policy are used for ethernet even
502 // if 'UseSharedProxies' is set to false.
503 // See https://crbug.com/454966 .
504 TEST_F(ProxyConfigServiceImplTest, SharedEthernetAndUserPolicy) {
505 SetUpSharedEthernet();
506 SetUpProxyConfigService(&profile_prefs_);
508 scoped_ptr<base::DictionaryValue> ethernet_policy(
509 chromeos::onc::ReadDictionaryFromJson(kEthernetPolicy));
511 scoped_ptr<base::ListValue> network_configs(new base::ListValue);
512 network_configs->Append(ethernet_policy.release());
514 profile_prefs_.SetUserPref(prefs::kUseSharedProxies,
515 new base::FundamentalValue(false));
516 profile_prefs_.SetManagedPref(prefs::kOpenNetworkConfiguration,
517 network_configs.release());
519 net::ProxyConfig actual_config;
520 SyncGetLatestProxyConfig(&actual_config);
521 net::ProxyConfig expected_config =
522 net::ProxyConfig::CreateFromCustomPacURL(GURL("http://domain.com/x"));
523 EXPECT_TRUE(expected_config.Equals(actual_config));
526 } // namespace chromeos