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 23namespace extensions { 24 25namespace { 26 27// A fake webstore domain. 28const 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. 33testing::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 77IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptAllFrames) { 78 ASSERT_TRUE(StartEmbeddedTestServer()); 79 ASSERT_TRUE(RunExtensionTest("content_scripts/all_frames")) << message_; 80} 81 82IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptAboutBlankIframes) { 83 ASSERT_TRUE(StartEmbeddedTestServer()); 84 ASSERT_TRUE( 85 RunExtensionTest("content_scripts/about_blank_iframes")) << message_; 86} 87 88IN_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 100IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptExtensionIframe) { 101 ASSERT_TRUE(StartEmbeddedTestServer()); 102 ASSERT_TRUE(RunExtensionTest("content_scripts/extension_iframe")) << message_; 103} 104 105IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptExtensionProcess) { 106 ASSERT_TRUE(StartEmbeddedTestServer()); 107 ASSERT_TRUE( 108 RunExtensionTest("content_scripts/extension_process")) << message_; 109} 110 111IN_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 123IN_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 134IN_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. 143IN_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. 150IN_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 161class 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. 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 179IN_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 207IN_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 236IN_PROC_BROWSER_TEST_F(ExtensionApiTest, 237 ContentScriptCSSLocalization) { 238 ASSERT_TRUE(StartEmbeddedTestServer()); 239 ASSERT_TRUE(RunExtensionTest("content_scripts/css_l10n")) << message_; 240} 241 242IN_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 276IN_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 284IN_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