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_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