Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/memory/ptr_util.h" | 6 #include "base/memory/ptr_util.h" |
| 7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
| 8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
| 9 #include "base/values.h" | 9 #include "base/values.h" |
| 10 #include "extensions/renderer/bindings/api_binding.h" | 10 #include "extensions/renderer/bindings/api_binding.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 bool AllowAllFeatures(v8::Local<v8::Context> context, const std::string& name) { | 73 bool AllowAllFeatures(v8::Local<v8::Context> context, const std::string& name) { |
| 74 return true; | 74 return true; |
| 75 } | 75 } |
| 76 | 76 |
| 77 void OnEventListenersChanged(const std::string& event_name, | 77 void OnEventListenersChanged(const std::string& event_name, |
| 78 binding::EventListenersChanged change, | 78 binding::EventListenersChanged change, |
| 79 const base::DictionaryValue* filter, | 79 const base::DictionaryValue* filter, |
| 80 bool was_manual, | 80 bool was_manual, |
| 81 v8::Local<v8::Context> context) {} | 81 v8::Local<v8::Context> context) {} |
| 82 | 82 |
| 83 void DoNothingWithSilentRequest( | |
| 84 v8::Local<v8::Context> context, | |
| 85 const std::string& call_name, | |
| 86 const std::vector<v8::Local<v8::Value>>& arguments) {} | |
| 87 | |
| 83 } // namespace | 88 } // namespace |
| 84 | 89 |
| 85 class APIBindingUnittest : public APIBindingTest { | 90 class APIBindingUnittest : public APIBindingTest { |
| 86 public: | 91 public: |
| 87 void OnFunctionCall(std::unique_ptr<APIRequestHandler::Request> request, | 92 void OnFunctionCall(std::unique_ptr<APIRequestHandler::Request> request, |
| 88 v8::Local<v8::Context> context) { | 93 v8::Local<v8::Context> context) { |
| 89 last_request_ = std::move(request); | 94 last_request_ = std::move(request); |
| 90 } | 95 } |
| 91 | 96 |
| 92 protected: | 97 protected: |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 143 void SetHooksDelegate( | 148 void SetHooksDelegate( |
| 144 std::unique_ptr<APIBindingHooksDelegate> hooks_delegate) { | 149 std::unique_ptr<APIBindingHooksDelegate> hooks_delegate) { |
| 145 binding_hooks_delegate_ = std::move(hooks_delegate); | 150 binding_hooks_delegate_ = std::move(hooks_delegate); |
| 146 ASSERT_TRUE(binding_hooks_delegate_); | 151 ASSERT_TRUE(binding_hooks_delegate_); |
| 147 } | 152 } |
| 148 | 153 |
| 149 void SetCreateCustomType(const APIBinding::CreateCustomType& callback) { | 154 void SetCreateCustomType(const APIBinding::CreateCustomType& callback) { |
| 150 create_custom_type_ = callback; | 155 create_custom_type_ = callback; |
| 151 } | 156 } |
| 152 | 157 |
| 158 void SetOnSilentRequest(const APIBinding::OnSilentRequest& callback) { | |
| 159 on_silent_request_ = callback; | |
| 160 } | |
| 161 | |
| 153 void SetAvailabilityCallback( | 162 void SetAvailabilityCallback( |
| 154 const BindingAccessChecker::AvailabilityCallback& callback) { | 163 const BindingAccessChecker::AvailabilityCallback& callback) { |
| 155 availability_callback_ = callback; | 164 availability_callback_ = callback; |
| 156 } | 165 } |
| 157 | 166 |
| 158 void InitializeBinding() { | 167 void InitializeBinding() { |
| 159 if (!binding_hooks_) { | 168 if (!binding_hooks_) { |
| 160 binding_hooks_ = base::MakeUnique<APIBindingHooks>( | 169 binding_hooks_ = base::MakeUnique<APIBindingHooks>( |
| 161 kBindingName, binding::RunJSFunctionSync()); | 170 kBindingName, binding::RunJSFunctionSync()); |
| 162 } | 171 } |
| 163 if (binding_hooks_delegate_) | 172 if (binding_hooks_delegate_) |
| 164 binding_hooks_->SetDelegate(std::move(binding_hooks_delegate_)); | 173 binding_hooks_->SetDelegate(std::move(binding_hooks_delegate_)); |
| 174 if (!on_silent_request_) | |
| 175 on_silent_request_ = base::Bind(&DoNothingWithSilentRequest); | |
| 165 if (!availability_callback_) | 176 if (!availability_callback_) |
| 166 availability_callback_ = base::Bind(&AllowAllFeatures); | 177 availability_callback_ = base::Bind(&AllowAllFeatures); |
| 167 event_handler_ = base::MakeUnique<APIEventHandler>( | 178 event_handler_ = base::MakeUnique<APIEventHandler>( |
| 168 base::Bind(&RunFunctionOnGlobalAndIgnoreResult), | 179 base::Bind(&RunFunctionOnGlobalAndIgnoreResult), |
| 169 base::Bind(&RunFunctionOnGlobalAndReturnHandle), | 180 base::Bind(&RunFunctionOnGlobalAndReturnHandle), |
| 170 base::Bind(&OnEventListenersChanged)); | 181 base::Bind(&OnEventListenersChanged)); |
| 171 access_checker_ = | 182 access_checker_ = |
| 172 base::MakeUnique<BindingAccessChecker>(availability_callback_); | 183 base::MakeUnique<BindingAccessChecker>(availability_callback_); |
| 173 binding_ = base::MakeUnique<APIBinding>( | 184 binding_ = base::MakeUnique<APIBinding>( |
| 174 kBindingName, binding_functions_.get(), binding_types_.get(), | 185 kBindingName, binding_functions_.get(), binding_types_.get(), |
| 175 binding_events_.get(), binding_properties_.get(), create_custom_type_, | 186 binding_events_.get(), binding_properties_.get(), create_custom_type_, |
| 176 std::move(binding_hooks_), &type_refs_, request_handler_.get(), | 187 on_silent_request_, std::move(binding_hooks_), &type_refs_, |
| 177 event_handler_.get(), access_checker_.get()); | 188 request_handler_.get(), event_handler_.get(), access_checker_.get()); |
| 178 EXPECT_EQ(!binding_types_.get(), type_refs_.empty()); | 189 EXPECT_EQ(!binding_types_.get(), type_refs_.empty()); |
| 179 } | 190 } |
| 180 | 191 |
| 181 void ExpectPass(v8::Local<v8::Object> object, | 192 void ExpectPass(v8::Local<v8::Object> object, |
| 182 const std::string& script_source, | 193 const std::string& script_source, |
| 183 const std::string& expected_json_arguments_single_quotes, | 194 const std::string& expected_json_arguments_single_quotes, |
| 184 bool expect_callback) { | 195 bool expect_callback) { |
| 185 ExpectPass(MainContext(), object, script_source, | 196 ExpectPass(MainContext(), object, script_source, |
| 186 expected_json_arguments_single_quotes, expect_callback); | 197 expected_json_arguments_single_quotes, expect_callback); |
| 187 } | 198 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 236 std::unique_ptr<BindingAccessChecker> access_checker_; | 247 std::unique_ptr<BindingAccessChecker> access_checker_; |
| 237 APITypeReferenceMap type_refs_; | 248 APITypeReferenceMap type_refs_; |
| 238 | 249 |
| 239 std::unique_ptr<base::ListValue> binding_functions_; | 250 std::unique_ptr<base::ListValue> binding_functions_; |
| 240 std::unique_ptr<base::ListValue> binding_events_; | 251 std::unique_ptr<base::ListValue> binding_events_; |
| 241 std::unique_ptr<base::ListValue> binding_types_; | 252 std::unique_ptr<base::ListValue> binding_types_; |
| 242 std::unique_ptr<base::DictionaryValue> binding_properties_; | 253 std::unique_ptr<base::DictionaryValue> binding_properties_; |
| 243 std::unique_ptr<APIBindingHooks> binding_hooks_; | 254 std::unique_ptr<APIBindingHooks> binding_hooks_; |
| 244 std::unique_ptr<APIBindingHooksDelegate> binding_hooks_delegate_; | 255 std::unique_ptr<APIBindingHooksDelegate> binding_hooks_delegate_; |
| 245 APIBinding::CreateCustomType create_custom_type_; | 256 APIBinding::CreateCustomType create_custom_type_; |
| 257 APIBinding::OnSilentRequest on_silent_request_; | |
| 246 BindingAccessChecker::AvailabilityCallback availability_callback_; | 258 BindingAccessChecker::AvailabilityCallback availability_callback_; |
| 247 | 259 |
| 248 DISALLOW_COPY_AND_ASSIGN(APIBindingUnittest); | 260 DISALLOW_COPY_AND_ASSIGN(APIBindingUnittest); |
| 249 }; | 261 }; |
| 250 | 262 |
| 251 void APIBindingUnittest::RunTest(v8::Local<v8::Context> context, | 263 void APIBindingUnittest::RunTest(v8::Local<v8::Context> context, |
| 252 v8::Local<v8::Object> object, | 264 v8::Local<v8::Object> object, |
| 253 const std::string& script_source, | 265 const std::string& script_source, |
| 254 bool should_pass, | 266 bool should_pass, |
| 255 const std::string& expected_json_arguments, | 267 const std::string& expected_json_arguments, |
| (...skipping 1016 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1272 v8::Local<v8::Object> binding_object = binding()->CreateInstance(context); | 1284 v8::Local<v8::Object> binding_object = binding()->CreateInstance(context); |
| 1273 | 1285 |
| 1274 // The extra property should be present on the binding object. | 1286 // The extra property should be present on the binding object. |
| 1275 EXPECT_EQ("42", GetStringPropertyFromObject(binding_object, context, | 1287 EXPECT_EQ("42", GetStringPropertyFromObject(binding_object, context, |
| 1276 "hookedProperty")); | 1288 "hookedProperty")); |
| 1277 // Sanity check: other values should still be there. | 1289 // Sanity check: other values should still be there. |
| 1278 EXPECT_EQ("function", | 1290 EXPECT_EQ("function", |
| 1279 GetStringPropertyFromObject(binding_object, context, "oneString")); | 1291 GetStringPropertyFromObject(binding_object, context, "oneString")); |
| 1280 } | 1292 } |
| 1281 | 1293 |
| 1294 // Test that running hooks returning different results correctly sends requests | |
| 1295 // or notifies of silent requests. | |
| 1296 TEST_F(APIBindingUnittest, TestSendingRequestsAndSilentRequestsWithHooks) { | |
| 1297 SetFunctions( | |
|
jbroman
2017/06/30 19:05:48
This seems to be missing any unit tests which have
Devlin
2017/07/06 17:09:57
Fair enough. Added one with real parameters. :)
| |
| 1298 "[{" | |
| 1299 " 'name': 'modifyArgs'," | |
| 1300 " 'parameters': []" | |
| 1301 "}, {" | |
| 1302 " 'name': 'invalidInvocation'," | |
| 1303 " 'parameters': []" | |
| 1304 "}, {" | |
| 1305 " 'name': 'throwException'," | |
| 1306 " 'parameters': []" | |
| 1307 "}, {" | |
| 1308 " 'name': 'dontHandle'," | |
| 1309 " 'parameters': []" | |
| 1310 "}, {" | |
| 1311 " 'name': 'handle'," | |
| 1312 " 'parameters': []" | |
| 1313 "}, {" | |
| 1314 " 'name': 'handleAndSendRequest'," | |
| 1315 " 'parameters': []" | |
| 1316 "}]"); | |
| 1317 | |
| 1318 using RequestResult = APIBindingHooks::RequestResult; | |
| 1319 | |
| 1320 auto basic_handler = [](RequestResult::ResultCode code, const APISignature*, | |
| 1321 v8::Local<v8::Context> context, | |
| 1322 std::vector<v8::Local<v8::Value>>* arguments, | |
| 1323 const APITypeReferenceMap& map) { | |
| 1324 return RequestResult(code); | |
| 1325 }; | |
| 1326 | |
| 1327 auto hooks = base::MakeUnique<APIBindingHooksTestDelegate>(); | |
| 1328 hooks->AddHandler( | |
| 1329 "test.modifyArgs", | |
| 1330 base::Bind(basic_handler, RequestResult::ARGUMENTS_UPDATED)); | |
| 1331 hooks->AddHandler( | |
| 1332 "test.invalidInvocation", | |
| 1333 base::Bind(basic_handler, RequestResult::INVALID_INVOCATION)); | |
| 1334 hooks->AddHandler("test.dontHandle", | |
| 1335 base::Bind(basic_handler, RequestResult::NOT_HANDLED)); | |
| 1336 hooks->AddHandler("test.handle", | |
| 1337 base::Bind(basic_handler, RequestResult::HANDLED)); | |
| 1338 hooks->AddHandler( | |
| 1339 "test.throwException", | |
| 1340 base::Bind([](const APISignature*, v8::Local<v8::Context> context, | |
| 1341 std::vector<v8::Local<v8::Value>>* arguments, | |
| 1342 const APITypeReferenceMap& map) { | |
| 1343 context->GetIsolate()->ThrowException( | |
| 1344 gin::StringToV8(context->GetIsolate(), "some error")); | |
| 1345 return RequestResult(RequestResult::THROWN); | |
| 1346 })); | |
| 1347 auto handle_and_send_request = | |
| 1348 [](APIRequestHandler* handler, const APISignature*, | |
| 1349 v8::Local<v8::Context> context, | |
| 1350 std::vector<v8::Local<v8::Value>>* arguments, | |
| 1351 const APITypeReferenceMap& map) { | |
| 1352 handler->StartRequest( | |
| 1353 context, "test.handleAndSendRequest", | |
| 1354 base::MakeUnique<base::ListValue>(), v8::Local<v8::Function>(), | |
| 1355 v8::Local<v8::Function>(), binding::RequestThread::UI); | |
| 1356 return RequestResult(RequestResult::HANDLED); | |
| 1357 }; | |
| 1358 hooks->AddHandler("test.handleAndSendRequest", | |
| 1359 base::Bind(handle_and_send_request, request_handler())); | |
| 1360 | |
| 1361 SetHooksDelegate(std::move(hooks)); | |
| 1362 | |
| 1363 auto on_silent_request = | |
| 1364 [](base::Optional<std::string>* name_out, v8::Local<v8::Context> context, | |
| 1365 const std::string& call_name, | |
| 1366 const std::vector<v8::Local<v8::Value>>& arguments) { | |
| 1367 *name_out = call_name; | |
| 1368 }; | |
| 1369 base::Optional<std::string> silent_request; | |
| 1370 SetOnSilentRequest(base::Bind(on_silent_request, &silent_request)); | |
| 1371 | |
| 1372 InitializeBinding(); | |
| 1373 | |
| 1374 v8::HandleScope handle_scope(isolate()); | |
| 1375 v8::Local<v8::Context> context = MainContext(); | |
| 1376 | |
| 1377 v8::Local<v8::Object> binding_object = binding()->CreateInstance(context); | |
| 1378 | |
| 1379 auto call_api_method = [binding_object, context](base::StringPiece name) { | |
| 1380 v8::Local<v8::Function> call = FunctionFromString( | |
| 1381 context, base::StringPrintf("(function(binding) { binding.%s(); })", | |
| 1382 name.data())); | |
| 1383 v8::Local<v8::Value> args[] = {binding_object}; | |
| 1384 // The throwException call will throw an exception; ignore it. | |
| 1385 ignore_result(call->Call(context, v8::Undefined(context->GetIsolate()), | |
| 1386 arraysize(args), args)); | |
| 1387 }; | |
| 1388 | |
| 1389 call_api_method("modifyArgs"); | |
| 1390 ASSERT_TRUE(last_request()); | |
| 1391 EXPECT_EQ("test.modifyArgs", last_request()->method_name); | |
| 1392 EXPECT_FALSE(silent_request); | |
| 1393 reset_last_request(); | |
| 1394 silent_request.reset(); | |
| 1395 | |
| 1396 call_api_method("invalidInvocation"); | |
| 1397 EXPECT_FALSE(last_request()); | |
| 1398 EXPECT_FALSE(silent_request); | |
| 1399 reset_last_request(); | |
| 1400 silent_request.reset(); | |
| 1401 | |
| 1402 call_api_method("throwException"); | |
| 1403 EXPECT_FALSE(last_request()); | |
| 1404 EXPECT_FALSE(silent_request); | |
| 1405 reset_last_request(); | |
| 1406 silent_request.reset(); | |
| 1407 | |
| 1408 call_api_method("dontHandle"); | |
| 1409 ASSERT_TRUE(last_request()); | |
| 1410 EXPECT_EQ("test.dontHandle", last_request()->method_name); | |
| 1411 EXPECT_FALSE(silent_request); | |
| 1412 reset_last_request(); | |
| 1413 silent_request.reset(); | |
| 1414 | |
| 1415 call_api_method("handle"); | |
| 1416 EXPECT_FALSE(last_request()); | |
| 1417 ASSERT_TRUE(silent_request); | |
| 1418 EXPECT_EQ("test.handle", *silent_request); | |
| 1419 reset_last_request(); | |
| 1420 silent_request.reset(); | |
| 1421 | |
| 1422 call_api_method("handleAndSendRequest"); | |
| 1423 ASSERT_TRUE(last_request()); | |
| 1424 EXPECT_EQ("test.handleAndSendRequest", last_request()->method_name); | |
| 1425 EXPECT_FALSE(silent_request); | |
| 1426 reset_last_request(); | |
| 1427 silent_request.reset(); | |
| 1428 } | |
| 1429 | |
| 1282 } // namespace extensions | 1430 } // namespace extensions |
| OLD | NEW |