Home | History | Annotate | Download | only in extensions
      1 // Copyright (c) 2011 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 #pragma once
      8 
      9 #include <deque>
     10 #include <string>
     11 
     12 #include "base/values.h"
     13 #include "chrome/browser/extensions/extension_browsertest.h"
     14 #include "content/common/notification_registrar.h"
     15 
     16 class Extension;
     17 
     18 // The general flow of these API tests should work like this:
     19 // (1) Setup initial browser state (e.g. create some bookmarks for the
     20 //     bookmark test)
     21 // (2) Call ASSERT_TRUE(RunExtensionTest(name));
     22 // (3) In your extension code, run your test and call chrome.test.pass or
     23 //     chrome.test.fail
     24 // (4) Verify expected browser state.
     25 // TODO(erikkay): There should also be a way to drive events in these tests.
     26 
     27 class ExtensionApiTest : public ExtensionBrowserTest {
     28  public:
     29   ExtensionApiTest();
     30   virtual ~ExtensionApiTest();
     31 
     32  protected:
     33   // Helper class that observes tests failing or passing. Observation starts
     34   // when the class is constructed. Get the next result by calling
     35   // GetNextResult() and message() if GetNextResult() return false. If there
     36   // are no results, this method will pump the UI message loop until one is
     37   // received.
     38   class ResultCatcher : public NotificationObserver {
     39    public:
     40     ResultCatcher();
     41     ~ResultCatcher();
     42 
     43     // Pumps the UI loop until a notification is received that an API test
     44     // succeeded or failed. Returns true if the test succeeded, false otherwise.
     45     bool GetNextResult();
     46 
     47     void RestrictToProfile(Profile* profile) { profile_restriction_ = profile; }
     48 
     49     const std::string& message() { return message_; }
     50 
     51    private:
     52     virtual void Observe(NotificationType type,
     53                          const NotificationSource& source,
     54                          const NotificationDetails& details);
     55 
     56     NotificationRegistrar registrar_;
     57 
     58     // A sequential list of pass/fail notifications from the test extension(s).
     59     std::deque<bool> results_;
     60 
     61     // If it failed, what was the error message?
     62     std::deque<std::string> messages_;
     63     std::string message_;
     64 
     65     // If non-NULL, we will listen to events from this profile only.
     66     Profile* profile_restriction_;
     67 
     68     // True if we're in a nested message loop waiting for results from
     69     // the extension.
     70     bool waiting_;
     71   };
     72 
     73   virtual void SetUpInProcessBrowserTestFixture();
     74   virtual void TearDownInProcessBrowserTestFixture();
     75 
     76   // Load |extension_name| and wait for pass / fail notification.
     77   // |extension_name| is a directory in "test/data/extensions/api_test".
     78   bool RunExtensionTest(const char* extension_name);
     79 
     80   // Same as RunExtensionTest, but enables the extension for incognito mode.
     81   bool RunExtensionTestIncognito(const char* extension_name);
     82 
     83   // Same as RunExtensionTest, but loads extension as component.
     84   bool RunComponentExtensionTest(const char* extension_name);
     85 
     86   // Same as RunExtensionTest, but disables file access.
     87   bool RunExtensionTestNoFileAccess(const char* extension_name);
     88 
     89   // Same as RunExtensionTestIncognito, but disables file access.
     90   bool RunExtensionTestIncognitoNoFileAccess(const char* extension_name);
     91 
     92   // If not empty, Load |extension_name|, load |page_url| and wait for pass /
     93   // fail notification from the extension API on the page. Note that if
     94   // |page_url| is not a valid url, it will be treated as a resource within
     95   // the extension. |extension_name| is a directory in
     96   // "test/data/extensions/api_test".
     97   bool RunExtensionSubtest(const char* extension_name,
     98                            const std::string& page_url);
     99 
    100   // Load |page_url| and wait for pass / fail notification from the extension
    101   // API on the page.
    102   bool RunPageTest(const std::string& page_url);
    103 
    104   // Start the test server, and store details of its state.  Those details
    105   // will be available to javascript tests using chrome.test.getConfig().
    106   bool StartTestServer();
    107 
    108   // Test that exactly one extension loaded.  If so, return a pointer to
    109   // the extension.  If not, return NULL and set message_.
    110   const Extension* GetSingleLoadedExtension();
    111 
    112   // All extensions tested by ExtensionApiTest are in the "api_test" dir.
    113   virtual void SetUpCommandLine(CommandLine* command_line);
    114 
    115   // If it failed, what was the error message?
    116   std::string message_;
    117 
    118  private:
    119   bool RunExtensionTestImpl(const char* extension_name,
    120                             const std::string& test_page,
    121                             bool enable_incogntio,
    122                             bool enable_fileaccess,
    123                             bool load_as_component);
    124 
    125   // Hold details of the test, set in C++, which can be accessed by
    126   // javascript using chrome.test.getConfig().
    127   scoped_ptr<DictionaryValue> test_config_;
    128 };
    129 
    130 #endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_APITEST_H_
    131