Istiaque Ahmed | b9af5f8 | 2017-09-20 18:19:45 | [diff] [blame] | 1 | // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef EXTENSIONS_RENDERER_EVENT_BOOKKEEPER_H_ |
| 6 | #define EXTENSIONS_RENDERER_EVENT_BOOKKEEPER_H_ |
| 7 | |
| 8 | #include <map> |
| 9 | #include <memory> |
| 10 | #include <set> |
| 11 | #include <string> |
| 12 | |
| 13 | #include "base/macros.h" |
| 14 | #include "extensions/common/event_filter.h" |
| 15 | #include "extensions/common/extension_id.h" |
| 16 | |
| 17 | namespace base { |
| 18 | class DictionaryValue; |
| 19 | } |
| 20 | |
| 21 | namespace extensions { |
| 22 | class EventFilter; |
| 23 | class ScriptContext; |
| 24 | class ValueCounter; |
| 25 | |
| 26 | // Class to manage thread (main or worker) specific event global data. |
| 27 | // |
| 28 | // TODO(lazyboy): This class could use an IPCMessageSender to also notify the |
| 29 | // browser/ about the changes in the event data it manages. Currently this is |
| 30 | // done from EventBindings, i.e. EventBindings updates/queries EventBookkeeper |
| 31 | // and then notifies the browser/. |
| 32 | // TODO(devlin/lazyboy): This class is only necessary with JS-based bindings. |
| 33 | // Remove it when Native bindings launch. |
| 34 | class EventBookkeeper { |
| 35 | public: |
| 36 | EventBookkeeper(); |
| 37 | ~EventBookkeeper(); |
| 38 | |
| 39 | // Returns the instance of EventBookkeeper that belongs to current thread. |
| 40 | static EventBookkeeper* Get(); |
| 41 | |
| 42 | // Increments the number of event-listeners for the given |event_name| and |
| 43 | // ScriptContext. Returns the count after the increment. |
| 44 | int IncrementEventListenerCount(ScriptContext* script_context, |
| 45 | const std::string& event_name); |
| 46 | // Decrements the number of event-listeners for the given |event_name| and |
| 47 | // ScriptContext. Returns the count after the decrement. |
| 48 | int DecrementEventListenerCount(ScriptContext* script_context, |
| 49 | const std::string& event_name); |
| 50 | |
| 51 | // Returns the EventFilter. |
| 52 | EventFilter& event_filter() { return event_filter_; } |
| 53 | |
| 54 | // Adds a filter to |event_name| in |extension_id|, returning true if it |
| 55 | // was the first filter for that event in that extension. |
| 56 | bool AddFilter(const std::string& event_name, |
| 57 | const ExtensionId& extension_id, |
| 58 | const base::DictionaryValue& filter); |
| 59 | // Removes a filter from |event_name| in |extension_id|, returning true if it |
| 60 | // was the last filter for that event in that extension. |
| 61 | bool RemoveFilter(const std::string& event_name, |
| 62 | const ExtensionId& extension_id, |
| 63 | base::DictionaryValue* filter); |
| 64 | |
| 65 | // Returns true if there is an event (managed or unmanaged) with the given |
| 66 | // context and event name. |
| 67 | bool HasListener(ScriptContext* script_context, |
| 68 | const std::string& event_name); |
| 69 | |
| 70 | void AddUnmanagedEvent(ScriptContext* context, const std::string& event_name); |
| 71 | void RemoveUnmanagedEvent(ScriptContext* context, |
| 72 | const std::string& event_name); |
| 73 | void RemoveAllUnmanagedListeners(ScriptContext* context); |
| 74 | |
| 75 | private: |
| 76 | using EventName = std::string; |
| 77 | |
| 78 | // A map of event name to the number of contexts listening to that event. |
| 79 | using EventListenerCounts = std::map<EventName, int>; |
| 80 | // Maps context id -> (map of event name -> listener count). |
| 81 | using AllCounts = std::map<std::string, EventListenerCounts>; |
| 82 | |
| 83 | using FilteredEventListenerKey = std::pair<ExtensionId, EventName>; |
| 84 | // A map of <extension id, event name> pair to listener counts. |
| 85 | using FilteredEventListenerCounts = |
| 86 | std::map<FilteredEventListenerKey, std::unique_ptr<ValueCounter>>; |
| 87 | |
| 88 | // A map of context to name of events the context has. |
| 89 | using UnmanagedListenerMap = std::map<ScriptContext*, std::set<std::string>>; |
| 90 | |
| 91 | // Used to notify the browser about event listeners when we transition between |
| 92 | // 0 and 1. |
| 93 | AllCounts listener_counts_; |
| 94 | |
| 95 | // The event filter. |
| 96 | EventFilter event_filter_; |
| 97 | |
| 98 | // A map of (extension ID, event name) pairs to the filtered listener counts |
| 99 | // for that pair. The map is used to keep track of which filters are in effect |
| 100 | // for which events. Used to notify the browser about filtered event |
| 101 | // listeners when we transition between 0 and 1. |
| 102 | FilteredEventListenerCounts filtered_listener_counts_; |
| 103 | |
| 104 | // A collection of the unmanaged events (i.e., those for which the browser is |
| 105 | // not notified of changes) that have listeners, by context. |
| 106 | UnmanagedListenerMap unmanaged_listeners_; |
| 107 | |
| 108 | DISALLOW_COPY_AND_ASSIGN(EventBookkeeper); |
| 109 | }; |
| 110 | |
| 111 | } // namespace extensions |
| 112 | |
| 113 | #endif // EXTENSIONS_RENDERER_EVENT_BOOKKEEPER_H_ |