| OLD | NEW |
| 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 <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.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 "components/crx_file/id_util.h" | 13 #include "components/crx_file/id_util.h" |
| 14 #include "content/public/child/v8_value_converter.h" | 14 #include "content/public/child/v8_value_converter.h" |
| 15 #include "content/public/renderer/render_thread.h" | 15 #include "content/public/renderer/render_thread.h" |
| 16 #include "content/public/renderer/render_view.h" | 16 #include "content/public/renderer/render_view.h" |
| 17 #include "extensions/common/event_filter.h" | 17 #include "extensions/common/event_filter.h" |
| 18 #include "extensions/common/extension.h" | 18 #include "extensions/common/extension.h" |
| 19 #include "extensions/common/extension_messages.h" | 19 #include "extensions/common/extension_messages.h" |
| 20 #include "extensions/common/manifest_handlers/background_info.h" | 20 #include "extensions/common/manifest_handlers/background_info.h" |
| 21 #include "extensions/common/value_counter.h" | 21 #include "extensions/common/value_counter.h" |
| 22 #include "extensions/renderer/extension_helper.h" | 22 #include "extensions/renderer/extension_helper.h" |
| 23 #include "extensions/renderer/script_context.h" | 23 #include "extensions/renderer/script_context.h" |
| 24 #include "extensions/renderer/v8_maybe_helpers.h" |
| 24 #include "url/gurl.h" | 25 #include "url/gurl.h" |
| 25 | 26 |
| 26 namespace extensions { | 27 namespace extensions { |
| 27 | 28 |
| 28 namespace { | 29 namespace { |
| 29 | 30 |
| 30 // A map of event names to the number of contexts listening to that event. | 31 // A map of event names to the number of contexts listening to that event. |
| 31 // We notify the browser about event listeners when we transition between 0 | 32 // We notify the browser about event listeners when we transition between 0 |
| 32 // and 1. | 33 // and 1. |
| 33 typedef std::map<std::string, int> EventListenerCounts; | 34 typedef std::map<std::string, int> EventListenerCounts; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 if (!render_view) | 80 if (!render_view) |
| 80 return false; | 81 return false; |
| 81 ExtensionHelper* helper = ExtensionHelper::Get(render_view); | 82 ExtensionHelper* helper = ExtensionHelper::Get(render_view); |
| 82 return (extension && BackgroundInfo::HasLazyBackgroundPage(extension) && | 83 return (extension && BackgroundInfo::HasLazyBackgroundPage(extension) && |
| 83 helper->view_type() == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); | 84 helper->view_type() == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); |
| 84 } | 85 } |
| 85 | 86 |
| 86 EventFilteringInfo ParseFromObject(v8::Local<v8::Object> object, | 87 EventFilteringInfo ParseFromObject(v8::Local<v8::Object> object, |
| 87 v8::Isolate* isolate) { | 88 v8::Isolate* isolate) { |
| 88 EventFilteringInfo info; | 89 EventFilteringInfo info; |
| 89 v8::Local<v8::String> url(v8::String::NewFromUtf8(isolate, "url")); | 90 v8::Local<v8::String> url(ToV8String(isolate, "url")); |
| 90 if (object->Has(url)) { | 91 v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
| 91 v8::Local<v8::Value> url_value(object->Get(url)); | 92 if (CheckV8Call(object->Has(context, url))) { |
| 93 v8::Local<v8::Value> url_value(UnsafeGet(context, object, url)); |
| 92 info.SetURL(GURL(*v8::String::Utf8Value(url_value))); | 94 info.SetURL(GURL(*v8::String::Utf8Value(url_value))); |
| 93 } | 95 } |
| 94 v8::Local<v8::String> instance_id( | 96 v8::Local<v8::String> instance_id(ToV8String(isolate, "instanceId")); |
| 95 v8::String::NewFromUtf8(isolate, "instanceId")); | 97 if (CheckV8Call(object->Has(context, instance_id))) { |
| 96 if (object->Has(instance_id)) { | 98 v8::Local<v8::Value> instance_id_value( |
| 97 v8::Local<v8::Value> instance_id_value(object->Get(instance_id)); | 99 UnsafeGet(context, object, instance_id)); |
| 98 info.SetInstanceID(instance_id_value->IntegerValue()); | 100 info.SetInstanceID( |
| 101 instance_id_value->IntegerValue(context).FromJust()); |
| 99 } | 102 } |
| 100 v8::Local<v8::String> service_type( | 103 v8::Local<v8::String> service_type(ToV8String(isolate, "serviceType")); |
| 101 v8::String::NewFromUtf8(isolate, "serviceType")); | 104 if (CheckV8Call(object->Has(context, service_type))) { |
| 102 if (object->Has(service_type)) { | 105 v8::Local<v8::Value> service_type_value( |
| 103 v8::Local<v8::Value> service_type_value(object->Get(service_type)); | 106 UnsafeGet(context, object, service_type)); |
| 104 info.SetServiceType(*v8::String::Utf8Value(service_type_value)); | 107 info.SetServiceType(*v8::String::Utf8Value(service_type_value)); |
| 105 } | 108 } |
| 106 return info; | 109 return info; |
| 107 } | 110 } |
| 108 | 111 |
| 109 // Add a filter to |event_name| in |extension_id|, returning true if it | 112 // Add a filter to |event_name| in |extension_id|, returning true if it |
| 110 // was the first filter for that event in that extension. | 113 // was the first filter for that event in that extension. |
| 111 bool AddFilter(const std::string& event_name, | 114 bool AddFilter(const std::string& event_name, |
| 112 const std::string& extension_id, | 115 const std::string& extension_id, |
| 113 base::DictionaryValue* filter) { | 116 base::DictionaryValue* filter) { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 content::RenderThread::Get()->Send( | 197 content::RenderThread::Get()->Send( |
| 195 new ExtensionHostMsg_AddLazyListener(extension_id, event_name)); | 198 new ExtensionHostMsg_AddLazyListener(extension_id, event_name)); |
| 196 } | 199 } |
| 197 } | 200 } |
| 198 | 201 |
| 199 void EventBindings::DetachEventHandler( | 202 void EventBindings::DetachEventHandler( |
| 200 const v8::FunctionCallbackInfo<v8::Value>& args) { | 203 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 201 CHECK_EQ(2, args.Length()); | 204 CHECK_EQ(2, args.Length()); |
| 202 CHECK(args[0]->IsString()); | 205 CHECK(args[0]->IsString()); |
| 203 CHECK(args[1]->IsBoolean()); | 206 CHECK(args[1]->IsBoolean()); |
| 204 DetachEvent(*v8::String::Utf8Value(args[0]), args[1]->BooleanValue()); | 207 DetachEvent(*v8::String::Utf8Value(args[0]), |
| 208 args[1].As<v8::Boolean>()->Value()); |
| 205 } | 209 } |
| 206 | 210 |
| 207 void EventBindings::DetachEvent(const std::string& event_name, bool is_manual) { | 211 void EventBindings::DetachEvent(const std::string& event_name, bool is_manual) { |
| 208 // See comment in AttachEvent(). | 212 // See comment in AttachEvent(). |
| 209 attached_event_names_.erase(event_name); | 213 attached_event_names_.erase(event_name); |
| 210 | 214 |
| 211 const std::string& extension_id = context()->GetExtensionID(); | 215 const std::string& extension_id = context()->GetExtensionID(); |
| 212 | 216 |
| 213 if (DecrementEventListenerCount(context(), event_name) == 0) { | 217 if (DecrementEventListenerCount(context(), event_name) == 0) { |
| 214 content::RenderThread::Get()->Send(new ExtensionHostMsg_RemoveListener( | 218 content::RenderThread::Get()->Send(new ExtensionHostMsg_RemoveListener( |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 } | 278 } |
| 275 | 279 |
| 276 args.GetReturnValue().Set(static_cast<int32_t>(id)); | 280 args.GetReturnValue().Set(static_cast<int32_t>(id)); |
| 277 } | 281 } |
| 278 | 282 |
| 279 void EventBindings::DetachFilteredEvent( | 283 void EventBindings::DetachFilteredEvent( |
| 280 const v8::FunctionCallbackInfo<v8::Value>& args) { | 284 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 281 CHECK_EQ(2, args.Length()); | 285 CHECK_EQ(2, args.Length()); |
| 282 CHECK(args[0]->IsInt32()); | 286 CHECK(args[0]->IsInt32()); |
| 283 CHECK(args[1]->IsBoolean()); | 287 CHECK(args[1]->IsBoolean()); |
| 284 bool is_manual = args[1]->BooleanValue(); | 288 bool is_manual = args[1].As<v8::Boolean>()->Value(); |
| 285 | 289 |
| 286 std::string extension_id = context()->GetExtensionID(); | 290 std::string extension_id = context()->GetExtensionID(); |
| 287 | 291 |
| 288 int matcher_id = args[0]->Int32Value(); | 292 int matcher_id = args[0].As<v8::Int32>()->Value(); |
| 289 EventFilter& event_filter = g_event_filter.Get(); | 293 EventFilter& event_filter = g_event_filter.Get(); |
| 290 EventMatcher* event_matcher = event_filter.GetEventMatcher(matcher_id); | 294 EventMatcher* event_matcher = event_filter.GetEventMatcher(matcher_id); |
| 291 | 295 |
| 292 const std::string& event_name = event_filter.GetEventName(matcher_id); | 296 const std::string& event_name = event_filter.GetEventName(matcher_id); |
| 293 | 297 |
| 294 // Only send IPCs the last time a filter gets removed. | 298 // Only send IPCs the last time a filter gets removed. |
| 295 if (RemoveFilter(event_name, extension_id, event_matcher->value())) { | 299 if (RemoveFilter(event_name, extension_id, event_matcher->value())) { |
| 296 bool lazy = is_manual && IsLazyBackgroundPage(context()->GetRenderView(), | 300 bool lazy = is_manual && IsLazyBackgroundPage(context()->GetRenderView(), |
| 297 context()->extension()); | 301 context()->extension()); |
| 298 content::RenderThread::Get()->Send( | 302 content::RenderThread::Get()->Send( |
| 299 new ExtensionHostMsg_RemoveFilteredListener( | 303 new ExtensionHostMsg_RemoveFilteredListener( |
| 300 extension_id, event_name, *event_matcher->value(), lazy)); | 304 extension_id, event_name, *event_matcher->value(), lazy)); |
| 301 } | 305 } |
| 302 | 306 |
| 303 event_filter.RemoveEventMatcher(matcher_id); | 307 event_filter.RemoveEventMatcher(matcher_id); |
| 304 } | 308 } |
| 305 | 309 |
| 306 void EventBindings::MatchAgainstEventFilter( | 310 void EventBindings::MatchAgainstEventFilter( |
| 307 const v8::FunctionCallbackInfo<v8::Value>& args) { | 311 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 308 v8::Isolate* isolate = args.GetIsolate(); | 312 v8::Isolate* isolate = args.GetIsolate(); |
| 309 typedef std::set<EventFilter::MatcherID> MatcherIDs; | 313 typedef std::set<EventFilter::MatcherID> MatcherIDs; |
| 310 EventFilter& event_filter = g_event_filter.Get(); | 314 EventFilter& event_filter = g_event_filter.Get(); |
| 311 std::string event_name = *v8::String::Utf8Value(args[0]); | 315 std::string event_name = *v8::String::Utf8Value(args[0]); |
| 316 CHECK(args[1]->IsObject()); |
| 312 EventFilteringInfo info = | 317 EventFilteringInfo info = |
| 313 ParseFromObject(args[1]->ToObject(isolate), isolate); | 318 ParseFromObject(args[1].As<v8::Object>(), isolate); |
| 314 // Only match events routed to this context's RenderView or ones that don't | 319 // Only match events routed to this context's RenderView or ones that don't |
| 315 // have a routingId in their filter. | 320 // have a routingId in their filter. |
| 316 MatcherIDs matched_event_filters = event_filter.MatchEvent( | 321 MatcherIDs matched_event_filters = event_filter.MatchEvent( |
| 317 event_name, info, context()->GetRenderView()->GetRoutingID()); | 322 event_name, info, context()->GetRenderView()->GetRoutingID()); |
| 318 v8::Local<v8::Array> array( | 323 v8::Local<v8::Array> array( |
| 319 v8::Array::New(isolate, matched_event_filters.size())); | 324 v8::Array::New(isolate, matched_event_filters.size())); |
| 320 int i = 0; | 325 int i = 0; |
| 321 for (MatcherIDs::iterator it = matched_event_filters.begin(); | 326 for (MatcherIDs::iterator it = matched_event_filters.begin(); |
| 322 it != matched_event_filters.end(); | 327 it != matched_event_filters.end(); |
| 323 ++it) { | 328 ++it) { |
| 324 array->Set(v8::Integer::New(isolate, i++), v8::Integer::New(isolate, *it)); | 329 SetProperty(isolate->GetCurrentContext(), array, |
| 330 v8::Integer::New(isolate, i++), v8::Integer::New(isolate, *it)); |
| 325 } | 331 } |
| 326 args.GetReturnValue().Set(array); | 332 args.GetReturnValue().Set(array); |
| 327 } | 333 } |
| 328 | 334 |
| 329 scoped_ptr<EventMatcher> EventBindings::ParseEventMatcher( | 335 scoped_ptr<EventMatcher> EventBindings::ParseEventMatcher( |
| 330 base::DictionaryValue* filter_dict) { | 336 base::DictionaryValue* filter_dict) { |
| 331 return scoped_ptr<EventMatcher>(new EventMatcher( | 337 return scoped_ptr<EventMatcher>(new EventMatcher( |
| 332 scoped_ptr<base::DictionaryValue>(filter_dict->DeepCopy()), | 338 scoped_ptr<base::DictionaryValue>(filter_dict->DeepCopy()), |
| 333 context()->GetRenderView()->GetRoutingID())); | 339 context()->GetRenderView()->GetRoutingID())); |
| 334 } | 340 } |
| 335 | 341 |
| 336 void EventBindings::OnInvalidated() { | 342 void EventBindings::OnInvalidated() { |
| 337 // Detach all attached events that weren't attached. Iterate over a copy | 343 // Detach all attached events that weren't attached. Iterate over a copy |
| 338 // because it will be mutated. | 344 // because it will be mutated. |
| 339 std::set<std::string> attached_event_names_safe = attached_event_names_; | 345 std::set<std::string> attached_event_names_safe = attached_event_names_; |
| 340 for (const std::string& event_name : attached_event_names_safe) { | 346 for (const std::string& event_name : attached_event_names_safe) { |
| 341 DetachEvent(event_name, false /* is_manual */); | 347 DetachEvent(event_name, false /* is_manual */); |
| 342 } | 348 } |
| 343 DCHECK(attached_event_names_.empty()) | 349 DCHECK(attached_event_names_.empty()) |
| 344 << "Events cannot be attached during invalidation"; | 350 << "Events cannot be attached during invalidation"; |
| 345 } | 351 } |
| 346 | 352 |
| 347 } // namespace extensions | 353 } // namespace extensions |
| OLD | NEW |