Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(914)

Side by Side Diff: extensions/renderer/event_bindings.cc

Issue 2909673003: [Extensions Bindings] Request JS execution from messaging bindings (Closed)
Patch Set: . Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/event_bindings.h" 5 #include "extensions/renderer/event_bindings.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <map> 9 #include <map>
10 #include <memory> 10 #include <memory>
11 #include <utility> 11 #include <utility>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/lazy_instance.h" 14 #include "base/lazy_instance.h"
15 #include "base/memory/ptr_util.h" 15 #include "base/memory/ptr_util.h"
16 #include "components/crx_file/id_util.h" 16 #include "components/crx_file/id_util.h"
17 #include "content/public/child/v8_value_converter.h" 17 #include "content/public/child/v8_value_converter.h"
18 #include "content/public/renderer/render_frame.h" 18 #include "content/public/renderer/render_frame.h"
19 #include "content/public/renderer/render_thread.h" 19 #include "content/public/renderer/render_thread.h"
20 #include "content/public/renderer/render_view.h" 20 #include "content/public/renderer/render_view.h"
21 #include "extensions/common/event_filter.h" 21 #include "extensions/common/event_filter.h"
22 #include "extensions/common/extension.h" 22 #include "extensions/common/extension.h"
23 #include "extensions/common/extension_messages.h" 23 #include "extensions/common/extension_messages.h"
24 #include "extensions/common/value_counter.h" 24 #include "extensions/common/value_counter.h"
25 #include "extensions/renderer/extension_frame_helper.h" 25 #include "extensions/renderer/extension_frame_helper.h"
26 #include "extensions/renderer/script_context.h" 26 #include "extensions/renderer/script_context.h"
27 #include "gin/converter.h"
27 #include "url/gurl.h" 28 #include "url/gurl.h"
28 29
29 namespace extensions { 30 namespace extensions {
30 31
31 namespace { 32 namespace {
32 33
33 // A map of event names to the number of contexts listening to that event. 34 // A map of event names to the number of contexts listening to that event.
34 // We notify the browser about event listeners when we transition between 0 35 // We notify the browser about event listeners when we transition between 0
35 // and 1. 36 // and 1.
36 typedef std::map<std::string, int> EventListenerCounts; 37 typedef std::map<std::string, int> EventListenerCounts;
37 38
38 // A map of extension IDs to listener counts for that extension. 39 // A map of extension IDs to listener counts for that extension.
39 base::LazyInstance<std::map<std::string, EventListenerCounts>>::DestructorAtExit 40 base::LazyInstance<std::map<std::string, EventListenerCounts>>::DestructorAtExit
40 g_listener_counts = LAZY_INSTANCE_INITIALIZER; 41 g_listener_counts = LAZY_INSTANCE_INITIALIZER;
41 42
43 // A collection of the unmanaged events (i.e., those for which the browser is
44 // not notified of changes) that have listeners, by context.
45 base::LazyInstance<std::map<ScriptContext*, std::set<std::string>>>::Leaky
46 g_unmanaged_listeners = LAZY_INSTANCE_INITIALIZER;
47
42 // A map of (extension ID, event name) pairs to the filtered listener counts 48 // A map of (extension ID, event name) pairs to the filtered listener counts
43 // for that pair. The map is used to keep track of which filters are in effect 49 // for that pair. The map is used to keep track of which filters are in effect
44 // for which events. We notify the browser about filtered event listeners when 50 // for which events. We notify the browser about filtered event listeners when
45 // we transition between 0 and 1. 51 // we transition between 0 and 1.
46 using FilteredEventListenerKey = std::pair<std::string, std::string>; 52 using FilteredEventListenerKey = std::pair<std::string, std::string>;
47 using FilteredEventListenerCounts = 53 using FilteredEventListenerCounts =
48 std::map<FilteredEventListenerKey, std::unique_ptr<ValueCounter>>; 54 std::map<FilteredEventListenerKey, std::unique_ptr<ValueCounter>>;
49 base::LazyInstance<FilteredEventListenerCounts>::DestructorAtExit 55 base::LazyInstance<FilteredEventListenerCounts>::DestructorAtExit
50 g_filtered_listener_counts = LAZY_INSTANCE_INITIALIZER; 56 g_filtered_listener_counts = LAZY_INSTANCE_INITIALIZER;
51 57
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 base::Unretained(this))); 170 base::Unretained(this)));
165 RouteFunction( 171 RouteFunction(
166 "AttachFilteredEvent", 172 "AttachFilteredEvent",
167 base::Bind(&EventBindings::AttachFilteredEvent, base::Unretained(this))); 173 base::Bind(&EventBindings::AttachFilteredEvent, base::Unretained(this)));
168 RouteFunction("DetachFilteredEvent", 174 RouteFunction("DetachFilteredEvent",
169 base::Bind(&EventBindings::DetachFilteredEventHandler, 175 base::Bind(&EventBindings::DetachFilteredEventHandler,
170 base::Unretained(this))); 176 base::Unretained(this)));
171 RouteFunction("MatchAgainstEventFilter", 177 RouteFunction("MatchAgainstEventFilter",
172 base::Bind(&EventBindings::MatchAgainstEventFilter, 178 base::Bind(&EventBindings::MatchAgainstEventFilter,
173 base::Unretained(this))); 179 base::Unretained(this)));
180 RouteFunction(
181 "AttachUnmanagedEvent",
182 base::Bind(&EventBindings::AttachUnmanagedEvent, base::Unretained(this)));
183 RouteFunction(
184 "DetachUnmanagedEvent",
185 base::Bind(&EventBindings::DetachUnmanagedEvent, base::Unretained(this)));
174 186
175 // It's safe to use base::Unretained here because |context| will always 187 // It's safe to use base::Unretained here because |context| will always
176 // outlive us. 188 // outlive us.
177 context->AddInvalidationObserver( 189 context->AddInvalidationObserver(
178 base::Bind(&EventBindings::OnInvalidated, base::Unretained(this))); 190 base::Bind(&EventBindings::OnInvalidated, base::Unretained(this)));
179 } 191 }
180 192
181 EventBindings::~EventBindings() {} 193 EventBindings::~EventBindings() {}
182 194
195 bool EventBindings::HasListener(ScriptContext* script_context,
196 const std::string& event_name) {
197 auto& unmanaged_listeners = g_unmanaged_listeners.Get();
lazyboy 2017/06/05 18:18:32 const auto& here and in line 203?
Devlin 2017/06/09 20:18:02 Done.
198 auto unmanaged_iter = unmanaged_listeners.find(script_context);
199 if (unmanaged_iter != unmanaged_listeners.end() &&
200 base::ContainsKey(unmanaged_iter->second, event_name)) {
201 return true;
202 }
203 auto& managed_listeners = g_listener_counts.Get();
204 auto managed_iter =
205 managed_listeners.find(GetKeyForScriptContext(script_context));
206 if (managed_iter != managed_listeners.end()) {
207 auto event_iter = managed_iter->second.find(event_name);
208 if (event_iter != managed_iter->second.end() && event_iter->second > 0) {
209 return true;
210 }
211 }
212
213 return false;
214 }
215
183 void EventBindings::AttachEventHandler( 216 void EventBindings::AttachEventHandler(
184 const v8::FunctionCallbackInfo<v8::Value>& args) { 217 const v8::FunctionCallbackInfo<v8::Value>& args) {
185 CHECK_EQ(1, args.Length()); 218 CHECK_EQ(1, args.Length());
186 CHECK(args[0]->IsString()); 219 CHECK(args[0]->IsString());
187 AttachEvent(*v8::String::Utf8Value(args[0])); 220 AttachEvent(*v8::String::Utf8Value(args[0]));
188 } 221 }
189 222
190 void EventBindings::AttachEvent(const std::string& event_name) { 223 void EventBindings::AttachEvent(const std::string& event_name) {
191 if (!context()->HasAccessOrThrowError(event_name)) 224 if (!context()->HasAccessOrThrowError(event_name))
192 return; 225 return;
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 v8::Array::New(isolate, matched_event_filters.size())); 371 v8::Array::New(isolate, matched_event_filters.size()));
339 int i = 0; 372 int i = 0;
340 for (MatcherIDs::iterator it = matched_event_filters.begin(); 373 for (MatcherIDs::iterator it = matched_event_filters.begin();
341 it != matched_event_filters.end(); 374 it != matched_event_filters.end();
342 ++it) { 375 ++it) {
343 array->Set(v8::Integer::New(isolate, i++), v8::Integer::New(isolate, *it)); 376 array->Set(v8::Integer::New(isolate, i++), v8::Integer::New(isolate, *it));
344 } 377 }
345 args.GetReturnValue().Set(array); 378 args.GetReturnValue().Set(array);
346 } 379 }
347 380
381 void EventBindings::AttachUnmanagedEvent(
382 const v8::FunctionCallbackInfo<v8::Value>& args) {
383 v8::Isolate* isolate = args.GetIsolate();
384 v8::HandleScope handle_scope(isolate);
385 CHECK_EQ(1, args.Length());
386 CHECK(args[0]->IsString());
387 std::string event_name = gin::V8ToString(args[0]);
388 g_unmanaged_listeners.Get()[context()].insert(event_name);
389 }
390
391 void EventBindings::DetachUnmanagedEvent(
392 const v8::FunctionCallbackInfo<v8::Value>& args) {
393 v8::Isolate* isolate = args.GetIsolate();
394 v8::HandleScope handle_scope(isolate);
395 CHECK_EQ(1, args.Length());
396 CHECK(args[0]->IsString());
397 std::string event_name = gin::V8ToString(args[0]);
398 g_unmanaged_listeners.Get()[context()].erase(event_name);
399 }
400
348 std::unique_ptr<EventMatcher> EventBindings::ParseEventMatcher( 401 std::unique_ptr<EventMatcher> EventBindings::ParseEventMatcher(
349 std::unique_ptr<base::DictionaryValue> filter) { 402 std::unique_ptr<base::DictionaryValue> filter) {
350 return base::MakeUnique<EventMatcher>( 403 return base::MakeUnique<EventMatcher>(
351 std::move(filter), context()->GetRenderFrame()->GetRoutingID()); 404 std::move(filter), context()->GetRenderFrame()->GetRoutingID());
352 } 405 }
353 406
354 void EventBindings::OnInvalidated() { 407 void EventBindings::OnInvalidated() {
355 // Detach all attached events that weren't attached. Iterate over a copy 408 // Detach all attached events that weren't attached. Iterate over a copy
356 // because it will be mutated. 409 // because it will be mutated.
357 std::set<std::string> attached_event_names_safe = attached_event_names_; 410 std::set<std::string> attached_event_names_safe = attached_event_names_;
358 for (const std::string& event_name : attached_event_names_safe) { 411 for (const std::string& event_name : attached_event_names_safe) {
359 DetachEvent(event_name, false /* is_manual */); 412 DetachEvent(event_name, false /* is_manual */);
360 } 413 }
361 DCHECK(attached_event_names_.empty()) 414 DCHECK(attached_event_names_.empty())
362 << "Events cannot be attached during invalidation"; 415 << "Events cannot be attached during invalidation";
363 416
364 // Same for filtered events. 417 // Same for filtered events.
365 std::set<int> attached_matcher_ids_safe = attached_matcher_ids_; 418 std::set<int> attached_matcher_ids_safe = attached_matcher_ids_;
366 for (int matcher_id : attached_matcher_ids_safe) { 419 for (int matcher_id : attached_matcher_ids_safe) {
367 DetachFilteredEvent(matcher_id, false /* is_manual */); 420 DetachFilteredEvent(matcher_id, false /* is_manual */);
368 } 421 }
369 DCHECK(attached_matcher_ids_.empty()) 422 DCHECK(attached_matcher_ids_.empty())
370 << "Filtered events cannot be attached during invalidation"; 423 << "Filtered events cannot be attached during invalidation";
424
425 g_unmanaged_listeners.Get().erase(context());
371 } 426 }
372 427
373 } // namespace extensions 428 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698