| 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 |