Chromium Code Reviews| 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 chrome = chrome || {}; | 5 var chrome = chrome || {}; |
| 6 (function () { | 6 (function () { |
| 7 native function GetChromeHidden(); | 7 native function GetChromeHidden(); |
| 8 native function AttachEvent(eventName); | 8 native function AttachEvent(eventName); |
| 9 native function DetachEvent(eventName); | 9 native function DetachEvent(eventName); |
| 10 native function Print(); | 10 native function Print(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 51 | 51 |
| 52 // Event object. If opt_eventName is provided, this object represents | 52 // Event object. If opt_eventName is provided, this object represents |
| 53 // the unique instance of that named event, and dispatching an event | 53 // the unique instance of that named event, and dispatching an event |
| 54 // with that name will route through this object's listeners. | 54 // with that name will route through this object's listeners. |
| 55 // | 55 // |
| 56 // Example: | 56 // Example: |
| 57 // chrome.tabs.onChanged = new chrome.Event("tab-changed"); | 57 // chrome.tabs.onChanged = new chrome.Event("tab-changed"); |
| 58 // chrome.tabs.onChanged.addListener(function(data) { alert(data); }); | 58 // chrome.tabs.onChanged.addListener(function(data) { alert(data); }); |
| 59 // chromeHidden.Event.dispatch("tab-changed", "hi"); | 59 // chromeHidden.Event.dispatch("tab-changed", "hi"); |
| 60 // will result in an alert dialog that says 'hi'. | 60 // will result in an alert dialog that says 'hi'. |
| 61 chrome.Event = function(opt_eventName, opt_argSchemas) { | 61 // |
| 62 // If opt_eventOptions exists, it is a dictionary that contains the boolean | |
| 63 // entries "supportsListeners" and "supportsRules". | |
| 64 chrome.Event = function(opt_eventName, opt_argSchemas, opt_eventOptions) { | |
| 62 this.eventName_ = opt_eventName; | 65 this.eventName_ = opt_eventName; |
| 63 this.listeners_ = []; | 66 this.listeners_ = []; |
| 67 this.eventOptions_ = opt_eventOptions || | |
| 68 {"supportsListeners": true, "supportsRules": false}; | |
| 64 | 69 |
| 65 // Validate event parameters if we are in debug. | 70 // Validate event parameters if we are in debug. |
| 66 if (opt_argSchemas && | 71 if (opt_argSchemas && |
| 67 chromeHidden.validateCallbacks && | 72 chromeHidden.validateCallbacks && |
| 68 chromeHidden.validate) { | 73 chromeHidden.validate) { |
| 69 | 74 |
| 70 this.validate_ = function(args) { | 75 this.validate_ = function(args) { |
| 71 try { | 76 try { |
| 72 chromeHidden.validate(args, opt_argSchemas); | 77 chromeHidden.validate(args, opt_argSchemas); |
| 73 } catch (exception) { | 78 } catch (exception) { |
| 74 return "Event validation error during " + opt_eventName + " -- " + | 79 return "Event validation error during " + opt_eventName + " -- " + |
| 75 exception; | 80 exception; |
| 76 } | 81 } |
| 77 }; | 82 }; |
| 83 } else { | |
| 84 this.validate_ = function() {} | |
| 78 } | 85 } |
| 79 }; | 86 }; |
| 80 | 87 |
| 81 // A map of event names to the event object that is registered to that name. | 88 // A map of event names to the event object that is registered to that name. |
| 82 var attachedNamedEvents = {}; | 89 var attachedNamedEvents = {}; |
| 83 | 90 |
| 84 // An array of all attached event objects, used for detaching on unload. | 91 // An array of all attached event objects, used for detaching on unload. |
| 85 var allAttachedEvents = []; | 92 var allAttachedEvents = []; |
| 86 | 93 |
| 87 // A map of functions that massage event arguments before they are dispatched. | 94 // A map of functions that massage event arguments before they are dispatched. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 120 }; | 127 }; |
| 121 | 128 |
| 122 // Test if a named event has any listeners. | 129 // Test if a named event has any listeners. |
| 123 chromeHidden.Event.hasListener = function(name) { | 130 chromeHidden.Event.hasListener = function(name) { |
| 124 return (attachedNamedEvents[name] && | 131 return (attachedNamedEvents[name] && |
| 125 attachedNamedEvents[name].listeners_.length > 0); | 132 attachedNamedEvents[name].listeners_.length > 0); |
| 126 }; | 133 }; |
| 127 | 134 |
| 128 // Registers a callback to be called when this event is dispatched. | 135 // Registers a callback to be called when this event is dispatched. |
| 129 chrome.Event.prototype.addListener = function(cb) { | 136 chrome.Event.prototype.addListener = function(cb) { |
| 137 if (!this.eventOptions_.supportsListeners) | |
| 138 throw new Error("This event does not support listeners."); | |
| 130 if (this.listeners_.length == 0) { | 139 if (this.listeners_.length == 0) { |
| 131 this.attach_(); | 140 this.attach_(); |
| 132 } | 141 } |
| 133 this.listeners_.push(cb); | 142 this.listeners_.push(cb); |
| 134 }; | 143 }; |
| 135 | 144 |
| 136 // Unregisters a callback. | 145 // Unregisters a callback. |
| 137 chrome.Event.prototype.removeListener = function(cb) { | 146 chrome.Event.prototype.removeListener = function(cb) { |
| 147 if (!this.eventOptions_.supportsListeners) | |
| 148 throw new Error("This event does not support listeners."); | |
| 138 var idx = this.findListener_(cb); | 149 var idx = this.findListener_(cb); |
| 139 if (idx == -1) { | 150 if (idx == -1) { |
| 140 return; | 151 return; |
| 141 } | 152 } |
| 142 | 153 |
| 143 this.listeners_.splice(idx, 1); | 154 this.listeners_.splice(idx, 1); |
| 144 if (this.listeners_.length == 0) { | 155 if (this.listeners_.length == 0) { |
| 145 this.detach_(); | 156 this.detach_(); |
| 146 } | 157 } |
| 147 }; | 158 }; |
| 148 | 159 |
| 149 // Test if the given callback is registered for this event. | 160 // Test if the given callback is registered for this event. |
| 150 chrome.Event.prototype.hasListener = function(cb) { | 161 chrome.Event.prototype.hasListener = function(cb) { |
| 162 if (!this.eventOptions_.supportsListeners) | |
| 163 throw new Error("This event does not support listeners."); | |
| 151 return this.findListener_(cb) > -1; | 164 return this.findListener_(cb) > -1; |
| 152 }; | 165 }; |
| 153 | 166 |
| 154 // Test if any callbacks are registered for this event. | 167 // Test if any callbacks are registered for this event. |
| 155 chrome.Event.prototype.hasListeners = function(cb) { | 168 chrome.Event.prototype.hasListeners = function() { |
| 169 if (!this.eventOptions_.supportsListeners) | |
| 170 throw new Error("This event does not support listeners."); | |
| 156 return this.listeners_.length > 0; | 171 return this.listeners_.length > 0; |
| 157 }; | 172 }; |
| 158 | 173 |
| 159 // Returns the index of the given callback if registered, or -1 if not | 174 // Returns the index of the given callback if registered, or -1 if not |
| 160 // found. | 175 // found. |
| 161 chrome.Event.prototype.findListener_ = function(cb) { | 176 chrome.Event.prototype.findListener_ = function(cb) { |
| 162 for (var i = 0; i < this.listeners_.length; i++) { | 177 for (var i = 0; i < this.listeners_.length; i++) { |
| 163 if (this.listeners_[i] == cb) { | 178 if (this.listeners_[i] == cb) { |
| 164 return i; | 179 return i; |
| 165 } | 180 } |
| 166 } | 181 } |
| 167 | 182 |
| 168 return -1; | 183 return -1; |
| 169 }; | 184 }; |
| 170 | 185 |
| 171 // Dispatches this event object to all listeners, passing all supplied | 186 // Dispatches this event object to all listeners, passing all supplied |
| 172 // arguments to this function each listener. | 187 // arguments to this function each listener. |
| 173 chrome.Event.prototype.dispatch = function(varargs) { | 188 chrome.Event.prototype.dispatch = function(varargs) { |
| 189 if (!this.eventOptions_.supportsListeners) | |
| 190 throw new Error("This event does not support listeners."); | |
| 174 var args = Array.prototype.slice.call(arguments); | 191 var args = Array.prototype.slice.call(arguments); |
| 175 if (this.validate_) { | 192 var validationErrors = this.validate_(args); |
| 176 var validationErrors = this.validate_(args); | 193 if (validationErrors) { |
| 177 if (validationErrors) { | 194 return validationErrors; |
| 178 return validationErrors; | |
| 179 } | |
| 180 } | 195 } |
| 181 for (var i = 0; i < this.listeners_.length; i++) { | 196 for (var i = 0; i < this.listeners_.length; i++) { |
| 182 try { | 197 try { |
| 183 this.listeners_[i].apply(null, args); | 198 this.listeners_[i].apply(null, args); |
| 184 } catch (e) { | 199 } catch (e) { |
| 185 console.error("Error in event handler for '" + this.eventName_ + | 200 console.error("Error in event handler for '" + this.eventName_ + |
| 186 "': " + e.stack); | 201 "': " + e.stack); |
| 187 } | 202 } |
| 188 } | 203 } |
| 189 }; | 204 }; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 220 | 235 |
| 221 delete attachedNamedEvents[this.eventName_]; | 236 delete attachedNamedEvents[this.eventName_]; |
| 222 }; | 237 }; |
| 223 | 238 |
| 224 chrome.Event.prototype.destroy_ = function() { | 239 chrome.Event.prototype.destroy_ = function() { |
| 225 this.listeners_ = []; | 240 this.listeners_ = []; |
| 226 this.validate_ = []; | 241 this.validate_ = []; |
| 227 this.detach_(); | 242 this.detach_(); |
| 228 }; | 243 }; |
| 229 | 244 |
| 245 chrome.Event.prototype.addRules = function(rules, opt_cb) { | |
| 246 if (!this.eventOptions_.supportsRules) | |
| 247 throw new Error("This event does not support rules."); | |
| 248 chrome.experimental.declarative.addRules(this.eventName_, rules, opt_cb); | |
|
not at google - send to devlin
2012/02/01 23:07:23
You'll still need to check that the experimental.d
battre
2012/02/02 13:49:59
Anticipating that experimental.declarative will be
| |
| 249 } | |
| 250 | |
| 251 chrome.Event.prototype.removeRules = function(ruleIdentifiers, opt_cb) { | |
| 252 if (!this.eventOptions_.supportsRules) | |
| 253 throw new Error("This event does not support rules."); | |
| 254 chrome.experimental.declarative.removeRules( | |
| 255 this.eventName_, ruleIdentifiers, opt_cb); | |
| 256 } | |
| 257 | |
| 258 chrome.Event.prototype.getRules = function(ruleIdentifiers, cb) { | |
| 259 if (!this.eventOptions_.supportsRules) | |
| 260 throw new Error("This event does not support rules."); | |
| 261 chrome.experimental.declarative.getRules( | |
| 262 this.eventName_, ruleIdentifiers, cb); | |
| 263 } | |
| 264 | |
| 230 // Special load events: we don't use the DOM unload because that slows | 265 // Special load events: we don't use the DOM unload because that slows |
| 231 // down tab shutdown. On the other hand, onUnload might not always fire, | 266 // down tab shutdown. On the other hand, onUnload might not always fire, |
| 232 // since Chrome will terminate renderers on shutdown (SuddenTermination). | 267 // since Chrome will terminate renderers on shutdown (SuddenTermination). |
| 233 chromeHidden.onLoad = new chrome.Event(); | 268 chromeHidden.onLoad = new chrome.Event(); |
| 234 chromeHidden.onUnload = new chrome.Event(); | 269 chromeHidden.onUnload = new chrome.Event(); |
| 235 | 270 |
| 236 chromeHidden.dispatchOnLoad = | 271 chromeHidden.dispatchOnLoad = |
| 237 chromeHidden.onLoad.dispatch.bind(chromeHidden.onLoad); | 272 chromeHidden.onLoad.dispatch.bind(chromeHidden.onLoad); |
| 238 | 273 |
| 239 chromeHidden.dispatchOnUnload = function() { | 274 chromeHidden.dispatchOnUnload = function() { |
| 240 chromeHidden.onUnload.dispatch(); | 275 chromeHidden.onUnload.dispatch(); |
| 241 for (var i = 0; i < allAttachedEvents.length; ++i) { | 276 for (var i = 0; i < allAttachedEvents.length; ++i) { |
| 242 var event = allAttachedEvents[i]; | 277 var event = allAttachedEvents[i]; |
| 243 if (event) | 278 if (event) |
| 244 event.detach_(); | 279 event.detach_(); |
| 245 } | 280 } |
| 246 }; | 281 }; |
| 247 | 282 |
| 248 chromeHidden.dispatchError = function(msg) { | 283 chromeHidden.dispatchError = function(msg) { |
| 249 console.error(msg); | 284 console.error(msg); |
| 250 }; | 285 }; |
| 251 })(); | 286 })(); |
| OLD | NEW |