Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
|
blois
2013/01/23 02:06:12
2013
sashab
2013/01/23 04:45:34
Done.
| |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
|
blois
2013/01/23 02:06:12
Normally we don't use leading _ for file names (at
sashab
2013/01/23 04:45:34
No worries; I can fix this.
| |
| 4 | |
| 5 /** | |
| 6 * A set of utilities for use with the Chrome Extension APIs. | |
| 7 * | |
| 8 * Allows for easy access to required JS objects. | |
| 9 */ | |
| 10 part of chrome; | |
| 11 | |
| 12 /** | |
| 13 * A dart object, that is convertible to JS. Used for creating objects in dart, | |
| 14 * then passing them to JS. | |
| 15 * | |
| 16 * Objects that are passable to JS need to implement this interface. | |
| 17 */ | |
| 18 abstract class ChromeObject { | |
| 19 /* | |
| 20 * Default Constructor | |
| 21 * | |
| 22 * Called by child objects during their regular construction. | |
| 23 */ | |
| 24 ChromeObject() : | |
| 25 _jsObject = null; | |
| 26 | |
| 27 /* | |
| 28 * Internal proxy constructor | |
| 29 * | |
| 30 * Creates a new object using this existing proxy. | |
| 31 */ | |
| 32 ChromeObject._proxy(this._jsObject); | |
| 33 | |
| 34 /* | |
| 35 * JS Object Representation | |
| 36 */ | |
| 37 Object _jsObject; | |
| 38 | |
| 39 /* | |
| 40 * Return a Map representation of this object's members, non-recursively. | |
| 41 */ | |
| 42 Map _toMap(); | |
| 43 | |
| 44 /* | |
| 45 * Return a non-recursive serialized representation of this object. | |
| 46 * | |
| 47 * Returns a Map representation, if this object has not yet been proxied, | |
| 48 * or the existing proxy, if it has already been proxied. | |
| 49 */ | |
| 50 Object _serialize() { | |
| 51 if (_jsObject == null) | |
| 52 return this._toMap(); | |
| 53 return _jsObject; | |
| 54 } | |
| 55 | |
| 56 /* | |
| 57 * Returns True if this object has a matching JS object, False otherwise. | |
| 58 */ | |
| 59 bool _hasProxy() { | |
| 60 return this._jsObject != null; | |
| 61 } | |
| 62 } | |
| 63 | |
| 64 /** | |
| 65 * Useful functions for converting arguments. | |
| 66 */ | |
| 67 | |
| 68 /** | |
| 69 * Converts the given map-type argument to js-friendly format, recursively. | |
| 70 * Returns the new Map object. | |
| 71 */ | |
| 72 Object _convertMapArgument(Map argument) { | |
| 73 Map m = new Map(); | |
| 74 for (Object key in argument.keys) | |
| 75 m[key] = convertArgument(argument[key]); | |
| 76 return convertDartToNative_Dictionary(m); | |
| 77 } | |
| 78 | |
| 79 /* | |
| 80 Map _convertMapArgument(Map argument) { | |
| 81 var object = JS('var', '{}'); | |
| 82 for (Object key in argument.keys) | |
| 83 JS('void', '#[#] = #', object, key, convertArgument(argument[key])); | |
| 84 return object; | |
| 85 } | |
| 86 */ | |
| 87 | |
| 88 /** | |
| 89 * Converts the given list-type argument to js-friendly format, recursively. | |
| 90 * Returns the new List object. | |
| 91 */ | |
| 92 List _convertListArgument(List argument) { | |
| 93 List l = new List(); | |
| 94 for (var i = 0; i < argument.length; i ++) | |
| 95 l.add(convertArgument(argument[i])); | |
| 96 return l; | |
| 97 } | |
| 98 | |
| 99 /** | |
| 100 * Converts the given argument Object to js-friendly format, recursively. | |
| 101 * | |
| 102 * Flattens out all Chrome objects into their corresponding ._toMap() | |
| 103 * definitions, then converts them to JS objects. | |
| 104 * | |
| 105 * Returns the new argument. | |
| 106 * | |
| 107 * Cannot be used for functions. | |
| 108 */ | |
| 109 Object convertArgument(var argument) { | |
| 110 if (argument == null) | |
| 111 return argument; | |
| 112 | |
| 113 if (argument is num || argument is String || argument is bool) | |
| 114 return argument; | |
| 115 | |
| 116 if (argument is ChromeObject) | |
| 117 return convertArgument(argument._serialize()); | |
| 118 | |
| 119 if (argument is List) | |
| 120 return _convertListArgument(argument); | |
| 121 | |
| 122 if (argument is Map) | |
| 123 return _convertMapArgument(argument); | |
| 124 | |
| 125 if (argument is Function) | |
| 126 throw new Exception("Cannot serialize Function argument ${argument}."); | |
| 127 | |
| 128 // TODO(sashab): Try and detect whether the argument is already serialized. | |
| 129 return argument; | |
| 130 } | |
| 131 | |
| 132 /** | |
| 133 * Description of a declarative rule for handling events. | |
| 134 */ | |
| 135 class Rule extends ChromeObject { | |
| 136 String _id; | |
| 137 List _conditions; | |
| 138 List _actions; | |
| 139 int _priority; | |
| 140 | |
| 141 /* | |
| 142 * Public (Dart) constructor | |
| 143 */ | |
| 144 Rule({ | |
| 145 String id, | |
| 146 List conditions, | |
| 147 List actions, | |
| 148 int priority | |
| 149 }) : | |
| 150 _id = id, | |
| 151 _conditions = conditions, | |
| 152 _actions = actions, | |
| 153 _priority = priority | |
| 154 ; | |
| 155 | |
| 156 /* | |
| 157 * Private (JS) constructor | |
| 158 */ | |
| 159 Rule._proxy(_jsObject) | |
| 160 : super._proxy(_jsObject); | |
| 161 | |
| 162 /* | |
| 163 * Serialisation method | |
| 164 */ | |
| 165 Map _toMap() { | |
| 166 Map m = {}; | |
| 167 if (id != null) m['id'] = id; | |
| 168 if (conditions != null) m['conditions'] = conditions; | |
| 169 if (actions != null) m['actions'] = actions; | |
| 170 if (priority != null) m['priority'] = priority; | |
| 171 return m; | |
| 172 } | |
| 173 | |
| 174 /* | |
| 175 * Public accessors | |
| 176 */ | |
| 177 String get id { | |
| 178 if (!this._hasProxy()) | |
| 179 return this._id; | |
| 180 return JS('String', '#.id', this._jsObject); | |
| 181 } | |
| 182 | |
| 183 void set id(String id) { | |
| 184 if (!this._hasProxy()) | |
| 185 this._id = id; | |
| 186 else | |
| 187 JS('void', '#.id = #', this._jsObject, convertArgument(id)); | |
| 188 } | |
| 189 | |
| 190 List get conditions { | |
| 191 if (!this._hasProxy()) | |
| 192 return this._conditions; | |
| 193 return JS('List', '#.conditions', this._jsObject); | |
| 194 } | |
| 195 | |
| 196 void set conditions(List conditions) { | |
| 197 if (!this._hasProxy()) | |
| 198 this._conditions = conditions; | |
| 199 else | |
| 200 JS('void', '#.conditions = #', this._jsObject, convertArgument(conditions) ); | |
|
blois
2013/01/23 02:06:12
line length
sashab
2013/01/23 04:45:34
Done, except for the comments on Events
| |
| 201 } | |
| 202 | |
| 203 List get actions { | |
| 204 if (!this._hasProxy()) | |
| 205 return this._actions; | |
| 206 return JS('List', '#.actions', this._jsObject); | |
| 207 } | |
| 208 | |
| 209 void set actions(List actions) { | |
| 210 if (!this._hasProxy()) | |
| 211 this._actions = actions; | |
| 212 else | |
| 213 JS('void', '#.actions = #', this._jsObject, convertArgument(actions)); | |
| 214 } | |
| 215 | |
| 216 int get priority { | |
| 217 if (!this._hasProxy()) | |
| 218 return this._priority; | |
| 219 return JS('int', '#.priority', this._jsObject); | |
| 220 } | |
| 221 | |
| 222 void set priority(int priority) { | |
| 223 if (!this._hasProxy()) | |
| 224 this._priority = priority; | |
| 225 else | |
| 226 JS('void', '#.priority = #', this._jsObject, convertArgument(priority)); | |
| 227 } | |
| 228 | |
| 229 } | |
| 230 | |
| 231 /** | |
| 232 * The Event class. | |
| 233 * | |
| 234 * Chrome Event classes extend this interface. | |
| 235 * | |
| 236 * e.g. | |
| 237 * | |
| 238 * // chrome.app.runtime.onLaunched | |
| 239 * class $Event_ChromeAppRuntimeOnLaunched extends $Event { | |
|
blois
2013/01/23 02:06:12
For DOM events, we're moving them over to streams.
sashab
2013/01/23 04:45:34
We could change these to be streams later? Are the
| |
| 240 * // constructor, passing the arity of the callback | |
| 241 * $Event_ChromeAppRuntimeOnLaunched(jsObject) : | |
| 242 * super._(jsObject, 1); | |
| 243 * | |
| 244 * // methods, strengthening the Function parameter specificity | |
| 245 * void addListener(void callback(LaunchData launchData)) | |
| 246 * => super.addListener(callback); | |
| 247 * void removeListener(void callback(LaunchData launchData)) | |
| 248 * => super.removeListener(callback); | |
| 249 * bool hasListener(void callback(LaunchData launchData)) | |
| 250 * => super.hasListener(callback); | |
| 251 * } | |
| 252 * | |
| 253 */ | |
| 254 class $Event { | |
|
blois
2013/01/23 02:06:12
Why the leading $?
sashab
2013/01/23 04:45:34
To distinguish it from html:Event. Should I just c
Emily Fortuna
2013/01/23 19:28:04
I made a comment on this in another version of thi
sashab
2013/01/23 22:24:53
I guess I'm just worried because I'm importing dar
| |
| 255 // JS var | |
| 256 Object _jsObject; | |
| 257 | |
| 258 // number of arguments the callback takes | |
| 259 int _callbackArity; | |
| 260 | |
| 261 // constructor | |
| 262 $Event._(this._jsObject, this._callbackArity); | |
| 263 | |
| 264 // methods | |
| 265 | |
| 266 /** | |
| 267 * Registers an event listener <em>callback</em> to an event. | |
| 268 */ | |
| 269 void addListener(Function callback) => | |
| 270 JS('void', | |
| 271 '#.addListener(#)', | |
| 272 this._jsObject, | |
| 273 convertDartClosureToJS(callback, this._callbackArity) | |
| 274 ); | |
| 275 | |
| 276 /** | |
| 277 * Deregisters an event listener <em>callback</em> from an event. | |
| 278 */ | |
| 279 void removeListener(Function callback) => | |
| 280 JS('void', | |
| 281 '#.removeListener(#)', | |
| 282 this._jsObject, | |
| 283 convertDartClosureToJS(callback, this._callbackArity) | |
| 284 ); | |
| 285 | |
| 286 /** | |
| 287 * Returns True if <em>callback</em> is registered to the event. | |
| 288 */ | |
| 289 bool hasListener(Function callback) => | |
| 290 JS('bool', | |
| 291 '#.hasListener(#)', | |
| 292 this._jsObject, | |
| 293 convertDartClosureToJS(callback, this._callbackArity) | |
| 294 ); | |
| 295 | |
| 296 /** | |
| 297 * Returns true if any event listeners are registered to the event. | |
| 298 */ | |
| 299 bool hasListeners() => | |
| 300 JS('bool', | |
| 301 '#.hasListeners()', | |
| 302 this._jsObject | |
| 303 ); | |
| 304 | |
| 305 /** | |
| 306 * Registers rules to handle events. | |
| 307 * | |
| 308 * @param eventName Name of the event this function affects. | |
|
blois
2013/01/23 02:06:12
Dart doesn't use JS-style param comments.
sashab
2013/01/23 04:45:34
These were taken from events.idl. Should I just re
| |
| 309 * @param rules Rules to be registered. These do not replace previously regist ered rules. | |
| 310 * @param callback Called with registered rules. | |
| 311 */ | |
| 312 void addRules(String eventName, List<Rule> rules, [ void callback(List<Rule> r ules) ]) { | |
|
blois
2013/01/23 02:06:12
Usually no space between [ and arg-
rules, [void
blois
2013/01/23 02:06:12
80 char line length (and more below)
sashab
2013/01/23 04:45:34
Done.
sashab
2013/01/23 04:45:34
Done (except for Event comments).
| |
| 313 // proxy the callback | |
| 314 void __proxied_callback(List rules) {}; | |
| 315 | |
| 316 if (callback != null) | |
| 317 void __proxied_callback(List rules) { | |
| 318 List<Rule> __proxy_rules = new List<Rule>(); | |
| 319 | |
| 320 for (Object o in rules) | |
| 321 __proxy_rules.add(new Rule._proxy(o)); | |
| 322 | |
| 323 callback(__proxy_rules); | |
| 324 } | |
| 325 | |
| 326 JS('void', | |
| 327 '#.addRules(#, #, #)', | |
| 328 this._jsObject, | |
| 329 convertArgument(eventName), | |
| 330 convertArgument(rules), | |
| 331 convertDartClosureToJS(callback, 1) | |
| 332 ); | |
| 333 } | |
| 334 | |
| 335 /** | |
| 336 * Returns currently registered rules. | |
| 337 * | |
| 338 * @param eventName Name of the event this function affects. | |
| 339 * @param ruleIdentifiers If an array is passed, only rules with identifiers c ontained in this array are returned. | |
| 340 * @param callback Called with registered rules. | |
| 341 */ | |
| 342 void getRules(String eventName, [ List<String> ruleIdentifiers, void callback( List<Rule> rules) ]) { | |
| 343 // proxy the callback | |
| 344 void __proxied_callback(List rules) {}; | |
| 345 | |
| 346 if (callback != null) | |
| 347 void __proxied_callback(List rules) { | |
| 348 List<Rule> __proxy_rules = new List<Rule>(); | |
| 349 | |
| 350 for (Object o in rules) | |
| 351 __proxy_rules.add(new Rule._proxy(o)); | |
| 352 | |
| 353 callback(__proxy_rules); | |
| 354 } | |
| 355 | |
| 356 JS('void', | |
| 357 '#.getRules(#, #, #)', | |
| 358 this._jsObject, | |
| 359 convertArgument(eventName), | |
| 360 convertArgument(ruleIdentifiers), | |
| 361 convertDartClosureToJS(callback, 1) | |
| 362 ); | |
| 363 } | |
| 364 | |
| 365 /** | |
| 366 * Unregisters currently registered rules. | |
| 367 * | |
| 368 * @param eventName Name of the event this function affects. | |
| 369 * @param ruleIdentifiers If an array is passed, only rules with identifiers c ontained in this array are unregistered. | |
| 370 * @param callback Called when rules were unregistered. | |
| 371 */ | |
| 372 void removeRules(String eventName, [ List<String> ruleIdentifiers, void callba ck() ]) => | |
| 373 JS('void', | |
| 374 '#.removeRules(#, #, #)', | |
| 375 this._jsObject, | |
| 376 convertArgument(eventName), | |
| 377 convertArgument(ruleIdentifiers), | |
| 378 convertDartClosureToJS(callback, 0) | |
| 379 ); | |
| 380 } | |
| 381 | |
| 382 | |
| 383 | |
| 384 | |
| 385 | |
| 386 | |
| 387 | |
| 388 | |
| 389 | |
| 390 | |
| 391 | |
| 392 | |
| OLD | NEW |