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

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

Issue 2924683002: [Extensions Bindings] Avoid passing the event filter to JS (Closed)
Patch Set: rebase Created 3 years, 6 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/constants.h" 21 #include "extensions/common/constants.h"
22 #include "extensions/common/event_filter.h" 22 #include "extensions/common/event_filter.h"
23 #include "extensions/common/extension.h" 23 #include "extensions/common/extension.h"
24 #include "extensions/common/extension_messages.h" 24 #include "extensions/common/extension_messages.h"
25 #include "extensions/common/extension_urls.h"
25 #include "extensions/common/value_counter.h" 26 #include "extensions/common/value_counter.h"
26 #include "extensions/renderer/extension_frame_helper.h" 27 #include "extensions/renderer/extension_frame_helper.h"
27 #include "extensions/renderer/script_context.h" 28 #include "extensions/renderer/script_context.h"
28 #include "extensions/renderer/service_worker_request_sender.h" 29 #include "extensions/renderer/service_worker_request_sender.h"
29 #include "extensions/renderer/worker_thread_dispatcher.h" 30 #include "extensions/renderer/worker_thread_dispatcher.h"
30 #include "gin/converter.h" 31 #include "gin/converter.h"
31 #include "url/gurl.h" 32 #include "url/gurl.h"
32 33
33 namespace extensions { 34 namespace extensions {
34 35
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 } 82 }
82 83
83 // Decrements the number of event-listeners for the given |event_name| and 84 // Decrements the number of event-listeners for the given |event_name| and
84 // ScriptContext. Returns the count after the increment. 85 // ScriptContext. Returns the count after the increment.
85 int DecrementEventListenerCount(ScriptContext* script_context, 86 int DecrementEventListenerCount(ScriptContext* script_context,
86 const std::string& event_name) { 87 const std::string& event_name) {
87 return --g_listener_counts 88 return --g_listener_counts
88 .Get()[GetKeyForScriptContext(script_context)][event_name]; 89 .Get()[GetKeyForScriptContext(script_context)][event_name];
89 } 90 }
90 91
91 EventFilteringInfo ParseFromObject(v8::Local<v8::Object> object,
92 v8::Isolate* isolate) {
93 EventFilteringInfo info;
94 v8::Local<v8::String> url(v8::String::NewFromUtf8(isolate, "url"));
95 if (object->Has(url)) {
96 v8::Local<v8::Value> url_value(object->Get(url));
97 info.SetURL(GURL(*v8::String::Utf8Value(url_value)));
98 }
99 v8::Local<v8::String> instance_id(
100 v8::String::NewFromUtf8(isolate, "instanceId"));
101 if (object->Has(instance_id)) {
102 v8::Local<v8::Value> instance_id_value(object->Get(instance_id));
103 info.SetInstanceID(instance_id_value->IntegerValue());
104 }
105 v8::Local<v8::String> service_type(
106 v8::String::NewFromUtf8(isolate, "serviceType"));
107 if (object->Has(service_type)) {
108 v8::Local<v8::Value> service_type_value(object->Get(service_type));
109 info.SetServiceType(*v8::String::Utf8Value(service_type_value));
110 }
111 v8::Local<v8::String> window_types(
112 v8::String::NewFromUtf8(isolate, "windowType"));
113 if (object->Has(window_types)) {
114 v8::Local<v8::Value> window_types_value(object->Get(window_types));
115 info.SetWindowType(*v8::String::Utf8Value(window_types_value));
116 }
117
118 v8::Local<v8::String> window_exposed(
119 v8::String::NewFromUtf8(isolate, "windowExposedByDefault"));
120 if (object->Has(window_exposed)) {
121 v8::Local<v8::Value> window_exposed_value(object->Get(window_exposed));
122 info.SetWindowExposedByDefault(
123 window_exposed_value.As<v8::Boolean>()->Value());
124 }
125
126 return info;
127 }
128
129 // Add a filter to |event_name| in |extension_id|, returning true if it 92 // Add a filter to |event_name| in |extension_id|, returning true if it
130 // was the first filter for that event in that extension. 93 // was the first filter for that event in that extension.
131 bool AddFilter(const std::string& event_name, 94 bool AddFilter(const std::string& event_name,
132 const std::string& extension_id, 95 const std::string& extension_id,
133 const base::DictionaryValue& filter) { 96 const base::DictionaryValue& filter) {
134 FilteredEventListenerKey key(extension_id, event_name); 97 FilteredEventListenerKey key(extension_id, event_name);
135 FilteredEventListenerCounts& all_counts = g_filtered_listener_counts.Get(); 98 FilteredEventListenerCounts& all_counts = g_filtered_listener_counts.Get();
136 FilteredEventListenerCounts::const_iterator counts = all_counts.find(key); 99 FilteredEventListenerCounts::const_iterator counts = all_counts.find(key);
137 if (counts == all_counts.end()) { 100 if (counts == all_counts.end()) {
138 counts = 101 counts =
(...skipping 17 matching lines...) Expand all
156 // |filter|. If there are more equivalent filters, or if there weren't any in 119 // |filter|. If there are more equivalent filters, or if there weren't any in
157 // the first place, it returns false. 120 // the first place, it returns false.
158 if (counts->second->Remove(*filter)) { 121 if (counts->second->Remove(*filter)) {
159 if (counts->second->is_empty()) 122 if (counts->second->is_empty())
160 all_counts.erase(counts); // Clean up if there are no more filters. 123 all_counts.erase(counts); // Clean up if there are no more filters.
161 return true; 124 return true;
162 } 125 }
163 return false; 126 return false;
164 } 127 }
165 128
129 // Returns a v8::Array containing the ids of the listeners that match the given
130 // |event_filter_dict| in the given |script_context|.
131 v8::Local<v8::Array> GetMatchingListeners(
132 ScriptContext* script_context,
133 const std::string& event_name,
134 const base::DictionaryValue& event_filter_dict) {
135 const EventFilter& event_filter = g_event_filter.Get();
136 EventFilteringInfo info(event_filter_dict);
137 v8::Isolate* isolate = script_context->isolate();
138 v8::Local<v8::Context> context = script_context->v8_context();
139
140 // Only match events routed to this context's RenderFrame or ones that don't
141 // have a routingId in their filter.
142 std::set<EventFilter::MatcherID> matched_event_filters =
143 event_filter.MatchEvent(event_name, info,
144 script_context->GetRenderFrame()->GetRoutingID());
145 v8::Local<v8::Array> array(
146 v8::Array::New(isolate, matched_event_filters.size()));
147 int i = 0;
148 for (EventFilter::MatcherID id : matched_event_filters) {
149 CHECK(array->CreateDataProperty(context, i++, v8::Integer::New(isolate, id))
150 .ToChecked());
151 }
152
153 return array;
154 }
155
166 } // namespace 156 } // namespace
167 157
168 EventBindings::EventBindings(ScriptContext* context) 158 EventBindings::EventBindings(ScriptContext* context)
169 : ObjectBackedNativeHandler(context) { 159 : ObjectBackedNativeHandler(context) {
170 RouteFunction("AttachEvent", base::Bind(&EventBindings::AttachEventHandler, 160 RouteFunction("AttachEvent", base::Bind(&EventBindings::AttachEventHandler,
171 base::Unretained(this))); 161 base::Unretained(this)));
172 RouteFunction("DetachEvent", base::Bind(&EventBindings::DetachEventHandler, 162 RouteFunction("DetachEvent", base::Bind(&EventBindings::DetachEventHandler,
173 base::Unretained(this))); 163 base::Unretained(this)));
174 RouteFunction( 164 RouteFunction(
175 "AttachFilteredEvent", 165 "AttachFilteredEvent",
176 base::Bind(&EventBindings::AttachFilteredEvent, base::Unretained(this))); 166 base::Bind(&EventBindings::AttachFilteredEvent, base::Unretained(this)));
177 RouteFunction("DetachFilteredEvent", 167 RouteFunction("DetachFilteredEvent",
178 base::Bind(&EventBindings::DetachFilteredEventHandler, 168 base::Bind(&EventBindings::DetachFilteredEventHandler,
179 base::Unretained(this))); 169 base::Unretained(this)));
180 RouteFunction("MatchAgainstEventFilter",
181 base::Bind(&EventBindings::MatchAgainstEventFilter,
182 base::Unretained(this)));
183 RouteFunction( 170 RouteFunction(
184 "AttachUnmanagedEvent", 171 "AttachUnmanagedEvent",
185 base::Bind(&EventBindings::AttachUnmanagedEvent, base::Unretained(this))); 172 base::Bind(&EventBindings::AttachUnmanagedEvent, base::Unretained(this)));
186 RouteFunction( 173 RouteFunction(
187 "DetachUnmanagedEvent", 174 "DetachUnmanagedEvent",
188 base::Bind(&EventBindings::DetachUnmanagedEvent, base::Unretained(this))); 175 base::Bind(&EventBindings::DetachUnmanagedEvent, base::Unretained(this)));
189 176
190 // It's safe to use base::Unretained here because |context| will always 177 // It's safe to use base::Unretained here because |context| will always
191 // outlive us. 178 // outlive us.
192 context->AddInvalidationObserver( 179 context->AddInvalidationObserver(
(...skipping 16 matching lines...) Expand all
209 if (managed_iter != managed_listeners.end()) { 196 if (managed_iter != managed_listeners.end()) {
210 auto event_iter = managed_iter->second.find(event_name); 197 auto event_iter = managed_iter->second.find(event_name);
211 if (event_iter != managed_iter->second.end() && event_iter->second > 0) { 198 if (event_iter != managed_iter->second.end() && event_iter->second > 0) {
212 return true; 199 return true;
213 } 200 }
214 } 201 }
215 202
216 return false; 203 return false;
217 } 204 }
218 205
206 // static
207 void EventBindings::DispatchEventInContext(
208 const std::string& event_name,
209 const base::ListValue* event_args,
210 const base::DictionaryValue* filtering_info,
211 ScriptContext* context) {
212 v8::HandleScope handle_scope(context->isolate());
213 v8::Context::Scope context_scope(context->v8_context());
214
215 v8::Local<v8::Array> listener_ids;
216 if (filtering_info && !filtering_info->empty())
217 listener_ids = GetMatchingListeners(context, event_name, *filtering_info);
218 else
219 listener_ids = v8::Array::New(context->isolate());
220
221 std::unique_ptr<content::V8ValueConverter> converter(
222 content::V8ValueConverter::create());
223 v8::Local<v8::Value> v8_args[] = {
224 gin::StringToSymbol(context->isolate(), event_name),
225 converter->ToV8Value(event_args, context->v8_context()), listener_ids,
226 };
227
228 context->module_system()->CallModuleMethodSafe(
229 kEventBindings, "dispatchEvent", arraysize(v8_args), v8_args);
230 }
231
219 void EventBindings::AttachEventHandler( 232 void EventBindings::AttachEventHandler(
220 const v8::FunctionCallbackInfo<v8::Value>& args) { 233 const v8::FunctionCallbackInfo<v8::Value>& args) {
221 CHECK_EQ(1, args.Length()); 234 CHECK_EQ(1, args.Length());
222 CHECK(args[0]->IsString()); 235 CHECK(args[0]->IsString());
223 AttachEvent(*v8::String::Utf8Value(args[0])); 236 AttachEvent(*v8::String::Utf8Value(args[0]));
224 } 237 }
225 238
226 void EventBindings::AttachEvent(const std::string& event_name) { 239 void EventBindings::AttachEvent(const std::string& event_name) {
227 if (!context()->HasAccessOrThrowError(event_name)) 240 if (!context()->HasAccessOrThrowError(event_name))
228 return; 241 return;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 if (is_lazy_context) { 301 if (is_lazy_context) {
289 sender->Send(new ExtensionHostMsg_RemoveLazyListener( 302 sender->Send(new ExtensionHostMsg_RemoveLazyListener(
290 extension_id, event_name, worker_thread_id)); 303 extension_id, event_name, worker_thread_id));
291 } 304 }
292 } 305 }
293 } 306 }
294 307
295 // MatcherID AttachFilteredEvent(string event_name, object filter) 308 // MatcherID AttachFilteredEvent(string event_name, object filter)
296 // event_name - Name of the event to attach. 309 // event_name - Name of the event to attach.
297 // filter - Which instances of the named event are we interested in. 310 // filter - Which instances of the named event are we interested in.
298 // returns the id assigned to the listener, which will be returned from calls 311 // returns the id assigned to the listener, which will be provided to calls to
299 // to MatchAgainstEventFilter where this listener matches. 312 // dispatchEvent().
300 void EventBindings::AttachFilteredEvent( 313 void EventBindings::AttachFilteredEvent(
301 const v8::FunctionCallbackInfo<v8::Value>& args) { 314 const v8::FunctionCallbackInfo<v8::Value>& args) {
302 CHECK_EQ(2, args.Length()); 315 CHECK_EQ(2, args.Length());
303 CHECK(args[0]->IsString()); 316 CHECK(args[0]->IsString());
304 CHECK(args[1]->IsObject()); 317 CHECK(args[1]->IsObject());
305 318
306 std::string event_name = *v8::String::Utf8Value(args[0]); 319 std::string event_name = *v8::String::Utf8Value(args[0]);
307 if (!context()->HasAccessOrThrowError(event_name)) 320 if (!context()->HasAccessOrThrowError(event_name))
308 return; 321 return;
309 322
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 is_manual && ExtensionFrameHelper::IsContextForEventPage(context()); 376 is_manual && ExtensionFrameHelper::IsContextForEventPage(context());
364 content::RenderThread::Get()->Send( 377 content::RenderThread::Get()->Send(
365 new ExtensionHostMsg_RemoveFilteredListener( 378 new ExtensionHostMsg_RemoveFilteredListener(
366 extension_id, event_name, *event_matcher->value(), remove_lazy)); 379 extension_id, event_name, *event_matcher->value(), remove_lazy));
367 } 380 }
368 381
369 event_filter.RemoveEventMatcher(matcher_id); 382 event_filter.RemoveEventMatcher(matcher_id);
370 attached_matcher_ids_.erase(matcher_id); 383 attached_matcher_ids_.erase(matcher_id);
371 } 384 }
372 385
373 void EventBindings::MatchAgainstEventFilter(
374 const v8::FunctionCallbackInfo<v8::Value>& args) {
375 v8::Isolate* isolate = args.GetIsolate();
376 typedef std::set<EventFilter::MatcherID> MatcherIDs;
377 EventFilter& event_filter = g_event_filter.Get();
378 std::string event_name = *v8::String::Utf8Value(args[0]);
379 EventFilteringInfo info =
380 ParseFromObject(args[1]->ToObject(isolate), isolate);
381 // Only match events routed to this context's RenderFrame or ones that don't
382 // have a routingId in their filter.
383 MatcherIDs matched_event_filters = event_filter.MatchEvent(
384 event_name, info, context()->GetRenderFrame()->GetRoutingID());
385 v8::Local<v8::Array> array(
386 v8::Array::New(isolate, matched_event_filters.size()));
387 int i = 0;
388 for (MatcherIDs::iterator it = matched_event_filters.begin();
389 it != matched_event_filters.end();
390 ++it) {
391 array->Set(v8::Integer::New(isolate, i++), v8::Integer::New(isolate, *it));
392 }
393 args.GetReturnValue().Set(array);
394 }
395
396 void EventBindings::AttachUnmanagedEvent( 386 void EventBindings::AttachUnmanagedEvent(
397 const v8::FunctionCallbackInfo<v8::Value>& args) { 387 const v8::FunctionCallbackInfo<v8::Value>& args) {
398 v8::Isolate* isolate = args.GetIsolate(); 388 v8::Isolate* isolate = args.GetIsolate();
399 v8::HandleScope handle_scope(isolate); 389 v8::HandleScope handle_scope(isolate);
400 CHECK_EQ(1, args.Length()); 390 CHECK_EQ(1, args.Length());
401 CHECK(args[0]->IsString()); 391 CHECK(args[0]->IsString());
402 std::string event_name = gin::V8ToString(args[0]); 392 std::string event_name = gin::V8ToString(args[0]);
403 g_unmanaged_listeners.Get()[context()].insert(event_name); 393 g_unmanaged_listeners.Get()[context()].insert(event_name);
404 } 394 }
405 395
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 for (int matcher_id : attached_matcher_ids_safe) { 434 for (int matcher_id : attached_matcher_ids_safe) {
445 DetachFilteredEvent(matcher_id, false /* is_manual */); 435 DetachFilteredEvent(matcher_id, false /* is_manual */);
446 } 436 }
447 DCHECK(attached_matcher_ids_.empty()) 437 DCHECK(attached_matcher_ids_.empty())
448 << "Filtered events cannot be attached during invalidation"; 438 << "Filtered events cannot be attached during invalidation";
449 439
450 g_unmanaged_listeners.Get().erase(context()); 440 g_unmanaged_listeners.Get().erase(context());
451 } 441 }
452 442
453 } // namespace extensions 443 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/renderer/event_bindings.h ('k') | extensions/renderer/js_extension_bindings_system.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698