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