[email protected] | b62084b | 2012-06-12 01:53:30 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 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/command_line.h" |
[email protected] | 5799981 | 2013-02-24 05:40:52 | [diff] [blame] | 6 | #include "base/files/file_path.h" |
[email protected] | f74c62c | 2011-10-19 23:34:16 | [diff] [blame] | 7 | #include "base/path_service.h" |
[email protected] | 112158af | 2013-06-07 23:46:18 | [diff] [blame] | 8 | #include "base/strings/utf_string_conversions.h" |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 9 | #include "chrome/browser/extensions/crx_installer.h" |
| 10 | #include "chrome/browser/extensions/extension_browsertest.h" |
| 11 | #include "chrome/browser/extensions/extension_service.h" |
lukasza | b3a950f | 2017-06-19 21:08:23 | [diff] [blame] | 12 | #include "chrome/browser/extensions/test_extension_dir.h" |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 13 | #include "chrome/browser/profiles/profile.h" |
| 14 | #include "chrome/browser/ui/browser.h" |
[email protected] | 47ae2337 | 2013-01-29 01:50:48 | [diff] [blame] | 15 | #include "chrome/browser/ui/tabs/tab_strip_model.h" |
[email protected] | f74c62c | 2011-10-19 23:34:16 | [diff] [blame] | 16 | #include "chrome/common/chrome_paths.h" |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 17 | #include "chrome/common/chrome_switches.h" |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 18 | #include "chrome/test/base/ui_test_utils.h" |
brettw | b1fc1b8 | 2016-02-02 00:19:08 | [diff] [blame] | 19 | #include "components/prefs/pref_service.h" |
[email protected] | e67385f | 2011-12-21 06:00:56 | [diff] [blame] | 20 | #include "content/public/browser/plugin_service.h" |
lukasza | b3a950f | 2017-06-19 21:08:23 | [diff] [blame] | 21 | #include "content/public/browser/render_frame_host.h" |
[email protected] | 4ca1530 | 2012-01-03 05:53:20 | [diff] [blame] | 22 | #include "content/public/browser/web_contents.h" |
[email protected] | d7bd3e5 | 2013-07-21 04:29:20 | [diff] [blame] | 23 | #include "content/public/common/webplugininfo.h" |
[email protected] | 7d478cb | 2012-07-24 17:19:42 | [diff] [blame] | 24 | #include "content/public/test/browser_test_utils.h" |
[email protected] | 59b0e60 | 2014-01-30 00:41:24 | [diff] [blame] | 25 | #include "extensions/browser/extension_system.h" |
[email protected] | f2cb3cf | 2013-03-21 01:40:53 | [diff] [blame] | 26 | #include "net/dns/mock_host_resolver.h" |
svaldez | a01f7d9 | 2015-11-18 17:47:56 | [diff] [blame] | 27 | #include "net/test/embedded_test_server/embedded_test_server.h" |
[email protected] | e67385f | 2011-12-21 06:00:56 | [diff] [blame] | 28 | |
| 29 | using content::PluginService; |
[email protected] | 4ca1530 | 2012-01-03 05:53:20 | [diff] [blame] | 30 | using content::WebContents; |
[email protected] | 1c321ee5 | 2012-05-21 03:02:34 | [diff] [blame] | 31 | using extensions::Extension; |
[email protected] | 1d5e58b | 2013-01-31 08:41:40 | [diff] [blame] | 32 | using extensions::Manifest; |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 33 | |
| 34 | namespace { |
| 35 | |
thestig | 4b36dd3 | 2014-10-31 20:30:19 | [diff] [blame] | 36 | const char kExtensionId[] = "bjjcibdiodkkeanflmiijlcfieiemced"; |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 37 | |
| 38 | // This class tests that the Native Client plugin is blocked unless the |
| 39 | // .nexe is part of an extension from the Chrome Webstore. |
| 40 | class NaClExtensionTest : public ExtensionBrowserTest { |
| 41 | public: |
[email protected] | 90ca4427 | 2012-07-18 18:15:48 | [diff] [blame] | 42 | NaClExtensionTest() {} |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 43 | |
jam | bb11ed74 | 2017-05-01 17:27:59 | [diff] [blame] | 44 | void SetUpOnMainThread() override { |
| 45 | ExtensionBrowserTest::SetUpOnMainThread(); |
| 46 | host_resolver()->AddRule("*", "127.0.0.1"); |
| 47 | ASSERT_TRUE(embedded_test_server()->Start()); |
| 48 | } |
| 49 | |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 50 | protected: |
| 51 | enum InstallType { |
| 52 | INSTALL_TYPE_COMPONENT, |
[email protected] | a9d1a103 | 2011-08-18 00:34:57 | [diff] [blame] | 53 | INSTALL_TYPE_UNPACKED, |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 54 | INSTALL_TYPE_FROM_WEBSTORE, |
| 55 | INSTALL_TYPE_NON_WEBSTORE, |
| 56 | }; |
[email protected] | 24a6ccb | 2013-05-04 00:19:00 | [diff] [blame] | 57 | enum PluginType { |
| 58 | PLUGIN_TYPE_NONE = 0, |
| 59 | PLUGIN_TYPE_EMBED = 1, |
| 60 | PLUGIN_TYPE_CONTENT_HANDLER = 2, |
| 61 | PLUGIN_TYPE_ALL = PLUGIN_TYPE_EMBED | |
| 62 | PLUGIN_TYPE_CONTENT_HANDLER, |
| 63 | }; |
| 64 | |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 65 | |
[email protected] | 3aacd948 | 2013-03-19 09:49:36 | [diff] [blame] | 66 | const Extension* InstallExtension(const base::FilePath& file_path, |
| 67 | InstallType install_type) { |
[email protected] | 06bdd2b | 2012-11-30 18:47:13 | [diff] [blame] | 68 | ExtensionService* service = extensions::ExtensionSystem::Get( |
| 69 | browser()->profile())->extension_service(); |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 70 | const Extension* extension = NULL; |
| 71 | switch (install_type) { |
| 72 | case INSTALL_TYPE_COMPONENT: |
| 73 | if (LoadExtensionAsComponent(file_path)) { |
| 74 | extension = service->GetExtensionById(kExtensionId, false); |
| 75 | } |
| 76 | break; |
| 77 | |
[email protected] | a9d1a103 | 2011-08-18 00:34:57 | [diff] [blame] | 78 | case INSTALL_TYPE_UNPACKED: |
| 79 | // Install the extension from a folder so it's unpacked. |
| 80 | if (LoadExtension(file_path)) { |
| 81 | extension = service->GetExtensionById(kExtensionId, false); |
| 82 | } |
| 83 | break; |
| 84 | |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 85 | case INSTALL_TYPE_FROM_WEBSTORE: |
[email protected] | a9d1a103 | 2011-08-18 00:34:57 | [diff] [blame] | 86 | // Install native_client.crx from the webstore. |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 87 | if (InstallExtensionFromWebstore(file_path, 1)) { |
[email protected] | 918c271 | 2013-10-21 23:59:56 | [diff] [blame] | 88 | extension = service->GetExtensionById(last_loaded_extension_id(), |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 89 | false); |
| 90 | } |
| 91 | break; |
| 92 | |
| 93 | case INSTALL_TYPE_NON_WEBSTORE: |
[email protected] | a9d1a103 | 2011-08-18 00:34:57 | [diff] [blame] | 94 | // Install native_client.crx but not from the webstore. |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 95 | if (ExtensionBrowserTest::InstallExtension(file_path, 1)) { |
[email protected] | 918c271 | 2013-10-21 23:59:56 | [diff] [blame] | 96 | extension = service->GetExtensionById(last_loaded_extension_id(), |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 97 | false); |
| 98 | } |
| 99 | break; |
| 100 | } |
| 101 | return extension; |
| 102 | } |
| 103 | |
[email protected] | 3aacd948 | 2013-03-19 09:49:36 | [diff] [blame] | 104 | const Extension* InstallExtension(InstallType install_type) { |
| 105 | base::FilePath file_path = test_data_dir_.AppendASCII("native_client"); |
| 106 | return InstallExtension(file_path, install_type); |
| 107 | } |
| 108 | |
| 109 | const Extension* InstallHostedApp() { |
| 110 | base::FilePath file_path = test_data_dir_.AppendASCII( |
| 111 | "native_client_hosted_app"); |
| 112 | return InstallExtension(file_path, INSTALL_TYPE_FROM_WEBSTORE); |
| 113 | } |
| 114 | |
[email protected] | f74c62c | 2011-10-19 23:34:16 | [diff] [blame] | 115 | bool IsNaClPluginLoaded() { |
[email protected] | 650b2d5 | 2013-02-10 03:41:45 | [diff] [blame] | 116 | base::FilePath path; |
[email protected] | f74c62c | 2011-10-19 23:34:16 | [diff] [blame] | 117 | if (PathService::Get(chrome::FILE_NACL_PLUGIN, &path)) { |
[email protected] | d7bd3e5 | 2013-07-21 04:29:20 | [diff] [blame] | 118 | content::WebPluginInfo info; |
[email protected] | f74c62c | 2011-10-19 23:34:16 | [diff] [blame] | 119 | return PluginService::GetInstance()->GetPluginInfoByPath(path, &info); |
| 120 | } |
| 121 | return false; |
| 122 | } |
| 123 | |
[email protected] | 24a6ccb | 2013-05-04 00:19:00 | [diff] [blame] | 124 | void CheckPluginsCreated(const GURL& url, PluginType expected_to_succeed) { |
[email protected] | e3cb452 | 2013-03-07 22:18:45 | [diff] [blame] | 125 | ui_test_utils::NavigateToURL(browser(), url); |
[email protected] | f74c62c | 2011-10-19 23:34:16 | [diff] [blame] | 126 | // Don't run tests if the NaCl plugin isn't loaded. |
| 127 | if (!IsNaClPluginLoaded()) |
| 128 | return; |
| 129 | |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 130 | bool embedded_plugin_created = false; |
| 131 | bool content_handler_plugin_created = false; |
[email protected] | 47ae2337 | 2013-01-29 01:50:48 | [diff] [blame] | 132 | WebContents* web_contents = |
| 133 | browser()->tab_strip_model()->GetActiveWebContents(); |
[email protected] | b6987e0 | 2013-01-04 18:30:43 | [diff] [blame] | 134 | ASSERT_TRUE(content::ExecuteScriptAndExtractBool( |
| 135 | web_contents, |
[email protected] | 06bc5d9 | 2013-01-02 22:44:13 | [diff] [blame] | 136 | "window.domAutomationController.send(EmbeddedPluginCreated());", |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 137 | &embedded_plugin_created)); |
[email protected] | b6987e0 | 2013-01-04 18:30:43 | [diff] [blame] | 138 | ASSERT_TRUE(content::ExecuteScriptAndExtractBool( |
| 139 | web_contents, |
[email protected] | 06bc5d9 | 2013-01-02 22:44:13 | [diff] [blame] | 140 | "window.domAutomationController.send(ContentHandlerPluginCreated());", |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 141 | &content_handler_plugin_created)); |
| 142 | |
[email protected] | 24a6ccb | 2013-05-04 00:19:00 | [diff] [blame] | 143 | EXPECT_EQ(embedded_plugin_created, |
| 144 | (expected_to_succeed & PLUGIN_TYPE_EMBED) != 0); |
| 145 | EXPECT_EQ(content_handler_plugin_created, |
| 146 | (expected_to_succeed & PLUGIN_TYPE_CONTENT_HANDLER) != 0); |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 147 | } |
[email protected] | e3cb452 | 2013-03-07 22:18:45 | [diff] [blame] | 148 | |
[email protected] | 24a6ccb | 2013-05-04 00:19:00 | [diff] [blame] | 149 | void CheckPluginsCreated(const Extension* extension, |
| 150 | PluginType expected_to_succeed) { |
| 151 | CheckPluginsCreated(extension->GetResourceURL("test.html"), |
| 152 | expected_to_succeed); |
[email protected] | e3cb452 | 2013-03-07 22:18:45 | [diff] [blame] | 153 | } |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 154 | }; |
| 155 | |
| 156 | // Test that the NaCl plugin isn't blocked for Webstore extensions. |
[email protected] | 7070a87 | 2013-11-21 21:23:42 | [diff] [blame] | 157 | // Disabled: http://crbug.com/319892 |
| 158 | IN_PROC_BROWSER_TEST_F(NaClExtensionTest, DISABLED_WebStoreExtension) { |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 159 | const Extension* extension = InstallExtension(INSTALL_TYPE_FROM_WEBSTORE); |
| 160 | ASSERT_TRUE(extension); |
[email protected] | 24a6ccb | 2013-05-04 00:19:00 | [diff] [blame] | 161 | CheckPluginsCreated(extension, PLUGIN_TYPE_ALL); |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 162 | } |
| 163 | |
| 164 | // Test that the NaCl plugin is blocked for non-Webstore extensions. |
[email protected] | 7070a87 | 2013-11-21 21:23:42 | [diff] [blame] | 165 | // Disabled: http://crbug.com/319892 |
| 166 | IN_PROC_BROWSER_TEST_F(NaClExtensionTest, DISABLED_NonWebStoreExtension) { |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 167 | const Extension* extension = InstallExtension(INSTALL_TYPE_NON_WEBSTORE); |
| 168 | ASSERT_TRUE(extension); |
[email protected] | 24a6ccb | 2013-05-04 00:19:00 | [diff] [blame] | 169 | CheckPluginsCreated(extension, PLUGIN_TYPE_NONE); |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 170 | } |
| 171 | |
| 172 | // Test that the NaCl plugin isn't blocked for component extensions. |
[email protected] | 7070a87 | 2013-11-21 21:23:42 | [diff] [blame] | 173 | // Disabled: http://crbug.com/319892 |
| 174 | IN_PROC_BROWSER_TEST_F(NaClExtensionTest, DISABLED_ComponentExtension) { |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 175 | const Extension* extension = InstallExtension(INSTALL_TYPE_COMPONENT); |
| 176 | ASSERT_TRUE(extension); |
[email protected] | 1d5e58b | 2013-01-31 08:41:40 | [diff] [blame] | 177 | ASSERT_EQ(extension->location(), Manifest::COMPONENT); |
[email protected] | 24a6ccb | 2013-05-04 00:19:00 | [diff] [blame] | 178 | CheckPluginsCreated(extension, PLUGIN_TYPE_ALL); |
[email protected] | a9d1a103 | 2011-08-18 00:34:57 | [diff] [blame] | 179 | } |
| 180 | |
| 181 | // Test that the NaCl plugin isn't blocked for unpacked extensions. |
[email protected] | 7070a87 | 2013-11-21 21:23:42 | [diff] [blame] | 182 | // Disabled: http://crbug.com/319892 |
| 183 | IN_PROC_BROWSER_TEST_F(NaClExtensionTest, DISABLED_UnpackedExtension) { |
[email protected] | a9d1a103 | 2011-08-18 00:34:57 | [diff] [blame] | 184 | const Extension* extension = InstallExtension(INSTALL_TYPE_UNPACKED); |
| 185 | ASSERT_TRUE(extension); |
[email protected] | 12075d1 | 2013-02-27 05:38:05 | [diff] [blame] | 186 | ASSERT_EQ(extension->location(), Manifest::UNPACKED); |
[email protected] | 24a6ccb | 2013-05-04 00:19:00 | [diff] [blame] | 187 | CheckPluginsCreated(extension, PLUGIN_TYPE_ALL); |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 188 | } |
| 189 | |
[email protected] | 24a6ccb | 2013-05-04 00:19:00 | [diff] [blame] | 190 | // Test that the NaCl plugin is blocked for non chrome-extension urls, except |
| 191 | // if it's a content (MIME type) handler. |
[email protected] | 7070a87 | 2013-11-21 21:23:42 | [diff] [blame] | 192 | // Disabled: http://crbug.com/319892 |
| 193 | IN_PROC_BROWSER_TEST_F(NaClExtensionTest, DISABLED_NonExtensionScheme) { |
[email protected] | e3cb452 | 2013-03-07 22:18:45 | [diff] [blame] | 194 | const Extension* extension = InstallExtension(INSTALL_TYPE_FROM_WEBSTORE); |
| 195 | ASSERT_TRUE(extension); |
| 196 | CheckPluginsCreated( |
svaldez | a01f7d9 | 2015-11-18 17:47:56 | [diff] [blame] | 197 | embedded_test_server()->GetURL("/extensions/native_client/test.html"), |
[email protected] | 24a6ccb | 2013-05-04 00:19:00 | [diff] [blame] | 198 | PLUGIN_TYPE_CONTENT_HANDLER); |
[email protected] | e3cb452 | 2013-03-07 22:18:45 | [diff] [blame] | 199 | } |
| 200 | |
[email protected] | 3aacd948 | 2013-03-19 09:49:36 | [diff] [blame] | 201 | // Test that NaCl plugin isn't blocked for hosted app URLs. |
| 202 | IN_PROC_BROWSER_TEST_F(NaClExtensionTest, HostedApp) { |
svaldez | a01f7d9 | 2015-11-18 17:47:56 | [diff] [blame] | 203 | GURL url = |
| 204 | embedded_test_server()->GetURL("/extensions/native_client/test.html"); |
[email protected] | 3aacd948 | 2013-03-19 09:49:36 | [diff] [blame] | 205 | GURL::Replacements replace_host; |
mgiuca | 77752c3 | 2015-02-05 07:31:18 | [diff] [blame] | 206 | replace_host.SetHostStr("localhost"); |
[email protected] | 3aacd948 | 2013-03-19 09:49:36 | [diff] [blame] | 207 | replace_host.ClearPort(); |
| 208 | url = url.ReplaceComponents(replace_host); |
| 209 | |
| 210 | const Extension* extension = InstallHostedApp(); |
| 211 | ASSERT_TRUE(extension); |
[email protected] | 24a6ccb | 2013-05-04 00:19:00 | [diff] [blame] | 212 | CheckPluginsCreated(url, PLUGIN_TYPE_ALL); |
[email protected] | 3aacd948 | 2013-03-19 09:49:36 | [diff] [blame] | 213 | } |
| 214 | |
lukasza | b3a950f | 2017-06-19 21:08:23 | [diff] [blame] | 215 | // Verify that there is no renderer crash when PNaCl plugin is loaded in a |
| 216 | // subframe with a remote parent / main frame. This is a regression test |
| 217 | // for https://crbug.com/728295. |
| 218 | IN_PROC_BROWSER_TEST_F(NaClExtensionTest, MainFrameIsRemote) { |
| 219 | // The test tries to load a PNaCl plugin into an *extension* frame to avoid |
| 220 | // running into the following error: "Only unpacked extensions and apps |
| 221 | // installed from the Chrome Web Store can load NaCl modules without enabling |
| 222 | // Native Client in about:flags." |
| 223 | extensions::TestExtensionDir ext_dir; |
| 224 | ext_dir.WriteFile(FILE_PATH_LITERAL("subframe.html"), |
| 225 | "<html><body>Extension frame</body></html>"); |
| 226 | ext_dir.WriteManifest( |
| 227 | R"( |
| 228 | { |
| 229 | "name": "ChromeSitePerProcessTest.MainFrameIsRemote", |
| 230 | "version": "0.1", |
| 231 | "manifest_version": 2, |
| 232 | "web_accessible_resources": [ "subframe.html" ] |
| 233 | } |
| 234 | )"); |
| 235 | const extensions::Extension* extension = |
| 236 | LoadExtension(ext_dir.UnpackedPath()); |
| 237 | |
| 238 | // Navigate to a page with an iframe. |
| 239 | GURL main_url(embedded_test_server()->GetURL("a.com", "/iframe.html")); |
| 240 | ui_test_utils::NavigateToURL(browser(), main_url); |
| 241 | |
| 242 | // Navigate the subframe to the extension's html file. |
| 243 | content::WebContents* web_contents = |
| 244 | browser()->tab_strip_model()->GetActiveWebContents(); |
| 245 | ASSERT_TRUE(content::NavigateIframeToURL( |
| 246 | web_contents, "test", extension->GetResourceURL("subframe.html"))); |
| 247 | |
| 248 | // Sanity check - the test setup should cause main frame and subframe to be in |
| 249 | // a different process. |
| 250 | content::RenderFrameHost* subframe = web_contents->GetAllFrames()[1]; |
| 251 | EXPECT_NE(web_contents->GetMainFrame()->GetProcess(), subframe->GetProcess()); |
| 252 | |
| 253 | // Insert a plugin element into the subframe. Before the fix from |
| 254 | // https://crrev.com/2932703005 this would have trigerred a crash reported in |
| 255 | // https://crbug.com/728295. |
| 256 | std::string script = R"( |
| 257 | var embed = document.createElement("embed"); |
| 258 | embed.id = "test_nexe"; |
| 259 | embed.name = "nacl_module"; |
| 260 | embed.type = "application/x-pnacl"; |
| 261 | embed.src = "doesnt-exist.nmf"; |
| 262 | embed.addEventListener('error', function() { |
| 263 | window.domAutomationController.send(true); |
| 264 | }); |
| 265 | document.body.appendChild(embed); )"; |
| 266 | bool done; |
| 267 | EXPECT_TRUE(ExecuteScriptAndExtractBool(subframe, script, &done)); |
| 268 | |
| 269 | // If we get here, then it means that the renderer didn't crash (the crash |
| 270 | // would have prevented the "error" event from firing and so |
| 271 | // ExecuteScriptAndExtractBool above wouldn't return). |
| 272 | } |
| 273 | |
[email protected] | cefa749d | 2011-08-11 22:21:48 | [diff] [blame] | 274 | } // namespace |