blob: fc02b551b9b0bac3ee301ea6f123241e326965b3 [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
dchengc963c7142016-04-08 03:55:225#include <memory>
[email protected]a964e112011-04-14 21:52:516#include <string>
7
8#include "base/command_line.h"
9#include "base/json/json_reader.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]af44e7fb2011-07-29 18:32:3217#include "chrome/test/base/ui_test_utils.h"
[email protected]4ca15302012-01-03 05:53:2018#include "content/public/browser/web_contents.h"
[email protected]7d478cb2012-07-24 17:19:4219#include "content/public/test/browser_test_utils.h"
[email protected]e4452d32013-11-15 23:07:4120#include "extensions/common/extension.h"
[email protected]d42c11152013-08-22 19:36:3221#include "extensions/common/manifest.h"
[email protected]f2cb3cf2013-03-21 01:40:5322#include "net/dns/mock_host_resolver.h"
nickfa2254b2015-08-07 23:27:2923#include "net/test/embedded_test_server/embedded_test_server.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
Devlin Cronin836f545d2018-05-09 00:25:0528class ChromeAppAPITest : public extensions::ExtensionBrowserTest {
jambb11ed742017-05-01 17:27:5929 void SetUpOnMainThread() override {
Devlin Cronin836f545d2018-05-09 00:25:0530 extensions::ExtensionBrowserTest::SetUpOnMainThread();
jambb11ed742017-05-01 17:27:5931 host_resolver()->AddRule("*", "127.0.0.1");
32 ASSERT_TRUE(embedded_test_server()->Start());
33 }
34
[email protected]80675fc2011-06-21 02:05:4935 protected:
[email protected]b27c3622014-03-22 00:26:5536 bool IsAppInstalledInMainFrame() {
37 return IsAppInstalledInFrame(
38 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame());
39 }
40 bool IsAppInstalledInIFrame() {
41 return IsAppInstalledInFrame(GetIFrame());
42 }
43 bool IsAppInstalledInFrame(content::RenderFrameHost* frame) {
[email protected]06bc5d92013-01-02 22:44:1344 const char kGetAppIsInstalled[] =
45 "window.domAutomationController.send(window.chrome.app.isInstalled);";
[email protected]80675fc2011-06-21 02:05:4946 bool result;
[email protected]b27c3622014-03-22 00:26:5547 CHECK(content::ExecuteScriptAndExtractBool(frame,
48 kGetAppIsInstalled,
49 &result));
[email protected]f2fe87c2012-04-24 17:53:4950 return result;
51 }
52
[email protected]b27c3622014-03-22 00:26:5553 std::string InstallStateInMainFrame() {
54 return InstallStateInFrame(
55 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame());
56 }
57 std::string InstallStateInIFrame() {
58 return InstallStateInFrame(GetIFrame());
59 }
60 std::string InstallStateInFrame(content::RenderFrameHost* frame) {
[email protected]06bc5d92013-01-02 22:44:1361 const char kGetAppInstallState[] =
62 "window.chrome.app.installState("
63 " function(s) { window.domAutomationController.send(s); });";
[email protected]f2fe87c2012-04-24 17:53:4964 std::string result;
[email protected]b27c3622014-03-22 00:26:5565 CHECK(content::ExecuteScriptAndExtractString(frame,
66 kGetAppInstallState,
67 &result));
[email protected]f2fe87c2012-04-24 17:53:4968 return result;
69 }
70
[email protected]b27c3622014-03-22 00:26:5571 std::string RunningStateInMainFrame() {
72 return RunningStateInFrame(
73 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame());
74 }
75 std::string RunningStateInIFrame() {
76 return RunningStateInFrame(GetIFrame());
77 }
78 std::string RunningStateInFrame(content::RenderFrameHost* frame) {
[email protected]06bc5d92013-01-02 22:44:1379 const char kGetAppRunningState[] =
80 "window.domAutomationController.send("
81 " window.chrome.app.runningState());";
[email protected]f2fe87c2012-04-24 17:53:4982 std::string result;
[email protected]b27c3622014-03-22 00:26:5583 CHECK(content::ExecuteScriptAndExtractString(frame,
84 kGetAppRunningState,
85 &result));
[email protected]80675fc2011-06-21 02:05:4986 return result;
87 }
88
[email protected]a964e112011-04-14 21:52:5189 private:
[email protected]b27c3622014-03-22 00:26:5590 content::RenderFrameHost* GetIFrame() {
91 return content::FrameMatchingPredicate(
92 browser()->tab_strip_model()->GetActiveWebContents(),
93 base::Bind(&content::FrameIsChildOfMainFrame));
94 }
[email protected]a964e112011-04-14 21:52:5195};
96
nickfa2254b2015-08-07 23:27:2997IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, IsInstalled) {
nickfa2254b2015-08-07 23:27:2998 GURL app_url =
99 embedded_test_server()->GetURL("app.com", "/extensions/test_file.html");
100 GURL non_app_url = embedded_test_server()->GetURL(
101 "nonapp.com", "/extensions/test_file.html");
[email protected]a964e112011-04-14 21:52:51102
[email protected]80675fc2011-06-21 02:05:49103 // Before the app is installed, app.com does not think that it is installed
104 ui_test_utils::NavigateToURL(browser(), app_url);
[email protected]b27c3622014-03-22 00:26:55105 EXPECT_FALSE(IsAppInstalledInMainFrame());
[email protected]a964e112011-04-14 21:52:51106
107 // Load an app which includes app.com in its extent.
108 const Extension* extension = LoadExtension(
109 test_data_dir_.AppendASCII("app_dot_com_app"));
110 ASSERT_TRUE(extension);
111
[email protected]80675fc2011-06-21 02:05:49112 // Even after the app is installed, the existing app.com tab is not in an
113 // app process, so chrome.app.isInstalled should return false.
[email protected]b27c3622014-03-22 00:26:55114 EXPECT_FALSE(IsAppInstalledInMainFrame());
[email protected]a964e112011-04-14 21:52:51115
116 // Test that a non-app page has chrome.app.isInstalled = false.
117 ui_test_utils::NavigateToURL(browser(), non_app_url);
[email protected]b27c3622014-03-22 00:26:55118 EXPECT_FALSE(IsAppInstalledInMainFrame());
[email protected]a964e112011-04-14 21:52:51119
120 // Test that a non-app page returns null for chrome.app.getDetails().
[email protected]06bc5d92013-01-02 22:44:13121 const char kGetAppDetails[] =
122 "window.domAutomationController.send("
123 " JSON.stringify(window.chrome.app.getDetails()));";
[email protected]80675fc2011-06-21 02:05:49124 std::string result;
[email protected]a964e112011-04-14 21:52:51125 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43126 content::ExecuteScriptAndExtractString(
[email protected]47ae23372013-01-29 01:50:48127 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13128 kGetAppDetails,
129 &result));
[email protected]a964e112011-04-14 21:52:51130 EXPECT_EQ("null", result);
131
132 // Check that an app page has chrome.app.isInstalled = true.
133 ui_test_utils::NavigateToURL(browser(), app_url);
[email protected]b27c3622014-03-22 00:26:55134 EXPECT_TRUE(IsAppInstalledInMainFrame());
[email protected]a964e112011-04-14 21:52:51135
136 // Check that an app page returns the correct result for
137 // chrome.app.getDetails().
138 ui_test_utils::NavigateToURL(browser(), app_url);
139 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43140 content::ExecuteScriptAndExtractString(
[email protected]47ae23372013-01-29 01:50:48141 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13142 kGetAppDetails,
143 &result));
dchengc963c7142016-04-08 03:55:22144 std::unique_ptr<base::DictionaryValue> app_details(
estadeb09312b2015-05-22 16:30:13145 static_cast<base::DictionaryValue*>(
olli.raula4d364162015-09-10 06:39:40146 base::JSONReader::Read(result).release()));
[email protected]953620b2011-12-04 00:55:32147 // extension->manifest() does not contain the id.
[email protected]a964e112011-04-14 21:52:51148 app_details->Remove("id", NULL);
149 EXPECT_TRUE(app_details.get());
[email protected]953620b2011-12-04 00:55:32150 EXPECT_TRUE(app_details->Equals(extension->manifest()->value()));
[email protected]a964e112011-04-14 21:52:51151
[email protected]9b3a5c22011-05-31 08:03:13152 // Try to change app.isInstalled. Should silently fail, so
153 // that isInstalled should have the initial value.
154 ASSERT_TRUE(
[email protected]b6987e02013-01-04 18:30:43155 content::ExecuteScriptAndExtractString(
[email protected]47ae23372013-01-29 01:50:48156 browser()->tab_strip_model()->GetActiveWebContents(),
[email protected]06bc5d92013-01-02 22:44:13157 "window.domAutomationController.send("
158 " function() {"
159 " var value = window.chrome.app.isInstalled;"
160 " window.chrome.app.isInstalled = !value;"
161 " if (window.chrome.app.isInstalled == value) {"
162 " return 'true';"
163 " } else {"
164 " return 'false';"
165 " }"
166 " }()"
167 ");",
168 &result));
[email protected]9b3a5c22011-05-31 08:03:13169
170 // Should not be able to alter window.chrome.app.isInstalled from javascript";
171 EXPECT_EQ("true", result);
[email protected]a964e112011-04-14 21:52:51172}
173
[email protected]f2fe87c2012-04-24 17:53:49174IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, InstallAndRunningState) {
nickfa2254b2015-08-07 23:27:29175 GURL app_url = embedded_test_server()->GetURL(
176 "app.com", "/extensions/get_app_details_for_frame.html");
177 GURL non_app_url = embedded_test_server()->GetURL(
178 "nonapp.com", "/extensions/get_app_details_for_frame.html");
[email protected]f2fe87c2012-04-24 17:53:49179
180 // Before the app is installed, app.com does not think that it is installed
181 ui_test_utils::NavigateToURL(browser(), app_url);
182
[email protected]b27c3622014-03-22 00:26:55183 EXPECT_EQ("not_installed", InstallStateInMainFrame());
184 EXPECT_EQ("cannot_run", RunningStateInMainFrame());
185 EXPECT_FALSE(IsAppInstalledInMainFrame());
[email protected]f2fe87c2012-04-24 17:53:49186
187 const Extension* extension = LoadExtension(
188 test_data_dir_.AppendASCII("app_dot_com_app"));
189 ASSERT_TRUE(extension);
190
[email protected]b27c3622014-03-22 00:26:55191 EXPECT_EQ("installed", InstallStateInMainFrame());
192 EXPECT_EQ("ready_to_run", RunningStateInMainFrame());
193 EXPECT_FALSE(IsAppInstalledInMainFrame());
[email protected]f2fe87c2012-04-24 17:53:49194
195 // Reloading the page should put the tab in an app process.
196 ui_test_utils::NavigateToURL(browser(), app_url);
[email protected]b27c3622014-03-22 00:26:55197 EXPECT_EQ("installed", InstallStateInMainFrame());
198 EXPECT_EQ("running", RunningStateInMainFrame());
199 EXPECT_TRUE(IsAppInstalledInMainFrame());
[email protected]f2fe87c2012-04-24 17:53:49200
201 // Disable the extension and verify the state.
[email protected]03d25812014-06-22 19:41:55202 ExtensionService* service = extensions::ExtensionSystem::Get(
203 browser()->profile())->extension_service();
Minh X. Nguyen45479012017-08-18 21:35:36204 service->DisableExtension(
205 extension->id(),
206 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE);
[email protected]f2fe87c2012-04-24 17:53:49207 ui_test_utils::NavigateToURL(browser(), app_url);
208
[email protected]b27c3622014-03-22 00:26:55209 EXPECT_EQ("disabled", InstallStateInMainFrame());
210 EXPECT_EQ("cannot_run", RunningStateInMainFrame());
211 EXPECT_FALSE(IsAppInstalledInMainFrame());
[email protected]f2fe87c2012-04-24 17:53:49212
[email protected]03d25812014-06-22 19:41:55213 service->EnableExtension(extension->id());
[email protected]b27c3622014-03-22 00:26:55214 EXPECT_EQ("installed", InstallStateInMainFrame());
215 EXPECT_EQ("ready_to_run", RunningStateInMainFrame());
216 EXPECT_FALSE(IsAppInstalledInMainFrame());
[email protected]f2fe87c2012-04-24 17:53:49217
218 // The non-app URL should still not be installed or running.
219 ui_test_utils::NavigateToURL(browser(), non_app_url);
220
[email protected]b27c3622014-03-22 00:26:55221 EXPECT_EQ("not_installed", InstallStateInMainFrame());
222 EXPECT_EQ("cannot_run", RunningStateInMainFrame());
223 EXPECT_FALSE(IsAppInstalledInMainFrame());
[email protected]f2fe87c2012-04-24 17:53:49224
[email protected]b27c3622014-03-22 00:26:55225 EXPECT_EQ("installed", InstallStateInIFrame());
226 EXPECT_EQ("cannot_run", RunningStateInIFrame());
Alex Moshchuke63b9e92017-10-14 00:27:22227
228 // With --site-per-process, the iframe on nonapp.com will currently swap
229 // processes and go into the hosted app process.
230 if (content::AreAllSitesIsolatedForTesting())
231 EXPECT_TRUE(IsAppInstalledInIFrame());
232 else
233 EXPECT_FALSE(IsAppInstalledInIFrame());
[email protected]f2fe87c2012-04-24 17:53:49234}
235
236IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, InstallAndRunningStateFrame) {
nickfa2254b2015-08-07 23:27:29237 GURL app_url = embedded_test_server()->GetURL(
238 "app.com", "/extensions/get_app_details_for_frame_reversed.html");
[email protected]f2fe87c2012-04-24 17:53:49239
240 // Check the install and running state of a non-app iframe running
241 // within an app.
242 ui_test_utils::NavigateToURL(browser(), app_url);
243
[email protected]b27c3622014-03-22 00:26:55244 EXPECT_EQ("not_installed", InstallStateInIFrame());
245 EXPECT_EQ("cannot_run", RunningStateInIFrame());
246 EXPECT_FALSE(IsAppInstalledInIFrame());
[email protected]f2fe87c2012-04-24 17:53:49247}