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 <map>
6
7 #include "chrome/browser/chrome_notification_types.h"
8 #include "chrome/browser/extensions/extension_apitest.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/extensions/extension_system.h"
11 #include "chrome/browser/extensions/extension_test_message_listener.h"
12 #include "chrome/browser/extensions/launch_util.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_commands.h"
16 #include "chrome/browser/ui/browser_finder.h"
17 #include "chrome/browser/ui/browser_iterator.h"
18 #include "chrome/browser/ui/tabs/tab_strip_model.h"
19 #include "chrome/common/chrome_switches.h"
20 #include "chrome/common/extensions/extension_constants.h"
21 #include "content/public/test/test_utils.h"
22 #include "extensions/browser/test_management_policy.h"
23 #include "extensions/common/manifest.h"
24
25 using extensions::Extension;
26 using extensions::Manifest;
27
28 namespace {
29
30 // Find a browser other than |browser|.
FindOtherBrowser(Browser * browser)31 Browser* FindOtherBrowser(Browser* browser) {
32 Browser* found = NULL;
33 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
34 if (*it == browser)
35 continue;
36 found = *it;
37 }
38 return found;
39 }
40
41 } // namespace
42
43 class ExtensionManagementApiTest : public ExtensionApiTest {
44 public:
SetUpCommandLine(CommandLine * command_line)45 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
46 ExtensionApiTest::SetUpCommandLine(command_line);
47 command_line->AppendSwitch(switches::kEnablePanels);
48 }
49
LoadExtensions()50 virtual void LoadExtensions() {
51 base::FilePath basedir = test_data_dir_.AppendASCII("management");
52
53 // Load 5 enabled items.
54 LoadNamedExtension(basedir, "enabled_extension");
55 LoadNamedExtension(basedir, "enabled_app");
56 LoadNamedExtension(basedir, "description");
57 LoadNamedExtension(basedir, "permissions");
58 LoadNamedExtension(basedir, "short_name");
59
60 // Load 2 disabled items.
61 LoadNamedExtension(basedir, "disabled_extension");
62 DisableExtension(extension_ids_["disabled_extension"]);
63 LoadNamedExtension(basedir, "disabled_app");
64 DisableExtension(extension_ids_["disabled_app"]);
65 }
66
67 // Load an app, and wait for a message from app "management/launch_on_install"
68 // indicating that the new app has been launched.
LoadAndWaitForLaunch(const std::string & app_path,std::string * out_app_id)69 void LoadAndWaitForLaunch(const std::string& app_path,
70 std::string* out_app_id) {
71 ExtensionTestMessageListener launched_app("launched app", false);
72 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(app_path)));
73
74 if (out_app_id)
75 *out_app_id = last_loaded_extension_id();
76
77 ASSERT_TRUE(launched_app.WaitUntilSatisfied());
78 }
79
80 protected:
LoadNamedExtension(const base::FilePath & path,const std::string & name)81 void LoadNamedExtension(const base::FilePath& path,
82 const std::string& name) {
83 const Extension* extension = LoadExtension(path.AppendASCII(name));
84 ASSERT_TRUE(extension);
85 extension_ids_[name] = extension->id();
86 }
87
InstallNamedExtension(const base::FilePath & path,const std::string & name,Manifest::Location install_source)88 void InstallNamedExtension(const base::FilePath& path,
89 const std::string& name,
90 Manifest::Location install_source) {
91 const Extension* extension = InstallExtension(path.AppendASCII(name), 1,
92 install_source);
93 ASSERT_TRUE(extension);
94 extension_ids_[name] = extension->id();
95 }
96
97 // Maps installed extension names to their IDs.
98 std::map<std::string, std::string> extension_ids_;
99 };
100
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,Basics)101 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, Basics) {
102 LoadExtensions();
103
104 base::FilePath basedir = test_data_dir_.AppendASCII("management");
105 InstallNamedExtension(basedir, "internal_extension", Manifest::INTERNAL);
106 InstallNamedExtension(basedir, "external_extension",
107 Manifest::EXTERNAL_PREF);
108 InstallNamedExtension(basedir, "admin_extension",
109 Manifest::EXTERNAL_POLICY_DOWNLOAD);
110
111 ASSERT_TRUE(RunExtensionSubtest("management/test", "basics.html"));
112 }
113
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,NoPermission)114 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, NoPermission) {
115 LoadExtensions();
116 ASSERT_TRUE(RunExtensionSubtest("management/no_permission", "test.html"));
117 }
118
119 // Disabled: http://crbug.com/174411
120 #if defined(OS_WIN)
121 #define MAYBE_Uninstall DISABLED_Uninstall
122 #else
123 #define MAYBE_Uninstall Uninstall
124 #endif
125
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,MAYBE_Uninstall)126 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, MAYBE_Uninstall) {
127 LoadExtensions();
128 ASSERT_TRUE(RunExtensionSubtest("management/test", "uninstall.html"));
129 }
130
131 // Fails often on Windows dbg bots. http://crbug.com/177163
132 #if defined(OS_WIN)
133 #define MAYBE_ManagementPolicyAllowed DISABLED_ManagementPolicyAllowed
134 #else
135 #define MAYBE_ManagementPolicyAllowed ManagementPolicyAllowed
136 #endif // defined(OS_WIN)
137 // Tests actions on extensions when no management policy is in place.
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,MAYBE_ManagementPolicyAllowed)138 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,
139 MAYBE_ManagementPolicyAllowed) {
140 LoadExtensions();
141 ExtensionService* service = extensions::ExtensionSystem::Get(
142 browser()->profile())->extension_service();
143 EXPECT_TRUE(service->GetExtensionById(extension_ids_["enabled_extension"],
144 false));
145
146 // Ensure that all actions are allowed.
147 extensions::ExtensionSystem::Get(
148 browser()->profile())->management_policy()->UnregisterAllProviders();
149
150 ASSERT_TRUE(RunExtensionSubtest("management/management_policy",
151 "allowed.html"));
152 // The last thing the test does is uninstall the "enabled_extension".
153 EXPECT_FALSE(service->GetExtensionById(extension_ids_["enabled_extension"],
154 true));
155 }
156
157 // Fails often on Windows dbg bots. http://crbug.com/177163
158 #if defined(OS_WIN)
159 #define MAYBE_ManagementPolicyProhibited DISABLED_ManagementPolicyProhibited
160 #else
161 #define MAYBE_ManagementPolicyProhibited ManagementPolicyProhibited
162 #endif // defined(OS_WIN)
163 // Tests actions on extensions when management policy prohibits those actions.
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,MAYBE_ManagementPolicyProhibited)164 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,
165 MAYBE_ManagementPolicyProhibited) {
166 LoadExtensions();
167 ExtensionService* service = extensions::ExtensionSystem::Get(
168 browser()->profile())->extension_service();
169 EXPECT_TRUE(service->GetExtensionById(extension_ids_["enabled_extension"],
170 false));
171
172 // Prohibit status changes.
173 extensions::ManagementPolicy* policy = extensions::ExtensionSystem::Get(
174 browser()->profile())->management_policy();
175 policy->UnregisterAllProviders();
176 extensions::TestManagementPolicyProvider provider(
177 extensions::TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS);
178 policy->RegisterProvider(&provider);
179 ASSERT_TRUE(RunExtensionSubtest("management/management_policy",
180 "prohibited.html"));
181 }
182
183 // Disabled. See http://crbug.com/176023
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,DISABLED_LaunchPanelApp)184 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, DISABLED_LaunchPanelApp) {
185 ExtensionService* service = extensions::ExtensionSystem::Get(
186 browser()->profile())->extension_service();
187
188 // Load an extension that calls launchApp() on any app that gets
189 // installed.
190 ExtensionTestMessageListener launcher_loaded("launcher loaded", false);
191 ASSERT_TRUE(LoadExtension(
192 test_data_dir_.AppendASCII("management/launch_on_install")));
193 ASSERT_TRUE(launcher_loaded.WaitUntilSatisfied());
194
195 // Load an app with app.launch.container = "panel".
196 std::string app_id;
197 LoadAndWaitForLaunch("management/launch_app_panel", &app_id);
198 ASSERT_FALSE(HasFatalFailure()); // Stop the test if any ASSERT failed.
199
200 // Find the app's browser. Check that it is a popup.
201 ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(),
202 browser()->host_desktop_type()));
203 Browser* app_browser = FindOtherBrowser(browser());
204 ASSERT_TRUE(app_browser->is_type_popup());
205 ASSERT_TRUE(app_browser->is_app());
206
207 // Close the app panel.
208 content::WindowedNotificationObserver signal(
209 chrome::NOTIFICATION_BROWSER_CLOSED,
210 content::Source<Browser>(app_browser));
211
212 chrome::CloseWindow(app_browser);
213 signal.Wait();
214
215 // Unload the extension.
216 UninstallExtension(app_id);
217 ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
218 browser()->host_desktop_type()));
219 ASSERT_FALSE(service->GetExtensionById(app_id, true));
220
221 // Set a pref indicating that the user wants to launch in a regular tab.
222 // This should be ignored, because panel apps always load in a popup.
223 extensions::SetLaunchType(service->extension_prefs(),
224 app_id, extensions::LAUNCH_TYPE_REGULAR);
225
226 // Load the extension again.
227 std::string app_id_new;
228 LoadAndWaitForLaunch("management/launch_app_panel", &app_id_new);
229 ASSERT_FALSE(HasFatalFailure());
230
231 // If the ID changed, then the pref will not apply to the app.
232 ASSERT_EQ(app_id, app_id_new);
233
234 // Find the app's browser. Apps that should load in a panel ignore
235 // prefs, so we should still see the launch in a popup.
236 ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(),
237 browser()->host_desktop_type()));
238 app_browser = FindOtherBrowser(browser());
239 ASSERT_TRUE(app_browser->is_type_popup());
240 ASSERT_TRUE(app_browser->is_app());
241 }
242
243 // Disabled: http://crbug.com/230165
244 #if defined(OS_WIN)
245 #define MAYBE_LaunchTabApp DISABLED_LaunchTabApp
246 #else
247 #define MAYBE_LaunchTabApp LaunchTabApp
248 #endif
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,MAYBE_LaunchTabApp)249 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, MAYBE_LaunchTabApp) {
250 ExtensionService* service = extensions::ExtensionSystem::Get(
251 browser()->profile())->extension_service();
252
253 // Load an extension that calls launchApp() on any app that gets
254 // installed.
255 ExtensionTestMessageListener launcher_loaded("launcher loaded", false);
256 ASSERT_TRUE(LoadExtension(
257 test_data_dir_.AppendASCII("management/launch_on_install")));
258 ASSERT_TRUE(launcher_loaded.WaitUntilSatisfied());
259
260 // Code below assumes that the test starts with a single browser window
261 // hosting one tab.
262 ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
263 browser()->host_desktop_type()));
264 ASSERT_EQ(1, browser()->tab_strip_model()->count());
265
266 // Load an app with app.launch.container = "tab".
267 std::string app_id;
268 LoadAndWaitForLaunch("management/launch_app_tab", &app_id);
269 ASSERT_FALSE(HasFatalFailure());
270
271 // Check that the app opened in a new tab of the existing browser.
272 ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
273 browser()->host_desktop_type()));
274 ASSERT_EQ(2, browser()->tab_strip_model()->count());
275
276 // Unload the extension.
277 UninstallExtension(app_id);
278 ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
279 browser()->host_desktop_type()));
280 ASSERT_FALSE(service->GetExtensionById(app_id, true));
281
282 // Set a pref indicating that the user wants to launch in a window.
283 extensions::SetLaunchType(service->extension_prefs(),
284 app_id, extensions::LAUNCH_TYPE_WINDOW);
285
286 std::string app_id_new;
287 LoadAndWaitForLaunch("management/launch_app_tab", &app_id_new);
288 ASSERT_FALSE(HasFatalFailure());
289
290 // If the ID changed, then the pref will not apply to the app.
291 ASSERT_EQ(app_id, app_id_new);
292
293 #if defined(OS_MACOSX)
294 // App windows are not yet implemented on mac os. We should fall back
295 // to a normal tab.
296 ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
297 browser()->host_desktop_type()));
298 ASSERT_EQ(2, browser()->tab_strip_model()->count());
299 #else
300 // Find the app's browser. Opening in a new window will create
301 // a new browser.
302 ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(),
303 browser()->host_desktop_type()));
304 Browser* app_browser = FindOtherBrowser(browser());
305 ASSERT_TRUE(app_browser->is_app());
306 #endif
307 }
308