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