1 // Copyright (c) 2012 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.
4
5 #include "chrome/test/base/module_system_test.h"
6
7 #include "extensions/common/extension_urls.h"
8 #include "grit/renderer_resources.h"
9
10 namespace extensions {
11 namespace {
12
13 class EventUnittest : public ModuleSystemTest {
SetUp()14 virtual void SetUp() OVERRIDE {
15 ModuleSystemTest::SetUp();
16
17 RegisterModule(kEventBindings, IDR_EVENT_BINDINGS_JS);
18 RegisterModule("json_schema", IDR_JSON_SCHEMA_JS);
19 RegisterModule(kSchemaUtils, IDR_SCHEMA_UTILS_JS);
20 RegisterModule("unload_event", IDR_UNLOAD_EVENT_JS);
21 RegisterModule("utils", IDR_UTILS_JS);
22
23 // Mock out the native handler for event_bindings. These mocks will fail if
24 // any invariants maintained by the real event_bindings are broken.
25 OverrideNativeHandler("event_natives",
26 "var assert = requireNative('assert');"
27 "var attachedListeners = exports.attachedListeners = {};"
28 "var attachedFilteredListeners = "
29 " exports.attachedFilteredListeners = {};"
30 "var nextId = 0;"
31 "var idToName = {};"
32
33 "exports.AttachEvent = function(eventName) {"
34 " assert.AssertFalse(!!attachedListeners[eventName]);"
35 " attachedListeners[eventName] = 1;"
36 "};"
37
38 "exports.DetachEvent = function(eventName) {"
39 " assert.AssertTrue(!!attachedListeners[eventName]);"
40 " delete attachedListeners[eventName];"
41 "};"
42
43 "exports.IsEventAttached = function(eventName) {"
44 " return !!attachedListeners[eventName];"
45 "};"
46
47 "exports.AttachFilteredEvent = function(name, filters) {"
48 " var id = nextId++;"
49 " idToName[id] = name;"
50 " attachedFilteredListeners[name] ="
51 " attachedFilteredListeners[name] || [];"
52 " attachedFilteredListeners[name][id] = filters;"
53 " return id;"
54 "};"
55
56 "exports.DetachFilteredEvent = function(id, manual) {"
57 " var i = attachedFilteredListeners[idToName[id]].indexOf(id);"
58 " attachedFilteredListeners[idToName[id]].splice(i, 1);"
59 "};"
60
61 "exports.HasFilteredListener = function(name) {"
62 " return attachedFilteredListeners[name].length;"
63 "};");
64 OverrideNativeHandler("sendRequest",
65 "exports.sendRequest = function() {};");
66 OverrideNativeHandler("apiDefinitions",
67 "exports.GetExtensionAPIDefinitionsForTest = function() {};");
68 OverrideNativeHandler("logging",
69 "exports.DCHECK = function() {};");
70 OverrideNativeHandler("schema_registry",
71 "exports.GetSchema = function() {};");
72 }
73 };
74
TEST_F(EventUnittest,TestNothing)75 TEST_F(EventUnittest, TestNothing) {
76 ExpectNoAssertionsMade();
77 }
78
TEST_F(EventUnittest,AddRemoveTwoListeners)79 TEST_F(EventUnittest, AddRemoveTwoListeners) {
80 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
81 RegisterModule("test",
82 "var assert = requireNative('assert');"
83 "var Event = require('event_bindings').Event;"
84 "var eventNatives = requireNative('event_natives');"
85 "var myEvent = new Event('named-event');"
86 "var cb1 = function() {};"
87 "var cb2 = function() {};"
88 "myEvent.addListener(cb1);"
89 "myEvent.addListener(cb2);"
90 "myEvent.removeListener(cb1);"
91 "assert.AssertTrue(!!eventNatives.attachedListeners['named-event']);"
92 "myEvent.removeListener(cb2);"
93 "assert.AssertFalse(!!eventNatives.attachedListeners['named-event']);");
94 module_system_->Require("test");
95 }
96
TEST_F(EventUnittest,OnUnloadDetachesAllListeners)97 TEST_F(EventUnittest, OnUnloadDetachesAllListeners) {
98 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
99 RegisterModule("test",
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 module_system_->Require("test");
111 }
112
TEST_F(EventUnittest,OnUnloadDetachesAllListenersEvenDupes)113 TEST_F(EventUnittest, OnUnloadDetachesAllListenersEvenDupes) {
114 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
115 RegisterModule("test",
116 "var assert = requireNative('assert');"
117 "var Event = require('event_bindings').Event;"
118 "var eventNatives = requireNative('event_natives');"
119 "var myEvent = new Event('named-event');"
120 "var cb1 = function() {};"
121 "myEvent.addListener(cb1);"
122 "myEvent.addListener(cb1);"
123 "require('unload_event').dispatch();"
124 "assert.AssertFalse(!!eventNatives.attachedListeners['named-event']);");
125 module_system_->Require("test");
126 }
127
TEST_F(EventUnittest,EventsThatSupportRulesMustHaveAName)128 TEST_F(EventUnittest, EventsThatSupportRulesMustHaveAName) {
129 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
130 RegisterModule("test",
131 "var Event = require('event_bindings').Event;"
132 "var eventOpts = {supportsRules: true};"
133 "var assert = requireNative('assert');"
134 "var caught = false;"
135 "try {"
136 " var myEvent = new Event(undefined, undefined, eventOpts);"
137 "} catch (e) {"
138 " caught = true;"
139 "}"
140 "assert.AssertTrue(caught);");
141 module_system_->Require("test");
142 }
143
TEST_F(EventUnittest,NamedEventDispatch)144 TEST_F(EventUnittest, NamedEventDispatch) {
145 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
146 RegisterModule("test",
147 "var Event = require('event_bindings').Event;"
148 "var dispatchEvent = require('event_bindings').dispatchEvent;"
149 "var assert = requireNative('assert');"
150 "var e = new Event('myevent');"
151 "var called = false;"
152 "e.addListener(function() { called = true; });"
153 "dispatchEvent('myevent', []);"
154 "assert.AssertTrue(called);");
155 module_system_->Require("test");
156 }
157
TEST_F(EventUnittest,AddListenerWithFiltersThrowsErrorByDefault)158 TEST_F(EventUnittest, AddListenerWithFiltersThrowsErrorByDefault) {
159 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
160 RegisterModule("test",
161 "var Event = require('event_bindings').Event;"
162 "var assert = requireNative('assert');"
163 "var e = new Event('myevent');"
164 "var filter = [{"
165 " url: {hostSuffix: 'google.com'},"
166 "}];"
167 "var caught = false;"
168 "try {"
169 " e.addListener(function() {}, filter);"
170 "} catch (e) {"
171 " caught = true;"
172 "}"
173 "assert.AssertTrue(caught);");
174 module_system_->Require("test");
175 }
176
TEST_F(EventUnittest,FilteredEventsAttachment)177 TEST_F(EventUnittest, FilteredEventsAttachment) {
178 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
179 RegisterModule("test",
180 "var Event = require('event_bindings').Event;"
181 "var assert = requireNative('assert');"
182 "var bindings = requireNative('event_natives');"
183 "var eventOpts = {supportsListeners: true, supportsFilters: true};"
184 "var e = new Event('myevent', undefined, eventOpts);"
185 "var cb = function() {};"
186 "var filters = {url: [{hostSuffix: 'google.com'}]};"
187 "e.addListener(cb, filters);"
188 "assert.AssertTrue(bindings.HasFilteredListener('myevent'));"
189 "e.removeListener(cb);"
190 "assert.AssertFalse(bindings.HasFilteredListener('myevent'));");
191 module_system_->Require("test");
192 }
193
TEST_F(EventUnittest,DetachFilteredEvent)194 TEST_F(EventUnittest, DetachFilteredEvent) {
195 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
196 RegisterModule("test",
197 "var Event = require('event_bindings').Event;"
198 "var assert = requireNative('assert');"
199 "var bindings = requireNative('event_natives');"
200 "var eventOpts = {supportsListeners: true, supportsFilters: true};"
201 "var e = new Event('myevent', undefined, eventOpts);"
202 "var cb1 = function() {};"
203 "var cb2 = function() {};"
204 "var filters = {url: [{hostSuffix: 'google.com'}]};"
205 "e.addListener(cb1, filters);"
206 "e.addListener(cb2, filters);"
207 "e.detach_();"
208 "assert.AssertFalse(bindings.HasFilteredListener('myevent'));");
209 module_system_->Require("test");
210 }
211
TEST_F(EventUnittest,AttachAndRemoveSameFilteredEventListener)212 TEST_F(EventUnittest, AttachAndRemoveSameFilteredEventListener) {
213 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
214 RegisterModule("test",
215 "var Event = require('event_bindings').Event;"
216 "var assert = requireNative('assert');"
217 "var bindings = requireNative('event_natives');"
218 "var eventOpts = {supportsListeners: true, supportsFilters: true};"
219 "var e = new Event('myevent', undefined, eventOpts);"
220 "var cb = function() {};"
221 "var filters = {url: [{hostSuffix: 'google.com'}]};"
222 "e.addListener(cb, filters);"
223 "e.addListener(cb, filters);"
224 "assert.AssertTrue(bindings.HasFilteredListener('myevent'));"
225 "e.removeListener(cb);"
226 "assert.AssertTrue(bindings.HasFilteredListener('myevent'));"
227 "e.removeListener(cb);"
228 "assert.AssertFalse(bindings.HasFilteredListener('myevent'));");
229 module_system_->Require("test");
230 }
231
TEST_F(EventUnittest,AddingFilterWithUrlFieldNotAListThrowsException)232 TEST_F(EventUnittest, AddingFilterWithUrlFieldNotAListThrowsException) {
233 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
234 RegisterModule("test",
235 "var Event = require('event_bindings').Event;"
236 "var assert = requireNative('assert');"
237 "var eventOpts = {supportsListeners: true, supportsFilters: true};"
238 "var e = new Event('myevent', undefined, eventOpts);"
239 "var cb = function() {};"
240 "var filters = {url: {hostSuffix: 'google.com'}};"
241 "var caught = false;"
242 "try {"
243 " e.addListener(cb, filters);"
244 "} catch (e) {"
245 " caught = true;"
246 "}"
247 "assert.AssertTrue(caught);");
248 module_system_->Require("test");
249 }
250
TEST_F(EventUnittest,MaxListeners)251 TEST_F(EventUnittest, MaxListeners) {
252 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
253 RegisterModule("test",
254 "var Event = require('event_bindings').Event;"
255 "var assert = requireNative('assert');"
256 "var eventOpts = {supportsListeners: true, maxListeners: 1};"
257 "var e = new Event('myevent', undefined, eventOpts);"
258 "var cb = function() {};"
259 "var caught = false;"
260 "try {"
261 " e.addListener(cb);"
262 "} catch (e) {"
263 " caught = true;"
264 "}"
265 "assert.AssertTrue(!caught);"
266 "try {"
267 " e.addListener(cb);"
268 "} catch (e) {"
269 " caught = true;"
270 "}"
271 "assert.AssertTrue(caught);");
272 module_system_->Require("test");
273 }
274
275 } // namespace
276 } // namespace extensions
277