xref: /openbmc/rest-dbus/resources/dbus.js (revision 9b0e0bab5150ccc4333ce442932f8969f365155e)
1
2var g_bus;
3var initial_state = {
4    'bus': 'session',
5};
6
7function populate_tree_services(node, cb, bus)
8{
9    jQuery.getJSON('/bus/' + bus.name, function(data) {
10            var children = [];
11            for (var i in data.objects) {
12                var service = data.objects[i];
13                if (service.name[0] == ':')
14                        continue;
15                children.push({
16                        'text': service.name,
17                        'children': true,
18                        'type': 'service',
19                        'bus': bus,
20                        'service': service,
21                    });
22            }
23            cb(children);
24    });
25}
26
27function populate_tree_objects(node, cb)
28{
29    var ctx = node.original;
30    jQuery.getJSON('/bus/' + ctx.bus.name + '/' + ctx.service.name,
31            function(data) {
32                var children = [];
33                for (var i in data.objects) {
34                    var obj = data.objects[i];
35                    children.push({
36                            'text': obj.path,
37                            'children': true,
38                            'type': 'object',
39                            'bus': ctx.bus,
40                            'service': ctx.service,
41                            'object': obj,
42                        });
43                }
44                cb(children);
45    });
46}
47
48function populate_tree_interfaces(node, cb)
49{
50    var ctx = node.original;
51    jQuery.getJSON('/bus/' + ctx.bus.name + '/' + ctx.service.name +
52                ctx.object.path,
53            function(data) {
54                console.log(data);
55                var children = [];
56                for (var i in data.interfaces) {
57                    var iface = data.interfaces[i];
58                    children.push({
59                            'text': iface.name,
60                            'children': true,
61                            'type': 'interface',
62                            'bus': ctx.bus,
63                            'service': ctx.service,
64                            'object': ctx.object,
65                            'interface': iface,
66                        });
67                }
68                cb(children);
69    });
70}
71
72function format_one_type(type)
73{
74    var ret = Object();
75    var basic_types = {
76        'v': 'variant',
77        'i': 'int32',
78        'x': 'int64',
79        'u': 'uint32',
80        't': 'uint64',
81        'g': 'type',
82        'h': 'file',
83        'd': 'double',
84        's': 'string',
85        'o': 'objpath',
86        'y': 'byte',
87        'b': 'boolean',
88    }
89
90    var c = type[0];
91    if (basic_types[c]) {
92        ret.type = basic_types[c];
93        ret.left = type.substring(1);
94        return ret;
95    }
96
97    if (c == '(') {
98        var i;
99        var n;
100        for (i = 1, n = 1; i < type.length; i++) {
101            var c = type[i];
102            if (c == '(')
103                n++;
104            if (c == ')')
105                if (--n == 0)
106                    break;
107
108        }
109        if (i == type.length)
110            return ret;
111        var content = type.substring(1, i);
112        ret.type = 'struct {' + format_types(content).join(', ') + '}';
113        ret.left = type.substring(i+1);
114        return ret;
115    }
116
117    if (c == 'a') {
118        var content = type.substring(1);
119        if (content[0] == '{') {
120            var i;
121            var n;
122            for (i = 1, n = 1; i < content.length; i++) {
123                var c = content[i];
124                if (c == '{')
125                    n++;
126                if (c == '}')
127                    if (--n == 0)
128                        break;
129
130            }
131            content = content.substring(1, i);
132            var types = format_types(content);
133            console.log("{", content, "}", types);
134            ret.type = 'dict {' + types[0] + ' → ' + types[1] + '}';
135            ret.left = type.substring(i+1);
136        } else {
137            var t = format_one_type(content);
138            ret.type = '[' + t.type + ']';
139            ret.left = t.left;
140        }
141        return ret;
142    }
143
144    ret.type = c;
145    ret.left = type.substring(1);
146    return ret;
147
148}
149
150function format_types(type)
151{
152    var t;
153    var ts = [];
154    for (;;) {
155        t = format_one_type(type);
156        ts.push(t.type);
157
158        if (!t.left || !t.left.length)
159            break;
160        type = t.left;
161    }
162    return ts;
163}
164
165function format_type(type)
166{
167    return format_types(type)[0];
168}
169
170function format_method_arg(arg)
171{
172    return '<span class="method-arg">' +
173            '<span class="method-arg-type">' + format_type(arg.type) +
174             '</span> ' +
175            '<span class="method-arg-name">' + arg.name + '</span></span>';
176}
177
178function format_method(method)
179{
180    var in_args = [];
181    var out_args = [];
182    for (var i in method.args) {
183        var arg = method.args[i];
184        var str = format_method_arg(arg);
185        if (arg.direction == 'in')
186            in_args.push(str);
187        else
188            out_args.push(str);
189    }
190    return '<span class="method">' +
191              '<span class="method-name">' + method.name + "</span>" +
192              '<span class="method-args">(' + in_args.join(', ') + ')</span>' +
193              ' → ' +
194              '<span class="method-args">' + out_args.join(', ') + '</span>' +
195              '</span>'
196}
197
198function format_property(name, value)
199{
200    return '<span class="property">' +
201            '<span class="property-name">' + name + '</span>' +
202            ' = ' +
203            '<span class="property-value">' + value + '</span>' +
204           '</span>'
205}
206
207function populate_tree_interface_items(node, cb)
208{
209    var ctx = node.original;
210    jQuery.getJSON('/bus/' + ctx.bus.name + '/' + ctx.service.name +
211                ctx.object.path + '/' + ctx.interface.name,
212            function(data) {
213                console.log(data);
214                var children = [];
215                for (var i in data.methods) {
216                    var method = data.methods[i];
217                    children.push({
218                            'text': format_method(method),
219                            'children': [],
220                            'type': 'method',
221                            'method': method,
222                            'bus': ctx.bus,
223                            'service': ctx.service,
224                            'object': ctx.object,
225                            'interface': ctx.interface,
226                        });
227                }
228                for (var i in data.properties) {
229                    var property = data.properties[i];
230                    children.push({
231                            'text': format_property(i, property),
232                            'children': [],
233                        });
234                }
235                cb(children);
236    });
237}
238function populate_tree(node, cb)
239{
240    if (!node.original) {
241        populate_tree_services(node, cb, g_bus);
242        return;
243    }
244
245    var type = node.original.type;
246    if (type == 'service') {
247        populate_tree_objects(node, cb);
248    } else if (type == 'object') {
249        populate_tree_interfaces(node, cb);
250    } else if (type == 'interface') {
251        populate_tree_interface_items(node, cb);
252    }
253}
254
255function select_node(evt, data)
256{
257    var ctx = data.node.original;
258    if (!ctx || ctx.type != 'method')
259        return;
260
261    var method = ctx.method;
262    jQuery("#method-call-ui").remove();
263
264    var container = data.instance.get_node(data.node, true);
265
266    var in_args = []
267    for (var i in method.args) {
268        var arg = method.args[i];
269        if (arg.direction != 'in')
270            continue;
271        in_args.push({
272            'type': format_method_arg(arg),
273            'idx': i,
274        });
275    }
276    method.nargs = in_args.length;
277
278    var template = jQuery.templates('#method-call-ui-template');
279    container.append(template.render({
280                'method': method,
281                'in_args': in_args,
282    }));
283    jQuery("form", container).submit(function(e) {
284            var form = jQuery(e.target);
285            var n = jQuery("input[name=argN]", form).val();
286            var data = [];
287            for (var i = 0; i < n; i++) {
288                var val = jQuery("input[name=arg" + i + ']', form).val();
289                try {
290                    data.push(JSON.parse(val));
291                } catch (e) {
292                    data.push(null);
293                }
294            }
295            jQuery.ajax(form.attr("action"),
296                    {
297                        'method': 'POST',
298                        'contentType': 'text/json',
299                        'data': JSON.stringify(data),
300                        'dataType': 'text',
301                        'success': function(data, status) {
302                            jQuery('#method-call-ui-result').text(data);
303                        },
304                    });
305            return false;
306    });
307}
308
309function set_bus(b)
310{
311    g_bus = b;
312    $('#container').jstree({
313        'core': {
314            'data': populate_tree,
315            'multiple': false,
316            'themes': {
317                'icons': false,
318            },
319        }
320    }).on('select_node.jstree', select_node);
321}
322
323function init()
324{
325    var select = jQuery('select#bus');
326    select.empty();
327    select.append(jQuery('<option>').text('---'));
328    jQuery.getJSON('/bus/', function(data) {
329            for (var i in data.busses) {
330                var bus = data.busses[i];
331                var elem = jQuery('<option>');
332                elem.text(bus.name);
333                elem.data('bus', bus);
334                select.append(elem);
335                if (initial_state.bus == bus.name) {
336                    elem.attr('selected', 'true');
337                    set_bus(bus);
338                }
339            }
340            select.bind('change', function(e) {
341                var elem = jQuery("option:selected", e.target);
342                var b = elem.data('bus');
343                if (b)
344                    set_bus(b);
345            });
346        })
347}
348
349jQuery(document).ready(init);
350