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/test/base/ui_test_utils.h"
18 #include "content/public/browser/web_contents.h"
19 #include "content/public/test/browser_test_utils.h"
20 #include "extensions/common/extension.h"
21 #include "extensions/common/manifest.h"
22 #include "net/dns/mock_host_resolver.h"
23 #include "net/test/embedded_test_server/embedded_test_server.h"
26 using extensions::Extension
;
28 class ChromeAppAPITest
: public ExtensionBrowserTest
{
30 bool IsAppInstalledInMainFrame() {
31 return IsAppInstalledInFrame(
32 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame());
34 bool IsAppInstalledInIFrame() {
35 return IsAppInstalledInFrame(GetIFrame());
37 bool IsAppInstalledInFrame(content::RenderFrameHost
* frame
) {
38 const char kGetAppIsInstalled
[] =
39 "window.domAutomationController.send(window.chrome.app.isInstalled);";
41 CHECK(content::ExecuteScriptAndExtractBool(frame
,
47 std::string
InstallStateInMainFrame() {
48 return InstallStateInFrame(
49 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame());
51 std::string
InstallStateInIFrame() {
52 return InstallStateInFrame(GetIFrame());
54 std::string
InstallStateInFrame(content::RenderFrameHost
* frame
) {
55 const char kGetAppInstallState
[] =
56 "window.chrome.app.installState("
57 " function(s) { window.domAutomationController.send(s); });";
59 CHECK(content::ExecuteScriptAndExtractString(frame
,
65 std::string
RunningStateInMainFrame() {
66 return RunningStateInFrame(
67 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame());
69 std::string
RunningStateInIFrame() {
70 return RunningStateInFrame(GetIFrame());
72 std::string
RunningStateInFrame(content::RenderFrameHost
* frame
) {
73 const char kGetAppRunningState
[] =
74 "window.domAutomationController.send("
75 " window.chrome.app.runningState());";
77 CHECK(content::ExecuteScriptAndExtractString(frame
,
84 content::RenderFrameHost
* GetIFrame() {
85 return content::FrameMatchingPredicate(
86 browser()->tab_strip_model()->GetActiveWebContents(),
87 base::Bind(&content::FrameIsChildOfMainFrame
));
91 IN_PROC_BROWSER_TEST_F(ChromeAppAPITest
, IsInstalled
) {
92 host_resolver()->AddRule("*", "127.0.0.1");
93 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
95 embedded_test_server()->GetURL("app.com", "/extensions/test_file.html");
96 GURL non_app_url
= embedded_test_server()->GetURL(
97 "nonapp.com", "/extensions/test_file.html");
99 // 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(IsAppInstalledInMainFrame());
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
);
108 // 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(IsAppInstalledInMainFrame());
112 // Test that a non-app page has chrome.app.isInstalled = false.
113 ui_test_utils::NavigateToURL(browser(), non_app_url
);
114 EXPECT_FALSE(IsAppInstalledInMainFrame());
116 // Test that a non-app page returns null for chrome.app.getDetails().
117 const char kGetAppDetails
[] =
118 "window.domAutomationController.send("
119 " JSON.stringify(window.chrome.app.getDetails()));";
122 content::ExecuteScriptAndExtractString(
123 browser()->tab_strip_model()->GetActiveWebContents(),
126 EXPECT_EQ("null", result
);
128 // Check that an app page has chrome.app.isInstalled = true.
129 ui_test_utils::NavigateToURL(browser(), app_url
);
130 EXPECT_TRUE(IsAppInstalledInMainFrame());
132 // Check that an app page returns the correct result for
133 // chrome.app.getDetails().
134 ui_test_utils::NavigateToURL(browser(), app_url
);
136 content::ExecuteScriptAndExtractString(
137 browser()->tab_strip_model()->GetActiveWebContents(),
140 scoped_ptr
<base::DictionaryValue
> app_details(
141 static_cast<base::DictionaryValue
*>(
142 base::JSONReader::Read(result
).release()));
143 // extension->manifest() does not contain the id.
144 app_details
->Remove("id", NULL
);
145 EXPECT_TRUE(app_details
.get());
146 EXPECT_TRUE(app_details
->Equals(extension
->manifest()->value()));
148 // Try to change app.isInstalled. Should silently fail, so
149 // that isInstalled should have the initial value.
151 content::ExecuteScriptAndExtractString(
152 browser()->tab_strip_model()->GetActiveWebContents(),
153 "window.domAutomationController.send("
155 " var value = window.chrome.app.isInstalled;"
156 " window.chrome.app.isInstalled = !value;"
157 " if (window.chrome.app.isInstalled == value) {"
166 // Should not be able to alter window.chrome.app.isInstalled from javascript";
167 EXPECT_EQ("true", result
);
170 IN_PROC_BROWSER_TEST_F(ChromeAppAPITest
, InstallAndRunningState
) {
171 host_resolver()->AddRule("*", "127.0.0.1");
172 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
173 GURL app_url
= embedded_test_server()->GetURL(
174 "app.com", "/extensions/get_app_details_for_frame.html");
175 GURL non_app_url
= embedded_test_server()->GetURL(
176 "nonapp.com", "/extensions/get_app_details_for_frame.html");
178 // Before the app is installed, app.com does not think that it is installed
179 ui_test_utils::NavigateToURL(browser(), app_url
);
181 EXPECT_EQ("not_installed", InstallStateInMainFrame());
182 EXPECT_EQ("cannot_run", RunningStateInMainFrame());
183 EXPECT_FALSE(IsAppInstalledInMainFrame());
185 const Extension
* extension
= LoadExtension(
186 test_data_dir_
.AppendASCII("app_dot_com_app"));
187 ASSERT_TRUE(extension
);
189 EXPECT_EQ("installed", InstallStateInMainFrame());
190 EXPECT_EQ("ready_to_run", RunningStateInMainFrame());
191 EXPECT_FALSE(IsAppInstalledInMainFrame());
193 // Reloading the page should put the tab in an app process.
194 ui_test_utils::NavigateToURL(browser(), app_url
);
195 EXPECT_EQ("installed", InstallStateInMainFrame());
196 EXPECT_EQ("running", RunningStateInMainFrame());
197 EXPECT_TRUE(IsAppInstalledInMainFrame());
199 // Disable the extension and verify the state.
200 ExtensionService
* service
= extensions::ExtensionSystem::Get(
201 browser()->profile())->extension_service();
202 service
->DisableExtension(extension
->id(),
203 Extension::DISABLE_PERMISSIONS_INCREASE
);
204 ui_test_utils::NavigateToURL(browser(), app_url
);
206 EXPECT_EQ("disabled", InstallStateInMainFrame());
207 EXPECT_EQ("cannot_run", RunningStateInMainFrame());
208 EXPECT_FALSE(IsAppInstalledInMainFrame());
210 service
->EnableExtension(extension
->id());
211 EXPECT_EQ("installed", InstallStateInMainFrame());
212 EXPECT_EQ("ready_to_run", RunningStateInMainFrame());
213 EXPECT_FALSE(IsAppInstalledInMainFrame());
215 // The non-app URL should still not be installed or running.
216 ui_test_utils::NavigateToURL(browser(), non_app_url
);
218 EXPECT_EQ("not_installed", InstallStateInMainFrame());
219 EXPECT_EQ("cannot_run", RunningStateInMainFrame());
220 EXPECT_FALSE(IsAppInstalledInMainFrame());
222 EXPECT_EQ("installed", InstallStateInIFrame());
223 EXPECT_EQ("cannot_run", RunningStateInIFrame());
224 EXPECT_FALSE(IsAppInstalledInIFrame());
227 IN_PROC_BROWSER_TEST_F(ChromeAppAPITest
, InstallAndRunningStateFrame
) {
228 host_resolver()->AddRule("*", "127.0.0.1");
229 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
230 GURL app_url
= embedded_test_server()->GetURL(
231 "app.com", "/extensions/get_app_details_for_frame_reversed.html");
233 // Check the install and running state of a non-app iframe running
235 ui_test_utils::NavigateToURL(browser(), app_url
);
237 EXPECT_EQ("not_installed", InstallStateInIFrame());
238 EXPECT_EQ("cannot_run", RunningStateInIFrame());
239 EXPECT_FALSE(IsAppInstalledInIFrame());