OLD | NEW |
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/bindings/api_event_handler.h" | 5 #include "extensions/renderer/bindings/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/optional.h" | 10 #include "base/optional.h" |
11 #include "base/test/mock_callback.h" | 11 #include "base/test/mock_callback.h" |
12 #include "base/values.h" | 12 #include "base/values.h" |
13 #include "extensions/common/event_filtering_info.h" | 13 #include "extensions/common/event_filtering_info.h" |
14 #include "extensions/renderer/bindings/api_binding_test.h" | 14 #include "extensions/renderer/bindings/api_binding_test.h" |
15 #include "extensions/renderer/bindings/api_binding_test_util.h" | 15 #include "extensions/renderer/bindings/api_binding_test_util.h" |
16 #include "extensions/renderer/bindings/exception_handler.h" | 16 #include "extensions/renderer/bindings/exception_handler.h" |
17 #include "gin/arguments.h" | 17 #include "gin/arguments.h" |
18 #include "gin/converter.h" | 18 #include "gin/converter.h" |
19 #include "gin/public/context_holder.h" | 19 #include "gin/public/context_holder.h" |
20 #include "testing/gmock/include/gmock/gmock.h" | 20 #include "testing/gmock/include/gmock/gmock.h" |
21 | 21 |
22 namespace extensions { | 22 namespace extensions { |
23 | 23 |
24 namespace { | 24 namespace { |
25 | 25 |
| 26 const char kAddListenerFunction[] = |
| 27 "(function(event, listener) { event.addListener(listener); })"; |
| 28 const char kRemoveListenerFunction[] = |
| 29 "(function(event, listener) { event.removeListener(listener); })"; |
| 30 |
26 using MockEventChangeHandler = ::testing::StrictMock< | 31 using MockEventChangeHandler = ::testing::StrictMock< |
27 base::MockCallback<APIEventHandler::EventListenersChangedMethod>>; | 32 base::MockCallback<APIEventHandler::EventListenersChangedMethod>>; |
28 | 33 |
29 void DoNothingOnEventListenersChanged(const std::string& event_name, | 34 void DoNothingOnEventListenersChanged(const std::string& event_name, |
30 binding::EventListenersChanged change, | 35 binding::EventListenersChanged change, |
31 const base::DictionaryValue* value, | 36 const base::DictionaryValue* value, |
32 bool was_manual, | 37 bool was_manual, |
33 v8::Local<v8::Context> context) {} | 38 v8::Local<v8::Context> context) {} |
34 | 39 |
35 class APIEventHandlerTest : public APIBindingTest { | 40 class APIEventHandlerTest : public APIBindingTest { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 } // namespace | 76 } // namespace |
72 | 77 |
73 // Tests adding, removing, and querying event listeners by calling the | 78 // Tests adding, removing, and querying event listeners by calling the |
74 // associated methods on the JS object. | 79 // associated methods on the JS object. |
75 TEST_F(APIEventHandlerTest, AddingRemovingAndQueryingEventListeners) { | 80 TEST_F(APIEventHandlerTest, AddingRemovingAndQueryingEventListeners) { |
76 const char kEventName[] = "alpha"; | 81 const char kEventName[] = "alpha"; |
77 v8::HandleScope handle_scope(isolate()); | 82 v8::HandleScope handle_scope(isolate()); |
78 v8::Local<v8::Context> context = MainContext(); | 83 v8::Local<v8::Context> context = MainContext(); |
79 | 84 |
80 v8::Local<v8::Object> event = handler()->CreateEventInstance( | 85 v8::Local<v8::Object> event = handler()->CreateEventInstance( |
81 kEventName, false, binding::kNoListenerMax, true, context); | 86 kEventName, false, true, binding::kNoListenerMax, true, context); |
82 ASSERT_FALSE(event.IsEmpty()); | 87 ASSERT_FALSE(event.IsEmpty()); |
83 | 88 |
84 EXPECT_EQ(0u, handler()->GetNumEventListenersForTesting(kEventName, context)); | 89 EXPECT_EQ(0u, handler()->GetNumEventListenersForTesting(kEventName, context)); |
85 | 90 |
86 const char kListenerFunction[] = "(function() {})"; | 91 const char kListenerFunction[] = "(function() {})"; |
87 v8::Local<v8::Function> listener_function = | 92 v8::Local<v8::Function> listener_function = |
88 FunctionFromString(context, kListenerFunction); | 93 FunctionFromString(context, kListenerFunction); |
89 ASSERT_FALSE(listener_function.IsEmpty()); | 94 ASSERT_FALSE(listener_function.IsEmpty()); |
90 | 95 |
91 const char kAddListenerFunction[] = | |
92 "(function(event, listener) { event.addListener(listener); })"; | |
93 v8::Local<v8::Function> add_listener_function = | 96 v8::Local<v8::Function> add_listener_function = |
94 FunctionFromString(context, kAddListenerFunction); | 97 FunctionFromString(context, kAddListenerFunction); |
95 | 98 |
96 { | 99 { |
97 v8::Local<v8::Value> argv[] = {event, listener_function}; | 100 v8::Local<v8::Value> argv[] = {event, listener_function}; |
98 RunFunction(add_listener_function, context, arraysize(argv), argv); | 101 RunFunction(add_listener_function, context, arraysize(argv), argv); |
99 } | 102 } |
100 // There should only be one listener on the event. | 103 // There should only be one listener on the event. |
101 EXPECT_EQ(1u, handler()->GetNumEventListenersForTesting(kEventName, context)); | 104 EXPECT_EQ(1u, handler()->GetNumEventListenersForTesting(kEventName, context)); |
102 | 105 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 { | 144 { |
142 v8::Local<v8::Value> argv[] = {event}; | 145 v8::Local<v8::Value> argv[] = {event}; |
143 v8::Local<v8::Value> result = | 146 v8::Local<v8::Value> result = |
144 RunFunction(has_listeners_function, context, arraysize(argv), argv); | 147 RunFunction(has_listeners_function, context, arraysize(argv), argv); |
145 bool has_listeners = false; | 148 bool has_listeners = false; |
146 EXPECT_TRUE( | 149 EXPECT_TRUE( |
147 gin::Converter<bool>::FromV8(isolate(), result, &has_listeners)); | 150 gin::Converter<bool>::FromV8(isolate(), result, &has_listeners)); |
148 EXPECT_TRUE(has_listeners); | 151 EXPECT_TRUE(has_listeners); |
149 } | 152 } |
150 | 153 |
151 const char kRemoveListenerFunction[] = | |
152 "(function(event, listener) { event.removeListener(listener); })"; | |
153 v8::Local<v8::Function> remove_listener_function = | 154 v8::Local<v8::Function> remove_listener_function = |
154 FunctionFromString(context, kRemoveListenerFunction); | 155 FunctionFromString(context, kRemoveListenerFunction); |
155 { | 156 { |
156 v8::Local<v8::Value> argv[] = {event, listener_function}; | 157 v8::Local<v8::Value> argv[] = {event, listener_function}; |
157 RunFunction(remove_listener_function, context, arraysize(argv), argv); | 158 RunFunction(remove_listener_function, context, arraysize(argv), argv); |
158 } | 159 } |
159 EXPECT_EQ(0u, handler()->GetNumEventListenersForTesting(kEventName, context)); | 160 EXPECT_EQ(0u, handler()->GetNumEventListenersForTesting(kEventName, context)); |
160 | 161 |
161 { | 162 { |
162 v8::Local<v8::Value> argv[] = {event}; | 163 v8::Local<v8::Value> argv[] = {event}; |
163 v8::Local<v8::Value> result = | 164 v8::Local<v8::Value> result = |
164 RunFunction(has_listeners_function, context, arraysize(argv), argv); | 165 RunFunction(has_listeners_function, context, arraysize(argv), argv); |
165 bool has_listeners = false; | 166 bool has_listeners = false; |
166 EXPECT_TRUE( | 167 EXPECT_TRUE( |
167 gin::Converter<bool>::FromV8(isolate(), result, &has_listeners)); | 168 gin::Converter<bool>::FromV8(isolate(), result, &has_listeners)); |
168 EXPECT_FALSE(has_listeners); | 169 EXPECT_FALSE(has_listeners); |
169 } | 170 } |
170 } | 171 } |
171 | 172 |
172 // Tests listening for and firing different events. | 173 // Tests listening for and firing different events. |
173 TEST_F(APIEventHandlerTest, FiringEvents) { | 174 TEST_F(APIEventHandlerTest, FiringEvents) { |
174 const char kAlphaName[] = "alpha"; | 175 const char kAlphaName[] = "alpha"; |
175 const char kBetaName[] = "beta"; | 176 const char kBetaName[] = "beta"; |
176 v8::HandleScope handle_scope(isolate()); | 177 v8::HandleScope handle_scope(isolate()); |
177 v8::Local<v8::Context> context = MainContext(); | 178 v8::Local<v8::Context> context = MainContext(); |
178 | 179 |
179 v8::Local<v8::Object> alpha_event = handler()->CreateEventInstance( | 180 v8::Local<v8::Object> alpha_event = handler()->CreateEventInstance( |
180 kAlphaName, false, binding::kNoListenerMax, true, context); | 181 kAlphaName, false, true, binding::kNoListenerMax, true, context); |
181 v8::Local<v8::Object> beta_event = handler()->CreateEventInstance( | 182 v8::Local<v8::Object> beta_event = handler()->CreateEventInstance( |
182 kBetaName, false, binding::kNoListenerMax, true, context); | 183 kBetaName, false, true, binding::kNoListenerMax, true, context); |
183 ASSERT_FALSE(alpha_event.IsEmpty()); | 184 ASSERT_FALSE(alpha_event.IsEmpty()); |
184 ASSERT_FALSE(beta_event.IsEmpty()); | 185 ASSERT_FALSE(beta_event.IsEmpty()); |
185 | 186 |
186 const char kAlphaListenerFunction1[] = | 187 const char kAlphaListenerFunction1[] = |
187 "(function() {\n" | 188 "(function() {\n" |
188 " if (!this.alphaCount1) this.alphaCount1 = 0;\n" | 189 " if (!this.alphaCount1) this.alphaCount1 = 0;\n" |
189 " ++this.alphaCount1;\n" | 190 " ++this.alphaCount1;\n" |
190 "});\n"; | 191 "});\n"; |
191 v8::Local<v8::Function> alpha_listener1 = | 192 v8::Local<v8::Function> alpha_listener1 = |
192 FunctionFromString(context, kAlphaListenerFunction1); | 193 FunctionFromString(context, kAlphaListenerFunction1); |
193 const char kAlphaListenerFunction2[] = | 194 const char kAlphaListenerFunction2[] = |
194 "(function() {\n" | 195 "(function() {\n" |
195 " if (!this.alphaCount2) this.alphaCount2 = 0;\n" | 196 " if (!this.alphaCount2) this.alphaCount2 = 0;\n" |
196 " ++this.alphaCount2;\n" | 197 " ++this.alphaCount2;\n" |
197 "});\n"; | 198 "});\n"; |
198 v8::Local<v8::Function> alpha_listener2 = | 199 v8::Local<v8::Function> alpha_listener2 = |
199 FunctionFromString(context, kAlphaListenerFunction2); | 200 FunctionFromString(context, kAlphaListenerFunction2); |
200 const char kBetaListenerFunction[] = | 201 const char kBetaListenerFunction[] = |
201 "(function() {\n" | 202 "(function() {\n" |
202 " if (!this.betaCount) this.betaCount = 0;\n" | 203 " if (!this.betaCount) this.betaCount = 0;\n" |
203 " ++this.betaCount;\n" | 204 " ++this.betaCount;\n" |
204 "});\n"; | 205 "});\n"; |
205 v8::Local<v8::Function> beta_listener = | 206 v8::Local<v8::Function> beta_listener = |
206 FunctionFromString(context, kBetaListenerFunction); | 207 FunctionFromString(context, kBetaListenerFunction); |
207 ASSERT_FALSE(alpha_listener1.IsEmpty()); | 208 ASSERT_FALSE(alpha_listener1.IsEmpty()); |
208 ASSERT_FALSE(alpha_listener2.IsEmpty()); | 209 ASSERT_FALSE(alpha_listener2.IsEmpty()); |
209 ASSERT_FALSE(beta_listener.IsEmpty()); | 210 ASSERT_FALSE(beta_listener.IsEmpty()); |
210 | 211 |
211 { | 212 { |
212 const char kAddListenerFunction[] = | |
213 "(function(event, listener) { event.addListener(listener); })"; | |
214 v8::Local<v8::Function> add_listener_function = | 213 v8::Local<v8::Function> add_listener_function = |
215 FunctionFromString(context, kAddListenerFunction); | 214 FunctionFromString(context, kAddListenerFunction); |
216 { | 215 { |
217 v8::Local<v8::Value> argv[] = {alpha_event, alpha_listener1}; | 216 v8::Local<v8::Value> argv[] = {alpha_event, alpha_listener1}; |
218 RunFunction(add_listener_function, context, arraysize(argv), argv); | 217 RunFunction(add_listener_function, context, arraysize(argv), argv); |
219 } | 218 } |
220 { | 219 { |
221 v8::Local<v8::Value> argv[] = {alpha_event, alpha_listener2}; | 220 v8::Local<v8::Value> argv[] = {alpha_event, alpha_listener2}; |
222 RunFunction(add_listener_function, context, arraysize(argv), argv); | 221 RunFunction(add_listener_function, context, arraysize(argv), argv); |
223 } | 222 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 EXPECT_EQ(1, get_fired_count("betaCount")); | 266 EXPECT_EQ(1, get_fired_count("betaCount")); |
268 } | 267 } |
269 | 268 |
270 // Tests firing events with arguments. | 269 // Tests firing events with arguments. |
271 TEST_F(APIEventHandlerTest, EventArguments) { | 270 TEST_F(APIEventHandlerTest, EventArguments) { |
272 v8::HandleScope handle_scope(isolate()); | 271 v8::HandleScope handle_scope(isolate()); |
273 v8::Local<v8::Context> context = MainContext(); | 272 v8::Local<v8::Context> context = MainContext(); |
274 | 273 |
275 const char kEventName[] = "alpha"; | 274 const char kEventName[] = "alpha"; |
276 v8::Local<v8::Object> event = handler()->CreateEventInstance( | 275 v8::Local<v8::Object> event = handler()->CreateEventInstance( |
277 kEventName, false, binding::kNoListenerMax, true, context); | 276 kEventName, false, true, binding::kNoListenerMax, true, context); |
278 ASSERT_FALSE(event.IsEmpty()); | 277 ASSERT_FALSE(event.IsEmpty()); |
279 | 278 |
280 const char kListenerFunction[] = | 279 const char kListenerFunction[] = |
281 "(function() { this.eventArgs = Array.from(arguments); })"; | 280 "(function() { this.eventArgs = Array.from(arguments); })"; |
282 v8::Local<v8::Function> listener_function = | 281 v8::Local<v8::Function> listener_function = |
283 FunctionFromString(context, kListenerFunction); | 282 FunctionFromString(context, kListenerFunction); |
284 ASSERT_FALSE(listener_function.IsEmpty()); | 283 ASSERT_FALSE(listener_function.IsEmpty()); |
285 | 284 |
286 { | 285 { |
287 const char kAddListenerFunction[] = | |
288 "(function(event, listener) { event.addListener(listener); })"; | |
289 v8::Local<v8::Function> add_listener_function = | 286 v8::Local<v8::Function> add_listener_function = |
290 FunctionFromString(context, kAddListenerFunction); | 287 FunctionFromString(context, kAddListenerFunction); |
291 v8::Local<v8::Value> argv[] = {event, listener_function}; | 288 v8::Local<v8::Value> argv[] = {event, listener_function}; |
292 RunFunction(add_listener_function, context, arraysize(argv), argv); | 289 RunFunction(add_listener_function, context, arraysize(argv), argv); |
293 } | 290 } |
294 | 291 |
295 const char kArguments[] = "['foo',1,{'prop1':'bar'}]"; | 292 const char kArguments[] = "['foo',1,{'prop1':'bar'}]"; |
296 std::unique_ptr<base::ListValue> event_args = ListValueFromString(kArguments); | 293 std::unique_ptr<base::ListValue> event_args = ListValueFromString(kArguments); |
297 ASSERT_TRUE(event_args); | 294 ASSERT_TRUE(event_args); |
298 handler()->FireEventInContext(kEventName, context, *event_args, nullptr); | 295 handler()->FireEventInContext(kEventName, context, *event_args, nullptr); |
(...skipping 15 matching lines...) Expand all Loading... |
314 | 311 |
315 v8::Local<v8::Function> listener_a = FunctionFromString( | 312 v8::Local<v8::Function> listener_a = FunctionFromString( |
316 context_a, "(function(arg) { this.eventArgs = arg + 'alpha'; })"); | 313 context_a, "(function(arg) { this.eventArgs = arg + 'alpha'; })"); |
317 ASSERT_FALSE(listener_a.IsEmpty()); | 314 ASSERT_FALSE(listener_a.IsEmpty()); |
318 v8::Local<v8::Function> listener_b = FunctionFromString( | 315 v8::Local<v8::Function> listener_b = FunctionFromString( |
319 context_b, "(function(arg) { this.eventArgs = arg + 'beta'; })"); | 316 context_b, "(function(arg) { this.eventArgs = arg + 'beta'; })"); |
320 ASSERT_FALSE(listener_b.IsEmpty()); | 317 ASSERT_FALSE(listener_b.IsEmpty()); |
321 | 318 |
322 // Create two instances of the same event in different contexts. | 319 // Create two instances of the same event in different contexts. |
323 v8::Local<v8::Object> event_a = handler()->CreateEventInstance( | 320 v8::Local<v8::Object> event_a = handler()->CreateEventInstance( |
324 kEventName, false, binding::kNoListenerMax, true, context_a); | 321 kEventName, false, true, binding::kNoListenerMax, true, context_a); |
325 ASSERT_FALSE(event_a.IsEmpty()); | 322 ASSERT_FALSE(event_a.IsEmpty()); |
326 v8::Local<v8::Object> event_b = handler()->CreateEventInstance( | 323 v8::Local<v8::Object> event_b = handler()->CreateEventInstance( |
327 kEventName, false, binding::kNoListenerMax, true, context_b); | 324 kEventName, false, true, binding::kNoListenerMax, true, context_b); |
328 ASSERT_FALSE(event_b.IsEmpty()); | 325 ASSERT_FALSE(event_b.IsEmpty()); |
329 | 326 |
330 // Add two separate listeners to the event, one in each context. | 327 // Add two separate listeners to the event, one in each context. |
331 const char kAddListenerFunction[] = | |
332 "(function(event, listener) { event.addListener(listener); })"; | |
333 { | 328 { |
334 v8::Local<v8::Function> add_listener_a = | 329 v8::Local<v8::Function> add_listener_a = |
335 FunctionFromString(context_a, kAddListenerFunction); | 330 FunctionFromString(context_a, kAddListenerFunction); |
336 v8::Local<v8::Value> argv[] = {event_a, listener_a}; | 331 v8::Local<v8::Value> argv[] = {event_a, listener_a}; |
337 RunFunction(add_listener_a, context_a, arraysize(argv), argv); | 332 RunFunction(add_listener_a, context_a, arraysize(argv), argv); |
338 } | 333 } |
339 EXPECT_EQ(1u, | 334 EXPECT_EQ(1u, |
340 handler()->GetNumEventListenersForTesting(kEventName, context_a)); | 335 handler()->GetNumEventListenersForTesting(kEventName, context_a)); |
341 EXPECT_EQ(0u, | 336 EXPECT_EQ(0u, |
342 handler()->GetNumEventListenersForTesting(kEventName, context_b)); | 337 handler()->GetNumEventListenersForTesting(kEventName, context_b)); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 "eventArgs")); | 381 "eventArgs")); |
387 } | 382 } |
388 } | 383 } |
389 | 384 |
390 TEST_F(APIEventHandlerTest, DifferentCallingMethods) { | 385 TEST_F(APIEventHandlerTest, DifferentCallingMethods) { |
391 v8::HandleScope handle_scope(isolate()); | 386 v8::HandleScope handle_scope(isolate()); |
392 v8::Local<v8::Context> context = MainContext(); | 387 v8::Local<v8::Context> context = MainContext(); |
393 | 388 |
394 const char kEventName[] = "alpha"; | 389 const char kEventName[] = "alpha"; |
395 v8::Local<v8::Object> event = handler()->CreateEventInstance( | 390 v8::Local<v8::Object> event = handler()->CreateEventInstance( |
396 kEventName, false, binding::kNoListenerMax, true, context); | 391 kEventName, false, true, binding::kNoListenerMax, true, context); |
397 ASSERT_FALSE(event.IsEmpty()); | 392 ASSERT_FALSE(event.IsEmpty()); |
398 | 393 |
399 const char kAddListenerOnNull[] = | 394 const char kAddListenerOnNull[] = |
400 "(function(event) {\n" | 395 "(function(event) {\n" |
401 " event.addListener.call(null, function() {});\n" | 396 " event.addListener.call(null, function() {});\n" |
402 "})"; | 397 "})"; |
403 { | 398 { |
404 v8::Local<v8::Value> args[] = {event}; | 399 v8::Local<v8::Value> args[] = {event}; |
405 // TODO(devlin): This is the generic type error that gin throws. It's not | 400 // TODO(devlin): This is the generic type error that gin throws. It's not |
406 // very descriptive, nor does it match the web (which would just say e.g. | 401 // very descriptive, nor does it match the web (which would just say e.g. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 context, 1, args); | 433 context, 1, args); |
439 } | 434 } |
440 EXPECT_EQ(2u, handler()->GetNumEventListenersForTesting(kEventName, context)); | 435 EXPECT_EQ(2u, handler()->GetNumEventListenersForTesting(kEventName, context)); |
441 } | 436 } |
442 | 437 |
443 TEST_F(APIEventHandlerTest, TestDispatchFromJs) { | 438 TEST_F(APIEventHandlerTest, TestDispatchFromJs) { |
444 v8::HandleScope handle_scope(isolate()); | 439 v8::HandleScope handle_scope(isolate()); |
445 v8::Local<v8::Context> context = MainContext(); | 440 v8::Local<v8::Context> context = MainContext(); |
446 | 441 |
447 v8::Local<v8::Object> event = handler()->CreateEventInstance( | 442 v8::Local<v8::Object> event = handler()->CreateEventInstance( |
448 "alpha", false, binding::kNoListenerMax, true, context); | 443 "alpha", false, true, binding::kNoListenerMax, true, context); |
449 ASSERT_FALSE(event.IsEmpty()); | 444 ASSERT_FALSE(event.IsEmpty()); |
450 | 445 |
451 const char kListenerFunction[] = | 446 const char kListenerFunction[] = |
452 "(function() {\n" | 447 "(function() {\n" |
453 " this.eventArgs = Array.from(arguments);\n" | 448 " this.eventArgs = Array.from(arguments);\n" |
454 "});"; | 449 "});"; |
455 v8::Local<v8::Function> listener = | 450 v8::Local<v8::Function> listener = |
456 FunctionFromString(context, kListenerFunction); | 451 FunctionFromString(context, kListenerFunction); |
457 | 452 |
458 const char kAddListenerFunction[] = | |
459 "(function(event, listener) { event.addListener(listener); })"; | |
460 v8::Local<v8::Function> add_listener_function = | 453 v8::Local<v8::Function> add_listener_function = |
461 FunctionFromString(context, kAddListenerFunction); | 454 FunctionFromString(context, kAddListenerFunction); |
462 | 455 |
463 { | 456 { |
464 v8::Local<v8::Value> argv[] = {event, listener}; | 457 v8::Local<v8::Value> argv[] = {event, listener}; |
465 RunFunctionOnGlobal(add_listener_function, context, arraysize(argv), argv); | 458 RunFunctionOnGlobal(add_listener_function, context, arraysize(argv), argv); |
466 } | 459 } |
467 | 460 |
468 v8::Local<v8::Function> fire_event_function = | 461 v8::Local<v8::Function> fire_event_function = |
469 FunctionFromString( | 462 FunctionFromString( |
470 context, | 463 context, |
471 "(function(event) { event.dispatch(42, 'foo', {bar: 'baz'}); })"); | 464 "(function(event) { event.dispatch(42, 'foo', {bar: 'baz'}); })"); |
472 { | 465 { |
473 v8::Local<v8::Value> argv[] = {event}; | 466 v8::Local<v8::Value> argv[] = {event}; |
474 RunFunctionOnGlobal(fire_event_function, context, arraysize(argv), argv); | 467 RunFunctionOnGlobal(fire_event_function, context, arraysize(argv), argv); |
475 } | 468 } |
476 | 469 |
477 EXPECT_EQ("[42,\"foo\",{\"bar\":\"baz\"}]", | 470 EXPECT_EQ("[42,\"foo\",{\"bar\":\"baz\"}]", |
478 GetStringPropertyFromObject( | 471 GetStringPropertyFromObject( |
479 context->Global(), context, "eventArgs")); | 472 context->Global(), context, "eventArgs")); |
480 } | 473 } |
481 | 474 |
482 // Test listeners that remove themselves in their handling of the event. | 475 // Test listeners that remove themselves in their handling of the event. |
483 TEST_F(APIEventHandlerTest, RemovingListenersWhileHandlingEvent) { | 476 TEST_F(APIEventHandlerTest, RemovingListenersWhileHandlingEvent) { |
484 v8::HandleScope handle_scope(isolate()); | 477 v8::HandleScope handle_scope(isolate()); |
485 v8::Local<v8::Context> context = MainContext(); | 478 v8::Local<v8::Context> context = MainContext(); |
486 | 479 |
487 const char kEventName[] = "alpha"; | 480 const char kEventName[] = "alpha"; |
488 v8::Local<v8::Object> event = handler()->CreateEventInstance( | 481 v8::Local<v8::Object> event = handler()->CreateEventInstance( |
489 kEventName, false, binding::kNoListenerMax, true, context); | 482 kEventName, false, true, binding::kNoListenerMax, true, context); |
490 ASSERT_FALSE(event.IsEmpty()); | 483 ASSERT_FALSE(event.IsEmpty()); |
491 { | 484 { |
492 // Cache the event object on the global in order to allow for easy removal. | 485 // Cache the event object on the global in order to allow for easy removal. |
493 v8::Local<v8::Function> set_event_on_global = | 486 v8::Local<v8::Function> set_event_on_global = |
494 FunctionFromString( | 487 FunctionFromString( |
495 context, | 488 context, |
496 "(function(event) { this.testEvent = event; })"); | 489 "(function(event) { this.testEvent = event; })"); |
497 v8::Local<v8::Value> args[] = {event}; | 490 v8::Local<v8::Value> args[] = {event}; |
498 RunFunctionOnGlobal(set_event_on_global, context, arraysize(args), args); | 491 RunFunctionOnGlobal(set_event_on_global, context, arraysize(args), args); |
499 EXPECT_EQ(event, | 492 EXPECT_EQ(event, |
500 GetPropertyFromObject(context->Global(), context, "testEvent")); | 493 GetPropertyFromObject(context->Global(), context, "testEvent")); |
501 } | 494 } |
502 | 495 |
503 // A listener function that removes itself as a listener. | 496 // A listener function that removes itself as a listener. |
504 const char kListenerFunction[] = | 497 const char kListenerFunction[] = |
505 "(function() {\n" | 498 "(function() {\n" |
506 " return function listener() {\n" | 499 " return function listener() {\n" |
507 " this.testEvent.removeListener(listener);\n" | 500 " this.testEvent.removeListener(listener);\n" |
508 " };\n" | 501 " };\n" |
509 "})();"; | 502 "})();"; |
510 | 503 |
511 // Create and add a bunch of listeners. | 504 // Create and add a bunch of listeners. |
512 std::vector<v8::Local<v8::Function>> listeners; | 505 std::vector<v8::Local<v8::Function>> listeners; |
513 const size_t kNumListeners = 20u; | 506 const size_t kNumListeners = 20u; |
514 listeners.reserve(kNumListeners); | 507 listeners.reserve(kNumListeners); |
515 for (size_t i = 0; i < kNumListeners; ++i) | 508 for (size_t i = 0; i < kNumListeners; ++i) |
516 listeners.push_back(FunctionFromString(context, kListenerFunction)); | 509 listeners.push_back(FunctionFromString(context, kListenerFunction)); |
517 | 510 |
518 const char kAddListenerFunction[] = | |
519 "(function(event, listener) { event.addListener(listener); })"; | |
520 v8::Local<v8::Function> add_listener_function = | 511 v8::Local<v8::Function> add_listener_function = |
521 FunctionFromString(context, kAddListenerFunction); | 512 FunctionFromString(context, kAddListenerFunction); |
522 | 513 |
523 for (const auto& listener : listeners) { | 514 for (const auto& listener : listeners) { |
524 v8::Local<v8::Value> argv[] = {event, listener}; | 515 v8::Local<v8::Value> argv[] = {event, listener}; |
525 RunFunctionOnGlobal(add_listener_function, context, arraysize(argv), argv); | 516 RunFunctionOnGlobal(add_listener_function, context, arraysize(argv), argv); |
526 } | 517 } |
527 | 518 |
528 // Fire the event. All listeners should be removed (and we shouldn't crash). | 519 // Fire the event. All listeners should be removed (and we shouldn't crash). |
529 EXPECT_EQ(kNumListeners, | 520 EXPECT_EQ(kNumListeners, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 SetHandler(base::MakeUnique<APIEventHandler>( | 554 SetHandler(base::MakeUnique<APIEventHandler>( |
564 base::Bind(run_js_and_expect_error), | 555 base::Bind(run_js_and_expect_error), |
565 base::Bind(&RunFunctionOnGlobalAndReturnHandle), | 556 base::Bind(&RunFunctionOnGlobalAndReturnHandle), |
566 base::Bind(&DoNothingOnEventListenersChanged), &exception_handler)); | 557 base::Bind(&DoNothingOnEventListenersChanged), &exception_handler)); |
567 | 558 |
568 v8::HandleScope handle_scope(isolate()); | 559 v8::HandleScope handle_scope(isolate()); |
569 v8::Local<v8::Context> context = MainContext(); | 560 v8::Local<v8::Context> context = MainContext(); |
570 | 561 |
571 const char kEventName[] = "alpha"; | 562 const char kEventName[] = "alpha"; |
572 v8::Local<v8::Object> event = handler()->CreateEventInstance( | 563 v8::Local<v8::Object> event = handler()->CreateEventInstance( |
573 kEventName, false, binding::kNoListenerMax, true, context); | 564 kEventName, false, true, binding::kNoListenerMax, true, context); |
574 ASSERT_FALSE(event.IsEmpty()); | 565 ASSERT_FALSE(event.IsEmpty()); |
575 | 566 |
576 // A listener that will throw an exception. We guarantee that we throw the | 567 // A listener that will throw an exception. We guarantee that we throw the |
577 // exception first so that we don't rely on event listener ordering. | 568 // exception first so that we don't rely on event listener ordering. |
578 const char kListenerFunction[] = | 569 const char kListenerFunction[] = |
579 "(function() {\n" | 570 "(function() {\n" |
580 " if (!this.didThrow) {\n" | 571 " if (!this.didThrow) {\n" |
581 " this.didThrow = true;\n" | 572 " this.didThrow = true;\n" |
582 " throw new Error('Event handler error');\n" | 573 " throw new Error('Event handler error');\n" |
583 " }\n" | 574 " }\n" |
584 " this.eventArgs = Array.from(arguments);\n" | 575 " this.eventArgs = Array.from(arguments);\n" |
585 "});"; | 576 "});"; |
586 | 577 |
587 const char kAddListenerFunction[] = | |
588 "(function(event, listener) { event.addListener(listener); })"; | |
589 v8::Local<v8::Function> add_listener_function = | 578 v8::Local<v8::Function> add_listener_function = |
590 FunctionFromString(context, kAddListenerFunction); | 579 FunctionFromString(context, kAddListenerFunction); |
591 | 580 |
592 for (int i = 0; i < 2; ++i) { | 581 for (int i = 0; i < 2; ++i) { |
593 v8::Local<v8::Function> listener = | 582 v8::Local<v8::Function> listener = |
594 FunctionFromString(context, kListenerFunction); | 583 FunctionFromString(context, kListenerFunction); |
595 v8::Local<v8::Value> argv[] = {event, listener}; | 584 v8::Local<v8::Value> argv[] = {event, listener}; |
596 RunFunctionOnGlobal(add_listener_function, context, arraysize(argv), argv); | 585 RunFunctionOnGlobal(add_listener_function, context, arraysize(argv), argv); |
597 } | 586 } |
598 EXPECT_EQ(2u, handler()->GetNumEventListenersForTesting(kEventName, context)); | 587 EXPECT_EQ(2u, handler()->GetNumEventListenersForTesting(kEventName, context)); |
(...skipping 22 matching lines...) Expand all Loading... |
621 nullptr)); | 610 nullptr)); |
622 | 611 |
623 v8::HandleScope handle_scope(isolate()); | 612 v8::HandleScope handle_scope(isolate()); |
624 | 613 |
625 v8::Local<v8::Context> context_a = MainContext(); | 614 v8::Local<v8::Context> context_a = MainContext(); |
626 v8::Local<v8::Context> context_b = AddContext(); | 615 v8::Local<v8::Context> context_b = AddContext(); |
627 | 616 |
628 const char kEventName1[] = "onFoo"; | 617 const char kEventName1[] = "onFoo"; |
629 const char kEventName2[] = "onBar"; | 618 const char kEventName2[] = "onBar"; |
630 v8::Local<v8::Object> event1_a = handler()->CreateEventInstance( | 619 v8::Local<v8::Object> event1_a = handler()->CreateEventInstance( |
631 kEventName1, false, binding::kNoListenerMax, true, context_a); | 620 kEventName1, false, true, binding::kNoListenerMax, true, context_a); |
632 ASSERT_FALSE(event1_a.IsEmpty()); | 621 ASSERT_FALSE(event1_a.IsEmpty()); |
633 v8::Local<v8::Object> event2_a = handler()->CreateEventInstance( | 622 v8::Local<v8::Object> event2_a = handler()->CreateEventInstance( |
634 kEventName2, false, binding::kNoListenerMax, true, context_a); | 623 kEventName2, false, true, binding::kNoListenerMax, true, context_a); |
635 ASSERT_FALSE(event2_a.IsEmpty()); | 624 ASSERT_FALSE(event2_a.IsEmpty()); |
636 v8::Local<v8::Object> event1_b = handler()->CreateEventInstance( | 625 v8::Local<v8::Object> event1_b = handler()->CreateEventInstance( |
637 kEventName1, false, binding::kNoListenerMax, true, context_b); | 626 kEventName1, false, true, binding::kNoListenerMax, true, context_b); |
638 ASSERT_FALSE(event1_b.IsEmpty()); | 627 ASSERT_FALSE(event1_b.IsEmpty()); |
639 | 628 |
640 const char kAddListenerFunction[] = | |
641 "(function(event, listener) { event.addListener(listener); })"; | |
642 const char kRemoveListenerFunction[] = | |
643 "(function(event, listener) { event.removeListener(listener); })"; | |
644 | |
645 // Add a listener to the first event. The APIEventHandler should notify | 629 // Add a listener to the first event. The APIEventHandler should notify |
646 // since it's a change in state (no listeners -> listeners). | 630 // since it's a change in state (no listeners -> listeners). |
647 v8::Local<v8::Function> add_listener = | 631 v8::Local<v8::Function> add_listener = |
648 FunctionFromString(context_a, kAddListenerFunction); | 632 FunctionFromString(context_a, kAddListenerFunction); |
649 v8::Local<v8::Function> listener1 = | 633 v8::Local<v8::Function> listener1 = |
650 FunctionFromString(context_a, "(function() {})"); | 634 FunctionFromString(context_a, "(function() {})"); |
651 { | 635 { |
652 EXPECT_CALL(change_handler, | 636 EXPECT_CALL(change_handler, |
653 Run(kEventName1, binding::EventListenersChanged::HAS_LISTENERS, | 637 Run(kEventName1, binding::EventListenersChanged::HAS_LISTENERS, |
654 nullptr, true, context_a)) | 638 nullptr, true, context_a)) |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 ::testing::Mock::VerifyAndClearExpectations(&change_handler); | 733 ::testing::Mock::VerifyAndClearExpectations(&change_handler); |
750 } | 734 } |
751 | 735 |
752 // Test registering an argument massager for a given event. | 736 // Test registering an argument massager for a given event. |
753 TEST_F(APIEventHandlerTest, TestArgumentMassagers) { | 737 TEST_F(APIEventHandlerTest, TestArgumentMassagers) { |
754 v8::HandleScope handle_scope(isolate()); | 738 v8::HandleScope handle_scope(isolate()); |
755 v8::Local<v8::Context> context = MainContext(); | 739 v8::Local<v8::Context> context = MainContext(); |
756 | 740 |
757 const char kEventName[] = "alpha"; | 741 const char kEventName[] = "alpha"; |
758 v8::Local<v8::Object> event = handler()->CreateEventInstance( | 742 v8::Local<v8::Object> event = handler()->CreateEventInstance( |
759 kEventName, false, binding::kNoListenerMax, true, context); | 743 kEventName, false, true, binding::kNoListenerMax, true, context); |
760 ASSERT_FALSE(event.IsEmpty()); | 744 ASSERT_FALSE(event.IsEmpty()); |
761 | 745 |
762 const char kArgumentMassager[] = | 746 const char kArgumentMassager[] = |
763 "(function(originalArgs, dispatch) {\n" | 747 "(function(originalArgs, dispatch) {\n" |
764 " this.originalArgs = originalArgs;\n" | 748 " this.originalArgs = originalArgs;\n" |
765 " dispatch(['primary', 'secondary']);\n" | 749 " dispatch(['primary', 'secondary']);\n" |
766 "});"; | 750 "});"; |
767 v8::Local<v8::Function> massager = | 751 v8::Local<v8::Function> massager = |
768 FunctionFromString(context, kArgumentMassager); | 752 FunctionFromString(context, kArgumentMassager); |
769 handler()->RegisterArgumentMassager(context, "alpha", massager); | 753 handler()->RegisterArgumentMassager(context, "alpha", massager); |
770 | 754 |
771 const char kListenerFunction[] = | 755 const char kListenerFunction[] = |
772 "(function() { this.eventArgs = Array.from(arguments); })"; | 756 "(function() { this.eventArgs = Array.from(arguments); })"; |
773 v8::Local<v8::Function> listener_function = | 757 v8::Local<v8::Function> listener_function = |
774 FunctionFromString(context, kListenerFunction); | 758 FunctionFromString(context, kListenerFunction); |
775 ASSERT_FALSE(listener_function.IsEmpty()); | 759 ASSERT_FALSE(listener_function.IsEmpty()); |
776 | 760 |
777 { | 761 { |
778 const char kAddListenerFunction[] = | |
779 "(function(event, listener) { event.addListener(listener); })"; | |
780 v8::Local<v8::Function> add_listener_function = | 762 v8::Local<v8::Function> add_listener_function = |
781 FunctionFromString(context, kAddListenerFunction); | 763 FunctionFromString(context, kAddListenerFunction); |
782 v8::Local<v8::Value> argv[] = {event, listener_function}; | 764 v8::Local<v8::Value> argv[] = {event, listener_function}; |
783 RunFunction(add_listener_function, context, arraysize(argv), argv); | 765 RunFunction(add_listener_function, context, arraysize(argv), argv); |
784 } | 766 } |
785 | 767 |
786 const char kArguments[] = "['first','second']"; | 768 const char kArguments[] = "['first','second']"; |
787 std::unique_ptr<base::ListValue> event_args = ListValueFromString(kArguments); | 769 std::unique_ptr<base::ListValue> event_args = ListValueFromString(kArguments); |
788 ASSERT_TRUE(event_args); | 770 ASSERT_TRUE(event_args); |
789 handler()->FireEventInContext(kEventName, context, *event_args, nullptr); | 771 handler()->FireEventInContext(kEventName, context, *event_args, nullptr); |
790 | 772 |
791 EXPECT_EQ( | 773 EXPECT_EQ( |
792 "[\"first\",\"second\"]", | 774 "[\"first\",\"second\"]", |
793 GetStringPropertyFromObject(context->Global(), context, "originalArgs")); | 775 GetStringPropertyFromObject(context->Global(), context, "originalArgs")); |
794 EXPECT_EQ( | 776 EXPECT_EQ( |
795 "[\"primary\",\"secondary\"]", | 777 "[\"primary\",\"secondary\"]", |
796 GetStringPropertyFromObject(context->Global(), context, "eventArgs")); | 778 GetStringPropertyFromObject(context->Global(), context, "eventArgs")); |
797 } | 779 } |
798 | 780 |
799 // Test registering an argument massager for a given event and dispatching | 781 // Test registering an argument massager for a given event and dispatching |
800 // asynchronously. | 782 // asynchronously. |
801 TEST_F(APIEventHandlerTest, TestArgumentMassagersAsyncDispatch) { | 783 TEST_F(APIEventHandlerTest, TestArgumentMassagersAsyncDispatch) { |
802 v8::HandleScope handle_scope(isolate()); | 784 v8::HandleScope handle_scope(isolate()); |
803 v8::Local<v8::Context> context = MainContext(); | 785 v8::Local<v8::Context> context = MainContext(); |
804 | 786 |
805 const char kEventName[] = "alpha"; | 787 const char kEventName[] = "alpha"; |
806 v8::Local<v8::Object> event = handler()->CreateEventInstance( | 788 v8::Local<v8::Object> event = handler()->CreateEventInstance( |
807 kEventName, false, binding::kNoListenerMax, true, context); | 789 kEventName, false, true, binding::kNoListenerMax, true, context); |
808 ASSERT_FALSE(event.IsEmpty()); | 790 ASSERT_FALSE(event.IsEmpty()); |
809 | 791 |
810 const char kArgumentMassager[] = | 792 const char kArgumentMassager[] = |
811 "(function(originalArgs, dispatch) {\n" | 793 "(function(originalArgs, dispatch) {\n" |
812 " this.originalArgs = originalArgs;\n" | 794 " this.originalArgs = originalArgs;\n" |
813 " this.dispatch = dispatch;\n" | 795 " this.dispatch = dispatch;\n" |
814 "});"; | 796 "});"; |
815 v8::Local<v8::Function> massager = | 797 v8::Local<v8::Function> massager = |
816 FunctionFromString(context, kArgumentMassager); | 798 FunctionFromString(context, kArgumentMassager); |
817 handler()->RegisterArgumentMassager(context, "alpha", massager); | 799 handler()->RegisterArgumentMassager(context, "alpha", massager); |
818 | 800 |
819 const char kListenerFunction[] = | 801 const char kListenerFunction[] = |
820 "(function() { this.eventArgs = Array.from(arguments); })"; | 802 "(function() { this.eventArgs = Array.from(arguments); })"; |
821 v8::Local<v8::Function> listener_function = | 803 v8::Local<v8::Function> listener_function = |
822 FunctionFromString(context, kListenerFunction); | 804 FunctionFromString(context, kListenerFunction); |
823 ASSERT_FALSE(listener_function.IsEmpty()); | 805 ASSERT_FALSE(listener_function.IsEmpty()); |
824 | 806 |
825 { | 807 { |
826 const char kAddListenerFunction[] = | |
827 "(function(event, listener) { event.addListener(listener); })"; | |
828 v8::Local<v8::Function> add_listener_function = | 808 v8::Local<v8::Function> add_listener_function = |
829 FunctionFromString(context, kAddListenerFunction); | 809 FunctionFromString(context, kAddListenerFunction); |
830 v8::Local<v8::Value> argv[] = {event, listener_function}; | 810 v8::Local<v8::Value> argv[] = {event, listener_function}; |
831 RunFunction(add_listener_function, context, arraysize(argv), argv); | 811 RunFunction(add_listener_function, context, arraysize(argv), argv); |
832 } | 812 } |
833 | 813 |
834 const char kArguments[] = "['first','second']"; | 814 const char kArguments[] = "['first','second']"; |
835 std::unique_ptr<base::ListValue> event_args = ListValueFromString(kArguments); | 815 std::unique_ptr<base::ListValue> event_args = ListValueFromString(kArguments); |
836 ASSERT_TRUE(event_args); | 816 ASSERT_TRUE(event_args); |
837 handler()->FireEventInContext(kEventName, context, *event_args, nullptr); | 817 handler()->FireEventInContext(kEventName, context, *event_args, nullptr); |
(...skipping 22 matching lines...) Expand all Loading... |
860 GetStringPropertyFromObject(context->Global(), context, "eventArgs")); | 840 GetStringPropertyFromObject(context->Global(), context, "eventArgs")); |
861 } | 841 } |
862 | 842 |
863 // Test registering an argument massager and never dispatching. | 843 // Test registering an argument massager and never dispatching. |
864 TEST_F(APIEventHandlerTest, TestArgumentMassagersNeverDispatch) { | 844 TEST_F(APIEventHandlerTest, TestArgumentMassagersNeverDispatch) { |
865 v8::HandleScope handle_scope(isolate()); | 845 v8::HandleScope handle_scope(isolate()); |
866 v8::Local<v8::Context> context = MainContext(); | 846 v8::Local<v8::Context> context = MainContext(); |
867 | 847 |
868 const char kEventName[] = "alpha"; | 848 const char kEventName[] = "alpha"; |
869 v8::Local<v8::Object> event = handler()->CreateEventInstance( | 849 v8::Local<v8::Object> event = handler()->CreateEventInstance( |
870 kEventName, false, binding::kNoListenerMax, true, context); | 850 kEventName, false, true, binding::kNoListenerMax, true, context); |
871 ASSERT_FALSE(event.IsEmpty()); | 851 ASSERT_FALSE(event.IsEmpty()); |
872 | 852 |
873 // A massager that never dispatches. | 853 // A massager that never dispatches. |
874 const char kArgumentMassager[] = "(function(originalArgs, dispatch) {})"; | 854 const char kArgumentMassager[] = "(function(originalArgs, dispatch) {})"; |
875 v8::Local<v8::Function> massager = | 855 v8::Local<v8::Function> massager = |
876 FunctionFromString(context, kArgumentMassager); | 856 FunctionFromString(context, kArgumentMassager); |
877 handler()->RegisterArgumentMassager(context, "alpha", massager); | 857 handler()->RegisterArgumentMassager(context, "alpha", massager); |
878 | 858 |
879 const char kListenerFunction[] = "(function() {})"; | 859 const char kListenerFunction[] = "(function() {})"; |
880 v8::Local<v8::Function> listener_function = | 860 v8::Local<v8::Function> listener_function = |
881 FunctionFromString(context, kListenerFunction); | 861 FunctionFromString(context, kListenerFunction); |
882 ASSERT_FALSE(listener_function.IsEmpty()); | 862 ASSERT_FALSE(listener_function.IsEmpty()); |
883 | 863 |
884 const char kAddListenerFunction[] = | |
885 "(function(event, listener) { event.addListener(listener); })"; | |
886 v8::Local<v8::Function> add_listener_function = | 864 v8::Local<v8::Function> add_listener_function = |
887 FunctionFromString(context, kAddListenerFunction); | 865 FunctionFromString(context, kAddListenerFunction); |
888 v8::Local<v8::Value> argv[] = {event, listener_function}; | 866 v8::Local<v8::Value> argv[] = {event, listener_function}; |
889 RunFunction(add_listener_function, context, arraysize(argv), argv); | 867 RunFunction(add_listener_function, context, arraysize(argv), argv); |
890 | 868 |
891 handler()->FireEventInContext(kEventName, context, base::ListValue(), | 869 handler()->FireEventInContext(kEventName, context, base::ListValue(), |
892 nullptr); | 870 nullptr); |
893 | 871 |
894 // Nothing should blow up. (We tested in the previous test that the event | 872 // Nothing should blow up. (We tested in the previous test that the event |
895 // isn't notified without calling dispatch, so all there is to test here is | 873 // isn't notified without calling dispatch, so all there is to test here is |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
977 [](const std::string& event_name, binding::EventListenersChanged changed, | 955 [](const std::string& event_name, binding::EventListenersChanged changed, |
978 const base::DictionaryValue* filter, bool was_manual, | 956 const base::DictionaryValue* filter, bool was_manual, |
979 v8::Local<v8::Context> context) { ADD_FAILURE(); }; | 957 v8::Local<v8::Context> context) { ADD_FAILURE(); }; |
980 | 958 |
981 APIEventHandler handler(base::Bind(&RunFunctionOnGlobalAndIgnoreResult), | 959 APIEventHandler handler(base::Bind(&RunFunctionOnGlobalAndIgnoreResult), |
982 base::Bind(&RunFunctionOnGlobalAndReturnHandle), | 960 base::Bind(&RunFunctionOnGlobalAndReturnHandle), |
983 base::Bind(fail_on_notified), nullptr); | 961 base::Bind(fail_on_notified), nullptr); |
984 | 962 |
985 const char kEventName[] = "alpha"; | 963 const char kEventName[] = "alpha"; |
986 v8::Local<v8::Object> event = handler.CreateEventInstance( | 964 v8::Local<v8::Object> event = handler.CreateEventInstance( |
987 kEventName, false, binding::kNoListenerMax, false, context); | 965 kEventName, false, true, binding::kNoListenerMax, false, context); |
988 | 966 |
989 const char kListener[] = | 967 const char kListener[] = |
990 "(function() {\n" | 968 "(function() {\n" |
991 " this.eventArgs = Array.from(arguments);\n" | 969 " this.eventArgs = Array.from(arguments);\n" |
992 "});"; | 970 "});"; |
993 v8::Local<v8::Function> listener = FunctionFromString(context, kListener); | 971 v8::Local<v8::Function> listener = FunctionFromString(context, kListener); |
994 | 972 |
995 { | 973 { |
996 const char kAddListener[] = | 974 const char kAddListener[] = |
997 "(function(event, listener) { event.addListener(listener); })"; | 975 "(function(event, listener) { event.addListener(listener); })"; |
(...skipping 14 matching lines...) Expand all Loading... |
1012 const char kRemoveListener[] = | 990 const char kRemoveListener[] = |
1013 "(function(event, listener) { event.removeListener(listener); })"; | 991 "(function(event, listener) { event.removeListener(listener); })"; |
1014 v8::Local<v8::Value> args[] = {event, listener}; | 992 v8::Local<v8::Value> args[] = {event, listener}; |
1015 RunFunction(FunctionFromString(context, kRemoveListener), context, | 993 RunFunction(FunctionFromString(context, kRemoveListener), context, |
1016 arraysize(args), args); | 994 arraysize(args), args); |
1017 } | 995 } |
1018 | 996 |
1019 EXPECT_EQ(0u, handler.GetNumEventListenersForTesting(kEventName, context)); | 997 EXPECT_EQ(0u, handler.GetNumEventListenersForTesting(kEventName, context)); |
1020 } | 998 } |
1021 | 999 |
| 1000 // Test callback notifications for events that don't support lazy listeners. |
| 1001 TEST_F(APIEventHandlerTest, TestEventsWithoutLazyListeners) { |
| 1002 MockEventChangeHandler change_handler; |
| 1003 APIEventHandler handler(base::Bind(&RunFunctionOnGlobalAndIgnoreResult), |
| 1004 base::Bind(&RunFunctionOnGlobalAndReturnHandle), |
| 1005 change_handler.Get(), nullptr); |
| 1006 |
| 1007 v8::HandleScope handle_scope(isolate()); |
| 1008 v8::Local<v8::Context> context = MainContext(); |
| 1009 |
| 1010 const char kLazyListenersSupported[] = "supportsLazyListeners"; |
| 1011 const char kLazyListenersNotSupported[] = "noLazyListeners"; |
| 1012 v8::Local<v8::Object> lazy_listeners_supported = |
| 1013 handler.CreateEventInstance(kLazyListenersSupported, false, true, |
| 1014 binding::kNoListenerMax, true, context); |
| 1015 v8::Local<v8::Object> lazy_listeners_not_supported = |
| 1016 handler.CreateEventInstance(kLazyListenersNotSupported, false, false, |
| 1017 binding::kNoListenerMax, true, context); |
| 1018 ASSERT_FALSE(lazy_listeners_not_supported.IsEmpty()); |
| 1019 |
| 1020 v8::Local<v8::Function> add_listener = |
| 1021 FunctionFromString(context, kAddListenerFunction); |
| 1022 v8::Local<v8::Function> listener = |
| 1023 FunctionFromString(context, "(function() {})"); |
| 1024 { |
| 1025 EXPECT_CALL(change_handler, |
| 1026 Run(kLazyListenersSupported, |
| 1027 binding::EventListenersChanged::HAS_LISTENERS, nullptr, |
| 1028 true, context)) |
| 1029 .Times(1); |
| 1030 v8::Local<v8::Value> argv[] = {lazy_listeners_supported, listener}; |
| 1031 RunFunction(add_listener, context, arraysize(argv), argv); |
| 1032 ::testing::Mock::VerifyAndClearExpectations(&change_handler); |
| 1033 } |
| 1034 |
| 1035 { |
| 1036 EXPECT_CALL(change_handler, |
| 1037 Run(kLazyListenersNotSupported, |
| 1038 binding::EventListenersChanged::HAS_LISTENERS, nullptr, |
| 1039 false, context)) |
| 1040 .Times(1); |
| 1041 v8::Local<v8::Value> argv[] = {lazy_listeners_not_supported, listener}; |
| 1042 RunFunction(add_listener, context, arraysize(argv), argv); |
| 1043 ::testing::Mock::VerifyAndClearExpectations(&change_handler); |
| 1044 } |
| 1045 |
| 1046 v8::Local<v8::Function> remove_listener = |
| 1047 FunctionFromString(context, kRemoveListenerFunction); |
| 1048 { |
| 1049 EXPECT_CALL(change_handler, |
| 1050 Run(kLazyListenersSupported, |
| 1051 binding::EventListenersChanged::NO_LISTENERS, nullptr, true, |
| 1052 context)) |
| 1053 .Times(1); |
| 1054 v8::Local<v8::Value> argv[] = {lazy_listeners_supported, listener}; |
| 1055 RunFunction(remove_listener, context, arraysize(argv), argv); |
| 1056 ::testing::Mock::VerifyAndClearExpectations(&change_handler); |
| 1057 } |
| 1058 |
| 1059 { |
| 1060 EXPECT_CALL(change_handler, |
| 1061 Run(kLazyListenersNotSupported, |
| 1062 binding::EventListenersChanged::NO_LISTENERS, nullptr, |
| 1063 false, context)) |
| 1064 .Times(1); |
| 1065 v8::Local<v8::Value> argv[] = {lazy_listeners_not_supported, listener}; |
| 1066 RunFunction(remove_listener, context, arraysize(argv), argv); |
| 1067 ::testing::Mock::VerifyAndClearExpectations(&change_handler); |
| 1068 } |
| 1069 |
| 1070 DisposeContext(context); |
| 1071 } |
| 1072 |
1022 } // namespace extensions | 1073 } // namespace extensions |
OLD | NEW |