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