| Index: extensions/renderer/api_event_listeners.h
|
| diff --git a/extensions/renderer/api_event_listeners.h b/extensions/renderer/api_event_listeners.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..307730c0f907646387b5024eabaaf42f929925cf
|
| --- /dev/null
|
| +++ b/extensions/renderer/api_event_listeners.h
|
| @@ -0,0 +1,155 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef EXTENSIONS_RENDERER_API_EVENT_LISTENERS_H_
|
| +#define EXTENSIONS_RENDERER_API_EVENT_LISTENERS_H_
|
| +
|
| +#include <string>
|
| +#include <vector>
|
| +
|
| +#include "base/callback.h"
|
| +#include "base/macros.h"
|
| +#include "extensions/common/value_counter.h"
|
| +#include "extensions/renderer/api_binding_types.h"
|
| +#include "v8/include/v8.h"
|
| +
|
| +namespace base {
|
| +class DictionaryValue;
|
| +}
|
| +
|
| +namespace extensions {
|
| +class EventFilter;
|
| +class EventFilteringInfo;
|
| +
|
| +// A base class to hold listeners for a given event. This allows for adding,
|
| +// removing, and querying listeners in the list, and calling a callback when
|
| +// transitioning from 0 -> 1 or 1 -> 0 listeners.
|
| +class APIEventListeners {
|
| + public:
|
| + using ListenersUpdated =
|
| + base::Callback<void(binding::EventListenersChanged,
|
| + const base::DictionaryValue* filter,
|
| + v8::Local<v8::Context> context)>;
|
| +
|
| + virtual ~APIEventListeners() = default;
|
| +
|
| + // Adds the given |listener| to the list, possibly associating it with the
|
| + // given |filter|. Returns true if the listener is added. Populates |error|
|
| + // with any errors encountered. Note that |error| is *not* always populated
|
| + // if false is returned, since we don't consider trying to re-add a listener
|
| + // to be an error.
|
| + virtual bool AddListener(v8::Local<v8::Function> listener,
|
| + v8::Local<v8::Object> filter,
|
| + v8::Local<v8::Context> context,
|
| + std::string* error) = 0;
|
| +
|
| + // Removes the given |listener|, if it's present in the list.
|
| + virtual void RemoveListener(v8::Local<v8::Function> listener,
|
| + v8::Local<v8::Context> context) = 0;
|
| +
|
| + // Returns true if the given |listener| is in the list.
|
| + virtual bool HasListener(v8::Local<v8::Function> listener) = 0;
|
| +
|
| + // Returns the number of listeners in the list.
|
| + virtual size_t GetNumListeners() = 0;
|
| +
|
| + // Returns the listeners that should be notified for the given |filter|.
|
| + virtual std::vector<v8::Local<v8::Function>> GetListeners(
|
| + const EventFilteringInfo* filter,
|
| + v8::Local<v8::Context> context) = 0;
|
| +
|
| + // Invalidates the list.
|
| + virtual void Invalidate(v8::Local<v8::Context> context) = 0;
|
| +
|
| + protected:
|
| + APIEventListeners() {}
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(APIEventListeners);
|
| +};
|
| +
|
| +// A listener list implementation that doesn't support filtering. Each event
|
| +// dispatched is dispatched to all the associated listeners.
|
| +class UnfilteredEventListeners final : public APIEventListeners {
|
| + public:
|
| + UnfilteredEventListeners(const ListenersUpdated& listeners_updated);
|
| + ~UnfilteredEventListeners() override;
|
| +
|
| + bool AddListener(v8::Local<v8::Function> listener,
|
| + v8::Local<v8::Object> filter,
|
| + v8::Local<v8::Context> context,
|
| + std::string* error) override;
|
| + void RemoveListener(v8::Local<v8::Function> listener,
|
| + v8::Local<v8::Context> context) override;
|
| + bool HasListener(v8::Local<v8::Function> listener) override;
|
| + size_t GetNumListeners() override;
|
| + std::vector<v8::Local<v8::Function>> GetListeners(
|
| + const EventFilteringInfo* filter,
|
| + v8::Local<v8::Context> context) override;
|
| + void Invalidate(v8::Local<v8::Context> context) override;
|
| +
|
| + private:
|
| + // The event listeners associated with this event.
|
| + // TODO(devlin): Having these listeners held as v8::Globals means that we
|
| + // need to worry about cycles when a listener holds a reference to the event,
|
| + // e.g. EventEmitter -> Listener -> EventEmitter. Right now, we handle that by
|
| + // requiring Invalidate() to be called, but that means that events that aren't
|
| + // Invalidate()'d earlier can leak until context destruction. We could
|
| + // circumvent this by storing the listeners strongly in a private propery
|
| + // (thus traceable by v8), and optionally keep a weak cache on this object.
|
| + std::vector<v8::Global<v8::Function>> listeners_;
|
| +
|
| + ListenersUpdated listeners_updated_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(UnfilteredEventListeners);
|
| +};
|
| +
|
| +// A listener list implementation that supports filtering. Events should only
|
| +// be dispatched to those listeners whose filters match. Additionally, the
|
| +// updated callback is triggered any time a listener with a new filter is
|
| +// added, or the last listener with a given filter is removed.
|
| +class FilteredEventListeners final : public APIEventListeners {
|
| + public:
|
| + FilteredEventListeners(const ListenersUpdated& listeners_updated,
|
| + const std::string& event_name,
|
| + EventFilter* event_filter);
|
| + ~FilteredEventListeners() override;
|
| +
|
| + bool AddListener(v8::Local<v8::Function> listener,
|
| + v8::Local<v8::Object> filter,
|
| + v8::Local<v8::Context> context,
|
| + std::string* error) override;
|
| + void RemoveListener(v8::Local<v8::Function> listener,
|
| + v8::Local<v8::Context> context) override;
|
| + bool HasListener(v8::Local<v8::Function> listener) override;
|
| + size_t GetNumListeners() override;
|
| + std::vector<v8::Local<v8::Function>> GetListeners(
|
| + const EventFilteringInfo* filter,
|
| + v8::Local<v8::Context> context) override;
|
| + void Invalidate(v8::Local<v8::Context> context) override;
|
| +
|
| + private:
|
| + struct ListenerData;
|
| +
|
| + void InvalidateListener(const ListenerData& listener,
|
| + v8::Local<v8::Context> context);
|
| +
|
| + // Note: See TODO on UnfilteredEventListeners::listeners_.
|
| + std::vector<ListenerData> listeners_;
|
| +
|
| + ListenersUpdated listeners_updated_;
|
| +
|
| + std::string event_name_;
|
| +
|
| + // The associated EventFilter; required to outlive this object.
|
| + EventFilter* event_filter_ = nullptr;
|
| +
|
| + ValueCounter value_counter_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(FilteredEventListeners);
|
| +};
|
| +
|
| +} // namespace extensions
|
| +
|
| +#endif // EXTENSIONS_RENDERER_API_EVENT_LISTENERS_H_
|
|
|