• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
Getnet::__anond879b91f0111::SettingsTable72   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:
MockEnvironment()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.
Reset()104   void Reset() {
105     EnvVarValues zero_values = { 0 };
106     values = zero_values;
107   }
108 
109   // Begin base::Environment implementation.
GetVar(const char * variable_name,std::string * result)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 
SetVar(const char * variable_name,const std::string & new_value)121   virtual bool SetVar(const char* variable_name, const std::string& new_value)
122       OVERRIDE {
123     ADD_FAILURE();
124     return false;
125   }
126 
UnSetVar(const char * variable_name)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;
MockSettingGetter()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.
Reset()173   void Reset() {
174     GConfValues zero_values = { 0 };
175     values = zero_values;
176   }
177 
Init(base::SingleThreadTaskRunner * glib_thread_task_runner,base::MessageLoopForIO * file_loop)178   virtual bool Init(base::SingleThreadTaskRunner* glib_thread_task_runner,
179                     base::MessageLoopForIO* file_loop) OVERRIDE {
180     return true;
181   }
182 
ShutDown()183   virtual void ShutDown() OVERRIDE {}
184 
SetUpNotifications(ProxyConfigServiceLinux::Delegate * delegate)185   virtual bool SetUpNotifications(ProxyConfigServiceLinux::Delegate* delegate)
186       OVERRIDE {
187     return true;
188   }
189 
GetNotificationTaskRunner()190   virtual base::SingleThreadTaskRunner* GetNotificationTaskRunner() OVERRIDE {
191     return NULL;
192   }
193 
GetConfigSource()194   virtual ProxyConfigSource GetConfigSource() OVERRIDE {
195     return PROXY_CONFIG_SOURCE_TEST;
196   }
197 
GetString(StringSetting key,std::string * result)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 
GetBool(BoolSetting key,bool * result)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 
GetInt(IntSetting key,int * result)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 
GetStringList(StringListSetting key,std::vector<std::string> * result)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 
BypassListIsReversed()234   virtual bool BypassListIsReversed() OVERRIDE {
235     return false;
236   }
237 
MatchHostsUsingSuffixMatching()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|.
SynchConfigGetter(net::ProxyConfigServiceLinux * 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 
~SynchConfigGetter()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).
SetupAndInitialFetch()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.
SyncGetLatestProxyConfig(net::ProxyConfig * 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_|]
Init()312   void Init() {
313     event_.Signal();
314   }
315 
316   // Calls GetLatestProxyConfig, running on |io_thread_| Signals |event_|
317   // on completion.
GetLatestConfigOnIOThread()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.
CleanUp()325   void CleanUp() {
326     base::MessageLoop::current()->RunUntilIdle();
327     event_.Signal();
328   }
329 
Wait()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:
SetUp()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 
TearDown()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 
TEST_F(ProxyConfigServiceLinuxTest,BasicGConfTest)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 
TEST_F(ProxyConfigServiceLinuxTest,BasicEnvTest)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 
TEST_F(ProxyConfigServiceLinuxTest,GconfNotification)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 
TEST_F(ProxyConfigServiceLinuxTest,KDEConfigParser)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     base::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 
TEST_F(ProxyConfigServiceLinuxTest,KDEHomePicker)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   base::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   base::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