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 |