blob: 86428bff01c13c4804e6c8d06ca6e466c9f9d4c0 [file] [log] [blame]
[email protected]f2fe87c2012-04-24 17:53:491// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]a964e112011-04-14 21:52:512// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <string>
6
7#include "base/command_line.h"
8#include "base/json/json_reader.h"
[email protected]0ef01962011-06-14 08:33:379#include "base/memory/scoped_ptr.h"
[email protected]3ea1b182013-02-08 22:38:4110#include "base/strings/string_number_conversions.h"
[email protected]a964e112011-04-14 21:52:5111#include "base/values.h"
12#include "chrome/browser/extensions/extension_browsertest.h"
[email protected]f2fe87c2012-04-24 17:53:4913#include "chrome/browser/extensions/extension_service.h"
14#include "chrome/browser/profiles/profile.h"
[email protected]a964e112011-04-14 21:52:5115#include "chrome/browser/ui/browser.h"
[email protected]47ae23372013-01-29 01:50:4816#include "chrome/browser/ui/tabs/tab_strip_model.h"
[email protected]a964e112011-04-14 21:52:5117#include "chrome/common/chrome_switches.h"
[email protected]af44e7fb2011-07-29 18:32:3218#include "chrome/test/base/ui_test_utils.h"
[email protected]4ca15302012-01-03 05:53:2019#include "content/public/browser/web_contents.h"
[email protected]7d478cb2012-07-24 17:19:4220#include "content/public/test/browser_test_utils.h"
[email protected]e4452d32013-11-15 23:07:4121#include "extensions/common/extension.h"
[email protected]d42c11152013-08-22 19:36:3222#include "extensions/common/manifest.h"
[email protected]f2cb3cf2013-03-21 01:40:5323#include "net/dns/mock_host_resolver.h"
[email protected]a6483d22013-07-03 22:11:0024#include "url/gurl.h"
[email protected]a964e112011-04-14 21:52:5125
[email protected]1c321ee2012-05-21 03:02:3426using extensions::Extension;
27
[email protected]a964e112011-04-14 21:52:5128class ChromeAppAPITest : public ExtensionBrowserTest {
[email protected]80675fc2011-06-21 02:05:4929 protected:
[email protected]b27c3622014-03-22 00:26:5530 bool IsAppInstalledInMainFrame() {
31 return IsAppInstalledInFrame(
32 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame());
33 }
34 bool IsAppInstalledInIFrame() {
35 return IsAppInstalledInFrame(GetIFrame());
36 }
37 bool IsAppInstalledInFrame(content::RenderFrameHost* frame) {
[email protected]06bc5d92013-01-02 22:44:1338 const char kGetAppIsInstalled[] =
39 "window.domAutomationController.send(window.chrome.app.isInstalled);";
[email protected]80675fc2011-06-21 02:05:4940 bool result;
[email protected]b27c3622014-03-22 00:26:5541 CHECK(content::ExecuteScriptAndExtractBool(frame,
42 kGetAppIsInstalled,
43 &result));
[email protected]f2fe87c2012-04-24 17:53:4944 return result;
45 }
46
[email protected]b27c3622014-03-22 00:26:5547 std::string InstallStateInMainFrame() {
48 return InstallStateInFrame(
49 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame());
50 }
51 std::string InstallStateInIFrame() {
52 return InstallStateInFrame(GetIFrame());
53 }
54 std::string InstallStateInFrame(content::RenderFrameHost* frame) {
[email protected]06bc5d92013-01-02 22:44:1355 const char kGetAppInstallState[] =
56 "window.chrome.app.installState("
57 " function(s) { window.domAutomationController.send(s); });";
[email protected]f2fe87c2012-04-24 17:53:4958 std::string result;
[email protected]b27c3622014-03-22 00:26:5559 CHECK(content::ExecuteScriptAndExtractString(frame,
60 kGetAppInstallState,
61 &result));
[email protected]f2fe87c2012-04-24 17:53:4962 return result;
63 }
64
[email protected]b27c3622014-03-22 00:26:5565 std::string RunningStateInMainFrame() {
66 return RunningStateInFrame(
67 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame());
68 }
69 std::string RunningStateInIFrame() {
70 return RunningStateInFrame(GetIFrame());
71 }
72 std::string RunningStateInFrame(content::RenderFrameHost* frame) {
[email protected]06bc5d92013-01-02 22:44:1373 const char kGetAppRunningState[] =
74 "window.domAutomationController.send("
75 " window.chrome.app.runningState());";
[email protected]f2fe87c2012-04-24 17:53:4976 std::string result;
[email protected]b27c3622014-03-22 00:26:5577 CHECK(content::ExecuteScriptAndExtractString(frame,
78 kGetAppRunningState,
79 &result));
[email protected]80675fc2011-06-21 02:05:4980 return result;
81 }
82
[email protected]a964e112011-04-14 21:52:5183 private:
[email protected]b27c3622014-03-22 00:26:5584 content::RenderFrameHost* GetIFrame() {
85 return content::FrameMatchingPredicate(
86 browser()->tab_strip_model()->GetActiveWebContents(),
87 base::Bind(&content::FrameIsChildOfMainFrame));
88 }
89
[email protected]49aeab62013-02-07 02:53:1190 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
[email protected]a964e112011-04-14 21:52:5191 ExtensionBrowserTest::SetUpCommandLine(command_line);
92 command_line->AppendSwitchASCII(switches::kAppsCheckoutURL,
93 "http://checkout.com:");
94 }
95};
96
[email protected]89117c42013-05-07 16:47:2597// Flaky http://crbug.com/238674
98#if defined(OS_WIN)
99#define MAYBE_IsInstalled DISABLED_IsInstalled
100#else
101#define MAYBE_IsInstalled IsInstalled
102#endif
103IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, MAYBE_IsInstalled) {
[email protected]a964e112011-04-14 21:52:51104 std::string app_host("app.com");
105 std::string nonapp_host("nonapp.com");
106
107 host_resolver()->AddRule(app_host, "127.0.0.1");
108 host_resolver()->AddRule(nonapp_host, "127.0.0.1");
109 ASSERT_TRUE(test_server()->Start());
110
111 GURL test_file_url(test_server()->GetURL("extensions/test_file.html"));
112 GURL::Replacements replace_host;
113
114 replace_host.SetHostStr(app_host);
115 GURL app_url(test_file_url.ReplaceComponents(replace_host));
116
117 replace_host.SetHostStr(nonapp_host);
118 GURL non_app_url(test_file_url.ReplaceComponents(replace_host));
119
[email protected]80675fc2011-06-21 02:05:49120 // Before the app is installed, app.com does not think that it is installed
121 ui_test_utils::NavigateToURL(browser(), app_url);
[email protected]b27c3622014-03-22 00:26:55122 EXPECT_FALSE(IsAppInstalledInMainFrame());
[email protected]a964e112011-04-14 21:52:51123
124 // Load an app which includes app.com in its extent.
125 const Extension* extension = LoadExtension(
126 test_data_dir_.AppendASCII("app_dot_com_app"));
127 ASSERT_TRUE(extension);
128
[email protected]80675fc2011-06-21 02:05:49129 // Even after the app is installed, the existing app.com tab is not in an
130 // app process, so chrome.app.isInstalled should return false.
[email protected]b27c3622014-03-22 00:26:55131 EXPECT_FALSE(IsAppInstalledInMainFrame());
[email protected]a964e112011-04-14 21:52:51132
133 // Test that a non-app page has chrome.app.isInstalled = false.
134 ui_test_utils::NavigateToURL(browser(), non_app_url);
[email protected]b27c3622014-03-22 00:26:55135 EXPECT_FALSE(IsAppInstalledInMainFrame());
[email protected]a964e112011-04-14 21:52:51136
137 // Test that a non-app page returns null for chrome.app.getDetails().
[email protected]06bc5d92013-01-02 22:44:13138 const char kGetAppDetails[] =
139 "window.domAutomationController.send("
140 " JSON.stringify(window.chrome.app.getDetails()));";
[email protected]80675fc2011-06-21 02:05:49141 std::string result;
[email protected]a964e112011-04-14 21:52:51142 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43143 content::ExecuteScriptAndExtractString(
[email protected]47ae23372013-01-29 01:50:48144 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13145 kGetAppDetails,
146 &result));
[email protected]a964e112011-04-14 21:52:51147 EXPECT_EQ("null", result);
148
149 // Check that an app page has chrome.app.isInstalled = true.
150 ui_test_utils::NavigateToURL(browser(), app_url);
[email protected]b27c3622014-03-22 00:26:55151 EXPECT_TRUE(IsAppInstalledInMainFrame());
[email protected]a964e112011-04-14 21:52:51152
153 // Check that an app page returns the correct result for
154 // chrome.app.getDetails().
155 ui_test_utils::NavigateToURL(browser(), app_url);
156 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43157 content::ExecuteScriptAndExtractString(
[email protected]47ae23372013-01-29 01:50:48158 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13159 kGetAppDetails,
160 &result));
[email protected]023b3d12013-12-23 18:46:49161 scoped_ptr<base::DictionaryValue> app_details(
162 static_cast<base::DictionaryValue*>(base::JSONReader::Read(result)));
[email protected]953620b2011-12-04 00:55:32163 // extension->manifest() does not contain the id.
[email protected]a964e112011-04-14 21:52:51164 app_details->Remove("id", NULL);
165 EXPECT_TRUE(app_details.get());
[email protected]953620b2011-12-04 00:55:32166 EXPECT_TRUE(app_details->Equals(extension->manifest()->value()));
[email protected]a964e112011-04-14 21:52:51167
[email protected]9b3a5c22011-05-31 08:03:13168 // Try to change app.isInstalled. Should silently fail, so
169 // that isInstalled should have the initial value.
170 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43171 content::ExecuteScriptAndExtractString(
[email protected]47ae23372013-01-29 01:50:48172 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13173 "window.domAutomationController.send("
174 " function() {"
175 " var value = window.chrome.app.isInstalled;"
176 " window.chrome.app.isInstalled = !value;"
177 " if (window.chrome.app.isInstalled == value) {"
178 " return 'true';"
179 " } else {"
180 " return 'false';"
181 " }"
182 " }()"
183 ");",
184 &result));
[email protected]9b3a5c22011-05-31 08:03:13185
186 // Should not be able to alter window.chrome.app.isInstalled from javascript";
187 EXPECT_EQ("true", result);
[email protected]a964e112011-04-14 21:52:51188}
189
190IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, GetDetailsForFrame) {
191 std::string app_host("app.com");
192 std::string nonapp_host("nonapp.com");
193 std::string checkout_host("checkout.com");
194
195 host_resolver()->AddRule(app_host, "127.0.0.1");
196 host_resolver()->AddRule(nonapp_host, "127.0.0.1");
197 host_resolver()->AddRule(checkout_host, "127.0.0.1");
198 ASSERT_TRUE(test_server()->Start());
199
200 GURL test_file_url(test_server()->GetURL(
201 "files/extensions/get_app_details_for_frame.html"));
202 GURL::Replacements replace_host;
203
204 replace_host.SetHostStr(checkout_host);
205 GURL checkout_url(test_file_url.ReplaceComponents(replace_host));
206
207 replace_host.SetHostStr(app_host);
208 GURL app_url(test_file_url.ReplaceComponents(replace_host));
209
210 // Load an app which includes app.com in its extent.
211 const Extension* extension = LoadExtension(
212 test_data_dir_.AppendASCII("app_dot_com_app"));
213 ASSERT_TRUE(extension);
214
215 // Test that normal pages (even apps) cannot use getDetailsForFrame().
216 ui_test_utils::NavigateToURL(browser(), app_url);
[email protected]06bc5d92013-01-02 22:44:13217 const char kTestUnsuccessfulAccess[] =
218 "window.domAutomationController.send(window.testUnsuccessfulAccess())";
[email protected]a964e112011-04-14 21:52:51219 bool result = false;
220 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43221 content::ExecuteScriptAndExtractBool(
[email protected]47ae23372013-01-29 01:50:48222 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13223 kTestUnsuccessfulAccess,
224 &result));
[email protected]a964e112011-04-14 21:52:51225 EXPECT_TRUE(result);
226
227 // Test that checkout can use getDetailsForFrame() and that it works
228 // correctly.
229 ui_test_utils::NavigateToURL(browser(), checkout_url);
[email protected]06bc5d92013-01-02 22:44:13230 const char kGetDetailsForFrame[] =
231 "window.domAutomationController.send("
232 " JSON.stringify(chrome.app.getDetailsForFrame(frames[0])))";
[email protected]a964e112011-04-14 21:52:51233 std::string json;
234 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43235 content::ExecuteScriptAndExtractString(
[email protected]47ae23372013-01-29 01:50:48236 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13237 kGetDetailsForFrame,
238 &json));
[email protected]a964e112011-04-14 21:52:51239
[email protected]023b3d12013-12-23 18:46:49240 scoped_ptr<base::DictionaryValue> app_details(
241 static_cast<base::DictionaryValue*>(base::JSONReader::Read(json)));
[email protected]953620b2011-12-04 00:55:32242 // extension->manifest() does not contain the id.
[email protected]a964e112011-04-14 21:52:51243 app_details->Remove("id", NULL);
244 EXPECT_TRUE(app_details.get());
[email protected]953620b2011-12-04 00:55:32245 EXPECT_TRUE(app_details->Equals(extension->manifest()->value()));
[email protected]a964e112011-04-14 21:52:51246}
[email protected]f2fe87c2012-04-24 17:53:49247
248
249IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, InstallAndRunningState) {
250 std::string app_host("app.com");
251 std::string non_app_host("nonapp.com");
252
253 host_resolver()->AddRule(app_host, "127.0.0.1");
254 host_resolver()->AddRule(non_app_host, "127.0.0.1");
255 ASSERT_TRUE(test_server()->Start());
256
257 GURL test_file_url(test_server()->GetURL(
258 "files/extensions/get_app_details_for_frame.html"));
259 GURL::Replacements replace_host;
260
261 replace_host.SetHostStr(app_host);
262 GURL app_url(test_file_url.ReplaceComponents(replace_host));
263
264 replace_host.SetHostStr(non_app_host);
265 GURL non_app_url(test_file_url.ReplaceComponents(replace_host));
266
267 // Before the app is installed, app.com does not think that it is installed
268 ui_test_utils::NavigateToURL(browser(), app_url);
269
[email protected]b27c3622014-03-22 00:26:55270 EXPECT_EQ("not_installed", InstallStateInMainFrame());
271 EXPECT_EQ("cannot_run", RunningStateInMainFrame());
272 EXPECT_FALSE(IsAppInstalledInMainFrame());
[email protected]f2fe87c2012-04-24 17:53:49273
274 const Extension* extension = LoadExtension(
275 test_data_dir_.AppendASCII("app_dot_com_app"));
276 ASSERT_TRUE(extension);
277
[email protected]b27c3622014-03-22 00:26:55278 EXPECT_EQ("installed", InstallStateInMainFrame());
279 EXPECT_EQ("ready_to_run", RunningStateInMainFrame());
280 EXPECT_FALSE(IsAppInstalledInMainFrame());
[email protected]f2fe87c2012-04-24 17:53:49281
282 // Reloading the page should put the tab in an app process.
283 ui_test_utils::NavigateToURL(browser(), app_url);
[email protected]b27c3622014-03-22 00:26:55284 EXPECT_EQ("installed", InstallStateInMainFrame());
285 EXPECT_EQ("running", RunningStateInMainFrame());
286 EXPECT_TRUE(IsAppInstalledInMainFrame());
[email protected]f2fe87c2012-04-24 17:53:49287
288 // Disable the extension and verify the state.
289 browser()->profile()->GetExtensionService()->DisableExtension(
290 extension->id(), Extension::DISABLE_PERMISSIONS_INCREASE);
291 ui_test_utils::NavigateToURL(browser(), app_url);
292
[email protected]b27c3622014-03-22 00:26:55293 EXPECT_EQ("disabled", InstallStateInMainFrame());
294 EXPECT_EQ("cannot_run", RunningStateInMainFrame());
295 EXPECT_FALSE(IsAppInstalledInMainFrame());
[email protected]f2fe87c2012-04-24 17:53:49296
297 browser()->profile()->GetExtensionService()->EnableExtension(extension->id());
[email protected]b27c3622014-03-22 00:26:55298 EXPECT_EQ("installed", InstallStateInMainFrame());
299 EXPECT_EQ("ready_to_run", RunningStateInMainFrame());
300 EXPECT_FALSE(IsAppInstalledInMainFrame());
[email protected]f2fe87c2012-04-24 17:53:49301
302 // The non-app URL should still not be installed or running.
303 ui_test_utils::NavigateToURL(browser(), non_app_url);
304
[email protected]b27c3622014-03-22 00:26:55305 EXPECT_EQ("not_installed", InstallStateInMainFrame());
306 EXPECT_EQ("cannot_run", RunningStateInMainFrame());
307 EXPECT_FALSE(IsAppInstalledInMainFrame());
[email protected]f2fe87c2012-04-24 17:53:49308
[email protected]b27c3622014-03-22 00:26:55309 EXPECT_EQ("installed", InstallStateInIFrame());
310 EXPECT_EQ("cannot_run", RunningStateInIFrame());
311 EXPECT_FALSE(IsAppInstalledInIFrame());
[email protected]f2fe87c2012-04-24 17:53:49312
313}
314
315IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, InstallAndRunningStateFrame) {
316 std::string app_host("app.com");
317 std::string non_app_host("nonapp.com");
318
319 host_resolver()->AddRule(app_host, "127.0.0.1");
320 host_resolver()->AddRule(non_app_host, "127.0.0.1");
321 ASSERT_TRUE(test_server()->Start());
322
323 GURL test_file_url(test_server()->GetURL(
324 "files/extensions/get_app_details_for_frame_reversed.html"));
325 GURL::Replacements replace_host;
326
327 replace_host.SetHostStr(app_host);
328 GURL app_url(test_file_url.ReplaceComponents(replace_host));
329
330 replace_host.SetHostStr(non_app_host);
331 GURL non_app_url(test_file_url.ReplaceComponents(replace_host));
332
333 // Check the install and running state of a non-app iframe running
334 // within an app.
335 ui_test_utils::NavigateToURL(browser(), app_url);
336
[email protected]b27c3622014-03-22 00:26:55337 EXPECT_EQ("not_installed", InstallStateInIFrame());
338 EXPECT_EQ("cannot_run", RunningStateInIFrame());
339 EXPECT_FALSE(IsAppInstalledInIFrame());
[email protected]f2fe87c2012-04-24 17:53:49340}