Chromium Code Reviews| Index: tools/dom/src/chrome/utils.dart |
| diff --git a/tools/dom/src/chrome/utils.dart b/tools/dom/src/chrome/utils.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..9c45f853bf7b151a93ac7f0cf5556e9e3ed71add |
| --- /dev/null |
| +++ b/tools/dom/src/chrome/utils.dart |
| @@ -0,0 +1,327 @@ |
| +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +/** |
| + * A set of utilities for use with the Chrome Extension APIs. |
| + * |
| + * Allows for easy access to required JS objects. |
| + */ |
| +part of chrome; |
| + |
| +/** |
| + * A dart object, that is convertible to JS. Used for creating objects in dart, |
| + * then passing them to JS. |
| + * |
| + * Objects that are passable to JS need to implement this interface. |
| + */ |
| +abstract class ChromeObject { |
| + /* |
| + * Default Constructor |
| + * |
| + * Called by child objects during their regular construction. |
| + */ |
| + ChromeObject() : |
| + _jsObject = JS('var', '{}'); |
| + |
| + /* |
| + * Internal proxy constructor |
| + * |
| + * Creates a new Dart object using this existing proxy. |
| + */ |
| + ChromeObject._proxy(this._jsObject); |
| + |
| + /* |
| + * JS Object Representation |
| + */ |
| + Object _jsObject; |
| + |
| + /* |
| + * Retrieves the field of the given name. |
| + * |
| + * Returns the base JS representation of the object. |
| + */ |
| + Object getMember(String type, String fieldName) { |
| + return JS(type, '#[#]', this._jsObject, fieldName); |
| + } |
| + |
| + /* |
| + * Sets the field of the given name to the given value. |
| + * |
| + * Attempts to convert the given value to JS before assignment. |
| + */ |
| + void setMember(String fieldName, Object value) { |
| + JS('void', '#[#] = #', this._jsObject, fieldName, convertArgument(value)); |
| + } |
|
vsm
2013/01/23 20:44:50
I'm not sure it's worth having these helper method
sashab
2013/01/23 22:24:53
Is the type strongly enforced in the method signat
sashab
2013/01/24 22:21:33
The other reason I want to have it is this:
void
|
| +} |
| + |
| +/** |
| + * Useful functions for converting arguments. |
| + */ |
| + |
| +/** |
| + * Converts the given map-type argument to js-friendly format, recursively. |
| + * Returns the new Map object. |
| + */ |
| +Object _convertMapArgument(Map argument) { |
| + Map m = new Map(); |
| + for (Object key in argument.keys) |
| + m[key] = convertArgument(argument[key]); |
| + return convertDartToNative_Dictionary(m); |
| +} |
| + |
| +/** |
| + * Converts the given list-type argument to js-friendly format, recursively. |
| + * Returns the new List object. |
| + */ |
| +List _convertListArgument(List argument) { |
| + List l = new List(); |
| + for (var i = 0; i < argument.length; i ++) |
| + l.add(convertArgument(argument[i])); |
| + return l; |
| +} |
| + |
| +/** |
| + * Converts the given argument Object to js-friendly format, recursively. |
| + * |
| + * Flattens out all Chrome objects into their corresponding ._toMap() |
| + * definitions, then converts them to JS objects. |
| + * |
| + * Returns the new argument. |
| + * |
| + * Cannot be used for functions. |
| + */ |
| +Object convertArgument(var argument) { |
| + if (argument == null) |
| + return argument; |
| + |
| + if (argument is num || argument is String || argument is bool) |
| + return argument; |
| + |
| + if (argument is ChromeObject) |
| + return argument._jsObject; |
| + |
| + if (argument is List) |
| + return _convertListArgument(argument); |
| + |
| + if (argument is Map) |
| + return _convertMapArgument(argument); |
| + |
| + if (argument is Function) |
| + throw new Exception("Cannot serialize Function argument ${argument}."); |
| + |
| + // TODO(sashab): Try and detect whether the argument is already serialized. |
| + return argument; |
| +} |
| + |
| +/** |
| + * Description of a declarative rule for handling events. |
| + */ |
| +class Rule extends ChromeObject { |
| + /* |
| + * Public (Dart) constructor |
| + */ |
| + Rule({String id, List conditions, List actions, int priority}) { |
| + this.id = id; |
| + this.conditions = conditions; |
| + this.actions = actions; |
| + this.priority = priority; |
| + } |
| + |
| + /* |
| + * Private (JS) constructor |
| + */ |
| + Rule._proxy(_jsObject) |
| + : super._proxy(_jsObject); |
| + |
| + /* |
| + * Public accessors |
| + */ |
| + String get id => |
| + getMember('String', 'id'); |
| + |
| + void set id(String id) => |
| + setMember('id', id); |
| + |
| + // TODO(sashab): Wrap these generic Lists somehow. |
| + List get conditions => |
| + getMember('List', 'conditions'); |
| + |
| + void set conditions(List conditions) => |
| + setMember('conditions', conditions); |
| + |
| + // TODO(sashab): Wrap these generic Lists somehow. |
| + List get actions => |
| + getMember('List', 'actions'); |
| + |
| + void set actions(List actions) => |
| + setMember('actions', actions); |
| + |
| + int get priority => |
| + getMember('int', 'priority'); |
| + |
| + void set priority(int priority) => |
| + setMember('priority', priority); |
| + |
| +} |
| + |
| +/** |
| + * The Event class. |
| + * |
| + * Chrome Event classes extend this interface. |
| + * |
| + * e.g. |
| + * |
| + * // chrome.app.runtime.onLaunched |
| + * class $Event_ChromeAppRuntimeOnLaunched extends $Event { |
| + * // constructor, passing the arity of the callback |
| + * $Event_ChromeAppRuntimeOnLaunched(jsObject) : |
| + * super._(jsObject, 1); |
| + * |
| + * // methods, strengthening the Function parameter specificity |
| + * void addListener(void callback(LaunchData launchData)) |
| + * => super.addListener(callback); |
| + * void removeListener(void callback(LaunchData launchData)) |
| + * => super.removeListener(callback); |
| + * bool hasListener(void callback(LaunchData launchData)) |
| + * => super.hasListener(callback); |
| + * } |
| + * |
| + */ |
| +class $Event { |
| + /* |
| + * JS Object Representation |
| + */ |
| + Object _jsObject; |
| + |
| + /* |
| + * Number of arguments the callback takes. |
| + */ |
| + int _callbackArity; |
| + |
| + /* |
| + * Private constructor |
| + */ |
| + $Event._(this._jsObject, this._callbackArity); |
| + |
| + /* |
| + * Methods |
| + */ |
| + |
| + /** |
| + * Registers an event listener <em>callback</em> to an event. |
| + */ |
| + void addListener(Function callback) => |
| + JS('void', |
| + '#.addListener(#)', |
| + this._jsObject, |
| + convertDartClosureToJS(callback, this._callbackArity) |
| + ); |
| + |
| + /** |
| + * Deregisters an event listener <em>callback</em> from an event. |
| + */ |
| + void removeListener(Function callback) => |
| + JS('void', |
| + '#.removeListener(#)', |
| + this._jsObject, |
| + convertDartClosureToJS(callback, this._callbackArity) |
| + ); |
| + |
| + /** |
| + * Returns True if <em>callback</em> is registered to the event. |
| + */ |
| + bool hasListener(Function callback) => |
| + JS('bool', |
| + '#.hasListener(#)', |
| + this._jsObject, |
| + convertDartClosureToJS(callback, this._callbackArity) |
| + ); |
| + |
| + /** |
| + * Returns true if any event listeners are registered to the event. |
| + */ |
| + bool hasListeners() => |
| + JS('bool', |
| + '#.hasListeners()', |
| + this._jsObject |
| + ); |
| + |
| + /** |
| + * Registers rules to handle events. |
| + * |
| + * @param eventName Name of the event this function affects. |
| + * @param rules Rules to be registered. These do not replace previously registered rules. |
| + * @param callback Called with registered rules. |
| + */ |
| + void addRules(String eventName, List<Rule> rules, |
| + [void callback(List<Rule> rules)]) { |
| + // proxy the callback |
| + void __proxy_callback(List rules) { |
| + if (?callback) { |
| + List<Rule> __proxy_rules = new List<Rule>(); |
| + |
| + for (Object o in rules) |
| + __proxy_rules.add(new Rule._proxy(o)); |
| + |
| + callback(__proxy_rules); |
| + } |
| + } |
| + |
| + JS('void', |
| + '#.addRules(#, #, #)', |
| + this._jsObject, |
| + convertArgument(eventName), |
| + convertArgument(rules), |
| + convertDartClosureToJS(__proxy_callback, 1) |
| + ); |
| + } |
| + |
| + /** |
| + * Returns currently registered rules. |
| + * |
| + * @param eventName Name of the event this function affects. |
| + * @param ruleIdentifiers If an array is passed, only rules with identifiers contained in this array are returned. |
| + * @param callback Called with registered rules. |
| + */ |
| + void getRules(String eventName, [List<String> ruleIdentifiers, |
| + void callback(List<Rule> rules)]) { |
| + // proxy the callback |
| + void __proxy_callback(List rules) { |
| + if (?callback) { |
| + List<Rule> __proxy_rules = new List<Rule>(); |
| + |
| + for (Object o in rules) |
| + __proxy_rules.add(new Rule._proxy(o)); |
| + |
| + callback(__proxy_rules); |
| + } |
| + } |
| + |
| + JS('void', |
| + '#.getRules(#, #, #)', |
| + this._jsObject, |
| + convertArgument(eventName), |
| + convertArgument(ruleIdentifiers), |
| + convertDartClosureToJS(__proxy_callback, 1) |
| + ); |
| + } |
| + |
| + /** |
| + * Unregisters currently registered rules. |
| + * |
| + * @param eventName Name of the event this function affects. |
| + * @param ruleIdentifiers If an array is passed, only rules with identifiers contained in this array are unregistered. |
|
Emily Fortuna
2013/01/23 19:28:04
80 char....
sashab
2013/01/23 22:24:53
Done.
|
| + * @param callback Called when rules were unregistered. |
| + */ |
| + void removeRules(String eventName, [List<String> ruleIdentifiers, |
| + void callback()]) => |
| + JS('void', |
| + '#.removeRules(#, #, #)', |
| + this._jsObject, |
| + convertArgument(eventName), |
| + convertArgument(ruleIdentifiers), |
| + convertDartClosureToJS(callback, 0) |
| + ); |
| +} |
| + |