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
16class 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
27class 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