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

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

Issue 2722463006: [Extensions Bindings] Notify of event unregistration on invalidation (Closed)
Patch Set: nits Created 3 years, 9 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 "extensions/renderer/api_event_handler.h" 5 #include "extensions/renderer/api_event_handler.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback_helpers.h" 8 #include "base/callback_helpers.h"
9 #include "base/memory/ptr_util.h" 9 #include "base/memory/ptr_util.h"
10 #include "base/test/mock_callback.h" 10 #include "base/test/mock_callback.h"
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 121
122 { 122 {
123 v8::Local<v8::Value> argv[] = {event}; 123 v8::Local<v8::Value> argv[] = {event};
124 v8::Local<v8::Value> result = 124 v8::Local<v8::Value> result =
125 RunFunction(has_listeners_function, context, arraysize(argv), argv); 125 RunFunction(has_listeners_function, context, arraysize(argv), argv);
126 bool has_listeners = false; 126 bool has_listeners = false;
127 EXPECT_TRUE( 127 EXPECT_TRUE(
128 gin::Converter<bool>::FromV8(isolate(), result, &has_listeners)); 128 gin::Converter<bool>::FromV8(isolate(), result, &has_listeners));
129 EXPECT_FALSE(has_listeners); 129 EXPECT_FALSE(has_listeners);
130 } 130 }
131
132 handler.InvalidateContext(context);
131 } 133 }
132 134
133 // Tests listening for and firing different events. 135 // Tests listening for and firing different events.
134 TEST_F(APIEventHandlerTest, FiringEvents) { 136 TEST_F(APIEventHandlerTest, FiringEvents) {
135 const char kAlphaName[] = "alpha"; 137 const char kAlphaName[] = "alpha";
136 const char kBetaName[] = "beta"; 138 const char kBetaName[] = "beta";
137 v8::HandleScope handle_scope(isolate()); 139 v8::HandleScope handle_scope(isolate());
138 v8::Local<v8::Context> context = ContextLocal(); 140 v8::Local<v8::Context> context = ContextLocal();
139 141
140 APIEventHandler handler(base::Bind(&RunFunctionOnGlobalAndIgnoreResult), 142 APIEventHandler handler(base::Bind(&RunFunctionOnGlobalAndIgnoreResult),
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 221
220 handler.FireEventInContext(kAlphaName, context, base::ListValue()); 222 handler.FireEventInContext(kAlphaName, context, base::ListValue());
221 EXPECT_EQ(2, get_fired_count("alphaCount1")); 223 EXPECT_EQ(2, get_fired_count("alphaCount1"));
222 EXPECT_EQ(2, get_fired_count("alphaCount2")); 224 EXPECT_EQ(2, get_fired_count("alphaCount2"));
223 EXPECT_EQ(0, get_fired_count("betaCount")); 225 EXPECT_EQ(0, get_fired_count("betaCount"));
224 226
225 handler.FireEventInContext(kBetaName, context, base::ListValue()); 227 handler.FireEventInContext(kBetaName, context, base::ListValue());
226 EXPECT_EQ(2, get_fired_count("alphaCount1")); 228 EXPECT_EQ(2, get_fired_count("alphaCount1"));
227 EXPECT_EQ(2, get_fired_count("alphaCount2")); 229 EXPECT_EQ(2, get_fired_count("alphaCount2"));
228 EXPECT_EQ(1, get_fired_count("betaCount")); 230 EXPECT_EQ(1, get_fired_count("betaCount"));
231
232 handler.InvalidateContext(context);
229 } 233 }
230 234
231 // Tests firing events with arguments. 235 // Tests firing events with arguments.
232 TEST_F(APIEventHandlerTest, EventArguments) { 236 TEST_F(APIEventHandlerTest, EventArguments) {
233 v8::HandleScope handle_scope(isolate()); 237 v8::HandleScope handle_scope(isolate());
234 v8::Local<v8::Context> context = ContextLocal(); 238 v8::Local<v8::Context> context = ContextLocal();
235 239
236 const char kEventName[] = "alpha"; 240 const char kEventName[] = "alpha";
237 APIEventHandler handler(base::Bind(&RunFunctionOnGlobalAndIgnoreResult), 241 APIEventHandler handler(base::Bind(&RunFunctionOnGlobalAndIgnoreResult),
238 base::Bind(&DoNothingOnEventListenersChanged)); 242 base::Bind(&DoNothingOnEventListenersChanged));
(...skipping 17 matching lines...) Expand all
256 } 260 }
257 261
258 const char kArguments[] = "['foo',1,{'prop1':'bar'}]"; 262 const char kArguments[] = "['foo',1,{'prop1':'bar'}]";
259 std::unique_ptr<base::ListValue> event_args = ListValueFromString(kArguments); 263 std::unique_ptr<base::ListValue> event_args = ListValueFromString(kArguments);
260 ASSERT_TRUE(event_args); 264 ASSERT_TRUE(event_args);
261 handler.FireEventInContext(kEventName, context, *event_args); 265 handler.FireEventInContext(kEventName, context, *event_args);
262 266
263 EXPECT_EQ( 267 EXPECT_EQ(
264 ReplaceSingleQuotes(kArguments), 268 ReplaceSingleQuotes(kArguments),
265 GetStringPropertyFromObject(context->Global(), context, "eventArgs")); 269 GetStringPropertyFromObject(context->Global(), context, "eventArgs"));
270
271 handler.InvalidateContext(context);
266 } 272 }
267 273
268 // Test dispatching events to multiple contexts. 274 // Test dispatching events to multiple contexts.
269 TEST_F(APIEventHandlerTest, MultipleContexts) { 275 TEST_F(APIEventHandlerTest, MultipleContexts) {
270 v8::HandleScope handle_scope(isolate()); 276 v8::HandleScope handle_scope(isolate());
271 277
272 v8::Local<v8::Context> context_a = ContextLocal(); 278 v8::Local<v8::Context> context_a = ContextLocal();
273 v8::Local<v8::Context> context_b = v8::Context::New(isolate()); 279 v8::Local<v8::Context> context_b = v8::Context::New(isolate());
274 gin::ContextHolder holder_b(isolate()); 280 gin::ContextHolder holder_b(isolate());
275 holder_b.SetContext(context_b); 281 holder_b.SetContext(context_b);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 { 347 {
342 EXPECT_EQ("\"result_a:alpha\"", 348 EXPECT_EQ("\"result_a:alpha\"",
343 GetStringPropertyFromObject(context_a->Global(), context_a, 349 GetStringPropertyFromObject(context_a->Global(), context_a,
344 "eventArgs")); 350 "eventArgs"));
345 } 351 }
346 { 352 {
347 EXPECT_EQ("\"result_b:beta\"", 353 EXPECT_EQ("\"result_b:beta\"",
348 GetStringPropertyFromObject(context_b->Global(), context_b, 354 GetStringPropertyFromObject(context_b->Global(), context_b,
349 "eventArgs")); 355 "eventArgs"));
350 } 356 }
357
358 handler.InvalidateContext(context_a);
359 handler.InvalidateContext(context_b);
351 } 360 }
352 361
353 TEST_F(APIEventHandlerTest, DifferentCallingMethods) { 362 TEST_F(APIEventHandlerTest, DifferentCallingMethods) {
354 v8::HandleScope handle_scope(isolate()); 363 v8::HandleScope handle_scope(isolate());
355 v8::Local<v8::Context> context = ContextLocal(); 364 v8::Local<v8::Context> context = ContextLocal();
356 365
357 const char kEventName[] = "alpha"; 366 const char kEventName[] = "alpha";
358 APIEventHandler handler(base::Bind(&RunFunctionOnGlobalAndIgnoreResult), 367 APIEventHandler handler(base::Bind(&RunFunctionOnGlobalAndIgnoreResult),
359 base::Bind(&DoNothingOnEventListenersChanged)); 368 base::Bind(&DoNothingOnEventListenersChanged));
360 v8::Local<v8::Object> event = 369 v8::Local<v8::Object> event =
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 " event.addListener(function listener() {\n" 405 " event.addListener(function listener() {\n"
397 " event.hasListener(listener);\n" 406 " event.hasListener(listener);\n"
398 " });\n" 407 " });\n"
399 "})"; 408 "})";
400 { 409 {
401 v8::Local<v8::Value> args[] = {event}; 410 v8::Local<v8::Value> args[] = {event};
402 RunFunction(FunctionFromString(context, kAddListenerOnEventWithCapture), 411 RunFunction(FunctionFromString(context, kAddListenerOnEventWithCapture),
403 context, 1, args); 412 context, 1, args);
404 } 413 }
405 EXPECT_EQ(2u, handler.GetNumEventListenersForTesting(kEventName, context)); 414 EXPECT_EQ(2u, handler.GetNumEventListenersForTesting(kEventName, context));
415
416 handler.InvalidateContext(context);
406 } 417 }
407 418
408 TEST_F(APIEventHandlerTest, TestDispatchFromJs) { 419 TEST_F(APIEventHandlerTest, TestDispatchFromJs) {
409 v8::HandleScope handle_scope(isolate()); 420 v8::HandleScope handle_scope(isolate());
410 v8::Local<v8::Context> context = ContextLocal(); 421 v8::Local<v8::Context> context = ContextLocal();
411 422
412 APIEventHandler handler(base::Bind(&RunFunctionOnGlobalAndIgnoreResult), 423 APIEventHandler handler(base::Bind(&RunFunctionOnGlobalAndIgnoreResult),
413 base::Bind(&DoNothingOnEventListenersChanged)); 424 base::Bind(&DoNothingOnEventListenersChanged));
414 v8::Local<v8::Object> event = handler.CreateEventInstance("alpha", context); 425 v8::Local<v8::Object> event = handler.CreateEventInstance("alpha", context);
415 ASSERT_FALSE(event.IsEmpty()); 426 ASSERT_FALSE(event.IsEmpty());
(...skipping 20 matching lines...) Expand all
436 context, 447 context,
437 "(function(event) { event.dispatch(42, 'foo', {bar: 'baz'}); })"); 448 "(function(event) { event.dispatch(42, 'foo', {bar: 'baz'}); })");
438 { 449 {
439 v8::Local<v8::Value> argv[] = {event}; 450 v8::Local<v8::Value> argv[] = {event};
440 RunFunctionOnGlobal(fire_event_function, context, arraysize(argv), argv); 451 RunFunctionOnGlobal(fire_event_function, context, arraysize(argv), argv);
441 } 452 }
442 453
443 EXPECT_EQ("[42,\"foo\",{\"bar\":\"baz\"}]", 454 EXPECT_EQ("[42,\"foo\",{\"bar\":\"baz\"}]",
444 GetStringPropertyFromObject( 455 GetStringPropertyFromObject(
445 context->Global(), context, "eventArgs")); 456 context->Global(), context, "eventArgs"));
457
458 handler.InvalidateContext(context);
446 } 459 }
447 460
448 // Test listeners that remove themselves in their handling of the event. 461 // Test listeners that remove themselves in their handling of the event.
449 TEST_F(APIEventHandlerTest, RemovingListenersWhileHandlingEvent) { 462 TEST_F(APIEventHandlerTest, RemovingListenersWhileHandlingEvent) {
450 v8::HandleScope handle_scope(isolate()); 463 v8::HandleScope handle_scope(isolate());
451 v8::Local<v8::Context> context = ContextLocal(); 464 v8::Local<v8::Context> context = ContextLocal();
452 465
453 APIEventHandler handler(base::Bind(&RunFunctionOnGlobalAndIgnoreResult), 466 APIEventHandler handler(base::Bind(&RunFunctionOnGlobalAndIgnoreResult),
454 base::Bind(&DoNothingOnEventListenersChanged)); 467 base::Bind(&DoNothingOnEventListenersChanged));
455 const char kEventName[] = "alpha"; 468 const char kEventName[] = "alpha";
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
492 v8::Local<v8::Value> argv[] = {event, listener}; 505 v8::Local<v8::Value> argv[] = {event, listener};
493 RunFunctionOnGlobal(add_listener_function, context, arraysize(argv), argv); 506 RunFunctionOnGlobal(add_listener_function, context, arraysize(argv), argv);
494 } 507 }
495 508
496 // Fire the event. All listeners should be removed (and we shouldn't crash). 509 // Fire the event. All listeners should be removed (and we shouldn't crash).
497 EXPECT_EQ(kNumListeners, 510 EXPECT_EQ(kNumListeners,
498 handler.GetNumEventListenersForTesting(kEventName, context)); 511 handler.GetNumEventListenersForTesting(kEventName, context));
499 handler.FireEventInContext(kEventName, context, base::ListValue()); 512 handler.FireEventInContext(kEventName, context, base::ListValue());
500 EXPECT_EQ(0u, handler.GetNumEventListenersForTesting(kEventName, context)); 513 EXPECT_EQ(0u, handler.GetNumEventListenersForTesting(kEventName, context));
501 514
515 handler.InvalidateContext(context);
502 // TODO(devlin): Another possible test: register listener a and listener b, 516 // TODO(devlin): Another possible test: register listener a and listener b,
503 // where a removes b and b removes a. Theoretically, only one should be 517 // where a removes b and b removes a. Theoretically, only one should be
504 // notified. Investigate what we currently do in JS-style bindings. 518 // notified. Investigate what we currently do in JS-style bindings.
505 } 519 }
506 520
507 // Test an event listener throwing an exception. 521 // Test an event listener throwing an exception.
508 TEST_F(APIEventHandlerTest, TestEventListenersThrowingExceptions) { 522 TEST_F(APIEventHandlerTest, TestEventListenersThrowingExceptions) {
509 // The default test util methods (RunFunction*) assume no errors will ever 523 // The default test util methods (RunFunction*) assume no errors will ever
510 // be encountered. Instead, use an implementation that allows errors. 524 // be encountered. Instead, use an implementation that allows errors.
511 auto run_js_and_expect_error = [](v8::Local<v8::Function> function, 525 auto run_js_and_expect_error = [](v8::Local<v8::Function> function,
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 ASSERT_TRUE(event_args); 590 ASSERT_TRUE(event_args);
577 handler.FireEventInContext(kEventName, context, *event_args); 591 handler.FireEventInContext(kEventName, context, *event_args);
578 592
579 // An exception should have been thrown by the first listener and the second 593 // An exception should have been thrown by the first listener and the second
580 // listener should have recorded the event arguments. 594 // listener should have recorded the event arguments.
581 EXPECT_EQ("true", GetStringPropertyFromObject(context->Global(), context, 595 EXPECT_EQ("true", GetStringPropertyFromObject(context->Global(), context,
582 "didThrow")); 596 "didThrow"));
583 EXPECT_EQ("[42]", GetStringPropertyFromObject(context->Global(), context, 597 EXPECT_EQ("[42]", GetStringPropertyFromObject(context->Global(), context,
584 "eventArgs")); 598 "eventArgs"));
585 EXPECT_TRUE(did_throw); 599 EXPECT_TRUE(did_throw);
600
601 handler.InvalidateContext(context);
586 } 602 }
587 603
588 // Tests being notified as listeners are added or removed from events. 604 // Tests being notified as listeners are added or removed from events.
589 TEST_F(APIEventHandlerTest, CallbackNotifications) { 605 TEST_F(APIEventHandlerTest, CallbackNotifications) {
590 v8::HandleScope handle_scope(isolate()); 606 v8::HandleScope handle_scope(isolate());
591 607
592 v8::Local<v8::Context> context_a = ContextLocal(); 608 v8::Local<v8::Context> context_a = ContextLocal();
593 v8::Local<v8::Context> context_b = v8::Context::New(isolate()); 609 v8::Local<v8::Context> context_b = v8::Context::New(isolate());
594 gin::ContextHolder holder_b(isolate()); 610 gin::ContextHolder holder_b(isolate());
595 holder_b.SetContext(context_b); 611 holder_b.SetContext(context_b);
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 v8::Local<v8::Function> add_listener = 714 v8::Local<v8::Function> add_listener =
699 FunctionFromString(context_b, kAddListenerFunction); 715 FunctionFromString(context_b, kAddListenerFunction);
700 v8::Local<v8::Function> listener = 716 v8::Local<v8::Function> listener =
701 FunctionFromString(context_b, "(function() {})"); 717 FunctionFromString(context_b, "(function() {})");
702 v8::Local<v8::Value> argv[] = {event1_b, listener}; 718 v8::Local<v8::Value> argv[] = {event1_b, listener};
703 RunFunction(add_listener, context_b, arraysize(argv), argv); 719 RunFunction(add_listener, context_b, arraysize(argv), argv);
704 ::testing::Mock::VerifyAndClearExpectations(&change_handler); 720 ::testing::Mock::VerifyAndClearExpectations(&change_handler);
705 } 721 }
706 EXPECT_EQ(1u, 722 EXPECT_EQ(1u,
707 handler.GetNumEventListenersForTesting(kEventName1, context_b)); 723 handler.GetNumEventListenersForTesting(kEventName1, context_b));
724
725 // When the contexts are invalidated, we should receive listener removed
726 // notifications.
727 EXPECT_CALL(
728 change_handler,
729 Run(kEventName1, binding::EventListenersChanged::NO_LISTENERS, context_a))
730 .Times(1);
731 EXPECT_CALL(
732 change_handler,
733 Run(kEventName2, binding::EventListenersChanged::NO_LISTENERS, context_a))
734 .Times(1);
735 handler.InvalidateContext(context_a);
736 ::testing::Mock::VerifyAndClearExpectations(&change_handler);
737
738 EXPECT_CALL(
739 change_handler,
740 Run(kEventName1, binding::EventListenersChanged::NO_LISTENERS, context_b))
741 .Times(1);
742 handler.InvalidateContext(context_b);
743 ::testing::Mock::VerifyAndClearExpectations(&change_handler);
708 } 744 }
709 745
710 } // namespace extensions 746 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698