OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 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 | 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_listeners.h" | 5 #include "extensions/renderer/bindings/api_event_listeners.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <memory> | 8 #include <memory> |
9 | 9 |
10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 } | 72 } |
73 | 73 |
74 *filter_dict = base::DictionaryValue::From(std::move(value)); | 74 *filter_dict = base::DictionaryValue::From(std::move(value)); |
75 return true; | 75 return true; |
76 } | 76 } |
77 | 77 |
78 } // namespace | 78 } // namespace |
79 | 79 |
80 UnfilteredEventListeners::UnfilteredEventListeners( | 80 UnfilteredEventListeners::UnfilteredEventListeners( |
81 const ListenersUpdated& listeners_updated, | 81 const ListenersUpdated& listeners_updated, |
82 int max_listeners) | 82 int max_listeners, |
83 : listeners_updated_(listeners_updated), max_listeners_(max_listeners) { | 83 bool supports_lazy_listeners) |
| 84 : listeners_updated_(listeners_updated), |
| 85 max_listeners_(max_listeners), |
| 86 supports_lazy_listeners_(supports_lazy_listeners) { |
84 DCHECK(max_listeners_ == binding::kNoListenerMax || max_listeners_ > 0); | 87 DCHECK(max_listeners_ == binding::kNoListenerMax || max_listeners_ > 0); |
85 } | 88 } |
86 UnfilteredEventListeners::~UnfilteredEventListeners() = default; | 89 UnfilteredEventListeners::~UnfilteredEventListeners() = default; |
87 | 90 |
88 bool UnfilteredEventListeners::AddListener(v8::Local<v8::Function> listener, | 91 bool UnfilteredEventListeners::AddListener(v8::Local<v8::Function> listener, |
89 v8::Local<v8::Object> filter, | 92 v8::Local<v8::Object> filter, |
90 v8::Local<v8::Context> context, | 93 v8::Local<v8::Context> context, |
91 std::string* error) { | 94 std::string* error) { |
92 // |filter| should be checked before getting here. | 95 // |filter| should be checked before getting here. |
93 DCHECK(filter.IsEmpty()) | 96 DCHECK(filter.IsEmpty()) |
94 << "Filtered events should use FilteredEventListeners"; | 97 << "Filtered events should use FilteredEventListeners"; |
95 | 98 |
96 if (HasListener(listener)) | 99 if (HasListener(listener)) |
97 return false; | 100 return false; |
98 | 101 |
99 if (max_listeners_ != binding::kNoListenerMax && | 102 if (max_listeners_ != binding::kNoListenerMax && |
100 listeners_.size() >= static_cast<size_t>(max_listeners_)) { | 103 listeners_.size() >= static_cast<size_t>(max_listeners_)) { |
101 *error = kErrorTooManyListeners; | 104 *error = kErrorTooManyListeners; |
102 return false; | 105 return false; |
103 } | 106 } |
104 | 107 |
105 listeners_.push_back( | 108 listeners_.push_back( |
106 v8::Global<v8::Function>(context->GetIsolate(), listener)); | 109 v8::Global<v8::Function>(context->GetIsolate(), listener)); |
107 if (listeners_.size() == 1) { | 110 if (listeners_.size() == 1) { |
108 listeners_updated_.Run(binding::EventListenersChanged::HAS_LISTENERS, | 111 listeners_updated_.Run(binding::EventListenersChanged::HAS_LISTENERS, |
109 nullptr, true, context); | 112 nullptr, supports_lazy_listeners_, context); |
110 } | 113 } |
111 | 114 |
112 return true; | 115 return true; |
113 } | 116 } |
114 | 117 |
115 void UnfilteredEventListeners::RemoveListener(v8::Local<v8::Function> listener, | 118 void UnfilteredEventListeners::RemoveListener(v8::Local<v8::Function> listener, |
116 v8::Local<v8::Context> context) { | 119 v8::Local<v8::Context> context) { |
117 auto iter = std::find(listeners_.begin(), listeners_.end(), listener); | 120 auto iter = std::find(listeners_.begin(), listeners_.end(), listener); |
118 if (iter == listeners_.end()) | 121 if (iter == listeners_.end()) |
119 return; | 122 return; |
120 | 123 |
121 listeners_.erase(iter); | 124 listeners_.erase(iter); |
122 if (listeners_.empty()) { | 125 if (listeners_.empty()) { |
123 listeners_updated_.Run(binding::EventListenersChanged::NO_LISTENERS, | 126 listeners_updated_.Run(binding::EventListenersChanged::NO_LISTENERS, |
124 nullptr, true, context); | 127 nullptr, supports_lazy_listeners_, context); |
125 } | 128 } |
126 } | 129 } |
127 | 130 |
128 bool UnfilteredEventListeners::HasListener(v8::Local<v8::Function> listener) { | 131 bool UnfilteredEventListeners::HasListener(v8::Local<v8::Function> listener) { |
129 return std::find(listeners_.begin(), listeners_.end(), listener) != | 132 return std::find(listeners_.begin(), listeners_.end(), listener) != |
130 listeners_.end(); | 133 listeners_.end(); |
131 } | 134 } |
132 | 135 |
133 size_t UnfilteredEventListeners::GetNumListeners() { | 136 size_t UnfilteredEventListeners::GetNumListeners() { |
134 return listeners_.size(); | 137 return listeners_.size(); |
135 } | 138 } |
136 | 139 |
137 std::vector<v8::Local<v8::Function>> UnfilteredEventListeners::GetListeners( | 140 std::vector<v8::Local<v8::Function>> UnfilteredEventListeners::GetListeners( |
138 const EventFilteringInfo* filter, | 141 const EventFilteringInfo* filter, |
139 v8::Local<v8::Context> context) { | 142 v8::Local<v8::Context> context) { |
140 std::vector<v8::Local<v8::Function>> listeners; | 143 std::vector<v8::Local<v8::Function>> listeners; |
141 listeners.reserve(listeners_.size()); | 144 listeners.reserve(listeners_.size()); |
142 for (const auto& listener : listeners_) | 145 for (const auto& listener : listeners_) |
143 listeners.push_back(listener.Get(context->GetIsolate())); | 146 listeners.push_back(listener.Get(context->GetIsolate())); |
144 return listeners; | 147 return listeners; |
145 } | 148 } |
146 | 149 |
147 void UnfilteredEventListeners::Invalidate(v8::Local<v8::Context> context) { | 150 void UnfilteredEventListeners::Invalidate(v8::Local<v8::Context> context) { |
148 if (!listeners_.empty()) { | 151 if (!listeners_.empty()) { |
149 listeners_.clear(); | 152 listeners_.clear(); |
| 153 // We don't want to update stored lazy listeners in this case, since the |
| 154 // extension didn't unregister interest in the event. |
| 155 bool update_lazy_listeners = false; |
150 listeners_updated_.Run(binding::EventListenersChanged::NO_LISTENERS, | 156 listeners_updated_.Run(binding::EventListenersChanged::NO_LISTENERS, |
151 nullptr, false, context); | 157 nullptr, update_lazy_listeners, context); |
152 } | 158 } |
153 } | 159 } |
154 | 160 |
155 struct FilteredEventListeners::ListenerData { | 161 struct FilteredEventListeners::ListenerData { |
156 bool operator==(v8::Local<v8::Function> other_function) const { | 162 bool operator==(v8::Local<v8::Function> other_function) const { |
157 // Note that we only consider the listener function here, and not the | 163 // Note that we only consider the listener function here, and not the |
158 // filter. This implies that it's invalid to try and add the same | 164 // filter. This implies that it's invalid to try and add the same |
159 // function for multiple filters. | 165 // function for multiple filters. |
160 // TODO(devlin): It's always been this way, but should it be? | 166 // TODO(devlin): It's always been this way, but should it be? |
161 return function == other_function; | 167 return function == other_function; |
162 } | 168 } |
163 | 169 |
164 v8::Global<v8::Function> function; | 170 v8::Global<v8::Function> function; |
165 int filter_id; | 171 int filter_id; |
166 }; | 172 }; |
167 | 173 |
168 FilteredEventListeners::FilteredEventListeners( | 174 FilteredEventListeners::FilteredEventListeners( |
169 const ListenersUpdated& listeners_updated, | 175 const ListenersUpdated& listeners_updated, |
170 const std::string& event_name, | 176 const std::string& event_name, |
171 int max_listeners, | 177 int max_listeners, |
| 178 bool supports_lazy_listeners, |
172 EventFilter* event_filter) | 179 EventFilter* event_filter) |
173 : listeners_updated_(listeners_updated), | 180 : listeners_updated_(listeners_updated), |
174 event_name_(event_name), | 181 event_name_(event_name), |
175 max_listeners_(max_listeners), | 182 max_listeners_(max_listeners), |
| 183 supports_lazy_listeners_(supports_lazy_listeners), |
176 event_filter_(event_filter) {} | 184 event_filter_(event_filter) {} |
177 FilteredEventListeners::~FilteredEventListeners() = default; | 185 FilteredEventListeners::~FilteredEventListeners() = default; |
178 | 186 |
179 bool FilteredEventListeners::AddListener(v8::Local<v8::Function> listener, | 187 bool FilteredEventListeners::AddListener(v8::Local<v8::Function> listener, |
180 v8::Local<v8::Object> filter, | 188 v8::Local<v8::Object> filter, |
181 v8::Local<v8::Context> context, | 189 v8::Local<v8::Context> context, |
182 std::string* error) { | 190 std::string* error) { |
183 if (HasListener(listener)) | 191 if (HasListener(listener)) |
184 return false; | 192 return false; |
185 | 193 |
(...skipping 15 matching lines...) Expand all Loading... |
201 *error = "Could not add listener"; | 209 *error = "Could not add listener"; |
202 return false; | 210 return false; |
203 } | 211 } |
204 | 212 |
205 const EventMatcher* matcher = event_filter_->GetEventMatcher(filter_id); | 213 const EventMatcher* matcher = event_filter_->GetEventMatcher(filter_id); |
206 DCHECK(matcher); | 214 DCHECK(matcher); |
207 listeners_.push_back( | 215 listeners_.push_back( |
208 {v8::Global<v8::Function>(context->GetIsolate(), listener), filter_id}); | 216 {v8::Global<v8::Function>(context->GetIsolate(), listener), filter_id}); |
209 if (value_counter_.Add(*matcher->value())) { | 217 if (value_counter_.Add(*matcher->value())) { |
210 listeners_updated_.Run(binding::EventListenersChanged::HAS_LISTENERS, | 218 listeners_updated_.Run(binding::EventListenersChanged::HAS_LISTENERS, |
211 matcher->value(), true, context); | 219 matcher->value(), supports_lazy_listeners_, context); |
212 } | 220 } |
213 | 221 |
214 return true; | 222 return true; |
215 } | 223 } |
216 | 224 |
217 void FilteredEventListeners::RemoveListener(v8::Local<v8::Function> listener, | 225 void FilteredEventListeners::RemoveListener(v8::Local<v8::Function> listener, |
218 v8::Local<v8::Context> context) { | 226 v8::Local<v8::Context> context) { |
219 auto iter = std::find(listeners_.begin(), listeners_.end(), listener); | 227 auto iter = std::find(listeners_.begin(), listeners_.end(), listener); |
220 if (iter == listeners_.end()) | 228 if (iter == listeners_.end()) |
221 return; | 229 return; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 } | 265 } |
258 | 266 |
259 void FilteredEventListeners::InvalidateListener( | 267 void FilteredEventListeners::InvalidateListener( |
260 const ListenerData& listener, | 268 const ListenerData& listener, |
261 bool was_manual, | 269 bool was_manual, |
262 v8::Local<v8::Context> context) { | 270 v8::Local<v8::Context> context) { |
263 EventMatcher* matcher = event_filter_->GetEventMatcher(listener.filter_id); | 271 EventMatcher* matcher = event_filter_->GetEventMatcher(listener.filter_id); |
264 DCHECK(matcher); | 272 DCHECK(matcher); |
265 if (value_counter_.Remove(*matcher->value())) { | 273 if (value_counter_.Remove(*matcher->value())) { |
266 listeners_updated_.Run(binding::EventListenersChanged::NO_LISTENERS, | 274 listeners_updated_.Run(binding::EventListenersChanged::NO_LISTENERS, |
267 matcher->value(), was_manual, context); | 275 matcher->value(), |
| 276 was_manual && supports_lazy_listeners_, context); |
268 } | 277 } |
269 | 278 |
270 event_filter_->RemoveEventMatcher(listener.filter_id); | 279 event_filter_->RemoveEventMatcher(listener.filter_id); |
271 } | 280 } |
272 | 281 |
273 } // namespace extensions | 282 } // namespace extensions |
OLD | NEW |