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/strings/stringprintf.h"
6 #include "base/strings/utf_string_conversions.h"
7 #include "chrome/browser/extensions/api/permissions/permissions_api.h"
8 #include "chrome/browser/extensions/extension_apitest.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
12 #include "chrome/common/chrome_switches.h"
13 #include "chrome/test/base/ui_test_utils.h"
14 #include "content/public/browser/web_contents.h"
15 #include "content/public/test/browser_test_utils.h"
16 #include "extensions/browser/notification_types.h"
17 #include "extensions/common/extension.h"
18 #include "extensions/test/result_catcher.h"
19 #include "net/dns/mock_host_resolver.h"
20 #include "net/test/embedded_test_server/embedded_test_server.h"
21 #include "url/gurl.h"
22
23 namespace extensions {
24
25 namespace {
26
27 // A fake webstore domain.
28 const char kWebstoreDomain[] = "cws.com";
29
30 // Check whether or not style was injected, with |expected_injection| indicating
31 // the expected result. Also ensure that no CSS was added to the
32 // document.styleSheets array.
CheckStyleInjection(Browser * browser,const GURL & url,bool expected_injection)33 testing::AssertionResult CheckStyleInjection(Browser* browser,
34 const GURL& url,
35 bool expected_injection) {
36 ui_test_utils::NavigateToURL(browser, url);
37
38 bool css_injected = false;
39 if (!content::ExecuteScriptAndExtractBool(
40 browser->tab_strip_model()->GetActiveWebContents(),
41 "window.domAutomationController.send("
42 " document.defaultView.getComputedStyle(document.body, null)."
43 " getPropertyValue('display') == 'none');",
44 &css_injected)) {
45 return testing::AssertionFailure()
46 << "Failed to execute script and extract bool for injection status.";
47 }
48
49 if (css_injected != expected_injection) {
50 std::string message;
51 if (css_injected)
52 message = "CSS injected when no injection was expected.";
53 else
54 message = "CSS not injected when injection was expected.";
55 return testing::AssertionFailure() << message;
56 }
57
58 bool css_doesnt_add_to_list = false;
59 if (!content::ExecuteScriptAndExtractBool(
60 browser->tab_strip_model()->GetActiveWebContents(),
61 "window.domAutomationController.send("
62 " document.styleSheets.length == 0);",
63 &css_doesnt_add_to_list)) {
64 return testing::AssertionFailure()
65 << "Failed to execute script and extract bool for stylesheets length.";
66 }
67 if (!css_doesnt_add_to_list) {
68 return testing::AssertionFailure()
69 << "CSS injection added to number of stylesheets.";
70 }
71
72 return testing::AssertionSuccess();
73 }
74
75 } // namespace
76
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,ContentScriptAllFrames)77 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptAllFrames) {
78 ASSERT_TRUE(StartEmbeddedTestServer());
79 ASSERT_TRUE(RunExtensionTest("content_scripts/all_frames")) << message_;
80 }
81
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,ContentScriptAboutBlankIframes)82 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptAboutBlankIframes) {
83 ASSERT_TRUE(StartEmbeddedTestServer());
84 ASSERT_TRUE(
85 RunExtensionTest("content_scripts/about_blank_iframes")) << message_;
86 }
87
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,ContentScriptAboutBlankAndSrcdoc)88 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptAboutBlankAndSrcdoc) {
89 // The optional "*://*/*" permission is requested after verifying that
90 // content script insertion solely depends on content_scripts[*].matches.
91 // The permission is needed for chrome.tabs.executeScript tests.
92 PermissionsRequestFunction::SetAutoConfirmForTests(true);
93 PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
94
95 ASSERT_TRUE(StartEmbeddedTestServer());
96 ASSERT_TRUE(RunExtensionTest("content_scripts/about_blank_srcdoc"))
97 << message_;
98 }
99
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,ContentScriptExtensionIframe)100 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptExtensionIframe) {
101 ASSERT_TRUE(StartEmbeddedTestServer());
102 ASSERT_TRUE(RunExtensionTest("content_scripts/extension_iframe")) << message_;
103 }
104
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,ContentScriptExtensionProcess)105 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptExtensionProcess) {
106 ASSERT_TRUE(StartEmbeddedTestServer());
107 ASSERT_TRUE(
108 RunExtensionTest("content_scripts/extension_process")) << message_;
109 }
110
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,ContentScriptFragmentNavigation)111 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptFragmentNavigation) {
112 ASSERT_TRUE(StartEmbeddedTestServer());
113 const char* extension_name = "content_scripts/fragment";
114 ASSERT_TRUE(RunExtensionTest(extension_name)) << message_;
115 }
116
117 // Times out on Linux: http://crbug.com/163097
118 #if defined(OS_LINUX)
119 #define MAYBE_ContentScriptIsolatedWorlds DISABLED_ContentScriptIsolatedWorlds
120 #else
121 #define MAYBE_ContentScriptIsolatedWorlds ContentScriptIsolatedWorlds
122 #endif
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,MAYBE_ContentScriptIsolatedWorlds)123 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_ContentScriptIsolatedWorlds) {
124 // This extension runs various bits of script and tests that they all run in
125 // the same isolated world.
126 ASSERT_TRUE(StartEmbeddedTestServer());
127 ASSERT_TRUE(RunExtensionTest("content_scripts/isolated_world1")) << message_;
128
129 // Now load a different extension, inject into same page, verify worlds aren't
130 // shared.
131 ASSERT_TRUE(RunExtensionTest("content_scripts/isolated_world2")) << message_;
132 }
133
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,ContentScriptIgnoreHostPermissions)134 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptIgnoreHostPermissions) {
135 host_resolver()->AddRule("a.com", "127.0.0.1");
136 host_resolver()->AddRule("b.com", "127.0.0.1");
137 ASSERT_TRUE(StartEmbeddedTestServer());
138 ASSERT_TRUE(RunExtensionTest(
139 "content_scripts/dont_match_host_permissions")) << message_;
140 }
141
142 // crbug.com/39249 -- content scripts js should not run on view source.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,ContentScriptViewSource)143 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptViewSource) {
144 ASSERT_TRUE(StartEmbeddedTestServer());
145 ASSERT_TRUE(RunExtensionTest("content_scripts/view_source")) << message_;
146 }
147
148 // crbug.com/126257 -- content scripts should not get injected into other
149 // extensions.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,ContentScriptOtherExtensions)150 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptOtherExtensions) {
151 host_resolver()->AddRule("a.com", "127.0.0.1");
152 ASSERT_TRUE(StartEmbeddedTestServer());
153 // First, load extension that sets up content script.
154 ASSERT_TRUE(RunExtensionTest("content_scripts/other_extensions/injector"))
155 << message_;
156 // Then load targeted extension to make sure its content isn't changed.
157 ASSERT_TRUE(RunExtensionTest("content_scripts/other_extensions/victim"))
158 << message_;
159 }
160
161 class ContentScriptCssInjectionTest : public ExtensionApiTest {
162 protected:
163 // TODO(rdevlin.cronin): Make a testing switch that looks like FeatureSwitch,
164 // but takes in an optional value so that we don't have to do this.
SetUpCommandLine(base::CommandLine * command_line)165 virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE {
166 ExtensionApiTest::SetUpCommandLine(command_line);
167 // We change the Webstore URL to be http://cws.com. We need to do this so
168 // we can check that css injection is not allowed on the webstore (which
169 // could lead to spoofing). Unfortunately, host_resolver seems to have
170 // problems with redirecting "chrome.google.com" to the test server, so we
171 // can't use the real Webstore's URL. If this changes, we could clean this
172 // up.
173 command_line->AppendSwitchASCII(
174 switches::kAppsGalleryURL,
175 base::StringPrintf("http://%s", kWebstoreDomain));
176 }
177 };
178
IN_PROC_BROWSER_TEST_F(ContentScriptCssInjectionTest,ContentScriptInjectsStyles)179 IN_PROC_BROWSER_TEST_F(ContentScriptCssInjectionTest,
180 ContentScriptInjectsStyles) {
181 ASSERT_TRUE(StartEmbeddedTestServer());
182 host_resolver()->AddRule(kWebstoreDomain, "127.0.0.1");
183
184 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("content_scripts")
185 .AppendASCII("css_injection")));
186
187 // CSS injection should be allowed on an aribitrary web page.
188 GURL url =
189 embedded_test_server()->GetURL("/extensions/test_file_with_body.html");
190 EXPECT_TRUE(CheckStyleInjection(browser(), url, true));
191
192 // The loaded extension has an exclude match for "extensions/test_file.html",
193 // so no CSS should be injected.
194 url = embedded_test_server()->GetURL("/extensions/test_file.html");
195 EXPECT_TRUE(CheckStyleInjection(browser(), url, false));
196
197 // We disallow all injection on the webstore.
198 GURL::Replacements replacements;
199 std::string host(kWebstoreDomain);
200 replacements.SetHostStr(host);
201 url = embedded_test_server()->GetURL("/extensions/test_file_with_body.html")
202 .ReplaceComponents(replacements);
203 EXPECT_TRUE(CheckStyleInjection(browser(), url, false));
204 }
205
206 // crbug.com/120762
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,DISABLED_ContentScriptStylesInjectedIntoExistingRenderers)207 IN_PROC_BROWSER_TEST_F(
208 ExtensionApiTest,
209 DISABLED_ContentScriptStylesInjectedIntoExistingRenderers) {
210 ASSERT_TRUE(StartEmbeddedTestServer());
211
212 content::WindowedNotificationObserver signal(
213 extensions::NOTIFICATION_USER_SCRIPTS_UPDATED,
214 content::Source<Profile>(browser()->profile()));
215
216 // Start with a renderer already open at a URL.
217 GURL url(test_server()->GetURL("file/extensions/test_file.html"));
218 ui_test_utils::NavigateToURL(browser(), url);
219
220 LoadExtension(
221 test_data_dir_.AppendASCII("content_scripts/existing_renderers"));
222
223 signal.Wait();
224
225 // And check that its styles were affected by the styles that just got loaded.
226 bool styles_injected;
227 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
228 browser()->tab_strip_model()->GetActiveWebContents(),
229 "window.domAutomationController.send("
230 " document.defaultView.getComputedStyle(document.body, null)."
231 " getPropertyValue('background-color') == 'rgb(255, 0, 0)')",
232 &styles_injected));
233 ASSERT_TRUE(styles_injected);
234 }
235
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,ContentScriptCSSLocalization)236 IN_PROC_BROWSER_TEST_F(ExtensionApiTest,
237 ContentScriptCSSLocalization) {
238 ASSERT_TRUE(StartEmbeddedTestServer());
239 ASSERT_TRUE(RunExtensionTest("content_scripts/css_l10n")) << message_;
240 }
241
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,ContentScriptExtensionAPIs)242 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptExtensionAPIs) {
243 ASSERT_TRUE(StartEmbeddedTestServer());
244
245 const extensions::Extension* extension = LoadExtension(
246 test_data_dir_.AppendASCII("content_scripts/extension_api"));
247
248 ResultCatcher catcher;
249 ui_test_utils::NavigateToURL(
250 browser(),
251 embedded_test_server()->GetURL(
252 "/extensions/api_test/content_scripts/extension_api/functions.html"));
253 EXPECT_TRUE(catcher.GetNextResult());
254
255 // Navigate to a page that will cause a content script to run that starts
256 // listening for an extension event.
257 ui_test_utils::NavigateToURL(
258 browser(),
259 embedded_test_server()->GetURL(
260 "/extensions/api_test/content_scripts/extension_api/events.html"));
261
262 // Navigate to an extension page that will fire the event events.js is
263 // listening for.
264 ui_test_utils::NavigateToURLWithDisposition(
265 browser(), extension->GetResourceURL("fire_event.html"),
266 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_NONE);
267 EXPECT_TRUE(catcher.GetNextResult());
268 }
269
270 // Flaky on Windows. http://crbug.com/248418
271 #if defined(OS_WIN)
272 #define MAYBE_ContentScriptPermissionsApi DISABLED_ContentScriptPermissionsApi
273 #else
274 #define MAYBE_ContentScriptPermissionsApi ContentScriptPermissionsApi
275 #endif
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,MAYBE_ContentScriptPermissionsApi)276 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_ContentScriptPermissionsApi) {
277 extensions::PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
278 extensions::PermissionsRequestFunction::SetAutoConfirmForTests(true);
279 host_resolver()->AddRule("*.com", "127.0.0.1");
280 ASSERT_TRUE(StartEmbeddedTestServer());
281 ASSERT_TRUE(RunExtensionTest("content_scripts/permissions")) << message_;
282 }
283
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,ContentScriptBypassPageCSP)284 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptBypassPageCSP) {
285 ASSERT_TRUE(StartEmbeddedTestServer());
286 ASSERT_TRUE(RunExtensionTest("content_scripts/bypass_page_csp")) << message_;
287 }
288
289 } // namespace extensions
290