Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Side by Side Diff: extensions/renderer/api_binding_unittest.cc

Issue 2598123002: [Extensions Bindings] Add support for updateArgumentsPreValidate (Closed)
Patch Set: rebase Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 arguments_.reset(); 189 arguments_.reset();
190 } 190 }
191 191
192 TEST_F(APIBindingUnittest, Test) { 192 TEST_F(APIBindingUnittest, Test) {
193 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions); 193 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions);
194 ASSERT_TRUE(functions); 194 ASSERT_TRUE(functions);
195 ArgumentSpec::RefMap refs; 195 ArgumentSpec::RefMap refs;
196 APIBinding binding( 196 APIBinding binding(
197 "test", *functions, nullptr, nullptr, 197 "test", *functions, nullptr, nullptr,
198 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), 198 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)),
199 base::MakeUnique<APIBindingHooks>(binding::RunJSFunction()), &refs); 199 base::MakeUnique<APIBindingHooks>(binding::RunJSFunctionSync()), &refs);
200 EXPECT_TRUE(refs.empty()); 200 EXPECT_TRUE(refs.empty());
201 201
202 v8::HandleScope handle_scope(isolate()); 202 v8::HandleScope handle_scope(isolate());
203 v8::Local<v8::Context> context = ContextLocal(); 203 v8::Local<v8::Context> context = ContextLocal();
204 204
205 APIEventHandler event_handler( 205 APIEventHandler event_handler(
206 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); 206 base::Bind(&RunFunctionOnGlobalAndIgnoreResult));
207 v8::Local<v8::Object> binding_object = binding.CreateInstance( 207 v8::Local<v8::Object> binding_object = binding.CreateInstance(
208 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs)); 208 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs));
209 209
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 290
291 std::unique_ptr<base::ListValue> functions = 291 std::unique_ptr<base::ListValue> functions =
292 ListValueFromString(kRefFunctions); 292 ListValueFromString(kRefFunctions);
293 ASSERT_TRUE(functions); 293 ASSERT_TRUE(functions);
294 std::unique_ptr<base::ListValue> types = ListValueFromString(kTypes); 294 std::unique_ptr<base::ListValue> types = ListValueFromString(kTypes);
295 ASSERT_TRUE(types); 295 ASSERT_TRUE(types);
296 ArgumentSpec::RefMap refs; 296 ArgumentSpec::RefMap refs;
297 APIBinding binding( 297 APIBinding binding(
298 "test", *functions, types.get(), nullptr, 298 "test", *functions, types.get(), nullptr,
299 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), 299 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)),
300 base::MakeUnique<APIBindingHooks>(binding::RunJSFunction()), &refs); 300 base::MakeUnique<APIBindingHooks>(binding::RunJSFunctionSync()), &refs);
301 EXPECT_EQ(2u, refs.size()); 301 EXPECT_EQ(2u, refs.size());
302 EXPECT_TRUE(base::ContainsKey(refs, "refObj")); 302 EXPECT_TRUE(base::ContainsKey(refs, "refObj"));
303 EXPECT_TRUE(base::ContainsKey(refs, "refEnum")); 303 EXPECT_TRUE(base::ContainsKey(refs, "refEnum"));
304 304
305 v8::HandleScope handle_scope(isolate()); 305 v8::HandleScope handle_scope(isolate());
306 v8::Local<v8::Context> context = ContextLocal(); 306 v8::Local<v8::Context> context = ContextLocal();
307 307
308 APIEventHandler event_handler( 308 APIEventHandler event_handler(
309 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); 309 base::Bind(&RunFunctionOnGlobalAndIgnoreResult));
310 v8::Local<v8::Object> binding_object = binding.CreateInstance( 310 v8::Local<v8::Object> binding_object = binding.CreateInstance(
(...skipping 25 matching lines...) Expand all
336 " 'name': 'restrictedTwo'," 336 " 'name': 'restrictedTwo',"
337 " 'parameters': []" 337 " 'parameters': []"
338 "}]"; 338 "}]";
339 std::unique_ptr<base::ListValue> functions = 339 std::unique_ptr<base::ListValue> functions =
340 ListValueFromString(kRestrictedFunctions); 340 ListValueFromString(kRestrictedFunctions);
341 ASSERT_TRUE(functions); 341 ASSERT_TRUE(functions);
342 ArgumentSpec::RefMap refs; 342 ArgumentSpec::RefMap refs;
343 APIBinding binding( 343 APIBinding binding(
344 "test", *functions, nullptr, nullptr, 344 "test", *functions, nullptr, nullptr,
345 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), 345 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)),
346 base::MakeUnique<APIBindingHooks>(binding::RunJSFunction()), &refs); 346 base::MakeUnique<APIBindingHooks>(binding::RunJSFunctionSync()), &refs);
347 347
348 v8::HandleScope handle_scope(isolate()); 348 v8::HandleScope handle_scope(isolate());
349 v8::Local<v8::Context> context = ContextLocal(); 349 v8::Local<v8::Context> context = ContextLocal();
350 350
351 auto is_available = [](const std::string& name) { 351 auto is_available = [](const std::string& name) {
352 std::set<std::string> functions = {"test.allowedOne", "test.allowedTwo", 352 std::set<std::string> functions = {"test.allowedOne", "test.allowedTwo",
353 "test.restrictedOne", 353 "test.restrictedOne",
354 "test.restrictedTwo"}; 354 "test.restrictedTwo"};
355 EXPECT_TRUE(functions.count(name)); 355 EXPECT_TRUE(functions.count(name));
356 return name == "test.allowedOne" || name == "test.allowedTwo"; 356 return name == "test.allowedOne" || name == "test.allowedTwo";
(...skipping 22 matching lines...) Expand all
379 TEST_F(APIBindingUnittest, TestEventCreation) { 379 TEST_F(APIBindingUnittest, TestEventCreation) {
380 const char kEvents[] = "[{'name': 'onFoo'}, {'name': 'onBar'}]"; 380 const char kEvents[] = "[{'name': 'onFoo'}, {'name': 'onBar'}]";
381 std::unique_ptr<base::ListValue> events = ListValueFromString(kEvents); 381 std::unique_ptr<base::ListValue> events = ListValueFromString(kEvents);
382 ASSERT_TRUE(events); 382 ASSERT_TRUE(events);
383 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions); 383 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions);
384 ASSERT_TRUE(functions); 384 ASSERT_TRUE(functions);
385 ArgumentSpec::RefMap refs; 385 ArgumentSpec::RefMap refs;
386 APIBinding binding( 386 APIBinding binding(
387 "test", *functions, nullptr, events.get(), 387 "test", *functions, nullptr, events.get(),
388 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), 388 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)),
389 base::MakeUnique<APIBindingHooks>(binding::RunJSFunction()), &refs); 389 base::MakeUnique<APIBindingHooks>(binding::RunJSFunctionSync()), &refs);
390 390
391 v8::HandleScope handle_scope(isolate()); 391 v8::HandleScope handle_scope(isolate());
392 v8::Local<v8::Context> context = ContextLocal(); 392 v8::Local<v8::Context> context = ContextLocal();
393 393
394 APIEventHandler event_handler( 394 APIEventHandler event_handler(
395 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); 395 base::Bind(&RunFunctionOnGlobalAndIgnoreResult));
396 v8::Local<v8::Object> binding_object = binding.CreateInstance( 396 v8::Local<v8::Object> binding_object = binding.CreateInstance(
397 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs)); 397 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs));
398 398
399 // Event behavior is tested in the APIEventHandler unittests as well as the 399 // Event behavior is tested in the APIEventHandler unittests as well as the
(...skipping 15 matching lines...) Expand all
415 EXPECT_FALSE(has_on_baz.FromJust()); 415 EXPECT_FALSE(has_on_baz.FromJust());
416 } 416 }
417 417
418 TEST_F(APIBindingUnittest, TestDisposedContext) { 418 TEST_F(APIBindingUnittest, TestDisposedContext) {
419 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions); 419 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions);
420 ASSERT_TRUE(functions); 420 ASSERT_TRUE(functions);
421 ArgumentSpec::RefMap refs; 421 ArgumentSpec::RefMap refs;
422 APIBinding binding( 422 APIBinding binding(
423 "test", *functions, nullptr, nullptr, 423 "test", *functions, nullptr, nullptr,
424 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), 424 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)),
425 base::MakeUnique<APIBindingHooks>(binding::RunJSFunction()), &refs); 425 base::MakeUnique<APIBindingHooks>(binding::RunJSFunctionSync()), &refs);
426 EXPECT_TRUE(refs.empty()); 426 EXPECT_TRUE(refs.empty());
427 427
428 v8::HandleScope handle_scope(isolate()); 428 v8::HandleScope handle_scope(isolate());
429 v8::Local<v8::Context> context = ContextLocal(); 429 v8::Local<v8::Context> context = ContextLocal();
430 430
431 APIEventHandler event_handler( 431 APIEventHandler event_handler(
432 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); 432 base::Bind(&RunFunctionOnGlobalAndIgnoreResult));
433 v8::Local<v8::Object> binding_object = binding.CreateInstance( 433 v8::Local<v8::Object> binding_object = binding.CreateInstance(
434 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs)); 434 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs));
435 435
436 v8::Local<v8::Function> func = 436 v8::Local<v8::Function> func =
437 FunctionFromString(context, "(function(obj) { obj.oneString('foo'); })"); 437 FunctionFromString(context, "(function(obj) { obj.oneString('foo'); })");
438 v8::Local<v8::Value> argv[] = {binding_object}; 438 v8::Local<v8::Value> argv[] = {binding_object};
439 DisposeContext(); 439 DisposeContext();
440 RunFunction(func, context, arraysize(argv), argv); 440 RunFunction(func, context, arraysize(argv), argv);
441 EXPECT_FALSE(HandlerWasInvoked()); 441 EXPECT_FALSE(HandlerWasInvoked());
442 // This test passes if this does not crash, even under AddressSanitizer 442 // This test passes if this does not crash, even under AddressSanitizer
443 // builds. 443 // builds.
444 } 444 }
445 445
446 // Tests adding custom hooks for an API method. 446 // Tests adding custom hooks for an API method.
447 TEST_F(APIBindingUnittest, TestCustomHooks) { 447 TEST_F(APIBindingUnittest, TestCustomHooks) {
448 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions); 448 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions);
449 ASSERT_TRUE(functions); 449 ASSERT_TRUE(functions);
450 ArgumentSpec::RefMap refs; 450 ArgumentSpec::RefMap refs;
451 451
452 // Register a hook for the test.oneString method. 452 // Register a hook for the test.oneString method.
453 auto hooks = base::MakeUnique<APIBindingHooks>( 453 auto hooks = base::MakeUnique<APIBindingHooks>(
454 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); 454 base::Bind(&RunFunctionOnGlobalAndReturnHandle));
455 bool did_call = false; 455 bool did_call = false;
456 auto hook = [](bool* did_call, const APISignature* signature, 456 auto hook = [](bool* did_call, const APISignature* signature,
457 gin::Arguments* arguments, 457 v8::Local<v8::Context> context,
458 std::vector<v8::Local<v8::Value>>* arguments,
458 const ArgumentSpec::RefMap& ref_map) { 459 const ArgumentSpec::RefMap& ref_map) {
459 *did_call = true; 460 *did_call = true;
460 EXPECT_EQ(1, arguments->Length()); 461 if (arguments->size() != 1u) {
461 std::string argument; 462 EXPECT_EQ(1u, arguments->size());
462 EXPECT_TRUE(arguments->GetNext(&argument)); 463 return APIBindingHooks::RequestResult::HANDLED;
463 EXPECT_EQ("foo", argument); 464 }
465 EXPECT_EQ("foo", gin::V8ToString(arguments->at(0)));
464 return APIBindingHooks::RequestResult::HANDLED; 466 return APIBindingHooks::RequestResult::HANDLED;
465 }; 467 };
466 hooks->RegisterHandleRequest("test.oneString", base::Bind(hook, &did_call)); 468 hooks->RegisterHandleRequest("test.oneString", base::Bind(hook, &did_call));
467 469
468 APIBinding binding( 470 APIBinding binding(
469 "test", *functions, nullptr, nullptr, 471 "test", *functions, nullptr, nullptr,
470 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)), 472 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)),
471 std::move(hooks), &refs); 473 std::move(hooks), &refs);
472 EXPECT_TRUE(refs.empty()); 474 EXPECT_TRUE(refs.empty());
473 475
(...skipping 13 matching lines...) Expand all
487 RunFunction(func, context, 1, args); 489 RunFunction(func, context, 1, args);
488 EXPECT_TRUE(did_call); 490 EXPECT_TRUE(did_call);
489 491
490 // Other methods, like stringAndInt(), should behave normally. 492 // Other methods, like stringAndInt(), should behave normally.
491 ExpectPass(binding_object, "obj.stringAndInt('foo', 42);", "['foo',42]"); 493 ExpectPass(binding_object, "obj.stringAndInt('foo', 42);", "['foo',42]");
492 } 494 }
493 495
494 TEST_F(APIBindingUnittest, TestJSCustomHook) { 496 TEST_F(APIBindingUnittest, TestJSCustomHook) {
495 // Register a hook for the test.oneString method. 497 // Register a hook for the test.oneString method.
496 auto hooks = base::MakeUnique<APIBindingHooks>( 498 auto hooks = base::MakeUnique<APIBindingHooks>(
497 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); 499 base::Bind(&RunFunctionOnGlobalAndReturnHandle));
498 500
499 v8::HandleScope handle_scope(isolate()); 501 v8::HandleScope handle_scope(isolate());
500 v8::Local<v8::Context> context = ContextLocal(); 502 v8::Local<v8::Context> context = ContextLocal();
501 const char kRegisterHook[] = 503 const char kRegisterHook[] =
502 "(function(hooks) {\n" 504 "(function(hooks) {\n"
503 " hooks.setHandleRequest('oneString', function() {\n" 505 " hooks.setHandleRequest('oneString', function() {\n"
504 " this.requestArguments = Array.from(arguments);\n" 506 " this.requestArguments = Array.from(arguments);\n"
505 " });\n" 507 " });\n"
506 "})"; 508 "})";
507 v8::Local<v8::String> source_string = 509 v8::Local<v8::String> source_string =
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 std::unique_ptr<base::Value> response_args = 547 std::unique_ptr<base::Value> response_args =
546 GetBaseValuePropertyFromObject(context->Global(), context, 548 GetBaseValuePropertyFromObject(context->Global(), context,
547 "requestArguments"); 549 "requestArguments");
548 ASSERT_TRUE(response_args); 550 ASSERT_TRUE(response_args);
549 EXPECT_EQ("[\"foo\"]", ValueToString(*response_args)); 551 EXPECT_EQ("[\"foo\"]", ValueToString(*response_args));
550 552
551 // Other methods, like stringAndInt(), should behave normally. 553 // Other methods, like stringAndInt(), should behave normally.
552 ExpectPass(binding_object, "obj.stringAndInt('foo', 42);", "['foo',42]"); 554 ExpectPass(binding_object, "obj.stringAndInt('foo', 42);", "['foo',42]");
553 } 555 }
554 556
557 // Tests the updateArgumentsPreValidate hook.
jbroman 2017/01/02 19:46:38 It looks like it's legal for this hook to throw an
Devlin 2017/01/04 17:57:02 Done.
558 TEST_F(APIBindingUnittest, TestUpdateArgumentsPreValidate) {
559 // Register a hook for the test.oneString method.
560 auto hooks = base::MakeUnique<APIBindingHooks>(
561 base::Bind(&RunFunctionOnGlobalAndReturnHandle));
562
563 v8::HandleScope handle_scope(isolate());
564 v8::Local<v8::Context> context = ContextLocal();
565 const char kRegisterHook[] =
566 "(function(hooks) {\n"
567 " hooks.setUpdateArgumentsPreValidate('oneString', function() {\n"
568 " this.requestArguments = Array.from(arguments);\n"
569 " if (this.requestArguments[0] === true)\n"
570 " return ['hooked']\n"
571 " return this.requestArguments\n"
572 " });\n"
573 "})";
574 v8::Local<v8::String> source_string =
575 gin::StringToV8(isolate(), kRegisterHook);
576 v8::Local<v8::String> source_name =
577 gin::StringToV8(isolate(), "custom_hook");
578 hooks->RegisterJsSource(
579 v8::Global<v8::String>(isolate(), source_string),
580 v8::Global<v8::String>(isolate(), source_name));
581
582 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions);
583 ASSERT_TRUE(functions);
584 ArgumentSpec::RefMap refs;
585
586 APIBinding binding(
587 "test", *functions, nullptr, nullptr,
588 base::Bind(&APIBindingUnittest::OnFunctionCall, base::Unretained(this)),
589 std::move(hooks), &refs);
590 EXPECT_TRUE(refs.empty());
591
592 APIEventHandler event_handler(
593 base::Bind(&RunFunctionOnGlobalAndIgnoreResult));
594 v8::Local<v8::Object> binding_object = binding.CreateInstance(
595 context, isolate(), &event_handler, base::Bind(&AllowAllAPIs));
596
597 // Call the method with a hook. Since the hook updates arguments before
598 // validation, we should be able to pass in invalid arguments and still
599 // have the hook called.
600 ExpectFailure(binding_object, "obj.oneString(false);", kError);
601 // TODO(devlin): Add a utility method to retrieve a stringified property from
602 // an object; we do this enough.
603 std::unique_ptr<base::Value> response_args =
604 GetBaseValuePropertyFromObject(context->Global(), context,
605 "requestArguments");
606 ASSERT_TRUE(response_args);
607 EXPECT_EQ("[false]", ValueToString(*response_args));
608
609 ExpectPass(binding_object, "obj.oneString(true);", "['hooked']");
610 response_args =
611 GetBaseValuePropertyFromObject(context->Global(), context,
612 "requestArguments");
613 ASSERT_TRUE(response_args);
614 EXPECT_EQ("[true]", ValueToString(*response_args));
615
616 // Other methods, like stringAndInt(), should behave normally.
617 ExpectPass(binding_object, "obj.stringAndInt('foo', 42);", "['foo',42]");
618 }
619
555 } // namespace extensions 620 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698