| // 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 |
| */ |
| final Object _jsObject; |
| } |
| |
| /** |
| * 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 => JS('String', '#.id', this._jsObject); |
| |
| void set id(String id) { |
| JS('void', '#.id = #', this._jsObject, id); |
| } |
| |
| // TODO(sashab): Wrap these generic Lists somehow. |
| List get conditions => JS('List', '#.conditions', this._jsObject); |
| |
| void set conditions(List conditions) { |
| JS('void', '#.conditions = #', this._jsObject, convertArgument(conditions)); |
| } |
| |
| // TODO(sashab): Wrap these generic Lists somehow. |
| List get actions => JS('List', '#.actions', this._jsObject); |
| |
| void set actions(List actions) { |
| JS('void', '#.actions = #', this._jsObject, convertArgument(actions)); |
| } |
| |
| int get priority => JS('int', '#.priority', this._jsObject); |
| |
| void set priority(int priority) { |
| JS('void', '#.priority = #', this._jsObject, 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 |
| */ |
| final Object _jsObject; |
| |
| /* |
| * Number of arguments the callback takes. |
| */ |
| final 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. |
| /// |
| /// [eventName] is the name of the event this function affects and [rules] are |
| /// the rules to be registered. These do not replace previously registered |
| /// rules. [callback] is 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 != null) { |
| 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. |
| /// |
| /// [eventName] is the name of the event this function affects and, if an array |
| /// is passed as [ruleIdentifiers], only rules with identifiers contained in |
| /// this array are returned. [callback] is 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 != null) { |
| 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. |
| /// |
| /// [eventName] is the name of the event this function affects and, if an array |
| /// is passed as [ruleIdentifiers], only rules with identifiers contained in |
| /// this array are unregistered. [callback] is called when the rules are |
| /// unregistered. |
| /// |
| void removeRules(String eventName, [List<String> ruleIdentifiers, |
| void callback()]) => |
| JS('void', |
| '#.removeRules(#, #, #)', |
| this._jsObject, |
| convertArgument(eventName), |
| convertArgument(ruleIdentifiers), |
| convertDartClosureToJS(callback, 0) |
| ); |
| } |
| |