Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(214)

Side by Side Diff: chrome/renderer/extensions/event_bindings.cc

Issue 11571014: Lazy load chrome.* APIs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: android compilation Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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"
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 65
66 // 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.
67 base::LazyInstance<std::map<std::string, FilteredEventListenerCounts> > 67 base::LazyInstance<std::map<std::string, FilteredEventListenerCounts> >
68 g_filtered_listener_counts = LAZY_INSTANCE_INITIALIZER; 68 g_filtered_listener_counts = LAZY_INSTANCE_INITIALIZER;
69 69
70 base::LazyInstance<EventFilter> g_event_filter = LAZY_INSTANCE_INITIALIZER; 70 base::LazyInstance<EventFilter> g_event_filter = 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 v8::Handle<v8::Context> v8_context)
77 : ChromeV8Extension(dispatcher, v8_context) {
77 RouteStaticFunction("AttachEvent", &AttachEvent); 78 RouteStaticFunction("AttachEvent", &AttachEvent);
78 RouteStaticFunction("DetachEvent", &DetachEvent); 79 RouteStaticFunction("DetachEvent", &DetachEvent);
79 RouteStaticFunction("AttachFilteredEvent", &AttachFilteredEvent); 80 RouteStaticFunction("AttachFilteredEvent", &AttachFilteredEvent);
80 RouteStaticFunction("DetachFilteredEvent", &DetachFilteredEvent); 81 RouteStaticFunction("DetachFilteredEvent", &DetachFilteredEvent);
81 RouteStaticFunction("MatchAgainstEventFilter", &MatchAgainstEventFilter); 82 RouteStaticFunction("MatchAgainstEventFilter", &MatchAgainstEventFilter);
82 } 83 }
83 84
84 virtual ~ExtensionImpl() {} 85 virtual ~ExtensionImpl() {}
85 86
86 // Attach an event name to an object. 87 // Attach an event name to an object.
87 static v8::Handle<v8::Value> AttachEvent(const v8::Arguments& args) { 88 static v8::Handle<v8::Value> AttachEvent(const v8::Arguments& args) {
88 DCHECK(args.Length() == 1); 89 DCHECK(args.Length() == 1);
89 // TODO(erikkay) should enforce that event name is a string in the bindings 90 // TODO(erikkay) should enforce that event name is a string in the bindings
90 DCHECK(args[0]->IsString() || args[0]->IsUndefined()); 91 DCHECK(args[0]->IsString() || args[0]->IsUndefined());
91 92
92 if (args[0]->IsString()) { 93 if (args[0]->IsString()) {
93 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); 94 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
94 std::string event_name = *v8::String::AsciiValue(args[0]->ToString()); 95 std::string event_name = *v8::String::AsciiValue(args[0]->ToString());
95 Dispatcher* dispatcher = self->dispatcher(); 96 Dispatcher* dispatcher = self->dispatcher();
96 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set(); 97 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set();
97 ChromeV8Context* context = context_set.GetCurrent(); 98 ChromeV8Context* context = context_set.GetByV8Context(self->v8_context());
98 CHECK(context); 99 CHECK(context);
99 100
100 if (!dispatcher->CheckCurrentContextAccessToExtensionAPI(event_name)) 101 if (!dispatcher->CheckContextAccessToExtensionAPI(event_name, context))
101 return v8::Undefined(); 102 return v8::Undefined();
102 103
103 std::string extension_id = context->GetExtensionID(); 104 std::string extension_id = context->GetExtensionID();
104 EventListenerCounts& listener_counts = 105 EventListenerCounts& listener_counts =
105 g_listener_counts.Get()[extension_id]; 106 g_listener_counts.Get()[extension_id];
106 if (++listener_counts[event_name] == 1) { 107 if (++listener_counts[event_name] == 1) {
107 content::RenderThread::Get()->Send( 108 content::RenderThread::Get()->Send(
108 new ExtensionHostMsg_AddListener(extension_id, event_name)); 109 new ExtensionHostMsg_AddListener(extension_id, event_name));
109 } 110 }
110 111
111 // This is called the first time the page has added a listener. Since 112 // This is called the first time the page has added a listener. Since
112 // the background page is the only lazy page, we know this is the first 113 // the background page is the only lazy page, we know this is the first
113 // time this listener has been registered. 114 // time this listener has been registered.
114 if (IsLazyBackgroundPage(context->extension())) { 115 if (IsLazyBackgroundPage(self->GetRenderView(), context->extension())) {
115 content::RenderThread::Get()->Send( 116 content::RenderThread::Get()->Send(
116 new ExtensionHostMsg_AddLazyListener(extension_id, event_name)); 117 new ExtensionHostMsg_AddLazyListener(extension_id, event_name));
117 } 118 }
118 } 119 }
119 return v8::Undefined(); 120 return v8::Undefined();
120 } 121 }
121 122
122 static v8::Handle<v8::Value> DetachEvent(const v8::Arguments& args) { 123 static v8::Handle<v8::Value> DetachEvent(const v8::Arguments& args) {
123 DCHECK(args.Length() == 2); 124 DCHECK(args.Length() == 2);
124 // TODO(erikkay) should enforce that event name is a string in the bindings 125 // TODO(erikkay) should enforce that event name is a string in the bindings
125 DCHECK(args[0]->IsString() || args[0]->IsUndefined()); 126 DCHECK(args[0]->IsString() || args[0]->IsUndefined());
126 127
127 if (args[0]->IsString() && args[1]->IsBoolean()) { 128 if (args[0]->IsString() && args[1]->IsBoolean()) {
128 std::string event_name = *v8::String::AsciiValue(args[0]->ToString()); 129 std::string event_name = *v8::String::AsciiValue(args[0]->ToString());
129 bool is_manual = args[1]->BooleanValue(); 130 bool is_manual = args[1]->BooleanValue();
130 131
131 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); 132 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
132 Dispatcher* dispatcher = self->dispatcher(); 133 Dispatcher* dispatcher = self->dispatcher();
133 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set(); 134 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set();
134 ChromeV8Context* context = context_set.GetCurrent(); 135 ChromeV8Context* context = context_set.GetByV8Context(self->v8_context());
135 if (!context) 136 if (!context)
136 return v8::Undefined(); 137 return v8::Undefined();
137 138
138 std::string extension_id = context->GetExtensionID(); 139 std::string extension_id = context->GetExtensionID();
139 EventListenerCounts& listener_counts = 140 EventListenerCounts& listener_counts =
140 g_listener_counts.Get()[extension_id]; 141 g_listener_counts.Get()[extension_id];
141 142
142 if (--listener_counts[event_name] == 0) { 143 if (--listener_counts[event_name] == 0) {
143 content::RenderThread::Get()->Send( 144 content::RenderThread::Get()->Send(
144 new ExtensionHostMsg_RemoveListener(extension_id, event_name)); 145 new ExtensionHostMsg_RemoveListener(extension_id, event_name));
145 } 146 }
146 147
147 // DetachEvent is called when the last listener for the context is 148 // DetachEvent is called when the last listener for the context is
148 // removed. If the context is the background page, and it removes the 149 // removed. If the context is the background page, and it removes the
149 // last listener manually, then we assume that it is no longer interested 150 // last listener manually, then we assume that it is no longer interested
150 // in being awakened for this event. 151 // in being awakened for this event.
151 if (is_manual && IsLazyBackgroundPage(context->extension())) { 152 if (is_manual && IsLazyBackgroundPage(self->GetRenderView(),
153 context->extension())) {
152 content::RenderThread::Get()->Send( 154 content::RenderThread::Get()->Send(
153 new ExtensionHostMsg_RemoveLazyListener(extension_id, event_name)); 155 new ExtensionHostMsg_RemoveLazyListener(extension_id, event_name));
154 } 156 }
155 } 157 }
156 return v8::Undefined(); 158 return v8::Undefined();
157 } 159 }
158 160
159 // MatcherID AttachFilteredEvent(string event_name, object filter) 161 // MatcherID AttachFilteredEvent(string event_name, object filter)
160 // event_name - Name of the event to attach. 162 // event_name - Name of the event to attach.
161 // filter - Which instances of the named event are we interested in. 163 // filter - Which instances of the named event are we interested in.
162 // returns the id assigned to the listener, which will be returned from calls 164 // returns the id assigned to the listener, which will be returned from calls
163 // to MatchAgainstEventFilter where this listener matches. 165 // to MatchAgainstEventFilter where this listener matches.
164 static v8::Handle<v8::Value> AttachFilteredEvent(const v8::Arguments& args) { 166 static v8::Handle<v8::Value> AttachFilteredEvent(const v8::Arguments& args) {
165 DCHECK_EQ(2, args.Length()); 167 DCHECK_EQ(2, args.Length());
166 DCHECK(args[0]->IsString()); 168 DCHECK(args[0]->IsString());
167 DCHECK(args[1]->IsObject()); 169 DCHECK(args[1]->IsObject());
168 170
169 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); 171 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
170 Dispatcher* dispatcher = self->dispatcher(); 172 Dispatcher* dispatcher = self->dispatcher();
171 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set(); 173 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set();
172 ChromeV8Context* context = context_set.GetCurrent(); 174 ChromeV8Context* context = context_set.GetByV8Context(self->v8_context());
173 DCHECK(context); 175 DCHECK(context);
174 if (!context) 176 if (!context)
175 return v8::Integer::New(-1); 177 return v8::Integer::New(-1);
176 178
177 std::string event_name = *v8::String::AsciiValue(args[0]); 179 std::string event_name = *v8::String::AsciiValue(args[0]);
178 // This method throws an exception if it returns false. 180 // This method throws an exception if it returns false.
179 if (!dispatcher->CheckCurrentContextAccessToExtensionAPI(event_name)) 181 if (!dispatcher->CheckContextAccessToExtensionAPI(event_name, context))
180 return v8::Undefined(); 182 return v8::Undefined();
181 183
182 std::string extension_id = context->GetExtensionID(); 184 std::string extension_id = context->GetExtensionID();
183 if (extension_id.empty()) 185 if (extension_id.empty())
184 return v8::Integer::New(-1); 186 return v8::Integer::New(-1);
185 187
186 scoped_ptr<base::DictionaryValue> filter; 188 scoped_ptr<base::DictionaryValue> filter;
187 scoped_ptr<content::V8ValueConverter> converter( 189 scoped_ptr<content::V8ValueConverter> converter(
188 content::V8ValueConverter::create()); 190 content::V8ValueConverter::create());
189 191
190 base::DictionaryValue* filter_dict = NULL; 192 base::DictionaryValue* filter_dict = NULL;
191 base::Value* filter_value = converter->FromV8Value(args[1]->ToObject(), 193 base::Value* filter_value =
192 v8::Context::GetCurrent()); 194 converter->FromV8Value(args[1]->ToObject(), context->v8_context());
193 if (!filter_value) 195 if (!filter_value)
194 return v8::Integer::New(-1); 196 return v8::Integer::New(-1);
195 if (!filter_value->GetAsDictionary(&filter_dict)) { 197 if (!filter_value->GetAsDictionary(&filter_dict)) {
196 delete filter_value; 198 delete filter_value;
197 return v8::Integer::New(-1); 199 return v8::Integer::New(-1);
198 } 200 }
199 201
200 filter.reset(filter_dict); 202 filter.reset(filter_dict);
201 EventFilter& event_filter = g_event_filter.Get(); 203 EventFilter& event_filter = g_event_filter.Get();
202 int id = event_filter.AddEventMatcher(event_name, ParseEventMatcher( 204 int id = event_filter.AddEventMatcher(event_name, ParseEventMatcher(
203 filter.get())); 205 filter.get()));
204 206
205 // Only send IPCs the first time a filter gets added. 207 // Only send IPCs the first time a filter gets added.
206 if (AddFilter(event_name, extension_id, filter.get())) { 208 if (AddFilter(event_name, extension_id, filter.get())) {
207 bool lazy = IsLazyBackgroundPage(context->extension()); 209 bool lazy = IsLazyBackgroundPage(self->GetRenderView(),
210 context->extension());
208 content::RenderThread::Get()->Send( 211 content::RenderThread::Get()->Send(
209 new ExtensionHostMsg_AddFilteredListener(extension_id, event_name, 212 new ExtensionHostMsg_AddFilteredListener(extension_id, event_name,
210 *filter, lazy)); 213 *filter, lazy));
211 } 214 }
212 215
213 return v8::Integer::New(id); 216 return v8::Integer::New(id);
214 } 217 }
215 218
216 // Add a filter to |event_name| in |extension_id|, returning true if it 219 // Add a filter to |event_name| in |extension_id|, returning true if it
217 // was the first filter for that event in that extension. 220 // was the first filter for that event in that extension.
(...skipping 28 matching lines...) Expand all
246 // manual - false if this is part of the extension unload process where all 249 // manual - false if this is part of the extension unload process where all
247 // listeners are automatically detached. 250 // listeners are automatically detached.
248 static v8::Handle<v8::Value> DetachFilteredEvent(const v8::Arguments& args) { 251 static v8::Handle<v8::Value> DetachFilteredEvent(const v8::Arguments& args) {
249 DCHECK_EQ(2, args.Length()); 252 DCHECK_EQ(2, args.Length());
250 DCHECK(args[0]->IsInt32()); 253 DCHECK(args[0]->IsInt32());
251 DCHECK(args[1]->IsBoolean()); 254 DCHECK(args[1]->IsBoolean());
252 bool is_manual = args[1]->BooleanValue(); 255 bool is_manual = args[1]->BooleanValue();
253 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); 256 ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args);
254 Dispatcher* dispatcher = self->dispatcher(); 257 Dispatcher* dispatcher = self->dispatcher();
255 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set(); 258 const ChromeV8ContextSet& context_set = dispatcher->v8_context_set();
256 ChromeV8Context* context = context_set.GetCurrent(); 259 ChromeV8Context* context = context_set.GetByV8Context(self->v8_context());
257 if (!context) 260 if (!context)
258 return v8::Undefined(); 261 return v8::Undefined();
259 262
260 std::string extension_id = context->GetExtensionID(); 263 std::string extension_id = context->GetExtensionID();
261 if (extension_id.empty()) 264 if (extension_id.empty())
262 return v8::Undefined(); 265 return v8::Undefined();
263 266
264 int matcher_id = args[0]->Int32Value(); 267 int matcher_id = args[0]->Int32Value();
265 EventFilter& event_filter = g_event_filter.Get(); 268 EventFilter& event_filter = g_event_filter.Get();
266 EventMatcher* event_matcher = 269 EventMatcher* event_matcher =
267 event_filter.GetEventMatcher(matcher_id); 270 event_filter.GetEventMatcher(matcher_id);
268 271
269 const std::string& event_name = event_filter.GetEventName(matcher_id); 272 const std::string& event_name = event_filter.GetEventName(matcher_id);
270 273
271 // Only send IPCs the last time a filter gets removed. 274 // Only send IPCs the last time a filter gets removed.
272 if (RemoveFilter(event_name, extension_id, event_matcher->value())) { 275 if (RemoveFilter(event_name, extension_id, event_matcher->value())) {
273 bool lazy = is_manual && IsLazyBackgroundPage(context->extension()); 276 bool lazy = is_manual && IsLazyBackgroundPage(self->GetRenderView(),
277 context->extension());
274 content::RenderThread::Get()->Send( 278 content::RenderThread::Get()->Send(
275 new ExtensionHostMsg_RemoveFilteredListener(extension_id, event_name, 279 new ExtensionHostMsg_RemoveFilteredListener(extension_id, event_name,
276 *event_matcher->value(), 280 *event_matcher->value(),
277 lazy)); 281 lazy));
278 } 282 }
279 283
280 event_filter.RemoveEventMatcher(matcher_id); 284 event_filter.RemoveEventMatcher(matcher_id);
281 285
282 return v8::Undefined(); 286 return v8::Undefined();
283 } 287 }
(...skipping 20 matching lines...) Expand all
304 EventFilteringInfo info; 308 EventFilteringInfo info;
305 v8::Handle<v8::String> url(v8::String::New("url")); 309 v8::Handle<v8::String> url(v8::String::New("url"));
306 if (object->Has(url)) { 310 if (object->Has(url)) {
307 v8::Handle<v8::Value> url_value(object->Get(url)); 311 v8::Handle<v8::Value> url_value(object->Get(url));
308 info.SetURL(GURL(*v8::String::AsciiValue(url_value))); 312 info.SetURL(GURL(*v8::String::AsciiValue(url_value)));
309 } 313 }
310 return info; 314 return info;
311 } 315 }
312 316
313 private: 317 private:
314 static bool IsLazyBackgroundPage(const Extension* extension) { 318 static bool IsLazyBackgroundPage(content::RenderView* render_view,
315 content::RenderView* render_view = GetCurrentRenderView(); 319 const Extension* extension) {
316 if (!render_view) 320 if (!render_view)
317 return false; 321 return false;
318
319 ExtensionHelper* helper = ExtensionHelper::Get(render_view); 322 ExtensionHelper* helper = ExtensionHelper::Get(render_view);
320 return (extension && BackgroundInfo::HasLazyBackgroundPage(extension) && 323 return (extension && BackgroundInfo::HasLazyBackgroundPage(extension) &&
321 helper->view_type() == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); 324 helper->view_type() == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
322 } 325 }
323 326
324 static scoped_ptr<EventMatcher> ParseEventMatcher( 327 static scoped_ptr<EventMatcher> ParseEventMatcher(
325 base::DictionaryValue* filter_dict) { 328 base::DictionaryValue* filter_dict) {
326 return scoped_ptr<EventMatcher>(new EventMatcher( 329 return scoped_ptr<EventMatcher>(new EventMatcher(
327 scoped_ptr<base::DictionaryValue>(filter_dict->DeepCopy()))); 330 scoped_ptr<base::DictionaryValue>(filter_dict->DeepCopy())));
328 } 331 }
329 }; 332 };
330 333
331 } // namespace 334 } // namespace
332 335
333 // static 336 // static
334 ChromeV8Extension* EventBindings::Get(Dispatcher* dispatcher) { 337 ChromeV8Extension* EventBindings::Create(Dispatcher* dispatcher,
335 return new ExtensionImpl(dispatcher); 338 v8::Handle<v8::Context> context) {
339 return new ExtensionImpl(dispatcher, context);
336 } 340 }
337 341
338 } // namespace extensions 342 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/renderer/extensions/event_bindings.h ('k') | chrome/renderer/extensions/event_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698