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 #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSERTEST_H_ 6 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSERTEST_H_ 7 8 #include <string> 9 10 #include "base/command_line.h" 11 12 #include "base/files/file_path.h" 13 #include "base/files/scoped_temp_dir.h" 14 #include "base/test/scoped_path_override.h" 15 #include "chrome/browser/extensions/extension_test_notification_observer.h" 16 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/browser/ui/browser.h" 18 #include "chrome/common/extensions/features/feature_channel.h" 19 #include "chrome/test/base/in_process_browser_test.h" 20 #include "content/public/browser/web_contents.h" 21 #include "extensions/browser/extension_host.h" 22 #include "extensions/browser/extension_system.h" 23 #include "extensions/common/extension.h" 24 #include "extensions/common/feature_switch.h" 25 #include "extensions/common/manifest.h" 26 27 class ExtensionService; 28 class Profile; 29 30 namespace extensions { 31 class ExtensionCacheFake; 32 class ExtensionSet; 33 class ProcessManager; 34 } 35 36 // Base class for extension browser tests. Provides utilities for loading, 37 // unloading, and installing extensions. 38 class ExtensionBrowserTest : virtual public InProcessBrowserTest { 39 protected: 40 // Flags used to configure how the tests are run. 41 enum Flags { 42 kFlagNone = 0, 43 44 // Allow the extension to run in incognito mode. 45 kFlagEnableIncognito = 1 << 0, 46 47 // Allow file access for the extension. 48 kFlagEnableFileAccess = 1 << 1, 49 50 // Don't fail when the loaded manifest has warnings (should only be used 51 // when testing deprecated features). 52 kFlagIgnoreManifestWarnings = 1 << 2, 53 54 // Allow older manifest versions (typically these can't be loaded - we allow 55 // them for testing). 56 kFlagAllowOldManifestVersions = 1 << 3, 57 }; 58 59 ExtensionBrowserTest(); 60 virtual ~ExtensionBrowserTest(); 61 62 // Useful accessors. extension_service()63 ExtensionService* extension_service() { 64 return extensions::ExtensionSystem::Get(profile())->extension_service(); 65 } 66 last_loaded_extension_id()67 const std::string& last_loaded_extension_id() { 68 return observer_->last_loaded_extension_id(); 69 } 70 71 // Get the profile to use. 72 virtual Profile* profile(); 73 74 static const extensions::Extension* GetExtensionByPath( 75 const extensions::ExtensionSet* extensions, const base::FilePath& path); 76 77 // InProcessBrowserTest 78 virtual void SetUp() OVERRIDE; 79 virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE; 80 virtual void SetUpOnMainThread() OVERRIDE; 81 82 const extensions::Extension* LoadExtension(const base::FilePath& path); 83 84 // Load extension and enable it in incognito mode. 85 const extensions::Extension* LoadExtensionIncognito( 86 const base::FilePath& path); 87 88 // Load extension from the |path| folder. |flags| is bit mask of values from 89 // |Flags| enum. 90 const extensions::Extension* LoadExtensionWithFlags( 91 const base::FilePath& path, int flags); 92 93 // Same as above, but sets the installation parameter to the extension 94 // preferences. 95 const extensions::Extension* LoadExtensionWithInstallParam( 96 const base::FilePath& path, 97 int flags, 98 const std::string& install_param); 99 100 // Loads unpacked extension from |path| with manifest |manifest_relative_path| 101 // and imitates that it is a component extension. 102 // |manifest_relative_path| is relative to |path|. 103 const extensions::Extension* LoadExtensionAsComponentWithManifest( 104 const base::FilePath& path, 105 const base::FilePath::CharType* manifest_relative_path); 106 107 // Loads unpacked extension from |path| and imitates that it is a component 108 // extension. Equivalent to 109 // LoadExtensionAsComponentWithManifest(path, extensions::kManifestFilename). 110 const extensions::Extension* LoadExtensionAsComponent( 111 const base::FilePath& path); 112 113 // Pack the extension in |dir_path| into a crx file and return its path. 114 // Return an empty FilePath if there were errors. 115 base::FilePath PackExtension(const base::FilePath& dir_path); 116 117 // Pack the extension in |dir_path| into a crx file at |crx_path|, using the 118 // key |pem_path|. If |pem_path| does not exist, create a new key at 119 // |pem_out_path|. 120 // Return the path to the crx file, or an empty FilePath if there were errors. 121 base::FilePath PackExtensionWithOptions(const base::FilePath& dir_path, 122 const base::FilePath& crx_path, 123 const base::FilePath& pem_path, 124 const base::FilePath& pem_out_path); 125 126 // |expected_change| indicates how many extensions should be installed (or 127 // disabled, if negative). 128 // 1 means you expect a new install, 0 means you expect an upgrade, -1 means 129 // you expect a failed upgrade. InstallExtension(const base::FilePath & path,int expected_change)130 const extensions::Extension* InstallExtension(const base::FilePath& path, 131 int expected_change) { 132 return InstallOrUpdateExtension( 133 std::string(), path, INSTALL_UI_TYPE_NONE, expected_change); 134 } 135 136 // Same as above, but an install source other than Manifest::INTERNAL can be 137 // specified. InstallExtension(const base::FilePath & path,int expected_change,extensions::Manifest::Location install_source)138 const extensions::Extension* InstallExtension( 139 const base::FilePath& path, 140 int expected_change, 141 extensions::Manifest::Location install_source) { 142 return InstallOrUpdateExtension(std::string(), 143 path, 144 INSTALL_UI_TYPE_NONE, 145 expected_change, 146 install_source); 147 } 148 149 // Installs extension as if it came from the Chrome Webstore. 150 const extensions::Extension* InstallExtensionFromWebstore( 151 const base::FilePath& path, int expected_change); 152 153 // Same as above but passes an id to CrxInstaller and does not allow a 154 // privilege increase. UpdateExtension(const std::string & id,const base::FilePath & path,int expected_change)155 const extensions::Extension* UpdateExtension(const std::string& id, 156 const base::FilePath& path, 157 int expected_change) { 158 return InstallOrUpdateExtension(id, path, INSTALL_UI_TYPE_NONE, 159 expected_change); 160 } 161 162 // Same as UpdateExtension but waits for the extension to be idle first. 163 const extensions::Extension* UpdateExtensionWaitForIdle( 164 const std::string& id, const base::FilePath& path, int expected_change); 165 166 // Same as |InstallExtension| but with the normal extension UI showing up 167 // (for e.g. info bar on success). InstallExtensionWithUI(const base::FilePath & path,int expected_change)168 const extensions::Extension* InstallExtensionWithUI( 169 const base::FilePath& path, 170 int expected_change) { 171 return InstallOrUpdateExtension( 172 std::string(), path, INSTALL_UI_TYPE_NORMAL, expected_change); 173 } 174 InstallExtensionWithUIAutoConfirm(const base::FilePath & path,int expected_change,Browser * browser)175 const extensions::Extension* InstallExtensionWithUIAutoConfirm( 176 const base::FilePath& path, 177 int expected_change, 178 Browser* browser) { 179 return InstallOrUpdateExtension(std::string(), 180 path, 181 INSTALL_UI_TYPE_AUTO_CONFIRM, 182 expected_change, 183 browser, 184 extensions::Extension::NO_FLAGS); 185 } 186 InstallExtensionWithSourceAndFlags(const base::FilePath & path,int expected_change,extensions::Manifest::Location install_source,extensions::Extension::InitFromValueFlags creation_flags)187 const extensions::Extension* InstallExtensionWithSourceAndFlags( 188 const base::FilePath& path, 189 int expected_change, 190 extensions::Manifest::Location install_source, 191 extensions::Extension::InitFromValueFlags creation_flags) { 192 return InstallOrUpdateExtension(std::string(), 193 path, 194 INSTALL_UI_TYPE_NONE, 195 expected_change, 196 install_source, 197 browser(), 198 creation_flags, 199 false, 200 false); 201 } 202 InstallEphemeralAppWithSourceAndFlags(const base::FilePath & path,int expected_change,extensions::Manifest::Location install_source,extensions::Extension::InitFromValueFlags creation_flags)203 const extensions::Extension* InstallEphemeralAppWithSourceAndFlags( 204 const base::FilePath& path, 205 int expected_change, 206 extensions::Manifest::Location install_source, 207 extensions::Extension::InitFromValueFlags creation_flags) { 208 return InstallOrUpdateExtension(std::string(), 209 path, 210 INSTALL_UI_TYPE_NONE, 211 expected_change, 212 install_source, 213 browser(), 214 creation_flags, 215 false, 216 true); 217 } 218 219 // Begins install process but simulates a user cancel. StartInstallButCancel(const base::FilePath & path)220 const extensions::Extension* StartInstallButCancel( 221 const base::FilePath& path) { 222 return InstallOrUpdateExtension( 223 std::string(), path, INSTALL_UI_TYPE_CANCEL, 0); 224 } 225 226 void ReloadExtension(const std::string extension_id); 227 228 void UnloadExtension(const std::string& extension_id); 229 230 void UninstallExtension(const std::string& extension_id); 231 232 void DisableExtension(const std::string& extension_id); 233 234 void EnableExtension(const std::string& extension_id); 235 236 // Wait for the number of visible page actions to change to |count|. WaitForPageActionVisibilityChangeTo(int count)237 bool WaitForPageActionVisibilityChangeTo(int count) { 238 return observer_->WaitForPageActionVisibilityChangeTo(count); 239 } 240 241 // Waits until an extension is installed and loaded. Returns true if an 242 // install happened before timeout. WaitForExtensionInstall()243 bool WaitForExtensionInstall() { 244 return observer_->WaitForExtensionInstall(); 245 } 246 247 // Wait for an extension install error to be raised. Returns true if an 248 // error was raised. WaitForExtensionInstallError()249 bool WaitForExtensionInstallError() { 250 return observer_->WaitForExtensionInstallError(); 251 } 252 253 // Waits until an extension is loaded and all view have loaded. WaitForExtensionAndViewLoad()254 void WaitForExtensionAndViewLoad() { 255 return observer_->WaitForExtensionAndViewLoad(); 256 } 257 258 // Waits until an extension is loaded. WaitForExtensionLoad()259 void WaitForExtensionLoad() { 260 return observer_->WaitForExtensionLoad(); 261 } 262 263 // Waits for an extension load error. Returns true if the error really 264 // happened. WaitForExtensionLoadError()265 bool WaitForExtensionLoadError() { 266 return observer_->WaitForExtensionLoadError(); 267 } 268 269 // Wait for the specified extension to crash. Returns true if it really 270 // crashed. WaitForExtensionCrash(const std::string & extension_id)271 bool WaitForExtensionCrash(const std::string& extension_id) { 272 return observer_->WaitForExtensionCrash(extension_id); 273 } 274 275 // Wait for the crx installer to be done. Returns true if it really is done. WaitForCrxInstallerDone()276 bool WaitForCrxInstallerDone() { 277 return observer_->WaitForCrxInstallerDone(); 278 } 279 280 // Wait for all extension views to load. WaitForExtensionViewsToLoad()281 bool WaitForExtensionViewsToLoad() { 282 return observer_->WaitForExtensionViewsToLoad(); 283 } 284 285 // Simulates a page calling window.open on an URL and waits for the 286 // navigation. 287 void OpenWindow(content::WebContents* contents, 288 const GURL& url, 289 bool newtab_process_should_equal_opener, 290 content::WebContents** newtab_result); 291 292 // Simulates a page navigating itself to an URL and waits for the 293 // navigation. 294 void NavigateInRenderer(content::WebContents* contents, const GURL& url); 295 296 // Looks for an ExtensionHost whose URL has the given path component 297 // (including leading slash). Also verifies that the expected number of hosts 298 // are loaded. 299 extensions::ExtensionHost* FindHostWithPath( 300 extensions::ProcessManager* manager, 301 const std::string& path, 302 int expected_hosts); 303 304 // Returns 305 // extensions::browsertest_util::ExecuteScriptInBackgroundPage(profile(), 306 // extension_id, script). 307 std::string ExecuteScriptInBackgroundPage(const std::string& extension_id, 308 const std::string& script); 309 310 // Returns 311 // extensions::browsertest_util::ExecuteScriptInBackgroundPageNoWait( 312 // profile(), extension_id, script). 313 bool ExecuteScriptInBackgroundPageNoWait(const std::string& extension_id, 314 const std::string& script); 315 316 bool loaded_; 317 bool installed_; 318 319 #if defined(OS_CHROMEOS) 320 // True if the command line should be tweaked as if ChromeOS user is 321 // already logged in. 322 bool set_chromeos_user_; 323 #endif 324 325 // test_data/extensions. 326 base::FilePath test_data_dir_; 327 328 scoped_ptr<ExtensionTestNotificationObserver> observer_; 329 330 private: 331 // Temporary directory for testing. 332 base::ScopedTempDir temp_dir_; 333 334 // Specifies the type of UI (if any) to show during installation and what 335 // user action to simulate. 336 enum InstallUIType { 337 INSTALL_UI_TYPE_NONE, 338 INSTALL_UI_TYPE_CANCEL, 339 INSTALL_UI_TYPE_NORMAL, 340 INSTALL_UI_TYPE_AUTO_CONFIRM, 341 }; 342 343 const extensions::Extension* InstallOrUpdateExtension( 344 const std::string& id, 345 const base::FilePath& path, 346 InstallUIType ui_type, 347 int expected_change); 348 const extensions::Extension* InstallOrUpdateExtension( 349 const std::string& id, 350 const base::FilePath& path, 351 InstallUIType ui_type, 352 int expected_change, 353 Browser* browser, 354 extensions::Extension::InitFromValueFlags creation_flags); 355 const extensions::Extension* InstallOrUpdateExtension( 356 const std::string& id, 357 const base::FilePath& path, 358 InstallUIType ui_type, 359 int expected_change, 360 extensions::Manifest::Location install_source); 361 const extensions::Extension* InstallOrUpdateExtension( 362 const std::string& id, 363 const base::FilePath& path, 364 InstallUIType ui_type, 365 int expected_change, 366 extensions::Manifest::Location install_source, 367 Browser* browser, 368 extensions::Extension::InitFromValueFlags creation_flags, 369 bool wait_for_idle, 370 bool is_ephemeral); 371 372 // Make the current channel "dev" for the duration of the test. 373 extensions::ScopedCurrentChannel current_channel_; 374 375 // Disable external install UI. 376 extensions::FeatureSwitch::ScopedOverride 377 override_prompt_for_external_extensions_; 378 379 #if defined(OS_WIN) 380 // Use mock shortcut directories to ensure app shortcuts are cleaned up. 381 base::ScopedPathOverride user_desktop_override_; 382 base::ScopedPathOverride common_desktop_override_; 383 base::ScopedPathOverride user_quick_launch_override_; 384 base::ScopedPathOverride start_menu_override_; 385 base::ScopedPathOverride common_start_menu_override_; 386 #endif 387 388 // The default profile to be used. 389 Profile* profile_; 390 391 // Cache cache implementation. 392 scoped_ptr<extensions::ExtensionCacheFake> test_extension_cache_; 393 }; 394 395 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSERTEST_H_ 396