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

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

Issue 9192029: Bindings layer for declarative events API (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments Created 8 years, 10 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 | Annotate | Revision Log
OLDNEW
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
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
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
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 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698