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