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

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

Issue 10701134: Revert "Make EventBindings use static routed methods." (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/renderer/extensions/event_bindings.h" 5 #include "chrome/renderer/extensions/event_bindings.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 // track of which filters are in effect for which events. 57 // track of which filters are in effect for which events.
58 // We notify the browser about filtered event listeners when we transition 58 // We notify the browser about filtered event listeners when we transition
59 // between 0 and 1. 59 // between 0 and 1.
60 typedef std::map<std::string, linked_ptr<extensions::ValueCounter> > 60 typedef std::map<std::string, linked_ptr<extensions::ValueCounter> >
61 FilteredEventListenerCounts; 61 FilteredEventListenerCounts;
62 62
63 // A map of extension IDs to filtered listener counts for that extension. 63 // A map of extension IDs to filtered listener counts for that extension.
64 base::LazyInstance<std::map<std::string, FilteredEventListenerCounts> > 64 base::LazyInstance<std::map<std::string, FilteredEventListenerCounts> >
65 g_filtered_listener_counts = LAZY_INSTANCE_INITIALIZER; 65 g_filtered_listener_counts = LAZY_INSTANCE_INITIALIZER;
66 66
67 base::LazyInstance<extensions::EventFilter> g_event_filter =
68 LAZY_INSTANCE_INITIALIZER;
69
70 // TODO(koz): Merge this into EventBindings. 67 // TODO(koz): Merge this into EventBindings.
71 class ExtensionImpl : public ChromeV8Extension { 68 class ExtensionImpl : public ChromeV8Extension {
72 public: 69 public:
73 70
74 explicit ExtensionImpl(ExtensionDispatcher* dispatcher) 71 ExtensionImpl(ExtensionDispatcher* dispatcher,
75 : ChromeV8Extension(dispatcher) { 72 extensions::EventFilter* event_filter)
76 RouteStaticFunction("AttachEvent", &AttachEvent); 73 : ChromeV8Extension(dispatcher),
77 RouteStaticFunction("DetachEvent", &DetachEvent); 74 event_filter_(event_filter) {
78 RouteStaticFunction("AttachFilteredEvent", &AttachFilteredEvent); 75 RouteFunction("AttachEvent",
79 RouteStaticFunction("DetachFilteredEvent", &DetachFilteredEvent); 76 base::Bind(&ExtensionImpl::AttachEvent,
80 RouteStaticFunction("MatchAgainstEventFilter", &MatchAgainstEventFilter); 77 base::Unretained(this)));
78 RouteFunction("DetachEvent",
79 base::Bind(&ExtensionImpl::DetachEvent,
80 base::Unretained(this)));
81 RouteFunction("AttachFilteredEvent",
82 base::Bind(&ExtensionImpl::AttachFilteredEvent,
83 base::Unretained(this)));
84 RouteFunction("DetachFilteredEvent",
85 base::Bind(&ExtensionImpl::DetachFilteredEvent,
86 base::Unretained(this)));
87 RouteFunction("MatchAgainstEventFilter",
88 base::Bind(&ExtensionImpl::MatchAgainstEventFilter,
89 base::Unretained(this)));
81 } 90 }
82
83 ~ExtensionImpl() {} 91 ~ExtensionImpl() {}
84 92
85 // Attach an event name to an object. 93 // Attach an event name to an object.
86 static v8::Handle<v8::Value> AttachEvent(const v8::Arguments& args) { 94 v8::Handle<v8::Value> AttachEvent(const v8::Arguments& args) {
87 DCHECK(args.Length() == 1); 95 DCHECK(args.Length() == 1);
88 // TODO(erikkay) should enforce that event name is a string in the bindings 96 // TODO(erikkay) should enforce that event name is a string in the bindings
89 DCHECK(args[0]->IsString() || args[0]->IsUndefined()); 97 DCHECK(args[0]->IsString() || args[0]->IsUndefined());
90 98
91 if (args[0]->IsString()) { 99 if (args[0]->IsString()) {
92 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
93 std::string event_name = *v8::String::AsciiValue(args[0]->ToString()); 100 std::string event_name = *v8::String::AsciiValue(args[0]->ToString());
94 ExtensionDispatcher* extension_dispatcher = self->extension_dispatcher();
95 const ChromeV8ContextSet& context_set = 101 const ChromeV8ContextSet& context_set =
96 extension_dispatcher->v8_context_set(); 102 extension_dispatcher()->v8_context_set();
97 ChromeV8Context* context = context_set.GetCurrent(); 103 ChromeV8Context* context = context_set.GetCurrent();
98 CHECK(context); 104 CHECK(context);
99 105
100 if (!extension_dispatcher->CheckCurrentContextAccessToExtensionAPI( 106 if (!extension_dispatcher()->CheckCurrentContextAccessToExtensionAPI(
101 event_name)) 107 event_name))
102 return v8::Undefined(); 108 return v8::Undefined();
103 109
104 std::string extension_id = context->GetExtensionID(); 110 std::string extension_id = context->GetExtensionID();
105 EventListenerCounts& listener_counts = 111 EventListenerCounts& listener_counts =
106 g_listener_counts.Get()[extension_id]; 112 g_listener_counts.Get()[extension_id];
107 if (++listener_counts[event_name] == 1) { 113 if (++listener_counts[event_name] == 1) {
108 content::RenderThread::Get()->Send( 114 content::RenderThread::Get()->Send(
109 new ExtensionHostMsg_AddListener(extension_id, event_name)); 115 new ExtensionHostMsg_AddListener(extension_id, event_name));
110 } 116 }
111 117
112 // This is called the first time the page has added a listener. Since 118 // This is called the first time the page has added a listener. Since
113 // the background page is the only lazy page, we know this is the first 119 // the background page is the only lazy page, we know this is the first
114 // time this listener has been registered. 120 // time this listener has been registered.
115 if (IsLazyBackgroundPage(context->extension())) { 121 if (IsLazyBackgroundPage(context->extension())) {
116 content::RenderThread::Get()->Send( 122 content::RenderThread::Get()->Send(
117 new ExtensionHostMsg_AddLazyListener(extension_id, event_name)); 123 new ExtensionHostMsg_AddLazyListener(extension_id, event_name));
118 } 124 }
119 } 125 }
120 return v8::Undefined(); 126 return v8::Undefined();
121 } 127 }
122 128
123 static v8::Handle<v8::Value> DetachEvent(const v8::Arguments& args) { 129 v8::Handle<v8::Value> DetachEvent(const v8::Arguments& args) {
124 DCHECK(args.Length() == 2); 130 DCHECK(args.Length() == 2);
125 // TODO(erikkay) should enforce that event name is a string in the bindings 131 // TODO(erikkay) should enforce that event name is a string in the bindings
126 DCHECK(args[0]->IsString() || args[0]->IsUndefined()); 132 DCHECK(args[0]->IsString() || args[0]->IsUndefined());
127 133
128 if (args[0]->IsString() && args[1]->IsBoolean()) { 134 if (args[0]->IsString() && args[1]->IsBoolean()) {
129 std::string event_name = *v8::String::AsciiValue(args[0]->ToString()); 135 std::string event_name = *v8::String::AsciiValue(args[0]->ToString());
130 bool is_manual = args[1]->BooleanValue(); 136 bool is_manual = args[1]->BooleanValue();
131 137
132 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
133 ExtensionDispatcher* extension_dispatcher = self->extension_dispatcher();
134 const ChromeV8ContextSet& context_set = 138 const ChromeV8ContextSet& context_set =
135 extension_dispatcher->v8_context_set(); 139 extension_dispatcher()->v8_context_set();
136 ChromeV8Context* context = context_set.GetCurrent(); 140 ChromeV8Context* context = context_set.GetCurrent();
137 if (!context) 141 if (!context)
138 return v8::Undefined(); 142 return v8::Undefined();
139 143
140 std::string extension_id = context->GetExtensionID(); 144 std::string extension_id = context->GetExtensionID();
141 EventListenerCounts& listener_counts = 145 EventListenerCounts& listener_counts =
142 g_listener_counts.Get()[extension_id]; 146 g_listener_counts.Get()[extension_id];
143 147
144 if (--listener_counts[event_name] == 0) { 148 if (--listener_counts[event_name] == 0) {
145 content::RenderThread::Get()->Send( 149 content::RenderThread::Get()->Send(
(...skipping 10 matching lines...) Expand all
156 } 160 }
157 } 161 }
158 return v8::Undefined(); 162 return v8::Undefined();
159 } 163 }
160 164
161 // MatcherID AttachFilteredEvent(string event_name, object filter) 165 // MatcherID AttachFilteredEvent(string event_name, object filter)
162 // event_name - Name of the event to attach. 166 // event_name - Name of the event to attach.
163 // filter - Which instances of the named event are we interested in. 167 // filter - Which instances of the named event are we interested in.
164 // returns the id assigned to the listener, which will be returned from calls 168 // returns the id assigned to the listener, which will be returned from calls
165 // to MatchAgainstEventFilter where this listener matches. 169 // to MatchAgainstEventFilter where this listener matches.
166 static v8::Handle<v8::Value> AttachFilteredEvent(const v8::Arguments& args) { 170 v8::Handle<v8::Value> AttachFilteredEvent(const v8::Arguments& args) {
167 DCHECK_EQ(2, args.Length()); 171 DCHECK_EQ(2, args.Length());
168 DCHECK(args[0]->IsString()); 172 DCHECK(args[0]->IsString());
169 DCHECK(args[1]->IsObject()); 173 DCHECK(args[1]->IsObject());
170 174
171 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
172 ExtensionDispatcher* extension_dispatcher = self->extension_dispatcher();
173 const ChromeV8ContextSet& context_set = 175 const ChromeV8ContextSet& context_set =
174 extension_dispatcher->v8_context_set(); 176 extension_dispatcher()->v8_context_set();
175 ChromeV8Context* context = context_set.GetCurrent(); 177 ChromeV8Context* context = context_set.GetCurrent();
176 DCHECK(context); 178 DCHECK(context);
177 if (!context) 179 if (!context)
178 return v8::Integer::New(-1); 180 return v8::Integer::New(-1);
179 181
180 std::string event_name = *v8::String::AsciiValue(args[0]); 182 std::string event_name = *v8::String::AsciiValue(args[0]);
181 // This method throws an exception if it returns false. 183 // This method throws an exception if it returns false.
182 if (!extension_dispatcher->CheckCurrentContextAccessToExtensionAPI( 184 if (!extension_dispatcher()->CheckCurrentContextAccessToExtensionAPI(
183 event_name)) 185 event_name))
184 return v8::Undefined(); 186 return v8::Undefined();
185 187
186 std::string extension_id = context->GetExtensionID(); 188 std::string extension_id = context->GetExtensionID();
187 if (extension_id.empty()) 189 if (extension_id.empty())
188 return v8::Integer::New(-1); 190 return v8::Integer::New(-1);
189 191
190 scoped_ptr<base::DictionaryValue> filter; 192 scoped_ptr<base::DictionaryValue> filter;
191 scoped_ptr<content::V8ValueConverter> converter( 193 scoped_ptr<content::V8ValueConverter> converter(
192 content::V8ValueConverter::create()); 194 content::V8ValueConverter::create());
193 195
194 base::DictionaryValue* filter_dict = NULL; 196 base::DictionaryValue* filter_dict = NULL;
195 base::Value* filter_value = converter->FromV8Value(args[1]->ToObject(), 197 base::Value* filter_value = converter->FromV8Value(args[1]->ToObject(),
196 v8::Context::GetCurrent()); 198 v8::Context::GetCurrent());
197 if (!filter_value->GetAsDictionary(&filter_dict)) { 199 if (!filter_value->GetAsDictionary(&filter_dict)) {
198 delete filter_value; 200 delete filter_value;
199 return v8::Integer::New(-1); 201 return v8::Integer::New(-1);
200 } 202 }
201 203
202 filter.reset(filter_dict); 204 filter.reset(filter_dict);
203 extensions::EventFilter& event_filter = g_event_filter.Get(); 205 int id = event_filter_->AddEventMatcher(event_name, ParseEventMatcher(
204 int id = event_filter.AddEventMatcher(event_name, ParseEventMatcher(
205 filter.get())); 206 filter.get()));
206 207
207 // Only send IPCs the first time a filter gets added. 208 // Only send IPCs the first time a filter gets added.
208 if (AddFilter(event_name, extension_id, filter.get())) { 209 if (AddFilter(event_name, extension_id, filter.get())) {
209 bool lazy = IsLazyBackgroundPage(context->extension()); 210 bool lazy = IsLazyBackgroundPage(context->extension());
210 content::RenderThread::Get()->Send( 211 content::RenderThread::Get()->Send(
211 new ExtensionHostMsg_AddFilteredListener(extension_id, event_name, 212 new ExtensionHostMsg_AddFilteredListener(extension_id, event_name,
212 *filter, lazy)); 213 *filter, lazy));
213 } 214 }
214 215
215 return v8::Integer::New(id); 216 return v8::Integer::New(id);
216 } 217 }
217 218
218 // Add a filter to |event_name| in |extension_id|, returning true if it 219 // Add a filter to |event_name| in |extension_id|, returning true if it
219 // was the first filter for that event in that extension. 220 // was the first filter for that event in that extension.
220 static bool AddFilter(const std::string& event_name, 221 bool AddFilter(const std::string& event_name,
221 const std::string& extension_id, 222 const std::string& extension_id,
222 base::DictionaryValue* filter) { 223 base::DictionaryValue* filter) {
223 FilteredEventListenerCounts& counts = 224 FilteredEventListenerCounts& counts =
224 g_filtered_listener_counts.Get()[extension_id]; 225 g_filtered_listener_counts.Get()[extension_id];
225 FilteredEventListenerCounts::iterator it = counts.find(event_name); 226 FilteredEventListenerCounts::iterator it = counts.find(event_name);
226 if (it == counts.end()) 227 if (it == counts.end())
227 counts[event_name].reset(new extensions::ValueCounter); 228 counts[event_name].reset(new extensions::ValueCounter);
228 229
229 int result = counts[event_name]->Add(*filter); 230 int result = counts[event_name]->Add(*filter);
230 return 1 == result; 231 return 1 == result;
231 } 232 }
232 233
233 // Remove a filter from |event_name| in |extension_id|, returning true if it 234 // Remove a filter from |event_name| in |extension_id|, returning true if it
234 // was the last filter for that event in that extension. 235 // was the last filter for that event in that extension.
235 static bool RemoveFilter(const std::string& event_name, 236 bool RemoveFilter(const std::string& event_name,
236 const std::string& extension_id, 237 const std::string& extension_id,
237 base::DictionaryValue* filter) { 238 base::DictionaryValue* filter) {
238 FilteredEventListenerCounts& counts = 239 FilteredEventListenerCounts& counts =
239 g_filtered_listener_counts.Get()[extension_id]; 240 g_filtered_listener_counts.Get()[extension_id];
240 FilteredEventListenerCounts::iterator it = counts.find(event_name); 241 FilteredEventListenerCounts::iterator it = counts.find(event_name);
241 if (it == counts.end()) 242 if (it == counts.end())
242 return false; 243 return false;
243 return 0 == it->second->Remove(*filter); 244 return 0 == it->second->Remove(*filter);
244 } 245 }
245 246
246 // void DetachFilteredEvent(int id, bool manual) 247 // void DetachFilteredEvent(int id, bool manual)
247 // id - Id of the event to detach. 248 // id - Id of the event to detach.
248 // manual - false if this is part of the extension unload process where all 249 // manual - false if this is part of the extension unload process where all
249 // listeners are automatically detached. 250 // listeners are automatically detached.
250 static v8::Handle<v8::Value> DetachFilteredEvent(const v8::Arguments& args) { 251 v8::Handle<v8::Value> DetachFilteredEvent(const v8::Arguments& args) {
251 DCHECK_EQ(2, args.Length()); 252 DCHECK_EQ(2, args.Length());
252 DCHECK(args[0]->IsInt32()); 253 DCHECK(args[0]->IsInt32());
253 DCHECK(args[1]->IsBoolean()); 254 DCHECK(args[1]->IsBoolean());
254 bool is_manual = args[1]->BooleanValue(); 255 bool is_manual = args[1]->BooleanValue();
255 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
256 ExtensionDispatcher* extension_dispatcher = self->extension_dispatcher();
257 const ChromeV8ContextSet& context_set = 256 const ChromeV8ContextSet& context_set =
258 extension_dispatcher->v8_context_set(); 257 extension_dispatcher()->v8_context_set();
259 ChromeV8Context* context = context_set.GetCurrent(); 258 ChromeV8Context* context = context_set.GetCurrent();
260 if (!context) 259 if (!context)
261 return v8::Undefined(); 260 return v8::Undefined();
262 261
263 std::string extension_id = context->GetExtensionID(); 262 std::string extension_id = context->GetExtensionID();
264 if (extension_id.empty()) 263 if (extension_id.empty())
265 return v8::Undefined(); 264 return v8::Undefined();
266 265
267 int matcher_id = args[0]->Int32Value(); 266 int matcher_id = args[0]->Int32Value();
268 extensions::EventFilter& event_filter = g_event_filter.Get();
269 extensions::EventMatcher* event_matcher = 267 extensions::EventMatcher* event_matcher =
270 event_filter.GetEventMatcher(matcher_id); 268 event_filter_->GetEventMatcher(matcher_id);
271 269
272 const std::string& event_name = event_filter.GetEventName(matcher_id); 270 const std::string& event_name = event_filter_->GetEventName(matcher_id);
273 271
274 // Only send IPCs the last time a filter gets removed. 272 // Only send IPCs the last time a filter gets removed.
275 if (RemoveFilter(event_name, extension_id, event_matcher->value())) { 273 if (RemoveFilter(event_name, extension_id, event_matcher->value())) {
276 bool lazy = is_manual && IsLazyBackgroundPage(context->extension()); 274 bool lazy = is_manual && IsLazyBackgroundPage(context->extension());
277 content::RenderThread::Get()->Send( 275 content::RenderThread::Get()->Send(
278 new ExtensionHostMsg_RemoveFilteredListener(extension_id, event_name, 276 new ExtensionHostMsg_RemoveFilteredListener(extension_id, event_name,
279 *event_matcher->value(), 277 *event_matcher->value(),
280 lazy)); 278 lazy));
281 } 279 }
282 280
283 event_filter.RemoveEventMatcher(matcher_id); 281 event_filter_->RemoveEventMatcher(matcher_id);
284 282
285 return v8::Undefined(); 283 return v8::Undefined();
286 } 284 }
287 285
288 static v8::Handle<v8::Value> MatchAgainstEventFilter( 286 v8::Handle<v8::Value> MatchAgainstEventFilter(const v8::Arguments& args) {
289 const v8::Arguments& args) {
290 typedef std::set<extensions::EventFilter::MatcherID> MatcherIDs; 287 typedef std::set<extensions::EventFilter::MatcherID> MatcherIDs;
291 288
292 extensions::EventFilter& event_filter = g_event_filter.Get();
293 std::string event_name = *v8::String::AsciiValue(args[0]->ToString()); 289 std::string event_name = *v8::String::AsciiValue(args[0]->ToString());
294 extensions::EventFilteringInfo info = ParseFromObject(args[1]->ToObject()); 290 extensions::EventFilteringInfo info = ParseFromObject(args[1]->ToObject());
295 MatcherIDs matched_event_filters = event_filter.MatchEvent( 291 MatcherIDs matched_event_filters = event_filter_->MatchEvent(
296 event_name, info); 292 event_name, info);
297 v8::Handle<v8::Array> array(v8::Array::New(matched_event_filters.size())); 293 v8::Handle<v8::Array> array(v8::Array::New(matched_event_filters.size()));
298 int i = 0; 294 int i = 0;
299 for (MatcherIDs::iterator it = matched_event_filters.begin(); 295 for (MatcherIDs::iterator it = matched_event_filters.begin();
300 it != matched_event_filters.end(); ++it) { 296 it != matched_event_filters.end(); ++it) {
301 array->Set(v8::Integer::New(i++), v8::Integer::New(*it)); 297 array->Set(v8::Integer::New(i++), v8::Integer::New(*it));
302 } 298 }
303 return array; 299 return array;
304 } 300 }
305 301
306 static extensions::EventFilteringInfo ParseFromObject( 302 extensions::EventFilteringInfo ParseFromObject(
307 v8::Handle<v8::Object> object) { 303 v8::Handle<v8::Object> object) {
308 extensions::EventFilteringInfo info; 304 extensions::EventFilteringInfo info;
309 v8::Handle<v8::String> url(v8::String::New("url")); 305 v8::Handle<v8::String> url(v8::String::New("url"));
310 if (object->Has(url)) { 306 if (object->Has(url)) {
311 v8::Handle<v8::Value> url_value(object->Get(url)); 307 v8::Handle<v8::Value> url_value(object->Get(url));
312 info.SetURL(GURL(*v8::String::AsciiValue(url_value))); 308 info.SetURL(GURL(*v8::String::AsciiValue(url_value)));
313 } 309 }
314 return info; 310 return info;
315 } 311 }
316 312
317 private: 313 private:
318 static bool IsLazyBackgroundPage(const Extension* extension) { 314 extensions::EventFilter* event_filter_;
315 bool IsLazyBackgroundPage(const Extension* extension) {
319 content::RenderView* render_view = GetCurrentRenderView(); 316 content::RenderView* render_view = GetCurrentRenderView();
320 if (!render_view) 317 if (!render_view)
321 return false; 318 return false;
322 319
323 ExtensionHelper* helper = ExtensionHelper::Get(render_view); 320 ExtensionHelper* helper = ExtensionHelper::Get(render_view);
324 return (extension && extension->has_lazy_background_page() && 321 return (extension && extension->has_lazy_background_page() &&
325 helper->view_type() == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); 322 helper->view_type() == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
326 } 323 }
327 324
328 static scoped_ptr<extensions::EventMatcher> ParseEventMatcher( 325 scoped_ptr<extensions::EventMatcher> ParseEventMatcher(
329 base::DictionaryValue* filter_dict) { 326 base::DictionaryValue* filter_dict) {
330 return scoped_ptr<extensions::EventMatcher>(new extensions::EventMatcher( 327 return scoped_ptr<extensions::EventMatcher>(new extensions::EventMatcher(
331 scoped_ptr<base::DictionaryValue>(filter_dict->DeepCopy()))); 328 scoped_ptr<base::DictionaryValue>(filter_dict->DeepCopy())));
332 } 329 }
333 }; 330 };
334 331
335 } // namespace 332 } // namespace
336 333
337 // static 334 // static
338 ChromeV8Extension* EventBindings::Get(ExtensionDispatcher* dispatcher) { 335 ChromeV8Extension* EventBindings::Get(ExtensionDispatcher* dispatcher,
339 return new ExtensionImpl(dispatcher); 336 extensions::EventFilter* event_filter) {
337 return new ExtensionImpl(dispatcher, event_filter);
340 } 338 }
OLDNEW
« no previous file with comments | « chrome/renderer/extensions/event_bindings.h ('k') | chrome/renderer/extensions/extension_dispatcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698