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

Side by Side Diff: extensions/renderer/resources/event.js

Issue 1074273002: Move the event attach/detach logic on unload from event.js to (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix memory leak Created 5 years, 8 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 var exceptionHandler = require('uncaught_exception_handler'); 5 var exceptionHandler = require('uncaught_exception_handler');
6 var eventNatives = requireNative('event_natives'); 6 var eventNatives = requireNative('event_natives');
7 var logging = requireNative('logging'); 7 var logging = requireNative('logging');
8 var schemaRegistry = requireNative('schema_registry'); 8 var schemaRegistry = requireNative('schema_registry');
9 var sendRequest = require('sendRequest').sendRequest; 9 var sendRequest = require('sendRequest').sendRequest;
10 var utils = require('utils'); 10 var utils = require('utils');
11 var validate = require('schemaUtils').validate; 11 var validate = require('schemaUtils').validate;
12 var unloadEvent = require('unload_event');
13 12
14 // Schemas for the rule-style functions on the events API that 13 // Schemas for the rule-style functions on the events API that
15 // only need to be generated occasionally, so populate them lazily. 14 // only need to be generated occasionally, so populate them lazily.
16 var ruleFunctionSchemas = { 15 var ruleFunctionSchemas = {
17 // These values are set lazily: 16 // These values are set lazily:
18 // addRules: {}, 17 // addRules: {},
19 // getRules: {}, 18 // getRules: {},
20 // removeRules: {} 19 // removeRules: {}
21 }; 20 };
22 21
23 // This function ensures that |ruleFunctionSchemas| is populated. 22 // This function ensures that |ruleFunctionSchemas| is populated.
24 function ensureRuleSchemasLoaded() { 23 function ensureRuleSchemasLoaded() {
25 if (ruleFunctionSchemas.addRules) 24 if (ruleFunctionSchemas.addRules)
26 return; 25 return;
27 var eventsSchema = schemaRegistry.GetSchema("events"); 26 var eventsSchema = schemaRegistry.GetSchema("events");
28 var eventType = utils.lookup(eventsSchema.types, 'id', 'events.Event'); 27 var eventType = utils.lookup(eventsSchema.types, 'id', 'events.Event');
29 28
30 ruleFunctionSchemas.addRules = 29 ruleFunctionSchemas.addRules =
31 utils.lookup(eventType.functions, 'name', 'addRules'); 30 utils.lookup(eventType.functions, 'name', 'addRules');
32 ruleFunctionSchemas.getRules = 31 ruleFunctionSchemas.getRules =
33 utils.lookup(eventType.functions, 'name', 'getRules'); 32 utils.lookup(eventType.functions, 'name', 'getRules');
34 ruleFunctionSchemas.removeRules = 33 ruleFunctionSchemas.removeRules =
35 utils.lookup(eventType.functions, 'name', 'removeRules'); 34 utils.lookup(eventType.functions, 'name', 'removeRules');
36 } 35 }
37 36
38 // A map of event names to the event object that is registered to that name. 37 // A map of event names to the event object that is registered to that name.
39 var attachedNamedEvents = {}; 38 var attachedNamedEvents = {};
40 39
41 // An array of all attached event objects, used for detaching on unload.
42 var allAttachedEvents = [];
43
44 // A map of functions that massage event arguments before they are dispatched. 40 // A map of functions that massage event arguments before they are dispatched.
45 // Key is event name, value is function. 41 // Key is event name, value is function.
46 var eventArgumentMassagers = {}; 42 var eventArgumentMassagers = {};
47 43
48 // An attachment strategy for events that aren't attached to the browser. 44 // An attachment strategy for events that aren't attached to the browser.
49 // This applies to events with the "unmanaged" option and events without 45 // This applies to events with the "unmanaged" option and events without
50 // names. 46 // names.
51 var NullAttachmentStrategy = function(event) { 47 var NullAttachmentStrategy = function(event) {
52 this.event_ = event; 48 this.event_ = event;
53 }; 49 };
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 } 272 }
277 var listener = {callback: cb, filters: filters}; 273 var listener = {callback: cb, filters: filters};
278 this.attach_(listener); 274 this.attach_(listener);
279 $Array.push(this.listeners, listener); 275 $Array.push(this.listeners, listener);
280 }; 276 };
281 277
282 EventImpl.prototype.attach_ = function(listener) { 278 EventImpl.prototype.attach_ = function(listener) {
283 this.attachmentStrategy.onAddedListener(listener); 279 this.attachmentStrategy.onAddedListener(listener);
284 280
285 if (this.listeners.length == 0) { 281 if (this.listeners.length == 0) {
286 allAttachedEvents[allAttachedEvents.length] = this;
287 if (this.eventName) { 282 if (this.eventName) {
288 if (attachedNamedEvents[this.eventName]) { 283 if (attachedNamedEvents[this.eventName]) {
289 throw new Error("Event '" + this.eventName + 284 throw new Error("Event '" + this.eventName +
290 "' is already attached."); 285 "' is already attached.");
291 } 286 }
292 attachedNamedEvents[this.eventName] = this; 287 attachedNamedEvents[this.eventName] = this;
293 } 288 }
294 } 289 }
295 }; 290 };
296 291
297 // Unregisters a callback. 292 // Unregisters a callback.
298 EventImpl.prototype.removeListener = function(cb) { 293 EventImpl.prototype.removeListener = function(cb) {
299 if (!this.eventOptions.supportsListeners) 294 if (!this.eventOptions.supportsListeners)
300 throw new Error("This event does not support listeners."); 295 throw new Error("This event does not support listeners.");
301 296
302 var idx = this.findListener_(cb); 297 var idx = this.findListener_(cb);
303 if (idx == -1) 298 if (idx == -1)
304 return; 299 return;
305 300
306 var removedListener = $Array.splice(this.listeners, idx, 1)[0]; 301 var removedListener = $Array.splice(this.listeners, idx, 1)[0];
307 this.attachmentStrategy.onRemovedListener(removedListener); 302 this.attachmentStrategy.onRemovedListener(removedListener);
308 303
309 if (this.listeners.length == 0) { 304 if (this.listeners.length == 0) {
310 var i = $Array.indexOf(allAttachedEvents, this);
311 if (i >= 0)
312 delete allAttachedEvents[i];
313 if (this.eventName) { 305 if (this.eventName) {
314 if (!attachedNamedEvents[this.eventName]) { 306 if (!attachedNamedEvents[this.eventName]) {
315 throw new Error( 307 throw new Error(
316 "Event '" + this.eventName + "' is not attached."); 308 "Event '" + this.eventName + "' is not attached.");
317 } 309 }
318 delete attachedNamedEvents[this.eventName]; 310 delete attachedNamedEvents[this.eventName];
319 } 311 }
320 } 312 }
321 }; 313 };
322 314
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 validate([this.webViewInstanceId, ruleIdentifiers, cb], 483 validate([this.webViewInstanceId, ruleIdentifiers, cb],
492 $Array.splice( 484 $Array.splice(
493 $Array.slice(ruleFunctionSchemas.getRules.parameters), 1)); 485 $Array.slice(ruleFunctionSchemas.getRules.parameters), 1));
494 486
495 sendRequest( 487 sendRequest(
496 "events.getRules", 488 "events.getRules",
497 [this.eventName, this.webViewInstanceId, ruleIdentifiers, cb], 489 [this.eventName, this.webViewInstanceId, ruleIdentifiers, cb],
498 ruleFunctionSchemas.getRules.parameters); 490 ruleFunctionSchemas.getRules.parameters);
499 } 491 }
500 492
501 unloadEvent.addListener(function() {
502 for (var i = 0; i < allAttachedEvents.length; ++i) {
503 var event = allAttachedEvents[i];
504 if (event)
505 event.detach_();
506 }
507 });
508
509 var Event = utils.expose('Event', EventImpl, { functions: [ 493 var Event = utils.expose('Event', EventImpl, { functions: [
510 'addListener', 494 'addListener',
511 'removeListener', 495 'removeListener',
512 'hasListener', 496 'hasListener',
513 'hasListeners', 497 'hasListeners',
514 'dispatchToListener', 498 'dispatchToListener',
515 'dispatch', 499 'dispatch',
516 'addRules', 500 'addRules',
517 'removeRules', 501 'removeRules',
518 'getRules' 502 'getRules'
519 ] }); 503 ] });
520 504
521 // NOTE: Event is (lazily) exposed as chrome.Event from dispatcher.cc. 505 // NOTE: Event is (lazily) exposed as chrome.Event from dispatcher.cc.
522 exports.Event = Event; 506 exports.Event = Event;
523 507
524 exports.dispatchEvent = dispatchEvent; 508 exports.dispatchEvent = dispatchEvent;
525 exports.parseEventOptions = parseEventOptions; 509 exports.parseEventOptions = parseEventOptions;
526 exports.registerArgumentMassager = registerArgumentMassager; 510 exports.registerArgumentMassager = registerArgumentMassager;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698