blob: beabffd579efd2c8f4487e39f99e2e2f3548681e [file] [log] [blame]
[email protected]2c6e3b04c2014-07-24 12:48:091// Copyright 2014 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
[email protected]2c6e3b04c2014-07-24 12:48:095#include "base/files/file_path.h"
thestig18dfb7a52014-08-26 10:44:046#include "base/files/file_util.h"
[email protected]2c6e3b04c2014-07-24 12:48:097#include "base/path_service.h"
8#include "base/values.h"
avia2f4804a2015-12-24 23:11:139#include "build/build_config.h"
[email protected]2c6e3b04c2014-07-24 12:48:0910#include "chrome/browser/extensions/extension_apitest.h"
[email protected]2c6e3b04c2014-07-24 12:48:0911#include "chrome/browser/ui/browser.h"
12#include "chrome/browser/ui/tabs/tab_strip_model.h"
13#include "chrome/common/chrome_paths.h"
14#include "chrome/test/base/ui_test_utils.h"
15#include "content/public/browser/render_frame_host.h"
16#include "content/public/browser/web_contents.h"
17#include "content/public/test/browser_test_utils.h"
18#include "extensions/browser/event_router.h"
19#include "extensions/common/api/test.h"
20#include "extensions/common/extension.h"
lfg910f2f92014-09-19 05:31:0921#include "extensions/test/extension_test_message_listener.h"
[email protected]2c6e3b04c2014-07-24 12:48:0922#include "testing/gtest/include/gtest/gtest.h"
23
24namespace extensions {
25
kalmane58e62232015-07-23 18:27:2226namespace OnMessage = api::test::OnMessage;
[email protected]2c6e3b04c2014-07-24 12:48:0927
28namespace {
29
[email protected]2c6e3b04c2014-07-24 12:48:0930// Tests running extension APIs on WebUI.
31class ExtensionWebUITest : public ExtensionApiTest {
32 protected:
[email protected]c1abb3232014-07-30 18:28:3933 testing::AssertionResult RunTest(const char* name,
34 const GURL& page_url,
35 const GURL& frame_url,
36 bool expected_result) {
[email protected]2c6e3b04c2014-07-24 12:48:0937 // Tests are located in chrome/test/data/extensions/webui/$(name).
38 base::FilePath path;
39 PathService::Get(chrome::DIR_TEST_DATA, &path);
40 path =
41 path.AppendASCII("extensions").AppendASCII("webui").AppendASCII(name);
42
43 // Read the test.
44 if (!base::PathExists(path))
45 return testing::AssertionFailure() << "Couldn't find " << path.value();
46 std::string script;
47 base::ReadFileToString(path, &script);
48 script = "(function(){'use strict';" + script + "}());";
49
50 // Run the test.
[email protected]c1abb3232014-07-30 18:28:3951 bool actual_result = false;
52 content::RenderFrameHost* webui = NavigateToWebUI(page_url, frame_url);
[email protected]2c6e3b04c2014-07-24 12:48:0953 if (!webui)
54 return testing::AssertionFailure() << "Failed to navigate to WebUI";
[email protected]c1abb3232014-07-30 18:28:3955 CHECK(content::ExecuteScriptAndExtractBool(webui, script, &actual_result));
56 return (expected_result == actual_result)
57 ? testing::AssertionSuccess()
58 : (testing::AssertionFailure() << "Check console output");
[email protected]2c6e3b04c2014-07-24 12:48:0959 }
60
[email protected]e99bd0ae2014-08-19 00:49:0061 testing::AssertionResult RunTestOnExtensionsFrame(const char* name) {
62 // In the current extension WebUI design, the content is actually hosted in
63 // an iframe at chrome://extensions-frame.
[email protected]c1abb3232014-07-30 18:28:3964 return RunTest(name,
65 GURL("chrome://extensions"),
66 GURL("chrome://extensions-frame"),
[email protected]e99bd0ae2014-08-19 00:49:0067 true); // tests on chrome://extensions-frame should succeed
68 }
69
70 testing::AssertionResult RunTestOnChromeExtensionsFrame(const char* name) {
71 // Like RunTestOnExtensionsFrame, but chrome://extensions is an alias for
72 // chrome://chrome/extensions so test it explicitly.
73 return RunTest(name,
74 GURL("chrome://chrome/extensions"),
75 GURL("chrome://extensions-frame"),
76 true); // tests on chrome://extensions-frame should succeed
77 }
78
79 testing::AssertionResult RunTestOnChromeExtensions(const char* name) {
80 // Despite the extensions page being hosted in an iframe, also test the
81 // top-level chrome://extensions page (which actually loads
82 // chrome://chrome/extensions). In the past there was a bug where top-level
83 // extension WebUI bindings weren't correctly set up.
84 return RunTest(name,
85 GURL("chrome://chrome/extensions"),
86 GURL("chrome://chrome/extensions"),
87 true); // tests on chrome://chrome/extensions should succeed
[email protected]c1abb3232014-07-30 18:28:3988 }
89
90 testing::AssertionResult RunTestOnAbout(const char* name) {
91 // chrome://about is an innocuous page that doesn't have any bindings.
92 // Tests should fail.
93 return RunTest(name,
94 GURL("chrome://about"),
95 GURL("chrome://about"),
96 false); // tests on chrome://about should fail
97 }
98
99 private:
100 // Navigates the browser to a WebUI page and returns the RenderFrameHost for
101 // that page.
102 content::RenderFrameHost* NavigateToWebUI(const GURL& page_url,
103 const GURL& frame_url) {
104 ui_test_utils::NavigateToURL(browser(), page_url);
105
106 content::WebContents* active_web_contents =
107 browser()->tab_strip_model()->GetActiveWebContents();
108
109 if (active_web_contents->GetLastCommittedURL() == frame_url)
110 return active_web_contents->GetMainFrame();
111
alexmosc515c08b2014-12-15 23:33:01112 return FrameMatchingPredicate(
113 active_web_contents,
114 base::Bind(&content::FrameHasSourceUrl, frame_url));
[email protected]2c6e3b04c2014-07-24 12:48:09115 }
116};
117
jam4cfacac2015-09-16 09:57:40118#if !defined(OS_WIN) // flaky http://crbug.com/530722
119
[email protected]e99bd0ae2014-08-19 00:49:00120IN_PROC_BROWSER_TEST_F(ExtensionWebUITest, SanityCheckAvailableAPIsInFrame) {
121 ASSERT_TRUE(RunTestOnExtensionsFrame("sanity_check_available_apis.js"));
122}
123
124IN_PROC_BROWSER_TEST_F(ExtensionWebUITest,
125 SanityCheckAvailableAPIsInChromeFrame) {
126 ASSERT_TRUE(RunTestOnChromeExtensionsFrame("sanity_check_available_apis.js"));
127}
128
129IN_PROC_BROWSER_TEST_F(ExtensionWebUITest, SanityCheckAvailableAPIsInToplevel) {
130 ASSERT_TRUE(RunTestOnChromeExtensions("sanity_check_available_apis.js"));
[email protected]c1abb3232014-07-30 18:28:39131}
132
133IN_PROC_BROWSER_TEST_F(ExtensionWebUITest, SanityCheckUnavailableAPIs) {
134 ASSERT_TRUE(RunTestOnAbout("sanity_check_available_apis.js"));
[email protected]2c6e3b04c2014-07-24 12:48:09135}
136
137// Tests chrome.test.sendMessage, which exercises WebUI making a
138// function call and receiving a response.
139IN_PROC_BROWSER_TEST_F(ExtensionWebUITest, SendMessage) {
140 scoped_ptr<ExtensionTestMessageListener> listener(
141 new ExtensionTestMessageListener("ping", true));
142
[email protected]e99bd0ae2014-08-19 00:49:00143 ASSERT_TRUE(RunTestOnExtensionsFrame("send_message.js"));
[email protected]2c6e3b04c2014-07-24 12:48:09144
145 ASSERT_TRUE(listener->WaitUntilSatisfied());
146 listener->Reply("pong");
147
148 listener.reset(new ExtensionTestMessageListener(false));
149 ASSERT_TRUE(listener->WaitUntilSatisfied());
150 EXPECT_EQ("true", listener->message());
151}
152
153// Tests chrome.runtime.onMessage, which exercises WebUI registering and
154// receiving an event.
155IN_PROC_BROWSER_TEST_F(ExtensionWebUITest, OnMessage) {
[email protected]e99bd0ae2014-08-19 00:49:00156 ASSERT_TRUE(RunTestOnExtensionsFrame("on_message.js"));
[email protected]2c6e3b04c2014-07-24 12:48:09157
158 OnMessage::Info info;
159 info.data = "hi";
160 info.last_message = true;
kalmanef20c652015-07-06 22:18:33161 EventRouter::Get(profile())->BroadcastEvent(make_scoped_ptr(
162 new Event(events::RUNTIME_ON_MESSAGE, OnMessage::kEventName,
163 OnMessage::Create(info))));
[email protected]2c6e3b04c2014-07-24 12:48:09164
165 scoped_ptr<ExtensionTestMessageListener> listener(
166 new ExtensionTestMessageListener(false));
167 ASSERT_TRUE(listener->WaitUntilSatisfied());
168 EXPECT_EQ("true", listener->message());
169}
170
171// Tests chrome.runtime.lastError, which exercises WebUI accessing a property
172// on an API which it doesn't actually have access to. A bindings test really.
173IN_PROC_BROWSER_TEST_F(ExtensionWebUITest, RuntimeLastError) {
174 scoped_ptr<ExtensionTestMessageListener> listener(
175 new ExtensionTestMessageListener("ping", true));
176
[email protected]e99bd0ae2014-08-19 00:49:00177 ASSERT_TRUE(RunTestOnExtensionsFrame("runtime_last_error.js"));
[email protected]2c6e3b04c2014-07-24 12:48:09178
179 ASSERT_TRUE(listener->WaitUntilSatisfied());
180 listener->ReplyWithError("unknown host");
181
182 listener.reset(new ExtensionTestMessageListener(false));
183 ASSERT_TRUE(listener->WaitUntilSatisfied());
184 EXPECT_EQ("true", listener->message());
185}
186
[email protected]70527de2014-08-13 09:38:31187IN_PROC_BROWSER_TEST_F(ExtensionWebUITest, CanEmbedExtensionOptions) {
188 scoped_ptr<ExtensionTestMessageListener> listener(
189 new ExtensionTestMessageListener("ready", true));
190
[email protected]a73aae72014-08-21 23:28:04191 const Extension* extension =
192 LoadExtension(test_data_dir_.AppendASCII("extension_options")
193 .AppendASCII("embed_self"));
[email protected]70527de2014-08-13 09:38:31194 ASSERT_TRUE(extension);
195
[email protected]e99bd0ae2014-08-19 00:49:00196 ASSERT_TRUE(RunTestOnExtensionsFrame("can_embed_extension_options.js"));
[email protected]70527de2014-08-13 09:38:31197
198 ASSERT_TRUE(listener->WaitUntilSatisfied());
199 listener->Reply(extension->id());
kalman94b43482014-10-17 00:04:33200 listener.reset(new ExtensionTestMessageListener("load", false));
[email protected]70527de2014-08-13 09:38:31201 ASSERT_TRUE(listener->WaitUntilSatisfied());
202}
203
[email protected]3ae15dd62014-08-22 23:32:18204IN_PROC_BROWSER_TEST_F(ExtensionWebUITest, ReceivesExtensionOptionsOnClose) {
205 scoped_ptr<ExtensionTestMessageListener> listener(
206 new ExtensionTestMessageListener("ready", true));
207
208 const Extension* extension =
209 InstallExtension(test_data_dir_.AppendASCII("extension_options")
210 .AppendASCII("close_self"), 1);
211 ASSERT_TRUE(extension);
212
213 ASSERT_TRUE(
214 RunTestOnExtensionsFrame("receives_extension_options_on_close.js"));
215
216 ASSERT_TRUE(listener->WaitUntilSatisfied());
217 listener->Reply(extension->id());
218 listener.reset(new ExtensionTestMessageListener("onclose received", false));
219 ASSERT_TRUE(listener->WaitUntilSatisfied());
220}
221
kalman94b43482014-10-17 00:04:33222// Regression test for crbug.com/414526.
223//
224// Same setup as CanEmbedExtensionOptions but disable the extension before
225// embedding.
226IN_PROC_BROWSER_TEST_F(ExtensionWebUITest, EmbedDisabledExtension) {
227 scoped_ptr<ExtensionTestMessageListener> listener(
228 new ExtensionTestMessageListener("ready", true));
229
230 std::string extension_id;
231 {
232 const Extension* extension =
233 LoadExtension(test_data_dir_.AppendASCII("extension_options")
234 .AppendASCII("embed_self"));
235 ASSERT_TRUE(extension);
236 extension_id = extension->id();
237 DisableExtension(extension_id);
238 }
239
240 ASSERT_TRUE(RunTestOnExtensionsFrame("can_embed_extension_options.js"));
241
242 ASSERT_TRUE(listener->WaitUntilSatisfied());
243 listener->Reply(extension_id);
244 listener.reset(new ExtensionTestMessageListener("createfailed", false));
245 ASSERT_TRUE(listener->WaitUntilSatisfied());
246}
247
jam4cfacac2015-09-16 09:57:40248#endif
249
[email protected]2c6e3b04c2014-07-24 12:48:09250} // namespace
251
252} // namespace extensions