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