• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/chromeos/proxy_config_service_impl.h"
6 
7 #include <map>
8 #include <string>
9 #include <vector>
10 
11 #include "base/format_macros.h"
12 #include "base/logging.h"
13 #include "base/string_util.h"
14 #include "base/stringprintf.h"
15 #include "chrome/browser/chromeos/cros/cros_library.h"
16 #include "content/browser/browser_thread.h"
17 #include "content/common/json_value_serializer.h"
18 #include "net/proxy/proxy_config_service_common_unittest.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "testing/platform_test.h"
21 
22 namespace chromeos {
23 
24 namespace {
25 
26 struct Input {  // Fields of chromeos::ProxyConfigServiceImpl::ProxyConfig.
27   ProxyConfigServiceImpl::ProxyConfig::Mode mode;
28   const char* pac_url;
29   const char* single_uri;
30   const char* http_uri;
31   const char* https_uri;
32   const char* ftp_uri;
33   const char* socks_uri;
34   const char* bypass_rules;
35 };
36 
37 // Builds an identifier for each test in an array.
38 #define TEST_DESC(desc) base::StringPrintf("at line %d <%s>", __LINE__, desc)
39 
40 // Shortcuts to declare enums within chromeos's ProxyConfig.
41 #define MK_MODE(mode) ProxyConfigServiceImpl::ProxyConfig::MODE_##mode
42 #define MK_SRC(src) ProxyConfigServiceImpl::ProxyConfig::SOURCE_##src
43 #define MK_SCHM(scheme) net::ProxyServer::SCHEME_##scheme
44 
45 // Inspired from net/proxy/proxy_config_service_linux_unittest.cc.
46 const struct {
47   // Short description to identify the test
48   std::string description;
49 
50   bool is_valid;
51   bool test_read_write_access;
52 
53   Input input;
54 
55   // Expected outputs from fields of net::ProxyConfig (via IO).
56   bool auto_detect;
57   GURL pac_url;
58   net::ProxyRulesExpectation proxy_rules;
59 } tests[] = {
60   {
61     TEST_DESC("No proxying"),
62 
63     true,  // is_valid
64     true,  // test_read_write_access
65 
66     { // Input.
67       MK_MODE(DIRECT),  // mode
68     },
69 
70     // Expected result.
71     false,                                   // auto_detect
72     GURL(),                                  // pac_url
73     net::ProxyRulesExpectation::Empty(),     // proxy_rules
74   },
75 
76   {
77     TEST_DESC("Auto detect"),
78 
79     true,  // is_valid
80     true,  // test_read_write_access
81 
82     { // Input.
83       MK_MODE(AUTO_DETECT),  // mode
84     },
85 
86     // Expected result.
87     true,                                    // auto_detect
88     GURL(),                                  // pac_url
89     net::ProxyRulesExpectation::Empty(),     // proxy_rules
90   },
91 
92   {
93     TEST_DESC("Valid PAC URL"),
94 
95     true,  // is_valid
96     true,  // test_read_write_access
97 
98     { // Input.
99       MK_MODE(PAC_SCRIPT),     // mode
100       "http://wpad/wpad.dat",  // pac_url
101     },
102 
103     // Expected result.
104     false,                                   // auto_detect
105     GURL("http://wpad/wpad.dat"),            // pac_url
106     net::ProxyRulesExpectation::Empty(),     // proxy_rules
107   },
108 
109   {
110     TEST_DESC("Invalid PAC URL"),
111 
112     false,  // is_valid
113     false,  // test_read_write_access
114 
115     { // Input.
116       MK_MODE(PAC_SCRIPT),  // mode
117       "wpad.dat",           // pac_url
118     },
119 
120     // Expected result.
121     false,                                   // auto_detect
122     GURL(),                                  // pac_url
123     net::ProxyRulesExpectation::Empty(),     // proxy_rules
124   },
125 
126   {
127     TEST_DESC("Single-host in proxy list"),
128 
129     true,  // is_valid
130     true,  // test_read_write_access
131 
132     { // Input.
133       MK_MODE(SINGLE_PROXY),  // mode
134       NULL,                   // pac_url
135       "www.google.com",       // single_uri
136     },
137 
138     // Expected result.
139     false,                                   // auto_detect
140     GURL(),                                  // pac_url
141     net::ProxyRulesExpectation::Single(      // proxy_rules
142         "www.google.com:80",  // single proxy
143         ""),                  // bypass rules
144   },
145 
146   {
147     TEST_DESC("Single-host, different port"),
148 
149     true,   // is_valid
150     false,  // test_read_write_access
151 
152     { // Input.
153       MK_MODE(SINGLE_PROXY),  // mode
154       NULL,                   // pac_url
155       "www.google.com:99",    // single_uri
156     },
157 
158     // Expected result.
159     false,                                   // auto_detect
160     GURL(),                                  // pac_url
161     net::ProxyRulesExpectation::Single(      // proxy_rules
162         "www.google.com:99",  // single
163         ""),                  // bypass rules
164   },
165 
166   {
167     TEST_DESC("Tolerate a scheme"),
168 
169     true,   // is_valid
170     false,  // test_read_write_access
171 
172     { // Input.
173       MK_MODE(SINGLE_PROXY),       // mode
174       NULL,                        // pac_url
175       "http://www.google.com:99",  // single_uri
176     },
177 
178     // Expected result.
179     false,                                   // auto_detect
180     GURL(),                                  // pac_url
181     net::ProxyRulesExpectation::Single(      // proxy_rules
182         "www.google.com:99",  // single proxy
183         ""),                  // bypass rules
184   },
185 
186   {
187     TEST_DESC("Per-scheme proxy rules"),
188 
189     true,  // is_valid
190     true,  // test_read_write_access
191 
192     { // Input.
193       MK_MODE(PROXY_PER_SCHEME),  // mode
194       NULL,                       // pac_url
195       NULL,                       // single_uri
196       "www.google.com:80",        // http_uri
197       "www.foo.com:110",          // https_uri
198       "ftp.foo.com:121",          // ftp_uri
199       "socks.com:888",            // socks_uri
200     },
201 
202     // Expected result.
203     false,                          // auto_detect
204     GURL(),                         // pac_url
205     net::ProxyRulesExpectation::PerSchemeWithSocks(  // proxy_rules
206         "www.google.com:80",        // http
207         "https://www.foo.com:110",  // https
208         "ftp.foo.com:121",          // ftp
209         "socks5://socks.com:888",   // fallback proxy
210         ""),                        // bypass rules
211   },
212 
213   {
214     TEST_DESC("Bypass rules"),
215 
216     true,  // is_valid
217     true,  // test_read_write_access
218 
219     { // Input.
220       MK_MODE(SINGLE_PROXY),      // mode
221       NULL,                       // pac_url
222       "www.google.com",           // single_uri
223       NULL, NULL, NULL, NULL,     // per-proto
224       ".google.com, foo.com:99, 1.2.3.4:22, 127.0.0.1/8",  // bypass_rules
225     },
226 
227     // Expected result.
228     false,                          // auto_detect
229     GURL(),                         // pac_url
230     net::ProxyRulesExpectation::Single(                      // proxy_rules
231         "www.google.com:80",                                 // single proxy
232         "*.google.com,*foo.com:99,1.2.3.4:22,127.0.0.1/8"),  // bypass_rules
233   },
234 };  // tests
235 
236 }  // namespace
237 
238 class ProxyConfigServiceImplTest : public PlatformTest {
239  protected:
ProxyConfigServiceImplTest()240   ProxyConfigServiceImplTest()
241       : ui_thread_(BrowserThread::UI, &message_loop_),
242         io_thread_(BrowserThread::IO, &message_loop_) {
243   }
244 
~ProxyConfigServiceImplTest()245   virtual ~ProxyConfigServiceImplTest() {
246     config_service_ = NULL;
247     MessageLoop::current()->RunAllPending();
248   }
249 
CreateConfigService(const ProxyConfigServiceImpl::ProxyConfig & init_config)250   void CreateConfigService(
251       const ProxyConfigServiceImpl::ProxyConfig& init_config) {
252     // Instantiate proxy config service with |init_config|.
253     config_service_ = new ProxyConfigServiceImpl(init_config);
254   }
255 
SetAutomaticProxy(ProxyConfigServiceImpl::ProxyConfig::Mode mode,ProxyConfigServiceImpl::ProxyConfig::Source source,const char * pac_url,ProxyConfigServiceImpl::ProxyConfig * config,ProxyConfigServiceImpl::ProxyConfig::AutomaticProxy * automatic_proxy)256   void SetAutomaticProxy(
257       ProxyConfigServiceImpl::ProxyConfig::Mode mode,
258       ProxyConfigServiceImpl::ProxyConfig::Source source,
259       const char* pac_url,
260       ProxyConfigServiceImpl::ProxyConfig* config,
261       ProxyConfigServiceImpl::ProxyConfig::AutomaticProxy* automatic_proxy) {
262     config->mode = mode;
263     automatic_proxy->source = source;
264     if (pac_url)
265       automatic_proxy->pac_url = GURL(pac_url);
266   }
267 
SetManualProxy(ProxyConfigServiceImpl::ProxyConfig::Mode mode,ProxyConfigServiceImpl::ProxyConfig::Source source,const char * server_uri,net::ProxyServer::Scheme scheme,ProxyConfigServiceImpl::ProxyConfig * config,ProxyConfigServiceImpl::ProxyConfig::ManualProxy * manual_proxy)268   void SetManualProxy(
269       ProxyConfigServiceImpl::ProxyConfig::Mode mode,
270       ProxyConfigServiceImpl::ProxyConfig::Source source,
271       const char* server_uri,
272       net::ProxyServer::Scheme scheme,
273       ProxyConfigServiceImpl::ProxyConfig* config,
274       ProxyConfigServiceImpl::ProxyConfig::ManualProxy* manual_proxy) {
275     if (!server_uri)
276       return;
277     config->mode = mode;
278     manual_proxy->source = source;
279     manual_proxy->server = net::ProxyServer::FromURI(server_uri, scheme);
280   }
281 
InitConfigWithTestInput(const Input & input,ProxyConfigServiceImpl::ProxyConfig::Source source,ProxyConfigServiceImpl::ProxyConfig * init_config)282   void InitConfigWithTestInput(
283       const Input& input, ProxyConfigServiceImpl::ProxyConfig::Source source,
284       ProxyConfigServiceImpl::ProxyConfig* init_config) {
285     switch (input.mode) {
286       case MK_MODE(DIRECT):
287       case MK_MODE(AUTO_DETECT):
288       case MK_MODE(PAC_SCRIPT):
289         SetAutomaticProxy(input.mode, source, input.pac_url, init_config,
290                           &init_config->automatic_proxy);
291         return;
292       case MK_MODE(SINGLE_PROXY):
293         SetManualProxy(input.mode, source, input.single_uri, MK_SCHM(HTTP),
294                        init_config, &init_config->single_proxy);
295         break;
296       case MK_MODE(PROXY_PER_SCHEME):
297         SetManualProxy(input.mode, source, input.http_uri, MK_SCHM(HTTP),
298                        init_config, &init_config->http_proxy);
299         SetManualProxy(input.mode, source, input.https_uri, MK_SCHM(HTTPS),
300                        init_config, &init_config->https_proxy);
301         SetManualProxy(input.mode, source, input.ftp_uri, MK_SCHM(HTTP),
302                        init_config, &init_config->ftp_proxy);
303         SetManualProxy(input.mode, source, input.socks_uri, MK_SCHM(SOCKS5),
304                        init_config, &init_config->socks_proxy);
305         break;
306     }
307     if (input.bypass_rules) {
308       init_config->bypass_rules.ParseFromStringUsingSuffixMatching(
309           input.bypass_rules);
310     }
311   }
312 
TestReadWriteAccessForMode(const Input & input,ProxyConfigServiceImpl::ProxyConfig::Source source)313   void TestReadWriteAccessForMode(const Input& input,
314       ProxyConfigServiceImpl::ProxyConfig::Source source) {
315     // Init config from |source|.
316     ProxyConfigServiceImpl::ProxyConfig init_config;
317     InitConfigWithTestInput(input, source, &init_config);
318     CreateConfigService(init_config);
319 
320     ProxyConfigServiceImpl::ProxyConfig config;
321     config_service()->UIGetProxyConfig(&config);
322 
323     // For owner, write access to config should be equal CanBeWrittenByOwner().
324     // For non-owner, config is never writeable.
325     bool expected_writeable_by_owner = CanBeWrittenByOwner(source);
326     if (config.mode == MK_MODE(PROXY_PER_SCHEME)) {
327       if (input.http_uri) {
328         EXPECT_EQ(expected_writeable_by_owner,
329                   config.CanBeWrittenByUser(true, "http"));
330         EXPECT_FALSE(config.CanBeWrittenByUser(false, "http"));
331       }
332       if (input.https_uri) {
333         EXPECT_EQ(expected_writeable_by_owner,
334                   config.CanBeWrittenByUser(true, "http"));
335         EXPECT_FALSE(config.CanBeWrittenByUser(false, "https"));
336       }
337       if (input.ftp_uri) {
338         EXPECT_EQ(expected_writeable_by_owner,
339                   config.CanBeWrittenByUser(true, "http"));
340         EXPECT_FALSE(config.CanBeWrittenByUser(false, "ftp"));
341       }
342       if (input.socks_uri) {
343         EXPECT_EQ(expected_writeable_by_owner,
344                   config.CanBeWrittenByUser(true, "http"));
345         EXPECT_FALSE(config.CanBeWrittenByUser(false, "socks"));
346       }
347     } else {
348       EXPECT_EQ(expected_writeable_by_owner,
349                 config.CanBeWrittenByUser(true, std::string()));
350       EXPECT_FALSE(config.CanBeWrittenByUser(false, std::string()));
351     }
352   }
353 
TestReadWriteAccessForScheme(ProxyConfigServiceImpl::ProxyConfig::Source source,const char * server_uri,const std::string & scheme)354   void TestReadWriteAccessForScheme(
355       ProxyConfigServiceImpl::ProxyConfig::Source source,
356       const char* server_uri,
357       const std::string& scheme) {
358     // Init with manual |scheme| proxy.
359     ProxyConfigServiceImpl::ProxyConfig init_config;
360     ProxyConfigServiceImpl::ProxyConfig::ManualProxy* proxy =
361         init_config.MapSchemeToProxy(scheme);
362     net::ProxyServer::Scheme net_scheme = MK_SCHM(HTTP);
363     if (scheme == "http" || scheme == "ftp")
364       net_scheme = MK_SCHM(HTTP);
365     else if (scheme == "https")
366       net_scheme = MK_SCHM(HTTPS);
367     else if (scheme == "socks")
368       net_scheme = MK_SCHM(SOCKS4);
369     SetManualProxy(MK_MODE(PROXY_PER_SCHEME), source, server_uri, net_scheme,
370                    &init_config, proxy);
371     CreateConfigService(init_config);
372 
373     ProxyConfigServiceImpl::ProxyConfig config;
374     config_service()->UIGetProxyConfig(&config);
375 
376     // For owner, write access to config should be equal CanBeWrittenByOwner().
377     // For non-owner, config is never writeable.
378     bool expected_writeable_by_owner = CanBeWrittenByOwner(source);
379     EXPECT_EQ(expected_writeable_by_owner,
380               config.CanBeWrittenByUser(true, scheme));
381     EXPECT_FALSE(config.CanBeWrittenByUser(false, scheme));
382 
383     const char* all_schemes[] = {
384       "http", "https", "ftp", "socks",
385     };
386 
387     // Rest of protos should be writeable by owner, but not writeable by
388     // non-owner.
389     for (size_t i = 0; i < ARRAYSIZE_UNSAFE(all_schemes); ++i) {
390       if (scheme == all_schemes[i])
391         continue;
392       EXPECT_TRUE(config.CanBeWrittenByUser(true, all_schemes[i]));
393       EXPECT_FALSE(config.CanBeWrittenByUser(false, all_schemes[i]));
394     }
395   }
396 
397   // Synchronously gets the latest proxy config.
SyncGetLatestProxyConfig(net::ProxyConfig * config)398   bool SyncGetLatestProxyConfig(net::ProxyConfig* config) {
399     // Let message loop process all messages.
400     MessageLoop::current()->RunAllPending();
401     // Calls IOGetProxyConfig (which is called from
402     // ProxyConfigService::GetLatestProxyConfig), running on faked IO thread.
403     return config_service_->IOGetProxyConfig(config);
404   }
405 
config_service() const406   ProxyConfigServiceImpl* config_service() const {
407     return config_service_;
408   }
409 
410  private:
CanBeWrittenByOwner(ProxyConfigServiceImpl::ProxyConfig::Source source) const411   bool CanBeWrittenByOwner(
412     ProxyConfigServiceImpl::ProxyConfig::Source source) const {
413     return source == MK_SRC(POLICY) ? false : true;
414   }
415 
416   ScopedStubCrosEnabler stub_cros_enabler_;
417   MessageLoop message_loop_;
418   BrowserThread ui_thread_;
419   BrowserThread io_thread_;
420 
421   scoped_refptr<ProxyConfigServiceImpl> config_service_;
422 };
423 
TEST_F(ProxyConfigServiceImplTest,ChromeosProxyConfigToNetProxyConfig)424 TEST_F(ProxyConfigServiceImplTest, ChromeosProxyConfigToNetProxyConfig) {
425   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
426     SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
427                               tests[i].description.c_str()));
428 
429     ProxyConfigServiceImpl::ProxyConfig init_config;
430     InitConfigWithTestInput(tests[i].input, MK_SRC(OWNER), &init_config);
431     CreateConfigService(init_config);
432 
433     net::ProxyConfig config;
434     SyncGetLatestProxyConfig(&config);
435 
436     EXPECT_EQ(tests[i].auto_detect, config.auto_detect());
437     EXPECT_EQ(tests[i].pac_url, config.pac_url());
438     EXPECT_TRUE(tests[i].proxy_rules.Matches(config.proxy_rules()));
439   }
440 }
441 
TEST_F(ProxyConfigServiceImplTest,ModifyFromUI)442 TEST_F(ProxyConfigServiceImplTest, ModifyFromUI) {
443   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
444     SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
445                               tests[i].description.c_str()));
446 
447     // Init with direct.
448     ProxyConfigServiceImpl::ProxyConfig init_config;
449     SetAutomaticProxy(MK_MODE(DIRECT), MK_SRC(OWNER), NULL, &init_config,
450                       &init_config.automatic_proxy);
451     CreateConfigService(init_config);
452 
453     // Set config to tests[i].input via UI.
454     net::ProxyBypassRules bypass_rules;
455     const Input& input = tests[i].input;
456     switch (input.mode) {
457       case MK_MODE(DIRECT) :
458         config_service()->UISetProxyConfigToDirect();
459         break;
460       case MK_MODE(AUTO_DETECT) :
461         config_service()->UISetProxyConfigToAutoDetect();
462         break;
463       case MK_MODE(PAC_SCRIPT) :
464         config_service()->UISetProxyConfigToPACScript(GURL(input.pac_url));
465         break;
466       case MK_MODE(SINGLE_PROXY) :
467         config_service()->UISetProxyConfigToSingleProxy(
468             net::ProxyServer::FromURI(input.single_uri, MK_SCHM(HTTP)));
469         if (input.bypass_rules) {
470           bypass_rules.ParseFromStringUsingSuffixMatching(input.bypass_rules);
471           config_service()->UISetProxyConfigBypassRules(bypass_rules);
472         }
473         break;
474       case MK_MODE(PROXY_PER_SCHEME) :
475         if (input.http_uri) {
476           config_service()->UISetProxyConfigToProxyPerScheme("http",
477                   net::ProxyServer::FromURI(input.http_uri, MK_SCHM(HTTP)));
478         }
479         if (input.https_uri) {
480           config_service()->UISetProxyConfigToProxyPerScheme("https",
481               net::ProxyServer::FromURI(input.https_uri, MK_SCHM(HTTPS)));
482         }
483         if (input.ftp_uri) {
484           config_service()->UISetProxyConfigToProxyPerScheme("ftp",
485               net::ProxyServer::FromURI(input.ftp_uri, MK_SCHM(HTTP)));
486         }
487         if (input.socks_uri) {
488           config_service()->UISetProxyConfigToProxyPerScheme("socks",
489               net::ProxyServer::FromURI(input.socks_uri, MK_SCHM(SOCKS5)));
490         }
491         if (input.bypass_rules) {
492           bypass_rules.ParseFromStringUsingSuffixMatching(input.bypass_rules);
493           config_service()->UISetProxyConfigBypassRules(bypass_rules);
494         }
495         break;
496     }
497 
498     // Retrieve config from IO thread.
499     net::ProxyConfig io_config;
500     SyncGetLatestProxyConfig(&io_config);
501     EXPECT_EQ(tests[i].auto_detect, io_config.auto_detect());
502     EXPECT_EQ(tests[i].pac_url, io_config.pac_url());
503     EXPECT_TRUE(tests[i].proxy_rules.Matches(io_config.proxy_rules()));
504 
505     // Retrieve config from UI thread.
506     ProxyConfigServiceImpl::ProxyConfig ui_config;
507     config_service()->UIGetProxyConfig(&ui_config);
508     EXPECT_EQ(input.mode, ui_config.mode);
509     if (tests[i].is_valid) {
510       if (input.pac_url)
511         EXPECT_EQ(GURL(input.pac_url), ui_config.automatic_proxy.pac_url);
512       const net::ProxyRulesExpectation& proxy_rules = tests[i].proxy_rules;
513       if (input.single_uri)
514         EXPECT_EQ(proxy_rules.single_proxy,
515                   ui_config.single_proxy.server.ToURI());
516       if (input.http_uri)
517         EXPECT_EQ(proxy_rules.proxy_for_http,
518                   ui_config.http_proxy.server.ToURI());
519       if (input.https_uri)
520         EXPECT_EQ(proxy_rules.proxy_for_https,
521                   ui_config.https_proxy.server.ToURI());
522       if (input.ftp_uri)
523         EXPECT_EQ(proxy_rules.proxy_for_ftp,
524                   ui_config.ftp_proxy.server.ToURI());
525       if (input.socks_uri) {
526         EXPECT_EQ(proxy_rules.fallback_proxy,
527                   ui_config.socks_proxy.server.ToURI());
528       }
529       if (input.bypass_rules)
530         EXPECT_TRUE(bypass_rules.Equals(ui_config.bypass_rules));
531     }
532   }
533 }
534 
TEST_F(ProxyConfigServiceImplTest,ProxyChangedObserver)535 TEST_F(ProxyConfigServiceImplTest, ProxyChangedObserver) {
536   // This is used to observe for OnProxyConfigChanged notification.
537   class ProxyChangedObserver : public net::ProxyConfigService::Observer {
538    public:
539     explicit ProxyChangedObserver(
540         const scoped_refptr<ProxyConfigServiceImpl>& config_service)
541         : config_service_(config_service) {
542       config_service_->AddObserver(this);
543     }
544     virtual ~ProxyChangedObserver() {
545       config_service_->RemoveObserver(this);
546     }
547     net::ProxyConfigService::ConfigAvailability availability() const {
548       return availability_;
549     }
550     const net::ProxyConfig& config() const {
551       return config_;
552     }
553 
554    private:
555     virtual void OnProxyConfigChanged(
556         const net::ProxyConfig& config,
557         net::ProxyConfigService::ConfigAvailability availability) {
558       config_ = config;
559       availability_ = availability;
560     }
561 
562     scoped_refptr<ProxyConfigServiceImpl> config_service_;
563     net::ProxyConfigService::ConfigAvailability availability_;
564     net::ProxyConfig config_;
565   };
566 
567   // Init with direct.
568   ProxyConfigServiceImpl::ProxyConfig init_config;
569   SetAutomaticProxy(MK_MODE(DIRECT), MK_SRC(OWNER), NULL, &init_config,
570                     &init_config.automatic_proxy);
571   CreateConfigService(init_config);
572 
573   ProxyChangedObserver observer(config_service());
574 
575   // Set to pac script from UI.
576   EXPECT_TRUE(config_service()->UISetProxyConfigToPACScript(
577       GURL("http://wpad.dat")));
578   // Retrieve config from IO thread.
579   net::ProxyConfig io_config;
580   SyncGetLatestProxyConfig(&io_config);
581 
582   // Observer should have gotten the same new proxy config.
583   EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID, observer.availability());
584   EXPECT_TRUE(io_config.Equals(observer.config()));
585 }
586 
TEST_F(ProxyConfigServiceImplTest,SerializeAndDeserialize)587 TEST_F(ProxyConfigServiceImplTest, SerializeAndDeserialize) {
588   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
589     if (!tests[i].is_valid)
590       continue;
591 
592     SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
593                               tests[i].description.c_str()));
594 
595     ProxyConfigServiceImpl::ProxyConfig source_config;
596     InitConfigWithTestInput(tests[i].input, MK_SRC(OWNER), &source_config);
597 
598     // Serialize source_config into std::string.
599     std::string serialized_value;
600     EXPECT_TRUE(source_config.Serialize(&serialized_value));
601 
602     // Deserialize std:string into target_config.
603     ProxyConfigServiceImpl::ProxyConfig target_config;
604     EXPECT_TRUE(target_config.Deserialize(serialized_value));
605 
606     // Compare the configs after serialization and deserialization.
607     net::ProxyConfig net_src_cfg;
608     net::ProxyConfig net_tgt_cfg;
609     source_config.ToNetProxyConfig(&net_src_cfg);
610     target_config.ToNetProxyConfig(&net_tgt_cfg);
611 #if !defined(NDEBUG)
612     if (!net_src_cfg.Equals(net_tgt_cfg)) {
613       std::string src_output, tgt_output;
614       JSONStringValueSerializer src_serializer(&src_output);
615       src_serializer.Serialize(*net_src_cfg.ToValue());
616       JSONStringValueSerializer tgt_serializer(&tgt_output);
617       tgt_serializer.Serialize(*net_tgt_cfg.ToValue());
618       VLOG(1) << "source:\n" << src_output
619               << "\ntarget:\n" << tgt_output;
620     }
621 #endif  // !defined(NDEBUG)
622     EXPECT_TRUE(net_src_cfg.Equals(net_tgt_cfg));
623   }
624 }
625 
TEST_F(ProxyConfigServiceImplTest,ReadWriteAccessForPolicySource)626 TEST_F(ProxyConfigServiceImplTest, ReadWriteAccessForPolicySource) {
627   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
628     if (!tests[i].test_read_write_access)
629       continue;
630     SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
631                               tests[i].description.c_str()));
632     TestReadWriteAccessForMode(tests[i].input, MK_SRC(POLICY));
633   }
634 }
635 
TEST_F(ProxyConfigServiceImplTest,ReadWriteAccessForOwnerSource)636 TEST_F(ProxyConfigServiceImplTest, ReadWriteAccessForOwnerSource) {
637   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
638     if (!tests[i].test_read_write_access)
639       continue;
640     SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
641                               tests[i].description.c_str()));
642     TestReadWriteAccessForMode(tests[i].input, MK_SRC(OWNER));
643   }
644 }
645 
TEST_F(ProxyConfigServiceImplTest,ReadWriteAccessForMixedSchemes)646 TEST_F(ProxyConfigServiceImplTest, ReadWriteAccessForMixedSchemes) {
647   const char* http_uri = "www.google.com:80";
648   const char* https_uri = "www.foo.com:110";
649   const char* ftp_uri = "ftp.foo.com:121";
650   const char* socks_uri = "socks.com:888";
651 
652   // Init with policy source.
653   TestReadWriteAccessForScheme(MK_SRC(POLICY), http_uri, "http");
654   TestReadWriteAccessForScheme(MK_SRC(POLICY), https_uri, "https");
655   TestReadWriteAccessForScheme(MK_SRC(POLICY), ftp_uri, "ftp");
656   TestReadWriteAccessForScheme(MK_SRC(POLICY), socks_uri, "socks");
657 
658   // Init with owner source.
659   TestReadWriteAccessForScheme(MK_SRC(OWNER), http_uri, "http");
660   TestReadWriteAccessForScheme(MK_SRC(OWNER), https_uri, "https");
661   TestReadWriteAccessForScheme(MK_SRC(OWNER), ftp_uri, "ftp");
662   TestReadWriteAccessForScheme(MK_SRC(OWNER), socks_uri, "socks");
663 }
664 
665 }  // namespace chromeos
666