OLD | NEW |
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" |
11 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
13 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
| 14 #include "chrome/common/extensions/background_info.h" |
| 15 #include "chrome/common/extensions/extension.h" |
14 #include "chrome/common/extensions/extension_messages.h" | 16 #include "chrome/common/extensions/extension_messages.h" |
15 #include "chrome/common/extensions/extension_set.h" | 17 #include "chrome/common/extensions/extension_set.h" |
16 #include "chrome/common/extensions/value_counter.h" | 18 #include "chrome/common/extensions/value_counter.h" |
17 #include "chrome/common/url_constants.h" | 19 #include "chrome/common/url_constants.h" |
18 #include "chrome/common/view_type.h" | 20 #include "chrome/common/view_type.h" |
19 #include "chrome/renderer/extensions/chrome_v8_context.h" | 21 #include "chrome/renderer/extensions/chrome_v8_context.h" |
20 #include "chrome/renderer/extensions/chrome_v8_context_set.h" | 22 #include "chrome/renderer/extensions/chrome_v8_context_set.h" |
21 #include "chrome/renderer/extensions/chrome_v8_extension.h" | 23 #include "chrome/renderer/extensions/chrome_v8_extension.h" |
22 #include "chrome/renderer/extensions/dispatcher.h" | 24 #include "chrome/renderer/extensions/dispatcher.h" |
23 #include "chrome/renderer/extensions/event_bindings.h" | 25 #include "chrome/renderer/extensions/event_bindings.h" |
24 #include "chrome/renderer/extensions/extension_helper.h" | 26 #include "chrome/renderer/extensions/extension_helper.h" |
25 #include "chrome/renderer/extensions/user_script_slave.h" | 27 #include "chrome/renderer/extensions/user_script_slave.h" |
26 #include "content/public/renderer/render_thread.h" | 28 #include "content/public/renderer/render_thread.h" |
27 #include "content/public/renderer/v8_value_converter.h" | 29 #include "content/public/renderer/v8_value_converter.h" |
28 #include "extensions/common/event_filter.h" | 30 #include "extensions/common/event_filter.h" |
29 #include "googleurl/src/gurl.h" | 31 #include "googleurl/src/gurl.h" |
30 #include "grit/renderer_resources.h" | 32 #include "grit/renderer_resources.h" |
31 #include "third_party/WebKit/Source/Platform/chromium/public/WebURL.h" | 33 #include "third_party/WebKit/Source/Platform/chromium/public/WebURL.h" |
32 #include "third_party/WebKit/Source/Platform/chromium/public/WebURLRequest.h" | 34 #include "third_party/WebKit/Source/Platform/chromium/public/WebURLRequest.h" |
33 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 35 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
34 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 36 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
35 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" | 37 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" |
36 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 38 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
37 #include "v8/include/v8.h" | 39 #include "v8/include/v8.h" |
38 | 40 |
39 using WebKit::WebFrame; | 41 using WebKit::WebFrame; |
40 using WebKit::WebSecurityOrigin; | 42 using WebKit::WebSecurityOrigin; |
41 using WebKit::WebURL; | 43 using WebKit::WebURL; |
42 using content::RenderThread; | 44 using content::RenderThread; |
43 using extensions::Extension; | |
44 | 45 |
45 namespace extensions { | 46 namespace extensions { |
46 | 47 |
47 namespace { | 48 namespace { |
48 | 49 |
49 // A map of event names to the number of contexts listening to that event. | 50 // A map of event names to the number of contexts listening to that event. |
50 // We notify the browser about event listeners when we transition between 0 | 51 // We notify the browser about event listeners when we transition between 0 |
51 // and 1. | 52 // and 1. |
52 typedef std::map<std::string, int> EventListenerCounts; | 53 typedef std::map<std::string, int> EventListenerCounts; |
53 | 54 |
54 // A map of extension IDs to listener counts for that extension. | 55 // A map of extension IDs to listener counts for that extension. |
55 base::LazyInstance<std::map<std::string, EventListenerCounts> > | 56 base::LazyInstance<std::map<std::string, EventListenerCounts> > |
56 g_listener_counts = LAZY_INSTANCE_INITIALIZER; | 57 g_listener_counts = LAZY_INSTANCE_INITIALIZER; |
57 | 58 |
58 // A map of event names to a (filter -> count) map. The map is used to keep | 59 // A map of event names to a (filter -> count) map. The map is used to keep |
59 // track of which filters are in effect for which events. | 60 // track of which filters are in effect for which events. |
60 // We notify the browser about filtered event listeners when we transition | 61 // We notify the browser about filtered event listeners when we transition |
61 // between 0 and 1. | 62 // between 0 and 1. |
62 typedef std::map<std::string, linked_ptr<extensions::ValueCounter> > | 63 typedef std::map<std::string, linked_ptr<ValueCounter> > |
63 FilteredEventListenerCounts; | 64 FilteredEventListenerCounts; |
64 | 65 |
65 // 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. |
66 base::LazyInstance<std::map<std::string, FilteredEventListenerCounts> > | 67 base::LazyInstance<std::map<std::string, FilteredEventListenerCounts> > |
67 g_filtered_listener_counts = LAZY_INSTANCE_INITIALIZER; | 68 g_filtered_listener_counts = LAZY_INSTANCE_INITIALIZER; |
68 | 69 |
69 base::LazyInstance<extensions::EventFilter> g_event_filter = | 70 base::LazyInstance<EventFilter> g_event_filter = LAZY_INSTANCE_INITIALIZER; |
70 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 : ChromeV8Extension(dispatcher) { | 76 : ChromeV8Extension(dispatcher) { |
77 RouteStaticFunction("AttachEvent", &AttachEvent); | 77 RouteStaticFunction("AttachEvent", &AttachEvent); |
78 RouteStaticFunction("DetachEvent", &DetachEvent); | 78 RouteStaticFunction("DetachEvent", &DetachEvent); |
79 RouteStaticFunction("AttachFilteredEvent", &AttachFilteredEvent); | 79 RouteStaticFunction("AttachFilteredEvent", &AttachFilteredEvent); |
80 RouteStaticFunction("DetachFilteredEvent", &DetachFilteredEvent); | 80 RouteStaticFunction("DetachFilteredEvent", &DetachFilteredEvent); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 base::Value* filter_value = converter->FromV8Value(args[1]->ToObject(), | 191 base::Value* filter_value = converter->FromV8Value(args[1]->ToObject(), |
192 v8::Context::GetCurrent()); | 192 v8::Context::GetCurrent()); |
193 if (!filter_value) | 193 if (!filter_value) |
194 return v8::Integer::New(-1); | 194 return v8::Integer::New(-1); |
195 if (!filter_value->GetAsDictionary(&filter_dict)) { | 195 if (!filter_value->GetAsDictionary(&filter_dict)) { |
196 delete filter_value; | 196 delete filter_value; |
197 return v8::Integer::New(-1); | 197 return v8::Integer::New(-1); |
198 } | 198 } |
199 | 199 |
200 filter.reset(filter_dict); | 200 filter.reset(filter_dict); |
201 extensions::EventFilter& event_filter = g_event_filter.Get(); | 201 EventFilter& event_filter = g_event_filter.Get(); |
202 int id = event_filter.AddEventMatcher(event_name, ParseEventMatcher( | 202 int id = event_filter.AddEventMatcher(event_name, ParseEventMatcher( |
203 filter.get())); | 203 filter.get())); |
204 | 204 |
205 // Only send IPCs the first time a filter gets added. | 205 // Only send IPCs the first time a filter gets added. |
206 if (AddFilter(event_name, extension_id, filter.get())) { | 206 if (AddFilter(event_name, extension_id, filter.get())) { |
207 bool lazy = IsLazyBackgroundPage(context->extension()); | 207 bool lazy = IsLazyBackgroundPage(context->extension()); |
208 content::RenderThread::Get()->Send( | 208 content::RenderThread::Get()->Send( |
209 new ExtensionHostMsg_AddFilteredListener(extension_id, event_name, | 209 new ExtensionHostMsg_AddFilteredListener(extension_id, event_name, |
210 *filter, lazy)); | 210 *filter, lazy)); |
211 } | 211 } |
212 | 212 |
213 return v8::Integer::New(id); | 213 return v8::Integer::New(id); |
214 } | 214 } |
215 | 215 |
216 // 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 |
217 // was the first filter for that event in that extension. | 217 // was the first filter for that event in that extension. |
218 static bool AddFilter(const std::string& event_name, | 218 static bool AddFilter(const std::string& event_name, |
219 const std::string& extension_id, | 219 const std::string& extension_id, |
220 base::DictionaryValue* filter) { | 220 base::DictionaryValue* filter) { |
221 FilteredEventListenerCounts& counts = | 221 FilteredEventListenerCounts& counts = |
222 g_filtered_listener_counts.Get()[extension_id]; | 222 g_filtered_listener_counts.Get()[extension_id]; |
223 FilteredEventListenerCounts::iterator it = counts.find(event_name); | 223 FilteredEventListenerCounts::iterator it = counts.find(event_name); |
224 if (it == counts.end()) | 224 if (it == counts.end()) |
225 counts[event_name].reset(new extensions::ValueCounter); | 225 counts[event_name].reset(new ValueCounter); |
226 | 226 |
227 int result = counts[event_name]->Add(*filter); | 227 int result = counts[event_name]->Add(*filter); |
228 return 1 == result; | 228 return 1 == result; |
229 } | 229 } |
230 | 230 |
231 // Remove a filter from |event_name| in |extension_id|, returning true if it | 231 // Remove a filter from |event_name| in |extension_id|, returning true if it |
232 // was the last filter for that event in that extension. | 232 // was the last filter for that event in that extension. |
233 static bool RemoveFilter(const std::string& event_name, | 233 static bool RemoveFilter(const std::string& event_name, |
234 const std::string& extension_id, | 234 const std::string& extension_id, |
235 base::DictionaryValue* filter) { | 235 base::DictionaryValue* filter) { |
(...skipping 19 matching lines...) Expand all Loading... |
255 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set(); | 255 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set(); |
256 ChromeV8Context* context = context_set.GetCurrent(); | 256 ChromeV8Context* context = context_set.GetCurrent(); |
257 if (!context) | 257 if (!context) |
258 return v8::Undefined(); | 258 return v8::Undefined(); |
259 | 259 |
260 std::string extension_id = context->GetExtensionID(); | 260 std::string extension_id = context->GetExtensionID(); |
261 if (extension_id.empty()) | 261 if (extension_id.empty()) |
262 return v8::Undefined(); | 262 return v8::Undefined(); |
263 | 263 |
264 int matcher_id = args[0]->Int32Value(); | 264 int matcher_id = args[0]->Int32Value(); |
265 extensions::EventFilter& event_filter = g_event_filter.Get(); | 265 EventFilter& event_filter = g_event_filter.Get(); |
266 extensions::EventMatcher* event_matcher = | 266 EventMatcher* event_matcher = |
267 event_filter.GetEventMatcher(matcher_id); | 267 event_filter.GetEventMatcher(matcher_id); |
268 | 268 |
269 const std::string& event_name = event_filter.GetEventName(matcher_id); | 269 const std::string& event_name = event_filter.GetEventName(matcher_id); |
270 | 270 |
271 // Only send IPCs the last time a filter gets removed. | 271 // Only send IPCs the last time a filter gets removed. |
272 if (RemoveFilter(event_name, extension_id, event_matcher->value())) { | 272 if (RemoveFilter(event_name, extension_id, event_matcher->value())) { |
273 bool lazy = is_manual && IsLazyBackgroundPage(context->extension()); | 273 bool lazy = is_manual && IsLazyBackgroundPage(context->extension()); |
274 content::RenderThread::Get()->Send( | 274 content::RenderThread::Get()->Send( |
275 new ExtensionHostMsg_RemoveFilteredListener(extension_id, event_name, | 275 new ExtensionHostMsg_RemoveFilteredListener(extension_id, event_name, |
276 *event_matcher->value(), | 276 *event_matcher->value(), |
277 lazy)); | 277 lazy)); |
278 } | 278 } |
279 | 279 |
280 event_filter.RemoveEventMatcher(matcher_id); | 280 event_filter.RemoveEventMatcher(matcher_id); |
281 | 281 |
282 return v8::Undefined(); | 282 return v8::Undefined(); |
283 } | 283 } |
284 | 284 |
285 static v8::Handle<v8::Value> MatchAgainstEventFilter( | 285 static v8::Handle<v8::Value> MatchAgainstEventFilter( |
286 const v8::Arguments& args) { | 286 const v8::Arguments& args) { |
287 typedef std::set<extensions::EventFilter::MatcherID> MatcherIDs; | 287 typedef std::set<EventFilter::MatcherID> MatcherIDs; |
288 | 288 |
289 extensions::EventFilter& event_filter = g_event_filter.Get(); | 289 EventFilter& event_filter = g_event_filter.Get(); |
290 std::string event_name = *v8::String::AsciiValue(args[0]->ToString()); | 290 std::string event_name = *v8::String::AsciiValue(args[0]->ToString()); |
291 extensions::EventFilteringInfo info = ParseFromObject(args[1]->ToObject()); | 291 EventFilteringInfo info = ParseFromObject(args[1]->ToObject()); |
292 MatcherIDs matched_event_filters = event_filter.MatchEvent( | 292 MatcherIDs matched_event_filters = event_filter.MatchEvent( |
293 event_name, info); | 293 event_name, info); |
294 v8::Handle<v8::Array> array(v8::Array::New(matched_event_filters.size())); | 294 v8::Handle<v8::Array> array(v8::Array::New(matched_event_filters.size())); |
295 int i = 0; | 295 int i = 0; |
296 for (MatcherIDs::iterator it = matched_event_filters.begin(); | 296 for (MatcherIDs::iterator it = matched_event_filters.begin(); |
297 it != matched_event_filters.end(); ++it) { | 297 it != matched_event_filters.end(); ++it) { |
298 array->Set(v8::Integer::New(i++), v8::Integer::New(*it)); | 298 array->Set(v8::Integer::New(i++), v8::Integer::New(*it)); |
299 } | 299 } |
300 return array; | 300 return array; |
301 } | 301 } |
302 | 302 |
303 static extensions::EventFilteringInfo ParseFromObject( | 303 static EventFilteringInfo ParseFromObject(v8::Handle<v8::Object> object) { |
304 v8::Handle<v8::Object> object) { | 304 EventFilteringInfo info; |
305 extensions::EventFilteringInfo info; | |
306 v8::Handle<v8::String> url(v8::String::New("url")); | 305 v8::Handle<v8::String> url(v8::String::New("url")); |
307 if (object->Has(url)) { | 306 if (object->Has(url)) { |
308 v8::Handle<v8::Value> url_value(object->Get(url)); | 307 v8::Handle<v8::Value> url_value(object->Get(url)); |
309 info.SetURL(GURL(*v8::String::AsciiValue(url_value))); | 308 info.SetURL(GURL(*v8::String::AsciiValue(url_value))); |
310 } | 309 } |
311 return info; | 310 return info; |
312 } | 311 } |
313 | 312 |
314 private: | 313 private: |
315 static bool IsLazyBackgroundPage(const Extension* extension) { | 314 static bool IsLazyBackgroundPage(const Extension* extension) { |
316 content::RenderView* render_view = GetCurrentRenderView(); | 315 content::RenderView* render_view = GetCurrentRenderView(); |
317 if (!render_view) | 316 if (!render_view) |
318 return false; | 317 return false; |
319 | 318 |
320 ExtensionHelper* helper = ExtensionHelper::Get(render_view); | 319 ExtensionHelper* helper = ExtensionHelper::Get(render_view); |
321 return (extension && extension->has_lazy_background_page() && | 320 return (extension && BackgroundInfo::HasLazyBackgroundPage(extension) && |
322 helper->view_type() == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); | 321 helper->view_type() == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); |
323 } | 322 } |
324 | 323 |
325 static scoped_ptr<extensions::EventMatcher> ParseEventMatcher( | 324 static scoped_ptr<EventMatcher> ParseEventMatcher( |
326 base::DictionaryValue* filter_dict) { | 325 base::DictionaryValue* filter_dict) { |
327 return scoped_ptr<extensions::EventMatcher>(new extensions::EventMatcher( | 326 return scoped_ptr<EventMatcher>(new EventMatcher( |
328 scoped_ptr<base::DictionaryValue>(filter_dict->DeepCopy()))); | 327 scoped_ptr<base::DictionaryValue>(filter_dict->DeepCopy()))); |
329 } | 328 } |
330 }; | 329 }; |
331 | 330 |
332 } // namespace | 331 } // namespace |
333 | 332 |
334 // static | 333 // static |
335 ChromeV8Extension* EventBindings::Get(Dispatcher* dispatcher) { | 334 ChromeV8Extension* EventBindings::Get(Dispatcher* dispatcher) { |
336 return new ExtensionImpl(dispatcher); | 335 return new ExtensionImpl(dispatcher); |
337 } | 336 } |
338 | 337 |
339 } // namespace extensions | 338 } // namespace extensions |
OLD | NEW |