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 "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.
     63   ExtensionService* extension_service() {
     64     return extensions::ExtensionSystem::Get(profile())->extension_service();
     65   }
     66 
     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.
    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.
    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.
    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).
    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 
    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 
    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 
    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.
    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|.
    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.
    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.
    249   bool WaitForExtensionInstallError() {
    250     return observer_->WaitForExtensionInstallError();
    251   }
    252 
    253   // Waits until an extension is loaded and all view have loaded.
    254   void WaitForExtensionAndViewLoad() {
    255     return observer_->WaitForExtensionAndViewLoad();
    256   }
    257 
    258   // Waits until an extension is loaded.
    259   void WaitForExtensionLoad() {
    260     return observer_->WaitForExtensionLoad();
    261   }
    262 
    263   // Waits for an extension load error. Returns true if the error really
    264   // happened.
    265   bool WaitForExtensionLoadError() {
    266     return observer_->WaitForExtensionLoadError();
    267   }
    268 
    269   // Wait for the specified extension to crash. Returns true if it really
    270   // crashed.
    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.
    276   bool WaitForCrxInstallerDone() {
    277     return observer_->WaitForCrxInstallerDone();
    278   }
    279 
    280   // Wait for all extension views to load.
    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