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#include "base/prefs/pref_service.h"
6#include "chrome/browser/extensions/extension_apitest.h"
7#include "chrome/browser/extensions/extension_util.h"
8#include "chrome/browser/prefs/proxy_config_dictionary.h"
9#include "chrome/browser/profiles/profile.h"
10#include "chrome/browser/ui/browser.h"
11#include "chrome/common/chrome_switches.h"
12#include "chrome/common/pref_names.h"
13#include "extensions/common/extension.h"
14#include "extensions/test/result_catcher.h"
15
16namespace extensions {
17
18namespace {
19
20const char kNoServer[] = "";
21const char kNoBypass[] = "";
22const char kNoPac[] = "";
23
24}  // namespace
25
26class ProxySettingsApiTest : public ExtensionApiTest {
27 protected:
28  void ValidateSettings(int expected_mode,
29                        const std::string& expected_server,
30                        const std::string& bypass,
31                        const std::string& expected_pac_url,
32                        PrefService* pref_service) {
33    const PrefService::Preference* pref =
34        pref_service->FindPreference(prefs::kProxy);
35    ASSERT_TRUE(pref != NULL);
36    EXPECT_TRUE(pref->IsExtensionControlled());
37
38    ProxyConfigDictionary dict(pref_service->GetDictionary(prefs::kProxy));
39
40    ProxyPrefs::ProxyMode mode;
41    ASSERT_TRUE(dict.GetMode(&mode));
42    EXPECT_EQ(expected_mode, mode);
43
44    std::string value;
45    if (!bypass.empty()) {
46       ASSERT_TRUE(dict.GetBypassList(&value));
47       EXPECT_EQ(bypass, value);
48     } else {
49       EXPECT_FALSE(dict.GetBypassList(&value));
50     }
51
52    if (!expected_pac_url.empty()) {
53       ASSERT_TRUE(dict.GetPacUrl(&value));
54       EXPECT_EQ(expected_pac_url, value);
55     } else {
56       EXPECT_FALSE(dict.GetPacUrl(&value));
57     }
58
59    if (!expected_server.empty()) {
60      ASSERT_TRUE(dict.GetProxyServer(&value));
61      EXPECT_EQ(expected_server, value);
62    } else {
63      EXPECT_FALSE(dict.GetProxyServer(&value));
64    }
65  }
66
67  void ExpectNoSettings(PrefService* pref_service) {
68    const PrefService::Preference* pref =
69        pref_service->FindPreference(prefs::kProxy);
70    ASSERT_TRUE(pref != NULL);
71    EXPECT_FALSE(pref->IsExtensionControlled());
72  }
73
74  bool SetIsIncognitoEnabled(bool enabled) {
75    ResultCatcher catcher;
76    extensions::util::SetIsIncognitoEnabled(
77        GetSingleLoadedExtension()->id(), browser()->profile(), enabled);
78    if (!catcher.GetNextResult()) {
79      message_ = catcher.message();
80      return false;
81    }
82    return true;
83  }
84};
85
86// Tests direct connection settings.
87IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyDirectSettings) {
88  ASSERT_TRUE(RunExtensionTestIncognito("proxy/direct")) << message_;
89  const Extension* extension = GetSingleLoadedExtension();
90  ASSERT_TRUE(extension);
91
92  PrefService* pref_service = browser()->profile()->GetPrefs();
93  ValidateSettings(ProxyPrefs::MODE_DIRECT, kNoServer, kNoBypass, kNoPac,
94                   pref_service);
95
96  // As the extension is executed with incognito permission, the settings
97  // should propagate to incognito mode.
98  pref_service = browser()->profile()->GetOffTheRecordProfile()->GetPrefs();
99  ValidateSettings(ProxyPrefs::MODE_DIRECT, kNoServer, kNoBypass, kNoPac,
100                   pref_service);
101}
102
103// Tests auto-detect settings.
104IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyAutoSettings) {
105  ASSERT_TRUE(RunExtensionTestIncognito("proxy/auto")) << message_;
106  const Extension* extension = GetSingleLoadedExtension();
107  ASSERT_TRUE(extension);
108
109  PrefService* pref_service = browser()->profile()->GetPrefs();
110  ValidateSettings(ProxyPrefs::MODE_AUTO_DETECT, kNoServer, kNoBypass, kNoPac,
111                   pref_service);
112}
113
114// Tests PAC proxy settings.
115IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyPacScript) {
116  ASSERT_TRUE(RunExtensionTest("proxy/pac")) << message_;
117  const Extension* extension = GetSingleLoadedExtension();
118  ASSERT_TRUE(extension);
119
120  PrefService* pref_service = browser()->profile()->GetPrefs();
121  ValidateSettings(ProxyPrefs::MODE_PAC_SCRIPT, kNoServer, kNoBypass,
122                   "http://wpad/windows.pac", pref_service);
123
124  // As the extension is not executed with incognito permission, the settings
125  // should not propagate to incognito mode.
126  pref_service = browser()->profile()->GetOffTheRecordProfile()->GetPrefs();
127  ExpectNoSettings(pref_service);
128
129  // Now we enable the extension in incognito mode and verify that settings
130  // are applied.
131  ASSERT_TRUE(SetIsIncognitoEnabled(true));
132  ValidateSettings(ProxyPrefs::MODE_PAC_SCRIPT, kNoServer, kNoBypass,
133                   "http://wpad/windows.pac", pref_service);
134
135  // Disabling incognito permission should revoke the settings for incognito
136  // mode.
137  ASSERT_TRUE(SetIsIncognitoEnabled(false));
138  ExpectNoSettings(pref_service);
139}
140
141// Tests PAC proxy settings.
142IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyPacDataUrl) {
143  ASSERT_TRUE(RunExtensionTest("proxy/pacdataurl")) << message_;
144  const Extension* extension = GetSingleLoadedExtension();
145  ASSERT_TRUE(extension);
146  const char url[] =
147       "data:;base64,ZnVuY3Rpb24gRmluZFByb3h5R"
148       "m9yVVJMKHVybCwgaG9zdCkgewogIGlmIChob3N0ID09ICdmb29iYXIuY29tJykKICAgIHJl"
149       "dHVybiAnUFJPWFkgYmxhY2tob2xlOjgwJzsKICByZXR1cm4gJ0RJUkVDVCc7Cn0=";
150  PrefService* pref_service = browser()->profile()->GetPrefs();
151  ValidateSettings(ProxyPrefs::MODE_PAC_SCRIPT, kNoServer, kNoBypass,
152                   url, pref_service);
153}
154
155// Tests PAC proxy settings.
156IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyPacData) {
157  ASSERT_TRUE(RunExtensionTest("proxy/pacdata")) << message_;
158  const Extension* extension = GetSingleLoadedExtension();
159  ASSERT_TRUE(extension);
160  const char url[] =
161      "data:application/x-ns-proxy-autoconfig;base64,ZnVuY3Rpb24gRmluZFByb3h5R"
162      "m9yVVJMKHVybCwgaG9zdCkgewogIGlmIChob3N0ID09ICdmb29iYXIuY29tJykKICAgIHJl"
163      "dHVybiAnUFJPWFkgYmxhY2tob2xlOjgwJzsKICByZXR1cm4gJ0RJUkVDVCc7Cn0=";
164  PrefService* pref_service = browser()->profile()->GetPrefs();
165  ValidateSettings(ProxyPrefs::MODE_PAC_SCRIPT, kNoServer, kNoBypass,
166                   url, pref_service);
167}
168
169// Tests setting a single proxy to cover all schemes.
170IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyFixedSingle) {
171  ASSERT_TRUE(RunExtensionTest("proxy/single")) << message_;
172  const Extension* extension = GetSingleLoadedExtension();
173  ASSERT_TRUE(extension);
174
175  PrefService* pref_service = browser()->profile()->GetPrefs();
176  ValidateSettings(ProxyPrefs::MODE_FIXED_SERVERS,
177                 "127.0.0.1:100",
178                 kNoBypass,
179                 kNoPac,
180                 pref_service);
181}
182
183// Tests setting to use the system's proxy settings.
184IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxySystem) {
185  ASSERT_TRUE(RunExtensionTest("proxy/system")) << message_;
186  const Extension* extension = GetSingleLoadedExtension();
187  ASSERT_TRUE(extension);
188
189  PrefService* pref_service = browser()->profile()->GetPrefs();
190  ValidateSettings(ProxyPrefs::MODE_SYSTEM, kNoServer, kNoBypass, kNoPac,
191                   pref_service);
192}
193
194// Tests setting separate proxies for each scheme.
195IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyFixedIndividual) {
196  ASSERT_TRUE(RunExtensionTestIncognito("proxy/individual")) << message_;
197  const Extension* extension = GetSingleLoadedExtension();
198  ASSERT_TRUE(extension);
199
200  PrefService* pref_service = browser()->profile()->GetPrefs();
201  ValidateSettings(ProxyPrefs::MODE_FIXED_SERVERS,
202                   "http=quic://1.1.1.1:443;"
203                       "https=2.2.2.2:80;"  // http:// is pruned.
204                       "ftp=3.3.3.3:9000;"  // http:// is pruned.
205                       "socks=socks4://4.4.4.4:9090",
206                   kNoBypass,
207                   kNoPac,
208                   pref_service);
209
210  // Now check the incognito preferences.
211  pref_service = browser()->profile()->GetOffTheRecordProfile()->GetPrefs();
212  ValidateSettings(ProxyPrefs::MODE_FIXED_SERVERS,
213                   "http=quic://1.1.1.1:443;"
214                       "https=2.2.2.2:80;"
215                       "ftp=3.3.3.3:9000;"
216                       "socks=socks4://4.4.4.4:9090",
217                   kNoBypass,
218                   kNoPac,
219                   pref_service);
220}
221
222// Tests setting values only for incognito mode
223IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest,
224                       ProxyFixedIndividualIncognitoOnly) {
225  ASSERT_TRUE(RunExtensionTestIncognito("proxy/individual_incognito_only")) <<
226      message_;
227  const Extension* extension = GetSingleLoadedExtension();
228  ASSERT_TRUE(extension);
229
230  PrefService* pref_service = browser()->profile()->GetPrefs();
231  ExpectNoSettings(pref_service);
232
233  // Now check the incognito preferences.
234  pref_service = browser()->profile()->GetOffTheRecordProfile()->GetPrefs();
235  ValidateSettings(ProxyPrefs::MODE_FIXED_SERVERS,
236                   "http=1.1.1.1:80;"
237                       "https=socks5://2.2.2.2:1080;"
238                       "ftp=3.3.3.3:9000;"
239                       "socks=socks4://4.4.4.4:9090",
240                   kNoBypass,
241                   kNoPac,
242                   pref_service);
243}
244
245// Tests setting values also for incognito mode
246// Test disabled due to http://crbug.com/88972.
247IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest,
248                       DISABLED_ProxyFixedIndividualIncognitoAlso) {
249  ASSERT_TRUE(RunExtensionTestIncognito("proxy/individual_incognito_also")) <<
250      message_;
251  const Extension* extension = GetSingleLoadedExtension();
252  ASSERT_TRUE(extension);
253
254  PrefService* pref_service = browser()->profile()->GetPrefs();
255  ValidateSettings(ProxyPrefs::MODE_FIXED_SERVERS,
256                   "http=1.1.1.1:80;"
257                       "https=socks5://2.2.2.2:1080;"
258                       "ftp=3.3.3.3:9000;"
259                       "socks=socks4://4.4.4.4:9090",
260                   kNoBypass,
261                   kNoPac,
262                   pref_service);
263
264  // Now check the incognito preferences.
265  pref_service = browser()->profile()->GetOffTheRecordProfile()->GetPrefs();
266  ValidateSettings(ProxyPrefs::MODE_FIXED_SERVERS,
267                   "http=5.5.5.5:80;"
268                       "https=socks5://6.6.6.6:1080;"
269                       "ftp=7.7.7.7:9000;"
270                       "socks=socks4://8.8.8.8:9090",
271                   kNoBypass,
272                   kNoPac,
273                   pref_service);
274}
275
276// Tests setting and unsetting values
277IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyFixedIndividualRemove) {
278  ASSERT_TRUE(RunExtensionTest("proxy/individual_remove")) << message_;
279  const Extension* extension = GetSingleLoadedExtension();
280  ASSERT_TRUE(extension);
281
282  PrefService* pref_service = browser()->profile()->GetPrefs();
283  ExpectNoSettings(pref_service);
284}
285
286IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest,
287    ProxyBypass) {
288  ASSERT_TRUE(RunExtensionTestIncognito("proxy/bypass")) << message_;
289  const Extension* extension = GetSingleLoadedExtension();
290  ASSERT_TRUE(extension);
291
292  PrefService* pref_service = browser()->profile()->GetPrefs();
293  ValidateSettings(ProxyPrefs::MODE_FIXED_SERVERS,
294                   "http=1.1.1.1:80",
295                   "localhost,::1,foo.bar,<local>",
296                   kNoPac,
297                   pref_service);
298
299  // Now check the incognito preferences.
300  pref_service = browser()->profile()->GetOffTheRecordProfile()->GetPrefs();
301  ValidateSettings(ProxyPrefs::MODE_FIXED_SERVERS,
302                   "http=1.1.1.1:80",
303                   "localhost,::1,foo.bar,<local>",
304                   kNoPac,
305                   pref_service);
306}
307
308// This test sets proxy to an inavalid host "does.not.exist" and then fetches
309// a page from localhost, expecting an error since host is invalid.
310// On ChromeOS, localhost is by default bypassed, so the page from localhost
311// will be fetched successfully, resulting in no error.  Hence this test
312// shouldn't run on ChromeOS.
313#if defined(OS_CHROMEOS)
314#define MAYBE_ProxyEventsInvalidProxy DISABLED_ProxyEventsInvalidProxy
315#else
316#define MAYBE_ProxyEventsInvalidProxy ProxyEventsInvalidProxy
317#endif  // defined(OS_CHROMEOS)
318
319// Tests error events: invalid proxy
320IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, MAYBE_ProxyEventsInvalidProxy) {
321  ASSERT_TRUE(StartEmbeddedTestServer());
322  ASSERT_TRUE(
323      RunExtensionSubtest("proxy/events", "invalid_proxy.html")) << message_;
324}
325
326// Tests error events: PAC script parse error.
327IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyEventsParseError) {
328  ASSERT_TRUE(
329      RunExtensionSubtest("proxy/events", "parse_error.html")) << message_;
330}
331
332}  // namespace extensions
333