• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
Getnet::__anon0bb115370111::SettingsTable71   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:
MockEnvironment()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.
Reset()103   void Reset() {
104     EnvVarValues zero_values = { 0 };
105     values = zero_values;
106   }
107 
108   // Begin base::Environment implementation.
GetVar(const char * variable_name,std::string * result)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 
SetVar(const char * variable_name,const std::string & new_value)119   virtual bool SetVar(const char* variable_name, const std::string& new_value) {
120     ADD_FAILURE();
121     return false;
122   }
123 
UnSetVar(const char * variable_name)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:
MockGConfSettingGetter()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.
Reset()169   void Reset() {
170     GConfValues zero_values = { 0 };
171     values = zero_values;
172   }
173 
Init(MessageLoop * glib_default_loop,MessageLoopForIO * file_loop)174   virtual bool Init(MessageLoop* glib_default_loop,
175                     MessageLoopForIO* file_loop) {
176     return true;
177   }
178 
Shutdown()179   virtual void Shutdown() {}
180 
SetupNotification(ProxyConfigServiceLinux::Delegate * delegate)181   virtual bool SetupNotification(ProxyConfigServiceLinux::Delegate* delegate) {
182     return true;
183   }
184 
GetNotificationLoop()185   virtual MessageLoop* GetNotificationLoop() {
186     return NULL;
187   }
188 
GetDataSource()189   virtual const char* GetDataSource() {
190     return "test";
191   }
192 
GetString(const char * key,std::string * result)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 
GetInt(const char * key,int * result)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 
GetBoolean(const char * key,bool * result)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 
GetStringList(const char * key,std::vector<std::string> * result)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 
BypassListIsReversed()229   virtual bool BypassListIsReversed() {
230     return false;
231   }
232 
MatchHostsUsingSuffixMatching()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|.
SynchConfigGetter(net::ProxyConfigServiceLinux * 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 
~SynchConfigGetter()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).
SetupAndInitialFetch()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.
SyncGetLatestProxyConfig(net::ProxyConfig * 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_|]
Init()304   void Init() {
305     event_.Signal();
306   }
307 
308   // Calls GetLatestProxyConfig, running on |io_thread_| Signals |event_|
309   // on completion.
GetLatestConfigOnIOThread()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.
Cleanup()317   void Cleanup() {
318     MessageLoop::current()->RunAllPending();
319     event_.Signal();
320   }
321 
Wait()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:
SetUp()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 
TearDown()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 
TEST_F(ProxyConfigServiceLinuxTest,BasicGConfTest)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 
TEST_F(ProxyConfigServiceLinuxTest,BasicEnvTest)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 
TEST_F(ProxyConfigServiceLinuxTest,GconfNotification)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 
TEST_F(ProxyConfigServiceLinuxTest,KDEConfigParser)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 
TEST_F(ProxyConfigServiceLinuxTest,KDEHomePicker)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