blob: 1c5e417e73207b3e0b8b77cbfdf5ac978a7fc45b [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]af44e7fb2011-07-29 18:32:3219#include "chrome/test/base/ui_test_utils.h"
[email protected]4ca15302012-01-03 05:53:2020#include "content/public/browser/web_contents.h"
[email protected]7d478cb2012-07-24 17:19:4221#include "content/public/test/browser_test_utils.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]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
[email protected]89117c42013-05-07 16:47:2582// Flaky http://crbug.com/238674
83#if defined(OS_WIN)
84#define MAYBE_IsInstalled DISABLED_IsInstalled
85#else
86#define MAYBE_IsInstalled IsInstalled
87#endif
88IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, MAYBE_IsInstalled) {
[email protected]a964e112011-04-14 21:52:5189 std::string app_host("app.com");
90 std::string nonapp_host("nonapp.com");
91
92 host_resolver()->AddRule(app_host, "127.0.0.1");
93 host_resolver()->AddRule(nonapp_host, "127.0.0.1");
94 ASSERT_TRUE(test_server()->Start());
95
96 GURL test_file_url(test_server()->GetURL("extensions/test_file.html"));
97 GURL::Replacements replace_host;
98
99 replace_host.SetHostStr(app_host);
100 GURL app_url(test_file_url.ReplaceComponents(replace_host));
101
102 replace_host.SetHostStr(nonapp_host);
103 GURL non_app_url(test_file_url.ReplaceComponents(replace_host));
104
[email protected]80675fc2011-06-21 02:05:49105 // Before the app is installed, app.com does not think that it is installed
106 ui_test_utils::NavigateToURL(browser(), app_url);
107 EXPECT_FALSE(IsAppInstalled());
[email protected]a964e112011-04-14 21:52:51108
109 // Load an app which includes app.com in its extent.
110 const Extension* extension = LoadExtension(
111 test_data_dir_.AppendASCII("app_dot_com_app"));
112 ASSERT_TRUE(extension);
113
[email protected]80675fc2011-06-21 02:05:49114 // Even after the app is installed, the existing app.com tab is not in an
115 // app process, so chrome.app.isInstalled should return false.
116 EXPECT_FALSE(IsAppInstalled());
[email protected]a964e112011-04-14 21:52:51117
118 // Test that a non-app page has chrome.app.isInstalled = false.
119 ui_test_utils::NavigateToURL(browser(), non_app_url);
[email protected]80675fc2011-06-21 02:05:49120 EXPECT_FALSE(IsAppInstalled());
[email protected]a964e112011-04-14 21:52:51121
122 // Test that a non-app page returns null for chrome.app.getDetails().
[email protected]06bc5d92013-01-02 22:44:13123 const char kGetAppDetails[] =
124 "window.domAutomationController.send("
125 " JSON.stringify(window.chrome.app.getDetails()));";
[email protected]80675fc2011-06-21 02:05:49126 std::string result;
[email protected]a964e112011-04-14 21:52:51127 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43128 content::ExecuteScriptAndExtractString(
[email protected]47ae23372013-01-29 01:50:48129 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13130 kGetAppDetails,
131 &result));
[email protected]a964e112011-04-14 21:52:51132 EXPECT_EQ("null", result);
133
134 // Check that an app page has chrome.app.isInstalled = true.
135 ui_test_utils::NavigateToURL(browser(), app_url);
[email protected]80675fc2011-06-21 02:05:49136 EXPECT_TRUE(IsAppInstalled());
[email protected]a964e112011-04-14 21:52:51137
138 // Check that an app page returns the correct result for
139 // chrome.app.getDetails().
140 ui_test_utils::NavigateToURL(browser(), app_url);
141 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43142 content::ExecuteScriptAndExtractString(
[email protected]47ae23372013-01-29 01:50:48143 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13144 kGetAppDetails,
145 &result));
[email protected]a964e112011-04-14 21:52:51146 scoped_ptr<DictionaryValue> app_details(
[email protected]cd5785752012-04-11 00:15:41147 static_cast<DictionaryValue*>(base::JSONReader::Read(result)));
[email protected]953620b2011-12-04 00:55:32148 // extension->manifest() does not contain the id.
[email protected]a964e112011-04-14 21:52:51149 app_details->Remove("id", NULL);
150 EXPECT_TRUE(app_details.get());
[email protected]953620b2011-12-04 00:55:32151 EXPECT_TRUE(app_details->Equals(extension->manifest()->value()));
[email protected]a964e112011-04-14 21:52:51152
[email protected]9b3a5c22011-05-31 08:03:13153 // Try to change app.isInstalled. Should silently fail, so
154 // that isInstalled should have the initial value.
155 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43156 content::ExecuteScriptAndExtractString(
[email protected]47ae23372013-01-29 01:50:48157 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13158 "window.domAutomationController.send("
159 " function() {"
160 " var value = window.chrome.app.isInstalled;"
161 " window.chrome.app.isInstalled = !value;"
162 " if (window.chrome.app.isInstalled == value) {"
163 " return 'true';"
164 " } else {"
165 " return 'false';"
166 " }"
167 " }()"
168 ");",
169 &result));
[email protected]9b3a5c22011-05-31 08:03:13170
171 // Should not be able to alter window.chrome.app.isInstalled from javascript";
172 EXPECT_EQ("true", result);
[email protected]a964e112011-04-14 21:52:51173}
174
175IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, GetDetailsForFrame) {
176 std::string app_host("app.com");
177 std::string nonapp_host("nonapp.com");
178 std::string checkout_host("checkout.com");
179
180 host_resolver()->AddRule(app_host, "127.0.0.1");
181 host_resolver()->AddRule(nonapp_host, "127.0.0.1");
182 host_resolver()->AddRule(checkout_host, "127.0.0.1");
183 ASSERT_TRUE(test_server()->Start());
184
185 GURL test_file_url(test_server()->GetURL(
186 "files/extensions/get_app_details_for_frame.html"));
187 GURL::Replacements replace_host;
188
189 replace_host.SetHostStr(checkout_host);
190 GURL checkout_url(test_file_url.ReplaceComponents(replace_host));
191
192 replace_host.SetHostStr(app_host);
193 GURL app_url(test_file_url.ReplaceComponents(replace_host));
194
195 // Load an app which includes app.com in its extent.
196 const Extension* extension = LoadExtension(
197 test_data_dir_.AppendASCII("app_dot_com_app"));
198 ASSERT_TRUE(extension);
199
200 // Test that normal pages (even apps) cannot use getDetailsForFrame().
201 ui_test_utils::NavigateToURL(browser(), app_url);
[email protected]06bc5d92013-01-02 22:44:13202 const char kTestUnsuccessfulAccess[] =
203 "window.domAutomationController.send(window.testUnsuccessfulAccess())";
[email protected]a964e112011-04-14 21:52:51204 bool result = false;
205 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43206 content::ExecuteScriptAndExtractBool(
[email protected]47ae23372013-01-29 01:50:48207 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13208 kTestUnsuccessfulAccess,
209 &result));
[email protected]a964e112011-04-14 21:52:51210 EXPECT_TRUE(result);
211
212 // Test that checkout can use getDetailsForFrame() and that it works
213 // correctly.
214 ui_test_utils::NavigateToURL(browser(), checkout_url);
[email protected]06bc5d92013-01-02 22:44:13215 const char kGetDetailsForFrame[] =
216 "window.domAutomationController.send("
217 " JSON.stringify(chrome.app.getDetailsForFrame(frames[0])))";
[email protected]a964e112011-04-14 21:52:51218 std::string json;
219 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43220 content::ExecuteScriptAndExtractString(
[email protected]47ae23372013-01-29 01:50:48221 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13222 kGetDetailsForFrame,
223 &json));
[email protected]a964e112011-04-14 21:52:51224
225 scoped_ptr<DictionaryValue> app_details(
[email protected]cd5785752012-04-11 00:15:41226 static_cast<DictionaryValue*>(base::JSONReader::Read(json)));
[email protected]953620b2011-12-04 00:55:32227 // extension->manifest() does not contain the id.
[email protected]a964e112011-04-14 21:52:51228 app_details->Remove("id", NULL);
229 EXPECT_TRUE(app_details.get());
[email protected]953620b2011-12-04 00:55:32230 EXPECT_TRUE(app_details->Equals(extension->manifest()->value()));
[email protected]a964e112011-04-14 21:52:51231}
[email protected]f2fe87c2012-04-24 17:53:49232
233
234IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, InstallAndRunningState) {
235 std::string app_host("app.com");
236 std::string non_app_host("nonapp.com");
237
238 host_resolver()->AddRule(app_host, "127.0.0.1");
239 host_resolver()->AddRule(non_app_host, "127.0.0.1");
240 ASSERT_TRUE(test_server()->Start());
241
242 GURL test_file_url(test_server()->GetURL(
243 "files/extensions/get_app_details_for_frame.html"));
244 GURL::Replacements replace_host;
245
246 replace_host.SetHostStr(app_host);
247 GURL app_url(test_file_url.ReplaceComponents(replace_host));
248
249 replace_host.SetHostStr(non_app_host);
250 GURL non_app_url(test_file_url.ReplaceComponents(replace_host));
251
252 // Before the app is installed, app.com does not think that it is installed
253 ui_test_utils::NavigateToURL(browser(), app_url);
254
255 EXPECT_EQ("not_installed", InstallState());
256 EXPECT_EQ("cannot_run", RunningState());
257 EXPECT_FALSE(IsAppInstalled());
258
259 const Extension* extension = LoadExtension(
260 test_data_dir_.AppendASCII("app_dot_com_app"));
261 ASSERT_TRUE(extension);
262
263 EXPECT_EQ("installed", InstallState());
264 EXPECT_EQ("ready_to_run", RunningState());
265 EXPECT_FALSE(IsAppInstalled());
266
267 // Reloading the page should put the tab in an app process.
268 ui_test_utils::NavigateToURL(browser(), app_url);
269 EXPECT_EQ("installed", InstallState());
270 EXPECT_EQ("running", RunningState());
271 EXPECT_TRUE(IsAppInstalled());
272
273 // Disable the extension and verify the state.
274 browser()->profile()->GetExtensionService()->DisableExtension(
275 extension->id(), Extension::DISABLE_PERMISSIONS_INCREASE);
276 ui_test_utils::NavigateToURL(browser(), app_url);
277
278 EXPECT_EQ("disabled", InstallState());
279 EXPECT_EQ("cannot_run", RunningState());
280 EXPECT_FALSE(IsAppInstalled());
281
282 browser()->profile()->GetExtensionService()->EnableExtension(extension->id());
283 EXPECT_EQ("installed", InstallState());
284 EXPECT_EQ("ready_to_run", RunningState());
285 EXPECT_FALSE(IsAppInstalled());
286
287 // The non-app URL should still not be installed or running.
288 ui_test_utils::NavigateToURL(browser(), non_app_url);
289
290 EXPECT_EQ("not_installed", InstallState());
291 EXPECT_EQ("cannot_run", RunningState());
292 EXPECT_FALSE(IsAppInstalled());
293
[email protected]06bc5d92013-01-02 22:44:13294 EXPECT_EQ("installed", InstallState("//html/iframe[1]"));
295 EXPECT_EQ("cannot_run", RunningState("//html/iframe[1]"));
296 EXPECT_FALSE(IsAppInstalled("//html/iframe[1]"));
[email protected]f2fe87c2012-04-24 17:53:49297
298}
299
300IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, InstallAndRunningStateFrame) {
301 std::string app_host("app.com");
302 std::string non_app_host("nonapp.com");
303
304 host_resolver()->AddRule(app_host, "127.0.0.1");
305 host_resolver()->AddRule(non_app_host, "127.0.0.1");
306 ASSERT_TRUE(test_server()->Start());
307
308 GURL test_file_url(test_server()->GetURL(
309 "files/extensions/get_app_details_for_frame_reversed.html"));
310 GURL::Replacements replace_host;
311
312 replace_host.SetHostStr(app_host);
313 GURL app_url(test_file_url.ReplaceComponents(replace_host));
314
315 replace_host.SetHostStr(non_app_host);
316 GURL non_app_url(test_file_url.ReplaceComponents(replace_host));
317
318 // Check the install and running state of a non-app iframe running
319 // within an app.
320 ui_test_utils::NavigateToURL(browser(), app_url);
321
[email protected]06bc5d92013-01-02 22:44:13322 EXPECT_EQ("not_installed", InstallState("//html/iframe[1]"));
323 EXPECT_EQ("cannot_run", RunningState("//html/iframe[1]"));
324 EXPECT_FALSE(IsAppInstalled("//html/iframe[1]"));
[email protected]f2fe87c2012-04-24 17:53:49325}