Home | History | Annotate | Download | only in proxy
      1 // Copyright (c) 2012 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 // Unit tests for helper functions for the Chrome Extensions Proxy Settings API.
      6 
      7 #include "base/memory/scoped_ptr.h"
      8 #include "base/values.h"
      9 #include "chrome/browser/extensions/api/proxy/proxy_api_constants.h"
     10 #include "chrome/browser/extensions/api/proxy/proxy_api_helpers.h"
     11 #include "chrome/browser/prefs/proxy_config_dictionary.h"
     12 #include "chrome/browser/prefs/proxy_prefs.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 namespace extensions {
     16 
     17 namespace keys = proxy_api_constants;
     18 
     19 namespace {
     20 
     21 const char kSamplePacScript[] = "test";
     22 const char kSamplePacScriptAsDataUrl[] =
     23     "data:application/x-ns-proxy-autoconfig;base64,dGVzdA==";
     24 const char kSamplePacScriptAsDataUrl2[] =
     25     "data:;base64,dGVzdA==";
     26 const char kSamplePacScriptUrl[] = "http://wpad/wpad.dat";
     27 
     28 // Helper function to create a ProxyServer dictionary as defined in the
     29 // extension API.
     30 base::DictionaryValue* CreateTestProxyServerDict(const std::string& host) {
     31   base::DictionaryValue* dict = new base::DictionaryValue;
     32   dict->SetString(keys::kProxyConfigRuleHost, host);
     33   return dict;
     34 }
     35 
     36 // Helper function to create a ProxyServer dictionary as defined in the
     37 // extension API.
     38 base::DictionaryValue* CreateTestProxyServerDict(const std::string& schema,
     39                                                  const std::string& host,
     40                                                  int port) {
     41   base::DictionaryValue* dict = new base::DictionaryValue;
     42   dict->SetString(keys::kProxyConfigRuleScheme, schema);
     43   dict->SetString(keys::kProxyConfigRuleHost, host);
     44   dict->SetInteger(keys::kProxyConfigRulePort, port);
     45   return dict;
     46 }
     47 
     48 }  // namespace
     49 
     50 namespace proxy_api_helpers {
     51 
     52 TEST(ExtensionProxyApiHelpers, CreateDataURLFromPACScript) {
     53   std::string out;
     54   ASSERT_TRUE(CreateDataURLFromPACScript(kSamplePacScript, &out));
     55   EXPECT_EQ(kSamplePacScriptAsDataUrl, out);
     56 }
     57 
     58 TEST(ExtensionProxyApiHelpers, CreatePACScriptFromDataURL) {
     59   std::string out;
     60   // Verify deserialization of a PAC data:// URL that we created ourselves.
     61   ASSERT_TRUE(CreatePACScriptFromDataURL(kSamplePacScriptAsDataUrl, &out));
     62   EXPECT_EQ(kSamplePacScript, out);
     63 
     64   // Check that we don't require a mime-type.
     65   ASSERT_TRUE(CreatePACScriptFromDataURL(kSamplePacScriptAsDataUrl2, &out));
     66   EXPECT_EQ(kSamplePacScript, out);
     67 
     68   EXPECT_FALSE(CreatePACScriptFromDataURL("http://www.google.com", &out));
     69 }
     70 
     71 TEST(ExtensionProxyApiHelpers, GetProxyModeFromExtensionPref) {
     72   base::DictionaryValue proxy_config;
     73   ProxyPrefs::ProxyMode mode;
     74   std::string error;
     75   bool bad_message = false;
     76 
     77   // Test positive case.
     78   proxy_config.SetString(
     79       keys::kProxyConfigMode,
     80       ProxyPrefs::ProxyModeToString(ProxyPrefs::MODE_DIRECT));
     81   ASSERT_TRUE(GetProxyModeFromExtensionPref(&proxy_config, &mode, &error,
     82                                             &bad_message));
     83   EXPECT_EQ(ProxyPrefs::MODE_DIRECT, mode);
     84   EXPECT_EQ(std::string(), error);
     85   EXPECT_FALSE(bad_message);
     86 
     87   // Test negative case.
     88   proxy_config.SetString(keys::kProxyConfigMode, "foobar");
     89   EXPECT_FALSE(GetProxyModeFromExtensionPref(&proxy_config, &mode, &error,
     90                                              &bad_message));
     91   EXPECT_TRUE(bad_message);
     92 
     93   // Do not test |error|, as an invalid enumeration value is considered an
     94   // internal error. It should be filtered by the extensions API.
     95 }
     96 
     97 TEST(ExtensionProxyApiHelpers, GetPacUrlFromExtensionPref) {
     98   std::string out;
     99   std::string error;
    100   bool bad_message = false;
    101 
    102   base::DictionaryValue proxy_config;
    103   proxy_config.SetString(
    104       keys::kProxyConfigMode,
    105       ProxyPrefs::ProxyModeToString(ProxyPrefs::MODE_PAC_SCRIPT));
    106 
    107   // Currently we are still missing a PAC script entry.
    108   // This is silently ignored.
    109   ASSERT_TRUE(GetPacUrlFromExtensionPref(&proxy_config, &out, &error,
    110                                          &bad_message));
    111   EXPECT_EQ(std::string(), out);
    112   EXPECT_EQ(std::string(), error);
    113   EXPECT_FALSE(bad_message);
    114 
    115   // Set up a pac script.
    116   base::DictionaryValue* pacScriptDict = new base::DictionaryValue;
    117   pacScriptDict->SetString(keys::kProxyConfigPacScriptUrl, kSamplePacScriptUrl);
    118   proxy_config.Set(keys::kProxyConfigPacScript, pacScriptDict);
    119 
    120   ASSERT_TRUE(GetPacUrlFromExtensionPref(&proxy_config, &out, &error,
    121                                          &bad_message));
    122   EXPECT_EQ(kSamplePacScriptUrl, out);
    123   EXPECT_EQ(std::string(), error);
    124   EXPECT_FALSE(bad_message);
    125 }
    126 
    127 TEST(ExtensionProxyApiHelpers, GetPacDataFromExtensionPref) {
    128   std::string out;
    129   std::string error;
    130   bool bad_message = false;
    131 
    132   base::DictionaryValue proxy_config;
    133   proxy_config.SetString(
    134       keys::kProxyConfigMode,
    135       ProxyPrefs::ProxyModeToString(ProxyPrefs::MODE_PAC_SCRIPT));
    136 
    137   // Currently we are still missing a PAC data entry. This is silently ignored.
    138   ASSERT_TRUE(GetPacDataFromExtensionPref(&proxy_config, &out, &error,
    139                                           &bad_message));
    140   EXPECT_EQ(std::string(), out);
    141   EXPECT_EQ(std::string(), error);
    142   EXPECT_FALSE(bad_message);
    143 
    144   // Set up a PAC script.
    145   base::DictionaryValue* pacScriptDict = new base::DictionaryValue;
    146   pacScriptDict->SetString(keys::kProxyConfigPacScriptData, kSamplePacScript);
    147   proxy_config.Set(keys::kProxyConfigPacScript, pacScriptDict);
    148 
    149   ASSERT_TRUE(GetPacDataFromExtensionPref(&proxy_config, &out, &error,
    150                                           &bad_message));
    151   EXPECT_EQ(kSamplePacScript, out);
    152   EXPECT_EQ(std::string(), error);
    153   EXPECT_FALSE(bad_message);
    154 }
    155 
    156 TEST(ExtensionProxyApiHelpers, GetProxyRulesStringFromExtensionPref) {
    157   std::string out;
    158   std::string error;
    159   bool bad_message = false;
    160 
    161   base::DictionaryValue proxy_config;
    162   proxy_config.SetString(
    163       keys::kProxyConfigMode,
    164       ProxyPrefs::ProxyModeToString(ProxyPrefs::MODE_FIXED_SERVERS));
    165 
    166   // Currently we are still missing a proxy config entry.
    167   // This is silently ignored.
    168   ASSERT_TRUE(
    169       GetProxyRulesStringFromExtensionPref(&proxy_config, &out, &error,
    170                                            &bad_message));
    171   EXPECT_EQ(std::string(), out);
    172   EXPECT_EQ(std::string(), error);
    173 
    174   base::DictionaryValue* proxy_rules = new base::DictionaryValue;
    175   proxy_rules->Set(keys::field_name[1], CreateTestProxyServerDict("proxy1"));
    176   proxy_rules->Set(keys::field_name[2], CreateTestProxyServerDict("proxy2"));
    177   proxy_config.Set(keys::kProxyConfigRules, proxy_rules);
    178 
    179   ASSERT_TRUE(
    180       GetProxyRulesStringFromExtensionPref(&proxy_config, &out, &error,
    181                                            &bad_message));
    182   EXPECT_EQ("http=proxy1:80;https=proxy2:80", out);
    183   EXPECT_EQ(std::string(), error);
    184   EXPECT_FALSE(bad_message);
    185 }
    186 
    187 TEST(ExtensionProxyApiHelpers, GetBypassListFromExtensionPref) {
    188   std::string out;
    189   std::string error;
    190   bool bad_message = false;
    191 
    192   base::DictionaryValue proxy_config;
    193   proxy_config.SetString(
    194       keys::kProxyConfigMode,
    195       ProxyPrefs::ProxyModeToString(ProxyPrefs::MODE_FIXED_SERVERS));
    196 
    197   // Currently we are still missing a proxy config entry.
    198   // This is silently ignored.
    199   ASSERT_TRUE(
    200       GetBypassListFromExtensionPref(&proxy_config, &out, &error,
    201                                      &bad_message));
    202   EXPECT_EQ(std::string(), out);
    203   EXPECT_EQ(std::string(), error);
    204   EXPECT_FALSE(bad_message);
    205 
    206   base::ListValue* bypass_list = new base::ListValue;
    207   bypass_list->Append(new base::StringValue("host1"));
    208   bypass_list->Append(new base::StringValue("host2"));
    209   base::DictionaryValue* proxy_rules = new base::DictionaryValue;
    210   proxy_rules->Set(keys::kProxyConfigBypassList, bypass_list);
    211   proxy_config.Set(keys::kProxyConfigRules, proxy_rules);
    212 
    213   ASSERT_TRUE(
    214       GetBypassListFromExtensionPref(&proxy_config, &out, &error,
    215                                      &bad_message));
    216   EXPECT_EQ("host1,host2", out);
    217   EXPECT_EQ(std::string(), error);
    218   EXPECT_FALSE(bad_message);
    219 }
    220 
    221 TEST(ExtensionProxyApiHelpers, CreateProxyConfigDict) {
    222   std::string error;
    223   scoped_ptr<base::DictionaryValue> exp_direct(
    224       ProxyConfigDictionary::CreateDirect());
    225   scoped_ptr<base::DictionaryValue> out_direct(
    226       CreateProxyConfigDict(ProxyPrefs::MODE_DIRECT,
    227                             false,
    228                             std::string(),
    229                             std::string(),
    230                             std::string(),
    231                             std::string(),
    232                             &error));
    233   EXPECT_TRUE(base::Value::Equals(exp_direct.get(), out_direct.get()));
    234 
    235   scoped_ptr<base::DictionaryValue> exp_auto(
    236       ProxyConfigDictionary::CreateAutoDetect());
    237   scoped_ptr<base::DictionaryValue> out_auto(
    238       CreateProxyConfigDict(ProxyPrefs::MODE_AUTO_DETECT,
    239                             false,
    240                             std::string(),
    241                             std::string(),
    242                             std::string(),
    243                             std::string(),
    244                             &error));
    245   EXPECT_TRUE(base::Value::Equals(exp_auto.get(), out_auto.get()));
    246 
    247   scoped_ptr<base::DictionaryValue> exp_pac_url(
    248       ProxyConfigDictionary::CreatePacScript(kSamplePacScriptUrl, false));
    249   scoped_ptr<base::DictionaryValue> out_pac_url(
    250       CreateProxyConfigDict(ProxyPrefs::MODE_PAC_SCRIPT,
    251                             false,
    252                             kSamplePacScriptUrl,
    253                             std::string(),
    254                             std::string(),
    255                             std::string(),
    256                             &error));
    257   EXPECT_TRUE(base::Value::Equals(exp_pac_url.get(), out_pac_url.get()));
    258 
    259   scoped_ptr<base::DictionaryValue> exp_pac_data(
    260       ProxyConfigDictionary::CreatePacScript(kSamplePacScriptAsDataUrl, false));
    261   scoped_ptr<base::DictionaryValue> out_pac_data(
    262       CreateProxyConfigDict(ProxyPrefs::MODE_PAC_SCRIPT,
    263                             false,
    264                             std::string(),
    265                             kSamplePacScript,
    266                             std::string(),
    267                             std::string(),
    268                             &error));
    269   EXPECT_TRUE(base::Value::Equals(exp_pac_data.get(), out_pac_data.get()));
    270 
    271   scoped_ptr<base::DictionaryValue> exp_fixed(
    272       ProxyConfigDictionary::CreateFixedServers("foo:80", "localhost"));
    273   scoped_ptr<base::DictionaryValue> out_fixed(
    274       CreateProxyConfigDict(ProxyPrefs::MODE_FIXED_SERVERS,
    275                             false,
    276                             std::string(),
    277                             std::string(),
    278                             "foo:80",
    279                             "localhost",
    280                             &error));
    281   EXPECT_TRUE(base::Value::Equals(exp_fixed.get(), out_fixed.get()));
    282 
    283   scoped_ptr<base::DictionaryValue> exp_system(
    284       ProxyConfigDictionary::CreateSystem());
    285   scoped_ptr<base::DictionaryValue> out_system(
    286       CreateProxyConfigDict(ProxyPrefs::MODE_SYSTEM,
    287                             false,
    288                             std::string(),
    289                             std::string(),
    290                             std::string(),
    291                             std::string(),
    292                             &error));
    293   EXPECT_TRUE(base::Value::Equals(exp_system.get(), out_system.get()));
    294 
    295   // Neither of them should have set an error.
    296   EXPECT_EQ(std::string(), error);
    297 }
    298 
    299 TEST(ExtensionProxyApiHelpers, GetProxyServer) {
    300   base::DictionaryValue proxy_server_dict;
    301   net::ProxyServer created;
    302   std::string error;
    303   bool bad_message = false;
    304 
    305   // Test simplest case, no schema nor port specified --> defaults are used.
    306   proxy_server_dict.SetString(keys::kProxyConfigRuleHost, "proxy_server");
    307   ASSERT_TRUE(
    308       GetProxyServer(&proxy_server_dict, net::ProxyServer::SCHEME_HTTP,
    309                      &created, &error, &bad_message));
    310   EXPECT_EQ("PROXY proxy_server:80", created.ToPacString());
    311   EXPECT_FALSE(bad_message);
    312 
    313   // Test complete case.
    314   proxy_server_dict.SetString(keys::kProxyConfigRuleScheme, "socks4");
    315   proxy_server_dict.SetInteger(keys::kProxyConfigRulePort, 1234);
    316   ASSERT_TRUE(
    317         GetProxyServer(&proxy_server_dict, net::ProxyServer::SCHEME_HTTP,
    318                        &created, &error, &bad_message));
    319   EXPECT_EQ("SOCKS proxy_server:1234", created.ToPacString());
    320   EXPECT_FALSE(bad_message);
    321 }
    322 
    323 TEST(ExtensionProxyApiHelpers, JoinUrlList) {
    324   bool bad_message = false;
    325   base::ListValue list;
    326   list.Append(new base::StringValue("s1"));
    327   list.Append(new base::StringValue("s2"));
    328   list.Append(new base::StringValue("s3"));
    329 
    330   std::string out;
    331   std::string error;
    332   ASSERT_TRUE(JoinUrlList(&list, ";", &out, &error, &bad_message));
    333   EXPECT_EQ("s1;s2;s3", out);
    334   EXPECT_FALSE(bad_message);
    335 }
    336 
    337 // This tests CreateProxyServerDict as well.
    338 TEST(ExtensionProxyApiHelpers, CreateProxyRulesDict) {
    339   scoped_ptr<base::DictionaryValue> browser_pref(
    340       ProxyConfigDictionary::CreateFixedServers(
    341           "http=proxy1:80;https=proxy2:80;ftp=proxy3:80;socks=proxy4:80",
    342           "localhost"));
    343   ProxyConfigDictionary config(browser_pref.get());
    344   scoped_ptr<base::DictionaryValue> extension_pref(
    345       CreateProxyRulesDict(config));
    346   ASSERT_TRUE(extension_pref.get());
    347 
    348   scoped_ptr<base::DictionaryValue> expected(new base::DictionaryValue);
    349   expected->Set("proxyForHttp",
    350                 CreateTestProxyServerDict("http", "proxy1", 80));
    351   expected->Set("proxyForHttps",
    352                 CreateTestProxyServerDict("http", "proxy2", 80));
    353   expected->Set("proxyForFtp",
    354                 CreateTestProxyServerDict("http", "proxy3", 80));
    355   expected->Set("fallbackProxy",
    356                 CreateTestProxyServerDict("socks4", "proxy4", 80));
    357   base::ListValue* bypass_list = new base::ListValue;
    358   bypass_list->Append(new base::StringValue("localhost"));
    359   expected->Set(keys::kProxyConfigBypassList, bypass_list);
    360 
    361   EXPECT_TRUE(base::Value::Equals(expected.get(), extension_pref.get()));
    362 }
    363 
    364 // Test multiple proxies per scheme -- expect that only the first is returned.
    365 TEST(ExtensionProxyApiHelpers, CreateProxyRulesDictMultipleProxies) {
    366   scoped_ptr<base::DictionaryValue> browser_pref(
    367       ProxyConfigDictionary::CreateFixedServers(
    368           "http=proxy1:80,default://;https=proxy2:80,proxy1:80;ftp=proxy3:80,"
    369           "https://proxy5:443;socks=proxy4:80,proxy1:80",
    370           "localhost"));
    371   ProxyConfigDictionary config(browser_pref.get());
    372   scoped_ptr<base::DictionaryValue> extension_pref(
    373       CreateProxyRulesDict(config));
    374   ASSERT_TRUE(extension_pref.get());
    375 
    376   scoped_ptr<base::DictionaryValue> expected(new base::DictionaryValue);
    377   expected->Set("proxyForHttp",
    378                 CreateTestProxyServerDict("http", "proxy1", 80));
    379   expected->Set("proxyForHttps",
    380                 CreateTestProxyServerDict("http", "proxy2", 80));
    381   expected->Set("proxyForFtp",
    382                 CreateTestProxyServerDict("http", "proxy3", 80));
    383   expected->Set("fallbackProxy",
    384                 CreateTestProxyServerDict("socks4", "proxy4", 80));
    385   base::ListValue* bypass_list = new base::ListValue;
    386   bypass_list->Append(new base::StringValue("localhost"));
    387   expected->Set(keys::kProxyConfigBypassList, bypass_list);
    388 
    389   EXPECT_TRUE(base::Value::Equals(expected.get(), extension_pref.get()));
    390 }
    391 
    392 // Test if a PAC script URL is specified.
    393 TEST(ExtensionProxyApiHelpers, CreatePacScriptDictWithUrl) {
    394   scoped_ptr<base::DictionaryValue> browser_pref(
    395       ProxyConfigDictionary::CreatePacScript(kSamplePacScriptUrl, false));
    396   ProxyConfigDictionary config(browser_pref.get());
    397   scoped_ptr<base::DictionaryValue> extension_pref(CreatePacScriptDict(config));
    398   ASSERT_TRUE(extension_pref.get());
    399 
    400   scoped_ptr<base::DictionaryValue> expected(new base::DictionaryValue);
    401   expected->SetString(keys::kProxyConfigPacScriptUrl, kSamplePacScriptUrl);
    402   expected->SetBoolean(keys::kProxyConfigPacScriptMandatory, false);
    403 
    404   EXPECT_TRUE(base::Value::Equals(expected.get(), extension_pref.get()));
    405 }
    406 
    407 // Test if a PAC script is encoded in a data URL.
    408 TEST(ExtensionProxyApiHelpers, CreatePacScriptDictWidthData) {
    409   scoped_ptr<base::DictionaryValue> browser_pref(
    410       ProxyConfigDictionary::CreatePacScript(kSamplePacScriptAsDataUrl, false));
    411   ProxyConfigDictionary config(browser_pref.get());
    412   scoped_ptr<base::DictionaryValue> extension_pref(CreatePacScriptDict(config));
    413   ASSERT_TRUE(extension_pref.get());
    414 
    415   scoped_ptr<base::DictionaryValue> expected(new base::DictionaryValue);
    416   expected->SetString(keys::kProxyConfigPacScriptData, kSamplePacScript);
    417   expected->SetBoolean(keys::kProxyConfigPacScriptMandatory, false);
    418 
    419   EXPECT_TRUE(base::Value::Equals(expected.get(), extension_pref.get()));
    420 }
    421 
    422 TEST(ExtensionProxyApiHelpers, TokenizeToStringList) {
    423   base::ListValue expected;
    424   expected.Append(new base::StringValue("s1"));
    425   expected.Append(new base::StringValue("s2"));
    426   expected.Append(new base::StringValue("s3"));
    427 
    428   scoped_ptr<base::ListValue> out(TokenizeToStringList("s1;s2;s3", ";"));
    429   EXPECT_TRUE(base::Value::Equals(&expected, out.get()));
    430 }
    431 
    432 }  // namespace proxy_api_helpers
    433 }  // namespace extensions
    434