1 // Copyright 2012 The Chromium Authors
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_resolution/proxy_config_service_linux.h"
6
7 #include <map>
8 #include <string>
9 #include <string_view>
10 #include <vector>
11
12 #include "base/check.h"
13 #include "base/compiler_specific.h"
14 #include "base/files/file_path.h"
15 #include "base/files/file_util.h"
16 #include "base/format_macros.h"
17 #include "base/functional/bind.h"
18 #include "base/location.h"
19 #include "base/memory/raw_ptr.h"
20 #include "base/message_loop/message_pump_type.h"
21 #include "base/run_loop.h"
22 #include "base/strings/string_util.h"
23 #include "base/strings/stringprintf.h"
24 #include "base/synchronization/lock.h"
25 #include "base/synchronization/waitable_event.h"
26 #include "base/task/sequenced_task_runner.h"
27 #include "base/task/single_thread_task_runner.h"
28 #include "base/task/thread_pool/thread_pool_instance.h"
29 #include "base/threading/thread.h"
30 #include "base/time/time.h"
31 #include "net/proxy_resolution/proxy_config.h"
32 #include "net/proxy_resolution/proxy_config_service_common_unittest.h"
33 #include "net/test/test_with_task_environment.h"
34 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36 #include "testing/platform_test.h"
37
38 // TODO(eroman): Convert these to parameterized tests using TEST_P().
39
40 namespace net {
41 namespace {
42
43 // Set of values for all environment variables that we might
44 // query. NULL represents an unset variable.
45 struct EnvVarValues {
46 // The strange capitalization is so that the field matches the
47 // environment variable name exactly.
48 const char* DESKTOP_SESSION;
49 const char* HOME;
50 const char* KDEHOME;
51 const char* KDE_SESSION_VERSION;
52 const char* XDG_CURRENT_DESKTOP;
53 const char* auto_proxy;
54 const char* all_proxy;
55 const char* http_proxy;
56 const char* https_proxy;
57 const char* ftp_proxy;
58 const char* SOCKS_SERVER;
59 const char* SOCKS_VERSION;
60 const char* no_proxy;
61 const char* XDG_CONFIG_DIRS;
62 };
63
64 // Undo macro pollution from GDK includes (from message_loop.h).
65 #undef TRUE
66 #undef FALSE
67
68 // So as to distinguish between an unset boolean variable and
69 // one that is false.
70 enum BoolSettingValue { UNSET = 0, TRUE, FALSE };
71
72 // Set of values for all gsettings settings that we might query.
73 struct GSettingsValues {
74 // strings
75 const char* mode;
76 const char* autoconfig_url;
77 const char* http_host;
78 const char* secure_host;
79 const char* ftp_host;
80 const char* socks_host;
81 // integers
82 int http_port;
83 int secure_port;
84 int ftp_port;
85 int socks_port;
86 // booleans
87 BoolSettingValue use_proxy;
88 BoolSettingValue same_proxy;
89 BoolSettingValue use_auth;
90 // string list
91 std::vector<std::string> ignore_hosts;
92 };
93
94 // Mapping from a setting name to the location of the corresponding
95 // value (inside a EnvVarValues or GSettingsValues struct).
96 template <typename key_type, typename value_type>
97 struct SettingsTable {
98 typedef std::map<key_type, value_type*> map_type;
99
100 // Gets the value from its location
Getnet::__anondc2941640111::SettingsTable101 value_type Get(key_type key) {
102 auto it = settings.find(key);
103 // In case there's a typo or the unittest becomes out of sync.
104 CHECK(it != settings.end()) << "key " << key << " not found";
105 value_type* value_ptr = it->second;
106 return *value_ptr;
107 }
108
109 map_type settings;
110 };
111
112 class MockEnvironment : public base::Environment {
113 public:
MockEnvironment()114 MockEnvironment() {
115 #define ENTRY(x) table_[#x] = &values.x
116 ENTRY(DESKTOP_SESSION);
117 ENTRY(HOME);
118 ENTRY(KDEHOME);
119 ENTRY(KDE_SESSION_VERSION);
120 ENTRY(XDG_CURRENT_DESKTOP);
121 ENTRY(auto_proxy);
122 ENTRY(all_proxy);
123 ENTRY(http_proxy);
124 ENTRY(https_proxy);
125 ENTRY(ftp_proxy);
126 ENTRY(no_proxy);
127 ENTRY(SOCKS_SERVER);
128 ENTRY(SOCKS_VERSION);
129 ENTRY(XDG_CONFIG_DIRS);
130 #undef ENTRY
131 Reset();
132 }
133
134 // Zeroes all environment values.
Reset()135 void Reset() {
136 EnvVarValues zero_values = {nullptr};
137 values = zero_values;
138 }
139
140 // Begin base::Environment implementation.
GetVar(std::string_view variable_name,std::string * result)141 bool GetVar(std::string_view variable_name, std::string* result) override {
142 auto it = table_.find(variable_name);
143 if (it == table_.end() || !*it->second)
144 return false;
145
146 // Note that the variable may be defined but empty.
147 *result = *(it->second);
148 return true;
149 }
150
SetVar(std::string_view variable_name,const std::string & new_value)151 bool SetVar(std::string_view variable_name,
152 const std::string& new_value) override {
153 ADD_FAILURE();
154 return false;
155 }
156
UnSetVar(std::string_view variable_name)157 bool UnSetVar(std::string_view variable_name) override {
158 ADD_FAILURE();
159 return false;
160 }
161 // End base::Environment implementation.
162
163 // Intentionally public, for convenience when setting up a test.
164 EnvVarValues values;
165
166 private:
167 std::map<std::string_view, const char**> table_;
168 };
169
170 class MockSettingGetter : public ProxyConfigServiceLinux::SettingGetter {
171 public:
172 typedef ProxyConfigServiceLinux::SettingGetter SettingGetter;
MockSettingGetter()173 MockSettingGetter() {
174 #define ENTRY(key, field) \
175 strings_table.settings[SettingGetter::key] = &values.field
176 ENTRY(PROXY_MODE, mode);
177 ENTRY(PROXY_AUTOCONF_URL, autoconfig_url);
178 ENTRY(PROXY_HTTP_HOST, http_host);
179 ENTRY(PROXY_HTTPS_HOST, secure_host);
180 ENTRY(PROXY_FTP_HOST, ftp_host);
181 ENTRY(PROXY_SOCKS_HOST, socks_host);
182 #undef ENTRY
183 #define ENTRY(key, field) \
184 ints_table.settings[SettingGetter::key] = &values.field
185 ENTRY(PROXY_HTTP_PORT, http_port);
186 ENTRY(PROXY_HTTPS_PORT, secure_port);
187 ENTRY(PROXY_FTP_PORT, ftp_port);
188 ENTRY(PROXY_SOCKS_PORT, socks_port);
189 #undef ENTRY
190 #define ENTRY(key, field) \
191 bools_table.settings[SettingGetter::key] = &values.field
192 ENTRY(PROXY_USE_HTTP_PROXY, use_proxy);
193 ENTRY(PROXY_USE_SAME_PROXY, same_proxy);
194 ENTRY(PROXY_USE_AUTHENTICATION, use_auth);
195 #undef ENTRY
196 string_lists_table.settings[SettingGetter::PROXY_IGNORE_HOSTS] =
197 &values.ignore_hosts;
198 Reset();
199 }
200
201 // Zeros all environment values.
Reset()202 void Reset() {
203 GSettingsValues zero_values = {nullptr};
204 values = zero_values;
205 }
206
Init(const scoped_refptr<base::SingleThreadTaskRunner> & glib_task_runner)207 bool Init(const scoped_refptr<base::SingleThreadTaskRunner>& glib_task_runner)
208 override {
209 task_runner_ = glib_task_runner;
210 return true;
211 }
212
ShutDown()213 void ShutDown() override {}
214
SetUpNotifications(ProxyConfigServiceLinux::Delegate * delegate)215 bool SetUpNotifications(
216 ProxyConfigServiceLinux::Delegate* delegate) override {
217 return true;
218 }
219
GetNotificationTaskRunner()220 const scoped_refptr<base::SequencedTaskRunner>& GetNotificationTaskRunner()
221 override {
222 return task_runner_;
223 }
224
GetString(StringSetting key,std::string * result)225 bool GetString(StringSetting key, std::string* result) override {
226 const char* value = strings_table.Get(key);
227 if (value) {
228 *result = value;
229 return true;
230 }
231 return false;
232 }
233
GetBool(BoolSetting key,bool * result)234 bool GetBool(BoolSetting key, bool* result) override {
235 BoolSettingValue value = bools_table.Get(key);
236 switch (value) {
237 case UNSET:
238 return false;
239 case TRUE:
240 *result = true;
241 break;
242 case FALSE:
243 *result = false;
244 }
245 return true;
246 }
247
GetInt(IntSetting key,int * result)248 bool GetInt(IntSetting key, int* result) override {
249 // We don't bother to distinguish unset keys from 0 values.
250 *result = ints_table.Get(key);
251 return true;
252 }
253
GetStringList(StringListSetting key,std::vector<std::string> * result)254 bool GetStringList(StringListSetting key,
255 std::vector<std::string>* result) override {
256 *result = string_lists_table.Get(key);
257 // We don't bother to distinguish unset keys from empty lists.
258 return !result->empty();
259 }
260
BypassListIsReversed()261 bool BypassListIsReversed() override { return false; }
262
UseSuffixMatching()263 bool UseSuffixMatching() override { return false; }
264
265 // Intentionally public, for convenience when setting up a test.
266 GSettingsValues values;
267
268 private:
269 scoped_refptr<base::SequencedTaskRunner> task_runner_;
270 SettingsTable<StringSetting, const char*> strings_table;
271 SettingsTable<BoolSetting, BoolSettingValue> bools_table;
272 SettingsTable<IntSetting, int> ints_table;
273 SettingsTable<StringListSetting, std::vector<std::string>> string_lists_table;
274 };
275
276 // This helper class runs ProxyConfigServiceLinux::GetLatestProxyConfig() on
277 // the main TaskRunner and synchronously waits for the result.
278 // Some code duplicated from pac_file_fetcher_unittest.cc.
279 class SyncConfigGetter : public ProxyConfigService::Observer {
280 public:
SyncConfigGetter(std::unique_ptr<ProxyConfigServiceLinux> config_service)281 explicit SyncConfigGetter(
282 std::unique_ptr<ProxyConfigServiceLinux> config_service)
283 : event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
284 base::WaitableEvent::InitialState::NOT_SIGNALED),
285 main_thread_("Main_Thread"),
286 config_service_(std::move(config_service)),
287 matches_pac_url_event_(
288 base::WaitableEvent::ResetPolicy::AUTOMATIC,
289 base::WaitableEvent::InitialState::NOT_SIGNALED) {
290 // Start the main IO thread.
291 base::Thread::Options options;
292 options.message_pump_type = base::MessagePumpType::IO;
293 main_thread_.StartWithOptions(std::move(options));
294
295 // Make sure the thread started.
296 main_thread_.task_runner()->PostTask(
297 FROM_HERE,
298 base::BindOnce(&SyncConfigGetter::Init, base::Unretained(this)));
299 Wait();
300 }
301
~SyncConfigGetter()302 ~SyncConfigGetter() override {
303 // Clean up the main thread.
304 main_thread_.task_runner()->PostTask(
305 FROM_HERE,
306 base::BindOnce(&SyncConfigGetter::CleanUp, base::Unretained(this)));
307 Wait();
308 }
309
310 // Does gsettings setup and initial fetch of the proxy config,
311 // all on the calling thread (meant to be the thread with the
312 // default glib main loop, which is the glib thread).
SetupAndInitialFetch()313 void SetupAndInitialFetch() {
314 config_service_->SetupAndFetchInitialConfig(
315 base::SingleThreadTaskRunner::GetCurrentDefault(),
316 main_thread_.task_runner(), TRAFFIC_ANNOTATION_FOR_TESTS);
317 }
318 // Synchronously gets the proxy config.
SyncGetLatestProxyConfig(ProxyConfigWithAnnotation * config)319 ProxyConfigService::ConfigAvailability SyncGetLatestProxyConfig(
320 ProxyConfigWithAnnotation* config) {
321 main_thread_.task_runner()->PostTask(
322 FROM_HERE, base::BindOnce(&SyncConfigGetter::GetLatestConfigOnIOThread,
323 base::Unretained(this)));
324 Wait();
325 *config = proxy_config_;
326 return get_latest_config_result_;
327 }
328
329 // Instructs |matches_pac_url_event_| to be signalled once the configuration
330 // changes to |pac_url|. The way to use this function is:
331 //
332 // SetExpectedPacUrl(..);
333 // EXPECT_TRUE(base::WriteFile(...))
334 // WaitUntilPacUrlMatchesExpectation();
335 //
336 // The expectation must be set *before* any file-level mutation is done,
337 // otherwise the change may be received before
338 // WaitUntilPacUrlMatchesExpectation(), and subsequently be lost.
SetExpectedPacUrl(const std::string & pac_url)339 void SetExpectedPacUrl(const std::string& pac_url) {
340 base::AutoLock lock(lock_);
341 expected_pac_url_ = GURL(pac_url);
342 }
343
344 // Blocks until the proxy config service has received a configuration
345 // matching the value previously passed to SetExpectedPacUrl().
WaitUntilPacUrlMatchesExpectation()346 void WaitUntilPacUrlMatchesExpectation() {
347 matches_pac_url_event_.Wait();
348 matches_pac_url_event_.Reset();
349 }
350
351 private:
OnProxyConfigChanged(const ProxyConfigWithAnnotation & config,ProxyConfigService::ConfigAvailability availability)352 void OnProxyConfigChanged(
353 const ProxyConfigWithAnnotation& config,
354 ProxyConfigService::ConfigAvailability availability) override {
355 // If the configuration changed to |expected_pac_url_| signal the event.
356 base::AutoLock lock(lock_);
357 if (config.value().has_pac_url() &&
358 config.value().pac_url() == expected_pac_url_) {
359 expected_pac_url_ = GURL();
360 matches_pac_url_event_.Signal();
361 }
362 }
363
364 // [Runs on |main_thread_|]
Init()365 void Init() {
366 config_service_->AddObserver(this);
367 event_.Signal();
368 }
369
370 // Calls GetLatestProxyConfig, running on |main_thread_| Signals |event_|
371 // on completion.
GetLatestConfigOnIOThread()372 void GetLatestConfigOnIOThread() {
373 get_latest_config_result_ =
374 config_service_->GetLatestProxyConfig(&proxy_config_);
375 event_.Signal();
376 }
377
378 // [Runs on |main_thread_|] Signals |event_| on cleanup completion.
CleanUp()379 void CleanUp() {
380 config_service_->RemoveObserver(this);
381 config_service_.reset();
382 base::RunLoop().RunUntilIdle();
383 event_.Signal();
384 }
385
Wait()386 void Wait() {
387 event_.Wait();
388 event_.Reset();
389 }
390
391 base::WaitableEvent event_;
392 base::Thread main_thread_;
393
394 std::unique_ptr<ProxyConfigServiceLinux> config_service_;
395
396 // The config obtained by |main_thread_| and read back by the main
397 // thread.
398 ProxyConfigWithAnnotation proxy_config_;
399
400 // Return value from GetLatestProxyConfig().
401 ProxyConfigService::ConfigAvailability get_latest_config_result_;
402
403 // If valid, |expected_pac_url_| is the URL that is being waited for in
404 // the proxy configuration. The URL should only be accessed while |lock_|
405 // is held. Once a configuration arrives for |expected_pac_url_| then the
406 // event |matches_pac_url_event_| will be signalled.
407 base::Lock lock_;
408 GURL expected_pac_url_;
409 base::WaitableEvent matches_pac_url_event_;
410 };
411
412 // This test fixture is only really needed for the KDEConfigParser test case,
413 // but all the test cases with the same prefix ("ProxyConfigServiceLinuxTest")
414 // must use the same test fixture class (also "ProxyConfigServiceLinuxTest").
415 class ProxyConfigServiceLinuxTest : public PlatformTest,
416 public WithTaskEnvironment {
417 protected:
SetUp()418 void SetUp() override {
419 PlatformTest::SetUp();
420 // Set up a temporary KDE home directory.
421 std::string prefix("ProxyConfigServiceLinuxTest_user_home");
422 base::CreateNewTempDirectory(prefix, &user_home_);
423 config_home_ = user_home_.Append(FILE_PATH_LITERAL(".config"));
424 kde_home_ = user_home_.Append(FILE_PATH_LITERAL(".kde"));
425 base::FilePath path = kde_home_.Append(FILE_PATH_LITERAL("share"));
426 path = path.Append(FILE_PATH_LITERAL("config"));
427 base::CreateDirectory(path);
428 kioslaverc_ = path.Append(FILE_PATH_LITERAL("kioslaverc"));
429 // Set up paths but do not create the directory for .kde4.
430 kde4_home_ = user_home_.Append(FILE_PATH_LITERAL(".kde4"));
431 path = kde4_home_.Append(FILE_PATH_LITERAL("share"));
432 kde4_config_ = path.Append(FILE_PATH_LITERAL("config"));
433 kioslaverc4_ = kde4_config_.Append(FILE_PATH_LITERAL("kioslaverc"));
434 // Set up paths for KDE 5
435 kioslaverc5_ = config_home_.Append(FILE_PATH_LITERAL("kioslaverc"));
436 config_xdg_home_ = user_home_.Append(FILE_PATH_LITERAL("xdg"));
437 config_kdedefaults_home_ =
438 config_home_.Append(FILE_PATH_LITERAL("kdedefaults"));
439 kioslaverc5_xdg_ = config_xdg_home_.Append(FILE_PATH_LITERAL("kioslaverc"));
440 kioslaverc5_kdedefaults_ =
441 config_kdedefaults_home_.Append(FILE_PATH_LITERAL("kioslaverc"));
442 }
443
TearDown()444 void TearDown() override {
445 // Delete the temporary KDE home directory.
446 base::DeletePathRecursively(user_home_);
447 PlatformTest::TearDown();
448 }
449
450 base::FilePath user_home_;
451 base::FilePath config_home_;
452 base::FilePath config_xdg_home_;
453 base::FilePath config_kdedefaults_home_;
454 // KDE3 paths.
455 base::FilePath kde_home_;
456 base::FilePath kioslaverc_;
457 // KDE4 paths.
458 base::FilePath kde4_home_;
459 base::FilePath kde4_config_;
460 base::FilePath kioslaverc4_;
461 // KDE5 paths.
462 base::FilePath kioslaverc5_;
463 base::FilePath kioslaverc5_xdg_;
464 base::FilePath kioslaverc5_kdedefaults_;
465 };
466
467 // Builds an identifier for each test in an array.
468 #define TEST_DESC(desc) base::StringPrintf("at line %d <%s>", __LINE__, desc)
469
TEST_F(ProxyConfigServiceLinuxTest,BasicGSettingsTest)470 TEST_F(ProxyConfigServiceLinuxTest, BasicGSettingsTest) {
471 std::vector<std::string> empty_ignores;
472
473 std::vector<std::string> google_ignores;
474 google_ignores.push_back("*.google.com");
475
476 // Inspired from proxy_config_service_win_unittest.cc.
477 // Very neat, but harder to track down failures though.
478 const struct {
479 // Short description to identify the test
480 std::string description;
481
482 // Input.
483 GSettingsValues values;
484
485 // Expected outputs (availability and fields of ProxyConfig).
486 ProxyConfigService::ConfigAvailability availability;
487 bool auto_detect;
488 GURL pac_url;
489 ProxyRulesExpectation proxy_rules;
490 } tests[] = {
491 {
492 TEST_DESC("No proxying"),
493 {
494 // Input.
495 "none", // mode
496 "", // autoconfig_url
497 "", "", "", "", // hosts
498 0, 0, 0, 0, // ports
499 FALSE, FALSE, FALSE, // use, same, auth
500 empty_ignores, // ignore_hosts
501 },
502
503 // Expected result.
504 ProxyConfigService::CONFIG_VALID,
505 false, // auto_detect
506 GURL(), // pac_url
507 ProxyRulesExpectation::Empty(),
508 },
509
510 {
511 TEST_DESC("Auto detect"),
512 {
513 // Input.
514 "auto", // mode
515 "", // autoconfig_url
516 "", "", "", "", // hosts
517 0, 0, 0, 0, // ports
518 FALSE, FALSE, FALSE, // use, same, auth
519 empty_ignores, // ignore_hosts
520 },
521
522 // Expected result.
523 ProxyConfigService::CONFIG_VALID,
524 true, // auto_detect
525 GURL(), // pac_url
526 ProxyRulesExpectation::Empty(),
527 },
528
529 {
530 TEST_DESC("Valid PAC URL"),
531 {
532 // Input.
533 "auto", // mode
534 "http://wpad/wpad.dat", // autoconfig_url
535 "", "", "", "", // hosts
536 0, 0, 0, 0, // ports
537 FALSE, FALSE, FALSE, // use, same, auth
538 empty_ignores, // ignore_hosts
539 },
540
541 // Expected result.
542 ProxyConfigService::CONFIG_VALID,
543 false, // auto_detect
544 GURL("http://wpad/wpad.dat"), // pac_url
545 ProxyRulesExpectation::Empty(),
546 },
547
548 {
549 TEST_DESC("Invalid PAC URL"),
550 {
551 // Input.
552 "auto", // mode
553 "wpad.dat", // autoconfig_url
554 "", "", "", "", // hosts
555 0, 0, 0, 0, // ports
556 FALSE, FALSE, FALSE, // use, same, auth
557 empty_ignores, // ignore_hosts
558 },
559
560 // Expected result.
561 ProxyConfigService::CONFIG_VALID,
562 false, // auto_detect
563 GURL(), // pac_url
564 ProxyRulesExpectation::Empty(),
565 },
566
567 {
568 TEST_DESC("Single-host in proxy list"),
569 {
570 // Input.
571 "manual", // mode
572 "", // autoconfig_url
573 "www.google.com", "", "", "", // hosts
574 80, 0, 0, 0, // ports
575 TRUE, TRUE, FALSE, // use, same, auth
576 empty_ignores, // ignore_hosts
577 },
578
579 // Expected result.
580 ProxyConfigService::CONFIG_VALID,
581 false, // auto_detect
582 GURL(), // pac_url
583 ProxyRulesExpectation::Single("www.google.com:80", // single proxy
584 ""), // bypass rules
585 },
586
587 {
588 TEST_DESC("use_http_proxy is honored"),
589 {
590 // Input.
591 "manual", // mode
592 "", // autoconfig_url
593 "www.google.com", "", "", "", // hosts
594 80, 0, 0, 0, // ports
595 FALSE, TRUE, FALSE, // use, same, auth
596 empty_ignores, // ignore_hosts
597 },
598
599 // Expected result.
600 ProxyConfigService::CONFIG_VALID,
601 false, // auto_detect
602 GURL(), // pac_url
603 ProxyRulesExpectation::Empty(),
604 },
605
606 {
607 TEST_DESC("use_http_proxy and use_same_proxy are optional"),
608 {
609 // Input.
610 "manual", // mode
611 "", // autoconfig_url
612 "www.google.com", "", "", "", // hosts
613 80, 0, 0, 0, // ports
614 UNSET, UNSET, FALSE, // use, same, auth
615 empty_ignores, // ignore_hosts
616 },
617
618 // Expected result.
619 ProxyConfigService::CONFIG_VALID,
620 false, // auto_detect
621 GURL(), // pac_url
622 ProxyRulesExpectation::PerScheme("www.google.com:80", // http
623 "", // https
624 "", // ftp
625 ""), // bypass rules
626 },
627
628 {
629 TEST_DESC("Single-host, different port"),
630 {
631 // Input.
632 "manual", // mode
633 "", // autoconfig_url
634 "www.google.com", "", "", "", // hosts
635 88, 0, 0, 0, // ports
636 TRUE, TRUE, FALSE, // use, same, auth
637 empty_ignores, // ignore_hosts
638 },
639
640 // Expected result.
641 ProxyConfigService::CONFIG_VALID,
642 false, // auto_detect
643 GURL(), // pac_url
644 ProxyRulesExpectation::Single("www.google.com:88", // single proxy
645 ""), // bypass rules
646 },
647
648 {
649 TEST_DESC("Per-scheme proxy rules"),
650 {
651 // Input.
652 "manual", // mode
653 "", // autoconfig_url
654 "www.google.com", // http_host
655 "www.foo.com", // secure_host
656 "ftp.foo.com", // ftp
657 "", // socks
658 88, 110, 121, 0, // ports
659 TRUE, FALSE, FALSE, // use, same, auth
660 empty_ignores, // ignore_hosts
661 },
662
663 // Expected result.
664 ProxyConfigService::CONFIG_VALID,
665 false, // auto_detect
666 GURL(), // pac_url
667 ProxyRulesExpectation::PerScheme("www.google.com:88", // http
668 "www.foo.com:110", // https
669 "ftp.foo.com:121", // ftp
670 ""), // bypass rules
671 },
672
673 {
674 TEST_DESC("socks"),
675 {
676 // Input.
677 "manual", // mode
678 "", // autoconfig_url
679 "", "", "", "socks.com", // hosts
680 0, 0, 0, 99, // ports
681 TRUE, FALSE, FALSE, // use, same, auth
682 empty_ignores, // ignore_hosts
683 },
684
685 // Expected result.
686 ProxyConfigService::CONFIG_VALID,
687 false, // auto_detect
688 GURL(), // pac_url
689 ProxyRulesExpectation::Single(
690 "socks5://socks.com:99", // single proxy
691 "") // bypass rules
692 },
693
694 {
695 TEST_DESC("Per-scheme proxy rules with fallback to SOCKS"),
696 {
697 // Input.
698 "manual", // mode
699 "", // autoconfig_url
700 "www.google.com", // http_host
701 "www.foo.com", // secure_host
702 "ftp.foo.com", // ftp
703 "foobar.net", // socks
704 88, 110, 121, 99, // ports
705 TRUE, FALSE, FALSE, // use, same, auth
706 empty_ignores, // ignore_hosts
707 },
708
709 // Expected result.
710 ProxyConfigService::CONFIG_VALID,
711 false, // auto_detect
712 GURL(), // pac_url
713 ProxyRulesExpectation::PerSchemeWithSocks(
714 "www.google.com:88", // http
715 "www.foo.com:110", // https
716 "ftp.foo.com:121", // ftp
717 "socks5://foobar.net:99", // socks
718 ""), // bypass rules
719 },
720
721 {
722 TEST_DESC(
723 "Per-scheme proxy rules (just HTTP) with fallback to SOCKS"),
724 {
725 // Input.
726 "manual", // mode
727 "", // autoconfig_url
728 "www.google.com", // http_host
729 "", // secure_host
730 "", // ftp
731 "foobar.net", // socks
732 88, 0, 0, 99, // ports
733 TRUE, FALSE, FALSE, // use, same, auth
734 empty_ignores, // ignore_hosts
735 },
736
737 // Expected result.
738 ProxyConfigService::CONFIG_VALID,
739 false, // auto_detect
740 GURL(), // pac_url
741 ProxyRulesExpectation::PerSchemeWithSocks(
742 "www.google.com:88", // http
743 "", // https
744 "", // ftp
745 "socks5://foobar.net:99", // socks
746 ""), // bypass rules
747 },
748
749 {
750 TEST_DESC("Bypass *.google.com"),
751 {
752 // Input.
753 "manual", // mode
754 "", // autoconfig_url
755 "www.google.com", "", "", "", // hosts
756 80, 0, 0, 0, // ports
757 TRUE, TRUE, FALSE, // use, same, auth
758 google_ignores, // ignore_hosts
759 },
760
761 ProxyConfigService::CONFIG_VALID,
762 false, // auto_detect
763 GURL(), // pac_url
764 ProxyRulesExpectation::Single("www.google.com:80", // single proxy
765 "*.google.com"), // bypass rules
766 },
767 };
768
769 for (size_t i = 0; i < std::size(tests); ++i) {
770 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i,
771 tests[i].description.c_str()));
772 auto env = std::make_unique<MockEnvironment>();
773 auto setting_getter = std::make_unique<MockSettingGetter>();
774 auto* setting_getter_ptr = setting_getter.get();
775 SyncConfigGetter sync_config_getter(
776 std::make_unique<ProxyConfigServiceLinux>(
777 std::move(env), std::move(setting_getter),
778 TRAFFIC_ANNOTATION_FOR_TESTS));
779 ProxyConfigWithAnnotation config;
780 setting_getter_ptr->values = tests[i].values;
781 sync_config_getter.SetupAndInitialFetch();
782 ProxyConfigService::ConfigAvailability availability =
783 sync_config_getter.SyncGetLatestProxyConfig(&config);
784 EXPECT_EQ(tests[i].availability, availability);
785
786 if (availability == ProxyConfigService::CONFIG_VALID) {
787 EXPECT_EQ(tests[i].auto_detect, config.value().auto_detect());
788 EXPECT_EQ(tests[i].pac_url, config.value().pac_url());
789 EXPECT_TRUE(tests[i].proxy_rules.Matches(config.value().proxy_rules()));
790 }
791 }
792 }
793
TEST_F(ProxyConfigServiceLinuxTest,BasicEnvTest)794 TEST_F(ProxyConfigServiceLinuxTest, BasicEnvTest) {
795 // Inspired from proxy_config_service_win_unittest.cc.
796 const struct {
797 // Short description to identify the test
798 std::string description;
799
800 // Input.
801 EnvVarValues values;
802
803 // Expected outputs (availability and fields of ProxyConfig).
804 ProxyConfigService::ConfigAvailability availability;
805 bool auto_detect;
806 GURL pac_url;
807 ProxyRulesExpectation proxy_rules;
808 } tests[] = {
809 {
810 TEST_DESC("No proxying"),
811 {
812 // Input.
813 nullptr, // DESKTOP_SESSION
814 nullptr, // HOME
815 nullptr, // KDEHOME
816 nullptr, // KDE_SESSION_VERSION
817 nullptr, // XDG_CURRENT_DESKTOP
818 nullptr, // auto_proxy
819 nullptr, // all_proxy
820 nullptr, nullptr, nullptr, // per-proto proxies
821 nullptr, nullptr, // SOCKS
822 "*", // no_proxy
823 },
824
825 // Expected result.
826 ProxyConfigService::CONFIG_VALID,
827 false, // auto_detect
828 GURL(), // pac_url
829 ProxyRulesExpectation::Empty(),
830 },
831
832 {
833 TEST_DESC("Auto detect"),
834 {
835 // Input.
836 nullptr, // DESKTOP_SESSION
837 nullptr, // HOME
838 nullptr, // KDEHOME
839 nullptr, // KDE_SESSION_VERSION
840 nullptr, // XDG_CURRENT_DESKTOP
841 "", // auto_proxy
842 nullptr, // all_proxy
843 nullptr, nullptr, nullptr, // per-proto proxies
844 nullptr, nullptr, // SOCKS
845 nullptr, // no_proxy
846 },
847
848 // Expected result.
849 ProxyConfigService::CONFIG_VALID,
850 true, // auto_detect
851 GURL(), // pac_url
852 ProxyRulesExpectation::Empty(),
853 },
854
855 {
856 TEST_DESC("Valid PAC URL"),
857 {
858 // Input.
859 nullptr, // DESKTOP_SESSION
860 nullptr, // HOME
861 nullptr, // KDEHOME
862 nullptr, // KDE_SESSION_VERSION
863 nullptr, // XDG_CURRENT_DESKTOP
864 "http://wpad/wpad.dat", // auto_proxy
865 nullptr, // all_proxy
866 nullptr, nullptr, nullptr, // per-proto proxies
867 nullptr, nullptr, // SOCKS
868 nullptr, // no_proxy
869 },
870
871 // Expected result.
872 ProxyConfigService::CONFIG_VALID,
873 false, // auto_detect
874 GURL("http://wpad/wpad.dat"), // pac_url
875 ProxyRulesExpectation::Empty(),
876 },
877
878 {
879 TEST_DESC("Invalid PAC URL"),
880 {
881 // Input.
882 nullptr, // DESKTOP_SESSION
883 nullptr, // HOME
884 nullptr, // KDEHOME
885 nullptr, // KDE_SESSION_VERSION
886 nullptr, // XDG_CURRENT_DESKTOP
887 "wpad.dat", // auto_proxy
888 nullptr, // all_proxy
889 nullptr, nullptr, nullptr, // per-proto proxies
890 nullptr, nullptr, // SOCKS
891 nullptr, // no_proxy
892 },
893
894 // Expected result.
895 ProxyConfigService::CONFIG_VALID,
896 false, // auto_detect
897 GURL(), // pac_url
898 ProxyRulesExpectation::Empty(),
899 },
900
901 {
902 TEST_DESC("Single-host in proxy list"),
903 {
904 // Input.
905 nullptr, // DESKTOP_SESSION
906 nullptr, // HOME
907 nullptr, // KDEHOME
908 nullptr, // KDE_SESSION_VERSION
909 nullptr, // XDG_CURRENT_DESKTOP
910 nullptr, // auto_proxy
911 "www.google.com", // all_proxy
912 nullptr, nullptr, nullptr, // per-proto proxies
913 nullptr, nullptr, // SOCKS
914 nullptr, // no_proxy
915 },
916
917 // Expected result.
918 ProxyConfigService::CONFIG_VALID,
919 false, // auto_detect
920 GURL(), // pac_url
921 ProxyRulesExpectation::Single("www.google.com:80", // single proxy
922 ""), // bypass rules
923 },
924
925 {
926 TEST_DESC("Single-host, different port"),
927 {
928 // Input.
929 nullptr, // DESKTOP_SESSION
930 nullptr, // HOME
931 nullptr, // KDEHOME
932 nullptr, // KDE_SESSION_VERSION
933 nullptr, // XDG_CURRENT_DESKTOP
934 nullptr, // auto_proxy
935 "www.google.com:99", // all_proxy
936 nullptr, nullptr, nullptr, // per-proto proxies
937 nullptr, nullptr, // SOCKS
938 nullptr, // no_proxy
939 },
940
941 // Expected result.
942 ProxyConfigService::CONFIG_VALID,
943 false, // auto_detect
944 GURL(), // pac_url
945 ProxyRulesExpectation::Single("www.google.com:99", // single
946 ""), // bypass rules
947 },
948
949 {
950 TEST_DESC("Tolerate a scheme"),
951 {
952 // Input.
953 nullptr, // DESKTOP_SESSION
954 nullptr, // HOME
955 nullptr, // KDEHOME
956 nullptr, // KDE_SESSION_VERSION
957 nullptr, // XDG_CURRENT_DESKTOP
958 nullptr, // auto_proxy
959 "http://www.google.com:99", // all_proxy
960 nullptr, nullptr, nullptr, // per-proto proxies
961 nullptr, nullptr, // SOCKS
962 nullptr, // no_proxy
963 },
964
965 // Expected result.
966 ProxyConfigService::CONFIG_VALID,
967 false, // auto_detect
968 GURL(), // pac_url
969 ProxyRulesExpectation::Single("www.google.com:99", // single proxy
970 ""), // bypass rules
971 },
972
973 {
974 TEST_DESC("Per-scheme proxy rules"),
975 {
976 // Input.
977 nullptr, // DESKTOP_SESSION
978 nullptr, // HOME
979 nullptr, // KDEHOME
980 nullptr, // KDE_SESSION_VERSION
981 nullptr, // XDG_CURRENT_DESKTOP
982 nullptr, // auto_proxy
983 nullptr, // all_proxy
984 "www.google.com:80", "www.foo.com:110",
985 "ftp.foo.com:121", // per-proto
986 nullptr, nullptr, // SOCKS
987 nullptr, // no_proxy
988 },
989
990 // Expected result.
991 ProxyConfigService::CONFIG_VALID,
992 false, // auto_detect
993 GURL(), // pac_url
994 ProxyRulesExpectation::PerScheme("www.google.com:80", // http
995 "www.foo.com:110", // https
996 "ftp.foo.com:121", // ftp
997 ""), // bypass rules
998 },
999
1000 {
1001 TEST_DESC("socks"),
1002 {
1003 // Input.
1004 nullptr, // DESKTOP_SESSION
1005 nullptr, // HOME
1006 nullptr, // KDEHOME
1007 nullptr, // KDE_SESSION_VERSION
1008 nullptr, // XDG_CURRENT_DESKTOP
1009 nullptr, // auto_proxy
1010 "", // all_proxy
1011 nullptr, nullptr, nullptr, // per-proto proxies
1012 "socks.com:888", nullptr, // SOCKS
1013 nullptr, // no_proxy
1014 },
1015
1016 // Expected result.
1017 ProxyConfigService::CONFIG_VALID,
1018 false, // auto_detect
1019 GURL(), // pac_url
1020 ProxyRulesExpectation::Single(
1021 "socks5://socks.com:888", // single proxy
1022 ""), // bypass rules
1023 },
1024
1025 {
1026 TEST_DESC("socks4"),
1027 {
1028 // Input.
1029 nullptr, // DESKTOP_SESSION
1030 nullptr, // HOME
1031 nullptr, // KDEHOME
1032 nullptr, // KDE_SESSION_VERSION
1033 nullptr, // XDG_CURRENT_DESKTOP
1034 nullptr, // auto_proxy
1035 "", // all_proxy
1036 nullptr, nullptr, nullptr, // per-proto proxies
1037 "socks.com:888", "4", // SOCKS
1038 nullptr, // no_proxy
1039 },
1040
1041 // Expected result.
1042 ProxyConfigService::CONFIG_VALID,
1043 false, // auto_detect
1044 GURL(), // pac_url
1045 ProxyRulesExpectation::Single(
1046 "socks4://socks.com:888", // single proxy
1047 ""), // bypass rules
1048 },
1049
1050 {
1051 TEST_DESC("socks default port"),
1052 {
1053 // Input.
1054 nullptr, // DESKTOP_SESSION
1055 nullptr, // HOME
1056 nullptr, // KDEHOME
1057 nullptr, // KDE_SESSION_VERSION
1058 nullptr, // XDG_CURRENT_DESKTOP
1059 nullptr, // auto_proxy
1060 "", // all_proxy
1061 nullptr, nullptr, nullptr, // per-proto proxies
1062 "socks.com", nullptr, // SOCKS
1063 nullptr, // no_proxy
1064 },
1065
1066 // Expected result.
1067 ProxyConfigService::CONFIG_VALID,
1068 false, // auto_detect
1069 GURL(), // pac_url
1070 ProxyRulesExpectation::Single(
1071 "socks5://socks.com:1080", // single proxy
1072 ""), // bypass rules
1073 },
1074
1075 {
1076 TEST_DESC("bypass"),
1077 {
1078 // Input.
1079 nullptr, // DESKTOP_SESSION
1080 nullptr, // HOME
1081 nullptr, // KDEHOME
1082 nullptr, // KDE_SESSION_VERSION
1083 nullptr, // XDG_CURRENT_DESKTOP
1084 nullptr, // auto_proxy
1085 "www.google.com", // all_proxy
1086 nullptr, nullptr, nullptr, // per-proto
1087 nullptr, nullptr, // SOCKS
1088 ".google.com, foo.com:99, 1.2.3.4:22, 127.0.0.1/8", // no_proxy
1089 },
1090
1091 // Expected result.
1092 ProxyConfigService::CONFIG_VALID,
1093 false, // auto_detect
1094 GURL(), // pac_url
1095 ProxyRulesExpectation::Single(
1096 "www.google.com:80",
1097 "*.google.com,*foo.com:99,1.2.3.4:22,127.0.0.1/8"),
1098 },
1099 };
1100
1101 for (size_t i = 0; i < std::size(tests); ++i) {
1102 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i,
1103 tests[i].description.c_str()));
1104 auto env = std::make_unique<MockEnvironment>();
1105 env->values = tests[i].values;
1106 auto setting_getter = std::make_unique<MockSettingGetter>();
1107 SyncConfigGetter sync_config_getter(
1108 std::make_unique<ProxyConfigServiceLinux>(
1109 std::move(env), std::move(setting_getter),
1110 TRAFFIC_ANNOTATION_FOR_TESTS));
1111 ProxyConfigWithAnnotation config;
1112 sync_config_getter.SetupAndInitialFetch();
1113 ProxyConfigService::ConfigAvailability availability =
1114 sync_config_getter.SyncGetLatestProxyConfig(&config);
1115 EXPECT_EQ(tests[i].availability, availability);
1116
1117 if (availability == ProxyConfigService::CONFIG_VALID) {
1118 EXPECT_EQ(tests[i].auto_detect, config.value().auto_detect());
1119 EXPECT_EQ(tests[i].pac_url, config.value().pac_url());
1120 EXPECT_TRUE(tests[i].proxy_rules.Matches(config.value().proxy_rules()));
1121 }
1122 }
1123 }
1124
TEST_F(ProxyConfigServiceLinuxTest,GSettingsNotification)1125 TEST_F(ProxyConfigServiceLinuxTest, GSettingsNotification) {
1126 auto env = std::make_unique<MockEnvironment>();
1127 auto setting_getter = std::make_unique<MockSettingGetter>();
1128 auto* setting_getter_ptr = setting_getter.get();
1129 auto service = std::make_unique<ProxyConfigServiceLinux>(
1130 std::move(env), std::move(setting_getter), TRAFFIC_ANNOTATION_FOR_TESTS);
1131 auto* service_ptr = service.get();
1132 SyncConfigGetter sync_config_getter(std::move(service));
1133 ProxyConfigWithAnnotation config;
1134
1135 // Start with no proxy.
1136 setting_getter_ptr->values.mode = "none";
1137 sync_config_getter.SetupAndInitialFetch();
1138 EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1139 sync_config_getter.SyncGetLatestProxyConfig(&config));
1140 EXPECT_FALSE(config.value().auto_detect());
1141
1142 // Now set to auto-detect.
1143 setting_getter_ptr->values.mode = "auto";
1144 // Simulate setting change notification callback.
1145 service_ptr->OnCheckProxyConfigSettings();
1146 EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1147 sync_config_getter.SyncGetLatestProxyConfig(&config));
1148 EXPECT_TRUE(config.value().auto_detect());
1149
1150 // Simulate two settings changes, where PROXY_MODE is missing. This will make
1151 // the settings be interpreted as DIRECT.
1152 //
1153 // Trigering the check a *second* time is a regression test for
1154 // https://crbug.com/848237, where a comparison is done between two nullopts.
1155 for (size_t i = 0; i < 2; ++i) {
1156 setting_getter_ptr->values.mode = nullptr;
1157 service_ptr->OnCheckProxyConfigSettings();
1158 EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1159 sync_config_getter.SyncGetLatestProxyConfig(&config));
1160 EXPECT_FALSE(config.value().auto_detect());
1161 EXPECT_TRUE(config.value().proxy_rules().empty());
1162 }
1163 }
1164
TEST_F(ProxyConfigServiceLinuxTest,KDEConfigParser)1165 TEST_F(ProxyConfigServiceLinuxTest, KDEConfigParser) {
1166 // One of the tests below needs a worst-case long line prefix. We build it
1167 // programmatically so that it will always be the right size.
1168 std::string long_line;
1169 size_t limit = ProxyConfigServiceLinux::SettingGetter::BUFFER_SIZE - 1;
1170 for (size_t i = 0; i < limit; ++i)
1171 long_line += "-";
1172
1173 // Inspired from proxy_config_service_win_unittest.cc.
1174 const struct {
1175 // Short description to identify the test
1176 std::string description;
1177
1178 // Input.
1179 std::string kioslaverc;
1180 EnvVarValues env_values;
1181
1182 // Expected outputs (availability and fields of ProxyConfig).
1183 ProxyConfigService::ConfigAvailability availability;
1184 bool auto_detect;
1185 GURL pac_url;
1186 ProxyRulesExpectation proxy_rules;
1187 } tests[] = {
1188 {
1189 TEST_DESC("No proxying"),
1190
1191 // Input.
1192 "[Proxy Settings]\nProxyType=0\n",
1193 {}, // env_values
1194
1195 // Expected result.
1196 ProxyConfigService::CONFIG_VALID,
1197 false, // auto_detect
1198 GURL(), // pac_url
1199 ProxyRulesExpectation::Empty(),
1200 },
1201 {
1202 TEST_DESC("Invalid proxy type (ProxyType=-3)"),
1203
1204 // Input.
1205 "[Proxy Settings]\nProxyType=-3\n",
1206 {}, // env_values
1207
1208 // Expected result.
1209 ProxyConfigService::CONFIG_VALID,
1210 false, // auto_detect
1211 GURL(), // pac_url
1212 ProxyRulesExpectation::Empty(),
1213 },
1214
1215 {
1216 TEST_DESC("Invalid proxy type (ProxyType=AB-)"),
1217
1218 // Input.
1219 "[Proxy Settings]\nProxyType=AB-\n",
1220 {}, // env_values
1221
1222 // Expected result.
1223 ProxyConfigService::CONFIG_VALID,
1224 false, // auto_detect
1225 GURL(), // pac_url
1226 ProxyRulesExpectation::Empty(),
1227 },
1228
1229 {
1230 TEST_DESC("Auto detect"),
1231
1232 // Input.
1233 "[Proxy Settings]\nProxyType=3\n",
1234 {}, // env_values
1235
1236 // Expected result.
1237 ProxyConfigService::CONFIG_VALID,
1238 true, // auto_detect
1239 GURL(), // pac_url
1240 ProxyRulesExpectation::Empty(),
1241 },
1242
1243 {
1244 TEST_DESC("Valid PAC URL"),
1245
1246 // Input.
1247 "[Proxy Settings]\nProxyType=2\n"
1248 "Proxy Config Script=http://wpad/wpad.dat\n",
1249 {}, // env_values
1250
1251 // Expected result.
1252 ProxyConfigService::CONFIG_VALID,
1253 false, // auto_detect
1254 GURL("http://wpad/wpad.dat"), // pac_url
1255 ProxyRulesExpectation::Empty(),
1256 },
1257
1258 {
1259 TEST_DESC("Valid PAC file without file://"),
1260
1261 // Input.
1262 "[Proxy Settings]\nProxyType=2\n"
1263 "Proxy Config Script=/wpad/wpad.dat\n",
1264 {}, // env_values
1265
1266 // Expected result.
1267 ProxyConfigService::CONFIG_VALID,
1268 false, // auto_detect
1269 GURL("file:///wpad/wpad.dat"), // pac_url
1270 ProxyRulesExpectation::Empty(),
1271 },
1272
1273 {
1274 TEST_DESC("Per-scheme proxy rules"),
1275
1276 // Input.
1277 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1278 "httpsProxy=www.foo.com\nftpProxy=ftp.foo.com\n",
1279 {}, // env_values
1280
1281 // Expected result.
1282 ProxyConfigService::CONFIG_VALID,
1283 false, // auto_detect
1284 GURL(), // pac_url
1285 ProxyRulesExpectation::PerScheme("www.google.com:80", // http
1286 "www.foo.com:80", // https
1287 "ftp.foo.com:80", // http
1288 ""), // bypass rules
1289 },
1290
1291 {
1292 TEST_DESC("Only HTTP proxy specified"),
1293
1294 // Input.
1295 "[Proxy Settings]\nProxyType=1\n"
1296 "httpProxy=www.google.com\n",
1297 {}, // env_values
1298
1299 // Expected result.
1300 ProxyConfigService::CONFIG_VALID,
1301 false, // auto_detect
1302 GURL(), // pac_url
1303 ProxyRulesExpectation::PerScheme("www.google.com:80", // http
1304 "", // https
1305 "", // ftp
1306 ""), // bypass rules
1307 },
1308
1309 {
1310 TEST_DESC("Only HTTP proxy specified, different port"),
1311
1312 // Input.
1313 "[Proxy Settings]\nProxyType=1\n"
1314 "httpProxy=www.google.com:88\n",
1315 {}, // env_values
1316
1317 // Expected result.
1318 ProxyConfigService::CONFIG_VALID,
1319 false, // auto_detect
1320 GURL(), // pac_url
1321 ProxyRulesExpectation::PerScheme("www.google.com:88", // http
1322 "", // https
1323 "", // ftp
1324 ""), // bypass rules
1325 },
1326
1327 {
1328 TEST_DESC(
1329 "Only HTTP proxy specified, different port, space-delimited"),
1330
1331 // Input.
1332 "[Proxy Settings]\nProxyType=1\n"
1333 "httpProxy=www.google.com 88\n",
1334 {}, // env_values
1335
1336 // Expected result.
1337 ProxyConfigService::CONFIG_VALID,
1338 false, // auto_detect
1339 GURL(), // pac_url
1340 ProxyRulesExpectation::PerScheme("www.google.com:88", // http
1341 "", // https
1342 "", // ftp
1343 ""), // bypass rules
1344 },
1345
1346 {
1347 TEST_DESC("Bypass *.google.com"),
1348
1349 // Input.
1350 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1351 "NoProxyFor=.google.com\n",
1352 {}, // env_values
1353
1354 // Expected result.
1355 ProxyConfigService::CONFIG_VALID,
1356 false, // auto_detect
1357 GURL(), // pac_url
1358 ProxyRulesExpectation::PerScheme("www.google.com:80", // http
1359 "", // https
1360 "", // ftp
1361 "*.google.com"), // bypass rules
1362 },
1363
1364 {
1365 TEST_DESC("Bypass *.google.com and *.kde.org"),
1366
1367 // Input.
1368 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1369 "NoProxyFor=.google.com,.kde.org\n",
1370 {}, // env_values
1371
1372 // Expected result.
1373 ProxyConfigService::CONFIG_VALID,
1374 false, // auto_detect
1375 GURL(), // pac_url
1376 ProxyRulesExpectation::PerScheme(
1377 "www.google.com:80", // http
1378 "", // https
1379 "", // ftp
1380 "*.google.com,*.kde.org"), // bypass rules
1381 },
1382
1383 {
1384 TEST_DESC("Correctly parse bypass list with ReversedException=true"),
1385
1386 // Input.
1387 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1388 "NoProxyFor=.google.com\nReversedException=true\n",
1389 {}, // env_values
1390
1391 // Expected result.
1392 ProxyConfigService::CONFIG_VALID,
1393 false, // auto_detect
1394 GURL(), // pac_url
1395 ProxyRulesExpectation::PerSchemeWithBypassReversed(
1396 "www.google.com:80", // http
1397 "", // https
1398 "", // ftp
1399 "*.google.com"), // bypass rules
1400 },
1401
1402 {
1403 TEST_DESC("Correctly parse bypass list with ReversedException=false"),
1404
1405 // Input.
1406 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1407 "NoProxyFor=.google.com\nReversedException=false\n",
1408 {}, // env_values
1409
1410 // Expected result.
1411 ProxyConfigService::CONFIG_VALID,
1412 false, // auto_detect
1413 GURL(), // pac_url
1414 ProxyRulesExpectation::PerScheme("www.google.com:80", // http
1415 "", // https
1416 "", // ftp
1417 "*.google.com"), // bypass rules
1418 },
1419
1420 {
1421 TEST_DESC("Correctly parse bypass list with ReversedException=1"),
1422
1423 // Input.
1424 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1425 "NoProxyFor=.google.com\nReversedException=1\n",
1426 {}, // env_values
1427
1428 // Expected result.
1429 ProxyConfigService::CONFIG_VALID,
1430 false, // auto_detect
1431 GURL(), // pac_url
1432 ProxyRulesExpectation::PerSchemeWithBypassReversed(
1433 "www.google.com:80", // http
1434 "", // https
1435 "", // ftp
1436 "*.google.com"), // bypass rules
1437 },
1438
1439 {
1440 TEST_DESC("Overflow: ReversedException=18446744073709551617"),
1441
1442 // Input.
1443 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1444 "NoProxyFor=.google.com\nReversedException=18446744073709551617\n",
1445 {}, // env_values
1446
1447 // Expected result.
1448 ProxyConfigService::CONFIG_VALID,
1449 false, // auto_detect
1450 GURL(), // pac_url
1451 ProxyRulesExpectation::PerScheme("www.google.com:80", // http
1452 "", // https
1453 "", // ftp
1454 "*.google.com"), // bypass rules
1455 },
1456
1457 {
1458 TEST_DESC("Not a number: ReversedException=noitpecxE"),
1459
1460 // Input.
1461 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1462 "NoProxyFor=.google.com\nReversedException=noitpecxE\n",
1463 {}, // env_values
1464
1465 // Expected result.
1466 ProxyConfigService::CONFIG_VALID,
1467 false, // auto_detect
1468 GURL(), // pac_url
1469 ProxyRulesExpectation::PerScheme("www.google.com:80", // http
1470 "", // https
1471 "", // ftp
1472 "*.google.com"), // bypass rules
1473 },
1474
1475 {
1476 TEST_DESC("socks"),
1477
1478 // Input.
1479 "[Proxy Settings]\nProxyType=1\nsocksProxy=socks.com 888\n",
1480 {}, // env_values
1481
1482 // Expected result.
1483 ProxyConfigService::CONFIG_VALID,
1484 false, // auto_detect
1485 GURL(), // pac_url
1486 ProxyRulesExpectation::Single(
1487 "socks5://socks.com:888", // single proxy
1488 ""), // bypass rules
1489 },
1490
1491 {
1492 TEST_DESC("socks4"),
1493
1494 // Input.
1495 "[Proxy Settings]\nProxyType=1\nsocksProxy=socks4://socks.com 888\n",
1496 {}, // env_values
1497
1498 // Expected result.
1499 ProxyConfigService::CONFIG_VALID,
1500 false, // auto_detect
1501 GURL(), // pac_url
1502 ProxyRulesExpectation::Single(
1503 "socks4://socks.com:888", // single proxy
1504 ""), // bypass rules
1505 },
1506
1507 {
1508 TEST_DESC("Treat all hostname patterns as wildcard patterns"),
1509
1510 // Input.
1511 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1512 "NoProxyFor=google.com,kde.org,<local>\n",
1513 {}, // env_values
1514
1515 // Expected result.
1516 ProxyConfigService::CONFIG_VALID,
1517 false, // auto_detect
1518 GURL(), // pac_url
1519 ProxyRulesExpectation::PerScheme(
1520 "www.google.com:80", // http
1521 "", // https
1522 "", // ftp
1523 "*google.com,*kde.org,<local>"), // bypass rules
1524 },
1525
1526 {
1527 TEST_DESC("Allow trailing whitespace after boolean value"),
1528
1529 // Input.
1530 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1531 "NoProxyFor=.google.com\nReversedException=true \n",
1532 {}, // env_values
1533
1534 // Expected result.
1535 ProxyConfigService::CONFIG_VALID,
1536 false, // auto_detect
1537 GURL(), // pac_url
1538 ProxyRulesExpectation::PerSchemeWithBypassReversed(
1539 "www.google.com:80", // http
1540 "", // https
1541 "", // ftp
1542 "*.google.com"), // bypass rules
1543 },
1544
1545 {
1546 TEST_DESC("Ignore settings outside [Proxy Settings]"),
1547
1548 // Input.
1549 "httpsProxy=www.foo.com\n[Proxy Settings]\nProxyType=1\n"
1550 "httpProxy=www.google.com\n[Other Section]\nftpProxy=ftp.foo.com\n",
1551 {}, // env_values
1552
1553 // Expected result.
1554 ProxyConfigService::CONFIG_VALID,
1555 false, // auto_detect
1556 GURL(), // pac_url
1557 ProxyRulesExpectation::PerScheme("www.google.com:80", // http
1558 "", // https
1559 "", // ftp
1560 ""), // bypass rules
1561 },
1562
1563 {
1564 TEST_DESC("Handle CRLF line endings"),
1565
1566 // Input.
1567 "[Proxy Settings]\r\nProxyType=1\r\nhttpProxy=www.google.com\r\n",
1568 {}, // env_values
1569
1570 // Expected result.
1571 ProxyConfigService::CONFIG_VALID,
1572 false, // auto_detect
1573 GURL(), // pac_url
1574 ProxyRulesExpectation::PerScheme("www.google.com:80", // http
1575 "", // https
1576 "", // ftp
1577 ""), // bypass rules
1578 },
1579
1580 {
1581 TEST_DESC("Handle blank lines and mixed line endings"),
1582
1583 // Input.
1584 "[Proxy Settings]\r\n\nProxyType=1\n\r\nhttpProxy=www.google.com\n\n",
1585 {}, // env_values
1586
1587 // Expected result.
1588 ProxyConfigService::CONFIG_VALID,
1589 false, // auto_detect
1590 GURL(), // pac_url
1591 ProxyRulesExpectation::PerScheme("www.google.com:80", // http
1592 "", // https
1593 "", // ftp
1594 ""), // bypass rules
1595 },
1596
1597 {
1598 TEST_DESC("Handle localized settings"),
1599
1600 // Input.
1601 "[Proxy Settings]\nProxyType[$e]=1\nhttpProxy[$e]=www.google.com\n",
1602 {}, // env_values
1603
1604 // Expected result.
1605 ProxyConfigService::CONFIG_VALID,
1606 false, // auto_detect
1607 GURL(), // pac_url
1608 ProxyRulesExpectation::PerScheme("www.google.com:80", // http
1609 "", // https
1610 "", // ftp
1611 ""), // bypass rules
1612 },
1613
1614 {
1615 TEST_DESC("Ignore malformed localized settings"),
1616
1617 // Input.
1618 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1619 "httpsProxy$e]=www.foo.com\nftpProxy=ftp.foo.com\n",
1620 {}, // env_values
1621
1622 // Expected result.
1623 ProxyConfigService::CONFIG_VALID,
1624 false, // auto_detect
1625 GURL(), // pac_url
1626 ProxyRulesExpectation::PerScheme("www.google.com:80", // http
1627 "", // https
1628 "ftp.foo.com:80", // ftp
1629 ""), // bypass rules
1630 },
1631
1632 {
1633 TEST_DESC("Handle strange whitespace"),
1634
1635 // Input.
1636 "[Proxy Settings]\nProxyType [$e] =2\n"
1637 " Proxy Config Script = http:// foo\n",
1638 {}, // env_values
1639
1640 // Expected result.
1641 ProxyConfigService::CONFIG_VALID,
1642 false, // auto_detect
1643 GURL("http:// foo"), // pac_url
1644 ProxyRulesExpectation::Empty(),
1645 },
1646
1647 {
1648 TEST_DESC("Ignore all of a line which is too long"),
1649
1650 // Input.
1651 std::string("[Proxy Settings]\nProxyType=1\nftpProxy=ftp.foo.com\n") +
1652 long_line + "httpsProxy=www.foo.com\nhttpProxy=www.google.com\n",
1653 {}, // env_values
1654
1655 // Expected result.
1656 ProxyConfigService::CONFIG_VALID,
1657 false, // auto_detect
1658 GURL(), // pac_url
1659 ProxyRulesExpectation::PerScheme("www.google.com:80", // http
1660 "", // https
1661 "ftp.foo.com:80", // ftp
1662 ""), // bypass rules
1663 },
1664
1665 {
1666 TEST_DESC("Indirect Proxy - no env vars set"),
1667
1668 // Input.
1669 "[Proxy Settings]\nProxyType=4\nhttpProxy=http_proxy\n"
1670 "httpsProxy=https_proxy\nftpProxy=ftp_proxy\nNoProxyFor=no_proxy\n",
1671 {}, // env_values
1672
1673 // Expected result.
1674 ProxyConfigService::CONFIG_VALID,
1675 false, // auto_detect
1676 GURL(), // pac_url
1677 ProxyRulesExpectation::Empty(),
1678 },
1679
1680 {
1681 TEST_DESC("Indirect Proxy - with env vars set"),
1682
1683 // Input.
1684 "[Proxy Settings]\nProxyType=4\nhttpProxy=http_proxy\n"
1685 "httpsProxy=https_proxy\nftpProxy=ftp_proxy\nNoProxyFor=no_proxy\n"
1686 "socksProxy=SOCKS_SERVER\n",
1687 {
1688 // env_values
1689 nullptr, // DESKTOP_SESSION
1690 nullptr, // HOME
1691 nullptr, // KDEHOME
1692 nullptr, // KDE_SESSION_VERSION
1693 nullptr, // XDG_CURRENT_DESKTOP
1694 nullptr, // auto_proxy
1695 nullptr, // all_proxy
1696 "www.normal.com", // http_proxy
1697 "www.secure.com", // https_proxy
1698 "ftp.foo.com", // ftp_proxy
1699 "socks.comfy.com:1234", nullptr, // SOCKS
1700 ".google.com, .kde.org", // no_proxy
1701 },
1702
1703 // Expected result.
1704 ProxyConfigService::CONFIG_VALID,
1705 false, // auto_detect
1706 GURL(), // pac_url
1707 ProxyRulesExpectation::PerSchemeWithSocks(
1708 "www.normal.com:80", // http
1709 "www.secure.com:80", // https
1710 "ftp.foo.com:80", // ftp
1711 "socks5://socks.comfy.com:1234", // socks
1712 "*.google.com,*.kde.org"), // bypass rules
1713 },
1714 };
1715
1716 for (size_t i = 0; i < std::size(tests); ++i) {
1717 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i,
1718 tests[i].description.c_str()));
1719 auto env = std::make_unique<MockEnvironment>();
1720 env->values = tests[i].env_values;
1721 // Force the KDE getter to be used and tell it where the test is.
1722 env->values.DESKTOP_SESSION = "kde4";
1723 env->values.KDEHOME = kde_home_.value().c_str();
1724 SyncConfigGetter sync_config_getter(
1725 std::make_unique<ProxyConfigServiceLinux>(
1726 std::move(env), TRAFFIC_ANNOTATION_FOR_TESTS));
1727 ProxyConfigWithAnnotation config;
1728 // Overwrite the kioslaverc file.
1729 base::WriteFile(kioslaverc_, tests[i].kioslaverc);
1730 sync_config_getter.SetupAndInitialFetch();
1731 ProxyConfigService::ConfigAvailability availability =
1732 sync_config_getter.SyncGetLatestProxyConfig(&config);
1733 EXPECT_EQ(tests[i].availability, availability);
1734
1735 if (availability == ProxyConfigService::CONFIG_VALID) {
1736 EXPECT_EQ(tests[i].auto_detect, config.value().auto_detect());
1737 EXPECT_EQ(tests[i].pac_url, config.value().pac_url());
1738 EXPECT_TRUE(tests[i].proxy_rules.Matches(config.value().proxy_rules()));
1739 }
1740 }
1741 }
1742
TEST_F(ProxyConfigServiceLinuxTest,KDEHomePicker)1743 TEST_F(ProxyConfigServiceLinuxTest, KDEHomePicker) {
1744 // Auto detect proxy settings.
1745 std::string slaverc3 = "[Proxy Settings]\nProxyType=3\n";
1746 // Valid PAC URL.
1747 std::string slaverc4 =
1748 "[Proxy Settings]\nProxyType=2\n"
1749 "Proxy Config Script=http://wpad/wpad.dat\n";
1750 GURL slaverc4_pac_url("http://wpad/wpad.dat");
1751 // Basic HTTP proxy setting.
1752 std::string slaverc5 =
1753 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com 80\n";
1754 ProxyRulesExpectation slaverc5_rules =
1755 ProxyRulesExpectation::PerScheme("www.google.com:80", // http
1756 "", // https
1757 "", // ftp
1758 ""); // bypass rules
1759
1760 // Overwrite the .kde kioslaverc file.
1761 base::WriteFile(kioslaverc_, slaverc3);
1762
1763 // If .kde4 exists it will mess up the first test. It should not, as
1764 // we created the directory for $HOME in the test setup.
1765 CHECK(!base::DirectoryExists(kde4_home_));
1766
1767 {
1768 SCOPED_TRACE("KDE4, no .kde4 directory, verify fallback");
1769 auto env = std::make_unique<MockEnvironment>();
1770 env->values.DESKTOP_SESSION = "kde4";
1771 env->values.HOME = user_home_.value().c_str();
1772 SyncConfigGetter sync_config_getter(
1773 std::make_unique<ProxyConfigServiceLinux>(
1774 std::move(env), TRAFFIC_ANNOTATION_FOR_TESTS));
1775 ProxyConfigWithAnnotation config;
1776 sync_config_getter.SetupAndInitialFetch();
1777 EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1778 sync_config_getter.SyncGetLatestProxyConfig(&config));
1779 EXPECT_TRUE(config.value().auto_detect());
1780 EXPECT_EQ(GURL(), config.value().pac_url());
1781 }
1782
1783 // Now create .kde4 and put a kioslaverc in the config directory.
1784 // Note that its timestamp will be at least as new as the .kde one.
1785 base::CreateDirectory(kde4_config_);
1786 base::WriteFile(kioslaverc4_, slaverc4);
1787 CHECK(base::PathExists(kioslaverc4_));
1788
1789 {
1790 SCOPED_TRACE("KDE4, .kde4 directory present, use it");
1791 auto env = std::make_unique<MockEnvironment>();
1792 env->values.DESKTOP_SESSION = "kde4";
1793 env->values.HOME = user_home_.value().c_str();
1794 SyncConfigGetter sync_config_getter(
1795 std::make_unique<ProxyConfigServiceLinux>(
1796 std::move(env), TRAFFIC_ANNOTATION_FOR_TESTS));
1797 ProxyConfigWithAnnotation config;
1798 sync_config_getter.SetupAndInitialFetch();
1799 EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1800 sync_config_getter.SyncGetLatestProxyConfig(&config));
1801 EXPECT_FALSE(config.value().auto_detect());
1802 EXPECT_EQ(slaverc4_pac_url, config.value().pac_url());
1803 }
1804
1805 {
1806 SCOPED_TRACE("KDE3, .kde4 directory present, ignore it");
1807 auto env = std::make_unique<MockEnvironment>();
1808 env->values.DESKTOP_SESSION = "kde";
1809 env->values.HOME = user_home_.value().c_str();
1810 SyncConfigGetter sync_config_getter(
1811 std::make_unique<ProxyConfigServiceLinux>(
1812 std::move(env), TRAFFIC_ANNOTATION_FOR_TESTS));
1813 ProxyConfigWithAnnotation config;
1814 sync_config_getter.SetupAndInitialFetch();
1815 EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1816 sync_config_getter.SyncGetLatestProxyConfig(&config));
1817 EXPECT_TRUE(config.value().auto_detect());
1818 EXPECT_EQ(GURL(), config.value().pac_url());
1819 }
1820
1821 {
1822 SCOPED_TRACE("KDE4, .kde4 directory present, KDEHOME set to .kde");
1823 auto env = std::make_unique<MockEnvironment>();
1824 env->values.DESKTOP_SESSION = "kde4";
1825 env->values.HOME = user_home_.value().c_str();
1826 env->values.KDEHOME = kde_home_.value().c_str();
1827 SyncConfigGetter sync_config_getter(
1828 std::make_unique<ProxyConfigServiceLinux>(
1829 std::move(env), TRAFFIC_ANNOTATION_FOR_TESTS));
1830 ProxyConfigWithAnnotation config;
1831 sync_config_getter.SetupAndInitialFetch();
1832 EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1833 sync_config_getter.SyncGetLatestProxyConfig(&config));
1834 EXPECT_TRUE(config.value().auto_detect());
1835 EXPECT_EQ(GURL(), config.value().pac_url());
1836 }
1837
1838 // Finally, make the .kde4 config directory older than the .kde directory
1839 // and make sure we then use .kde instead of .kde4 since it's newer.
1840 base::TouchFile(kde4_config_, base::Time(), base::Time());
1841
1842 {
1843 SCOPED_TRACE("KDE4, very old .kde4 directory present, use .kde");
1844 auto env = std::make_unique<MockEnvironment>();
1845 env->values.DESKTOP_SESSION = "kde4";
1846 env->values.HOME = user_home_.value().c_str();
1847 SyncConfigGetter sync_config_getter(
1848 std::make_unique<ProxyConfigServiceLinux>(
1849 std::move(env), TRAFFIC_ANNOTATION_FOR_TESTS));
1850 ProxyConfigWithAnnotation config;
1851 sync_config_getter.SetupAndInitialFetch();
1852 EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1853 sync_config_getter.SyncGetLatestProxyConfig(&config));
1854 EXPECT_TRUE(config.value().auto_detect());
1855 EXPECT_EQ(GURL(), config.value().pac_url());
1856 }
1857
1858 // For KDE 5 create ${HOME}/.config and put a kioslaverc in the directory.
1859 base::CreateDirectory(config_home_);
1860 base::WriteFile(kioslaverc5_, slaverc5);
1861 CHECK(base::PathExists(kioslaverc5_));
1862
1863 {
1864 SCOPED_TRACE("KDE5, .kde and .kde4 present, use .config");
1865 auto env = std::make_unique<MockEnvironment>();
1866 env->values.XDG_CURRENT_DESKTOP = "KDE";
1867 env->values.KDE_SESSION_VERSION = "5";
1868 env->values.HOME = user_home_.value().c_str();
1869 SyncConfigGetter sync_config_getter(
1870 std::make_unique<ProxyConfigServiceLinux>(
1871 std::move(env), TRAFFIC_ANNOTATION_FOR_TESTS));
1872 ProxyConfigWithAnnotation config;
1873 sync_config_getter.SetupAndInitialFetch();
1874 EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1875 sync_config_getter.SyncGetLatestProxyConfig(&config));
1876 EXPECT_FALSE(config.value().auto_detect());
1877 EXPECT_TRUE(slaverc5_rules.Matches(config.value().proxy_rules()));
1878 }
1879 }
1880
1881 // Tests that the KDE proxy config service watches for file and directory
1882 // changes.
TEST_F(ProxyConfigServiceLinuxTest,KDEFileChanged)1883 TEST_F(ProxyConfigServiceLinuxTest, KDEFileChanged) {
1884 // Set up the initial .kde kioslaverc file.
1885 EXPECT_TRUE(
1886 base::WriteFile(kioslaverc_,
1887 "[Proxy Settings]\nProxyType=2\n"
1888 "Proxy Config Script=http://version1/wpad.dat\n"));
1889
1890 // Initialize the config service using kioslaverc.
1891 auto env = std::make_unique<MockEnvironment>();
1892 env->values.DESKTOP_SESSION = "kde4";
1893 env->values.HOME = user_home_.value().c_str();
1894 SyncConfigGetter sync_config_getter(std::make_unique<ProxyConfigServiceLinux>(
1895 std::move(env), TRAFFIC_ANNOTATION_FOR_TESTS));
1896 ProxyConfigWithAnnotation config;
1897 sync_config_getter.SetupAndInitialFetch();
1898 EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1899 sync_config_getter.SyncGetLatestProxyConfig(&config));
1900 EXPECT_TRUE(config.value().has_pac_url());
1901 EXPECT_EQ(GURL("http://version1/wpad.dat"), config.value().pac_url());
1902
1903 //-----------------------------------------------------
1904
1905 // Change the kioslaverc file by overwriting it. Verify that the change was
1906 // observed.
1907 sync_config_getter.SetExpectedPacUrl("http://version2/wpad.dat");
1908
1909 // Initialization posts a task to start watching kioslaverc file. Ensure that
1910 // registration has happened before modifying it or the file change won't be
1911 // observed.
1912 base::ThreadPoolInstance::Get()->FlushForTesting();
1913
1914 EXPECT_TRUE(
1915 base::WriteFile(kioslaverc_,
1916 "[Proxy Settings]\nProxyType=2\n"
1917 "Proxy Config Script=http://version2/wpad.dat\n"));
1918
1919 // Wait for change to be noticed.
1920 sync_config_getter.WaitUntilPacUrlMatchesExpectation();
1921
1922 //-----------------------------------------------------
1923
1924 // Change the kioslaverc file by renaming it. If only the file's inode
1925 // were being watched (rather than directory) this will not result in
1926 // an observable change. Note that KDE when re-writing proxy settings does
1927 // so by renaming a new file, so the inode will change.
1928 sync_config_getter.SetExpectedPacUrl("http://version3/wpad.dat");
1929
1930 // Create a new file, and rename it into place.
1931 EXPECT_TRUE(
1932 base::WriteFile(kioslaverc_.AddExtension("new"),
1933 "[Proxy Settings]\nProxyType=2\n"
1934 "Proxy Config Script=http://version3/wpad.dat\n"));
1935 base::Move(kioslaverc_, kioslaverc_.AddExtension("old"));
1936 base::Move(kioslaverc_.AddExtension("new"), kioslaverc_);
1937
1938 // Wait for change to be noticed.
1939 sync_config_getter.WaitUntilPacUrlMatchesExpectation();
1940
1941 //-----------------------------------------------------
1942
1943 // Change the kioslaverc file once more by ovewriting it. This is really
1944 // just another test to make sure things still work after the directory
1945 // change was observed (this final test probably isn't very useful).
1946 sync_config_getter.SetExpectedPacUrl("http://version4/wpad.dat");
1947
1948 EXPECT_TRUE(
1949 base::WriteFile(kioslaverc_,
1950 "[Proxy Settings]\nProxyType=2\n"
1951 "Proxy Config Script=http://version4/wpad.dat\n"));
1952
1953 // Wait for change to be noticed.
1954 sync_config_getter.WaitUntilPacUrlMatchesExpectation();
1955
1956 //-----------------------------------------------------
1957
1958 // TODO(eroman): Add a test where kioslaverc is deleted next. Currently this
1959 // doesn't trigger any notifications, but it probably should.
1960 }
1961
TEST_F(ProxyConfigServiceLinuxTest,KDEMultipleKioslaverc)1962 TEST_F(ProxyConfigServiceLinuxTest, KDEMultipleKioslaverc) {
1963 std::string xdg_config_dirs = config_kdedefaults_home_.value();
1964 xdg_config_dirs += ':';
1965 xdg_config_dirs += config_xdg_home_.value();
1966
1967 const struct {
1968 // Short description to identify the test
1969 std::string description;
1970
1971 // Input.
1972 std::string kioslaverc;
1973 base::FilePath kioslaverc_path;
1974 bool auto_detect;
1975 GURL pac_url;
1976 ProxyRulesExpectation proxy_rules;
1977 } tests[] = {
1978 {
1979 TEST_DESC("Use xdg/kioslaverc"),
1980
1981 // Input.
1982 "[Proxy Settings]\nProxyType=3\n"
1983 "Proxy Config Script=http://wpad/wpad.dat\n"
1984 "httpsProxy=www.foo.com\n",
1985 kioslaverc5_xdg_, // kioslaverc path
1986 true, // auto_detect
1987 GURL(), // pac_url
1988 ProxyRulesExpectation::Empty(),
1989 },
1990 {
1991 TEST_DESC(".config/kdedefaults/kioslaverc overrides xdg/kioslaverc"),
1992
1993 // Input.
1994 "[Proxy Settings]\nProxyType=2\n"
1995 "NoProxyFor=.google.com,.kde.org\n",
1996 kioslaverc5_kdedefaults_, // kioslaverc path
1997 false, // auto_detect
1998 GURL("http://wpad/wpad.dat"), // pac_url
1999 ProxyRulesExpectation::Empty(),
2000 },
2001 {
2002 TEST_DESC(".config/kioslaverc overrides others"),
2003
2004 // Input.
2005 "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com 80\n"
2006 "ReversedException=true\n",
2007 kioslaverc5_, // kioslaverc path
2008 false, // auto_detect
2009 GURL(), // pac_url
2010 ProxyRulesExpectation::PerSchemeWithBypassReversed(
2011 "www.google.com:80", // http
2012 "www.foo.com:80", // https
2013 "", // ftp
2014 "*.google.com,*.kde.org"), // bypass rules,
2015 },
2016 };
2017
2018 // Create directories for all configs
2019 base::CreateDirectory(config_home_);
2020 base::CreateDirectory(config_xdg_home_);
2021 base::CreateDirectory(config_kdedefaults_home_);
2022
2023 for (size_t i = 0; i < std::size(tests); ++i) {
2024 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i,
2025 tests[i].description.c_str()));
2026 auto env = std::make_unique<MockEnvironment>();
2027 env->values.XDG_CURRENT_DESKTOP = "KDE";
2028 env->values.KDE_SESSION_VERSION = "5";
2029 env->values.HOME = user_home_.value().c_str();
2030 env->values.XDG_CONFIG_DIRS = xdg_config_dirs.c_str();
2031 SyncConfigGetter sync_config_getter(
2032 std::make_unique<ProxyConfigServiceLinux>(
2033 std::move(env), TRAFFIC_ANNOTATION_FOR_TESTS));
2034 ProxyConfigWithAnnotation config;
2035 // Write the kioslaverc file to specified location.
2036 base::WriteFile(tests[i].kioslaverc_path, tests[i].kioslaverc);
2037 CHECK(base::PathExists(tests[i].kioslaverc_path));
2038 sync_config_getter.SetupAndInitialFetch();
2039 ProxyConfigService::ConfigAvailability availability =
2040 sync_config_getter.SyncGetLatestProxyConfig(&config);
2041 EXPECT_EQ(availability, ProxyConfigService::CONFIG_VALID);
2042
2043 if (availability == ProxyConfigService::CONFIG_VALID) {
2044 EXPECT_EQ(tests[i].auto_detect, config.value().auto_detect());
2045 EXPECT_EQ(tests[i].pac_url, config.value().pac_url());
2046 EXPECT_TRUE(tests[i].proxy_rules.Matches(config.value().proxy_rules()));
2047 }
2048 }
2049 }
2050
2051 } // namespace
2052
2053 } // namespace net
2054