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