| 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/api_binding.h" | 10 #include "extensions/renderer/api_binding.h" |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 } | 187 } |
| 188 | 188 |
| 189 arguments_.reset(); | 189 arguments_.reset(); |
| 190 } | 190 } |
| 191 | 191 |
| 192 TEST_F(APIBindingUnittest, TestEmptyAPI) { | 192 TEST_F(APIBindingUnittest, TestEmptyAPI) { |
| 193 ArgumentSpec::RefMap refs; | 193 ArgumentSpec::RefMap refs; |
| 194 APIBinding binding( | 194 APIBinding binding( |
| 195 "empty", nullptr, nullptr, nullptr, | 195 "empty", nullptr, nullptr, nullptr, |
| 196 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), | 196 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), |
| 197 base::MakeUnique<APIBindingHooks>(binding::RunJSFunction()), &refs); | 197 base::MakeUnique<APIBindingHooks>(binding::RunJSFunctionSync()), &refs); |
| 198 EXPECT_TRUE(refs.empty()); | 198 EXPECT_TRUE(refs.empty()); |
| 199 | 199 |
| 200 v8::HandleScope handle_scope(isolate()); | 200 v8::HandleScope handle_scope(isolate()); |
| 201 v8::Local<v8::Context> context = ContextLocal(); | 201 v8::Local<v8::Context> context = ContextLocal(); |
| 202 | 202 |
| 203 APIEventHandler event_handler( | 203 APIEventHandler event_handler( |
| 204 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); | 204 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); |
| 205 v8::Local<v8::Object> binding_object = binding.CreateInstance( | 205 v8::Local<v8::Object> binding_object = binding.CreateInstance( |
| 206 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs)); | 206 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs)); |
| 207 EXPECT_EQ( | 207 EXPECT_EQ( |
| 208 0u, | 208 0u, |
| 209 binding_object->GetOwnPropertyNames(context).ToLocalChecked()->Length()); | 209 binding_object->GetOwnPropertyNames(context).ToLocalChecked()->Length()); |
| 210 } | 210 } |
| 211 | 211 |
| 212 TEST_F(APIBindingUnittest, Test) { | 212 TEST_F(APIBindingUnittest, Test) { |
| 213 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions); | 213 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions); |
| 214 ASSERT_TRUE(functions); | 214 ASSERT_TRUE(functions); |
| 215 ArgumentSpec::RefMap refs; | 215 ArgumentSpec::RefMap refs; |
| 216 APIBinding binding( | 216 APIBinding binding( |
| 217 "test", functions.get(), nullptr, nullptr, | 217 "test", functions.get(), nullptr, nullptr, |
| 218 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), | 218 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), |
| 219 base::MakeUnique<APIBindingHooks>(binding::RunJSFunction()), &refs); | 219 base::MakeUnique<APIBindingHooks>(binding::RunJSFunctionSync()), &refs); |
| 220 EXPECT_TRUE(refs.empty()); | 220 EXPECT_TRUE(refs.empty()); |
| 221 | 221 |
| 222 v8::HandleScope handle_scope(isolate()); | 222 v8::HandleScope handle_scope(isolate()); |
| 223 v8::Local<v8::Context> context = ContextLocal(); | 223 v8::Local<v8::Context> context = ContextLocal(); |
| 224 | 224 |
| 225 APIEventHandler event_handler( | 225 APIEventHandler event_handler( |
| 226 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); | 226 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); |
| 227 v8::Local<v8::Object> binding_object = binding.CreateInstance( | 227 v8::Local<v8::Object> binding_object = binding.CreateInstance( |
| 228 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs)); | 228 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs)); |
| 229 | 229 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 | 310 |
| 311 std::unique_ptr<base::ListValue> functions = | 311 std::unique_ptr<base::ListValue> functions = |
| 312 ListValueFromString(kRefFunctions); | 312 ListValueFromString(kRefFunctions); |
| 313 ASSERT_TRUE(functions); | 313 ASSERT_TRUE(functions); |
| 314 std::unique_ptr<base::ListValue> types = ListValueFromString(kTypes); | 314 std::unique_ptr<base::ListValue> types = ListValueFromString(kTypes); |
| 315 ASSERT_TRUE(types); | 315 ASSERT_TRUE(types); |
| 316 ArgumentSpec::RefMap refs; | 316 ArgumentSpec::RefMap refs; |
| 317 APIBinding binding( | 317 APIBinding binding( |
| 318 "test", functions.get(), types.get(), nullptr, | 318 "test", functions.get(), types.get(), nullptr, |
| 319 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), | 319 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), |
| 320 base::MakeUnique<APIBindingHooks>(binding::RunJSFunction()), &refs); | 320 base::MakeUnique<APIBindingHooks>(binding::RunJSFunctionSync()), &refs); |
| 321 EXPECT_EQ(2u, refs.size()); | 321 EXPECT_EQ(2u, refs.size()); |
| 322 EXPECT_TRUE(base::ContainsKey(refs, "refObj")); | 322 EXPECT_TRUE(base::ContainsKey(refs, "refObj")); |
| 323 EXPECT_TRUE(base::ContainsKey(refs, "refEnum")); | 323 EXPECT_TRUE(base::ContainsKey(refs, "refEnum")); |
| 324 | 324 |
| 325 v8::HandleScope handle_scope(isolate()); | 325 v8::HandleScope handle_scope(isolate()); |
| 326 v8::Local<v8::Context> context = ContextLocal(); | 326 v8::Local<v8::Context> context = ContextLocal(); |
| 327 | 327 |
| 328 APIEventHandler event_handler( | 328 APIEventHandler event_handler( |
| 329 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); | 329 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); |
| 330 v8::Local<v8::Object> binding_object = binding.CreateInstance( | 330 v8::Local<v8::Object> binding_object = binding.CreateInstance( |
| (...skipping 25 matching lines...) Expand all Loading... |
| 356 " 'name': 'restrictedTwo'," | 356 " 'name': 'restrictedTwo'," |
| 357 " 'parameters': []" | 357 " 'parameters': []" |
| 358 "}]"; | 358 "}]"; |
| 359 std::unique_ptr<base::ListValue> functions = | 359 std::unique_ptr<base::ListValue> functions = |
| 360 ListValueFromString(kRestrictedFunctions); | 360 ListValueFromString(kRestrictedFunctions); |
| 361 ASSERT_TRUE(functions); | 361 ASSERT_TRUE(functions); |
| 362 ArgumentSpec::RefMap refs; | 362 ArgumentSpec::RefMap refs; |
| 363 APIBinding binding( | 363 APIBinding binding( |
| 364 "test", functions.get(), nullptr, nullptr, | 364 "test", functions.get(), nullptr, nullptr, |
| 365 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), | 365 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), |
| 366 base::MakeUnique<APIBindingHooks>(binding::RunJSFunction()), &refs); | 366 base::MakeUnique<APIBindingHooks>(binding::RunJSFunctionSync()), &refs); |
| 367 | 367 |
| 368 v8::HandleScope handle_scope(isolate()); | 368 v8::HandleScope handle_scope(isolate()); |
| 369 v8::Local<v8::Context> context = ContextLocal(); | 369 v8::Local<v8::Context> context = ContextLocal(); |
| 370 | 370 |
| 371 auto is_available = [](const std::string& name) { | 371 auto is_available = [](const std::string& name) { |
| 372 std::set<std::string> functions = {"test.allowedOne", "test.allowedTwo", | 372 std::set<std::string> functions = {"test.allowedOne", "test.allowedTwo", |
| 373 "test.restrictedOne", | 373 "test.restrictedOne", |
| 374 "test.restrictedTwo"}; | 374 "test.restrictedTwo"}; |
| 375 EXPECT_TRUE(functions.count(name)); | 375 EXPECT_TRUE(functions.count(name)); |
| 376 return name == "test.allowedOne" || name == "test.allowedTwo"; | 376 return name == "test.allowedOne" || name == "test.allowedTwo"; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 399 TEST_F(APIBindingUnittest, TestEventCreation) { | 399 TEST_F(APIBindingUnittest, TestEventCreation) { |
| 400 const char kEvents[] = "[{'name': 'onFoo'}, {'name': 'onBar'}]"; | 400 const char kEvents[] = "[{'name': 'onFoo'}, {'name': 'onBar'}]"; |
| 401 std::unique_ptr<base::ListValue> events = ListValueFromString(kEvents); | 401 std::unique_ptr<base::ListValue> events = ListValueFromString(kEvents); |
| 402 ASSERT_TRUE(events); | 402 ASSERT_TRUE(events); |
| 403 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions); | 403 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions); |
| 404 ASSERT_TRUE(functions); | 404 ASSERT_TRUE(functions); |
| 405 ArgumentSpec::RefMap refs; | 405 ArgumentSpec::RefMap refs; |
| 406 APIBinding binding( | 406 APIBinding binding( |
| 407 "test", functions.get(), nullptr, events.get(), | 407 "test", functions.get(), nullptr, events.get(), |
| 408 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), | 408 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), |
| 409 base::MakeUnique<APIBindingHooks>(binding::RunJSFunction()), &refs); | 409 base::MakeUnique<APIBindingHooks>(binding::RunJSFunctionSync()), &refs); |
| 410 | 410 |
| 411 v8::HandleScope handle_scope(isolate()); | 411 v8::HandleScope handle_scope(isolate()); |
| 412 v8::Local<v8::Context> context = ContextLocal(); | 412 v8::Local<v8::Context> context = ContextLocal(); |
| 413 | 413 |
| 414 APIEventHandler event_handler( | 414 APIEventHandler event_handler( |
| 415 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); | 415 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); |
| 416 v8::Local<v8::Object> binding_object = binding.CreateInstance( | 416 v8::Local<v8::Object> binding_object = binding.CreateInstance( |
| 417 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs)); | 417 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs)); |
| 418 | 418 |
| 419 // Event behavior is tested in the APIEventHandler unittests as well as the | 419 // Event behavior is tested in the APIEventHandler unittests as well as the |
| (...skipping 15 matching lines...) Expand all Loading... |
| 435 EXPECT_FALSE(has_on_baz.FromJust()); | 435 EXPECT_FALSE(has_on_baz.FromJust()); |
| 436 } | 436 } |
| 437 | 437 |
| 438 TEST_F(APIBindingUnittest, TestDisposedContext) { | 438 TEST_F(APIBindingUnittest, TestDisposedContext) { |
| 439 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions); | 439 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions); |
| 440 ASSERT_TRUE(functions); | 440 ASSERT_TRUE(functions); |
| 441 ArgumentSpec::RefMap refs; | 441 ArgumentSpec::RefMap refs; |
| 442 APIBinding binding( | 442 APIBinding binding( |
| 443 "test", functions.get(), nullptr, nullptr, | 443 "test", functions.get(), nullptr, nullptr, |
| 444 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), | 444 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), |
| 445 base::MakeUnique<APIBindingHooks>(binding::RunJSFunction()), &refs); | 445 base::MakeUnique<APIBindingHooks>(binding::RunJSFunctionSync()), &refs); |
| 446 EXPECT_TRUE(refs.empty()); | 446 EXPECT_TRUE(refs.empty()); |
| 447 | 447 |
| 448 v8::HandleScope handle_scope(isolate()); | 448 v8::HandleScope handle_scope(isolate()); |
| 449 v8::Local<v8::Context> context = ContextLocal(); | 449 v8::Local<v8::Context> context = ContextLocal(); |
| 450 | 450 |
| 451 APIEventHandler event_handler( | 451 APIEventHandler event_handler( |
| 452 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); | 452 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); |
| 453 v8::Local<v8::Object> binding_object = binding.CreateInstance( | 453 v8::Local<v8::Object> binding_object = binding.CreateInstance( |
| 454 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs)); | 454 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs)); |
| 455 | 455 |
| 456 v8::Local<v8::Function> func = | 456 v8::Local<v8::Function> func = |
| 457 FunctionFromString(context, "(function(obj) { obj.oneString('foo'); })"); | 457 FunctionFromString(context, "(function(obj) { obj.oneString('foo'); })"); |
| 458 v8::Local<v8::Value> argv[] = {binding_object}; | 458 v8::Local<v8::Value> argv[] = {binding_object}; |
| 459 DisposeContext(); | 459 DisposeContext(); |
| 460 RunFunction(func, context, arraysize(argv), argv); | 460 RunFunction(func, context, arraysize(argv), argv); |
| 461 EXPECT_FALSE(HandlerWasInvoked()); | 461 EXPECT_FALSE(HandlerWasInvoked()); |
| 462 // This test passes if this does not crash, even under AddressSanitizer | 462 // This test passes if this does not crash, even under AddressSanitizer |
| 463 // builds. | 463 // builds. |
| 464 } | 464 } |
| 465 | 465 |
| 466 // Tests adding custom hooks for an API method. | 466 // Tests adding custom hooks for an API method. |
| 467 TEST_F(APIBindingUnittest, TestCustomHooks) { | 467 TEST_F(APIBindingUnittest, TestCustomHooks) { |
| 468 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions); | 468 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions); |
| 469 ASSERT_TRUE(functions); | 469 ASSERT_TRUE(functions); |
| 470 ArgumentSpec::RefMap refs; | 470 ArgumentSpec::RefMap refs; |
| 471 | 471 |
| 472 // Register a hook for the test.oneString method. | 472 // Register a hook for the test.oneString method. |
| 473 auto hooks = base::MakeUnique<APIBindingHooks>( | 473 auto hooks = base::MakeUnique<APIBindingHooks>( |
| 474 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); | 474 base::Bind(&RunFunctionOnGlobalAndReturnHandle)); |
| 475 bool did_call = false; | 475 bool did_call = false; |
| 476 auto hook = [](bool* did_call, const APISignature* signature, | 476 auto hook = [](bool* did_call, const APISignature* signature, |
| 477 gin::Arguments* arguments, | 477 v8::Local<v8::Context> context, |
| 478 std::vector<v8::Local<v8::Value>>* arguments, |
| 478 const ArgumentSpec::RefMap& ref_map) { | 479 const ArgumentSpec::RefMap& ref_map) { |
| 479 *did_call = true; | 480 *did_call = true; |
| 480 EXPECT_EQ(1, arguments->Length()); | 481 if (arguments->size() != 1u) { |
| 481 std::string argument; | 482 EXPECT_EQ(1u, arguments->size()); |
| 482 EXPECT_TRUE(arguments->GetNext(&argument)); | 483 return APIBindingHooks::RequestResult::HANDLED; |
| 483 EXPECT_EQ("foo", argument); | 484 } |
| 485 EXPECT_EQ("foo", gin::V8ToString(arguments->at(0))); |
| 484 return APIBindingHooks::RequestResult::HANDLED; | 486 return APIBindingHooks::RequestResult::HANDLED; |
| 485 }; | 487 }; |
| 486 hooks->RegisterHandleRequest("test.oneString", base::Bind(hook, &did_call)); | 488 hooks->RegisterHandleRequest("test.oneString", base::Bind(hook, &did_call)); |
| 487 | 489 |
| 488 APIBinding binding( | 490 APIBinding binding( |
| 489 "test", functions.get(), nullptr, nullptr, | 491 "test", functions.get(), nullptr, nullptr, |
| 490 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), | 492 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), |
| 491 std::move(hooks), &refs); | 493 std::move(hooks), &refs); |
| 492 EXPECT_TRUE(refs.empty()); | 494 EXPECT_TRUE(refs.empty()); |
| 493 | 495 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 507 RunFunction(func, context, 1, args); | 509 RunFunction(func, context, 1, args); |
| 508 EXPECT_TRUE(did_call); | 510 EXPECT_TRUE(did_call); |
| 509 | 511 |
| 510 // Other methods, like stringAndInt(), should behave normally. | 512 // Other methods, like stringAndInt(), should behave normally. |
| 511 ExpectPass(binding_object, "obj.stringAndInt('foo', 42);", "['foo',42]"); | 513 ExpectPass(binding_object, "obj.stringAndInt('foo', 42);", "['foo',42]"); |
| 512 } | 514 } |
| 513 | 515 |
| 514 TEST_F(APIBindingUnittest, TestJSCustomHook) { | 516 TEST_F(APIBindingUnittest, TestJSCustomHook) { |
| 515 // Register a hook for the test.oneString method. | 517 // Register a hook for the test.oneString method. |
| 516 auto hooks = base::MakeUnique<APIBindingHooks>( | 518 auto hooks = base::MakeUnique<APIBindingHooks>( |
| 517 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); | 519 base::Bind(&RunFunctionOnGlobalAndReturnHandle)); |
| 518 | 520 |
| 519 v8::HandleScope handle_scope(isolate()); | 521 v8::HandleScope handle_scope(isolate()); |
| 520 v8::Local<v8::Context> context = ContextLocal(); | 522 v8::Local<v8::Context> context = ContextLocal(); |
| 521 const char kRegisterHook[] = | 523 const char kRegisterHook[] = |
| 522 "(function(hooks) {\n" | 524 "(function(hooks) {\n" |
| 523 " hooks.setHandleRequest('oneString', function() {\n" | 525 " hooks.setHandleRequest('oneString', function() {\n" |
| 524 " this.requestArguments = Array.from(arguments);\n" | 526 " this.requestArguments = Array.from(arguments);\n" |
| 525 " });\n" | 527 " });\n" |
| 526 "})"; | 528 "})"; |
| 527 v8::Local<v8::String> source_string = | 529 v8::Local<v8::String> source_string = |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 std::unique_ptr<base::Value> response_args = | 567 std::unique_ptr<base::Value> response_args = |
| 566 GetBaseValuePropertyFromObject(context->Global(), context, | 568 GetBaseValuePropertyFromObject(context->Global(), context, |
| 567 "requestArguments"); | 569 "requestArguments"); |
| 568 ASSERT_TRUE(response_args); | 570 ASSERT_TRUE(response_args); |
| 569 EXPECT_EQ("[\"foo\"]", ValueToString(*response_args)); | 571 EXPECT_EQ("[\"foo\"]", ValueToString(*response_args)); |
| 570 | 572 |
| 571 // Other methods, like stringAndInt(), should behave normally. | 573 // Other methods, like stringAndInt(), should behave normally. |
| 572 ExpectPass(binding_object, "obj.stringAndInt('foo', 42);", "['foo',42]"); | 574 ExpectPass(binding_object, "obj.stringAndInt('foo', 42);", "['foo',42]"); |
| 573 } | 575 } |
| 574 | 576 |
| 577 // Tests the updateArgumentsPreValidate hook. |
| 578 TEST_F(APIBindingUnittest, TestUpdateArgumentsPreValidate) { |
| 579 // Register a hook for the test.oneString method. |
| 580 auto hooks = base::MakeUnique<APIBindingHooks>( |
| 581 base::Bind(&RunFunctionOnGlobalAndReturnHandle)); |
| 582 |
| 583 v8::HandleScope handle_scope(isolate()); |
| 584 v8::Local<v8::Context> context = ContextLocal(); |
| 585 const char kRegisterHook[] = |
| 586 "(function(hooks) {\n" |
| 587 " hooks.setUpdateArgumentsPreValidate('oneString', function() {\n" |
| 588 " this.requestArguments = Array.from(arguments);\n" |
| 589 " if (this.requestArguments[0] === true)\n" |
| 590 " return ['hooked']\n" |
| 591 " return this.requestArguments\n" |
| 592 " });\n" |
| 593 "})"; |
| 594 v8::Local<v8::String> source_string = |
| 595 gin::StringToV8(isolate(), kRegisterHook); |
| 596 v8::Local<v8::String> source_name = |
| 597 gin::StringToV8(isolate(), "custom_hook"); |
| 598 hooks->RegisterJsSource( |
| 599 v8::Global<v8::String>(isolate(), source_string), |
| 600 v8::Global<v8::String>(isolate(), source_name)); |
| 601 |
| 602 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions); |
| 603 ASSERT_TRUE(functions); |
| 604 ArgumentSpec::RefMap refs; |
| 605 |
| 606 APIBinding binding( |
| 607 "test", functions.get(), nullptr, nullptr, |
| 608 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), |
| 609 std::move(hooks), &refs); |
| 610 EXPECT_TRUE(refs.empty()); |
| 611 |
| 612 APIEventHandler event_handler( |
| 613 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); |
| 614 v8::Local<v8::Object> binding_object = binding.CreateInstance( |
| 615 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs)); |
| 616 |
| 617 // Call the method with a hook. Since the hook updates arguments before |
| 618 // validation, we should be able to pass in invalid arguments and still |
| 619 // have the hook called. |
| 620 ExpectFailure(binding_object, "obj.oneString(false);", kError); |
| 621 EXPECT_EQ("[false]", GetStringPropertyFromObject( |
| 622 context->Global(), context, "requestArguments")); |
| 623 |
| 624 ExpectPass(binding_object, "obj.oneString(true);", "['hooked']"); |
| 625 EXPECT_EQ("[true]", GetStringPropertyFromObject( |
| 626 context->Global(), context, "requestArguments")); |
| 627 |
| 628 // Other methods, like stringAndInt(), should behave normally. |
| 629 ExpectPass(binding_object, "obj.stringAndInt('foo', 42);", "['foo',42]"); |
| 630 } |
| 631 |
| 632 // Tests the updateArgumentsPreValidate hook. |
| 633 TEST_F(APIBindingUnittest, TestThrowInUpdateArgumentsPreValidate) { |
| 634 auto run_js_and_allow_error = [](v8::Local<v8::Function> function, |
| 635 v8::Local<v8::Context> context, |
| 636 int argc, |
| 637 v8::Local<v8::Value> argv[]) { |
| 638 v8::MaybeLocal<v8::Value> maybe_result = |
| 639 function->Call(context, context->Global(), argc, argv); |
| 640 v8::Global<v8::Value> result; |
| 641 v8::Local<v8::Value> local; |
| 642 if (maybe_result.ToLocal(&local)) |
| 643 result.Reset(context->GetIsolate(), local); |
| 644 return result; |
| 645 }; |
| 646 |
| 647 // Register a hook for the test.oneString method. |
| 648 auto hooks = base::MakeUnique<APIBindingHooks>( |
| 649 base::Bind(run_js_and_allow_error)); |
| 650 |
| 651 v8::HandleScope handle_scope(isolate()); |
| 652 v8::Local<v8::Context> context = ContextLocal(); |
| 653 const char kRegisterHook[] = |
| 654 "(function(hooks) {\n" |
| 655 " hooks.setUpdateArgumentsPreValidate('oneString', function() {\n" |
| 656 " throw new Error('Custom Hook Error');\n" |
| 657 " });\n" |
| 658 "})"; |
| 659 v8::Local<v8::String> source_string = |
| 660 gin::StringToV8(isolate(), kRegisterHook); |
| 661 v8::Local<v8::String> source_name = |
| 662 gin::StringToV8(isolate(), "custom_hook"); |
| 663 hooks->RegisterJsSource( |
| 664 v8::Global<v8::String>(isolate(), source_string), |
| 665 v8::Global<v8::String>(isolate(), source_name)); |
| 666 |
| 667 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions); |
| 668 ASSERT_TRUE(functions); |
| 669 ArgumentSpec::RefMap refs; |
| 670 |
| 671 APIBinding binding( |
| 672 "test", functions.get(), nullptr, nullptr, |
| 673 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), |
| 674 std::move(hooks), &refs); |
| 675 EXPECT_TRUE(refs.empty()); |
| 676 |
| 677 APIEventHandler event_handler( |
| 678 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); |
| 679 v8::Local<v8::Object> binding_object = binding.CreateInstance( |
| 680 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs)); |
| 681 |
| 682 v8::Local<v8::Function> function = |
| 683 FunctionFromString(context, |
| 684 "(function(obj) { return obj.oneString('ping'); })"); |
| 685 v8::Local<v8::Value> args[] = {binding_object}; |
| 686 RunFunctionAndExpectError(function, context, v8::Undefined(isolate()), |
| 687 arraysize(args), args, |
| 688 "Uncaught Error: Custom Hook Error"); |
| 689 |
| 690 // Other methods, like stringAndInt(), should behave normally. |
| 691 ExpectPass(binding_object, "obj.stringAndInt('foo', 42);", "['foo',42]"); |
| 692 } |
| 693 |
| 575 } // namespace extensions | 694 } // namespace extensions |
| OLD | NEW |