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

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

Issue 2973903002: [Extensions Bindings] Introduce a supportsLazyListeners property (Closed)
Patch Set: . Created 3 years, 5 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
OLDNEW
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 <stdint.h> 7 #include <stdint.h>
8 8
9 #include <map> 9 #include <map>
10 #include <memory> 10 #include <memory>
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 context->v8_context()), 222 context->v8_context()),
223 listener_ids, 223 listener_ids,
224 }; 224 };
225 225
226 context->module_system()->CallModuleMethodSafe( 226 context->module_system()->CallModuleMethodSafe(
227 kEventBindings, "dispatchEvent", arraysize(v8_args), v8_args); 227 kEventBindings, "dispatchEvent", arraysize(v8_args), v8_args);
228 } 228 }
229 229
230 void EventBindings::AttachEventHandler( 230 void EventBindings::AttachEventHandler(
231 const v8::FunctionCallbackInfo<v8::Value>& args) { 231 const v8::FunctionCallbackInfo<v8::Value>& args) {
232 CHECK_EQ(1, args.Length()); 232 CHECK_EQ(2, args.Length());
233 CHECK(args[0]->IsString()); 233 CHECK(args[0]->IsString());
234 AttachEvent(*v8::String::Utf8Value(args[0])); 234 CHECK(args[1]->IsBoolean());
235 AttachEvent(*v8::String::Utf8Value(args[0]), args[1]->BooleanValue());
235 } 236 }
236 237
237 void EventBindings::AttachEvent(const std::string& event_name) { 238 void EventBindings::AttachEvent(const std::string& event_name,
239 bool supports_lazy_events) {
238 if (!context()->HasAccessOrThrowError(event_name)) 240 if (!context()->HasAccessOrThrowError(event_name))
239 return; 241 return;
240 242
241 // Record the attachment for this context so that events can be detached when 243 // Record the attachment for this context so that events can be detached when
242 // the context is destroyed. 244 // the context is destroyed.
243 // 245 //
244 // Ideally we'd CHECK that it's not already attached, however that's not 246 // Ideally we'd CHECK that it's not already attached, however that's not
245 // possible because extensions can create and attach events themselves. Very 247 // possible because extensions can create and attach events themselves. Very
246 // silly, but that's the way it is. For an example of this, see 248 // silly, but that's the way it is. For an example of this, see
247 // chrome/test/data/extensions/api_test/events/background.js. 249 // chrome/test/data/extensions/api_test/events/background.js.
(...skipping 11 matching lines...) Expand all
259 : context()->url(), 261 : context()->url(),
260 event_name, worker_thread_id)); 262 event_name, worker_thread_id));
261 } 263 }
262 264
263 // This is called the first time the page has added a listener. Since 265 // This is called the first time the page has added a listener. Since
264 // the background page is the only lazy page, we know this is the first 266 // the background page is the only lazy page, we know this is the first
265 // time this listener has been registered. 267 // time this listener has been registered.
266 bool is_lazy_context = 268 bool is_lazy_context =
267 ExtensionFrameHelper::IsContextForEventPage(context()) || 269 ExtensionFrameHelper::IsContextForEventPage(context()) ||
268 context()->context_type() == Feature::SERVICE_WORKER_CONTEXT; 270 context()->context_type() == Feature::SERVICE_WORKER_CONTEXT;
269 if (is_lazy_context) { 271 if (is_lazy_context && supports_lazy_events) {
270 if (is_service_worker_context) { 272 if (is_service_worker_context) {
271 sender->Send(new ExtensionHostMsg_AddLazyServiceWorkerListener( 273 sender->Send(new ExtensionHostMsg_AddLazyServiceWorkerListener(
272 extension_id, event_name, context()->service_worker_scope())); 274 extension_id, event_name, context()->service_worker_scope()));
273 } else { 275 } else {
274 sender->Send( 276 sender->Send(
275 new ExtensionHostMsg_AddLazyListener(extension_id, event_name)); 277 new ExtensionHostMsg_AddLazyListener(extension_id, event_name));
276 } 278 }
277 } 279 }
278 } 280 }
279 281
280 void EventBindings::DetachEventHandler( 282 void EventBindings::DetachEventHandler(
281 const v8::FunctionCallbackInfo<v8::Value>& args) { 283 const v8::FunctionCallbackInfo<v8::Value>& args) {
282 CHECK_EQ(2, args.Length()); 284 CHECK_EQ(3, args.Length());
283 CHECK(args[0]->IsString()); 285 CHECK(args[0]->IsString());
284 CHECK(args[1]->IsBoolean()); 286 CHECK(args[1]->IsBoolean());
285 DetachEvent(*v8::String::Utf8Value(args[0]), args[1]->BooleanValue()); 287 CHECK(args[2]->IsBoolean());
288 bool was_manual = args[1]->BooleanValue();
289 bool supports_lazy_listeners = args[2]->BooleanValue();
290 DetachEvent(*v8::String::Utf8Value(args[0]),
291 was_manual && supports_lazy_listeners);
286 } 292 }
287 293
288 void EventBindings::DetachEvent(const std::string& event_name, bool is_manual) { 294 void EventBindings::DetachEvent(const std::string& event_name,
295 bool remove_lazy_listener) {
289 // See comment in AttachEvent(). 296 // See comment in AttachEvent().
290 attached_event_names_.erase(event_name); 297 attached_event_names_.erase(event_name);
291 298
292 int worker_thread_id = content::WorkerThread::GetCurrentId(); 299 int worker_thread_id = content::WorkerThread::GetCurrentId();
293 const bool is_service_worker_context = worker_thread_id != kNonWorkerThreadId; 300 const bool is_service_worker_context = worker_thread_id != kNonWorkerThreadId;
294 IPC::Sender* sender = GetIPCSender(); 301 IPC::Sender* sender = GetIPCSender();
295 const std::string& extension_id = context()->GetExtensionID(); 302 const std::string& extension_id = context()->GetExtensionID();
296 303
297 if (DecrementEventListenerCount(context(), event_name) == 0) { 304 if (DecrementEventListenerCount(context(), event_name) == 0) {
298 sender->Send(new ExtensionHostMsg_RemoveListener( 305 sender->Send(new ExtensionHostMsg_RemoveListener(
299 extension_id, 306 extension_id,
300 is_service_worker_context ? context()->service_worker_scope() 307 is_service_worker_context ? context()->service_worker_scope()
301 : context()->url(), 308 : context()->url(),
302 event_name, worker_thread_id)); 309 event_name, worker_thread_id));
303 } 310 }
304 311
305 // DetachEvent is called when the last listener for the context is 312 // DetachEvent is called when the last listener for the context is
306 // removed. If the context is the background page or service worker, and it 313 // removed. If the context is the background page or service worker, and it
307 // removes the last listener manually, then we assume that it is no longer 314 // removes the last listener manually, then we assume that it is no longer
308 // interested in being awakened for this event. 315 // interested in being awakened for this event.
309 if (is_manual) { 316 if (remove_lazy_listener) {
310 bool is_lazy_context = 317 bool is_lazy_context =
311 ExtensionFrameHelper::IsContextForEventPage(context()) || 318 ExtensionFrameHelper::IsContextForEventPage(context()) ||
312 context()->context_type() == Feature::SERVICE_WORKER_CONTEXT; 319 context()->context_type() == Feature::SERVICE_WORKER_CONTEXT;
313 if (is_lazy_context) { 320 if (is_lazy_context) {
314 if (is_service_worker_context) { 321 if (is_service_worker_context) {
315 sender->Send(new ExtensionHostMsg_RemoveLazyServiceWorkerListener( 322 sender->Send(new ExtensionHostMsg_RemoveLazyServiceWorkerListener(
316 extension_id, event_name, context()->service_worker_scope())); 323 extension_id, event_name, context()->service_worker_scope()));
317 } else { 324 } else {
318 sender->Send( 325 sender->Send(
319 new ExtensionHostMsg_RemoveLazyListener(extension_id, event_name)); 326 new ExtensionHostMsg_RemoveLazyListener(extension_id, event_name));
320 } 327 }
321 } 328 }
322 } 329 }
323 } 330 }
324 331
325 // MatcherID AttachFilteredEvent(string event_name, object filter) 332 // MatcherID AttachFilteredEvent(string event_name, object filter)
326 // event_name - Name of the event to attach. 333 // event_name - Name of the event to attach.
327 // filter - Which instances of the named event are we interested in. 334 // filter - Which instances of the named event are we interested in.
328 // returns the id assigned to the listener, which will be provided to calls to 335 // returns the id assigned to the listener, which will be provided to calls to
329 // dispatchEvent(). 336 // dispatchEvent().
330 void EventBindings::AttachFilteredEvent( 337 void EventBindings::AttachFilteredEvent(
331 const v8::FunctionCallbackInfo<v8::Value>& args) { 338 const v8::FunctionCallbackInfo<v8::Value>& args) {
332 CHECK_EQ(2, args.Length()); 339 CHECK_EQ(3, args.Length());
333 CHECK(args[0]->IsString()); 340 CHECK(args[0]->IsString());
334 CHECK(args[1]->IsObject()); 341 CHECK(args[1]->IsObject());
342 CHECK(args[2]->IsBoolean());
335 343
336 std::string event_name = *v8::String::Utf8Value(args[0]); 344 std::string event_name = *v8::String::Utf8Value(args[0]);
337 if (!context()->HasAccessOrThrowError(event_name)) 345 if (!context()->HasAccessOrThrowError(event_name))
338 return; 346 return;
339 347
340 std::unique_ptr<base::DictionaryValue> filter; 348 std::unique_ptr<base::DictionaryValue> filter;
341 { 349 {
342 std::unique_ptr<base::Value> filter_value = 350 std::unique_ptr<base::Value> filter_value =
343 content::V8ValueConverter::Create()->FromV8Value( 351 content::V8ValueConverter::Create()->FromV8Value(
344 v8::Local<v8::Object>::Cast(args[1]), context()->v8_context()); 352 v8::Local<v8::Object>::Cast(args[1]), context()->v8_context());
345 if (!filter_value || !filter_value->IsType(base::Value::Type::DICTIONARY)) { 353 if (!filter_value || !filter_value->IsType(base::Value::Type::DICTIONARY)) {
346 args.GetReturnValue().Set(static_cast<int32_t>(-1)); 354 args.GetReturnValue().Set(static_cast<int32_t>(-1));
347 return; 355 return;
348 } 356 }
349 filter = base::DictionaryValue::From(std::move(filter_value)); 357 filter = base::DictionaryValue::From(std::move(filter_value));
350 } 358 }
351 359
360 bool supports_lazy_events = args[2]->BooleanValue();
361
352 int id = g_event_filter.Get().AddEventMatcher( 362 int id = g_event_filter.Get().AddEventMatcher(
353 event_name, 363 event_name,
354 base::MakeUnique<EventMatcher>( 364 base::MakeUnique<EventMatcher>(
355 std::move(filter), context()->GetRenderFrame()->GetRoutingID())); 365 std::move(filter), context()->GetRenderFrame()->GetRoutingID()));
356 if (id == -1) { 366 if (id == -1) {
357 args.GetReturnValue().Set(static_cast<int32_t>(-1)); 367 args.GetReturnValue().Set(static_cast<int32_t>(-1));
358 return; 368 return;
359 } 369 }
360 attached_matcher_ids_.insert(id); 370 attached_matcher_ids_.insert(id);
361 371
362 // Only send IPCs the first time a filter gets added. 372 // Only send IPCs the first time a filter gets added.
363 const EventMatcher* matcher = g_event_filter.Get().GetEventMatcher(id); 373 const EventMatcher* matcher = g_event_filter.Get().GetEventMatcher(id);
364 DCHECK(matcher); 374 DCHECK(matcher);
365 base::DictionaryValue* filter_weak = matcher->value(); 375 base::DictionaryValue* filter_weak = matcher->value();
366 std::string extension_id = context()->GetExtensionID(); 376 std::string extension_id = context()->GetExtensionID();
367 if (AddFilter(event_name, extension_id, *filter_weak)) { 377 if (AddFilter(event_name, extension_id, *filter_weak)) {
368 bool lazy = ExtensionFrameHelper::IsContextForEventPage(context()); 378 bool lazy = supports_lazy_events &&
379 ExtensionFrameHelper::IsContextForEventPage(context());
369 content::RenderThread::Get()->Send(new ExtensionHostMsg_AddFilteredListener( 380 content::RenderThread::Get()->Send(new ExtensionHostMsg_AddFilteredListener(
370 extension_id, event_name, *filter_weak, lazy)); 381 extension_id, event_name, *filter_weak, lazy));
371 } 382 }
372 383
373 args.GetReturnValue().Set(static_cast<int32_t>(id)); 384 args.GetReturnValue().Set(static_cast<int32_t>(id));
374 } 385 }
375 386
376 void EventBindings::DetachFilteredEventHandler( 387 void EventBindings::DetachFilteredEventHandler(
377 const v8::FunctionCallbackInfo<v8::Value>& args) { 388 const v8::FunctionCallbackInfo<v8::Value>& args) {
378 CHECK_EQ(2, args.Length()); 389 CHECK_EQ(3, args.Length());
379 CHECK(args[0]->IsInt32()); 390 CHECK(args[0]->IsInt32());
380 CHECK(args[1]->IsBoolean()); 391 CHECK(args[1]->IsBoolean());
381 DetachFilteredEvent(args[0]->Int32Value(), args[1]->BooleanValue()); 392 CHECK(args[2]->IsBoolean());
393 bool was_manual = args[1]->BooleanValue();
394 bool supports_lazy_events = args[2]->BooleanValue();
395 DetachFilteredEvent(args[0]->Int32Value(),
396 was_manual && supports_lazy_events);
382 } 397 }
383 398
384 void EventBindings::DetachFilteredEvent(int matcher_id, bool is_manual) { 399 void EventBindings::DetachFilteredEvent(int matcher_id,
400 bool remove_lazy_event) {
385 EventFilter& event_filter = g_event_filter.Get(); 401 EventFilter& event_filter = g_event_filter.Get();
386 EventMatcher* event_matcher = event_filter.GetEventMatcher(matcher_id); 402 EventMatcher* event_matcher = event_filter.GetEventMatcher(matcher_id);
387 403
388 const std::string& event_name = event_filter.GetEventName(matcher_id); 404 const std::string& event_name = event_filter.GetEventName(matcher_id);
389 405
390 // Only send IPCs the last time a filter gets removed. 406 // Only send IPCs the last time a filter gets removed.
391 std::string extension_id = context()->GetExtensionID(); 407 std::string extension_id = context()->GetExtensionID();
392 if (RemoveFilter(event_name, extension_id, event_matcher->value())) { 408 if (RemoveFilter(event_name, extension_id, event_matcher->value())) {
393 bool remove_lazy = 409 bool remove_lazy = remove_lazy_event &&
394 is_manual && ExtensionFrameHelper::IsContextForEventPage(context()); 410 ExtensionFrameHelper::IsContextForEventPage(context());
395 content::RenderThread::Get()->Send( 411 content::RenderThread::Get()->Send(
396 new ExtensionHostMsg_RemoveFilteredListener( 412 new ExtensionHostMsg_RemoveFilteredListener(
397 extension_id, event_name, *event_matcher->value(), remove_lazy)); 413 extension_id, event_name, *event_matcher->value(), remove_lazy));
398 } 414 }
399 415
400 event_filter.RemoveEventMatcher(matcher_id); 416 event_filter.RemoveEventMatcher(matcher_id);
401 attached_matcher_ids_.erase(matcher_id); 417 attached_matcher_ids_.erase(matcher_id);
402 } 418 }
403 419
404 void EventBindings::AttachUnmanagedEvent( 420 void EventBindings::AttachUnmanagedEvent(
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 for (int matcher_id : attached_matcher_ids_safe) { 462 for (int matcher_id : attached_matcher_ids_safe) {
447 DetachFilteredEvent(matcher_id, false /* is_manual */); 463 DetachFilteredEvent(matcher_id, false /* is_manual */);
448 } 464 }
449 DCHECK(attached_matcher_ids_.empty()) 465 DCHECK(attached_matcher_ids_.empty())
450 << "Filtered events cannot be attached during invalidation"; 466 << "Filtered events cannot be attached during invalidation";
451 467
452 g_unmanaged_listeners.Get().erase(context()); 468 g_unmanaged_listeners.Get().erase(context());
453 } 469 }
454 470
455 } // namespace extensions 471 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698