OLD | NEW |
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 var eventNatives = requireNative('event_natives'); | 5 var eventNatives = requireNative('event_natives'); |
6 var logging = requireNative('logging'); | 6 var logging = requireNative('logging'); |
7 var schemaRegistry = requireNative('schema_registry'); | 7 var schemaRegistry = requireNative('schema_registry'); |
8 var sendRequest = require('sendRequest').sendRequest; | 8 var sendRequest = require('sendRequest').sendRequest; |
9 var utils = require('utils'); | 9 var utils = require('utils'); |
10 var validate = require('schemaUtils').validate; | 10 var validate = require('schemaUtils').validate; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 }; | 102 }; |
103 | 103 |
104 FilteredAttachmentStrategy.prototype.detach = function(manual) { | 104 FilteredAttachmentStrategy.prototype.detach = function(manual) { |
105 for (var i in this.listenerMap_) | 105 for (var i in this.listenerMap_) |
106 this.detachListener(this.listenerMap_[i], manual); | 106 this.detachListener(this.listenerMap_[i], manual); |
107 }; | 107 }; |
108 | 108 |
109 FilteredAttachmentStrategy.prototype.getListenersByIDs = function(ids) { | 109 FilteredAttachmentStrategy.prototype.getListenersByIDs = function(ids) { |
110 var result = []; | 110 var result = []; |
111 for (var i = 0; i < ids.length; i++) | 111 for (var i = 0; i < ids.length; i++) |
112 result.push(this.listenerMap_[ids[i]]); | 112 $Array.push(result, this.listenerMap_[ids[i]]); |
113 return result; | 113 return result; |
114 }; | 114 }; |
115 | 115 |
116 function parseEventOptions(opt_eventOptions) { | 116 function parseEventOptions(opt_eventOptions) { |
117 function merge(dest, src) { | 117 function merge(dest, src) { |
118 for (var k in src) { | 118 for (var k in src) { |
119 if (!dest.hasOwnProperty(k)) { | 119 if (!$Object.hasOwnProperty(dest, k)) { |
120 dest[k] = src[k]; | 120 dest[k] = src[k]; |
121 } | 121 } |
122 } | 122 } |
123 } | 123 } |
124 | 124 |
125 var options = opt_eventOptions || {}; | 125 var options = opt_eventOptions || {}; |
126 merge(options, | 126 merge(options, |
127 {supportsFilters: false, | 127 {supportsFilters: false, |
128 supportsListeners: true, | 128 supportsListeners: true, |
129 supportsRules: false, | 129 supportsRules: false, |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 this.getListenerCount() >= this.eventOptions_.maxListeners) | 217 this.getListenerCount() >= this.eventOptions_.maxListeners) |
218 throw new Error("Too many listeners for " + this.eventName_); | 218 throw new Error("Too many listeners for " + this.eventName_); |
219 if (filters) { | 219 if (filters) { |
220 if (!this.eventOptions_.supportsFilters) | 220 if (!this.eventOptions_.supportsFilters) |
221 throw new Error("This event does not support filters."); | 221 throw new Error("This event does not support filters."); |
222 if (filters.url && !(filters.url instanceof Array)) | 222 if (filters.url && !(filters.url instanceof Array)) |
223 throw new Error("filters.url should be an array"); | 223 throw new Error("filters.url should be an array"); |
224 } | 224 } |
225 var listener = {callback: cb, filters: filters}; | 225 var listener = {callback: cb, filters: filters}; |
226 this.attach_(listener); | 226 this.attach_(listener); |
227 this.listeners_.push(listener); | 227 $Array.push(this.listeners_, listener); |
228 }; | 228 }; |
229 | 229 |
230 Event.prototype.attach_ = function(listener) { | 230 Event.prototype.attach_ = function(listener) { |
231 this.attachmentStrategy_.onAddedListener(listener); | 231 this.attachmentStrategy_.onAddedListener(listener); |
232 if (this.listeners_.length == 0) { | 232 if (this.listeners_.length == 0) { |
233 allAttachedEvents[allAttachedEvents.length] = this; | 233 allAttachedEvents[allAttachedEvents.length] = this; |
234 if (!this.eventName_) | 234 if (!this.eventName_) |
235 return; | 235 return; |
236 | 236 |
237 if (attachedNamedEvents[this.eventName_]) | 237 if (attachedNamedEvents[this.eventName_]) |
238 throw new Error("Event '" + this.eventName_ + "' is already attached."); | 238 throw new Error("Event '" + this.eventName_ + "' is already attached."); |
239 | 239 |
240 attachedNamedEvents[this.eventName_] = this; | 240 attachedNamedEvents[this.eventName_] = this; |
241 } | 241 } |
242 }; | 242 }; |
243 | 243 |
244 // Unregisters a callback. | 244 // Unregisters a callback. |
245 Event.prototype.removeListener = function(cb) { | 245 Event.prototype.removeListener = function(cb) { |
246 if (!this.eventOptions_.supportsListeners) | 246 if (!this.eventOptions_.supportsListeners) |
247 throw new Error("This event does not support listeners."); | 247 throw new Error("This event does not support listeners."); |
248 var idx = this.findListener_(cb); | 248 var idx = this.findListener_(cb); |
249 if (idx == -1) | 249 if (idx == -1) |
250 return; | 250 return; |
251 | 251 |
252 var removedListener = this.listeners_.splice(idx, 1)[0]; | 252 var removedListener = $Array.splice(this.listeners_, idx, 1)[0]; |
253 this.attachmentStrategy_.onRemovedListener(removedListener); | 253 this.attachmentStrategy_.onRemovedListener(removedListener); |
254 | 254 |
255 if (this.listeners_.length == 0) { | 255 if (this.listeners_.length == 0) { |
256 var i = allAttachedEvents.indexOf(this); | 256 var i = allAttachedEvents.indexOf(this); |
257 if (i >= 0) | 257 if (i >= 0) |
258 delete allAttachedEvents[i]; | 258 delete allAttachedEvents[i]; |
259 if (!this.eventName_) | 259 if (!this.eventName_) |
260 return; | 260 return; |
261 | 261 |
262 if (!attachedNamedEvents[this.eventName_]) | 262 if (!attachedNamedEvents[this.eventName_]) |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 if (!this.eventOptions_.supportsListeners) | 301 if (!this.eventOptions_.supportsListeners) |
302 throw new Error("This event does not support listeners."); | 302 throw new Error("This event does not support listeners."); |
303 var validationErrors = this.validateEventArgs_(args); | 303 var validationErrors = this.validateEventArgs_(args); |
304 if (validationErrors) { | 304 if (validationErrors) { |
305 console.error(validationErrors); | 305 console.error(validationErrors); |
306 return {validationErrors: validationErrors}; | 306 return {validationErrors: validationErrors}; |
307 } | 307 } |
308 | 308 |
309 // Make a copy of the listeners in case the listener list is modified | 309 // Make a copy of the listeners in case the listener list is modified |
310 // while dispatching the event. | 310 // while dispatching the event. |
311 var listeners = | 311 var listeners = $Array.slice( |
312 this.attachmentStrategy_.getListenersByIDs(listenerIDs).slice(); | 312 this.attachmentStrategy_.getListenersByIDs(listenerIDs)); |
313 | 313 |
314 var results = []; | 314 var results = []; |
315 for (var i = 0; i < listeners.length; i++) { | 315 for (var i = 0; i < listeners.length; i++) { |
316 try { | 316 try { |
317 var result = this.dispatchToListener(listeners[i].callback, args); | 317 var result = this.dispatchToListener(listeners[i].callback, args); |
318 if (result !== undefined) | 318 if (result !== undefined) |
319 results.push(result); | 319 $Array.push(results, result); |
320 } catch (e) { | 320 } catch (e) { |
321 var errorMessage = "Error in event handler"; | 321 var errorMessage = "Error in event handler"; |
322 if (this.eventName_) | 322 if (this.eventName_) |
323 errorMessage += " for " + this.eventName_; | 323 errorMessage += " for " + this.eventName_; |
324 errorMessage += ": " + e; | 324 errorMessage += ": " + e; |
325 console.error(errorMessage); | 325 console.error(errorMessage); |
326 } | 326 } |
327 } | 327 } |
328 if (results.length) | 328 if (results.length) |
329 return {results: results}; | 329 return {results: results}; |
330 } | 330 } |
331 | 331 |
332 // Can be overridden to support custom dispatching. | 332 // Can be overridden to support custom dispatching. |
333 Event.prototype.dispatchToListener = function(callback, args) { | 333 Event.prototype.dispatchToListener = function(callback, args) { |
334 return callback.apply(null, args); | 334 return $Function.apply(callback, null, args); |
335 } | 335 } |
336 | 336 |
337 // Dispatches this event object to all listeners, passing all supplied | 337 // Dispatches this event object to all listeners, passing all supplied |
338 // arguments to this function each listener. | 338 // arguments to this function each listener. |
339 Event.prototype.dispatch = function(varargs) { | 339 Event.prototype.dispatch = function(varargs) { |
340 return this.dispatch_(Array.prototype.slice.call(arguments), undefined); | 340 return this.dispatch_($Array.slice(arguments), undefined); |
341 }; | 341 }; |
342 | 342 |
343 // Detaches this event object from its name. | 343 // Detaches this event object from its name. |
344 Event.prototype.detach_ = function() { | 344 Event.prototype.detach_ = function() { |
345 this.attachmentStrategy_.detach(false); | 345 this.attachmentStrategy_.detach(false); |
346 }; | 346 }; |
347 | 347 |
348 Event.prototype.destroy_ = function() { | 348 Event.prototype.destroy_ = function() { |
349 this.listeners_ = []; | 349 this.listeners_ = []; |
350 this.validateEventArgs_ = []; | 350 this.validateEventArgs_ = []; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 } | 389 } |
390 | 390 |
391 validateRules(rules, | 391 validateRules(rules, |
392 this.eventOptions_.conditions, | 392 this.eventOptions_.conditions, |
393 this.eventOptions_.actions); | 393 this.eventOptions_.actions); |
394 | 394 |
395 ensureRuleSchemasLoaded(); | 395 ensureRuleSchemasLoaded(); |
396 // We remove the first parameter from the validation to give the user more | 396 // We remove the first parameter from the validation to give the user more |
397 // meaningful error messages. | 397 // meaningful error messages. |
398 validate([rules, opt_cb], | 398 validate([rules, opt_cb], |
399 ruleFunctionSchemas.addRules.parameters.slice().splice(1)); | 399 $Array.splice( |
| 400 $Array.slice(ruleFunctionSchemas.addRules.parameters), 1)); |
400 sendRequest("events.addRules", [this.eventName_, rules, opt_cb], | 401 sendRequest("events.addRules", [this.eventName_, rules, opt_cb], |
401 ruleFunctionSchemas.addRules.parameters); | 402 ruleFunctionSchemas.addRules.parameters); |
402 } | 403 } |
403 | 404 |
404 Event.prototype.removeRules = function(ruleIdentifiers, opt_cb) { | 405 Event.prototype.removeRules = function(ruleIdentifiers, opt_cb) { |
405 if (!this.eventOptions_.supportsRules) | 406 if (!this.eventOptions_.supportsRules) |
406 throw new Error("This event does not support rules."); | 407 throw new Error("This event does not support rules."); |
407 ensureRuleSchemasLoaded(); | 408 ensureRuleSchemasLoaded(); |
408 // We remove the first parameter from the validation to give the user more | 409 // We remove the first parameter from the validation to give the user more |
409 // meaningful error messages. | 410 // meaningful error messages. |
410 validate([ruleIdentifiers, opt_cb], | 411 validate([ruleIdentifiers, opt_cb], |
411 ruleFunctionSchemas.removeRules.parameters.slice().splice(1)); | 412 $Array.splice( |
| 413 $Array.slice(ruleFunctionSchemas.removeRules.parameters), 1)); |
412 sendRequest("events.removeRules", | 414 sendRequest("events.removeRules", |
413 [this.eventName_, ruleIdentifiers, opt_cb], | 415 [this.eventName_, ruleIdentifiers, opt_cb], |
414 ruleFunctionSchemas.removeRules.parameters); | 416 ruleFunctionSchemas.removeRules.parameters); |
415 } | 417 } |
416 | 418 |
417 Event.prototype.getRules = function(ruleIdentifiers, cb) { | 419 Event.prototype.getRules = function(ruleIdentifiers, cb) { |
418 if (!this.eventOptions_.supportsRules) | 420 if (!this.eventOptions_.supportsRules) |
419 throw new Error("This event does not support rules."); | 421 throw new Error("This event does not support rules."); |
420 ensureRuleSchemasLoaded(); | 422 ensureRuleSchemasLoaded(); |
421 // We remove the first parameter from the validation to give the user more | 423 // We remove the first parameter from the validation to give the user more |
422 // meaningful error messages. | 424 // meaningful error messages. |
423 validate([ruleIdentifiers, cb], | 425 validate([ruleIdentifiers, cb], |
424 ruleFunctionSchemas.getRules.parameters.slice().splice(1)); | 426 $Array.splice( |
| 427 $Array.slice(ruleFunctionSchemas.getRules.parameters), 1)); |
425 | 428 |
426 sendRequest("events.getRules", | 429 sendRequest("events.getRules", |
427 [this.eventName_, ruleIdentifiers, cb], | 430 [this.eventName_, ruleIdentifiers, cb], |
428 ruleFunctionSchemas.getRules.parameters); | 431 ruleFunctionSchemas.getRules.parameters); |
429 } | 432 } |
430 | 433 |
431 unloadEvent.addListener(function() { | 434 unloadEvent.addListener(function() { |
432 for (var i = 0; i < allAttachedEvents.length; ++i) { | 435 for (var i = 0; i < allAttachedEvents.length; ++i) { |
433 var event = allAttachedEvents[i]; | 436 var event = allAttachedEvents[i]; |
434 if (event) | 437 if (event) |
435 event.detach_(); | 438 event.detach_(); |
436 } | 439 } |
437 }); | 440 }); |
438 | 441 |
439 // NOTE: Event is (lazily) exposed as chrome.Event from dispatcher.cc. | 442 // NOTE: Event is (lazily) exposed as chrome.Event from dispatcher.cc. |
440 exports.Event = Event; | 443 exports.Event = Event; |
441 | 444 |
442 exports.dispatchEvent = dispatchEvent; | 445 exports.dispatchEvent = dispatchEvent; |
443 exports.parseEventOptions = parseEventOptions; | 446 exports.parseEventOptions = parseEventOptions; |
444 exports.registerArgumentMassager = registerArgumentMassager; | 447 exports.registerArgumentMassager = registerArgumentMassager; |
OLD | NEW |