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