blob: 36c9ec8a0f0bfaa68153f99be3bd063551658164 [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]a964e112011-04-14 21:52:5110#include "base/string_number_conversions.h"
11#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]52877dbc62012-06-29 22:22:0316#include "chrome/browser/ui/browser_tabstrip.h"
[email protected]a964e112011-04-14 21:52:5117#include "chrome/common/chrome_switches.h"
18#include "chrome/common/extensions/extension.h"
[email protected]953620b2011-12-04 00:55:3219#include "chrome/common/extensions/manifest.h"
[email protected]af44e7fb2011-07-29 18:32:3220#include "chrome/test/base/ui_test_utils.h"
[email protected]4ca15302012-01-03 05:53:2021#include "content/public/browser/web_contents.h"
[email protected]7d478cb2012-07-24 17:19:4222#include "content/public/test/browser_test_utils.h"
[email protected]a964e112011-04-14 21:52:5123#include "googleurl/src/gurl.h"
24#include "net/base/mock_host_resolver.h"
25
[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]06bc5d92013-01-02 22:44:1330 bool IsAppInstalled() { return IsAppInstalled(""); }
31 bool IsAppInstalled(const char* frame_xpath) {
32 const char kGetAppIsInstalled[] =
33 "window.domAutomationController.send(window.chrome.app.isInstalled);";
[email protected]80675fc2011-06-21 02:05:4934 bool result;
35 CHECK(
[email protected]7d478cb2012-07-24 17:19:4236 content::ExecuteJavaScriptAndExtractBool(
[email protected]52877dbc62012-06-29 22:22:0337 chrome::GetActiveWebContents(browser())->GetRenderViewHost(),
[email protected]06bc5d92013-01-02 22:44:1338 frame_xpath, kGetAppIsInstalled, &result));
[email protected]f2fe87c2012-04-24 17:53:4939 return result;
40 }
41
[email protected]06bc5d92013-01-02 22:44:1342 std::string InstallState() { return InstallState(""); }
43 std::string InstallState(const char* frame_xpath) {
44 const char kGetAppInstallState[] =
45 "window.chrome.app.installState("
46 " function(s) { window.domAutomationController.send(s); });";
[email protected]f2fe87c2012-04-24 17:53:4947 std::string result;
48 CHECK(
[email protected]7d478cb2012-07-24 17:19:4249 content::ExecuteJavaScriptAndExtractString(
[email protected]52877dbc62012-06-29 22:22:0350 chrome::GetActiveWebContents(browser())->GetRenderViewHost(),
[email protected]06bc5d92013-01-02 22:44:1351 frame_xpath, kGetAppInstallState, &result));
[email protected]f2fe87c2012-04-24 17:53:4952 return result;
53 }
54
[email protected]06bc5d92013-01-02 22:44:1355 std::string RunningState() { return RunningState(""); }
56 std::string RunningState(const char* frame_xpath) {
57 const char kGetAppRunningState[] =
58 "window.domAutomationController.send("
59 " window.chrome.app.runningState());";
[email protected]f2fe87c2012-04-24 17:53:4960 std::string result;
61 CHECK(
[email protected]7d478cb2012-07-24 17:19:4262 content::ExecuteJavaScriptAndExtractString(
[email protected]52877dbc62012-06-29 22:22:0363 chrome::GetActiveWebContents(browser())->GetRenderViewHost(),
[email protected]06bc5d92013-01-02 22:44:1364 frame_xpath, kGetAppRunningState, &result));
[email protected]80675fc2011-06-21 02:05:4965 return result;
66 }
67
[email protected]a964e112011-04-14 21:52:5168 private:
69 virtual void SetUpCommandLine(CommandLine* command_line) {
70 ExtensionBrowserTest::SetUpCommandLine(command_line);
71 command_line->AppendSwitchASCII(switches::kAppsCheckoutURL,
72 "http://checkout.com:");
73 }
74};
75
76IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, IsInstalled) {
77 std::string app_host("app.com");
78 std::string nonapp_host("nonapp.com");
79
80 host_resolver()->AddRule(app_host, "127.0.0.1");
81 host_resolver()->AddRule(nonapp_host, "127.0.0.1");
82 ASSERT_TRUE(test_server()->Start());
83
84 GURL test_file_url(test_server()->GetURL("extensions/test_file.html"));
85 GURL::Replacements replace_host;
86
87 replace_host.SetHostStr(app_host);
88 GURL app_url(test_file_url.ReplaceComponents(replace_host));
89
90 replace_host.SetHostStr(nonapp_host);
91 GURL non_app_url(test_file_url.ReplaceComponents(replace_host));
92
[email protected]80675fc2011-06-21 02:05:4993 // Before the app is installed, app.com does not think that it is installed
94 ui_test_utils::NavigateToURL(browser(), app_url);
95 EXPECT_FALSE(IsAppInstalled());
[email protected]a964e112011-04-14 21:52:5196
97 // Load an app which includes app.com in its extent.
98 const Extension* extension = LoadExtension(
99 test_data_dir_.AppendASCII("app_dot_com_app"));
100 ASSERT_TRUE(extension);
101
[email protected]80675fc2011-06-21 02:05:49102 // Even after the app is installed, the existing app.com tab is not in an
103 // app process, so chrome.app.isInstalled should return false.
104 EXPECT_FALSE(IsAppInstalled());
[email protected]a964e112011-04-14 21:52:51105
106 // Test that a non-app page has chrome.app.isInstalled = false.
107 ui_test_utils::NavigateToURL(browser(), non_app_url);
[email protected]80675fc2011-06-21 02:05:49108 EXPECT_FALSE(IsAppInstalled());
[email protected]a964e112011-04-14 21:52:51109
110 // Test that a non-app page returns null for chrome.app.getDetails().
[email protected]06bc5d92013-01-02 22:44:13111 const char kGetAppDetails[] =
112 "window.domAutomationController.send("
113 " JSON.stringify(window.chrome.app.getDetails()));";
[email protected]80675fc2011-06-21 02:05:49114 std::string result;
[email protected]a964e112011-04-14 21:52:51115 ASSERT_TRUE(
[email protected]7d478cb2012-07-24 17:19:42116 content::ExecuteJavaScriptAndExtractString(
[email protected]52877dbc62012-06-29 22:22:03117 chrome::GetActiveWebContents(browser())->GetRenderViewHost(),
[email protected]06bc5d92013-01-02 22:44:13118 "",
119 kGetAppDetails,
120 &result));
[email protected]a964e112011-04-14 21:52:51121 EXPECT_EQ("null", result);
122
123 // Check that an app page has chrome.app.isInstalled = true.
124 ui_test_utils::NavigateToURL(browser(), app_url);
[email protected]80675fc2011-06-21 02:05:49125 EXPECT_TRUE(IsAppInstalled());
[email protected]a964e112011-04-14 21:52:51126
127 // Check that an app page returns the correct result for
128 // chrome.app.getDetails().
129 ui_test_utils::NavigateToURL(browser(), app_url);
130 ASSERT_TRUE(
[email protected]7d478cb2012-07-24 17:19:42131 content::ExecuteJavaScriptAndExtractString(
[email protected]52877dbc62012-06-29 22:22:03132 chrome::GetActiveWebContents(browser())->GetRenderViewHost(),
[email protected]06bc5d92013-01-02 22:44:13133 "",
134 kGetAppDetails,
135 &result));
[email protected]a964e112011-04-14 21:52:51136 scoped_ptr<DictionaryValue> app_details(
[email protected]cd5785752012-04-11 00:15:41137 static_cast<DictionaryValue*>(base::JSONReader::Read(result)));
[email protected]953620b2011-12-04 00:55:32138 // extension->manifest() does not contain the id.
[email protected]a964e112011-04-14 21:52:51139 app_details->Remove("id", NULL);
140 EXPECT_TRUE(app_details.get());
[email protected]953620b2011-12-04 00:55:32141 EXPECT_TRUE(app_details->Equals(extension->manifest()->value()));
[email protected]a964e112011-04-14 21:52:51142
[email protected]9b3a5c22011-05-31 08:03:13143 // Try to change app.isInstalled. Should silently fail, so
144 // that isInstalled should have the initial value.
145 ASSERT_TRUE(
[email protected]7d478cb2012-07-24 17:19:42146 content::ExecuteJavaScriptAndExtractString(
[email protected]52877dbc62012-06-29 22:22:03147 chrome::GetActiveWebContents(browser())->GetRenderViewHost(),
[email protected]06bc5d92013-01-02 22:44:13148 "",
149 "window.domAutomationController.send("
150 " function() {"
151 " var value = window.chrome.app.isInstalled;"
152 " window.chrome.app.isInstalled = !value;"
153 " if (window.chrome.app.isInstalled == value) {"
154 " return 'true';"
155 " } else {"
156 " return 'false';"
157 " }"
158 " }()"
159 ");",
160 &result));
[email protected]9b3a5c22011-05-31 08:03:13161
162 // Should not be able to alter window.chrome.app.isInstalled from javascript";
163 EXPECT_EQ("true", result);
[email protected]a964e112011-04-14 21:52:51164}
165
166IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, GetDetailsForFrame) {
167 std::string app_host("app.com");
168 std::string nonapp_host("nonapp.com");
169 std::string checkout_host("checkout.com");
170
171 host_resolver()->AddRule(app_host, "127.0.0.1");
172 host_resolver()->AddRule(nonapp_host, "127.0.0.1");
173 host_resolver()->AddRule(checkout_host, "127.0.0.1");
174 ASSERT_TRUE(test_server()->Start());
175
176 GURL test_file_url(test_server()->GetURL(
177 "files/extensions/get_app_details_for_frame.html"));
178 GURL::Replacements replace_host;
179
180 replace_host.SetHostStr(checkout_host);
181 GURL checkout_url(test_file_url.ReplaceComponents(replace_host));
182
183 replace_host.SetHostStr(app_host);
184 GURL app_url(test_file_url.ReplaceComponents(replace_host));
185
186 // Load an app which includes app.com in its extent.
187 const Extension* extension = LoadExtension(
188 test_data_dir_.AppendASCII("app_dot_com_app"));
189 ASSERT_TRUE(extension);
190
191 // Test that normal pages (even apps) cannot use getDetailsForFrame().
192 ui_test_utils::NavigateToURL(browser(), app_url);
[email protected]06bc5d92013-01-02 22:44:13193 const char kTestUnsuccessfulAccess[] =
194 "window.domAutomationController.send(window.testUnsuccessfulAccess())";
[email protected]a964e112011-04-14 21:52:51195 bool result = false;
196 ASSERT_TRUE(
[email protected]7d478cb2012-07-24 17:19:42197 content::ExecuteJavaScriptAndExtractBool(
[email protected]52877dbc62012-06-29 22:22:03198 chrome::GetActiveWebContents(browser())->GetRenderViewHost(),
[email protected]06bc5d92013-01-02 22:44:13199 "",
200 kTestUnsuccessfulAccess,
201 &result));
[email protected]a964e112011-04-14 21:52:51202 EXPECT_TRUE(result);
203
204 // Test that checkout can use getDetailsForFrame() and that it works
205 // correctly.
206 ui_test_utils::NavigateToURL(browser(), checkout_url);
[email protected]06bc5d92013-01-02 22:44:13207 const char kGetDetailsForFrame[] =
208 "window.domAutomationController.send("
209 " JSON.stringify(chrome.app.getDetailsForFrame(frames[0])))";
[email protected]a964e112011-04-14 21:52:51210 std::string json;
211 ASSERT_TRUE(
[email protected]7d478cb2012-07-24 17:19:42212 content::ExecuteJavaScriptAndExtractString(
[email protected]52877dbc62012-06-29 22:22:03213 chrome::GetActiveWebContents(browser())->GetRenderViewHost(),
[email protected]06bc5d92013-01-02 22:44:13214 "",
215 kGetDetailsForFrame,
216 &json));
[email protected]a964e112011-04-14 21:52:51217
218 scoped_ptr<DictionaryValue> app_details(
[email protected]cd5785752012-04-11 00:15:41219 static_cast<DictionaryValue*>(base::JSONReader::Read(json)));
[email protected]953620b2011-12-04 00:55:32220 // extension->manifest() does not contain the id.
[email protected]a964e112011-04-14 21:52:51221 app_details->Remove("id", NULL);
222 EXPECT_TRUE(app_details.get());
[email protected]953620b2011-12-04 00:55:32223 EXPECT_TRUE(app_details->Equals(extension->manifest()->value()));
[email protected]a964e112011-04-14 21:52:51224}
[email protected]f2fe87c2012-04-24 17:53:49225
226
227IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, InstallAndRunningState) {
228 std::string app_host("app.com");
229 std::string non_app_host("nonapp.com");
230
231 host_resolver()->AddRule(app_host, "127.0.0.1");
232 host_resolver()->AddRule(non_app_host, "127.0.0.1");
233 ASSERT_TRUE(test_server()->Start());
234
235 GURL test_file_url(test_server()->GetURL(
236 "files/extensions/get_app_details_for_frame.html"));
237 GURL::Replacements replace_host;
238
239 replace_host.SetHostStr(app_host);
240 GURL app_url(test_file_url.ReplaceComponents(replace_host));
241
242 replace_host.SetHostStr(non_app_host);
243 GURL non_app_url(test_file_url.ReplaceComponents(replace_host));
244
245 // Before the app is installed, app.com does not think that it is installed
246 ui_test_utils::NavigateToURL(browser(), app_url);
247
248 EXPECT_EQ("not_installed", InstallState());
249 EXPECT_EQ("cannot_run", RunningState());
250 EXPECT_FALSE(IsAppInstalled());
251
252 const Extension* extension = LoadExtension(
253 test_data_dir_.AppendASCII("app_dot_com_app"));
254 ASSERT_TRUE(extension);
255
256 EXPECT_EQ("installed", InstallState());
257 EXPECT_EQ("ready_to_run", RunningState());
258 EXPECT_FALSE(IsAppInstalled());
259
260 // Reloading the page should put the tab in an app process.
261 ui_test_utils::NavigateToURL(browser(), app_url);
262 EXPECT_EQ("installed", InstallState());
263 EXPECT_EQ("running", RunningState());
264 EXPECT_TRUE(IsAppInstalled());
265
266 // Disable the extension and verify the state.
267 browser()->profile()->GetExtensionService()->DisableExtension(
268 extension->id(), Extension::DISABLE_PERMISSIONS_INCREASE);
269 ui_test_utils::NavigateToURL(browser(), app_url);
270
271 EXPECT_EQ("disabled", InstallState());
272 EXPECT_EQ("cannot_run", RunningState());
273 EXPECT_FALSE(IsAppInstalled());
274
275 browser()->profile()->GetExtensionService()->EnableExtension(extension->id());
276 EXPECT_EQ("installed", InstallState());
277 EXPECT_EQ("ready_to_run", RunningState());
278 EXPECT_FALSE(IsAppInstalled());
279
280 // The non-app URL should still not be installed or running.
281 ui_test_utils::NavigateToURL(browser(), non_app_url);
282
283 EXPECT_EQ("not_installed", InstallState());
284 EXPECT_EQ("cannot_run", RunningState());
285 EXPECT_FALSE(IsAppInstalled());
286
[email protected]06bc5d92013-01-02 22:44:13287 EXPECT_EQ("installed", InstallState("//html/iframe[1]"));
288 EXPECT_EQ("cannot_run", RunningState("//html/iframe[1]"));
289 EXPECT_FALSE(IsAppInstalled("//html/iframe[1]"));
[email protected]f2fe87c2012-04-24 17:53:49290
291}
292
293IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, InstallAndRunningStateFrame) {
294 std::string app_host("app.com");
295 std::string non_app_host("nonapp.com");
296
297 host_resolver()->AddRule(app_host, "127.0.0.1");
298 host_resolver()->AddRule(non_app_host, "127.0.0.1");
299 ASSERT_TRUE(test_server()->Start());
300
301 GURL test_file_url(test_server()->GetURL(
302 "files/extensions/get_app_details_for_frame_reversed.html"));
303 GURL::Replacements replace_host;
304
305 replace_host.SetHostStr(app_host);
306 GURL app_url(test_file_url.ReplaceComponents(replace_host));
307
308 replace_host.SetHostStr(non_app_host);
309 GURL non_app_url(test_file_url.ReplaceComponents(replace_host));
310
311 // Check the install and running state of a non-app iframe running
312 // within an app.
313 ui_test_utils::NavigateToURL(browser(), app_url);
314
[email protected]06bc5d92013-01-02 22:44:13315 EXPECT_EQ("not_installed", InstallState("//html/iframe[1]"));
316 EXPECT_EQ("cannot_run", RunningState("//html/iframe[1]"));
317 EXPECT_FALSE(IsAppInstalled("//html/iframe[1]"));
[email protected]f2fe87c2012-04-24 17:53:49318}