blob: 3103e6fa9788412bc6a4c618d0df3d1ab54e45f4 [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"
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"
[email protected]f2cb3cf2013-03-21 01:40:5324#include "net/dns/mock_host_resolver.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]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]b6987e02013-01-04 18:30:4336 content::ExecuteScriptInFrameAndExtractBool(
[email protected]47ae23372013-01-29 01:50:4837 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]b6987e02013-01-04 18:30:4338 frame_xpath,
39 kGetAppIsInstalled,
40 &result));
[email protected]f2fe87c2012-04-24 17:53:4941 return result;
42 }
43
[email protected]06bc5d92013-01-02 22:44:1344 std::string InstallState() { return InstallState(""); }
45 std::string InstallState(const char* frame_xpath) {
46 const char kGetAppInstallState[] =
47 "window.chrome.app.installState("
48 " function(s) { window.domAutomationController.send(s); });";
[email protected]f2fe87c2012-04-24 17:53:4949 std::string result;
50 CHECK(
[email protected]b6987e02013-01-04 18:30:4351 content::ExecuteScriptInFrameAndExtractString(
[email protected]47ae23372013-01-29 01:50:4852 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]b6987e02013-01-04 18:30:4353 frame_xpath,
54 kGetAppInstallState,
55 &result));
[email protected]f2fe87c2012-04-24 17:53:4956 return result;
57 }
58
[email protected]06bc5d92013-01-02 22:44:1359 std::string RunningState() { return RunningState(""); }
60 std::string RunningState(const char* frame_xpath) {
61 const char kGetAppRunningState[] =
62 "window.domAutomationController.send("
63 " window.chrome.app.runningState());";
[email protected]f2fe87c2012-04-24 17:53:4964 std::string result;
65 CHECK(
[email protected]b6987e02013-01-04 18:30:4366 content::ExecuteScriptInFrameAndExtractString(
[email protected]47ae23372013-01-29 01:50:4867 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]b6987e02013-01-04 18:30:4368 frame_xpath,
69 kGetAppRunningState,
70 &result));
[email protected]80675fc2011-06-21 02:05:4971 return result;
72 }
73
[email protected]a964e112011-04-14 21:52:5174 private:
[email protected]49aeab62013-02-07 02:53:1175 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
[email protected]a964e112011-04-14 21:52:5176 ExtensionBrowserTest::SetUpCommandLine(command_line);
77 command_line->AppendSwitchASCII(switches::kAppsCheckoutURL,
78 "http://checkout.com:");
79 }
80};
81
82IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, IsInstalled) {
83 std::string app_host("app.com");
84 std::string nonapp_host("nonapp.com");
85
86 host_resolver()->AddRule(app_host, "127.0.0.1");
87 host_resolver()->AddRule(nonapp_host, "127.0.0.1");
88 ASSERT_TRUE(test_server()->Start());
89
90 GURL test_file_url(test_server()->GetURL("extensions/test_file.html"));
91 GURL::Replacements replace_host;
92
93 replace_host.SetHostStr(app_host);
94 GURL app_url(test_file_url.ReplaceComponents(replace_host));
95
96 replace_host.SetHostStr(nonapp_host);
97 GURL non_app_url(test_file_url.ReplaceComponents(replace_host));
98
[email protected]80675fc2011-06-21 02:05:4999 // Before the app is installed, app.com does not think that it is installed
100 ui_test_utils::NavigateToURL(browser(), app_url);
101 EXPECT_FALSE(IsAppInstalled());
[email protected]a964e112011-04-14 21:52:51102
103 // Load an app which includes app.com in its extent.
104 const Extension* extension = LoadExtension(
105 test_data_dir_.AppendASCII("app_dot_com_app"));
106 ASSERT_TRUE(extension);
107
[email protected]80675fc2011-06-21 02:05:49108 // Even after the app is installed, the existing app.com tab is not in an
109 // app process, so chrome.app.isInstalled should return false.
110 EXPECT_FALSE(IsAppInstalled());
[email protected]a964e112011-04-14 21:52:51111
112 // Test that a non-app page has chrome.app.isInstalled = false.
113 ui_test_utils::NavigateToURL(browser(), non_app_url);
[email protected]80675fc2011-06-21 02:05:49114 EXPECT_FALSE(IsAppInstalled());
[email protected]a964e112011-04-14 21:52:51115
116 // Test that a non-app page returns null for chrome.app.getDetails().
[email protected]06bc5d92013-01-02 22:44:13117 const char kGetAppDetails[] =
118 "window.domAutomationController.send("
119 " JSON.stringify(window.chrome.app.getDetails()));";
[email protected]80675fc2011-06-21 02:05:49120 std::string result;
[email protected]a964e112011-04-14 21:52:51121 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43122 content::ExecuteScriptAndExtractString(
[email protected]47ae23372013-01-29 01:50:48123 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13124 kGetAppDetails,
125 &result));
[email protected]a964e112011-04-14 21:52:51126 EXPECT_EQ("null", result);
127
128 // Check that an app page has chrome.app.isInstalled = true.
129 ui_test_utils::NavigateToURL(browser(), app_url);
[email protected]80675fc2011-06-21 02:05:49130 EXPECT_TRUE(IsAppInstalled());
[email protected]a964e112011-04-14 21:52:51131
132 // Check that an app page returns the correct result for
133 // chrome.app.getDetails().
134 ui_test_utils::NavigateToURL(browser(), app_url);
135 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43136 content::ExecuteScriptAndExtractString(
[email protected]47ae23372013-01-29 01:50:48137 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13138 kGetAppDetails,
139 &result));
[email protected]a964e112011-04-14 21:52:51140 scoped_ptr<DictionaryValue> app_details(
[email protected]cd5785752012-04-11 00:15:41141 static_cast<DictionaryValue*>(base::JSONReader::Read(result)));
[email protected]953620b2011-12-04 00:55:32142 // extension->manifest() does not contain the id.
[email protected]a964e112011-04-14 21:52:51143 app_details->Remove("id", NULL);
144 EXPECT_TRUE(app_details.get());
[email protected]953620b2011-12-04 00:55:32145 EXPECT_TRUE(app_details->Equals(extension->manifest()->value()));
[email protected]a964e112011-04-14 21:52:51146
[email protected]9b3a5c22011-05-31 08:03:13147 // Try to change app.isInstalled. Should silently fail, so
148 // that isInstalled should have the initial value.
149 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43150 content::ExecuteScriptAndExtractString(
[email protected]47ae23372013-01-29 01:50:48151 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13152 "window.domAutomationController.send("
153 " function() {"
154 " var value = window.chrome.app.isInstalled;"
155 " window.chrome.app.isInstalled = !value;"
156 " if (window.chrome.app.isInstalled == value) {"
157 " return 'true';"
158 " } else {"
159 " return 'false';"
160 " }"
161 " }()"
162 ");",
163 &result));
[email protected]9b3a5c22011-05-31 08:03:13164
165 // Should not be able to alter window.chrome.app.isInstalled from javascript";
166 EXPECT_EQ("true", result);
[email protected]a964e112011-04-14 21:52:51167}
168
169IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, GetDetailsForFrame) {
170 std::string app_host("app.com");
171 std::string nonapp_host("nonapp.com");
172 std::string checkout_host("checkout.com");
173
174 host_resolver()->AddRule(app_host, "127.0.0.1");
175 host_resolver()->AddRule(nonapp_host, "127.0.0.1");
176 host_resolver()->AddRule(checkout_host, "127.0.0.1");
177 ASSERT_TRUE(test_server()->Start());
178
179 GURL test_file_url(test_server()->GetURL(
180 "files/extensions/get_app_details_for_frame.html"));
181 GURL::Replacements replace_host;
182
183 replace_host.SetHostStr(checkout_host);
184 GURL checkout_url(test_file_url.ReplaceComponents(replace_host));
185
186 replace_host.SetHostStr(app_host);
187 GURL app_url(test_file_url.ReplaceComponents(replace_host));
188
189 // Load an app which includes app.com in its extent.
190 const Extension* extension = LoadExtension(
191 test_data_dir_.AppendASCII("app_dot_com_app"));
192 ASSERT_TRUE(extension);
193
194 // Test that normal pages (even apps) cannot use getDetailsForFrame().
195 ui_test_utils::NavigateToURL(browser(), app_url);
[email protected]06bc5d92013-01-02 22:44:13196 const char kTestUnsuccessfulAccess[] =
197 "window.domAutomationController.send(window.testUnsuccessfulAccess())";
[email protected]a964e112011-04-14 21:52:51198 bool result = false;
199 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43200 content::ExecuteScriptAndExtractBool(
[email protected]47ae23372013-01-29 01:50:48201 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13202 kTestUnsuccessfulAccess,
203 &result));
[email protected]a964e112011-04-14 21:52:51204 EXPECT_TRUE(result);
205
206 // Test that checkout can use getDetailsForFrame() and that it works
207 // correctly.
208 ui_test_utils::NavigateToURL(browser(), checkout_url);
[email protected]06bc5d92013-01-02 22:44:13209 const char kGetDetailsForFrame[] =
210 "window.domAutomationController.send("
211 " JSON.stringify(chrome.app.getDetailsForFrame(frames[0])))";
[email protected]a964e112011-04-14 21:52:51212 std::string json;
213 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43214 content::ExecuteScriptAndExtractString(
[email protected]47ae23372013-01-29 01:50:48215 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13216 kGetDetailsForFrame,
217 &json));
[email protected]a964e112011-04-14 21:52:51218
219 scoped_ptr<DictionaryValue> app_details(
[email protected]cd5785752012-04-11 00:15:41220 static_cast<DictionaryValue*>(base::JSONReader::Read(json)));
[email protected]953620b2011-12-04 00:55:32221 // extension->manifest() does not contain the id.
[email protected]a964e112011-04-14 21:52:51222 app_details->Remove("id", NULL);
223 EXPECT_TRUE(app_details.get());
[email protected]953620b2011-12-04 00:55:32224 EXPECT_TRUE(app_details->Equals(extension->manifest()->value()));
[email protected]a964e112011-04-14 21:52:51225}
[email protected]f2fe87c2012-04-24 17:53:49226
227
228IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, InstallAndRunningState) {
229 std::string app_host("app.com");
230 std::string non_app_host("nonapp.com");
231
232 host_resolver()->AddRule(app_host, "127.0.0.1");
233 host_resolver()->AddRule(non_app_host, "127.0.0.1");
234 ASSERT_TRUE(test_server()->Start());
235
236 GURL test_file_url(test_server()->GetURL(
237 "files/extensions/get_app_details_for_frame.html"));
238 GURL::Replacements replace_host;
239
240 replace_host.SetHostStr(app_host);
241 GURL app_url(test_file_url.ReplaceComponents(replace_host));
242
243 replace_host.SetHostStr(non_app_host);
244 GURL non_app_url(test_file_url.ReplaceComponents(replace_host));
245
246 // Before the app is installed, app.com does not think that it is installed
247 ui_test_utils::NavigateToURL(browser(), app_url);
248
249 EXPECT_EQ("not_installed", InstallState());
250 EXPECT_EQ("cannot_run", RunningState());
251 EXPECT_FALSE(IsAppInstalled());
252
253 const Extension* extension = LoadExtension(
254 test_data_dir_.AppendASCII("app_dot_com_app"));
255 ASSERT_TRUE(extension);
256
257 EXPECT_EQ("installed", InstallState());
258 EXPECT_EQ("ready_to_run", RunningState());
259 EXPECT_FALSE(IsAppInstalled());
260
261 // Reloading the page should put the tab in an app process.
262 ui_test_utils::NavigateToURL(browser(), app_url);
263 EXPECT_EQ("installed", InstallState());
264 EXPECT_EQ("running", RunningState());
265 EXPECT_TRUE(IsAppInstalled());
266
267 // Disable the extension and verify the state.
268 browser()->profile()->GetExtensionService()->DisableExtension(
269 extension->id(), Extension::DISABLE_PERMISSIONS_INCREASE);
270 ui_test_utils::NavigateToURL(browser(), app_url);
271
272 EXPECT_EQ("disabled", InstallState());
273 EXPECT_EQ("cannot_run", RunningState());
274 EXPECT_FALSE(IsAppInstalled());
275
276 browser()->profile()->GetExtensionService()->EnableExtension(extension->id());
277 EXPECT_EQ("installed", InstallState());
278 EXPECT_EQ("ready_to_run", RunningState());
279 EXPECT_FALSE(IsAppInstalled());
280
281 // The non-app URL should still not be installed or running.
282 ui_test_utils::NavigateToURL(browser(), non_app_url);
283
284 EXPECT_EQ("not_installed", InstallState());
285 EXPECT_EQ("cannot_run", RunningState());
286 EXPECT_FALSE(IsAppInstalled());
287
[email protected]06bc5d92013-01-02 22:44:13288 EXPECT_EQ("installed", InstallState("//html/iframe[1]"));
289 EXPECT_EQ("cannot_run", RunningState("//html/iframe[1]"));
290 EXPECT_FALSE(IsAppInstalled("//html/iframe[1]"));
[email protected]f2fe87c2012-04-24 17:53:49291
292}
293
294IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, InstallAndRunningStateFrame) {
295 std::string app_host("app.com");
296 std::string non_app_host("nonapp.com");
297
298 host_resolver()->AddRule(app_host, "127.0.0.1");
299 host_resolver()->AddRule(non_app_host, "127.0.0.1");
300 ASSERT_TRUE(test_server()->Start());
301
302 GURL test_file_url(test_server()->GetURL(
303 "files/extensions/get_app_details_for_frame_reversed.html"));
304 GURL::Replacements replace_host;
305
306 replace_host.SetHostStr(app_host);
307 GURL app_url(test_file_url.ReplaceComponents(replace_host));
308
309 replace_host.SetHostStr(non_app_host);
310 GURL non_app_url(test_file_url.ReplaceComponents(replace_host));
311
312 // Check the install and running state of a non-app iframe running
313 // within an app.
314 ui_test_utils::NavigateToURL(browser(), app_url);
315
[email protected]06bc5d92013-01-02 22:44:13316 EXPECT_EQ("not_installed", InstallState("//html/iframe[1]"));
317 EXPECT_EQ("cannot_run", RunningState("//html/iframe[1]"));
318 EXPECT_FALSE(IsAppInstalled("//html/iframe[1]"));
[email protected]f2fe87c2012-04-24 17:53:49319}