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
25namespace net {
26namespace {
27
28// Set of values for all environment variables that we might
29// query. NULL represents an unset variable.
30struct 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.
47enum BoolSettingValue {
48  UNSET = 0, TRUE, FALSE
49};
50
51// Set of values for all gconf settings that we might query.
52struct 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).
66template<typename value_type>
67struct SettingsTable {
68  typedef std::map<std::string, value_type*> map_type;
69
70  // Gets the value from its location
71  value_type Get(const std::string& key) {
72    typename map_type::const_iterator it = settings.find(key);
73    // In case there's a typo or the unittest becomes out of sync.
74    CHECK(it != settings.end()) << "key " << key << " not found";
75    value_type* value_ptr = it->second;
76    return *value_ptr;
77  }
78
79  map_type settings;
80};
81
82class MockEnvironment : public base::Environment {
83 public:
84  MockEnvironment() {
85#define ENTRY(x) table.settings[#x] = &values.x
86    ENTRY(DESKTOP_SESSION);
87    ENTRY(HOME);
88    ENTRY(KDEHOME);
89    ENTRY(KDE_SESSION_VERSION);
90    ENTRY(auto_proxy);
91    ENTRY(all_proxy);
92    ENTRY(http_proxy);
93    ENTRY(https_proxy);
94    ENTRY(ftp_proxy);
95    ENTRY(no_proxy);
96    ENTRY(SOCKS_SERVER);
97    ENTRY(SOCKS_VERSION);
98#undef ENTRY
99    Reset();
100  }
101
102  // Zeros all environment values.
103  void Reset() {
104    EnvVarValues zero_values = { 0 };
105    values = zero_values;
106  }
107
108  // Begin base::Environment implementation.
109  virtual bool GetVar(const char* variable_name, std::string* result) {
110    const char* env_value = table.Get(variable_name);
111    if (env_value) {
112      // Note that the variable may be defined but empty.
113      *result = env_value;
114      return true;
115    }
116    return false;
117  }
118
119  virtual bool SetVar(const char* variable_name, const std::string& new_value) {
120    ADD_FAILURE();
121    return false;
122  }
123
124  virtual bool UnSetVar(const char* variable_name) {
125    ADD_FAILURE();
126    return false;
127  }
128  // End base::Environment implementation.
129
130  // Intentionally public, for convenience when setting up a test.
131  EnvVarValues values;
132
133 private:
134  SettingsTable<const char*> table;
135};
136
137class MockGConfSettingGetter
138    : public ProxyConfigServiceLinux::GConfSettingGetter {
139 public:
140  MockGConfSettingGetter() {
141#define ENTRY(key, field) \
142      strings_table.settings["/system/" key] = &values.field
143    ENTRY("proxy/mode", mode);
144    ENTRY("proxy/autoconfig_url", autoconfig_url);
145    ENTRY("http_proxy/host", http_host);
146    ENTRY("proxy/secure_host", secure_host);
147    ENTRY("proxy/ftp_host", ftp_host);
148    ENTRY("proxy/socks_host", socks_host);
149#undef ENTRY
150#define ENTRY(key, field) \
151      ints_table.settings["/system/" key] = &values.field
152    ENTRY("http_proxy/port", http_port);
153    ENTRY("proxy/secure_port", secure_port);
154    ENTRY("proxy/ftp_port", ftp_port);
155    ENTRY("proxy/socks_port", socks_port);
156#undef ENTRY
157#define ENTRY(key, field) \
158      bools_table.settings["/system/" key] = &values.field
159    ENTRY("http_proxy/use_http_proxy", use_proxy);
160    ENTRY("http_proxy/use_same_proxy", same_proxy);
161    ENTRY("http_proxy/use_authentication", use_auth);
162#undef ENTRY
163    string_lists_table.settings["/system/http_proxy/ignore_hosts"] =
164      &values.ignore_hosts;
165    Reset();
166  }
167
168  // Zeros all environment values.
169  void Reset() {
170    GConfValues zero_values = { 0 };
171    values = zero_values;
172  }
173
174  virtual bool Init(MessageLoop* glib_default_loop,
175                    MessageLoopForIO* file_loop) {
176    return true;
177  }
178
179  virtual void Shutdown() {}
180
181  virtual bool SetupNotification(ProxyConfigServiceLinux::Delegate* delegate) {
182    return true;
183  }
184
185  virtual MessageLoop* GetNotificationLoop() {
186    return NULL;
187  }
188
189  virtual const char* GetDataSource() {
190    return "test";
191  }
192
193  virtual bool GetString(const char* key, std::string* result) {
194    const char* value = strings_table.Get(key);
195    if (value) {
196      *result = value;
197      return true;
198    }
199    return false;
200  }
201
202  virtual bool GetInt(const char* key, int* result) {
203    // We don't bother to distinguish unset keys from 0 values.
204    *result = ints_table.Get(key);
205    return true;
206  }
207
208  virtual bool GetBoolean(const char* key, bool* result) {
209    BoolSettingValue value = bools_table.Get(key);
210    switch (value) {
211    case UNSET:
212      return false;
213    case TRUE:
214      *result = true;
215      break;
216    case FALSE:
217      *result = false;
218    }
219    return true;
220  }
221
222  virtual bool GetStringList(const char* key,
223                             std::vector<std::string>* result) {
224    *result = string_lists_table.Get(key);
225    // We don't bother to distinguish unset keys from empty lists.
226    return !result->empty();
227  }
228
229  virtual bool BypassListIsReversed() {
230    return false;
231  }
232
233  virtual bool MatchHostsUsingSuffixMatching() {
234    return false;
235  }
236
237  // Intentionally public, for convenience when setting up a test.
238  GConfValues values;
239
240 private:
241  SettingsTable<const char*> strings_table;
242  SettingsTable<int> ints_table;
243  SettingsTable<BoolSettingValue> bools_table;
244  SettingsTable<std::vector<std::string> > string_lists_table;
245};
246
247}  // namespace
248}  // namespace net
249
250// This helper class runs ProxyConfigServiceLinux::GetLatestProxyConfig() on
251// the IO thread and synchronously waits for the result.
252// Some code duplicated from proxy_script_fetcher_unittest.cc.
253class SynchConfigGetter {
254 public:
255  // Takes ownership of |config_service|.
256  explicit SynchConfigGetter(net::ProxyConfigServiceLinux* config_service)
257      : event_(false, false),
258        io_thread_("IO_Thread"),
259        config_service_(config_service) {
260    // Start an IO thread.
261    base::Thread::Options options;
262    options.message_loop_type = MessageLoop::TYPE_IO;
263    io_thread_.StartWithOptions(options);
264
265    // Make sure the thread started.
266    io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
267        this, &SynchConfigGetter::Init));
268    Wait();
269  }
270
271  ~SynchConfigGetter() {
272    // Let the config service post a destroy message to the IO thread
273    // before cleaning up that thread.
274    delete config_service_;
275    // Clean up the IO thread.
276    io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
277        this, &SynchConfigGetter::Cleanup));
278    Wait();
279  }
280
281  // Does gconf setup and initial fetch of the proxy config,
282  // all on the calling thread (meant to be the thread with the
283  // default glib main loop, which is the UI thread).
284  void SetupAndInitialFetch() {
285    MessageLoop* file_loop = io_thread_.message_loop();
286    DCHECK_EQ(MessageLoop::TYPE_IO, file_loop->type());
287    // We pass the mock IO thread as both the IO and file threads.
288    config_service_->SetupAndFetchInitialConfig(
289        MessageLoop::current(), io_thread_.message_loop(),
290        static_cast<MessageLoopForIO*>(file_loop));
291  }
292  // Synchronously gets the proxy config.
293  net::ProxyConfigService::ConfigAvailability SyncGetLatestProxyConfig(
294      net::ProxyConfig* config) {
295    io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
296        this, &SynchConfigGetter::GetLatestConfigOnIOThread));
297    Wait();
298    *config = proxy_config_;
299    return get_latest_config_result_;
300  }
301
302 private:
303  // [Runs on |io_thread_|]
304  void Init() {
305    event_.Signal();
306  }
307
308  // Calls GetLatestProxyConfig, running on |io_thread_| Signals |event_|
309  // on completion.
310  void GetLatestConfigOnIOThread() {
311    get_latest_config_result_ =
312        config_service_->GetLatestProxyConfig(&proxy_config_);
313    event_.Signal();
314  }
315
316  // [Runs on |io_thread_|] Signals |event_| on cleanup completion.
317  void Cleanup() {
318    MessageLoop::current()->RunAllPending();
319    event_.Signal();
320  }
321
322  void Wait() {
323    event_.Wait();
324    event_.Reset();
325  }
326
327  base::WaitableEvent event_;
328  base::Thread io_thread_;
329
330  net::ProxyConfigServiceLinux* config_service_;
331
332  // The config obtained by |io_thread_| and read back by the main
333  // thread.
334  net::ProxyConfig proxy_config_;
335
336  // Return value from GetLatestProxyConfig().
337  net::ProxyConfigService::ConfigAvailability get_latest_config_result_;
338};
339
340DISABLE_RUNNABLE_METHOD_REFCOUNT(SynchConfigGetter);
341
342namespace 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").
347class ProxyConfigServiceLinuxTest : public PlatformTest {
348 protected:
349  virtual void SetUp() {
350    PlatformTest::SetUp();
351    // Set up a temporary KDE home directory.
352    std::string prefix("ProxyConfigServiceLinuxTest_user_home");
353    file_util::CreateNewTempDirectory(prefix, &user_home_);
354    kde_home_ = user_home_.Append(FILE_PATH_LITERAL(".kde"));
355    FilePath path = kde_home_.Append(FILE_PATH_LITERAL("share"));
356    path = path.Append(FILE_PATH_LITERAL("config"));
357    file_util::CreateDirectory(path);
358    kioslaverc_ = path.Append(FILE_PATH_LITERAL("kioslaverc"));
359    // Set up paths but do not create the directory for .kde4.
360    kde4_home_ = user_home_.Append(FILE_PATH_LITERAL(".kde4"));
361    path = kde4_home_.Append(FILE_PATH_LITERAL("share"));
362    kde4_config_ = path.Append(FILE_PATH_LITERAL("config"));
363    kioslaverc4_ = kde4_config_.Append(FILE_PATH_LITERAL("kioslaverc"));
364  }
365
366  virtual void TearDown() {
367    // Delete the temporary KDE home directory.
368    file_util::Delete(user_home_, true);
369    PlatformTest::TearDown();
370  }
371
372  FilePath user_home_;
373  // KDE3 paths.
374  FilePath kde_home_;
375  FilePath kioslaverc_;
376  // KDE4 paths.
377  FilePath kde4_home_;
378  FilePath kde4_config_;
379  FilePath kioslaverc4_;
380};
381
382// Builds an identifier for each test in an array.
383#define TEST_DESC(desc) base::StringPrintf("at line %d <%s>", __LINE__, desc)
384
385TEST_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
645TEST_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
953TEST_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
977TEST_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
1396TEST_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