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 #include <set> | 8 #include <set> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
15 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 16 #include "components/crx_file/id_util.h" |
16 #include "content/public/renderer/render_thread.h" | 17 #include "content/public/renderer/render_thread.h" |
17 #include "content/public/renderer/render_view.h" | 18 #include "content/public/renderer/render_view.h" |
18 #include "content/public/renderer/v8_value_converter.h" | 19 #include "content/public/renderer/v8_value_converter.h" |
19 #include "extensions/common/event_filter.h" | 20 #include "extensions/common/event_filter.h" |
20 #include "extensions/common/extension.h" | 21 #include "extensions/common/extension.h" |
21 #include "extensions/common/extension_messages.h" | 22 #include "extensions/common/extension_messages.h" |
22 #include "extensions/common/manifest_handlers/background_info.h" | 23 #include "extensions/common/manifest_handlers/background_info.h" |
23 #include "extensions/common/value_counter.h" | 24 #include "extensions/common/value_counter.h" |
24 #include "extensions/renderer/dispatcher.h" | 25 #include "extensions/renderer/dispatcher.h" |
25 #include "extensions/renderer/extension_helper.h" | 26 #include "extensions/renderer/extension_helper.h" |
(...skipping 20 matching lines...) Expand all Loading... |
46 // between 0 and 1. | 47 // between 0 and 1. |
47 typedef std::map<std::string, linked_ptr<ValueCounter> > | 48 typedef std::map<std::string, linked_ptr<ValueCounter> > |
48 FilteredEventListenerCounts; | 49 FilteredEventListenerCounts; |
49 | 50 |
50 // A map of extension IDs to filtered listener counts for that extension. | 51 // A map of extension IDs to filtered listener counts for that extension. |
51 base::LazyInstance<std::map<std::string, FilteredEventListenerCounts> > | 52 base::LazyInstance<std::map<std::string, FilteredEventListenerCounts> > |
52 g_filtered_listener_counts = LAZY_INSTANCE_INITIALIZER; | 53 g_filtered_listener_counts = LAZY_INSTANCE_INITIALIZER; |
53 | 54 |
54 base::LazyInstance<EventFilter> g_event_filter = LAZY_INSTANCE_INITIALIZER; | 55 base::LazyInstance<EventFilter> g_event_filter = LAZY_INSTANCE_INITIALIZER; |
55 | 56 |
| 57 std::string GetKeyForScriptContext(ScriptContext* script_context) { |
| 58 const std::string& extension_id = script_context->GetExtensionID(); |
| 59 CHECK(crx_file::id_util::IdIsValid(extension_id) || |
| 60 script_context->GetURL().is_valid()); |
| 61 return crx_file::id_util::IdIsValid(extension_id) |
| 62 ? extension_id |
| 63 : script_context->GetURL().spec(); |
| 64 } |
| 65 |
| 66 // Increments the number of event-listeners for the given |event_name| and |
| 67 // ScriptContext. Returns the count after the increment. |
| 68 int IncrementEventListenerCount(ScriptContext* script_context, |
| 69 const std::string& event_name) { |
| 70 return ++g_listener_counts |
| 71 .Get()[GetKeyForScriptContext(script_context)][event_name]; |
| 72 } |
| 73 |
| 74 // Decrements the number of event-listeners for the given |event_name| and |
| 75 // ScriptContext. Returns the count after the increment. |
| 76 int DecrementEventListenerCount(ScriptContext* script_context, |
| 77 const std::string& event_name) { |
| 78 return --g_listener_counts |
| 79 .Get()[GetKeyForScriptContext(script_context)][event_name]; |
| 80 } |
| 81 |
56 bool IsLazyBackgroundPage(content::RenderView* render_view, | 82 bool IsLazyBackgroundPage(content::RenderView* render_view, |
57 const Extension* extension) { | 83 const Extension* extension) { |
58 if (!render_view) | 84 if (!render_view) |
59 return false; | 85 return false; |
60 ExtensionHelper* helper = ExtensionHelper::Get(render_view); | 86 ExtensionHelper* helper = ExtensionHelper::Get(render_view); |
61 return (extension && BackgroundInfo::HasLazyBackgroundPage(extension) && | 87 return (extension && BackgroundInfo::HasLazyBackgroundPage(extension) && |
62 helper->view_type() == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); | 88 helper->view_type() == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); |
63 } | 89 } |
64 | 90 |
65 EventFilteringInfo ParseFromObject(v8::Handle<v8::Object> object, | 91 EventFilteringInfo ParseFromObject(v8::Handle<v8::Object> object, |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 void EventBindings::AttachEvent( | 166 void EventBindings::AttachEvent( |
141 const v8::FunctionCallbackInfo<v8::Value>& args) { | 167 const v8::FunctionCallbackInfo<v8::Value>& args) { |
142 CHECK_EQ(1, args.Length()); | 168 CHECK_EQ(1, args.Length()); |
143 CHECK(args[0]->IsString()); | 169 CHECK(args[0]->IsString()); |
144 | 170 |
145 std::string event_name = *v8::String::Utf8Value(args[0]); | 171 std::string event_name = *v8::String::Utf8Value(args[0]); |
146 | 172 |
147 if (!dispatcher_->CheckContextAccessToExtensionAPI(event_name, context())) | 173 if (!dispatcher_->CheckContextAccessToExtensionAPI(event_name, context())) |
148 return; | 174 return; |
149 | 175 |
150 std::string extension_id = context()->GetExtensionID(); | 176 const std::string& extension_id = context()->GetExtensionID(); |
151 EventListenerCounts& listener_counts = g_listener_counts.Get()[extension_id]; | 177 if (IncrementEventListenerCount(context(), event_name) == 1) { |
152 if (++listener_counts[event_name] == 1) { | |
153 content::RenderThread::Get()->Send(new ExtensionHostMsg_AddListener( | 178 content::RenderThread::Get()->Send(new ExtensionHostMsg_AddListener( |
154 extension_id, context()->GetURL(), event_name)); | 179 extension_id, context()->GetURL(), event_name)); |
155 } | 180 } |
156 | 181 |
157 // This is called the first time the page has added a listener. Since | 182 // This is called the first time the page has added a listener. Since |
158 // the background page is the only lazy page, we know this is the first | 183 // the background page is the only lazy page, we know this is the first |
159 // time this listener has been registered. | 184 // time this listener has been registered. |
160 if (IsLazyBackgroundPage(context()->GetRenderView(), | 185 if (IsLazyBackgroundPage(context()->GetRenderView(), |
161 context()->extension())) { | 186 context()->extension())) { |
162 content::RenderThread::Get()->Send( | 187 content::RenderThread::Get()->Send( |
163 new ExtensionHostMsg_AddLazyListener(extension_id, event_name)); | 188 new ExtensionHostMsg_AddLazyListener(extension_id, event_name)); |
164 } | 189 } |
165 } | 190 } |
166 | 191 |
167 void EventBindings::DetachEvent( | 192 void EventBindings::DetachEvent( |
168 const v8::FunctionCallbackInfo<v8::Value>& args) { | 193 const v8::FunctionCallbackInfo<v8::Value>& args) { |
169 CHECK_EQ(2, args.Length()); | 194 CHECK_EQ(2, args.Length()); |
170 CHECK(args[0]->IsString()); | 195 CHECK(args[0]->IsString()); |
171 CHECK(args[1]->IsBoolean()); | 196 CHECK(args[1]->IsBoolean()); |
172 | 197 |
173 std::string event_name = *v8::String::Utf8Value(args[0]); | 198 std::string event_name = *v8::String::Utf8Value(args[0]); |
174 bool is_manual = args[1]->BooleanValue(); | 199 bool is_manual = args[1]->BooleanValue(); |
175 | 200 |
176 std::string extension_id = context()->GetExtensionID(); | 201 const std::string& extension_id = context()->GetExtensionID(); |
177 EventListenerCounts& listener_counts = g_listener_counts.Get()[extension_id]; | 202 if (DecrementEventListenerCount(context(), event_name) == 0) { |
178 | |
179 if (--listener_counts[event_name] == 0) { | |
180 content::RenderThread::Get()->Send(new ExtensionHostMsg_RemoveListener( | 203 content::RenderThread::Get()->Send(new ExtensionHostMsg_RemoveListener( |
181 extension_id, context()->GetURL(), event_name)); | 204 extension_id, context()->GetURL(), event_name)); |
182 } | 205 } |
183 | 206 |
184 // DetachEvent is called when the last listener for the context is | 207 // DetachEvent is called when the last listener for the context is |
185 // removed. If the context is the background page, and it removes the | 208 // removed. If the context is the background page, and it removes the |
186 // last listener manually, then we assume that it is no longer interested | 209 // last listener manually, then we assume that it is no longer interested |
187 // in being awakened for this event. | 210 // in being awakened for this event. |
188 if (is_manual && IsLazyBackgroundPage(context()->GetRenderView(), | 211 if (is_manual && IsLazyBackgroundPage(context()->GetRenderView(), |
189 context()->extension())) { | 212 context()->extension())) { |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 } | 318 } |
296 | 319 |
297 scoped_ptr<EventMatcher> EventBindings::ParseEventMatcher( | 320 scoped_ptr<EventMatcher> EventBindings::ParseEventMatcher( |
298 base::DictionaryValue* filter_dict) { | 321 base::DictionaryValue* filter_dict) { |
299 return scoped_ptr<EventMatcher>(new EventMatcher( | 322 return scoped_ptr<EventMatcher>(new EventMatcher( |
300 scoped_ptr<base::DictionaryValue>(filter_dict->DeepCopy()), | 323 scoped_ptr<base::DictionaryValue>(filter_dict->DeepCopy()), |
301 context()->GetRenderView()->GetRoutingID())); | 324 context()->GetRenderView()->GetRoutingID())); |
302 } | 325 } |
303 | 326 |
304 } // namespace extensions | 327 } // namespace extensions |
OLD | NEW |