blob: 29097ec354b08029b1d50a8c7f58f6e24db7c581 [file] [log] [blame]
[email protected]8809f1442012-01-20 21:21:471// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]637bf322011-10-01 20:46:322// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/extension_function_test_utils.h"
6
7#include <string>
8
[email protected]4e3ce3b2011-10-14 23:25:179#include "base/file_path.h"
[email protected]637bf322011-10-01 20:46:3210#include "base/json/json_reader.h"
11#include "base/values.h"
[email protected]4e3ce3b2011-10-14 23:25:1712#include "chrome/browser/extensions/extension_function.h"
13#include "chrome/browser/extensions/extension_function_dispatcher.h"
[email protected]637bf322011-10-01 20:46:3214#include "chrome/browser/ui/browser.h"
[email protected]4e3ce3b2011-10-14 23:25:1715#include "chrome/common/extensions/extension.h"
[email protected]d8c8749b92011-11-16 22:31:3216#include "chrome/test/base/ui_test_utils.h"
[email protected]637bf322011-10-01 20:46:3217#include "testing/gtest/include/gtest/gtest.h"
18
[email protected]ea049a02011-12-25 21:37:0919using content::WebContents;
[email protected]1c321ee2012-05-21 03:02:3420using extensions::Extension;
[email protected]ea049a02011-12-25 21:37:0921
[email protected]4e3ce3b2011-10-14 23:25:1722namespace {
23
24class TestFunctionDispatcherDelegate
25 : public ExtensionFunctionDispatcher::Delegate {
26 public:
27 explicit TestFunctionDispatcherDelegate(Browser* browser) :
28 browser_(browser) {}
29 virtual ~TestFunctionDispatcherDelegate() {}
30
31 private:
[email protected]b51f3562012-05-05 22:01:4332 virtual ExtensionWindowController* GetExtensionWindowController()
33 const OVERRIDE {
34 return browser_->extension_window_controller();
[email protected]4e3ce3b2011-10-14 23:25:1735 }
36
[email protected]ea049a02011-12-25 21:37:0937 virtual WebContents* GetAssociatedWebContents() const OVERRIDE {
[email protected]4e3ce3b2011-10-14 23:25:1738 return NULL;
39 }
40
41 Browser* browser_;
42};
43
44} // namespace
45
[email protected]637bf322011-10-01 20:46:3246namespace extension_function_test_utils {
47
48base::Value* ParseJSON(const std::string& data) {
[email protected]cd5785752012-04-11 00:15:4149 return base::JSONReader::Read(data);
[email protected]637bf322011-10-01 20:46:3250}
51
52base::ListValue* ParseList(const std::string& data) {
53 scoped_ptr<base::Value> result(ParseJSON(data));
54 if (result.get() && result->IsType(base::Value::TYPE_LIST))
55 return static_cast<base::ListValue*>(result.release());
56 else
57 return NULL;
58}
59
60base::DictionaryValue* ParseDictionary(
61 const std::string& data) {
62 scoped_ptr<base::Value> result(ParseJSON(data));
63 if (result.get() && result->IsType(base::Value::TYPE_DICTIONARY))
64 return static_cast<base::DictionaryValue*>(result.release());
65 else
66 return NULL;
67}
68
69bool GetBoolean(base::DictionaryValue* val, const std::string& key) {
70 bool result = false;
71 if (!val->GetBoolean(key, &result))
72 ADD_FAILURE() << key << " does not exist or is not a boolean.";
73 return result;
74}
75
76int GetInteger(base::DictionaryValue* val, const std::string& key) {
77 int result = 0;
78 if (!val->GetInteger(key, &result))
79 ADD_FAILURE() << key << " does not exist or is not an integer.";
80 return result;
81}
82
83std::string GetString(base::DictionaryValue* val, const std::string& key) {
84 std::string result;
85 if (!val->GetString(key, &result))
86 ADD_FAILURE() << key << " does not exist or is not a string.";
87 return result;
88}
89
90base::DictionaryValue* ToDictionary(base::Value* val) {
[email protected]8ce80ea62011-10-18 18:00:1891 EXPECT_TRUE(val);
92 EXPECT_EQ(base::Value::TYPE_DICTIONARY, val->GetType());
[email protected]637bf322011-10-01 20:46:3293 return static_cast<base::DictionaryValue*>(val);
94}
95
[email protected]008ff7fb2011-12-19 08:51:1796base::ListValue* ToList(base::Value* val) {
97 EXPECT_TRUE(val);
98 EXPECT_EQ(base::Value::TYPE_LIST, val->GetType());
99 return static_cast<base::ListValue*>(val);
100}
101
[email protected]4e3ce3b2011-10-14 23:25:17102scoped_refptr<Extension> CreateEmptyExtension() {
[email protected]6d2d55b2012-05-05 21:33:43103 return CreateEmptyExtensionWithLocation(Extension::INTERNAL);
104}
105
106scoped_refptr<Extension> CreateEmptyExtensionWithLocation(
107 Extension::Location location) {
[email protected]4e3ce3b2011-10-14 23:25:17108 std::string error;
109 const FilePath test_extension_path;
110 scoped_ptr<base::DictionaryValue> test_extension_value(
111 ParseDictionary("{\"name\": \"Test\", \"version\": \"1.0\"}"));
112 scoped_refptr<Extension> extension(Extension::Create(
113 test_extension_path,
[email protected]6d2d55b2012-05-05 21:33:43114 location,
[email protected]4e3ce3b2011-10-14 23:25:17115 *test_extension_value.get(),
116 Extension::NO_FLAGS,
117 &error));
[email protected]8ce80ea62011-10-18 18:00:18118 EXPECT_TRUE(error.empty()) << "Could not parse test extension " << error;
[email protected]4e3ce3b2011-10-14 23:25:17119 return extension;
120}
121
[email protected]637bf322011-10-01 20:46:32122std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function,
123 const std::string& args,
124 Browser* browser) {
125 return RunFunctionAndReturnError(function, args, browser, NONE);
126}
127std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function,
128 const std::string& args,
129 Browser* browser,
130 RunFunctionFlags flags) {
131 scoped_refptr<ExtensionFunction> function_owner(function);
132 RunFunction(function, args, browser, flags);
[email protected]07ff5fd2012-07-12 22:39:09133 EXPECT_FALSE(function->GetResultList()) << "Did not expect a result";
[email protected]637bf322011-10-01 20:46:32134 return function->GetError();
135}
136
[email protected]07ff5fd2012-07-12 22:39:09137base::Value* RunFunctionAndReturnSingleResult(
138 UIThreadExtensionFunction* function,
139 const std::string& args,
140 Browser* browser) {
141 return RunFunctionAndReturnSingleResult(function, args, browser, NONE);
[email protected]637bf322011-10-01 20:46:32142}
[email protected]07ff5fd2012-07-12 22:39:09143base::Value* RunFunctionAndReturnSingleResult(
144 UIThreadExtensionFunction* function,
145 const std::string& args,
146 Browser* browser,
147 RunFunctionFlags flags) {
[email protected]637bf322011-10-01 20:46:32148 scoped_refptr<ExtensionFunction> function_owner(function);
149 RunFunction(function, args, browser, flags);
[email protected]8ce80ea62011-10-18 18:00:18150 EXPECT_TRUE(function->GetError().empty()) << "Unexpected error: "
151 << function->GetError();
[email protected]07ff5fd2012-07-12 22:39:09152 base::Value* single_result = NULL;
153 if (function->GetResultList() != NULL &&
154 function->GetResultList()->Get(0, &single_result)) {
155 return single_result->DeepCopy();
156 }
157 return NULL;
[email protected]637bf322011-10-01 20:46:32158}
159
[email protected]d8c8749b92011-11-16 22:31:32160// This helps us be able to wait until an AsyncExtensionFunction calls
161// SendResponse.
[email protected]bdfc03e2011-11-22 00:20:33162class SendResponseDelegate
163 : public UIThreadExtensionFunction::DelegateForTests {
[email protected]d8c8749b92011-11-16 22:31:32164 public:
165 SendResponseDelegate() : should_post_quit_(false) {}
166
167 virtual ~SendResponseDelegate() {}
168
169 void set_should_post_quit(bool should_quit) {
170 should_post_quit_ = should_quit;
171 }
172
173 bool HasResponse() {
174 return response_.get() != NULL;
175 }
176
177 bool GetResponse() {
178 EXPECT_TRUE(HasResponse());
179 return *response_.get();
180 }
181
[email protected]bdfc03e2011-11-22 00:20:33182 virtual void OnSendResponse(UIThreadExtensionFunction* function,
[email protected]ca6df682012-04-10 23:00:20183 bool success,
184 bool bad_message) {
185 ASSERT_FALSE(bad_message);
[email protected]d8c8749b92011-11-16 22:31:32186 ASSERT_FALSE(HasResponse());
187 response_.reset(new bool);
188 *response_ = success;
189 if (should_post_quit_) {
190 MessageLoopForUI::current()->Quit();
191 }
192 }
193
194 private:
195 scoped_ptr<bool> response_;
196 bool should_post_quit_;
197};
198
[email protected]bdfc03e2011-11-22 00:20:33199bool RunFunction(UIThreadExtensionFunction* function,
200 const std::string& args,
201 Browser* browser,
202 RunFunctionFlags flags) {
[email protected]d8c8749b92011-11-16 22:31:32203 SendResponseDelegate response_delegate;
204 function->set_test_delegate(&response_delegate);
[email protected]bdfc03e2011-11-22 00:20:33205 scoped_ptr<base::ListValue> parsed_args(ParseList(args));
206 EXPECT_TRUE(parsed_args.get()) <<
207 "Could not parse extension function arguments: " << args;
208 function->SetArgs(parsed_args.get());
209
210 TestFunctionDispatcherDelegate dispatcher_delegate(browser);
211 ExtensionFunctionDispatcher dispatcher(
212 browser->profile(), &dispatcher_delegate);
213 function->set_dispatcher(dispatcher.AsWeakPtr());
214
215 function->set_profile(browser->profile());
216 function->set_include_incognito(flags & INCLUDE_INCOGNITO);
217 function->Run();
[email protected]d8c8749b92011-11-16 22:31:32218
219 // If the RunImpl of |function| didn't already call SendResponse, run the
220 // message loop until they do.
221 if (!response_delegate.HasResponse()) {
222 response_delegate.set_should_post_quit(true);
223 ui_test_utils::RunMessageLoop();
224 }
225
226 EXPECT_TRUE(response_delegate.HasResponse());
227 return response_delegate.GetResponse();
228}
229
[email protected]637bf322011-10-01 20:46:32230} // namespace extension_function_test_utils