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_APITEST_H_
      6 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_APITEST_H_
      7 
      8 #include <deque>
      9 #include <string>
     10 
     11 #include "base/compiler_specific.h"
     12 #include "base/values.h"
     13 #include "chrome/browser/extensions/extension_browsertest.h"
     14 #include "content/public/browser/notification_registrar.h"
     15 
     16 namespace base {
     17 class FilePath;
     18 }
     19 
     20 namespace extensions {
     21 class Extension;
     22 }
     23 
     24 // The general flow of these API tests should work like this:
     25 // (1) Setup initial browser state (e.g. create some bookmarks for the
     26 //     bookmark test)
     27 // (2) Call ASSERT_TRUE(RunExtensionTest(name));
     28 // (3) In your extension code, run your test and call chrome.test.pass or
     29 //     chrome.test.fail
     30 // (4) Verify expected browser state.
     31 // TODO(erikkay): There should also be a way to drive events in these tests.
     32 class ExtensionApiTest : public ExtensionBrowserTest {
     33  public:
     34   // Flags used to configure how the tests are run.
     35   // TODO(aa): Many of these are dupes of ExtensionBrowserTest::Flags. Combine
     36   // somehow?
     37   enum Flags {
     38     kFlagNone = 0,
     39 
     40     // Allow the extension to run in incognito mode.
     41     kFlagEnableIncognito = 1 << 0,
     42 
     43     // Launch the test page in an incognito window.
     44     kFlagUseIncognito = 1 << 1,
     45 
     46     // Allow file access for the extension.
     47     kFlagEnableFileAccess = 1 << 2,
     48 
     49     // Loads the extension with location COMPONENT.
     50     kFlagLoadAsComponent = 1 << 3,
     51 
     52     // Launch the extension as a platform app.
     53     kFlagLaunchPlatformApp = 1 << 4,
     54 
     55     // Don't fail when the loaded manifest has warnings.
     56     kFlagIgnoreManifestWarnings = 1 << 5,
     57 
     58     // Allow manifest versions older that Extension::kModernManifestVersion.
     59     // Used to test old manifest features.
     60     kFlagAllowOldManifestVersions = 1 << 6,
     61   };
     62 
     63   ExtensionApiTest();
     64   virtual ~ExtensionApiTest();
     65 
     66  protected:
     67   // Helper class that observes tests failing or passing. Observation starts
     68   // when the class is constructed. Get the next result by calling
     69   // GetNextResult() and message() if GetNextResult() return false. If there
     70   // are no results, this method will pump the UI message loop until one is
     71   // received.
     72   class ResultCatcher : public content::NotificationObserver {
     73    public:
     74     ResultCatcher();
     75     virtual ~ResultCatcher();
     76 
     77     // Pumps the UI loop until a notification is received that an API test
     78     // succeeded or failed. Returns true if the test succeeded, false otherwise.
     79     bool GetNextResult();
     80 
     81     void RestrictToProfile(Profile* profile) { profile_restriction_ = profile; }
     82 
     83     const std::string& message() { return message_; }
     84 
     85    private:
     86     virtual void Observe(int type,
     87                          const content::NotificationSource& source,
     88                          const content::NotificationDetails& details) OVERRIDE;
     89 
     90     content::NotificationRegistrar registrar_;
     91 
     92     // A sequential list of pass/fail notifications from the test extension(s).
     93     std::deque<bool> results_;
     94 
     95     // If it failed, what was the error message?
     96     std::deque<std::string> messages_;
     97     std::string message_;
     98 
     99     // If non-NULL, we will listen to events from this profile only.
    100     Profile* profile_restriction_;
    101 
    102     // True if we're in a nested message loop waiting for results from
    103     // the extension.
    104     bool waiting_;
    105   };
    106 
    107   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE;
    108   virtual void TearDownInProcessBrowserTestFixture() OVERRIDE;
    109 
    110   // Load |extension_name| and wait for pass / fail notification.
    111   // |extension_name| is a directory in "test/data/extensions/api_test".
    112   bool RunExtensionTest(const char* extension_name);
    113 
    114   // Same as RunExtensionTest, but enables the extension for incognito mode.
    115   bool RunExtensionTestIncognito(const char* extension_name);
    116 
    117   // Same as RunExtensionTest, but ignores any warnings in the manifest.
    118   bool RunExtensionTestIgnoreManifestWarnings(const char* extension_name);
    119 
    120   // Same as RunExtensionTest, allow old manifest ersions.
    121   bool RunExtensionTestAllowOldManifestVersion(const char* extension_name);
    122 
    123   // Same as RunExtensionTest, but loads extension as component.
    124   bool RunComponentExtensionTest(const char* extension_name);
    125 
    126   // Same as RunExtensionTest, but disables file access.
    127   bool RunExtensionTestNoFileAccess(const char* extension_name);
    128 
    129   // Same as RunExtensionTestIncognito, but disables file access.
    130   bool RunExtensionTestIncognitoNoFileAccess(const char* extension_name);
    131 
    132   // If not empty, Load |extension_name|, load |page_url| and wait for pass /
    133   // fail notification from the extension API on the page. Note that if
    134   // |page_url| is not a valid url, it will be treated as a resource within
    135   // the extension. |extension_name| is a directory in
    136   // "test/data/extensions/api_test".
    137   bool RunExtensionSubtest(const char* extension_name,
    138                            const std::string& page_url);
    139 
    140   // Same as RunExtensionSubtest, except run with the specific |flags|
    141   // (as defined in the Flags enum).
    142   bool RunExtensionSubtest(const char* extension_name,
    143                            const std::string& page_url,
    144                            int flags);
    145 
    146   // Load |page_url| and wait for pass / fail notification from the extension
    147   // API on the page.
    148   bool RunPageTest(const std::string& page_url);
    149   bool RunPageTest(const std::string& page_url, int flags);
    150 
    151   // Similar to RunExtensionTest, except used for running tests in platform app
    152   // shell windows.
    153   bool RunPlatformAppTest(const char* extension_name);
    154   // Similar to RunPlatformAppTest, except sets an additional string argument
    155   // |customArg| to the test config object.
    156   bool RunPlatformAppTestWithArg(
    157       const char* extension_name, const char* custom_arg);
    158 
    159   // Start the test server, and store details of its state.  Those details
    160   // will be available to javascript tests using chrome.test.getConfig().
    161   bool StartEmbeddedTestServer();
    162 
    163   // Start the test WebSocket server, and store details of its state. Those
    164   // details will be available to javascript tests using
    165   // chrome.test.getConfig().
    166   bool StartWebSocketServer(const base::FilePath& root_directory);
    167 
    168   // Test that exactly one extension loaded.  If so, return a pointer to
    169   // the extension.  If not, return NULL and set message_.
    170   const extensions::Extension* GetSingleLoadedExtension();
    171 
    172   // All extensions tested by ExtensionApiTest are in the "api_test" dir.
    173   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE;
    174 
    175   // If it failed, what was the error message?
    176   std::string message_;
    177 
    178  private:
    179   bool RunExtensionTestImpl(const char* extension_name,
    180                             const std::string& test_page,
    181                             const char* custom_arg,
    182                             int flags);
    183 
    184   // Hold details of the test, set in C++, which can be accessed by
    185   // javascript using chrome.test.getConfig().
    186   scoped_ptr<DictionaryValue> test_config_;
    187 
    188   // Hold the test WebSocket server.
    189   scoped_ptr<net::SpawnedTestServer> websocket_server_;
    190 };
    191 
    192 #endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_APITEST_H_
    193