| 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 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 Loading... |
| 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 Loading... |
| 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; |
| OLD | NEW |