• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include <string>
6 
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"
24 #include "url/gurl.h"
25 
26 using extensions::Extension;
27 
28 class ChromeAppAPITest : public ExtensionBrowserTest {
29  protected:
IsAppInstalled()30   bool IsAppInstalled() { return IsAppInstalled(""); }
IsAppInstalled(const char * frame_xpath)31   bool IsAppInstalled(const char* frame_xpath) {
32     const char kGetAppIsInstalled[] =
33         "window.domAutomationController.send(window.chrome.app.isInstalled);";
34     bool result;
35     CHECK(
36         content::ExecuteScriptInFrameAndExtractBool(
37             browser()->tab_strip_model()->GetActiveWebContents(),
38             frame_xpath,
39             kGetAppIsInstalled,
40             &result));
41     return result;
42   }
43 
InstallState()44   std::string InstallState() { return InstallState(""); }
InstallState(const char * frame_xpath)45   std::string InstallState(const char* frame_xpath) {
46     const char kGetAppInstallState[] =
47         "window.chrome.app.installState("
48         "    function(s) { window.domAutomationController.send(s); });";
49     std::string result;
50     CHECK(
51         content::ExecuteScriptInFrameAndExtractString(
52             browser()->tab_strip_model()->GetActiveWebContents(),
53             frame_xpath,
54             kGetAppInstallState,
55             &result));
56     return result;
57   }
58 
RunningState()59   std::string RunningState() { return RunningState(""); }
RunningState(const char * frame_xpath)60   std::string RunningState(const char* frame_xpath) {
61     const char kGetAppRunningState[] =
62         "window.domAutomationController.send("
63         "    window.chrome.app.runningState());";
64     std::string result;
65     CHECK(
66         content::ExecuteScriptInFrameAndExtractString(
67             browser()->tab_strip_model()->GetActiveWebContents(),
68             frame_xpath,
69             kGetAppRunningState,
70             &result));
71     return result;
72   }
73 
74  private:
SetUpCommandLine(CommandLine * command_line)75   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
76     ExtensionBrowserTest::SetUpCommandLine(command_line);
77     command_line->AppendSwitchASCII(switches::kAppsCheckoutURL,
78                                     "http://checkout.com:");
79   }
80 };
81 
82 // 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
IN_PROC_BROWSER_TEST_F(ChromeAppAPITest,MAYBE_IsInstalled)88 IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, MAYBE_IsInstalled) {
89   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 
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());
108 
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 
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());
117 
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());
121 
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()));";
126   std::string result;
127   ASSERT_TRUE(
128       content::ExecuteScriptAndExtractString(
129           browser()->tab_strip_model()->GetActiveWebContents(),
130           kGetAppDetails,
131           &result));
132   EXPECT_EQ("null", result);
133 
134   // Check that an app page has chrome.app.isInstalled = true.
135   ui_test_utils::NavigateToURL(browser(), app_url);
136   EXPECT_TRUE(IsAppInstalled());
137 
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(
142       content::ExecuteScriptAndExtractString(
143           browser()->tab_strip_model()->GetActiveWebContents(),
144           kGetAppDetails,
145           &result));
146   scoped_ptr<DictionaryValue> app_details(
147       static_cast<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()));
152 
153   // Try to change app.isInstalled.  Should silently fail, so
154   // that isInstalled should have the initial value.
155   ASSERT_TRUE(
156       content::ExecuteScriptAndExtractString(
157           browser()->tab_strip_model()->GetActiveWebContents(),
158           "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));
170 
171   // Should not be able to alter window.chrome.app.isInstalled from javascript";
172   EXPECT_EQ("true", result);
173 }
174 
IN_PROC_BROWSER_TEST_F(ChromeAppAPITest,GetDetailsForFrame)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");
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);
202   const char kTestUnsuccessfulAccess[] =
203       "window.domAutomationController.send(window.testUnsuccessfulAccess())";
204   bool result = false;
205   ASSERT_TRUE(
206       content::ExecuteScriptAndExtractBool(
207           browser()->tab_strip_model()->GetActiveWebContents(),
208           kTestUnsuccessfulAccess,
209           &result));
210   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);
215   const char kGetDetailsForFrame[] =
216       "window.domAutomationController.send("
217       "    JSON.stringify(chrome.app.getDetailsForFrame(frames[0])))";
218   std::string json;
219   ASSERT_TRUE(
220       content::ExecuteScriptAndExtractString(
221           browser()->tab_strip_model()->GetActiveWebContents(),
222           kGetDetailsForFrame,
223           &json));
224 
225   scoped_ptr<DictionaryValue> app_details(
226       static_cast<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()));
231 }
232 
233 
IN_PROC_BROWSER_TEST_F(ChromeAppAPITest,InstallAndRunningState)234 IN_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 
294   EXPECT_EQ("installed", InstallState("//html/iframe[1]"));
295   EXPECT_EQ("cannot_run", RunningState("//html/iframe[1]"));
296   EXPECT_FALSE(IsAppInstalled("//html/iframe[1]"));
297 
298 }
299 
IN_PROC_BROWSER_TEST_F(ChromeAppAPITest,InstallAndRunningStateFrame)300 IN_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 
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]"));
325 }
326