2 * DBus.js, a JS wrapper for the Browser D-Bus Bridge
3 * Copyright (c) 2008-2009 Movial Creative Technologies Inc
5 * Contact: Movial Creative Technologies Inc, <info@movial.com>
6 * Authors: Lauri Mylläri, <lauri.myllari@movial.com>
7 * Kalle Vahlman, <kalle.vahlman@movial.com>
8 * Ehsun Amanolahi, <ehsun.amanolahi@movial.com>
10 * Permission is hereby granted, free of charge, to any person
11 * obtaining a copy of this software and associated documentation
12 * files (the "Software"), to deal in the Software without
13 * restriction, including without limitation the rights to use,
14 * copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following
19 * The above copyright notice and this permission notice shall be
20 * included in all copies or substantial portions of the Software.
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
24 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
29 * OTHER DEALINGS IN THE SOFTWARE.
33 * @fileOverview The Browser D-Bus Bridge JavaScript API.
34 * @author <a href="mailto:kalle.vahlman@movial.com">Kalle Vahlman</a>
35 * @author <a href="mailto:lauri.myllari@movial.com">Lauri Mylläri</a>
36 * @author <a href="mailto:ehsun.amanolahi@movial.com">Ehsun Amanolahi</a>
43 * This is the Gecko wrapping for the Browser D-Bus Bridge API
44 * You can use the XPCOM API directly, but the Bridge API
46 * - has few utility features over the "raw" API (like introspection)
47 * - generally feels a bit more JavaScriptish (hopefully)
51 var ep = netscape.security.PrivilegeManager.enablePrivilege;
52 ep("UniversalXPConnect");
53 var cc = Components.classes;
54 var ci = Components.interfaces;
58 * Utility function that creates a wrapper function which handles signature
59 * conversion from wrapper(argarray) to method(arg1, ..., argN) and sets
60 * 'this' to point to the user-specified object. This is mainly used to
61 * convert the variant arrays from the XPCOM service to callback arguments.
63 var unWrap = function(method, user_data) {
66 method.apply(user_data, arguments[0]);
73 * Returns a function to create an nsIVariant carrying the given value
74 * as the specified variant type.
76 var makeVariantMaker = function(variant_type) {
77 return function(val) {
78 ep("UniversalXPConnect");
79 var variant = cc["@mozilla.org/variant;1"].createInstance(ci.nsIWritableVariant);
80 variant['setAs' + variant_type](val);
87 * @class The Browser D-Bus Bridge API.
89 * <p>The Browser D-Bus Bridge is a JavaScript
90 * <a href="http://dbus.freedesktop.org">D-Bus</a> bindings implementation
91 * for web browsers. The Bridge allows privileged JavaScript code to talk to
92 * the D-Bus, both session and system bus (if not prohibited by the D-Bus
94 * <p>Since the implementation differs between web browser
95 * engines, the Bridge defines and implements a unified API (referred to as
96 * "the Bridge API") to access D-Bus. While you can always use the
97 * implementation-specific APIs, their stability is not guaranteed. They
98 * also might not support extra features of the Bridge API
99 * (like introspection).
100 * <h2>Notes about types</h2>
101 * <p>The D-Bus specification introduces 16 distinct data types of which 12
102 * are "simple" types and 4 are container types. This is a bit of a problem
103 * since JavaScript inherenetly only supports five basic types; Boolean,
104 * Number, String, Array and Object. There are three ways how the Bridge
105 * solves this problem: signatures, autodetection and conversion methods.
106 * <p>Every D-Bus message includes a
107 * <a href="http://dbus.freedesktop.org/doc/dbus-specification.html
108 * #message-protocol-signatures">signature</a> specifying the types of the
109 * data it carries. This information has three sources: for signals the
110 * received D-Bus message itself, the introspection data of a service and
111 * the user of the Bridge API.
112 * <p>When the signature is known, the Bridge knows what type the arguments
113 * should be and can (try to) automatically convert the data to the right
115 * <p>If there is no signature information available, the Bridge tries to
116 * autodetect the signature. Since there are only five basic types in
117 * JavaScript, this only works with the following:
119 * <li>JavaScript Boolean to DBUS_TYPE_BOOLEAN
120 * <li>JavaScript Number to DBUS_TYPE_DOUBLE
121 * <li>JavaScript String to DBUS_TYPE_BOOLEAN
122 * <li>JavaScript Array to DBUS_TYPE_ARRAY
123 * <li>JavaScript Object to D-Bus DICT type (properties as key-value pairs)
125 * <p>The rest of the types need to be "marked" as specific D-Bus types with
126 * the conversion methods. The methods are implementation specific, which
127 * means you cannot rely on the return value of the conversion methods. They
128 * are meant to only be used when passing arguments to method calls or
129 * signals. You will also never be given such object by the Bridge in
130 * callbacks, all D-Bus message arguments are converted to one of the five
131 * JavaScript types before handing them to the callback.
133 * for example the ObjectPath and Signature types are simply strings in the
134 * callback. Other exceptions are Structs and Variants. D-Bus Structs are
135 * basically just a way to implement a mixed-type array, so they are
136 * represented as such in the Bridge API. Variants are a container type that
137 * allows any type of content (the type is encoded along with the value),
138 * but since JavaScript values have no static typing it is always passed as
139 * the contained value to the callbacks.
140 * <h2>Getting started</h2>
141 * <p>To get started with using the Bridge, continue to the
142 * <a href="#constructor">details section of the main class</a>.<br>
143 * @description The D-Bus singleton class.
144 * <p>The D-Bus Bridge API is based on a singleton class called DBus,
145 * through which all operations are made. To get this singleton to your web
146 * application, include the <em>dbus.js</em> in the <em>head</em> section:
147 * <p><code><script type='text/javascript' src='dbus.js'></script>
149 * <p>The DBus singleton is instantiated by <em>dbus.js</em> as a member of
150 * the global 'window' object. In other type of applications the
151 * <em>dbus.js</em> needs to be loaded and executed in whatever way is
152 * available before the Bridge API can be used.
153 * <p>The example code in this documentation uses an imaginary
154 * <em>Notes</em> service which is specified below. The specification is in
155 * <a href="http://dbus.freedesktop.org/doc/dbus-specification.html
156 * #introspection-format">the introspection data format</a>
157 * of D-Bus, the same type of data which you get by introspecting a service.
158 * <p>The preferred method of accessing a D-Bus service is to create an
159 * <em>interface object</em> with the <a href="#getInterface">
160 * dbus.getInterface()</a> method. It will automatically map an interface
161 * of a service that supports the <em>org.freedesktop.DBus.Introspectable
162 * </em> interface to a JavaSript object. If the service does not support
163 * introspection, you need to use the <a href="#getMethod">dbus.getMethod()
164 * </a> and <a href="#getSignal">dbus.getSignal()</a> methods directly to
167 * <caption>The imaginary Notes interface specification</caption>
169 * <?xml version="1.0" encoding="UTF-8"?>
170 * <node name="/org/movial/Notes">
171 * <interface name="org.movial.Notes">
174 * Adds a new note from a dictionary. The key "topic" is a string
175 * to define what the note is about, the rest of the keys are freeform
176 * content shown as a definition list in the note. Returns an ID to
177 * identify the note later.
179 * <method name="AddNote">
180 * <arg name="note_content" type="a{sv}" direction="in" />
181 * <arg name="note_id" type="u" direction="out" />
184 * <!-- Removes the note specified by the id. -->
185 * <method name="RemoveNote">
186 * <arg name="note_id" type="u" direction="in" />
189 * <!-- Emitted when a note is added -->
190 * <signal name="NoteAdded">
191 * <arg name="note_id" type="u" direction="out" />
192 * <arg name="note_content" type="a{sv}" direction="out" />
195 * <!-- Emitted when a note is removed -->
196 * <signal name="NoteRemoved">
197 * <arg name="note_id" type="u" direction="out" />
207 ep("UniversalXPConnect");
208 this.dbus = cc["@movial.com/dbus/service;1"].getService();
209 this.dbus = this.dbus.QueryInterface(Components.interfaces.IDBusService);
211 // Mirror static properties
212 DBus.prototype.SYSTEM = this.dbus.SYSTEM;
213 DBus.prototype.SESSION = this.dbus.SESSION;
217 // Methods for non-variant and non-automatic type conversions
220 * Converts the given value to a D-Bus UInt32
222 * @param val Value to convert
223 * @returns An object encapsulating a D-Bus value. It is not possible to
224 * convert the return value back to the original value.
226 DBus.prototype.UInt32 = makeVariantMaker("Uint32");
229 * Converts the given value to a D-Bus Int32
231 * @param val Value to convert
232 * @returns An object encapsulating a D-Bus value. It is not possible to
233 * convert the return value back to the original value.
235 DBus.prototype.Int32 = makeVariantMaker("Int32");
238 * Converts the given value to a D-Bus UInt16
240 * @param val Value to convert
241 * @returns An object encapsulating a D-Bus value. It is not possible to
242 * convert the return value back to the original value.
244 DBus.prototype.UInt16 = makeVariantMaker("Uint16");
247 * Converts the given value to a D-Bus Int16
249 * @param val Value to convert
250 * @returns An object encapsulating a D-Bus value. It is not possible to
251 * convert the return value back to the original value.
253 DBus.prototype.Int16 = makeVariantMaker("Int16");
256 * Converts the given value to a D-Bus UInt64
258 * @param val Value to convert
259 * @returns An object encapsulating a D-Bus value. It is not possible to
260 * convert the return value back to the original value.
262 DBus.prototype.UInt64 = makeVariantMaker("Uint64");
265 * Converts the given value to a D-Bus Int64
267 * @param val Value to convert
268 * @returns An object encapsulating a D-Bus value. It is not possible to
269 * convert the return value back to the original value.
271 DBus.prototype.Int64 = makeVariantMaker("Int64");
274 * Converts the given value to a D-Bus Byte
276 * @param val Value to convert
277 * @returns An object encapsulating a D-Bus value. It is not possible to
278 * convert the return value back to the original value.
280 DBus.prototype.Byte = makeVariantMaker("Int8");
283 * Converts the given value to a D-Bus ObjectPath
285 * @param val Value to convert
286 * @returns An object encapsulating a D-Bus value. It is not possible to
287 * convert the return value back to the original value.
289 DBus.prototype.ObjectPath = function(val) {
290 ep("UniversalXPConnect");
291 var carrier = cc["@movial.com/dbus/datacarrier;1"].createInstance(ci.IDBusDataCarrier);
298 * Converts the given value to a D-Bus Signature
300 * @param val Value to convert
301 * @returns An object encapsulating a D-Bus value. It is not possible to
302 * convert the return value back to the original value.
304 DBus.prototype.Signature = function(val) {
305 ep("UniversalXPConnect");
306 var carrier = cc["@movial.com/dbus/datacarrier;1"].createInstance(ci.IDBusDataCarrier);
313 * Converts the given value to a D-Bus Variant
315 * @param val Value to convert
316 * @returns An object encapsulating a D-Bus value. It is not possible to
317 * convert the return value back to the original value.
319 DBus.prototype.Variant = function(sig, val) {
320 ep("UniversalXPConnect");
321 var carrier = cc["@movial.com/dbus/datacarrier;1"].createInstance(ci.IDBusDataCarrier);
323 carrier.signature = sig;
329 * Converts the given value to a D-Bus Struct
331 * @param val Value to convert
332 * @returns An object encapsulating a D-Bus value. It is not possible to
333 * convert the return value back to the original value.
335 DBus.prototype.Struct = function(val) {
336 ep("UniversalXPConnect");
337 var carrier = cc["@movial.com/dbus/datacarrier;1"].createInstance(ci.IDBusDataCarrier);
343 // Lowlevel Bridge API methods
346 * Acquire a D-Bus Method object.
347 * @description <p>D-Bus method calls are handled as objects in the
348 * Bridge. You can instantiate a method object once and reuse it for
349 * multiple calls of the method. Method objects have two properties to
350 * wich you can set callback functions, <em>onreply</em> and
351 * <em>onerror</em>. The arguments of the callback functions depend
352 * on the interface specification.
353 * <p>The <em>onreply</em> callback is called when the method call has
354 * been made successfully and an reply message has beed received. The
355 * arguments of the callback depend on the interface specification.
356 * <p>The <em>onerror</em> callback is called when either the method
357 * call could not be made (due to wrong parameters or for other reasons)
358 * or the method call has been made, but resulted in an error message to
360 * <p>By default, the method calls are made asynchronously. If a
361 * synchronous method call is desired (so that the method call waits for
362 * a reply before returning), the <em>async</em> property can be set
363 * to <em>false</em>. As the call depends on reply from a separate
364 * process and can potentially take long to execute, synchronous calls
365 * should be avoided in order to not block the calling process (and thus
366 * possibly cause an unresponsive UI).
368 * <caption>Using the signal objects</caption>
369 * var addNote = dbus.getMethod(dbus.SESSION, 'org.movial.Notes',
370 * '/org/movial/Notes', 'AddNote');
372 * addNote.onreply = function(id){
373 * // The example reply message has signature of 'u'
376 * addNote.onerror = function(error, message) {
377 * // Error callbacks always have a name as the first argument and
378 * // possibly a descriptive message or other arguments following it.
379 * var msgstr = error + message ? message : ;
381 * msgstr += ': ' + message;
383 * alert('Adding a note failed!\n' + msgstr);
385 * // The signature of this method is 'a{sv}'. Dicts are mapped to
386 * // JavaScript Object class so we construct the argument using the
387 * // object construction notation. Variants are a container type which
388 * // holds any single complete type inside, but in the Bridge API they
389 * // are usually simply represented by their value.
390 * addNote( { "topic": "hot", "amount": 42 } );
394 * var removeNote = dbus.getMethod(dbus.SESSION, 'org.movial.Notes',
395 * '/org/movial/Notes', 'RemoveNote');
396 * // This time we choose not to care if it succeeds or not so we don't
397 * // supply onreply or onerror functions. This allows the actual D-Bus
398 * // message to be sent as "no reply expected" message.
399 * removeNote(noteID);
401 * @param bus dbus.SESSION or dbus.SYSTEM
402 * @param {String} dest destination service
403 * @param {String} path path of the object implementing the interface
404 * @param {String} method_name name of the method to acquire
405 * @param {String} inter interface to acquire
406 * @param {String} signature signature of the method, may be null
407 * @param {Object} data object to use as <em>this</em> in callbacks
408 * @returns {DBus.Method} method object or null on errors
410 DBus.prototype.getMethod = function(bustype,
420 * A wrapper function for method calls
421 * Executes the actual call through the XPCOM interface
423 var method = function() {
424 ep("UniversalXPConnect");
426 // The Array.prototype dance converts the "sort of Array but not
427 // quite" 'arguments' to a real Array object
428 method.dbusmethod.doCall(Array.prototype.slice.call(arguments),
431 if (method._onerror) {
432 method._onerror.apply(method.user_data, [e.toString()]);
437 // Store the user specified "this" object
438 method.user_data = user_data;
440 // Create the XPCOM method object
441 ep("UniversalXPConnect");
442 method.dbusmethod = this.dbus.getMethod(bustype,
449 /* XXX: Hmm? onreply and onerror are undefined here, no? */
450 method.dbusmethod.onReply = unWrap(method.onreply, method.user_data);
451 method.dbusmethod.onError = unWrap(method.onerror, method.user_data);
453 // Watch the onreply property and assign the callback through our
455 method.watch("onreply", function(id, oldval, newval) {
456 ep("UniversalXPConnect");
457 method.dbusmethod.onReply = unWrap(newval, method.user_data);
461 method.watch("onerror", function(id, oldval, newval) {
462 ep("UniversalXPConnect");
463 method.dbusmethod.onError = unWrap(newval, method.user_data);
464 // We need to shadow the property for some reason...
465 method._onerror = newval;
468 // Mirror the async property
470 method.watch("async", function(id, oldval, newval) {
471 ep("UniversalXPConnect");
472 method.dbusmethod.async = newval;
479 * Acquire a D-Bus Signal object.
480 * @description <p>D-Bus signals are handled as objects in the Bridge. You
481 * can instantiate a signal object once and reuse it for multiple sessions
482 * of listening to the signal.
483 * <p> The <em>enabled</em> property controls whether the signal is being
484 * listened to or not. In D-Bus terms, setting <em>enabled</em> to true
485 * adds a match rule with the specified arguments and setting it to false
487 * <p>The <em>onemit</em> property should be the function to call when
488 * when the signal is emitted on the message bus. The arguments of the
489 * callback depend on the interface specification. You can provide an
490 * object as the last argument for <em>getSignal()</em> which will be
491 * used as the <em>this</em> object in the callback.
493 * <caption>Using the signal objects</caption>
494 * var noteAdded = dbus.getSignal(dbus.SESSION,
495 * 'org.movial.Notes', 'NoteAdded',
497 * noteAdded.onemit = function(args) {
498 * // The signature of this signal is 'a{sv}'. 'args' is thus an object
499 * // and we can use the . accessor to get the values (variants are
500 * // always presented by their values in callbacks) since we know the
502 * alert(args.topic + "\n" + args.amount);
504 * noteAdded.enabled = true;
508 * // We are temporarily not interested in the signal so we disable it
509 * noteAdded.enabled = false;
511 * @param bus dbus.SESSION or dbus.SYSTEM
512 * @param {String} inter interface where the signal is
513 * @param {String} signal_name name of the signal
514 * @param {String} sender sender to filter by, usually null.
515 * @param {String} path object path to filter by, usually null.
516 * @param {Object} data object to use as <em>this</em> in the callback
517 * @returns {DBus.Signal} signal object or null on errors
519 DBus.prototype.getSignal = function(bustype,
527 // Create the XPCOM signal object
528 ep("UniversalXPConnect");
529 signal.dbussignal = this.dbus.getSignal(bustype,
535 // Store user-specified "this" for callbacks
536 signal.user_data = user_data;
538 // XXX: ummm.... onemit == undefined?
539 signal.dbussignal.onEmit = unWrap(signal.onemit, signal.user_data);
541 // Watch the onemit property for wrapping
542 signal.watch("onemit", function(id, oldval, newval) {
543 ep("UniversalXPConnect");
544 signal.dbussignal.onEmit = unWrap(newval, signal.user_data);
547 // Watch the enabled property for wrapping
548 signal.enabled = false;
549 signal.watch("enabled", function(id, oldval, newval) {
550 ep("UniversalXPConnect");
551 signal.dbussignal.enabled = newval;
559 * @description <p>Sends a signal message to the D-Bus.
561 * var notifyArgs = { "topic" : "hot", "amount" : 42 };
562 * var nodeID = generateNewIDForNote();
563 * if (!dbus.emitSignal(dbus.SESSION, '/org/movial/Notes',
564 * 'org.movial.Notes', 'NoteAdded',
565 * 'ua{sv}', noteID, notifyArgs)) {
566 * alert("Signal emission failed!");
569 * @param bus dbus.SESSION or dbus.SYSTEM
570 * @param {String} path object path that is sending the signal
571 * @param {String} inter interface where the signal is
572 * @param {String} signal_name name of the signal
573 * @param {String} signature signature of the signal, may be null
574 * @param arg1 first argument for the signal
576 * @param argN last argument for the signal
577 * @returns Boolean indicating if the emission was done succesfully
579 DBus.prototype.emitSignal = function() {
580 var args = arguments.splice(5);
581 ep("UniversalXPConnect");
582 this.dbus.emitSignal(arguments[0], arguments[1],
583 arguments[2], arguments[3],
584 arguments[4], args, args.length);
591 * Parses the interface description XML to a JS object
593 DBus.prototype.parseInterface = function(doc, bus, dest, path, inter){
595 var temp = doc.getElementsByTagName("interface");
596 //interesting interface is last
597 for( var i = temp.length - 1; i >=0; i--){
598 if( temp[i].getAttribute("name") != inter ) { continue; }
600 var methods = temp[i].getElementsByTagName("method");
601 for ( var j = 0, jl = methods.length; j < jl; j ++){
602 var name = methods[j].getAttribute("name");
604 var args = methods[j].getElementsByTagName("arg");
607 for( var z = 0, zl = args.length; z < zl; z ++){
609 if( args[z].getAttribute("direction") == "in"){
610 type.push(args[z].getAttribute("type") );
614 ret[name] = dbus.getMethod(bus, dest, path,
615 name, inter, type.join(""), ret );
619 var signals = temp[i].getElementsByTagName("signal");
620 for ( var j = 0, jl = signals.length; j < jl; j ++){
621 name = signals[j].getAttribute("name");
622 ret[name] = dbus.getSignal(bus,
624 this.object_path, ret);
625 ret[name].enabled = false;
626 ret[name].onemit = null;
628 ret.xml = (new XMLSerializer()).serializeToString(doc);
630 // break; //interface found
636 * Acquire an interface object through Introspection.
637 * <p>Uses the <em>Introspect</em> method on the standard
638 * <em>org.freedesktop.DBus.Introspectable</em> interface to map a given
639 * D-Bus interface to a JavaScript object. All methods and signals of that
640 * interface will be available as members of the object. You can refer to the
641 * <a href="#getMethod">getMethod()</a> and
642 * <a href="#getSignal">getSignal()</a> documentation to learn how to use the
643 * method and signal objects. The produced object is provided as <em>this</em>
644 * in the methods and signals.
645 * <p>Note that introspecting is not done asynchronously (to avoid requiring
646 * a callback to retrieve the interface object) so the <em>getInterface()</em>
647 * call will block until the service responds.
649 * <caption>Using the interface objects</caption>
650 * var notes = dbus.getInterface(dbus.SESSION,
651 * 'org.movial.Notes', '/org/movial/Notes',
652 * 'org.movial.Notes');
654 * // Set up listening to the "NoteAdded" signal.
655 * notes.NoteAdded.onemit = function(args) {
656 * // The signature of this signal is 'a{sv}'. 'args' is thus an object
657 * // and we can use the . accessor to get the values (variants are
658 * // always presented by their values in callbacks) since we know the
660 * alert(args.topic + "\n" + args.amount);
662 * notes.NoteAdded.enabled = true;
666 * notes.AddNote.onreply = function(id){
667 * // The example reply message has signature of 'u'
670 * notes.AddNote.onerror = function(error, message) {
671 * // Error callbacks always have a name as the first argument and
672 * // possibly a descriptive message or other arguments following it.
673 * var msgstr = error + message ? message : ;
675 * msgstr += ': ' + message;
677 * alert('Adding a note failed!\n' + msgstr);
679 * // The signature of this method is 'a{sv}'. Dicts are mapped to
680 * // JavaScript Object class so we construct the argument using the
681 * // object construction notation. Variants are a container type which
682 * // holds any single complete type inside, but in the Bridge API they
683 * // are usually simply represented by their value.
684 * notes.AddNote( { "topic": "hot", "amount": 42 } );
688 * // Remove the note we added earlier
689 * notes.RemoveNote( noteID );
690 * @param bus dbus.SESSION or dbus.SYSTEM
691 * @param {String} dest destination service
692 * @param {String} path object path
693 * @param {String} inter interface to acquire
694 * @returns {DBus.Interface} an object representing a D-Bus interface
696 DBus.prototype.getInterface = function(bus, dest, path, inter){
698 var introspect = dbus.getMethod(bus, dest, path,
700 "org.freedesktop.DBus.Introspectable" );
704 introspect.onreply = function(s){
705 doc = s.replace(/^\s*|\s*$/g,"");
710 introspect.onerror = function(s){
713 introspect.async = false;
720 doc = (new DOMParser()).parseFromString(doc, "text/xml");
722 return this.parseInterface(doc, bus, dest, path, inter);
726 * Conversion functions for default conversion types
727 * These are offered mainly just for completeness, there is usually no point in
728 * actually using them...
732 * Converts the given value to a D-Bus Boolean
733 * @param val Value to convert
734 * @returns An object encapsulating a D-Bus value. It is not possible to
735 * convert the return value back to the original value.
737 DBus.prototype.Boolean = function (val) { return Boolean(val); };
740 * Converts the given value to a D-Bus Double (the JS Number type)
741 * @param val Value to convert
742 * @returns An object encapsulating a D-Bus value. It is not possible to
743 * convert the return value back to the original value.
745 DBus.prototype.Double = function (val) { return Number(val); };
748 * Converts the given value to a D-Bus String
749 * @param val Value to convert
750 * @returns An object encapsulating a D-Bus value. It is not possible to
751 * convert the return value back to the original value.
753 DBus.prototype.String = function (val) { return String(val); };
756 * Converts the given value to a D-Bus Array
757 * @param val Value to convert
758 * @returns An object encapsulating a D-Bus value. It is not possible to
759 * convert the return value back to the original value.
761 DBus.prototype.Array = function (val) { return val; };
764 * Converts the given value to a D-Bus Dict
765 * @param val Value to convert
766 * @returns An object encapsulating a D-Bus value. It is not possible to
767 * convert the return value back to the original value.
769 DBus.prototype.Dict = function (val) { return val; };
771 // Instantiate the Bridge API singleton
773 window.dbus = new DBus();