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

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

Issue 12632004: Revert 186643 - Caused a 10% regression on SunSpider benchmark (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 9 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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 65
66 // A map of extension IDs to filtered listener counts for that extension. 66 // A map of extension IDs to filtered listener counts for that extension.
67 base::LazyInstance<std::map<std::string, FilteredEventListenerCounts> > 67 base::LazyInstance<std::map<std::string, FilteredEventListenerCounts> >
68 g_filtered_listener_counts = LAZY_INSTANCE_INITIALIZER; 68 g_filtered_listener_counts = LAZY_INSTANCE_INITIALIZER;
69 69
70 base::LazyInstance<EventFilter> g_event_filter = LAZY_INSTANCE_INITIALIZER; 70 base::LazyInstance<EventFilter> g_event_filter = LAZY_INSTANCE_INITIALIZER;
71 71
72 // TODO(koz): Merge this into EventBindings. 72 // TODO(koz): Merge this into EventBindings.
73 class ExtensionImpl : public ChromeV8Extension { 73 class ExtensionImpl : public ChromeV8Extension {
74 public: 74 public:
75 explicit ExtensionImpl(Dispatcher* dispatcher, 75 explicit ExtensionImpl(Dispatcher* dispatcher)
76 v8::Handle<v8::Context> v8_context) 76 : ChromeV8Extension(dispatcher) {
77 : ChromeV8Extension(dispatcher, v8_context) {
78 RouteStaticFunction("AttachEvent", &AttachEvent); 77 RouteStaticFunction("AttachEvent", &AttachEvent);
79 RouteStaticFunction("DetachEvent", &DetachEvent); 78 RouteStaticFunction("DetachEvent", &DetachEvent);
80 RouteStaticFunction("AttachFilteredEvent", &AttachFilteredEvent); 79 RouteStaticFunction("AttachFilteredEvent", &AttachFilteredEvent);
81 RouteStaticFunction("DetachFilteredEvent", &DetachFilteredEvent); 80 RouteStaticFunction("DetachFilteredEvent", &DetachFilteredEvent);
82 RouteStaticFunction("MatchAgainstEventFilter", &MatchAgainstEventFilter); 81 RouteStaticFunction("MatchAgainstEventFilter", &MatchAgainstEventFilter);
83 } 82 }
84 83
85 virtual ~ExtensionImpl() {} 84 virtual ~ExtensionImpl() {}
86 85
87 // Attach an event name to an object. 86 // Attach an event name to an object.
88 static v8::Handle<v8::Value> AttachEvent(const v8::Arguments& args) { 87 static v8::Handle<v8::Value> AttachEvent(const v8::Arguments& args) {
89 DCHECK(args.Length() == 1); 88 DCHECK(args.Length() == 1);
90 // TODO(erikkay) should enforce that event name is a string in the bindings 89 // TODO(erikkay) should enforce that event name is a string in the bindings
91 DCHECK(args[0]->IsString() || args[0]->IsUndefined()); 90 DCHECK(args[0]->IsString() || args[0]->IsUndefined());
92 91
93 if (args[0]->IsString()) { 92 if (args[0]->IsString()) {
94 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); 93 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
95 std::string event_name = *v8::String::AsciiValue(args[0]->ToString()); 94 std::string event_name = *v8::String::AsciiValue(args[0]->ToString());
96 Dispatcher* dispatcher = self->dispatcher(); 95 Dispatcher* dispatcher = self->dispatcher();
97 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set(); 96 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set();
98 ChromeV8Context* context = context_set.GetByV8Context(self->v8_context()); 97 ChromeV8Context* context = context_set.GetCurrent();
99 CHECK(context); 98 CHECK(context);
100 99
101 if (!dispatcher->CheckContextAccessToExtensionAPI(event_name, context)) 100 if (!dispatcher->CheckCurrentContextAccessToExtensionAPI(event_name))
102 return v8::Undefined(); 101 return v8::Undefined();
103 102
104 std::string extension_id = context->GetExtensionID(); 103 std::string extension_id = context->GetExtensionID();
105 EventListenerCounts& listener_counts = 104 EventListenerCounts& listener_counts =
106 g_listener_counts.Get()[extension_id]; 105 g_listener_counts.Get()[extension_id];
107 if (++listener_counts[event_name] == 1) { 106 if (++listener_counts[event_name] == 1) {
108 content::RenderThread::Get()->Send( 107 content::RenderThread::Get()->Send(
109 new ExtensionHostMsg_AddListener(extension_id, event_name)); 108 new ExtensionHostMsg_AddListener(extension_id, event_name));
110 } 109 }
111 110
112 // This is called the first time the page has added a listener. Since 111 // 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 112 // the background page is the only lazy page, we know this is the first
114 // time this listener has been registered. 113 // time this listener has been registered.
115 if (IsLazyBackgroundPage(self->GetRenderView(), context->extension())) { 114 if (IsLazyBackgroundPage(context->extension())) {
116 content::RenderThread::Get()->Send( 115 content::RenderThread::Get()->Send(
117 new ExtensionHostMsg_AddLazyListener(extension_id, event_name)); 116 new ExtensionHostMsg_AddLazyListener(extension_id, event_name));
118 } 117 }
119 } 118 }
120 return v8::Undefined(); 119 return v8::Undefined();
121 } 120 }
122 121
123 static v8::Handle<v8::Value> DetachEvent(const v8::Arguments& args) { 122 static v8::Handle<v8::Value> DetachEvent(const v8::Arguments& args) {
124 DCHECK(args.Length() == 2); 123 DCHECK(args.Length() == 2);
125 // TODO(erikkay) should enforce that event name is a string in the bindings 124 // TODO(erikkay) should enforce that event name is a string in the bindings
126 DCHECK(args[0]->IsString() || args[0]->IsUndefined()); 125 DCHECK(args[0]->IsString() || args[0]->IsUndefined());
127 126
128 if (args[0]->IsString() && args[1]->IsBoolean()) { 127 if (args[0]->IsString() && args[1]->IsBoolean()) {
129 std::string event_name = *v8::String::AsciiValue(args[0]->ToString()); 128 std::string event_name = *v8::String::AsciiValue(args[0]->ToString());
130 bool is_manual = args[1]->BooleanValue(); 129 bool is_manual = args[1]->BooleanValue();
131 130
132 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); 131 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
133 Dispatcher* dispatcher = self->dispatcher(); 132 Dispatcher* dispatcher = self->dispatcher();
134 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set(); 133 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set();
135 ChromeV8Context* context = context_set.GetByV8Context(self->v8_context()); 134 ChromeV8Context* context = context_set.GetCurrent();
136 if (!context) 135 if (!context)
137 return v8::Undefined(); 136 return v8::Undefined();
138 137
139 std::string extension_id = context->GetExtensionID(); 138 std::string extension_id = context->GetExtensionID();
140 EventListenerCounts& listener_counts = 139 EventListenerCounts& listener_counts =
141 g_listener_counts.Get()[extension_id]; 140 g_listener_counts.Get()[extension_id];
142 141
143 if (--listener_counts[event_name] == 0) { 142 if (--listener_counts[event_name] == 0) {
144 content::RenderThread::Get()->Send( 143 content::RenderThread::Get()->Send(
145 new ExtensionHostMsg_RemoveListener(extension_id, event_name)); 144 new ExtensionHostMsg_RemoveListener(extension_id, event_name));
146 } 145 }
147 146
148 // DetachEvent is called when the last listener for the context is 147 // DetachEvent is called when the last listener for the context is
149 // removed. If the context is the background page, and it removes the 148 // removed. If the context is the background page, and it removes the
150 // last listener manually, then we assume that it is no longer interested 149 // last listener manually, then we assume that it is no longer interested
151 // in being awakened for this event. 150 // in being awakened for this event.
152 if (is_manual && IsLazyBackgroundPage(self->GetRenderView(), 151 if (is_manual && IsLazyBackgroundPage(context->extension())) {
153 context->extension())) {
154 content::RenderThread::Get()->Send( 152 content::RenderThread::Get()->Send(
155 new ExtensionHostMsg_RemoveLazyListener(extension_id, event_name)); 153 new ExtensionHostMsg_RemoveLazyListener(extension_id, event_name));
156 } 154 }
157 } 155 }
158 return v8::Undefined(); 156 return v8::Undefined();
159 } 157 }
160 158
161 // MatcherID AttachFilteredEvent(string event_name, object filter) 159 // MatcherID AttachFilteredEvent(string event_name, object filter)
162 // event_name - Name of the event to attach. 160 // event_name - Name of the event to attach.
163 // filter - Which instances of the named event are we interested in. 161 // 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 162 // returns the id assigned to the listener, which will be returned from calls
165 // to MatchAgainstEventFilter where this listener matches. 163 // to MatchAgainstEventFilter where this listener matches.
166 static v8::Handle<v8::Value> AttachFilteredEvent(const v8::Arguments& args) { 164 static v8::Handle<v8::Value> AttachFilteredEvent(const v8::Arguments& args) {
167 DCHECK_EQ(2, args.Length()); 165 DCHECK_EQ(2, args.Length());
168 DCHECK(args[0]->IsString()); 166 DCHECK(args[0]->IsString());
169 DCHECK(args[1]->IsObject()); 167 DCHECK(args[1]->IsObject());
170 168
171 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); 169 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
172 Dispatcher* dispatcher = self->dispatcher(); 170 Dispatcher* dispatcher = self->dispatcher();
173 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set(); 171 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set();
174 ChromeV8Context* context = context_set.GetByV8Context(self->v8_context()); 172 ChromeV8Context* context = context_set.GetCurrent();
175 DCHECK(context); 173 DCHECK(context);
176 if (!context) 174 if (!context)
177 return v8::Integer::New(-1); 175 return v8::Integer::New(-1);
178 176
179 std::string event_name = *v8::String::AsciiValue(args[0]); 177 std::string event_name = *v8::String::AsciiValue(args[0]);
180 // This method throws an exception if it returns false. 178 // This method throws an exception if it returns false.
181 if (!dispatcher->CheckContextAccessToExtensionAPI(event_name, context)) 179 if (!dispatcher->CheckCurrentContextAccessToExtensionAPI(event_name))
182 return v8::Undefined(); 180 return v8::Undefined();
183 181
184 std::string extension_id = context->GetExtensionID(); 182 std::string extension_id = context->GetExtensionID();
185 if (extension_id.empty()) 183 if (extension_id.empty())
186 return v8::Integer::New(-1); 184 return v8::Integer::New(-1);
187 185
188 scoped_ptr<base::DictionaryValue> filter; 186 scoped_ptr<base::DictionaryValue> filter;
189 scoped_ptr<content::V8ValueConverter> converter( 187 scoped_ptr<content::V8ValueConverter> converter(
190 content::V8ValueConverter::create()); 188 content::V8ValueConverter::create());
191 189
192 base::DictionaryValue* filter_dict = NULL; 190 base::DictionaryValue* filter_dict = NULL;
193 base::Value* filter_value = 191 base::Value* filter_value = converter->FromV8Value(args[1]->ToObject(),
194 converter->FromV8Value(args[1]->ToObject(), context->v8_context()); 192 v8::Context::GetCurrent());
195 if (!filter_value) 193 if (!filter_value)
196 return v8::Integer::New(-1); 194 return v8::Integer::New(-1);
197 if (!filter_value->GetAsDictionary(&filter_dict)) { 195 if (!filter_value->GetAsDictionary(&filter_dict)) {
198 delete filter_value; 196 delete filter_value;
199 return v8::Integer::New(-1); 197 return v8::Integer::New(-1);
200 } 198 }
201 199
202 filter.reset(filter_dict); 200 filter.reset(filter_dict);
203 EventFilter& event_filter = g_event_filter.Get(); 201 EventFilter& event_filter = g_event_filter.Get();
204 int id = event_filter.AddEventMatcher(event_name, ParseEventMatcher( 202 int id = event_filter.AddEventMatcher(event_name, ParseEventMatcher(
205 filter.get())); 203 filter.get()));
206 204
207 // Only send IPCs the first time a filter gets added. 205 // Only send IPCs the first time a filter gets added.
208 if (AddFilter(event_name, extension_id, filter.get())) { 206 if (AddFilter(event_name, extension_id, filter.get())) {
209 bool lazy = IsLazyBackgroundPage(self->GetRenderView(), 207 bool lazy = IsLazyBackgroundPage(context->extension());
210 context->extension());
211 content::RenderThread::Get()->Send( 208 content::RenderThread::Get()->Send(
212 new ExtensionHostMsg_AddFilteredListener(extension_id, event_name, 209 new ExtensionHostMsg_AddFilteredListener(extension_id, event_name,
213 *filter, lazy)); 210 *filter, lazy));
214 } 211 }
215 212
216 return v8::Integer::New(id); 213 return v8::Integer::New(id);
217 } 214 }
218 215
219 // Add a filter to |event_name| in |extension_id|, returning true if it 216 // Add a filter to |event_name| in |extension_id|, returning true if it
220 // was the first filter for that event in that extension. 217 // was the first filter for that event in that extension.
(...skipping 28 matching lines...) Expand all
249 // manual - false if this is part of the extension unload process where all 246 // manual - false if this is part of the extension unload process where all
250 // listeners are automatically detached. 247 // listeners are automatically detached.
251 static v8::Handle<v8::Value> DetachFilteredEvent(const v8::Arguments& args) { 248 static v8::Handle<v8::Value> DetachFilteredEvent(const v8::Arguments& args) {
252 DCHECK_EQ(2, args.Length()); 249 DCHECK_EQ(2, args.Length());
253 DCHECK(args[0]->IsInt32()); 250 DCHECK(args[0]->IsInt32());
254 DCHECK(args[1]->IsBoolean()); 251 DCHECK(args[1]->IsBoolean());
255 bool is_manual = args[1]->BooleanValue(); 252 bool is_manual = args[1]->BooleanValue();
256 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); 253 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
257 Dispatcher* dispatcher = self->dispatcher(); 254 Dispatcher* dispatcher = self->dispatcher();
258 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set(); 255 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set();
259 ChromeV8Context* context = context_set.GetByV8Context(self->v8_context()); 256 ChromeV8Context* context = context_set.GetCurrent();
260 if (!context) 257 if (!context)
261 return v8::Undefined(); 258 return v8::Undefined();
262 259
263 std::string extension_id = context->GetExtensionID(); 260 std::string extension_id = context->GetExtensionID();
264 if (extension_id.empty()) 261 if (extension_id.empty())
265 return v8::Undefined(); 262 return v8::Undefined();
266 263
267 int matcher_id = args[0]->Int32Value(); 264 int matcher_id = args[0]->Int32Value();
268 EventFilter& event_filter = g_event_filter.Get(); 265 EventFilter& event_filter = g_event_filter.Get();
269 EventMatcher* event_matcher = 266 EventMatcher* event_matcher =
270 event_filter.GetEventMatcher(matcher_id); 267 event_filter.GetEventMatcher(matcher_id);
271 268
272 const std::string& event_name = event_filter.GetEventName(matcher_id); 269 const std::string& event_name = event_filter.GetEventName(matcher_id);
273 270
274 // Only send IPCs the last time a filter gets removed. 271 // Only send IPCs the last time a filter gets removed.
275 if (RemoveFilter(event_name, extension_id, event_matcher->value())) { 272 if (RemoveFilter(event_name, extension_id, event_matcher->value())) {
276 bool lazy = is_manual && IsLazyBackgroundPage(self->GetRenderView(), 273 bool lazy = is_manual && IsLazyBackgroundPage(context->extension());
277 context->extension());
278 content::RenderThread::Get()->Send( 274 content::RenderThread::Get()->Send(
279 new ExtensionHostMsg_RemoveFilteredListener(extension_id, event_name, 275 new ExtensionHostMsg_RemoveFilteredListener(extension_id, event_name,
280 *event_matcher->value(), 276 *event_matcher->value(),
281 lazy)); 277 lazy));
282 } 278 }
283 279
284 event_filter.RemoveEventMatcher(matcher_id); 280 event_filter.RemoveEventMatcher(matcher_id);
285 281
286 return v8::Undefined(); 282 return v8::Undefined();
287 } 283 }
(...skipping 20 matching lines...) Expand all
308 EventFilteringInfo info; 304 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(content::RenderView* render_view, 314 static bool IsLazyBackgroundPage(const Extension* extension) {
319 const Extension* extension) { 315 content::RenderView* render_view = GetCurrentRenderView();
320 if (!render_view) 316 if (!render_view)
321 return false; 317 return false;
318
322 ExtensionHelper* helper = ExtensionHelper::Get(render_view); 319 ExtensionHelper* helper = ExtensionHelper::Get(render_view);
323 return (extension && BackgroundInfo::HasLazyBackgroundPage(extension) && 320 return (extension && BackgroundInfo::HasLazyBackgroundPage(extension) &&
324 helper->view_type() == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); 321 helper->view_type() == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
325 } 322 }
326 323
327 static scoped_ptr<EventMatcher> ParseEventMatcher( 324 static scoped_ptr<EventMatcher> ParseEventMatcher(
328 base::DictionaryValue* filter_dict) { 325 base::DictionaryValue* filter_dict) {
329 return scoped_ptr<EventMatcher>(new EventMatcher( 326 return scoped_ptr<EventMatcher>(new EventMatcher(
330 scoped_ptr<base::DictionaryValue>(filter_dict->DeepCopy()))); 327 scoped_ptr<base::DictionaryValue>(filter_dict->DeepCopy())));
331 } 328 }
332 }; 329 };
333 330
334 } // namespace 331 } // namespace
335 332
336 // static 333 // static
337 ChromeV8Extension* EventBindings::Create(Dispatcher* dispatcher, 334 ChromeV8Extension* EventBindings::Get(Dispatcher* dispatcher) {
338 v8::Handle<v8::Context> context) { 335 return new ExtensionImpl(dispatcher);
339 return new ExtensionImpl(dispatcher, context);
340 } 336 }
341 337
342 } // namespace extensions 338 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/renderer/extensions/event_bindings.h ('k') | chrome/renderer/extensions/event_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698