Chromium Code Reviews| Index: extensions/renderer/event_bindings.cc |
| diff --git a/extensions/renderer/event_bindings.cc b/extensions/renderer/event_bindings.cc |
| index 5e8d41ac33cb30772b39e0ae6163d92f6985ede5..ee398d2b28780fbd92dae5f90e06720abe068d7d 100644 |
| --- a/extensions/renderer/event_bindings.cc |
| +++ b/extensions/renderer/event_bindings.cc |
| @@ -24,6 +24,7 @@ |
| #include "extensions/common/value_counter.h" |
| #include "extensions/renderer/extension_frame_helper.h" |
| #include "extensions/renderer/script_context.h" |
| +#include "gin/converter.h" |
| #include "url/gurl.h" |
| namespace extensions { |
| @@ -39,6 +40,11 @@ typedef std::map<std::string, int> EventListenerCounts; |
| base::LazyInstance<std::map<std::string, EventListenerCounts>>::DestructorAtExit |
| g_listener_counts = LAZY_INSTANCE_INITIALIZER; |
| +// A collection of the unmanaged events (i.e., those for which the browser is |
| +// not notified of changes) that have listeners, by context. |
| +base::LazyInstance<std::map<ScriptContext*, std::set<std::string>>>::Leaky |
| + g_unmanaged_listeners = LAZY_INSTANCE_INITIALIZER; |
| + |
| // A map of (extension ID, event name) pairs to the filtered listener counts |
| // for that pair. The map is used to keep track of which filters are in effect |
| // for which events. We notify the browser about filtered event listeners when |
| @@ -171,6 +177,12 @@ EventBindings::EventBindings(ScriptContext* context) |
| RouteFunction("MatchAgainstEventFilter", |
| base::Bind(&EventBindings::MatchAgainstEventFilter, |
| base::Unretained(this))); |
| + RouteFunction( |
| + "AttachUnmanagedEvent", |
| + base::Bind(&EventBindings::AttachUnmanagedEvent, base::Unretained(this))); |
| + RouteFunction( |
| + "DetachUnmanagedEvent", |
| + base::Bind(&EventBindings::DetachUnmanagedEvent, base::Unretained(this))); |
| // It's safe to use base::Unretained here because |context| will always |
| // outlive us. |
| @@ -180,6 +192,27 @@ EventBindings::EventBindings(ScriptContext* context) |
| EventBindings::~EventBindings() {} |
| +bool EventBindings::HasListener(ScriptContext* script_context, |
| + const std::string& event_name) { |
| + 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.
|
| + auto unmanaged_iter = unmanaged_listeners.find(script_context); |
| + if (unmanaged_iter != unmanaged_listeners.end() && |
| + base::ContainsKey(unmanaged_iter->second, event_name)) { |
| + return true; |
| + } |
| + auto& managed_listeners = g_listener_counts.Get(); |
| + auto managed_iter = |
| + managed_listeners.find(GetKeyForScriptContext(script_context)); |
| + if (managed_iter != managed_listeners.end()) { |
| + auto event_iter = managed_iter->second.find(event_name); |
| + if (event_iter != managed_iter->second.end() && event_iter->second > 0) { |
| + return true; |
| + } |
| + } |
| + |
| + return false; |
| +} |
| + |
| void EventBindings::AttachEventHandler( |
| const v8::FunctionCallbackInfo<v8::Value>& args) { |
| CHECK_EQ(1, args.Length()); |
| @@ -345,6 +378,26 @@ void EventBindings::MatchAgainstEventFilter( |
| args.GetReturnValue().Set(array); |
| } |
| +void EventBindings::AttachUnmanagedEvent( |
| + const v8::FunctionCallbackInfo<v8::Value>& args) { |
| + v8::Isolate* isolate = args.GetIsolate(); |
| + v8::HandleScope handle_scope(isolate); |
| + CHECK_EQ(1, args.Length()); |
| + CHECK(args[0]->IsString()); |
| + std::string event_name = gin::V8ToString(args[0]); |
| + g_unmanaged_listeners.Get()[context()].insert(event_name); |
| +} |
| + |
| +void EventBindings::DetachUnmanagedEvent( |
| + const v8::FunctionCallbackInfo<v8::Value>& args) { |
| + v8::Isolate* isolate = args.GetIsolate(); |
| + v8::HandleScope handle_scope(isolate); |
| + CHECK_EQ(1, args.Length()); |
| + CHECK(args[0]->IsString()); |
| + std::string event_name = gin::V8ToString(args[0]); |
| + g_unmanaged_listeners.Get()[context()].erase(event_name); |
| +} |
| + |
| std::unique_ptr<EventMatcher> EventBindings::ParseEventMatcher( |
| std::unique_ptr<base::DictionaryValue> filter) { |
| return base::MakeUnique<EventMatcher>( |
| @@ -368,6 +421,8 @@ void EventBindings::OnInvalidated() { |
| } |
| DCHECK(attached_matcher_ids_.empty()) |
| << "Filtered events cannot be attached during invalidation"; |
| + |
| + g_unmanaged_listeners.Get().erase(context()); |
| } |
| } // namespace extensions |