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