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/values.h"
12 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "components/crx_file/id_util.h"
16 #include "extensions/browser/api_test_utils.h"
17 #include "extensions/browser/extension_function.h"
18 #include "extensions/browser/extension_function_dispatcher.h"
19 #include "extensions/common/extension.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 using content::WebContents
;
23 using extensions::Extension
;
24 using extensions::Manifest
;
25 namespace keys
= extensions::tabs_constants
;
29 class TestFunctionDispatcherDelegate
30 : public extensions::ExtensionFunctionDispatcher::Delegate
{
32 explicit TestFunctionDispatcherDelegate(Browser
* browser
) :
34 ~TestFunctionDispatcherDelegate() override
{}
37 extensions::WindowController
* GetExtensionWindowController() const override
{
38 return browser_
->extension_window_controller();
41 WebContents
* GetAssociatedWebContents() const override
{ return NULL
; }
48 namespace extension_function_test_utils
{
50 base::Value
* ParseJSON(const std::string
& data
) {
51 return base::JSONReader::Read(data
);
54 base::ListValue
* ParseList(const std::string
& data
) {
55 base::Value
* result
= ParseJSON(data
);
56 base::ListValue
* list
= NULL
;
57 result
->GetAsList(&list
);
61 base::DictionaryValue
* ToDictionary(base::Value
* val
) {
63 EXPECT_EQ(base::Value::TYPE_DICTIONARY
, val
->GetType());
64 return static_cast<base::DictionaryValue
*>(val
);
67 base::ListValue
* ToList(base::Value
* val
) {
69 EXPECT_EQ(base::Value::TYPE_LIST
, val
->GetType());
70 return static_cast<base::ListValue
*>(val
);
73 bool HasPrivacySensitiveFields(base::DictionaryValue
* val
) {
75 if (val
->GetString(keys::kUrlKey
, &result
) ||
76 val
->GetString(keys::kTitleKey
, &result
) ||
77 val
->GetString(keys::kFaviconUrlKey
, &result
))
82 std::string
RunFunctionAndReturnError(UIThreadExtensionFunction
* function
,
83 const std::string
& args
,
85 return RunFunctionAndReturnError(function
, args
, browser
, NONE
);
87 std::string
RunFunctionAndReturnError(UIThreadExtensionFunction
* function
,
88 const std::string
& args
,
90 RunFunctionFlags flags
) {
91 scoped_refptr
<ExtensionFunction
> function_owner(function
);
92 // Without a callback the function will not generate a result.
93 function
->set_has_callback(true);
94 RunFunction(function
, args
, browser
, flags
);
95 EXPECT_FALSE(function
->GetResultList()) << "Did not expect a result";
96 return function
->GetError();
99 base::Value
* RunFunctionAndReturnSingleResult(
100 UIThreadExtensionFunction
* function
,
101 const std::string
& args
,
103 return RunFunctionAndReturnSingleResult(function
, args
, browser
, NONE
);
105 base::Value
* RunFunctionAndReturnSingleResult(
106 UIThreadExtensionFunction
* function
,
107 const std::string
& args
,
109 RunFunctionFlags flags
) {
110 scoped_refptr
<ExtensionFunction
> function_owner(function
);
111 // Without a callback the function will not generate a result.
112 function
->set_has_callback(true);
113 RunFunction(function
, args
, browser
, flags
);
114 EXPECT_TRUE(function
->GetError().empty()) << "Unexpected error: "
115 << function
->GetError();
116 const base::Value
* single_result
= NULL
;
117 if (function
->GetResultList() != NULL
&&
118 function
->GetResultList()->Get(0, &single_result
)) {
119 return single_result
->DeepCopy();
124 // This helps us be able to wait until an UIThreadExtensionFunction calls
126 class SendResponseDelegate
127 : public UIThreadExtensionFunction::DelegateForTests
{
129 SendResponseDelegate() : should_post_quit_(false) {}
131 virtual ~SendResponseDelegate() {}
133 void set_should_post_quit(bool should_quit
) {
134 should_post_quit_
= should_quit
;
138 return response_
.get() != NULL
;
142 EXPECT_TRUE(HasResponse());
143 return *response_
.get();
146 void OnSendResponse(UIThreadExtensionFunction
* function
,
148 bool bad_message
) override
{
149 ASSERT_FALSE(bad_message
);
150 ASSERT_FALSE(HasResponse());
151 response_
.reset(new bool);
152 *response_
= success
;
153 if (should_post_quit_
) {
154 base::MessageLoopForUI::current()->Quit();
159 scoped_ptr
<bool> response_
;
160 bool should_post_quit_
;
163 bool RunFunction(UIThreadExtensionFunction
* function
,
164 const std::string
& args
,
166 RunFunctionFlags flags
) {
167 scoped_ptr
<base::ListValue
> parsed_args(ParseList(args
));
168 EXPECT_TRUE(parsed_args
.get())
169 << "Could not parse extension function arguments: " << args
;
170 return RunFunction(function
, parsed_args
.Pass(), browser
, flags
);
173 bool RunFunction(UIThreadExtensionFunction
* function
,
174 scoped_ptr
<base::ListValue
> args
,
176 RunFunctionFlags flags
) {
177 TestFunctionDispatcherDelegate
dispatcher_delegate(browser
);
178 scoped_ptr
<extensions::ExtensionFunctionDispatcher
> dispatcher(
179 new extensions::ExtensionFunctionDispatcher(browser
->profile(),
180 &dispatcher_delegate
));
181 // TODO(yoz): The cast is a hack; these flags should be defined in
182 // only one place. See crbug.com/394840.
183 return extensions::api_test_utils::RunFunction(
188 static_cast<extensions::api_test_utils::RunFunctionFlags
>(flags
));
191 } // namespace extension_function_test_utils