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. 4 5 #include "net/proxy/proxy_config_service_linux.h" 6 7 #include <map> 8 #include <string> 9 #include <vector> 10 11 #include "base/bind.h" 12 #include "base/compiler_specific.h" 13 #include "base/file_util.h" 14 #include "base/files/file_path.h" 15 #include "base/format_macros.h" 16 #include "base/logging.h" 17 #include "base/strings/string_util.h" 18 #include "base/strings/stringprintf.h" 19 #include "base/synchronization/waitable_event.h" 20 #include "base/threading/thread.h" 21 #include "net/proxy/proxy_config.h" 22 #include "net/proxy/proxy_config_service_common_unittest.h" 23 #include "testing/gtest/include/gtest/gtest.h" 24 #include "testing/platform_test.h" 25 26 namespace net { 27 namespace { 28 29 // Set of values for all environment variables that we might 30 // query. NULL represents an unset variable. 31 struct EnvVarValues { 32 // The strange capitalization is so that the field matches the 33 // environment variable name exactly. 34 const char *DESKTOP_SESSION, *HOME, 35 *KDEHOME, *KDE_SESSION_VERSION, 36 *auto_proxy, *all_proxy, 37 *http_proxy, *https_proxy, *ftp_proxy, 38 *SOCKS_SERVER, *SOCKS_VERSION, 39 *no_proxy; 40 }; 41 42 // Undo macro pollution from GDK includes (from message_loop.h). 43 #undef TRUE 44 #undef FALSE 45 46 // So as to distinguish between an unset gconf boolean variable and 47 // one that is false. 48 enum BoolSettingValue { 49 UNSET = 0, TRUE, FALSE 50 }; 51 52 // Set of values for all gconf settings that we might query. 53 struct GConfValues { 54 // strings 55 const char *mode, *autoconfig_url, 56 *http_host, *secure_host, *ftp_host, *socks_host; 57 // integers 58 int http_port, secure_port, ftp_port, socks_port; 59 // booleans 60 BoolSettingValue use_proxy, same_proxy, use_auth; 61 // string list 62 std::vector<std::string> ignore_hosts; 63 }; 64 65 // Mapping from a setting name to the location of the corresponding 66 // value (inside a EnvVarValues or GConfValues struct). 67 template<typename key_type, typename value_type> 68 struct SettingsTable { 69 typedef std::map<key_type, value_type*> map_type; 70 71 // Gets the value from its location 72 value_type Get(key_type key) { 73 typename map_type::const_iterator it = settings.find(key); 74 // In case there's a typo or the unittest becomes out of sync. 75 CHECK(it != settings.end()) << "key " << key << " not found"; 76 value_type* value_ptr = it->second; 77 return *value_ptr; 78 } 79 80 map_type settings; 81 }; 82 83 class MockEnvironment : public base::Environment { 84 public: 85 MockEnvironment() { 86 #define ENTRY(x) table[#x] = &values.x 87 ENTRY(DESKTOP_SESSION); 88 ENTRY(HOME); 89 ENTRY(KDEHOME); 90 ENTRY(KDE_SESSION_VERSION); 91 ENTRY(auto_proxy); 92 ENTRY(all_proxy); 93 ENTRY(http_proxy); 94 ENTRY(https_proxy); 95 ENTRY(ftp_proxy); 96 ENTRY(no_proxy); 97 ENTRY(SOCKS_SERVER); 98 ENTRY(SOCKS_VERSION); 99 #undef ENTRY 100 Reset(); 101 } 102 103 // Zeroes all environment values. 104 void Reset() { 105 EnvVarValues zero_values = { 0 }; 106 values = zero_values; 107 } 108 109 // Begin base::Environment implementation. 110 virtual bool GetVar(const char* variable_name, std::string* result) OVERRIDE { 111 std::map<std::string, const char**>::iterator it = 112 table.find(variable_name); 113 if (it != table.end() && *(it->second) != NULL) { 114 // Note that the variable may be defined but empty. 115 *result = *(it->second); 116 return true; 117 } 118 return false; 119 } 120 121 virtual bool SetVar(const char* variable_name, const std::string& new_value) 122 OVERRIDE { 123 ADD_FAILURE(); 124 return false; 125 } 126 127 virtual bool UnSetVar(const char* variable_name) OVERRIDE { 128 ADD_FAILURE(); 129 return false; 130 } 131 // End base::Environment implementation. 132 133 // Intentionally public, for convenience when setting up a test. 134 EnvVarValues values; 135 136 private: 137 std::map<std::string, const char**> table; 138 }; 139 140 class MockSettingGetter 141 : public ProxyConfigServiceLinux::SettingGetter { 142 public: 143 typedef ProxyConfigServiceLinux::SettingGetter SettingGetter; 144 MockSettingGetter() { 145 #define ENTRY(key, field) \ 146 strings_table.settings[SettingGetter::key] = &values.field 147 ENTRY(PROXY_MODE, mode); 148 ENTRY(PROXY_AUTOCONF_URL, autoconfig_url); 149 ENTRY(PROXY_HTTP_HOST, http_host); 150 ENTRY(PROXY_HTTPS_HOST, secure_host); 151 ENTRY(PROXY_FTP_HOST, ftp_host); 152 ENTRY(PROXY_SOCKS_HOST, socks_host); 153 #undef ENTRY 154 #define ENTRY(key, field) \ 155 ints_table.settings[SettingGetter::key] = &values.field 156 ENTRY(PROXY_HTTP_PORT, http_port); 157 ENTRY(PROXY_HTTPS_PORT, secure_port); 158 ENTRY(PROXY_FTP_PORT, ftp_port); 159 ENTRY(PROXY_SOCKS_PORT, socks_port); 160 #undef ENTRY 161 #define ENTRY(key, field) \ 162 bools_table.settings[SettingGetter::key] = &values.field 163 ENTRY(PROXY_USE_HTTP_PROXY, use_proxy); 164 ENTRY(PROXY_USE_SAME_PROXY, same_proxy); 165 ENTRY(PROXY_USE_AUTHENTICATION, use_auth); 166 #undef ENTRY 167 string_lists_table.settings[SettingGetter::PROXY_IGNORE_HOSTS] = 168 &values.ignore_hosts; 169 Reset(); 170 } 171 172 // Zeros all environment values. 173 void Reset() { 174 GConfValues zero_values = { 0 }; 175 values = zero_values; 176 } 177 178 virtual bool Init(base::SingleThreadTaskRunner* glib_thread_task_runner, 179 base::MessageLoopForIO* file_loop) OVERRIDE { 180 return true; 181 } 182 183 virtual void ShutDown() OVERRIDE {} 184 185 virtual bool SetUpNotifications(ProxyConfigServiceLinux::Delegate* delegate) 186 OVERRIDE { 187 return true; 188 } 189 190 virtual base::SingleThreadTaskRunner* GetNotificationTaskRunner() OVERRIDE { 191 return NULL; 192 } 193 194 virtual ProxyConfigSource GetConfigSource() OVERRIDE { 195 return PROXY_CONFIG_SOURCE_TEST; 196 } 197 198 virtual bool GetString(StringSetting key, std::string* result) OVERRIDE { 199 const char* value = strings_table.Get(key); 200 if (value) { 201 *result = value; 202 return true; 203 } 204 return false; 205 } 206 207 virtual bool GetBool(BoolSetting key, bool* result) OVERRIDE { 208 BoolSettingValue value = bools_table.Get(key); 209 switch (value) { 210 case UNSET: 211 return false; 212 case TRUE: 213 *result = true; 214 break; 215 case FALSE: 216 *result = false; 217 } 218 return true; 219 } 220 221 virtual bool GetInt(IntSetting key, int* result) OVERRIDE { 222 // We don't bother to distinguish unset keys from 0 values. 223 *result = ints_table.Get(key); 224 return true; 225 } 226 227 virtual bool GetStringList(StringListSetting key, 228 std::vector<std::string>* result) OVERRIDE { 229 *result = string_lists_table.Get(key); 230 // We don't bother to distinguish unset keys from empty lists. 231 return !result->empty(); 232 } 233 234 virtual bool BypassListIsReversed() OVERRIDE { 235 return false; 236 } 237 238 virtual bool MatchHostsUsingSuffixMatching() OVERRIDE { 239 return false; 240 } 241 242 // Intentionally public, for convenience when setting up a test. 243 GConfValues values; 244 245 private: 246 SettingsTable<StringSetting, const char*> strings_table; 247 SettingsTable<BoolSetting, BoolSettingValue> bools_table; 248 SettingsTable<IntSetting, int> ints_table; 249 SettingsTable<StringListSetting, 250 std::vector<std::string> > string_lists_table; 251 }; 252 253 } // namespace 254 } // namespace net 255 256 // This helper class runs ProxyConfigServiceLinux::GetLatestProxyConfig() on 257 // the IO thread and synchronously waits for the result. 258 // Some code duplicated from proxy_script_fetcher_unittest.cc. 259 class SynchConfigGetter { 260 public: 261 // Takes ownership of |config_service|. 262 explicit SynchConfigGetter(net::ProxyConfigServiceLinux* config_service) 263 : event_(false, false), 264 io_thread_("IO_Thread"), 265 config_service_(config_service) { 266 // Start an IO thread. 267 base::Thread::Options options; 268 options.message_loop_type = base::MessageLoop::TYPE_IO; 269 io_thread_.StartWithOptions(options); 270 271 // Make sure the thread started. 272 io_thread_.message_loop()->PostTask(FROM_HERE, 273 base::Bind(&SynchConfigGetter::Init, base::Unretained(this))); 274 Wait(); 275 } 276 277 ~SynchConfigGetter() { 278 // Let the config service post a destroy message to the IO thread 279 // before cleaning up that thread. 280 delete config_service_; 281 // Clean up the IO thread. 282 io_thread_.message_loop()->PostTask(FROM_HERE, 283 base::Bind(&SynchConfigGetter::CleanUp, base::Unretained(this))); 284 Wait(); 285 } 286 287 // Does gconf setup and initial fetch of the proxy config, 288 // all on the calling thread (meant to be the thread with the 289 // default glib main loop, which is the UI thread). 290 void SetupAndInitialFetch() { 291 base::MessageLoop* file_loop = io_thread_.message_loop(); 292 DCHECK_EQ(base::MessageLoop::TYPE_IO, file_loop->type()); 293 // We pass the mock IO thread as both the IO and file threads. 294 config_service_->SetupAndFetchInitialConfig( 295 base::MessageLoopProxy::current().get(), 296 io_thread_.message_loop_proxy().get(), 297 static_cast<base::MessageLoopForIO*>(file_loop)); 298 } 299 // Synchronously gets the proxy config. 300 net::ProxyConfigService::ConfigAvailability SyncGetLatestProxyConfig( 301 net::ProxyConfig* config) { 302 io_thread_.message_loop()->PostTask(FROM_HERE, 303 base::Bind(&SynchConfigGetter::GetLatestConfigOnIOThread, 304 base::Unretained(this))); 305 Wait(); 306 *config = proxy_config_; 307 return get_latest_config_result_; 308 } 309 310 private: 311 // [Runs on |io_thread_|] 312 void Init() { 313 event_.Signal(); 314 } 315 316 // Calls GetLatestProxyConfig, running on |io_thread_| Signals |event_| 317 // on completion. 318 void GetLatestConfigOnIOThread() { 319 get_latest_config_result_ = 320 config_service_->GetLatestProxyConfig(&proxy_config_); 321 event_.Signal(); 322 } 323 324 // [Runs on |io_thread_|] Signals |event_| on cleanup completion. 325 void CleanUp() { 326 base::MessageLoop::current()->RunUntilIdle(); 327 event_.Signal(); 328 } 329 330 void Wait() { 331 event_.Wait(); 332 event_.Reset(); 333 } 334 335 base::WaitableEvent event_; 336 base::Thread io_thread_; 337 338 net::ProxyConfigServiceLinux* config_service_; 339 340 // The config obtained by |io_thread_| and read back by the main 341 // thread. 342 net::ProxyConfig proxy_config_; 343 344 // Return value from GetLatestProxyConfig(). 345 net::ProxyConfigService::ConfigAvailability get_latest_config_result_; 346 }; 347 348 namespace net { 349 350 // This test fixture is only really needed for the KDEConfigParser test case, 351 // but all the test cases with the same prefix ("ProxyConfigServiceLinuxTest") 352 // must use the same test fixture class (also "ProxyConfigServiceLinuxTest"). 353 class ProxyConfigServiceLinuxTest : public PlatformTest { 354 protected: 355 virtual void SetUp() OVERRIDE { 356 PlatformTest::SetUp(); 357 // Set up a temporary KDE home directory. 358 std::string prefix("ProxyConfigServiceLinuxTest_user_home"); 359 base::CreateNewTempDirectory(prefix, &user_home_); 360 kde_home_ = user_home_.Append(FILE_PATH_LITERAL(".kde")); 361 base::FilePath path = kde_home_.Append(FILE_PATH_LITERAL("share")); 362 path = path.Append(FILE_PATH_LITERAL("config")); 363 base::CreateDirectory(path); 364 kioslaverc_ = path.Append(FILE_PATH_LITERAL("kioslaverc")); 365 // Set up paths but do not create the directory for .kde4. 366 kde4_home_ = user_home_.Append(FILE_PATH_LITERAL(".kde4")); 367 path = kde4_home_.Append(FILE_PATH_LITERAL("share")); 368 kde4_config_ = path.Append(FILE_PATH_LITERAL("config")); 369 kioslaverc4_ = kde4_config_.Append(FILE_PATH_LITERAL("kioslaverc")); 370 } 371 372 virtual void TearDown() OVERRIDE { 373 // Delete the temporary KDE home directory. 374 base::DeleteFile(user_home_, true); 375 PlatformTest::TearDown(); 376 } 377 378 base::FilePath user_home_; 379 // KDE3 paths. 380 base::FilePath kde_home_; 381 base::FilePath kioslaverc_; 382 // KDE4 paths. 383 base::FilePath kde4_home_; 384 base::FilePath kde4_config_; 385 base::FilePath kioslaverc4_; 386 }; 387 388 // Builds an identifier for each test in an array. 389 #define TEST_DESC(desc) base::StringPrintf("at line %d <%s>", __LINE__, desc) 390 391 TEST_F(ProxyConfigServiceLinuxTest, BasicGConfTest) { 392 std::vector<std::string> empty_ignores; 393 394 std::vector<std::string> google_ignores; 395 google_ignores.push_back("*.google.com"); 396 397 // Inspired from proxy_config_service_win_unittest.cc. 398 // Very neat, but harder to track down failures though. 399 const struct { 400 // Short description to identify the test 401 std::string description; 402 403 // Input. 404 GConfValues values; 405 406 // Expected outputs (availability and fields of ProxyConfig). 407 ProxyConfigService::ConfigAvailability availability; 408 bool auto_detect; 409 GURL pac_url; 410 ProxyRulesExpectation proxy_rules; 411 } tests[] = { 412 { 413 TEST_DESC("No proxying"), 414 { // Input. 415 "none", // mode 416 "", // autoconfig_url 417 "", "", "", "", // hosts 418 0, 0, 0, 0, // ports 419 FALSE, FALSE, FALSE, // use, same, auth 420 empty_ignores, // ignore_hosts 421 }, 422 423 // Expected result. 424 ProxyConfigService::CONFIG_VALID, 425 false, // auto_detect 426 GURL(), // pac_url 427 ProxyRulesExpectation::Empty(), 428 }, 429 430 { 431 TEST_DESC("Auto detect"), 432 { // Input. 433 "auto", // mode 434 "", // autoconfig_url 435 "", "", "", "", // hosts 436 0, 0, 0, 0, // ports 437 FALSE, FALSE, FALSE, // use, same, auth 438 empty_ignores, // ignore_hosts 439 }, 440 441 // Expected result. 442 ProxyConfigService::CONFIG_VALID, 443 true, // auto_detect 444 GURL(), // pac_url 445 ProxyRulesExpectation::Empty(), 446 }, 447 448 { 449 TEST_DESC("Valid PAC URL"), 450 { // Input. 451 "auto", // mode 452 "http://wpad/wpad.dat", // autoconfig_url 453 "", "", "", "", // hosts 454 0, 0, 0, 0, // ports 455 FALSE, FALSE, FALSE, // use, same, auth 456 empty_ignores, // ignore_hosts 457 }, 458 459 // Expected result. 460 ProxyConfigService::CONFIG_VALID, 461 false, // auto_detect 462 GURL("http://wpad/wpad.dat"), // pac_url 463 ProxyRulesExpectation::Empty(), 464 }, 465 466 { 467 TEST_DESC("Invalid PAC URL"), 468 { // Input. 469 "auto", // mode 470 "wpad.dat", // autoconfig_url 471 "", "", "", "", // hosts 472 0, 0, 0, 0, // ports 473 FALSE, FALSE, FALSE, // use, same, auth 474 empty_ignores, // ignore_hosts 475 }, 476 477 // Expected result. 478 ProxyConfigService::CONFIG_VALID, 479 false, // auto_detect 480 GURL(), // pac_url 481 ProxyRulesExpectation::Empty(), 482 }, 483 484 { 485 TEST_DESC("Single-host in proxy list"), 486 { // Input. 487 "manual", // mode 488 "", // autoconfig_url 489 "www.google.com", "", "", "", // hosts 490 80, 0, 0, 0, // ports 491 TRUE, TRUE, FALSE, // use, same, auth 492 empty_ignores, // ignore_hosts 493 }, 494 495 // Expected result. 496 ProxyConfigService::CONFIG_VALID, 497 false, // auto_detect 498 GURL(), // pac_url 499 ProxyRulesExpectation::Single( 500 "www.google.com:80", // single proxy 501 ""), // bypass rules 502 }, 503 504 { 505 TEST_DESC("use_http_proxy is honored"), 506 { // Input. 507 "manual", // mode 508 "", // autoconfig_url 509 "www.google.com", "", "", "", // hosts 510 80, 0, 0, 0, // ports 511 FALSE, TRUE, FALSE, // use, same, auth 512 empty_ignores, // ignore_hosts 513 }, 514 515 // Expected result. 516 ProxyConfigService::CONFIG_VALID, 517 false, // auto_detect 518 GURL(), // pac_url 519 ProxyRulesExpectation::Empty(), 520 }, 521 522 { 523 TEST_DESC("use_http_proxy and use_same_proxy are optional"), 524 { // Input. 525 "manual", // mode 526 "", // autoconfig_url 527 "www.google.com", "", "", "", // hosts 528 80, 0, 0, 0, // ports 529 UNSET, UNSET, FALSE, // use, same, auth 530 empty_ignores, // ignore_hosts 531 }, 532 533 // Expected result. 534 ProxyConfigService::CONFIG_VALID, 535 false, // auto_detect 536 GURL(), // pac_url 537 ProxyRulesExpectation::PerScheme( 538 "www.google.com:80", // http 539 "", // https 540 "", // ftp 541 ""), // bypass rules 542 }, 543 544 { 545 TEST_DESC("Single-host, different port"), 546 { // Input. 547 "manual", // mode 548 "", // autoconfig_url 549 "www.google.com", "", "", "", // hosts 550 88, 0, 0, 0, // ports 551 TRUE, TRUE, FALSE, // use, same, auth 552 empty_ignores, // ignore_hosts 553 }, 554 555 // Expected result. 556 ProxyConfigService::CONFIG_VALID, 557 false, // auto_detect 558 GURL(), // pac_url 559 ProxyRulesExpectation::Single( 560 "www.google.com:88", // single proxy 561 ""), // bypass rules 562 }, 563 564 { 565 TEST_DESC("Per-scheme proxy rules"), 566 { // Input. 567 "manual", // mode 568 "", // autoconfig_url 569 "www.google.com", // http_host 570 "www.foo.com", // secure_host 571 "ftp.foo.com", // ftp 572 "", // socks 573 88, 110, 121, 0, // ports 574 TRUE, FALSE, FALSE, // use, same, auth 575 empty_ignores, // ignore_hosts 576 }, 577 578 // Expected result. 579 ProxyConfigService::CONFIG_VALID, 580 false, // auto_detect 581 GURL(), // pac_url 582 ProxyRulesExpectation::PerScheme( 583 "www.google.com:88", // http 584 "www.foo.com:110", // https 585 "ftp.foo.com:121", // ftp 586 ""), // bypass rules 587 }, 588 589 { 590 TEST_DESC("socks"), 591 { // Input. 592 "manual", // mode 593 "", // autoconfig_url 594 "", "", "", "socks.com", // hosts 595 0, 0, 0, 99, // ports 596 TRUE, FALSE, FALSE, // use, same, auth 597 empty_ignores, // ignore_hosts 598 }, 599 600 // Expected result. 601 ProxyConfigService::CONFIG_VALID, 602 false, // auto_detect 603 GURL(), // pac_url 604 ProxyRulesExpectation::Single( 605 "socks5://socks.com:99", // single proxy 606 "") // bypass rules 607 }, 608 609 { 610 TEST_DESC("Per-scheme proxy rules with fallback to SOCKS"), 611 { // Input. 612 "manual", // mode 613 "", // autoconfig_url 614 "www.google.com", // http_host 615 "www.foo.com", // secure_host 616 "ftp.foo.com", // ftp 617 "foobar.net", // socks 618 88, 110, 121, 99, // ports 619 TRUE, FALSE, FALSE, // use, same, auth 620 empty_ignores, // ignore_hosts 621 }, 622 623 // Expected result. 624 ProxyConfigService::CONFIG_VALID, 625 false, // auto_detect 626 GURL(), // pac_url 627 ProxyRulesExpectation::PerSchemeWithSocks( 628 "www.google.com:88", // http 629 "www.foo.com:110", // https 630 "ftp.foo.com:121", // ftp 631 "socks5://foobar.net:99", // socks 632 ""), // bypass rules 633 }, 634 635 { 636 TEST_DESC("Per-scheme proxy rules (just HTTP) with fallback to SOCKS"), 637 { // Input. 638 "manual", // mode 639 "", // autoconfig_url 640 "www.google.com", // http_host 641 "", // secure_host 642 "", // ftp 643 "foobar.net", // socks 644 88, 0, 0, 99, // ports 645 TRUE, FALSE, FALSE, // use, same, auth 646 empty_ignores, // ignore_hosts 647 }, 648 649 // Expected result. 650 ProxyConfigService::CONFIG_VALID, 651 false, // auto_detect 652 GURL(), // pac_url 653 ProxyRulesExpectation::PerSchemeWithSocks( 654 "www.google.com:88", // http 655 "", // https 656 "", // ftp 657 "socks5://foobar.net:99", // socks 658 ""), // bypass rules 659 }, 660 661 { 662 TEST_DESC("Bypass *.google.com"), 663 { // Input. 664 "manual", // mode 665 "", // autoconfig_url 666 "www.google.com", "", "", "", // hosts 667 80, 0, 0, 0, // ports 668 TRUE, TRUE, FALSE, // use, same, auth 669 google_ignores, // ignore_hosts 670 }, 671 672 ProxyConfigService::CONFIG_VALID, 673 false, // auto_detect 674 GURL(), // pac_url 675 ProxyRulesExpectation::Single( 676 "www.google.com:80", // single proxy 677 "*.google.com"), // bypass rules 678 }, 679 }; 680 681 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 682 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i, 683 tests[i].description.c_str())); 684 MockEnvironment* env = new MockEnvironment; 685 MockSettingGetter* setting_getter = new MockSettingGetter; 686 SynchConfigGetter sync_config_getter( 687 new ProxyConfigServiceLinux(env, setting_getter)); 688 ProxyConfig config; 689 setting_getter->values = tests[i].values; 690 sync_config_getter.SetupAndInitialFetch(); 691 ProxyConfigService::ConfigAvailability availability = 692 sync_config_getter.SyncGetLatestProxyConfig(&config); 693 EXPECT_EQ(tests[i].availability, availability); 694 695 if (availability == ProxyConfigService::CONFIG_VALID) { 696 EXPECT_EQ(tests[i].auto_detect, config.auto_detect()); 697 EXPECT_EQ(tests[i].pac_url, config.pac_url()); 698 EXPECT_TRUE(tests[i].proxy_rules.Matches(config.proxy_rules())); 699 } 700 } 701 } 702 703 TEST_F(ProxyConfigServiceLinuxTest, BasicEnvTest) { 704 // Inspired from proxy_config_service_win_unittest.cc. 705 const struct { 706 // Short description to identify the test 707 std::string description; 708 709 // Input. 710 EnvVarValues values; 711 712 // Expected outputs (availability and fields of ProxyConfig). 713 ProxyConfigService::ConfigAvailability availability; 714 bool auto_detect; 715 GURL pac_url; 716 ProxyRulesExpectation proxy_rules; 717 } tests[] = { 718 { 719 TEST_DESC("No proxying"), 720 { // Input. 721 NULL, // DESKTOP_SESSION 722 NULL, // HOME 723 NULL, // KDEHOME 724 NULL, // KDE_SESSION_VERSION 725 NULL, // auto_proxy 726 NULL, // all_proxy 727 NULL, NULL, NULL, // per-proto proxies 728 NULL, NULL, // SOCKS 729 "*", // no_proxy 730 }, 731 732 // Expected result. 733 ProxyConfigService::CONFIG_VALID, 734 false, // auto_detect 735 GURL(), // pac_url 736 ProxyRulesExpectation::Empty(), 737 }, 738 739 { 740 TEST_DESC("Auto detect"), 741 { // Input. 742 NULL, // DESKTOP_SESSION 743 NULL, // HOME 744 NULL, // KDEHOME 745 NULL, // KDE_SESSION_VERSION 746 "", // auto_proxy 747 NULL, // all_proxy 748 NULL, NULL, NULL, // per-proto proxies 749 NULL, NULL, // SOCKS 750 NULL, // no_proxy 751 }, 752 753 // Expected result. 754 ProxyConfigService::CONFIG_VALID, 755 true, // auto_detect 756 GURL(), // pac_url 757 ProxyRulesExpectation::Empty(), 758 }, 759 760 { 761 TEST_DESC("Valid PAC URL"), 762 { // Input. 763 NULL, // DESKTOP_SESSION 764 NULL, // HOME 765 NULL, // KDEHOME 766 NULL, // KDE_SESSION_VERSION 767 "http://wpad/wpad.dat", // auto_proxy 768 NULL, // all_proxy 769 NULL, NULL, NULL, // per-proto proxies 770 NULL, NULL, // SOCKS 771 NULL, // no_proxy 772 }, 773 774 // Expected result. 775 ProxyConfigService::CONFIG_VALID, 776 false, // auto_detect 777 GURL("http://wpad/wpad.dat"), // pac_url 778 ProxyRulesExpectation::Empty(), 779 }, 780 781 { 782 TEST_DESC("Invalid PAC URL"), 783 { // Input. 784 NULL, // DESKTOP_SESSION 785 NULL, // HOME 786 NULL, // KDEHOME 787 NULL, // KDE_SESSION_VERSION 788 "wpad.dat", // auto_proxy 789 NULL, // all_proxy 790 NULL, NULL, NULL, // per-proto proxies 791 NULL, NULL, // SOCKS 792 NULL, // no_proxy 793 }, 794 795 // Expected result. 796 ProxyConfigService::CONFIG_VALID, 797 false, // auto_detect 798 GURL(), // pac_url 799 ProxyRulesExpectation::Empty(), 800 }, 801 802 { 803 TEST_DESC("Single-host in proxy list"), 804 { // Input. 805 NULL, // DESKTOP_SESSION 806 NULL, // HOME 807 NULL, // KDEHOME 808 NULL, // KDE_SESSION_VERSION 809 NULL, // auto_proxy 810 "www.google.com", // all_proxy 811 NULL, NULL, NULL, // per-proto proxies 812 NULL, NULL, // SOCKS 813 NULL, // no_proxy 814 }, 815 816 // Expected result. 817 ProxyConfigService::CONFIG_VALID, 818 false, // auto_detect 819 GURL(), // pac_url 820 ProxyRulesExpectation::Single( 821 "www.google.com:80", // single proxy 822 ""), // bypass rules 823 }, 824 825 { 826 TEST_DESC("Single-host, different port"), 827 { // Input. 828 NULL, // DESKTOP_SESSION 829 NULL, // HOME 830 NULL, // KDEHOME 831 NULL, // KDE_SESSION_VERSION 832 NULL, // auto_proxy 833 "www.google.com:99", // all_proxy 834 NULL, NULL, NULL, // per-proto proxies 835 NULL, NULL, // SOCKS 836 NULL, // no_proxy 837 }, 838 839 // Expected result. 840 ProxyConfigService::CONFIG_VALID, 841 false, // auto_detect 842 GURL(), // pac_url 843 ProxyRulesExpectation::Single( 844 "www.google.com:99", // single 845 ""), // bypass rules 846 }, 847 848 { 849 TEST_DESC("Tolerate a scheme"), 850 { // Input. 851 NULL, // DESKTOP_SESSION 852 NULL, // HOME 853 NULL, // KDEHOME 854 NULL, // KDE_SESSION_VERSION 855 NULL, // auto_proxy 856 "http://www.google.com:99", // all_proxy 857 NULL, NULL, NULL, // per-proto proxies 858 NULL, NULL, // SOCKS 859 NULL, // no_proxy 860 }, 861 862 // Expected result. 863 ProxyConfigService::CONFIG_VALID, 864 false, // auto_detect 865 GURL(), // pac_url 866 ProxyRulesExpectation::Single( 867 "www.google.com:99", // single proxy 868 ""), // bypass rules 869 }, 870 871 { 872 TEST_DESC("Per-scheme proxy rules"), 873 { // Input. 874 NULL, // DESKTOP_SESSION 875 NULL, // HOME 876 NULL, // KDEHOME 877 NULL, // KDE_SESSION_VERSION 878 NULL, // auto_proxy 879 NULL, // all_proxy 880 "www.google.com:80", "www.foo.com:110", "ftp.foo.com:121", // per-proto 881 NULL, NULL, // SOCKS 882 NULL, // no_proxy 883 }, 884 885 // Expected result. 886 ProxyConfigService::CONFIG_VALID, 887 false, // auto_detect 888 GURL(), // pac_url 889 ProxyRulesExpectation::PerScheme( 890 "www.google.com:80", // http 891 "www.foo.com:110", // https 892 "ftp.foo.com:121", // ftp 893 ""), // bypass rules 894 }, 895 896 { 897 TEST_DESC("socks"), 898 { // Input. 899 NULL, // DESKTOP_SESSION 900 NULL, // HOME 901 NULL, // KDEHOME 902 NULL, // KDE_SESSION_VERSION 903 NULL, // auto_proxy 904 "", // all_proxy 905 NULL, NULL, NULL, // per-proto proxies 906 "socks.com:888", NULL, // SOCKS 907 NULL, // no_proxy 908 }, 909 910 // Expected result. 911 ProxyConfigService::CONFIG_VALID, 912 false, // auto_detect 913 GURL(), // pac_url 914 ProxyRulesExpectation::Single( 915 "socks5://socks.com:888", // single proxy 916 ""), // bypass rules 917 }, 918 919 { 920 TEST_DESC("socks4"), 921 { // Input. 922 NULL, // DESKTOP_SESSION 923 NULL, // HOME 924 NULL, // KDEHOME 925 NULL, // KDE_SESSION_VERSION 926 NULL, // auto_proxy 927 "", // all_proxy 928 NULL, NULL, NULL, // per-proto proxies 929 "socks.com:888", "4", // SOCKS 930 NULL, // no_proxy 931 }, 932 933 // Expected result. 934 ProxyConfigService::CONFIG_VALID, 935 false, // auto_detect 936 GURL(), // pac_url 937 ProxyRulesExpectation::Single( 938 "socks4://socks.com:888", // single proxy 939 ""), // bypass rules 940 }, 941 942 { 943 TEST_DESC("socks default port"), 944 { // Input. 945 NULL, // DESKTOP_SESSION 946 NULL, // HOME 947 NULL, // KDEHOME 948 NULL, // KDE_SESSION_VERSION 949 NULL, // auto_proxy 950 "", // all_proxy 951 NULL, NULL, NULL, // per-proto proxies 952 "socks.com", NULL, // SOCKS 953 NULL, // no_proxy 954 }, 955 956 // Expected result. 957 ProxyConfigService::CONFIG_VALID, 958 false, // auto_detect 959 GURL(), // pac_url 960 ProxyRulesExpectation::Single( 961 "socks5://socks.com:1080", // single proxy 962 ""), // bypass rules 963 }, 964 965 { 966 TEST_DESC("bypass"), 967 { // Input. 968 NULL, // DESKTOP_SESSION 969 NULL, // HOME 970 NULL, // KDEHOME 971 NULL, // KDE_SESSION_VERSION 972 NULL, // auto_proxy 973 "www.google.com", // all_proxy 974 NULL, NULL, NULL, // per-proto 975 NULL, NULL, // SOCKS 976 ".google.com, foo.com:99, 1.2.3.4:22, 127.0.0.1/8", // no_proxy 977 }, 978 979 // Expected result. 980 ProxyConfigService::CONFIG_VALID, 981 false, // auto_detect 982 GURL(), // pac_url 983 ProxyRulesExpectation::Single( 984 "www.google.com:80", 985 "*.google.com,*foo.com:99,1.2.3.4:22,127.0.0.1/8"), 986 }, 987 }; 988 989 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 990 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i, 991 tests[i].description.c_str())); 992 MockEnvironment* env = new MockEnvironment; 993 MockSettingGetter* setting_getter = new MockSettingGetter; 994 SynchConfigGetter sync_config_getter( 995 new ProxyConfigServiceLinux(env, setting_getter)); 996 ProxyConfig config; 997 env->values = tests[i].values; 998 sync_config_getter.SetupAndInitialFetch(); 999 ProxyConfigService::ConfigAvailability availability = 1000 sync_config_getter.SyncGetLatestProxyConfig(&config); 1001 EXPECT_EQ(tests[i].availability, availability); 1002 1003 if (availability == ProxyConfigService::CONFIG_VALID) { 1004 EXPECT_EQ(tests[i].auto_detect, config.auto_detect()); 1005 EXPECT_EQ(tests[i].pac_url, config.pac_url()); 1006 EXPECT_TRUE(tests[i].proxy_rules.Matches(config.proxy_rules())); 1007 } 1008 } 1009 } 1010 1011 TEST_F(ProxyConfigServiceLinuxTest, GconfNotification) { 1012 MockEnvironment* env = new MockEnvironment; 1013 MockSettingGetter* setting_getter = new MockSettingGetter; 1014 ProxyConfigServiceLinux* service = 1015 new ProxyConfigServiceLinux(env, setting_getter); 1016 SynchConfigGetter sync_config_getter(service); 1017 ProxyConfig config; 1018 1019 // Start with no proxy. 1020 setting_getter->values.mode = "none"; 1021 sync_config_getter.SetupAndInitialFetch(); 1022 EXPECT_EQ(ProxyConfigService::CONFIG_VALID, 1023 sync_config_getter.SyncGetLatestProxyConfig(&config)); 1024 EXPECT_FALSE(config.auto_detect()); 1025 1026 // Now set to auto-detect. 1027 setting_getter->values.mode = "auto"; 1028 // Simulate setting change notification callback. 1029 service->OnCheckProxyConfigSettings(); 1030 EXPECT_EQ(ProxyConfigService::CONFIG_VALID, 1031 sync_config_getter.SyncGetLatestProxyConfig(&config)); 1032 EXPECT_TRUE(config.auto_detect()); 1033 } 1034 1035 TEST_F(ProxyConfigServiceLinuxTest, KDEConfigParser) { 1036 // One of the tests below needs a worst-case long line prefix. We build it 1037 // programmatically so that it will always be the right size. 1038 std::string long_line; 1039 size_t limit = ProxyConfigServiceLinux::SettingGetter::BUFFER_SIZE - 1; 1040 for (size_t i = 0; i < limit; ++i) 1041 long_line += "-"; 1042 1043 // Inspired from proxy_config_service_win_unittest.cc. 1044 const struct { 1045 // Short description to identify the test 1046 std::string description; 1047 1048 // Input. 1049 std::string kioslaverc; 1050 EnvVarValues env_values; 1051 1052 // Expected outputs (availability and fields of ProxyConfig). 1053 ProxyConfigService::ConfigAvailability availability; 1054 bool auto_detect; 1055 GURL pac_url; 1056 ProxyRulesExpectation proxy_rules; 1057 } tests[] = { 1058 { 1059 TEST_DESC("No proxying"), 1060 1061 // Input. 1062 "[Proxy Settings]\nProxyType=0\n", 1063 {}, // env_values 1064 1065 // Expected result. 1066 ProxyConfigService::CONFIG_VALID, 1067 false, // auto_detect 1068 GURL(), // pac_url 1069 ProxyRulesExpectation::Empty(), 1070 }, 1071 1072 { 1073 TEST_DESC("Auto detect"), 1074 1075 // Input. 1076 "[Proxy Settings]\nProxyType=3\n", 1077 {}, // env_values 1078 1079 // Expected result. 1080 ProxyConfigService::CONFIG_VALID, 1081 true, // auto_detect 1082 GURL(), // pac_url 1083 ProxyRulesExpectation::Empty(), 1084 }, 1085 1086 { 1087 TEST_DESC("Valid PAC URL"), 1088 1089 // Input. 1090 "[Proxy Settings]\nProxyType=2\n" 1091 "Proxy Config Script=http://wpad/wpad.dat\n", 1092 {}, // env_values 1093 1094 // Expected result. 1095 ProxyConfigService::CONFIG_VALID, 1096 false, // auto_detect 1097 GURL("http://wpad/wpad.dat"), // pac_url 1098 ProxyRulesExpectation::Empty(), 1099 }, 1100 1101 { 1102 TEST_DESC("Valid PAC file without file://"), 1103 1104 // Input. 1105 "[Proxy Settings]\nProxyType=2\n" 1106 "Proxy Config Script=/wpad/wpad.dat\n", 1107 {}, // env_values 1108 1109 // Expected result. 1110 ProxyConfigService::CONFIG_VALID, 1111 false, // auto_detect 1112 GURL("file:///wpad/wpad.dat"), // pac_url 1113 ProxyRulesExpectation::Empty(), 1114 }, 1115 1116 { 1117 TEST_DESC("Per-scheme proxy rules"), 1118 1119 // Input. 1120 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n" 1121 "httpsProxy=www.foo.com\nftpProxy=ftp.foo.com\n", 1122 {}, // env_values 1123 1124 // Expected result. 1125 ProxyConfigService::CONFIG_VALID, 1126 false, // auto_detect 1127 GURL(), // pac_url 1128 ProxyRulesExpectation::PerScheme( 1129 "www.google.com:80", // http 1130 "www.foo.com:80", // https 1131 "ftp.foo.com:80", // http 1132 ""), // bypass rules 1133 }, 1134 1135 { 1136 TEST_DESC("Only HTTP proxy specified"), 1137 1138 // Input. 1139 "[Proxy Settings]\nProxyType=1\n" 1140 "httpProxy=www.google.com\n", 1141 {}, // env_values 1142 1143 // Expected result. 1144 ProxyConfigService::CONFIG_VALID, 1145 false, // auto_detect 1146 GURL(), // pac_url 1147 ProxyRulesExpectation::PerScheme( 1148 "www.google.com:80", // http 1149 "", // https 1150 "", // ftp 1151 ""), // bypass rules 1152 }, 1153 1154 { 1155 TEST_DESC("Only HTTP proxy specified, different port"), 1156 1157 // Input. 1158 "[Proxy Settings]\nProxyType=1\n" 1159 "httpProxy=www.google.com:88\n", 1160 {}, // env_values 1161 1162 // Expected result. 1163 ProxyConfigService::CONFIG_VALID, 1164 false, // auto_detect 1165 GURL(), // pac_url 1166 ProxyRulesExpectation::PerScheme( 1167 "www.google.com:88", // http 1168 "", // https 1169 "", // ftp 1170 ""), // bypass rules 1171 }, 1172 1173 { 1174 TEST_DESC("Only HTTP proxy specified, different port, space-delimited"), 1175 1176 // Input. 1177 "[Proxy Settings]\nProxyType=1\n" 1178 "httpProxy=www.google.com 88\n", 1179 {}, // env_values 1180 1181 // Expected result. 1182 ProxyConfigService::CONFIG_VALID, 1183 false, // auto_detect 1184 GURL(), // pac_url 1185 ProxyRulesExpectation::PerScheme( 1186 "www.google.com:88", // http 1187 "", // https 1188 "", // ftp 1189 ""), // bypass rules 1190 }, 1191 1192 { 1193 TEST_DESC("Bypass *.google.com"), 1194 1195 // Input. 1196 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n" 1197 "NoProxyFor=.google.com\n", 1198 {}, // env_values 1199 1200 // Expected result. 1201 ProxyConfigService::CONFIG_VALID, 1202 false, // auto_detect 1203 GURL(), // pac_url 1204 ProxyRulesExpectation::PerScheme( 1205 "www.google.com:80", // http 1206 "", // https 1207 "", // ftp 1208 "*.google.com"), // bypass rules 1209 }, 1210 1211 { 1212 TEST_DESC("Bypass *.google.com and *.kde.org"), 1213 1214 // Input. 1215 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n" 1216 "NoProxyFor=.google.com,.kde.org\n", 1217 {}, // env_values 1218 1219 // Expected result. 1220 ProxyConfigService::CONFIG_VALID, 1221 false, // auto_detect 1222 GURL(), // pac_url 1223 ProxyRulesExpectation::PerScheme( 1224 "www.google.com:80", // http 1225 "", // https 1226 "", // ftp 1227 "*.google.com,*.kde.org"), // bypass rules 1228 }, 1229 1230 { 1231 TEST_DESC("Correctly parse bypass list with ReversedException"), 1232 1233 // Input. 1234 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n" 1235 "NoProxyFor=.google.com\nReversedException=true\n", 1236 {}, // env_values 1237 1238 // Expected result. 1239 ProxyConfigService::CONFIG_VALID, 1240 false, // auto_detect 1241 GURL(), // pac_url 1242 ProxyRulesExpectation::PerSchemeWithBypassReversed( 1243 "www.google.com:80", // http 1244 "", // https 1245 "", // ftp 1246 "*.google.com"), // bypass rules 1247 }, 1248 1249 { 1250 TEST_DESC("socks"), 1251 1252 // Input. 1253 "[Proxy Settings]\nProxyType=1\nsocksProxy=socks.com 888\n", 1254 {}, // env_values 1255 1256 // Expected result. 1257 ProxyConfigService::CONFIG_VALID, 1258 false, // auto_detect 1259 GURL(), // pac_url 1260 ProxyRulesExpectation::Single( 1261 "socks5://socks.com:888", // single proxy 1262 ""), // bypass rules 1263 }, 1264 1265 { 1266 TEST_DESC("socks4"), 1267 1268 // Input. 1269 "[Proxy Settings]\nProxyType=1\nsocksProxy=socks4://socks.com 888\n", 1270 {}, // env_values 1271 1272 // Expected result. 1273 ProxyConfigService::CONFIG_VALID, 1274 false, // auto_detect 1275 GURL(), // pac_url 1276 ProxyRulesExpectation::Single( 1277 "socks4://socks.com:888", // single proxy 1278 ""), // bypass rules 1279 }, 1280 1281 { 1282 TEST_DESC("Treat all hostname patterns as wildcard patterns"), 1283 1284 // Input. 1285 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n" 1286 "NoProxyFor=google.com,kde.org,<local>\n", 1287 {}, // env_values 1288 1289 // Expected result. 1290 ProxyConfigService::CONFIG_VALID, 1291 false, // auto_detect 1292 GURL(), // pac_url 1293 ProxyRulesExpectation::PerScheme( 1294 "www.google.com:80", // http 1295 "", // https 1296 "", // ftp 1297 "*google.com,*kde.org,<local>"), // bypass rules 1298 }, 1299 1300 { 1301 TEST_DESC("Allow trailing whitespace after boolean value"), 1302 1303 // Input. 1304 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n" 1305 "NoProxyFor=.google.com\nReversedException=true \n", 1306 {}, // env_values 1307 1308 // Expected result. 1309 ProxyConfigService::CONFIG_VALID, 1310 false, // auto_detect 1311 GURL(), // pac_url 1312 ProxyRulesExpectation::PerSchemeWithBypassReversed( 1313 "www.google.com:80", // http 1314 "", // https 1315 "", // ftp 1316 "*.google.com"), // bypass rules 1317 }, 1318 1319 { 1320 TEST_DESC("Ignore settings outside [Proxy Settings]"), 1321 1322 // Input. 1323 "httpsProxy=www.foo.com\n[Proxy Settings]\nProxyType=1\n" 1324 "httpProxy=www.google.com\n[Other Section]\nftpProxy=ftp.foo.com\n", 1325 {}, // env_values 1326 1327 // Expected result. 1328 ProxyConfigService::CONFIG_VALID, 1329 false, // auto_detect 1330 GURL(), // pac_url 1331 ProxyRulesExpectation::PerScheme( 1332 "www.google.com:80", // http 1333 "", // https 1334 "", // ftp 1335 ""), // bypass rules 1336 }, 1337 1338 { 1339 TEST_DESC("Handle CRLF line endings"), 1340 1341 // Input. 1342 "[Proxy Settings]\r\nProxyType=1\r\nhttpProxy=www.google.com\r\n", 1343 {}, // env_values 1344 1345 // Expected result. 1346 ProxyConfigService::CONFIG_VALID, 1347 false, // auto_detect 1348 GURL(), // pac_url 1349 ProxyRulesExpectation::PerScheme( 1350 "www.google.com:80", // http 1351 "", // https 1352 "", // ftp 1353 ""), // bypass rules 1354 }, 1355 1356 { 1357 TEST_DESC("Handle blank lines and mixed line endings"), 1358 1359 // Input. 1360 "[Proxy Settings]\r\n\nProxyType=1\n\r\nhttpProxy=www.google.com\n\n", 1361 {}, // env_values 1362 1363 // Expected result. 1364 ProxyConfigService::CONFIG_VALID, 1365 false, // auto_detect 1366 GURL(), // pac_url 1367 ProxyRulesExpectation::PerScheme( 1368 "www.google.com:80", // http 1369 "", // https 1370 "", // ftp 1371 ""), // bypass rules 1372 }, 1373 1374 { 1375 TEST_DESC("Handle localized settings"), 1376 1377 // Input. 1378 "[Proxy Settings]\nProxyType[$e]=1\nhttpProxy[$e]=www.google.com\n", 1379 {}, // env_values 1380 1381 // Expected result. 1382 ProxyConfigService::CONFIG_VALID, 1383 false, // auto_detect 1384 GURL(), // pac_url 1385 ProxyRulesExpectation::PerScheme( 1386 "www.google.com:80", // http 1387 "", // https 1388 "", // ftp 1389 ""), // bypass rules 1390 }, 1391 1392 { 1393 TEST_DESC("Ignore malformed localized settings"), 1394 1395 // Input. 1396 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n" 1397 "httpsProxy$e]=www.foo.com\nftpProxy=ftp.foo.com\n", 1398 {}, // env_values 1399 1400 // Expected result. 1401 ProxyConfigService::CONFIG_VALID, 1402 false, // auto_detect 1403 GURL(), // pac_url 1404 ProxyRulesExpectation::PerScheme( 1405 "www.google.com:80", // http 1406 "", // https 1407 "ftp.foo.com:80", // ftp 1408 ""), // bypass rules 1409 }, 1410 1411 { 1412 TEST_DESC("Handle strange whitespace"), 1413 1414 // Input. 1415 "[Proxy Settings]\nProxyType [$e] =2\n" 1416 " Proxy Config Script = http:// foo\n", 1417 {}, // env_values 1418 1419 // Expected result. 1420 ProxyConfigService::CONFIG_VALID, 1421 false, // auto_detect 1422 GURL("http:// foo"), // pac_url 1423 ProxyRulesExpectation::Empty(), 1424 }, 1425 1426 { 1427 TEST_DESC("Ignore all of a line which is too long"), 1428 1429 // Input. 1430 std::string("[Proxy Settings]\nProxyType=1\nftpProxy=ftp.foo.com\n") + 1431 long_line + "httpsProxy=www.foo.com\nhttpProxy=www.google.com\n", 1432 {}, // env_values 1433 1434 // Expected result. 1435 ProxyConfigService::CONFIG_VALID, 1436 false, // auto_detect 1437 GURL(), // pac_url 1438 ProxyRulesExpectation::PerScheme( 1439 "www.google.com:80", // http 1440 "", // https 1441 "ftp.foo.com:80", // ftp 1442 ""), // bypass rules 1443 }, 1444 1445 { 1446 TEST_DESC("Indirect Proxy - no env vars set"), 1447 1448 // Input. 1449 "[Proxy Settings]\nProxyType=4\nhttpProxy=http_proxy\n" 1450 "httpsProxy=https_proxy\nftpProxy=ftp_proxy\nNoProxyFor=no_proxy\n", 1451 {}, // env_values 1452 1453 // Expected result. 1454 ProxyConfigService::CONFIG_VALID, 1455 false, // auto_detect 1456 GURL(), // pac_url 1457 ProxyRulesExpectation::Empty(), 1458 }, 1459 1460 { 1461 TEST_DESC("Indirect Proxy - with env vars set"), 1462 1463 // Input. 1464 "[Proxy Settings]\nProxyType=4\nhttpProxy=http_proxy\n" 1465 "httpsProxy=https_proxy\nftpProxy=ftp_proxy\nNoProxyFor=no_proxy\n", 1466 { // env_values 1467 NULL, // DESKTOP_SESSION 1468 NULL, // HOME 1469 NULL, // KDEHOME 1470 NULL, // KDE_SESSION_VERSION 1471 NULL, // auto_proxy 1472 NULL, // all_proxy 1473 "www.normal.com", // http_proxy 1474 "www.secure.com", // https_proxy 1475 "ftp.foo.com", // ftp_proxy 1476 NULL, NULL, // SOCKS 1477 ".google.com, .kde.org", // no_proxy 1478 }, 1479 1480 // Expected result. 1481 ProxyConfigService::CONFIG_VALID, 1482 false, // auto_detect 1483 GURL(), // pac_url 1484 ProxyRulesExpectation::PerScheme( 1485 "www.normal.com:80", // http 1486 "www.secure.com:80", // https 1487 "ftp.foo.com:80", // ftp 1488 "*.google.com,*.kde.org"), // bypass rules 1489 }, 1490 1491 }; 1492 1493 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 1494 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i, 1495 tests[i].description.c_str())); 1496 MockEnvironment* env = new MockEnvironment; 1497 env->values = tests[i].env_values; 1498 // Force the KDE getter to be used and tell it where the test is. 1499 env->values.DESKTOP_SESSION = "kde4"; 1500 env->values.KDEHOME = kde_home_.value().c_str(); 1501 SynchConfigGetter sync_config_getter( 1502 new ProxyConfigServiceLinux(env)); 1503 ProxyConfig config; 1504 // Overwrite the kioslaverc file. 1505 file_util::WriteFile(kioslaverc_, tests[i].kioslaverc.c_str(), 1506 tests[i].kioslaverc.length()); 1507 sync_config_getter.SetupAndInitialFetch(); 1508 ProxyConfigService::ConfigAvailability availability = 1509 sync_config_getter.SyncGetLatestProxyConfig(&config); 1510 EXPECT_EQ(tests[i].availability, availability); 1511 1512 if (availability == ProxyConfigService::CONFIG_VALID) { 1513 EXPECT_EQ(tests[i].auto_detect, config.auto_detect()); 1514 EXPECT_EQ(tests[i].pac_url, config.pac_url()); 1515 EXPECT_TRUE(tests[i].proxy_rules.Matches(config.proxy_rules())); 1516 } 1517 } 1518 } 1519 1520 TEST_F(ProxyConfigServiceLinuxTest, KDEHomePicker) { 1521 // Auto detect proxy settings. 1522 std::string slaverc3 = "[Proxy Settings]\nProxyType=3\n"; 1523 // Valid PAC URL. 1524 std::string slaverc4 = "[Proxy Settings]\nProxyType=2\n" 1525 "Proxy Config Script=http://wpad/wpad.dat\n"; 1526 GURL slaverc4_pac_url("http://wpad/wpad.dat"); 1527 1528 // Overwrite the .kde kioslaverc file. 1529 file_util::WriteFile(kioslaverc_, slaverc3.c_str(), slaverc3.length()); 1530 1531 // If .kde4 exists it will mess up the first test. It should not, as 1532 // we created the directory for $HOME in the test setup. 1533 CHECK(!base::DirectoryExists(kde4_home_)); 1534 1535 { SCOPED_TRACE("KDE4, no .kde4 directory, verify fallback"); 1536 MockEnvironment* env = new MockEnvironment; 1537 env->values.DESKTOP_SESSION = "kde4"; 1538 env->values.HOME = user_home_.value().c_str(); 1539 SynchConfigGetter sync_config_getter( 1540 new ProxyConfigServiceLinux(env)); 1541 ProxyConfig config; 1542 sync_config_getter.SetupAndInitialFetch(); 1543 EXPECT_EQ(ProxyConfigService::CONFIG_VALID, 1544 sync_config_getter.SyncGetLatestProxyConfig(&config)); 1545 EXPECT_TRUE(config.auto_detect()); 1546 EXPECT_EQ(GURL(), config.pac_url()); 1547 } 1548 1549 // Now create .kde4 and put a kioslaverc in the config directory. 1550 // Note that its timestamp will be at least as new as the .kde one. 1551 base::CreateDirectory(kde4_config_); 1552 file_util::WriteFile(kioslaverc4_, slaverc4.c_str(), slaverc4.length()); 1553 CHECK(base::PathExists(kioslaverc4_)); 1554 1555 { SCOPED_TRACE("KDE4, .kde4 directory present, use it"); 1556 MockEnvironment* env = new MockEnvironment; 1557 env->values.DESKTOP_SESSION = "kde4"; 1558 env->values.HOME = user_home_.value().c_str(); 1559 SynchConfigGetter sync_config_getter( 1560 new ProxyConfigServiceLinux(env)); 1561 ProxyConfig config; 1562 sync_config_getter.SetupAndInitialFetch(); 1563 EXPECT_EQ(ProxyConfigService::CONFIG_VALID, 1564 sync_config_getter.SyncGetLatestProxyConfig(&config)); 1565 EXPECT_FALSE(config.auto_detect()); 1566 EXPECT_EQ(slaverc4_pac_url, config.pac_url()); 1567 } 1568 1569 { SCOPED_TRACE("KDE3, .kde4 directory present, ignore it"); 1570 MockEnvironment* env = new MockEnvironment; 1571 env->values.DESKTOP_SESSION = "kde"; 1572 env->values.HOME = user_home_.value().c_str(); 1573 SynchConfigGetter sync_config_getter( 1574 new ProxyConfigServiceLinux(env)); 1575 ProxyConfig config; 1576 sync_config_getter.SetupAndInitialFetch(); 1577 EXPECT_EQ(ProxyConfigService::CONFIG_VALID, 1578 sync_config_getter.SyncGetLatestProxyConfig(&config)); 1579 EXPECT_TRUE(config.auto_detect()); 1580 EXPECT_EQ(GURL(), config.pac_url()); 1581 } 1582 1583 { SCOPED_TRACE("KDE4, .kde4 directory present, KDEHOME set to .kde"); 1584 MockEnvironment* env = new MockEnvironment; 1585 env->values.DESKTOP_SESSION = "kde4"; 1586 env->values.HOME = user_home_.value().c_str(); 1587 env->values.KDEHOME = kde_home_.value().c_str(); 1588 SynchConfigGetter sync_config_getter( 1589 new ProxyConfigServiceLinux(env)); 1590 ProxyConfig config; 1591 sync_config_getter.SetupAndInitialFetch(); 1592 EXPECT_EQ(ProxyConfigService::CONFIG_VALID, 1593 sync_config_getter.SyncGetLatestProxyConfig(&config)); 1594 EXPECT_TRUE(config.auto_detect()); 1595 EXPECT_EQ(GURL(), config.pac_url()); 1596 } 1597 1598 // Finally, make the .kde4 config directory older than the .kde directory 1599 // and make sure we then use .kde instead of .kde4 since it's newer. 1600 base::TouchFile(kde4_config_, base::Time(), base::Time()); 1601 1602 { SCOPED_TRACE("KDE4, very old .kde4 directory present, use .kde"); 1603 MockEnvironment* env = new MockEnvironment; 1604 env->values.DESKTOP_SESSION = "kde4"; 1605 env->values.HOME = user_home_.value().c_str(); 1606 SynchConfigGetter sync_config_getter( 1607 new ProxyConfigServiceLinux(env)); 1608 ProxyConfig config; 1609 sync_config_getter.SetupAndInitialFetch(); 1610 EXPECT_EQ(ProxyConfigService::CONFIG_VALID, 1611 sync_config_getter.SyncGetLatestProxyConfig(&config)); 1612 EXPECT_TRUE(config.auto_detect()); 1613 EXPECT_EQ(GURL(), config.pac_url()); 1614 } 1615 } 1616 1617 } // namespace net 1618