| 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 |