| Index: extensions/renderer/event_emitter.cc
|
| diff --git a/extensions/renderer/event_emitter.cc b/extensions/renderer/event_emitter.cc
|
| index 82523e96aeef7458c56031d0531294bf8e8991e5..e6cd97721cff477f894d881cebcec3acaa6a6c11 100644
|
| --- a/extensions/renderer/event_emitter.cc
|
| +++ b/extensions/renderer/event_emitter.cc
|
| @@ -6,6 +6,7 @@
|
|
|
| #include <algorithm>
|
|
|
| +#include "extensions/renderer/api_event_listeners.h"
|
| #include "gin/object_template_builder.h"
|
| #include "gin/per_context_data.h"
|
|
|
| @@ -13,9 +14,12 @@ namespace extensions {
|
|
|
| gin::WrapperInfo EventEmitter::kWrapperInfo = {gin::kEmbedderNativeGin};
|
|
|
| -EventEmitter::EventEmitter(const binding::RunJSFunction& run_js,
|
| - const ListenersChangedMethod& listeners_changed)
|
| - : run_js_(run_js), listeners_changed_(listeners_changed) {}
|
| +EventEmitter::EventEmitter(bool supports_filters,
|
| + std::unique_ptr<APIEventListeners> listeners,
|
| + const binding::RunJSFunction& run_js)
|
| + : supports_filters_(supports_filters),
|
| + listeners_(std::move(listeners)),
|
| + run_js_(run_js) {}
|
|
|
| EventEmitter::~EventEmitter() {}
|
|
|
| @@ -34,13 +38,11 @@ gin::ObjectTemplateBuilder EventEmitter::GetObjectTemplateBuilder(
|
| }
|
|
|
| void EventEmitter::Fire(v8::Local<v8::Context> context,
|
| - std::vector<v8::Local<v8::Value>>* args) {
|
| - // We create a local copy of listeners_ since the array can be modified during
|
| - // handling.
|
| - std::vector<v8::Local<v8::Function>> listeners;
|
| - listeners.reserve(listeners_.size());
|
| - for (const auto& listener : listeners_)
|
| - listeners.push_back(listener.Get(context->GetIsolate()));
|
| + std::vector<v8::Local<v8::Value>>* args,
|
| + const EventFilteringInfo* filter) {
|
| + // Note that |listeners_| can be modified during handling.
|
| + std::vector<v8::Local<v8::Function>> listeners =
|
| + listeners_->GetListeners(filter, context);
|
|
|
| for (const auto& listener : listeners) {
|
| v8::TryCatch try_catch(context->GetIsolate());
|
| @@ -52,9 +54,13 @@ void EventEmitter::Fire(v8::Local<v8::Context> context,
|
| }
|
| }
|
|
|
| -void EventEmitter::Invalidate() {
|
| +void EventEmitter::Invalidate(v8::Local<v8::Context> context) {
|
| valid_ = false;
|
| - listeners_.clear();
|
| + listeners_->Invalidate(context);
|
| +}
|
| +
|
| +size_t EventEmitter::GetNumListeners() const {
|
| + return listeners_->GetNumListeners();
|
| }
|
|
|
| void EventEmitter::AddListener(gin::Arguments* arguments) {
|
| @@ -72,6 +78,17 @@ void EventEmitter::AddListener(gin::Arguments* arguments) {
|
| if (!arguments->GetNext(&listener))
|
| return;
|
|
|
| + if (!arguments->PeekNext().IsEmpty() && !supports_filters_) {
|
| + arguments->ThrowTypeError("This event does not support filters");
|
| + return;
|
| + }
|
| +
|
| + v8::Local<v8::Object> filter;
|
| + if (!arguments->PeekNext().IsEmpty() && !arguments->GetNext(&filter)) {
|
| + arguments->ThrowTypeError("Invalid invocation");
|
| + return;
|
| + }
|
| +
|
| v8::Local<v8::Object> holder;
|
| CHECK(arguments->GetHolder(&holder));
|
| CHECK(!holder.IsEmpty());
|
| @@ -79,13 +96,10 @@ void EventEmitter::AddListener(gin::Arguments* arguments) {
|
| if (!gin::PerContextData::From(context))
|
| return;
|
|
|
| - if (!HasListener(listener)) {
|
| - listeners_.push_back(
|
| - v8::Global<v8::Function>(arguments->isolate(), listener));
|
| - if (listeners_.size() == 1) {
|
| - listeners_changed_.Run(binding::EventListenersChanged::HAS_LISTENERS,
|
| - context);
|
| - }
|
| + std::string error;
|
| + if (!listeners_->AddListener(listener, filter, context, &error) &&
|
| + !error.empty()) {
|
| + arguments->ThrowTypeError(error);
|
| }
|
| }
|
|
|
| @@ -99,34 +113,26 @@ void EventEmitter::RemoveListener(gin::Arguments* arguments) {
|
| if (!arguments->GetNext(&listener))
|
| return;
|
|
|
| - auto iter = std::find(listeners_.begin(), listeners_.end(), listener);
|
| - if (iter != listeners_.end()) {
|
| - listeners_.erase(iter);
|
| - if (listeners_.empty()) {
|
| - v8::Local<v8::Object> holder;
|
| - CHECK(arguments->GetHolder(&holder));
|
| - CHECK(!holder.IsEmpty());
|
| - v8::Local<v8::Context> context = holder->CreationContext();
|
| - listeners_changed_.Run(binding::EventListenersChanged::NO_LISTENERS,
|
| - context);
|
| - }
|
| - }
|
| + v8::Local<v8::Object> holder;
|
| + CHECK(arguments->GetHolder(&holder));
|
| + CHECK(!holder.IsEmpty());
|
| + v8::Local<v8::Context> context = holder->CreationContext();
|
| + listeners_->RemoveListener(listener, context);
|
| }
|
|
|
| bool EventEmitter::HasListener(v8::Local<v8::Function> listener) {
|
| - return std::find(listeners_.begin(), listeners_.end(), listener) !=
|
| - listeners_.end();
|
| + return listeners_->HasListener(listener);
|
| }
|
|
|
| bool EventEmitter::HasListeners() {
|
| - return !listeners_.empty();
|
| + return listeners_->GetNumListeners() != 0;
|
| }
|
|
|
| void EventEmitter::Dispatch(gin::Arguments* arguments) {
|
| if (!valid_)
|
| return;
|
|
|
| - if (listeners_.empty())
|
| + if (listeners_->GetNumListeners() == 0)
|
| return;
|
| v8::HandleScope handle_scope(arguments->isolate());
|
| v8::Local<v8::Context> context =
|
| @@ -136,7 +142,7 @@ void EventEmitter::Dispatch(gin::Arguments* arguments) {
|
| // Converting to v8::Values should never fail.
|
| CHECK(arguments->GetRemaining(&v8_args));
|
| }
|
| - Fire(context, &v8_args);
|
| + Fire(context, &v8_args, nullptr);
|
| }
|
|
|
| } // namespace extensions
|
|
|