Home | History | Annotate | Download | only in extensions
      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