blob: 92d12e7e65334e9e889be5b02d771ea71c68be74 [file] [log] [blame]
[email protected]fad73672012-06-15 23:26:061// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]c80b8ee2011-12-03 04:26:522// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Contains holistic tests of the bindings infrastructure
6
Gabriel Charette078e3662017-08-28 22:59:047#include "base/run_loop.h"
[email protected]7eef3942013-08-14 02:53:498#include "chrome/browser/extensions/api/permissions/permissions_api.h"
[email protected]c80b8ee2011-12-03 04:26:529#include "chrome/browser/extensions/extension_apitest.h"
jochen7923c2a2015-07-14 10:04:4510#include "chrome/browser/net/url_request_mock_util.h"
[email protected]fad73672012-06-15 23:26:0611#include "chrome/browser/ui/browser.h"
rdevlin.cronin83a4b3a2015-10-28 21:43:5812#include "chrome/browser/ui/tabs/tab_strip_model.h"
asargent79b64c32016-08-04 17:17:1413#include "chrome/common/chrome_switches.h"
rdevlin.cronin83a4b3a2015-10-28 21:43:5814#include "chrome/test/base/ui_test_utils.h"
jochen7923c2a2015-07-14 10:04:4515#include "content/public/browser/browser_thread.h"
[email protected]7d478cb2012-07-24 17:19:4216#include "content/public/test/browser_test_utils.h"
[email protected]22401dc2014-03-21 01:38:5717#include "extensions/browser/extension_host.h"
[email protected]98b6d942013-11-10 00:34:0718#include "extensions/browser/process_manager.h"
Devlin Croninc3a1e5072017-08-17 17:02:4919#include "extensions/common/switches.h"
lfg910f2f92014-09-19 05:31:0920#include "extensions/test/extension_test_message_listener.h"
yoze8dc2f12014-09-09 23:16:3221#include "extensions/test/result_catcher.h"
rdevlin.cronine6e20022017-06-13 18:23:4022#include "net/dns/mock_host_resolver.h"
rdevlin.cronin83a4b3a2015-10-28 21:43:5823#include "net/test/embedded_test_server/embedded_test_server.h"
[email protected]fad73672012-06-15 23:26:0624
[email protected]adafe5b2013-08-09 10:35:0425namespace extensions {
26namespace {
27
Devlin Croninc3a1e5072017-08-17 17:02:4928enum BindingsType { NATIVE_BINDINGS, JAVASCRIPT_BINDINGS };
29
30class ExtensionBindingsApiTest
31 : public ExtensionApiTest,
32 public ::testing::WithParamInterface<BindingsType> {
jochen7923c2a2015-07-14 10:04:4533 public:
Devlin Croninc3a1e5072017-08-17 17:02:4934 void SetUpCommandLine(base::CommandLine* command_line) override {
35 ExtensionApiTest::SetUpCommandLine(command_line);
36 command_line->AppendSwitchASCII(switches::kNativeCrxBindings,
37 GetParam() == NATIVE_BINDINGS ? "1" : "0");
38 }
39
jochen7923c2a2015-07-14 10:04:4540 void SetUpOnMainThread() override {
rdevlin.cronin17160cc62016-11-23 05:33:0841 ExtensionApiTest::SetUpOnMainThread();
rdevlin.cronine6e20022017-06-13 18:23:4042 host_resolver()->AddRule("*", "127.0.0.1");
43 ASSERT_TRUE(StartEmbeddedTestServer());
jochen7923c2a2015-07-14 10:04:4544 }
45};
[email protected]adafe5b2013-08-09 10:35:0446
Devlin Croninc3a1e5072017-08-17 17:02:4947IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest,
[email protected]7eef3942013-08-14 02:53:4948 UnavailableBindingsNeverRegistered) {
49 // Test will request the 'storage' permission.
50 PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
51 ASSERT_TRUE(RunExtensionTest(
52 "bindings/unavailable_bindings_never_registered")) << message_;
53}
54
Devlin Croninc3a1e5072017-08-17 17:02:4955IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest,
[email protected]adafe5b2013-08-09 10:35:0456 ExceptionInHandlerShouldNotCrash) {
[email protected]c80b8ee2011-12-03 04:26:5257 ASSERT_TRUE(RunExtensionSubtest(
58 "bindings/exception_in_handler_should_not_crash",
59 "page.html")) << message_;
60}
[email protected]fad73672012-06-15 23:26:0661
62// Tests that an error raised during an async function still fires
[email protected]754ea8b72013-01-08 15:10:3163// the callback, but sets chrome.runtime.lastError.
Devlin Croninc3a1e5072017-08-17 17:02:4964IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest, LastError) {
[email protected]fad73672012-06-15 23:26:0665 ASSERT_TRUE(LoadExtension(
Devlin Croninc3a1e5072017-08-17 17:02:4966 test_data_dir_.AppendASCII("bindings").AppendASCII("last_error")));
[email protected]fad73672012-06-15 23:26:0667
68 // Get the ExtensionHost that is hosting our background page.
[email protected]98b6d942013-11-10 00:34:0769 extensions::ProcessManager* manager =
reillyg0ea3fa902014-10-28 15:30:2370 extensions::ProcessManager::Get(browser()->profile());
[email protected]3a1dc572012-07-31 22:25:1371 extensions::ExtensionHost* host = FindHostWithPath(manager, "/bg.html", 1);
[email protected]fad73672012-06-15 23:26:0672
73 bool result = false;
[email protected]b6987e02013-01-04 18:30:4374 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
75 host->render_view_host(), "testLastError()", &result));
[email protected]fad73672012-06-15 23:26:0676 EXPECT_TRUE(result);
77}
[email protected]52eafbd2013-04-03 04:43:1978
[email protected]adafe5b2013-08-09 10:35:0479// Regression test that we don't delete our own bindings with about:blank
80// iframes.
Devlin Croninc3a1e5072017-08-17 17:02:4981IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest, AboutBlankIframe) {
[email protected]adafe5b2013-08-09 10:35:0482 ResultCatcher catcher;
83 ExtensionTestMessageListener listener("load", true);
84
85 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("bindings")
86 .AppendASCII("about_blank_iframe")));
87
88 ASSERT_TRUE(listener.WaitUntilSatisfied());
89
90 const Extension* extension = LoadExtension(
91 test_data_dir_.AppendASCII("bindings")
92 .AppendASCII("internal_apis_not_on_chrome_object"));
93 ASSERT_TRUE(extension);
94 listener.Reply(extension->id());
95
96 ASSERT_TRUE(catcher.GetNextResult()) << message_;
97}
98
Devlin Croninc3a1e5072017-08-17 17:02:4999IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest,
[email protected]adafe5b2013-08-09 10:35:04100 InternalAPIsNotOnChromeObject) {
[email protected]52eafbd2013-04-03 04:43:19101 ASSERT_TRUE(RunExtensionSubtest(
102 "bindings/internal_apis_not_on_chrome_object",
103 "page.html")) << message_;
104}
[email protected]adafe5b2013-08-09 10:35:04105
[email protected]fc034482013-08-09 20:25:14106// Tests that we don't override events when bindings are re-injected.
107// Regression test for http://crbug.com/269149.
rpaquay96bf3b7d2014-11-26 00:19:08108// Regression test for http://crbug.com/436593.
Henrik Grunell6b7d9db2017-06-14 10:27:20109// Flaky on Mac. http://crbug.com/733064.
Giovanni Ortuño Urquidi7ce215452017-06-14 03:34:08110#if defined(OS_MACOSX)
111#define MAYBE_EventOverriding DISABLED_EventOverriding
112#else
113#define MAYBE_EventOverriding EventOverriding
114#endif
Devlin Croninc3a1e5072017-08-17 17:02:49115IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest, MAYBE_EventOverriding) {
[email protected]fc034482013-08-09 20:25:14116 ASSERT_TRUE(RunExtensionTest("bindings/event_overriding")) << message_;
rdevlin.cronind734f682017-06-13 21:23:11117 // The extension test removes a window and, during window removal, sends the
118 // success message. Make sure we flush all pending tasks.
119 base::RunLoop().RunUntilIdle();
[email protected]fc034482013-08-09 20:25:14120}
121
kalman1bd5b182015-01-13 19:01:18122// Tests the effectiveness of the 'nocompile' feature file property.
123// Regression test for http://crbug.com/356133.
Devlin Croninc3a1e5072017-08-17 17:02:49124IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest, Nocompile) {
kalman1bd5b182015-01-13 19:01:18125 ASSERT_TRUE(RunExtensionSubtest("bindings/nocompile", "page.html"))
126 << message_;
127}
128
Devlin Croninc3a1e5072017-08-17 17:02:49129IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest, ApiEnums) {
rdevlin.cronin2ba3c88d2015-03-03 01:18:22130 ASSERT_TRUE(RunExtensionTest("bindings/api_enums")) << message_;
131};
132
jochen7923c2a2015-07-14 10:04:45133// Regression test for http://crbug.com/504011 - proper access checks on
134// getModuleSystem().
Devlin Croninc3a1e5072017-08-17 17:02:49135IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest, ModuleSystem) {
jochen7923c2a2015-07-14 10:04:45136 ASSERT_TRUE(RunExtensionTest("bindings/module_system")) << message_;
137}
138
Devlin Croninc3a1e5072017-08-17 17:02:49139IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest, NoExportOverriding) {
rdevlin.cronin83a4b3a2015-10-28 21:43:58140 // We need to create runtime bindings in the web page. An extension that's
141 // externally connectable will do that for us.
142 ASSERT_TRUE(LoadExtension(
143 test_data_dir_.AppendASCII("bindings")
144 .AppendASCII("externally_connectable_everywhere")));
145
146 ui_test_utils::NavigateToURL(
147 browser(),
148 embedded_test_server()->GetURL(
149 "/extensions/api_test/bindings/override_exports.html"));
150
151 // See chrome/test/data/extensions/api_test/bindings/override_exports.html.
152 std::string result;
153 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
154 browser()->tab_strip_model()->GetActiveWebContents(),
155 "window.domAutomationController.send("
156 "document.getElementById('status').textContent.trim());",
157 &result));
158 EXPECT_EQ("success", result);
159}
160
Devlin Croninc3a1e5072017-08-17 17:02:49161IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest, NoGinDefineOverriding) {
rdevlin.cronin415b73b2015-11-13 01:14:47162 // We need to create runtime bindings in the web page. An extension that's
163 // externally connectable will do that for us.
164 ASSERT_TRUE(LoadExtension(
165 test_data_dir_.AppendASCII("bindings")
166 .AppendASCII("externally_connectable_everywhere")));
167
168 ui_test_utils::NavigateToURL(
169 browser(),
170 embedded_test_server()->GetURL(
171 "/extensions/api_test/bindings/override_gin_define.html"));
172 ASSERT_FALSE(
173 browser()->tab_strip_model()->GetActiveWebContents()->IsCrashed());
174
175 // See chrome/test/data/extensions/api_test/bindings/override_gin_define.html.
176 std::string result;
177 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
178 browser()->tab_strip_model()->GetActiveWebContents(),
179 "window.domAutomationController.send("
180 "document.getElementById('status').textContent.trim());",
181 &result));
182 EXPECT_EQ("success", result);
183}
184
Devlin Croninc3a1e5072017-08-17 17:02:49185IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest, HandlerFunctionTypeChecking) {
rdevlin.cronina5ecbc82015-10-29 23:41:29186 ui_test_utils::NavigateToURL(
187 browser(),
188 embedded_test_server()->GetURL(
189 "/extensions/api_test/bindings/handler_function_type_checking.html"));
190 content::WebContents* web_contents =
191 browser()->tab_strip_model()->GetActiveWebContents();
192 EXPECT_FALSE(web_contents->IsCrashed());
193 // See handler_function_type_checking.html.
194 std::string result;
195 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
196 web_contents,
197 "window.domAutomationController.send("
198 "document.getElementById('status').textContent.trim());",
199 &result));
200 EXPECT_EQ("success", result);
201}
202
Devlin Croninc3a1e5072017-08-17 17:02:49203IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest,
rdevlin.cronin75b803b2016-03-02 00:13:47204 MoreNativeFunctionInterceptionTests) {
rdevlin.cronin75b803b2016-03-02 00:13:47205 // We need to create runtime bindings in the web page. An extension that's
206 // externally connectable will do that for us.
207 ASSERT_TRUE(
208 LoadExtension(test_data_dir_.AppendASCII("bindings")
209 .AppendASCII("externally_connectable_everywhere")));
210
211 ui_test_utils::NavigateToURL(
212 browser(),
213 embedded_test_server()->GetURL(
214 "/extensions/api_test/bindings/function_interceptions.html"));
215 content::WebContents* web_contents =
216 browser()->tab_strip_model()->GetActiveWebContents();
217 EXPECT_FALSE(web_contents->IsCrashed());
218 // See function_interceptions.html.
219 std::string result;
220 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
221 web_contents, "window.domAutomationController.send(window.testStatus);",
222 &result));
223 EXPECT_EQ("success", result);
224}
225
asargent79b64c32016-08-04 17:17:14226class FramesExtensionBindingsApiTest : public ExtensionBindingsApiTest {
227 public:
228 void SetUpCommandLine(base::CommandLine* command_line) override {
229 ExtensionBindingsApiTest::SetUpCommandLine(command_line);
Devlin Croninc3a1e5072017-08-17 17:02:49230 command_line->AppendSwitch(::switches::kDisablePopupBlocking);
asargent79b64c32016-08-04 17:17:14231 }
232};
233
234// This tests that web pages with iframes or child windows pointing at
235// chrome-extenison:// urls, both web_accessible and nonexistent pages, don't
236// get improper extensions bindings injected while they briefly still point at
237// about:blank and are still scriptable by their parent.
238//
239// The general idea is to load up 2 extensions, one which listens for external
240// messages ("receiver") and one which we'll try first faking messages from in
241// the web page's iframe, as well as actually send a message from later
242// ("sender").
Dave Tapuska61ed7fbb2017-09-05 21:42:08243IN_PROC_BROWSER_TEST_P(FramesExtensionBindingsApiTest, FramesBeforeNavigation) {
asargent79b64c32016-08-04 17:17:14244 // Load the sender and receiver extensions, and make sure they are ready.
245 ExtensionTestMessageListener sender_ready("sender_ready", true);
246 const Extension* sender = LoadExtension(
247 test_data_dir_.AppendASCII("bindings").AppendASCII("message_sender"));
248 ASSERT_NE(nullptr, sender);
249 ASSERT_TRUE(sender_ready.WaitUntilSatisfied());
250
251 ExtensionTestMessageListener receiver_ready("receiver_ready", false);
252 const Extension* receiver =
253 LoadExtension(test_data_dir_.AppendASCII("bindings")
254 .AppendASCII("external_message_listener"));
255 ASSERT_NE(nullptr, receiver);
256 ASSERT_TRUE(receiver_ready.WaitUntilSatisfied());
257
258 // Load the web page which tries to impersonate the sender extension via
259 // scripting iframes/child windows before they finish navigating to pages
260 // within the sender extension.
asargent79b64c32016-08-04 17:17:14261 ui_test_utils::NavigateToURL(
262 browser(),
263 embedded_test_server()->GetURL(
264 "/extensions/api_test/bindings/frames_before_navigation.html"));
265
266 bool page_success = false;
267 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
268 browser()->tab_strip_model()->GetWebContentsAt(0), "getResult()",
269 &page_success));
270 EXPECT_TRUE(page_success);
271
272 // Reply to |sender|, causing it to send a message over to |receiver|, and
273 // then ask |receiver| for the total message count. It should be 1 since
274 // |receiver| should not have received any impersonated messages.
275 sender_ready.Reply(receiver->id());
276 int message_count = 0;
277 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
278 ProcessManager::Get(profile())
279 ->GetBackgroundHostForExtension(receiver->id())
280 ->host_contents(),
281 "getMessageCountAfterReceivingRealSenderMessage()", &message_count));
282 EXPECT_EQ(1, message_count);
283}
284
Devlin Croninc3a1e5072017-08-17 17:02:49285IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest, TestFreezingChrome) {
rdevlin.cronin741da002017-04-24 20:27:41286 ui_test_utils::NavigateToURL(
287 browser(), embedded_test_server()->GetURL(
288 "/extensions/api_test/bindings/freeze.html"));
289 content::WebContents* web_contents =
290 browser()->tab_strip_model()->GetActiveWebContents();
291 ASSERT_FALSE(web_contents->IsCrashed());
292}
293
rdevlin.cronine6e20022017-06-13 18:23:40294// Tests interaction with event filter parsing.
Devlin Croninc3a1e5072017-08-17 17:02:49295IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest, TestEventFilterParsing) {
rdevlin.cronine6e20022017-06-13 18:23:40296 ExtensionTestMessageListener listener("ready", false);
297 ASSERT_TRUE(
298 LoadExtension(test_data_dir_.AppendASCII("bindings/event_filter")));
299 ASSERT_TRUE(listener.WaitUntilSatisfied());
300
301 ResultCatcher catcher;
302 ui_test_utils::NavigateToURL(
303 browser(), embedded_test_server()->GetURL("example.com", "/title1.html"));
304 ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
305}
306
rdevlin.cronin350824d42017-06-16 14:47:35307// crbug.com/733337
Devlin Croninc3a1e5072017-08-17 17:02:49308IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest, ValidationInterception) {
rdevlin.cronin350824d42017-06-16 14:47:35309 // We need to create runtime bindings in the web page. An extension that's
310 // externally connectable will do that for us.
311 ASSERT_TRUE(
312 LoadExtension(test_data_dir_.AppendASCII("bindings")
313 .AppendASCII("externally_connectable_everywhere")));
314
315 content::WebContents* web_contents =
316 browser()->tab_strip_model()->GetActiveWebContents();
317 ui_test_utils::NavigateToURL(
318 browser(),
319 embedded_test_server()->GetURL(
320 "/extensions/api_test/bindings/validation_interception.html"));
321 content::WaitForLoadStop(web_contents);
322 ASSERT_FALSE(web_contents->IsCrashed());
323 bool caught = false;
324 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
325 web_contents, "domAutomationController.send(caught)", &caught));
326 EXPECT_TRUE(caught);
327}
328
Devlin Cronin5cf20f02017-10-10 14:25:04329IN_PROC_BROWSER_TEST_P(ExtensionBindingsApiTest, UncaughtExceptionLogging) {
330 ASSERT_TRUE(RunExtensionTest("bindings/uncaught_exception_logging"))
331 << message_;
332}
333
Devlin Croninc3a1e5072017-08-17 17:02:49334// Run core bindings API tests with both native and JS-based bindings. This
335// ensures we have some minimum level of coverage while in the experimental
336// phase, when native bindings may be enabled on trunk but not at 100% stable.
337INSTANTIATE_TEST_CASE_P(Native,
338 ExtensionBindingsApiTest,
339 ::testing::Values(NATIVE_BINDINGS));
340INSTANTIATE_TEST_CASE_P(JavaScript,
341 ExtensionBindingsApiTest,
342 ::testing::Values(JAVASCRIPT_BINDINGS));
343
344INSTANTIATE_TEST_CASE_P(Native,
345 FramesExtensionBindingsApiTest,
346 ::testing::Values(NATIVE_BINDINGS));
347INSTANTIATE_TEST_CASE_P(JavaScript,
348 FramesExtensionBindingsApiTest,
349 ::testing::Values(JAVASCRIPT_BINDINGS));
350
[email protected]adafe5b2013-08-09 10:35:04351} // namespace
352} // namespace extensions