• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RestrictToProfile(Profile * profile)81     void RestrictToProfile(Profile* profile) { profile_restriction_ = profile; }
82 
message()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 std::string& extension_name);
113 
114   // Same as RunExtensionTest, but enables the extension for incognito mode.
115   bool RunExtensionTestIncognito(const std::string& extension_name);
116 
117   // Same as RunExtensionTest, but ignores any warnings in the manifest.
118   bool RunExtensionTestIgnoreManifestWarnings(
119       const std::string& extension_name);
120 
121   // Same as RunExtensionTest, allow old manifest ersions.
122   bool RunExtensionTestAllowOldManifestVersion(
123       const std::string& extension_name);
124 
125   // Same as RunExtensionTest, but loads extension as component.
126   bool RunComponentExtensionTest(const std::string& extension_name);
127 
128   // Same as RunExtensionTest, but disables file access.
129   bool RunExtensionTestNoFileAccess(const std::string& extension_name);
130 
131   // Same as RunExtensionTestIncognito, but disables file access.
132   bool RunExtensionTestIncognitoNoFileAccess(const std::string& extension_name);
133 
134   // If not empty, Load |extension_name|, load |page_url| and wait for pass /
135   // fail notification from the extension API on the page. Note that if
136   // |page_url| is not a valid url, it will be treated as a resource within
137   // the extension. |extension_name| is a directory in
138   // "test/data/extensions/api_test".
139   bool RunExtensionSubtest(const std::string& extension_name,
140                            const std::string& page_url);
141 
142   // Same as RunExtensionSubtest, except run with the specific |flags|
143   // (as defined in the Flags enum).
144   bool RunExtensionSubtest(const std::string& extension_name,
145                            const std::string& page_url,
146                            int flags);
147 
148   // Load |page_url| and wait for pass / fail notification from the extension
149   // API on the page.
150   bool RunPageTest(const std::string& page_url);
151   bool RunPageTest(const std::string& page_url, int flags);
152 
153   // Similar to RunExtensionTest, except used for running tests in platform app
154   // shell windows.
155   bool RunPlatformAppTest(const std::string& extension_name);
156 
157   // Similar to RunPlatformAppTest, except sets an additional string argument
158   // |customArg| to the test config object.
159   bool RunPlatformAppTestWithArg(
160       const std::string& extension_name, const char* custom_arg);
161 
162   // Similar to RunPlatformAppTest, with custom |flags| (as defined in the Flags
163   // enum). The kFlagLaunchPlatformApp flag is automatically added.
164   bool RunPlatformAppTestWithFlags(const std::string& extension_name,
165                                    int flags);
166 
167   // Start the test server, and store details of its state.  Those details
168   // will be available to javascript tests using chrome.test.getConfig().
169   bool StartEmbeddedTestServer();
170 
171   // Start the test WebSocket server, and store details of its state. Those
172   // details will be available to javascript tests using
173   // chrome.test.getConfig().
174   bool StartWebSocketServer(const base::FilePath& root_directory);
175 
176   // Start the test FTP server, and store details of its state. Those
177   // details will be available to JavaScript tests using
178   // chrome.test.getConfig().
179   bool StartFTPServer(const base::FilePath& root_directory);
180 
181   // Start the spawned test server, and store details of its state.  Those
182   // details will be available to javascript tests using
183   // chrome.test.getConfig().
184   bool StartSpawnedTestServer();
185 
186   // Test that exactly one extension loaded.  If so, return a pointer to
187   // the extension.  If not, return NULL and set message_.
188   const extensions::Extension* GetSingleLoadedExtension();
189 
190   // All extensions tested by ExtensionApiTest are in the "api_test" dir.
191   virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE;
192 
193   // If it failed, what was the error message?
194   std::string message_;
195 
196  private:
197   bool RunExtensionTestImpl(const std::string& extension_name,
198                             const std::string& test_page,
199                             const char* custom_arg,
200                             int flags);
201 
202   // Hold details of the test, set in C++, which can be accessed by
203   // javascript using chrome.test.getConfig().
204   scoped_ptr<base::DictionaryValue> test_config_;
205 
206   // Hold the test WebSocket server.
207   scoped_ptr<net::SpawnedTestServer> websocket_server_;
208 
209   // Hold the test FTP server.
210   scoped_ptr<net::SpawnedTestServer> ftp_server_;
211 };
212 
213 #endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_APITEST_H_
214