extension_function_test_utils.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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#include "chrome/browser/extensions/extension_function_test_utils.h" 6 7#include <string> 8 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 "chrome/test/base/ui_test_utils.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 "extensions/common/id_util.h" 21#include "testing/gtest/include/gtest/gtest.h" 22 23using content::WebContents; 24using extensions::Extension; 25using extensions::Manifest; 26namespace keys = extensions::tabs_constants; 27 28namespace { 29 30class TestFunctionDispatcherDelegate 31 : public extensions::ExtensionFunctionDispatcher::Delegate { 32 public: 33 explicit TestFunctionDispatcherDelegate(Browser* browser) : 34 browser_(browser) {} 35 virtual ~TestFunctionDispatcherDelegate() {} 36 37 private: 38 virtual extensions::WindowController* GetExtensionWindowController() 39 const OVERRIDE { 40 return browser_->extension_window_controller(); 41 } 42 43 virtual WebContents* GetAssociatedWebContents() const OVERRIDE { 44 return NULL; 45 } 46 47 Browser* browser_; 48}; 49 50} // namespace 51 52namespace extension_function_test_utils { 53 54base::Value* ParseJSON(const std::string& data) { 55 return base::JSONReader::Read(data); 56} 57 58base::ListValue* ParseList(const std::string& data) { 59 base::Value* result = ParseJSON(data); 60 base::ListValue* list = NULL; 61 result->GetAsList(&list); 62 return list; 63} 64 65base::DictionaryValue* ParseDictionary( 66 const std::string& data) { 67 base::Value* result = ParseJSON(data); 68 base::DictionaryValue* dict = NULL; 69 result->GetAsDictionary(&dict); 70 return dict; 71} 72 73bool GetBoolean(base::DictionaryValue* val, const std::string& key) { 74 bool result = false; 75 if (!val->GetBoolean(key, &result)) 76 ADD_FAILURE() << key << " does not exist or is not a boolean."; 77 return result; 78} 79 80int GetInteger(base::DictionaryValue* val, const std::string& key) { 81 int result = 0; 82 if (!val->GetInteger(key, &result)) 83 ADD_FAILURE() << key << " does not exist or is not an integer."; 84 return result; 85} 86 87std::string GetString(base::DictionaryValue* val, const std::string& key) { 88 std::string result; 89 if (!val->GetString(key, &result)) 90 ADD_FAILURE() << key << " does not exist or is not a string."; 91 return result; 92} 93 94base::DictionaryValue* ToDictionary(base::Value* val) { 95 EXPECT_TRUE(val); 96 EXPECT_EQ(base::Value::TYPE_DICTIONARY, val->GetType()); 97 return static_cast<base::DictionaryValue*>(val); 98} 99 100base::ListValue* ToList(base::Value* val) { 101 EXPECT_TRUE(val); 102 EXPECT_EQ(base::Value::TYPE_LIST, val->GetType()); 103 return static_cast<base::ListValue*>(val); 104} 105 106scoped_refptr<Extension> CreateEmptyExtension() { 107 return CreateEmptyExtensionWithLocation(Manifest::INTERNAL); 108} 109 110scoped_refptr<Extension> CreateEmptyExtensionWithLocation( 111 Manifest::Location location) { 112 scoped_ptr<base::DictionaryValue> test_extension_value( 113 ParseDictionary("{\"name\": \"Test\", \"version\": \"1.0\"}")); 114 return CreateExtension(location, test_extension_value.get(), std::string()); 115} 116 117scoped_refptr<Extension> CreateEmptyExtension( 118 const std::string& id_input) { 119 scoped_ptr<base::DictionaryValue> test_extension_value( 120 ParseDictionary("{\"name\": \"Test\", \"version\": \"1.0\"}")); 121 return CreateExtension(Manifest::INTERNAL, test_extension_value.get(), 122 id_input); 123} 124 125scoped_refptr<Extension> CreateExtension( 126 base::DictionaryValue* test_extension_value) { 127 return CreateExtension(Manifest::INTERNAL, test_extension_value, 128 std::string()); 129} 130 131scoped_refptr<Extension> CreateExtension( 132 Manifest::Location location, 133 base::DictionaryValue* test_extension_value, 134 const std::string& id_input) { 135 std::string error; 136 const base::FilePath test_extension_path; 137 std::string id; 138 if (!id_input.empty()) 139 id = extensions::id_util::GenerateId(id_input); 140 scoped_refptr<Extension> extension(Extension::Create( 141 test_extension_path, 142 location, 143 *test_extension_value, 144 Extension::NO_FLAGS, 145 id, 146 &error)); 147 EXPECT_TRUE(error.empty()) << "Could not parse test extension " << error; 148 return extension; 149} 150 151bool HasPrivacySensitiveFields(base::DictionaryValue* val) { 152 std::string result; 153 if (val->GetString(keys::kUrlKey, &result) || 154 val->GetString(keys::kTitleKey, &result) || 155 val->GetString(keys::kFaviconUrlKey, &result)) 156 return true; 157 return false; 158} 159 160std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function, 161 const std::string& args, 162 Browser* browser) { 163 return RunFunctionAndReturnError(function, args, browser, NONE); 164} 165std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function, 166 const std::string& args, 167 Browser* browser, 168 RunFunctionFlags flags) { 169 scoped_refptr<ExtensionFunction> function_owner(function); 170 // Without a callback the function will not generate a result. 171 function->set_has_callback(true); 172 RunFunction(function, args, browser, flags); 173 EXPECT_FALSE(function->GetResultList()) << "Did not expect a result"; 174 return function->GetError(); 175} 176 177base::Value* RunFunctionAndReturnSingleResult( 178 UIThreadExtensionFunction* function, 179 const std::string& args, 180 Browser* browser) { 181 return RunFunctionAndReturnSingleResult(function, args, browser, NONE); 182} 183base::Value* RunFunctionAndReturnSingleResult( 184 UIThreadExtensionFunction* function, 185 const std::string& args, 186 Browser* browser, 187 RunFunctionFlags flags) { 188 scoped_refptr<ExtensionFunction> function_owner(function); 189 // Without a callback the function will not generate a result. 190 function->set_has_callback(true); 191 RunFunction(function, args, browser, flags); 192 EXPECT_TRUE(function->GetError().empty()) << "Unexpected error: " 193 << function->GetError(); 194 const base::Value* single_result = NULL; 195 if (function->GetResultList() != NULL && 196 function->GetResultList()->Get(0, &single_result)) { 197 return single_result->DeepCopy(); 198 } 199 return NULL; 200} 201 202// This helps us be able to wait until an UIThreadExtensionFunction calls 203// SendResponse. 204class SendResponseDelegate 205 : public UIThreadExtensionFunction::DelegateForTests { 206 public: 207 SendResponseDelegate() : should_post_quit_(false) {} 208 209 virtual ~SendResponseDelegate() {} 210 211 void set_should_post_quit(bool should_quit) { 212 should_post_quit_ = should_quit; 213 } 214 215 bool HasResponse() { 216 return response_.get() != NULL; 217 } 218 219 bool GetResponse() { 220 EXPECT_TRUE(HasResponse()); 221 return *response_.get(); 222 } 223 224 virtual void OnSendResponse(UIThreadExtensionFunction* function, 225 bool success, 226 bool bad_message) OVERRIDE { 227 ASSERT_FALSE(bad_message); 228 ASSERT_FALSE(HasResponse()); 229 response_.reset(new bool); 230 *response_ = success; 231 if (should_post_quit_) { 232 base::MessageLoopForUI::current()->Quit(); 233 } 234 } 235 236 private: 237 scoped_ptr<bool> response_; 238 bool should_post_quit_; 239}; 240 241bool RunFunction(UIThreadExtensionFunction* function, 242 const std::string& args, 243 Browser* browser, 244 RunFunctionFlags flags) { 245 TestFunctionDispatcherDelegate dispatcher_delegate(browser); 246 scoped_ptr<extensions::ExtensionFunctionDispatcher> dispatcher( 247 new extensions::ExtensionFunctionDispatcher(browser->profile(), 248 &dispatcher_delegate)); 249 // TODO(yoz): The cast is a hack; these flags should be defined in 250 // only one place. See crbug.com/394840. 251 return extensions::api_test_utils::RunFunction( 252 function, 253 args, 254 browser->profile(), 255 dispatcher.Pass(), 256 static_cast<extensions::api_test_utils::RunFunctionFlags>(flags)); 257} 258 259} // namespace extension_function_test_utils 260