Home | History | Annotate | Download | only in proxy
      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