1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/common/extension_urls.h"
6 #include "extensions/renderer/module_system_test.h"
7 #include "grit/extensions_renderer_resources.h"
12 class EventUnittest
: public ModuleSystemTest
{
13 void SetUp() override
{
14 ModuleSystemTest::SetUp();
16 env()->RegisterModule(kEventBindings
, IDR_EVENT_BINDINGS_JS
);
17 env()->RegisterModule("json_schema", IDR_JSON_SCHEMA_JS
);
18 env()->RegisterModule(kSchemaUtils
, IDR_SCHEMA_UTILS_JS
);
19 env()->RegisterModule("uncaught_exception_handler",
20 IDR_UNCAUGHT_EXCEPTION_HANDLER_JS
);
21 env()->RegisterModule("unload_event", IDR_UNLOAD_EVENT_JS
);
22 env()->RegisterModule("utils", IDR_UTILS_JS
);
24 // Mock out the native handler for event_bindings. These mocks will fail if
25 // any invariants maintained by the real event_bindings are broken.
26 env()->OverrideNativeHandler(
28 "var assert = requireNative('assert');"
29 "var attachedListeners = exports.attachedListeners = {};"
30 "var attachedFilteredListeners = "
31 " exports.attachedFilteredListeners = {};"
34 "exports.AttachEvent = function(eventName) {"
35 " assert.AssertFalse(!!attachedListeners[eventName]);"
36 " attachedListeners[eventName] = 1;"
38 "exports.DetachEvent = function(eventName) {"
39 " assert.AssertTrue(!!attachedListeners[eventName]);"
40 " delete attachedListeners[eventName];"
42 "exports.IsEventAttached = function(eventName) {"
43 " return !!attachedListeners[eventName];"
45 "exports.AttachFilteredEvent = function(name, filters) {"
47 " idToName[id] = name;"
48 " attachedFilteredListeners[name] ="
49 " attachedFilteredListeners[name] || [];"
50 " attachedFilteredListeners[name][id] = filters;"
53 "exports.DetachFilteredEvent = function(id, manual) {"
54 " var i = attachedFilteredListeners[idToName[id]].indexOf(id);"
55 " attachedFilteredListeners[idToName[id]].splice(i, 1);"
57 "exports.HasFilteredListener = function(name) {"
58 " return attachedFilteredListeners[name].length;"
60 env()->OverrideNativeHandler("sendRequest",
61 "exports.sendRequest = function() {};");
62 env()->OverrideNativeHandler(
64 "exports.GetExtensionAPIDefinitionsForTest = function() {};");
65 env()->OverrideNativeHandler("logging", "exports.DCHECK = function() {};");
66 env()->OverrideNativeHandler("schema_registry",
67 "exports.GetSchema = function() {};");
71 TEST_F(EventUnittest
, TestNothing
) {
72 ExpectNoAssertionsMade();
75 TEST_F(EventUnittest
, AddRemoveTwoListeners
) {
76 ModuleSystem::NativesEnabledScope
natives_enabled_scope(
77 env()->module_system());
78 env()->RegisterModule(
80 "var assert = requireNative('assert');"
81 "var Event = require('event_bindings').Event;"
82 "var eventNatives = requireNative('event_natives');"
83 "var myEvent = new Event('named-event');"
84 "var cb1 = function() {};"
85 "var cb2 = function() {};"
86 "myEvent.addListener(cb1);"
87 "myEvent.addListener(cb2);"
88 "myEvent.removeListener(cb1);"
89 "assert.AssertTrue(!!eventNatives.attachedListeners['named-event']);"
90 "myEvent.removeListener(cb2);"
91 "assert.AssertFalse(!!eventNatives.attachedListeners['named-event']);");
92 env()->module_system()->Require("test");
95 TEST_F(EventUnittest
, OnUnloadDetachesAllListeners
) {
96 ModuleSystem::NativesEnabledScope
natives_enabled_scope(
97 env()->module_system());
98 env()->RegisterModule(
100 "var assert = requireNative('assert');"
101 "var Event = require('event_bindings').Event;"
102 "var eventNatives = requireNative('event_natives');"
103 "var myEvent = new Event('named-event');"
104 "var cb1 = function() {};"
105 "var cb2 = function() {};"
106 "myEvent.addListener(cb1);"
107 "myEvent.addListener(cb2);"
108 "require('unload_event').dispatch();"
109 "assert.AssertFalse(!!eventNatives.attachedListeners['named-event']);");
110 env()->module_system()->Require("test");
113 TEST_F(EventUnittest
, OnUnloadDetachesAllListenersEvenDupes
) {
114 ModuleSystem::NativesEnabledScope
natives_enabled_scope(
115 env()->module_system());
116 env()->RegisterModule(
118 "var assert = requireNative('assert');"
119 "var Event = require('event_bindings').Event;"
120 "var eventNatives = requireNative('event_natives');"
121 "var myEvent = new Event('named-event');"
122 "var cb1 = function() {};"
123 "myEvent.addListener(cb1);"
124 "myEvent.addListener(cb1);"
125 "require('unload_event').dispatch();"
126 "assert.AssertFalse(!!eventNatives.attachedListeners['named-event']);");
127 env()->module_system()->Require("test");
130 TEST_F(EventUnittest
, EventsThatSupportRulesMustHaveAName
) {
131 ModuleSystem::NativesEnabledScope
natives_enabled_scope(
132 env()->module_system());
133 env()->RegisterModule(
135 "var Event = require('event_bindings').Event;"
136 "var eventOpts = {supportsRules: true};"
137 "var assert = requireNative('assert');"
138 "var caught = false;"
140 " var myEvent = new Event(undefined, undefined, eventOpts);"
144 "assert.AssertTrue(caught);");
145 env()->module_system()->Require("test");
148 TEST_F(EventUnittest
, NamedEventDispatch
) {
149 ModuleSystem::NativesEnabledScope
natives_enabled_scope(
150 env()->module_system());
151 env()->RegisterModule(
153 "var Event = require('event_bindings').Event;"
154 "var dispatchEvent = require('event_bindings').dispatchEvent;"
155 "var assert = requireNative('assert');"
156 "var e = new Event('myevent');"
157 "var called = false;"
158 "e.addListener(function() { called = true; });"
159 "dispatchEvent('myevent', []);"
160 "assert.AssertTrue(called);");
161 env()->module_system()->Require("test");
164 TEST_F(EventUnittest
, AddListenerWithFiltersThrowsErrorByDefault
) {
165 ModuleSystem::NativesEnabledScope
natives_enabled_scope(
166 env()->module_system());
167 env()->RegisterModule("test",
168 "var Event = require('event_bindings').Event;"
169 "var assert = requireNative('assert');"
170 "var e = new Event('myevent');"
172 " url: {hostSuffix: 'google.com'},"
174 "var caught = false;"
176 " e.addListener(function() {}, filter);"
180 "assert.AssertTrue(caught);");
181 env()->module_system()->Require("test");
184 TEST_F(EventUnittest
, FilteredEventsAttachment
) {
185 ModuleSystem::NativesEnabledScope
natives_enabled_scope(
186 env()->module_system());
187 env()->RegisterModule(
189 "var Event = require('event_bindings').Event;"
190 "var assert = requireNative('assert');"
191 "var bindings = requireNative('event_natives');"
192 "var eventOpts = {supportsListeners: true, supportsFilters: true};"
193 "var e = new Event('myevent', undefined, eventOpts);"
194 "var cb = function() {};"
195 "var filters = {url: [{hostSuffix: 'google.com'}]};"
196 "e.addListener(cb, filters);"
197 "assert.AssertTrue(bindings.HasFilteredListener('myevent'));"
198 "e.removeListener(cb);"
199 "assert.AssertFalse(bindings.HasFilteredListener('myevent'));");
200 env()->module_system()->Require("test");
203 TEST_F(EventUnittest
, DetachFilteredEvent
) {
204 ModuleSystem::NativesEnabledScope
natives_enabled_scope(
205 env()->module_system());
206 env()->RegisterModule(
208 "var Event = require('event_bindings').Event;"
209 "var assert = requireNative('assert');"
210 "var bindings = requireNative('event_natives');"
211 "var eventOpts = {supportsListeners: true, supportsFilters: true};"
212 "var e = new Event('myevent', undefined, eventOpts);"
213 "var cb1 = function() {};"
214 "var cb2 = function() {};"
215 "var filters = {url: [{hostSuffix: 'google.com'}]};"
216 "e.addListener(cb1, filters);"
217 "e.addListener(cb2, filters);"
218 "privates(e).impl.detach_();"
219 "assert.AssertFalse(bindings.HasFilteredListener('myevent'));");
220 env()->module_system()->Require("test");
223 TEST_F(EventUnittest
, AttachAndRemoveSameFilteredEventListener
) {
224 ModuleSystem::NativesEnabledScope
natives_enabled_scope(
225 env()->module_system());
226 env()->RegisterModule(
228 "var Event = require('event_bindings').Event;"
229 "var assert = requireNative('assert');"
230 "var bindings = requireNative('event_natives');"
231 "var eventOpts = {supportsListeners: true, supportsFilters: true};"
232 "var e = new Event('myevent', undefined, eventOpts);"
233 "var cb = function() {};"
234 "var filters = {url: [{hostSuffix: 'google.com'}]};"
235 "e.addListener(cb, filters);"
236 "e.addListener(cb, filters);"
237 "assert.AssertTrue(bindings.HasFilteredListener('myevent'));"
238 "e.removeListener(cb);"
239 "assert.AssertTrue(bindings.HasFilteredListener('myevent'));"
240 "e.removeListener(cb);"
241 "assert.AssertFalse(bindings.HasFilteredListener('myevent'));");
242 env()->module_system()->Require("test");
245 TEST_F(EventUnittest
, AddingFilterWithUrlFieldNotAListThrowsException
) {
246 ModuleSystem::NativesEnabledScope
natives_enabled_scope(
247 env()->module_system());
248 env()->RegisterModule(
250 "var Event = require('event_bindings').Event;"
251 "var assert = requireNative('assert');"
252 "var eventOpts = {supportsListeners: true, supportsFilters: true};"
253 "var e = new Event('myevent', undefined, eventOpts);"
254 "var cb = function() {};"
255 "var filters = {url: {hostSuffix: 'google.com'}};"
256 "var caught = false;"
258 " e.addListener(cb, filters);"
262 "assert.AssertTrue(caught);");
263 env()->module_system()->Require("test");
266 TEST_F(EventUnittest
, MaxListeners
) {
267 ModuleSystem::NativesEnabledScope
natives_enabled_scope(
268 env()->module_system());
269 env()->RegisterModule(
271 "var Event = require('event_bindings').Event;"
272 "var assert = requireNative('assert');"
273 "var eventOpts = {supportsListeners: true, maxListeners: 1};"
274 "var e = new Event('myevent', undefined, eventOpts);"
275 "var cb = function() {};"
276 "var caught = false;"
278 " e.addListener(cb);"
282 "assert.AssertTrue(!caught);"
284 " e.addListener(cb);"
288 "assert.AssertTrue(caught);");
289 env()->module_system()->Require("test");
293 } // namespace extensions