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

Unified Diff: extensions/renderer/api_event_handler_unittest.cc

Issue 2605353003: [Extensions Bindings] Allow event listener unregistration in handling (Closed)
Patch Set: . 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | extensions/renderer/event_emitter.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: extensions/renderer/api_event_handler_unittest.cc
diff --git a/extensions/renderer/api_event_handler_unittest.cc b/extensions/renderer/api_event_handler_unittest.cc
index ce1993779b74cf469e82d8be4e1bce1cd76ee3c5..e43c860cbd8a9902f606d22755bab182898816f0 100644
--- a/extensions/renderer/api_event_handler_unittest.cc
+++ b/extensions/renderer/api_event_handler_unittest.cc
@@ -447,4 +447,63 @@ TEST_F(APIEventHandlerTest, TestDispatchFromJs) {
context->Global(), context, "eventArgs"));
}
+// Test listeners that remove themselves in their handling of the event.
+TEST_F(APIEventHandlerTest, RemovingListenersWhileHandlingEvent) {
+ v8::HandleScope handle_scope(isolate());
+ v8::Local<v8::Context> context = ContextLocal();
+
+ APIEventHandler handler(base::Bind(&RunFunctionOnGlobalAndIgnoreResult));
+ const char kEventName[] = "alpha";
+ v8::Local<v8::Object> event =
+ handler.CreateEventInstance(kEventName, context);
+ ASSERT_FALSE(event.IsEmpty());
+
+ {
+ // Cache the event object on the global in order to allow for easy removal.
+ v8::Local<v8::Function> set_event_on_global =
+ FunctionFromString(
+ context,
+ "(function(event) { this.testEvent = event; })");
+ v8::Local<v8::Value> args[] = {event};
+ RunFunctionOnGlobal(set_event_on_global, context, arraysize(args), args);
+ EXPECT_EQ(event,
+ GetPropertyFromObject(context->Global(), context, "testEvent"));
+ }
+
+ // A listener function that removes itself as a listener.
+ const char kListenerFunction[] =
+ "(function() {\n"
+ " return function listener() {\n"
+ " this.testEvent.removeListener(listener);\n"
+ " };\n"
+ "})();";
+
+ // Create and add a bunch of listeners.
+ std::vector<v8::Local<v8::Function>> listeners;
+ const size_t kNumListeners = 20u;
+ listeners.reserve(kNumListeners);
+ for (size_t i = 0; i < kNumListeners; ++i)
+ listeners.push_back(FunctionFromString(context, kListenerFunction));
+
+ const char kAddListenerFunction[] =
+ "(function(event, listener) { event.addListener(listener); })";
+ v8::Local<v8::Function> add_listener_function =
+ FunctionFromString(context, kAddListenerFunction);
+
+ for (const auto& listener : listeners) {
+ v8::Local<v8::Value> argv[] = {event, listener};
+ RunFunctionOnGlobal(add_listener_function, context, arraysize(argv), argv);
+ }
+
+ // Fire the event. All listeners should be removed (and we shouldn't crash).
+ EXPECT_EQ(kNumListeners,
+ handler.GetNumEventListenersForTesting(kEventName, context));
+ handler.FireEventInContext(kEventName, context, base::ListValue());
+ EXPECT_EQ(0u, handler.GetNumEventListenersForTesting(kEventName, context));
+
+ // TODO(devlin): Another possible test: register listener a and listener b,
+ // where a removes b and b removes a. Theoretically, only one should be
+ // notified. Investigate what we currently do in JS-style bindings.
+}
+
} // namespace extensions
« no previous file with comments | « no previous file | extensions/renderer/event_emitter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698