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