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.
5 #include "chrome/browser/extensions/extension_function_test_utils.h"
9 #include "base/files/file_path.h"
10 #include "base/json/json_reader.h"
11 #include "base/macros.h"
12 #include "base/values.h"
13 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "components/crx_file/id_util.h"
17 #include "extensions/browser/api_test_utils.h"
18 #include "extensions/browser/extension_function.h"
19 #include "extensions/browser/extension_function_dispatcher.h"
20 #include "extensions/common/extension.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 using content::WebContents
;
24 using extensions::Extension
;
25 using extensions::Manifest
;
26 namespace keys
= extensions::tabs_constants
;
30 class TestFunctionDispatcherDelegate
31 : public extensions::ExtensionFunctionDispatcher::Delegate
{
33 explicit TestFunctionDispatcherDelegate(Browser
* browser
) :
35 ~TestFunctionDispatcherDelegate() override
{}
38 extensions::WindowController
* GetExtensionWindowController() const override
{
39 return browser_
->extension_window_controller();
42 WebContents
* GetAssociatedWebContents() const override
{ return NULL
; }
49 namespace extension_function_test_utils
{
51 base::ListValue
* ParseList(const std::string
& data
) {
52 scoped_ptr
<base::Value
> result
= base::JSONReader::Read(data
);
53 base::ListValue
* list
= NULL
;
54 result
->GetAsList(&list
);
55 ignore_result(result
.release());
59 base::DictionaryValue
* ToDictionary(base::Value
* val
) {
61 EXPECT_EQ(base::Value::TYPE_DICTIONARY
, val
->GetType());
62 return static_cast<base::DictionaryValue
*>(val
);
65 base::ListValue
* ToList(base::Value
* val
) {
67 EXPECT_EQ(base::Value::TYPE_LIST
, val
->GetType());
68 return static_cast<base::ListValue
*>(val
);
71 bool HasPrivacySensitiveFields(base::DictionaryValue
* val
) {
73 if (val
->GetString(keys::kUrlKey
, &result
) ||
74 val
->GetString(keys::kTitleKey
, &result
) ||
75 val
->GetString(keys::kFaviconUrlKey
, &result
))
80 std::string
RunFunctionAndReturnError(UIThreadExtensionFunction
* function
,
81 const std::string
& args
,
83 return RunFunctionAndReturnError(function
, args
, browser
, NONE
);
85 std::string
RunFunctionAndReturnError(UIThreadExtensionFunction
* function
,
86 const std::string
& args
,
88 RunFunctionFlags flags
) {
89 scoped_refptr
<ExtensionFunction
> function_owner(function
);
90 // Without a callback the function will not generate a result.
91 function
->set_has_callback(true);
92 RunFunction(function
, args
, browser
, flags
);
93 EXPECT_FALSE(function
->GetResultList()) << "Did not expect a result";
94 return function
->GetError();
97 base::Value
* RunFunctionAndReturnSingleResult(
98 UIThreadExtensionFunction
* function
,
99 const std::string
& args
,
101 return RunFunctionAndReturnSingleResult(function
, args
, browser
, NONE
);
103 base::Value
* RunFunctionAndReturnSingleResult(
104 UIThreadExtensionFunction
* function
,
105 const std::string
& args
,
107 RunFunctionFlags flags
) {
108 scoped_refptr
<ExtensionFunction
> function_owner(function
);
109 // Without a callback the function will not generate a result.
110 function
->set_has_callback(true);
111 RunFunction(function
, args
, browser
, flags
);
112 EXPECT_TRUE(function
->GetError().empty()) << "Unexpected error: "
113 << function
->GetError();
114 const base::Value
* single_result
= NULL
;
115 if (function
->GetResultList() != NULL
&&
116 function
->GetResultList()->Get(0, &single_result
)) {
117 return single_result
->DeepCopy();
122 // This helps us be able to wait until an UIThreadExtensionFunction calls
124 class SendResponseDelegate
125 : public UIThreadExtensionFunction::DelegateForTests
{
127 SendResponseDelegate() : should_post_quit_(false) {}
129 virtual ~SendResponseDelegate() {}
131 void set_should_post_quit(bool should_quit
) {
132 should_post_quit_
= should_quit
;
136 return response_
.get() != NULL
;
140 EXPECT_TRUE(HasResponse());
141 return *response_
.get();
144 void OnSendResponse(UIThreadExtensionFunction
* function
,
146 bool bad_message
) override
{
147 ASSERT_FALSE(bad_message
);
148 ASSERT_FALSE(HasResponse());
149 response_
.reset(new bool);
150 *response_
= success
;
151 if (should_post_quit_
) {
152 base::MessageLoopForUI::current()->Quit();
157 scoped_ptr
<bool> response_
;
158 bool should_post_quit_
;
161 bool RunFunction(UIThreadExtensionFunction
* function
,
162 const std::string
& args
,
164 RunFunctionFlags flags
) {
165 scoped_ptr
<base::ListValue
> parsed_args(ParseList(args
));
166 EXPECT_TRUE(parsed_args
.get())
167 << "Could not parse extension function arguments: " << args
;
168 return RunFunction(function
, parsed_args
.Pass(), browser
, flags
);
171 bool RunFunction(UIThreadExtensionFunction
* function
,
172 scoped_ptr
<base::ListValue
> args
,
174 RunFunctionFlags flags
) {
175 TestFunctionDispatcherDelegate
dispatcher_delegate(browser
);
176 scoped_ptr
<extensions::ExtensionFunctionDispatcher
> dispatcher(
177 new extensions::ExtensionFunctionDispatcher(browser
->profile()));
178 dispatcher
->set_delegate(&dispatcher_delegate
);
179 // TODO(yoz): The cast is a hack; these flags should be defined in
180 // only one place. See crbug.com/394840.
181 return extensions::api_test_utils::RunFunction(
186 static_cast<extensions::api_test_utils::RunFunctionFlags
>(flags
));
189 } // namespace extension_function_test_utils