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