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 |