management_apitest.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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// Fails often on Windows dbg bots. http://crbug.com/177163
124#if defined(OS_WIN)
125#define MAYBE_ManagementPolicyAllowed DISABLED_ManagementPolicyAllowed
126#else
127#define MAYBE_ManagementPolicyAllowed ManagementPolicyAllowed
128#endif  // defined(OS_WIN)
129// Tests actions on extensions when no management policy is in place.
130IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,
131                       MAYBE_ManagementPolicyAllowed) {
132  LoadExtensions();
133  ExtensionService* service = extensions::ExtensionSystem::Get(
134      browser()->profile())->extension_service();
135  EXPECT_TRUE(service->GetExtensionById(extension_ids_["enabled_extension"],
136                                        false));
137
138  // Ensure that all actions are allowed.
139  extensions::ExtensionSystem::Get(
140      browser()->profile())->management_policy()->UnregisterAllProviders();
141
142  ASSERT_TRUE(RunExtensionSubtest("management/management_policy",
143                                  "allowed.html"));
144  // The last thing the test does is uninstall the "enabled_extension".
145  EXPECT_FALSE(service->GetExtensionById(extension_ids_["enabled_extension"],
146                                         true));
147}
148
149// Fails often on Windows dbg bots. http://crbug.com/177163
150#if defined(OS_WIN)
151#define MAYBE_ManagementPolicyProhibited DISABLED_ManagementPolicyProhibited
152#else
153#define MAYBE_ManagementPolicyProhibited ManagementPolicyProhibited
154#endif  // defined(OS_WIN)
155// Tests actions on extensions when management policy prohibits those actions.
156IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,
157                       MAYBE_ManagementPolicyProhibited) {
158  LoadExtensions();
159  ExtensionService* service = extensions::ExtensionSystem::Get(
160      browser()->profile())->extension_service();
161  EXPECT_TRUE(service->GetExtensionById(extension_ids_["enabled_extension"],
162                                        false));
163
164  // Prohibit status changes.
165  extensions::ManagementPolicy* policy = extensions::ExtensionSystem::Get(
166      browser()->profile())->management_policy();
167  policy->UnregisterAllProviders();
168  extensions::TestManagementPolicyProvider provider(
169    extensions::TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS);
170  policy->RegisterProvider(&provider);
171  ASSERT_TRUE(RunExtensionSubtest("management/management_policy",
172                                  "prohibited.html"));
173}
174
175// Disabled. See http://crbug.com/176023
176IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, DISABLED_LaunchPanelApp) {
177  ExtensionService* service = extensions::ExtensionSystem::Get(
178      browser()->profile())->extension_service();
179
180  // Load an extension that calls launchApp() on any app that gets
181  // installed.
182  ExtensionTestMessageListener launcher_loaded("launcher loaded", false);
183  ASSERT_TRUE(LoadExtension(
184      test_data_dir_.AppendASCII("management/launch_on_install")));
185  ASSERT_TRUE(launcher_loaded.WaitUntilSatisfied());
186
187  // Load an app with app.launch.container = "panel".
188  std::string app_id;
189  LoadAndWaitForLaunch("management/launch_app_panel", &app_id);
190  ASSERT_FALSE(HasFatalFailure());  // Stop the test if any ASSERT failed.
191
192  // Find the app's browser.  Check that it is a popup.
193  ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(),
194                                        browser()->host_desktop_type()));
195  Browser* app_browser = FindOtherBrowser(browser());
196  ASSERT_TRUE(app_browser->is_type_popup());
197  ASSERT_TRUE(app_browser->is_app());
198
199  // Close the app panel.
200  content::WindowedNotificationObserver signal(
201      chrome::NOTIFICATION_BROWSER_CLOSED,
202      content::Source<Browser>(app_browser));
203
204  chrome::CloseWindow(app_browser);
205  signal.Wait();
206
207  // Unload the extension.
208  UninstallExtension(app_id);
209  ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
210                                        browser()->host_desktop_type()));
211  ASSERT_FALSE(service->GetExtensionById(app_id, true));
212
213  // Set a pref indicating that the user wants to launch in a regular tab.
214  // This should be ignored, because panel apps always load in a popup.
215  service->extension_prefs()->SetLaunchType(
216      app_id, extensions::ExtensionPrefs::LAUNCH_REGULAR);
217
218  // Load the extension again.
219  std::string app_id_new;
220  LoadAndWaitForLaunch("management/launch_app_panel", &app_id_new);
221  ASSERT_FALSE(HasFatalFailure());
222
223  // If the ID changed, then the pref will not apply to the app.
224  ASSERT_EQ(app_id, app_id_new);
225
226  // Find the app's browser.  Apps that should load in a panel ignore
227  // prefs, so we should still see the launch in a popup.
228  ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(),
229                                        browser()->host_desktop_type()));
230  app_browser = FindOtherBrowser(browser());
231  ASSERT_TRUE(app_browser->is_type_popup());
232  ASSERT_TRUE(app_browser->is_app());
233}
234
235// Disabled: http://crbug.com/230165
236#if defined(OS_WIN)
237#define MAYBE_LaunchTabApp DISABLED_LaunchTabApp
238#else
239#define MAYBE_LaunchTabApp LaunchTabApp
240#endif
241IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, MAYBE_LaunchTabApp) {
242  ExtensionService* service = extensions::ExtensionSystem::Get(
243      browser()->profile())->extension_service();
244
245  // Load an extension that calls launchApp() on any app that gets
246  // installed.
247  ExtensionTestMessageListener launcher_loaded("launcher loaded", false);
248  ASSERT_TRUE(LoadExtension(
249      test_data_dir_.AppendASCII("management/launch_on_install")));
250  ASSERT_TRUE(launcher_loaded.WaitUntilSatisfied());
251
252  // Code below assumes that the test starts with a single browser window
253  // hosting one tab.
254  ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
255                                        browser()->host_desktop_type()));
256  ASSERT_EQ(1, browser()->tab_strip_model()->count());
257
258  // Load an app with app.launch.container = "tab".
259  std::string app_id;
260  LoadAndWaitForLaunch("management/launch_app_tab", &app_id);
261  ASSERT_FALSE(HasFatalFailure());
262
263  // Check that the app opened in a new tab of the existing browser.
264  ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
265                                        browser()->host_desktop_type()));
266  ASSERT_EQ(2, browser()->tab_strip_model()->count());
267
268  // Unload the extension.
269  UninstallExtension(app_id);
270  ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
271                                        browser()->host_desktop_type()));
272  ASSERT_FALSE(service->GetExtensionById(app_id, true));
273
274  // Set a pref indicating that the user wants to launch in a window.
275  service->extension_prefs()->SetLaunchType(
276      app_id, extensions::ExtensionPrefs::LAUNCH_WINDOW);
277
278  std::string app_id_new;
279  LoadAndWaitForLaunch("management/launch_app_tab", &app_id_new);
280  ASSERT_FALSE(HasFatalFailure());
281
282  // If the ID changed, then the pref will not apply to the app.
283  ASSERT_EQ(app_id, app_id_new);
284
285#if defined(OS_MACOSX)
286  // App windows are not yet implemented on mac os.  We should fall back
287  // to a normal tab.
288  ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
289                                        browser()->host_desktop_type()));
290  ASSERT_EQ(2, browser()->tab_strip_model()->count());
291#else
292  // Find the app's browser.  Opening in a new window will create
293  // a new browser.
294  ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(),
295                                        browser()->host_desktop_type()));
296  Browser* app_browser = FindOtherBrowser(browser());
297  ASSERT_TRUE(app_browser->is_app());
298#endif
299}
300