1 // Copyright (c) 2012 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.
7 #include "base/command_line.h"
8 #include "base/json/json_reader.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/values.h"
12 #include "chrome/browser/extensions/extension_browsertest.h"
13 #include "chrome/browser/extensions/extension_service.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/test/base/ui_test_utils.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/test/browser_test_utils.h"
21 #include "extensions/common/extension.h"
22 #include "extensions/common/manifest.h"
23 #include "net/dns/mock_host_resolver.h"
26 using extensions::Extension
;
28 class ChromeAppAPITest
: public ExtensionBrowserTest
{
30 bool IsAppInstalled() { return IsAppInstalled(""); }
31 bool IsAppInstalled(const char* frame_xpath
) {
32 const char kGetAppIsInstalled
[] =
33 "window.domAutomationController.send(window.chrome.app.isInstalled);";
36 content::ExecuteScriptInFrameAndExtractBool(
37 browser()->tab_strip_model()->GetActiveWebContents(),
44 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); });";
51 content::ExecuteScriptInFrameAndExtractString(
52 browser()->tab_strip_model()->GetActiveWebContents(),
59 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());";
66 content::ExecuteScriptInFrameAndExtractString(
67 browser()->tab_strip_model()->GetActiveWebContents(),
75 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
76 ExtensionBrowserTest::SetUpCommandLine(command_line
);
77 command_line
->AppendSwitchASCII(switches::kAppsCheckoutURL
,
78 "http://checkout.com:");
82 // Flaky http://crbug.com/238674
84 #define MAYBE_IsInstalled DISABLED_IsInstalled
86 #define MAYBE_IsInstalled IsInstalled
88 IN_PROC_BROWSER_TEST_F(ChromeAppAPITest
, MAYBE_IsInstalled
) {
89 std::string
app_host("app.com");
90 std::string
nonapp_host("nonapp.com");
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());
96 GURL
test_file_url(test_server()->GetURL("extensions/test_file.html"));
97 GURL::Replacements replace_host
;
99 replace_host
.SetHostStr(app_host
);
100 GURL
app_url(test_file_url
.ReplaceComponents(replace_host
));
102 replace_host
.SetHostStr(nonapp_host
);
103 GURL
non_app_url(test_file_url
.ReplaceComponents(replace_host
));
105 // 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());
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
);
114 // 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());
118 // Test that a non-app page has chrome.app.isInstalled = false.
119 ui_test_utils::NavigateToURL(browser(), non_app_url
);
120 EXPECT_FALSE(IsAppInstalled());
122 // Test that a non-app page returns null for chrome.app.getDetails().
123 const char kGetAppDetails
[] =
124 "window.domAutomationController.send("
125 " JSON.stringify(window.chrome.app.getDetails()));";
128 content::ExecuteScriptAndExtractString(
129 browser()->tab_strip_model()->GetActiveWebContents(),
132 EXPECT_EQ("null", result
);
134 // Check that an app page has chrome.app.isInstalled = true.
135 ui_test_utils::NavigateToURL(browser(), app_url
);
136 EXPECT_TRUE(IsAppInstalled());
138 // Check that an app page returns the correct result for
139 // chrome.app.getDetails().
140 ui_test_utils::NavigateToURL(browser(), app_url
);
142 content::ExecuteScriptAndExtractString(
143 browser()->tab_strip_model()->GetActiveWebContents(),
146 scoped_ptr
<base::DictionaryValue
> app_details(
147 static_cast<base::DictionaryValue
*>(base::JSONReader::Read(result
)));
148 // extension->manifest() does not contain the id.
149 app_details
->Remove("id", NULL
);
150 EXPECT_TRUE(app_details
.get());
151 EXPECT_TRUE(app_details
->Equals(extension
->manifest()->value()));
153 // Try to change app.isInstalled. Should silently fail, so
154 // that isInstalled should have the initial value.
156 content::ExecuteScriptAndExtractString(
157 browser()->tab_strip_model()->GetActiveWebContents(),
158 "window.domAutomationController.send("
160 " var value = window.chrome.app.isInstalled;"
161 " window.chrome.app.isInstalled = !value;"
162 " if (window.chrome.app.isInstalled == value) {"
171 // Should not be able to alter window.chrome.app.isInstalled from javascript";
172 EXPECT_EQ("true", result
);
175 IN_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");
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());
185 GURL
test_file_url(test_server()->GetURL(
186 "files/extensions/get_app_details_for_frame.html"));
187 GURL::Replacements replace_host
;
189 replace_host
.SetHostStr(checkout_host
);
190 GURL
checkout_url(test_file_url
.ReplaceComponents(replace_host
));
192 replace_host
.SetHostStr(app_host
);
193 GURL
app_url(test_file_url
.ReplaceComponents(replace_host
));
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
);
200 // Test that normal pages (even apps) cannot use getDetailsForFrame().
201 ui_test_utils::NavigateToURL(browser(), app_url
);
202 const char kTestUnsuccessfulAccess
[] =
203 "window.domAutomationController.send(window.testUnsuccessfulAccess())";
206 content::ExecuteScriptAndExtractBool(
207 browser()->tab_strip_model()->GetActiveWebContents(),
208 kTestUnsuccessfulAccess
,
212 // Test that checkout can use getDetailsForFrame() and that it works
214 ui_test_utils::NavigateToURL(browser(), checkout_url
);
215 const char kGetDetailsForFrame
[] =
216 "window.domAutomationController.send("
217 " JSON.stringify(chrome.app.getDetailsForFrame(frames[0])))";
220 content::ExecuteScriptAndExtractString(
221 browser()->tab_strip_model()->GetActiveWebContents(),
225 scoped_ptr
<base::DictionaryValue
> app_details(
226 static_cast<base::DictionaryValue
*>(base::JSONReader::Read(json
)));
227 // extension->manifest() does not contain the id.
228 app_details
->Remove("id", NULL
);
229 EXPECT_TRUE(app_details
.get());
230 EXPECT_TRUE(app_details
->Equals(extension
->manifest()->value()));
234 IN_PROC_BROWSER_TEST_F(ChromeAppAPITest
, InstallAndRunningState
) {
235 std::string
app_host("app.com");
236 std::string
non_app_host("nonapp.com");
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());
242 GURL
test_file_url(test_server()->GetURL(
243 "files/extensions/get_app_details_for_frame.html"));
244 GURL::Replacements replace_host
;
246 replace_host
.SetHostStr(app_host
);
247 GURL
app_url(test_file_url
.ReplaceComponents(replace_host
));
249 replace_host
.SetHostStr(non_app_host
);
250 GURL
non_app_url(test_file_url
.ReplaceComponents(replace_host
));
252 // Before the app is installed, app.com does not think that it is installed
253 ui_test_utils::NavigateToURL(browser(), app_url
);
255 EXPECT_EQ("not_installed", InstallState());
256 EXPECT_EQ("cannot_run", RunningState());
257 EXPECT_FALSE(IsAppInstalled());
259 const Extension
* extension
= LoadExtension(
260 test_data_dir_
.AppendASCII("app_dot_com_app"));
261 ASSERT_TRUE(extension
);
263 EXPECT_EQ("installed", InstallState());
264 EXPECT_EQ("ready_to_run", RunningState());
265 EXPECT_FALSE(IsAppInstalled());
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());
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
);
278 EXPECT_EQ("disabled", InstallState());
279 EXPECT_EQ("cannot_run", RunningState());
280 EXPECT_FALSE(IsAppInstalled());
282 browser()->profile()->GetExtensionService()->EnableExtension(extension
->id());
283 EXPECT_EQ("installed", InstallState());
284 EXPECT_EQ("ready_to_run", RunningState());
285 EXPECT_FALSE(IsAppInstalled());
287 // The non-app URL should still not be installed or running.
288 ui_test_utils::NavigateToURL(browser(), non_app_url
);
290 EXPECT_EQ("not_installed", InstallState());
291 EXPECT_EQ("cannot_run", RunningState());
292 EXPECT_FALSE(IsAppInstalled());
294 EXPECT_EQ("installed", InstallState("//html/iframe[1]"));
295 EXPECT_EQ("cannot_run", RunningState("//html/iframe[1]"));
296 EXPECT_FALSE(IsAppInstalled("//html/iframe[1]"));
300 IN_PROC_BROWSER_TEST_F(ChromeAppAPITest
, InstallAndRunningStateFrame
) {
301 std::string
app_host("app.com");
302 std::string
non_app_host("nonapp.com");
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());
308 GURL
test_file_url(test_server()->GetURL(
309 "files/extensions/get_app_details_for_frame_reversed.html"));
310 GURL::Replacements replace_host
;
312 replace_host
.SetHostStr(app_host
);
313 GURL
app_url(test_file_url
.ReplaceComponents(replace_host
));
315 replace_host
.SetHostStr(non_app_host
);
316 GURL
non_app_url(test_file_url
.ReplaceComponents(replace_host
));
318 // Check the install and running state of a non-app iframe running
320 ui_test_utils::NavigateToURL(browser(), app_url
);
322 EXPECT_EQ("not_installed", InstallState("//html/iframe[1]"));
323 EXPECT_EQ("cannot_run", RunningState("//html/iframe[1]"));
324 EXPECT_FALSE(IsAppInstalled("//html/iframe[1]"));