Fixes TIVI-2784 - Wifi password is not empty
[profile/ivi/SettingsApp.git] / js / panel-connman.js
1 /*
2  * Copyright (c) 2013, Intel Corporation.
3  *
4  * This program is licensed under the terms and conditions of the
5  * Apache License, version 2.0.  The full text of the Apache License is at
6  * http://www.apache.org/licenses/LICENSE-2.0
7  *
8  */
9 var connmanScanInProgress = false;
10
11 function connmanPanelInit() {
12
13     /* Connman Settings Panel */
14     $('#page_connman').on('pageshow', function(event, data) {
15         if (data.prevPage.attr('id') === 'page_connman_service') return;
16
17         wsAPI.subscribeEvents(connmanEventReceived);
18
19         console.log('Get all the available technologies');
20         settings.connman.getTechnologies(function(technologies) {
21             for (var i = 0; i < technologies.length; i++) {
22                 var technology = technologies[i];
23                 console.log('Connman technology found: ' + technology.prop.Type);
24                 if (technology.prop.Type === 'bluetooth') {
25                     /* Do not show bluetooth */
26                     continue;
27                 }
28                 if (technology.prop.Powered === undefined) {
29                     (function(t) {
30                         t.getPowered(function(is_powered) {
31                             t.prop.Powered = is_powered;
32                             if ($('#toggle_connman_' + t.prop.Type).length <= 0) {
33                                 /* element doesn't exist, create it */
34                                 connmanConstructTechnologyElement(t);
35                             } else {
36                                 /* element already exist */
37                                 connmanToggleTechnology(t.prop.Type, is_powered);
38                             }
39                         }, function(e) {
40                             t.prop.Powered = false;
41                             connmanConstructTechnologyElement(t);
42                         });
43                     })(technology);
44                 } else {
45                     if ($('#toggle_connman_' + technology.prop.Type).length <= 0) {
46                         /* element doesn't exist, create it */
47                         connmanConstructTechnologyElement(technology);
48                     } else {
49                         /* element already exist */
50                         connmanToggleTechnology(technology.prop.Type, technology.prop.Powered);
51                     }
52                 }
53             }
54         }, function(e) {
55             showMsg('Error', e);
56         });
57     });
58
59     $('#button_connman_refresh').on('click', function() {
60         /* connman only supports wifi scan */
61         if ($('#toggle_connman_wifi').val() === 'on') {
62             connmanScan('/net/connman/technology/wifi');
63         } else {
64             connmanSync(null, function(e) {
65                 showMsg('Error', e);
66             });
67         }
68     });
69
70     $('#button_connman_wifi_add').on('click', function() {
71         if (connmanScanInProgress) return;
72
73         console.log('Enter add WiFi page');
74         $.mobile.changePage('#page_wifi_add');
75     });
76
77     /* Connman tethering page */
78     $('#page_connman_tethering').on('pageshow', function(event, data) {
79         connmanTetheringPageReload();
80     });
81
82     /* Connman service detail page */
83     $('#page_connman_service').on('pageshow', function(event, data) {
84         var service_id = localStorage.getItem('connman_service_id');
85         if (service_id == undefined) return;
86         var service = $(jqId(service_id)).data('service-object');
87         connmanConstructServicePanel(service);
88     });
89
90     /* WiFi connect page */
91     $('#page_wifi_connect').on('pagebeforeshow', function(event, data) {
92         $('#input_wifi_connect_passphrase').val('');
93     });
94
95     /* WiFi add new network page */
96     $('#page_wifi_add').on('pagebeforeshow', function(event, data) {
97         $('#input_wifi_add_ssid').val('');
98         $('#input_wifi_add_password').val('');
99         $('#radio_wifi_none').prop('checked', true);
100         $('input[name=radio_wifi_security]').checkboxradio('refresh');
101         $('#input_wifi_add_password').textinput('disable');
102     });
103
104     $('#button_wifi_add').on('click', function() {
105         var name = $('#input_wifi_add_ssid').val();
106         var security = $('input[name=radio_wifi_security]:checked').val();
107         var passcode = $('#input_wifi_add_password').val();
108
109         if (name === '') {
110             showMsg('Error', 'Enter SSID');
111             return;
112         }
113
114         if (security !== 'none' && passcode === '') {
115             showMsg('Error', 'Enter passphrase');
116             return;
117         }
118
119         showSpinner(false, 'Adding...');
120         connmanGetHiddenServicePath(security, function(service_path) {
121             var service = new settings.connman.ConnmanService('', {
122                 'Name': name,
123                 'EncryptionMode': security
124             });
125             service.connect(passcode, function() {
126                 /* success */
127                 connmanSync(function() {
128                     hideSpinner();
129                     console.log('Go back to Connman page');
130                     $.mobile.changePage('#page_connman');
131                 }, function(e) {
132                     showMsg('Error', e);
133                 });
134             }, function(e) {
135                 /* error */
136                 hideSpinner();
137                 showMsg('Error', 'Failed to add network: ' + e);
138             });
139         }, function(e) {
140             hideSpinner();
141             showMsg('Error', e);
142         });
143     });
144
145     $('[name="radio_wifi_security"]').on('change', function(event, data) {
146         var security = $('input[name=radio_wifi_security]:checked').val();
147
148         if (security === 'none') {
149             $('#input_wifi_add_password').textinput('disable');
150             $('#input_wifi_add_password').val('');
151         } else {
152             $('#input_wifi_add_password').textinput('enable');
153         }
154     });
155
156     $('#button_wifi_connect').on('click', function() {
157         var service_id = localStorage.getItem('connman_service_id');
158         if (service_id == undefined) return;
159         var service = $(jqId(service_id)).data('service-object');
160         var passcode = $('#input_wifi_connect_passphrase').val();
161         connmanConnectToService(service, passcode, function() {
162             console.log('Successfully connected to service: ' + service.prop.Name);
163             if ($.mobile.activePage.attr('id') !== 'page_connman') {
164                 console.log('Go back to Connman page');
165                 $.mobile.changePage('#page_connman');
166             }
167         }, function(e) {
168             showMsg('Error', 'Connect service failed: ' + e);
169         });
170     });
171 }
172
173 function connmanEventReceived(event) {
174     if (event.type === WS_EVENT_TYPE.CONNMAN) {
175         if ($.mobile.activePage.attr('id') !== 'page_connman' && $.mobile.activePage.attr('id') !== 'page_connman_service') {
176             return;
177         }
178
179         if (event.name === 'ServicesChanged') {
180             connmanHandleServicesChanged(event.id, event.value);
181         } else if (event.name === 'PropertyChanged') {
182             connmanHandlePropertyChanged(event.id, event.value);
183         } else {
184             console.log('Unsupported event received: ' + event.name);
185         }
186     }
187 }
188
189 function connmanHandleServicesChanged(object_path, services) {
190     var servicesChanged = services[0];
191     var servicesRemoved = services[1];
192
193     console.log(servicesChanged.length + ' services changed');
194     for (var i = 0; i < servicesChanged.length; i++) {
195         if (servicesChanged[i][0] === undefined) {
196             console.log('Invalid parameters, missing object path');
197             continue;
198         }
199
200         var service = $(jqId(servicesChanged[i][0])).data('service-object');
201
202         if (service == null) {
203             console.log('could not find service object ' + servicesChanged[i][0]);
204             continue;
205         }
206
207         for (var prop in servicesChanged[i][1]) {
208             if (servicesChanged[i][1].hasOwnProperty(prop)) {
209                 service.prop.prop = servicesChanged[i][1].prop;
210                 connmanUpdateService(service);
211                 console.log('Service ' + service.prop.Name + ' updated: ' + prop);
212             }
213         }
214     }
215
216     console.log(servicesRemoved.length + ' services removed');
217     for (var i = 0; i < servicesRemoved.length; i++) {
218         if (servicesRemoved[i] === undefined) {
219             console.log('Invalid parameters, missing object path');
220             continue;
221         }
222
223         connmanRemoveFromAvailableList(servicesRemoved[i]);
224     }
225 }
226
227 function connmanHandlePropertyChanged(id, property) {
228     if (property[0] === 'Powered') {
229         var index = id.lastIndexOf('/');
230         var technology = id.substring(index + 1);
231         if (property[1] === true) {
232             connmanToggleTechnology(technology, true);
233             if (technology === 'wifi') {
234                 setTimeout(function() {
235                     /* add a 1 sec delay */
236                     connmanScan(id);
237                 }, 1000);
238             }
239         } else {
240             connmanToggleTechnology(technology, false);
241         }
242     }
243
244     if (property[0] === 'State') {
245         /* specific service has changed */
246         var service = $(jqId(id)).data('service-object');
247         if (service == null) {
248             console.error('Connman service not found ' + id);
249             return;
250         }
251
252         service.prop.State = property[1];
253         connmanUpdateService(service);
254     } else if (property[0] === 'Connected') {
255         /* unknown service has changed, sync Connman */
256         console.log('Unknown service connected property changed');
257         connmanSync(null, function(e) {
258             showMsg('Error', e);
259         });
260     }
261 }
262
263 function connmanClearAvailableList() {
264     $('#listview_services_available').html('');
265 }
266
267 function connmanScan(technology) {
268     if (technology !== '/net/connman/technology/wifi') {
269         /* Connman only supports wifi scan */
270         return;
271     }
272
273     if (connmanScanInProgress) {
274         console.log('Connman scan in progress...');
275         return;
276     }
277
278     console.log('Start connman scan');
279     connmanScanInProgress = true;
280
281     /* clear the services list with new scan */
282     connmanClearAvailableList();
283
284     showSpinner(false, 'Scanning...');
285     $('#toggle_connman_wifi').slider('disable');
286     $('#toggle_connman_wifi').slider('refresh');
287     settings.connman.scan(technology, function(services) {
288         hideSpinner();
289         connmanScanInProgress = false;
290         $('#toggle_connman_wifi').slider('enable');
291         $('#toggle_connman_wifi').slider('refresh');
292         console.log('found ' + services.length + ' connman services');
293         for (var i = 0; i < services.length; i++) {
294             var service = services[i];
295             if (service.prop.Type === undefined || service.prop.Type === 'bluetooth') {
296                 console.log('Ignore bluetooth or unknown services');
297                 continue;
298             }
299             if (service.prop.Name === undefined) {
300                 console.log('Ignore hidden service - ' + service.id);
301                 continue;
302             }
303
304             connmanUpdateService(service);
305         }
306     }, function(e) {
307         hideSpinner();
308         connmanScanInProgress = false;
309         $('#toggle_connman_wifi').slider('enable');
310         $('#toggle_connman_wifi').slider('refresh');
311         showMsg('Error', 'Cannot scan: ' + e);
312     });
313 }
314
315 function connmanSync(success_cb, error_cb) {
316     if (connmanScanInProgress) {
317         console.log('Connman scan in progress...');
318         return;
319     }
320
321     console.log('Start connman sync');
322     /* clear the services list with new scan */
323     connmanClearAvailableList();
324
325     wifiScanInProgress = true;
326     $('#toggle_connman_wifi').slider('disable');
327     $('#toggle_connman_wifi').slider('refresh');
328     settings.connman.getServices(function(services) {
329         connmanScanInProgress = false;
330         $('#toggle_connman_wifi').slider('enable');
331         $('#toggle_connman_wifi').slider('refresh');
332         console.log('found ' + services.length + ' connman services');
333         for (var i = 0; i < services.length; i++) {
334             var service = services[i];
335             if (service.prop.Type === undefined || service.prop.Type === 'bluetooth') {
336                 console.log('Ignore bluetooth or unknown services');
337                 continue;
338             }
339             if (service.prop.Name === undefined) {
340                 console.log('Ignore hidden service - ' + service.id);
341                 continue;
342             }
343
344             connmanUpdateService(service);
345         }
346         if (success_cb) {
347             success_cb();
348         }
349     }, function(e) {
350         connmanScanInProgress = false;
351         $('#toggle_connman_wifi').slider('enable');
352         $('#toggle_connman_wifi').slider('refresh');
353         if (error_cb) {
354             error_cb(e);
355         }
356     });
357 }
358
359 function connmanRefreshServicesList() {
360     $('#listview_services_available').listview('refresh');
361 }
362
363 function connmanAppendToAvailableList(service) {
364     if ($('#listview_services_available').find(jqId(service.id)).length != 0) return;
365
366     var parent = '#listview_services_available';
367     connmanConstructServiceElement(parent, service);
368     connmanUpdateServiceButton(service);
369     connmanRefreshServicesList();
370 }
371
372 function connmanRemoveFromAvailableList(service_id) {
373     var removeThis = $('#listview_services_available li').filter(function() {
374         return $(this).find(jqId(service_id)).length === 1;
375     });
376
377     if (removeThis.length !== 0) {
378         removeThis.remove();
379         connmanRefreshServicesList();
380     }
381 }
382
383 function getSignalStrengthStr(strength) {
384     var signal_strength = 'unknown';
385     if (strength > 0 && strength <= 20) {
386         strength = 'very poor';
387     } else if (strength > 20 && strength <= 40) {
388         signal_strength = 'poor';
389     } else if (strength > 40 && strength <= 70) {
390         signal_strength = 'average';
391     } else if (strength > 70 && strength <= 90) {
392         signal_strength = 'good';
393     } else if (strength > 90 && strength <= 100) {
394         signal_strength = 'excellent';
395     }
396     return signal_strength;
397 }
398
399 function connmanConstructTechnologyElement(technology) {
400     if (technology.prop.Type === undefined || technology.prop.Name == undefined) {
401         console.error('technology type or name missing ' + technology);
402         return;
403     }
404
405     var html = '<ul data-role="listview" data-inset="true" class="ui-listview ui-listview-inset">';
406     html += '<li data-role="fieldcontain">';
407     html += '<label for="toggle_connman_' + technology.prop.Type + '" class="ui-slider">' + technology.prop.Name + '</label>';
408     html += '<select data-role="slider" name="toggle_connman_' + technology.prop.Type + '" ';
409     html += 'id="toggle_connman_' + technology.prop.Type + '" class="ui-slider-switch">';
410     html += '<option value="off">Off</option>';
411     html += '<option value="on">On</option>';
412     html += '</select></li></ul>';
413     $('#connman_technologies').append(html).trigger('create');
414
415     console.log('Connman technology ' + technology.prop.Type + ' is powered: ' + technology.prop.Powered);
416     if (technology.prop.Powered) {
417         connmanToggleTechnology(technology.prop.Type, true);
418         if ($('ul#listview_services_available li').length === 0) {
419             /* connman only supports wifi scan */
420             if (technology.prop.Type === 'wifi') {
421                 connmanScan(technology.id);
422             } else {
423                 connmanSync(null, function(e) {
424                     showMsg('Error', e);
425                 });
426             }
427         }
428     } else {
429         connmanToggleTechnology(technology.prop.Type, false);
430     }
431
432     $('#toggle_connman_' + technology.prop.Type).change(function() {
433         console.log('toggle ' + technology.prop.Type + ' changed');
434
435         if (connmanScanInProgress) {
436             console.log('Connman scan in progress...');
437             return;
438         }
439
440         $('#toggle_connman_' + technology.prop.Type).slider('disable');
441         $('#toggle_connman_' + technology.prop.Type).slider('refresh');
442         if ($('#toggle_connman_' + technology.prop.Type).val() === 'off') {
443             technology.setPowered(false, function() {
444                 /* success */
445                 $('#toggle_connman_' + technology.prop.Type).slider('enable');
446                 $('#toggle_connman_' + technology.prop.Type).slider('refresh');
447                 console.log('Successfully disabled connman technology ' + technology.prop.Type);
448             }, function(e) {
449                 /* error */
450                 hideSpinner();
451                 $('#toggle_connman_' + technology.prop.Type).slider('enable');
452                 $('#toggle_connman_' + technology.prop.Type).val('on').slider('refresh');
453                 showMsg('Error', 'Cannot disable ' + technology.prop.Type);
454             });
455         } else {
456             technology.setPowered(true, function() {
457                 /* success */
458                 $('#toggle_connman_' + technology.prop.Type).slider('enable');
459                 $('#toggle_connman_' + technology.prop.Type).slider('refresh');
460                 if (technology.prop.Type === 'wifi') {
461                     setTimeout(function() {
462                         /* add a 1 sec delay */
463                         connmanScan(technology.id);
464                     }, 1000);
465                 }
466                 console.log('Successfully enabled connman technology ' + technology.prop.Type);
467             }, function(e) {
468                 /* error */
469                 hideSpinner();
470                 $('#toggle_connman_' + technology.prop.Type).slider('enable');
471                 $('#toggle_connman_' + technology.prop.Type).val('off').slider('refresh');
472                 showMsg('Error', 'Cannot enable ' + technology.prop.Type);
473             });
474         }
475     });
476 }
477
478 function connmanConstructServiceElement(parent, service) {
479     if (service.id === undefined || service.prop.Type === undefined) {
480         console.error('service id or type missing ' + service);
481         return;
482     }
483
484     var html = '<li data-icon="false"><a href="#" id="' + jqId(service.id).replace('#', '') + '">';
485     html += '<div class="service-ssid">' + service.prop.Name + '</div>';
486
487     if (service.prop.Type === 'wifi') {
488         html += '<div class="service-encryption">Encryption: ' + service.prop.EncryptionMode + '</div>';
489         html += '<div class="service-strength">Signal: ' + getSignalStrengthStr(service.prop.Strength) + '</div>';
490     }
491     html += '<div class="service-status"></div>';
492     html += '<div data-role="button" class="service-action-button ui-li-aside" data-inline="true"></div>';
493     html += '</a></li>';
494     $(parent).append(html).trigger('create');
495
496     /* store service object in the element so we can reference it later */
497     $(jqId(service.id)).data('service-object', service);
498
499     $(jqId(service.id)).on('click', function() {
500         /* BUG in webruntime that cause click event when another page is rendered */
501         if ($.mobile.activePage.attr('id') === 'page_connman') {
502             localStorage.setItem('connman_service_id', service.id);
503             console.log('Enter Connman service page');
504             $.mobile.changePage('#page_connman_service');
505         }
506     });
507
508     $(jqId(service.id)).find('div.service-action-button').on('click', function(e) {
509         var parent = $(this).parent().attr('id');
510
511         /*
512          * prevent the click event to propagate up
513          */
514         e.stopImmediatePropagation();
515         e.preventDefault();
516
517         /* retrieve the service object from element */
518         var service = $(jqId(parent)).data('service-object');
519         if (service == null) {
520             console.error('Connman service object not found');
521             return;
522         }
523
524         if (service.prop.State === 'idle') {
525             if (service.prop.EncryptionMode === 'none') {
526                 connmanConnectToService(service, null);
527             } else {
528                 connmanConnectToService(service, null, null, function(e) {
529                     console.log('Connect failed, will ask for passphrase');
530                     localStorage.setItem('connman_service_id', service.id);
531                     console.log('Enter connect WiFi page');
532                     $.mobile.changePage('#page_wifi_connect');
533                 });
534             }
535         } else if (service.prop.State === 'ready') {
536             console.log('Disconnecting from service: ' + service.prop.Name);
537             showSpinner(false, 'Disconnecting...');
538             service.disconnect(function() {
539                 /* success */
540                 connmanSync(function() {
541                     hideSpinner();
542                 }, function(e) {
543                     showMsg('Error', e);
544                 })
545             }, function(e) {
546                 /* error */
547                 hideSpinner();
548                 showMsg('Error', 'Disconnect service failed: ' + e);
549             });
550         }
551     });
552 }
553
554 function connmanTetheringPageReload() {
555     $('#connman_tethering_technologies').html('');
556     settings.connman.getTechnologies(function(technologies) {
557         for (var i = 0; i < technologies.length; i++) {
558             var technology = technologies[i];
559             console.log('Connman technology available for tethering: ' + technology.prop.Name);
560             connmanConstructTetheringElement(technology);
561         }
562     }, function(e) {
563         showMsg('Error', e);
564     });
565 }
566
567 function connmanConstructTetheringElement(technology) {
568     if (technology.prop.Type === undefined || technology.prop.Name == undefined) {
569         console.error('technology type or name missing ' + technology);
570         return;
571     }
572
573     var html = '<ul data-role="listview" data-inset="true" class="ui-listview ui-listview-inset">';
574     html += '<li data-role="fieldcontain">';
575     html += '<label for="toggle_tethering_' + technology.prop.Type + '" class="ui-slider">Tether ' + technology.prop.Name + '</label>';
576     html += '<select data-role="slider" name="toggle_tethering_' + technology.prop.Type + '" ';
577     html += 'id="toggle_tethering_' + technology.prop.Type + '" class="ui-slider-switch">';
578     html += '<option value="off">Off</option>';
579     html += '<option value="on">On</option>';
580     html += '</select></li></ul>';
581     $('#connman_tethering_technologies').append(html).trigger('create');
582
583     console.log('Connman technology ' + technology.prop.Type + ' is tethered: ' + technology.prop.Tethering);
584
585     if (technology.prop.Powered === true && technology.prop.Connected === true) {
586         if (technology.prop.Tethering === true) {
587             $('#toggle_tethering_' + technology.prop.Type).val('on').slider('refresh');
588             $('#input_wifi_tethering_id').textinput('disable');
589             $('#input_wifi_tethering_passphrase').textinput('disable');
590             /* WiFi-only options */
591             if (technology.prop.Type === 'wifi') {
592                 $('#connman_wifi_tethering_options').show();
593                 if (technology.prop.TetheringIdentifier) {
594                     $('#input_wifi_tethering_id').val(technology.prop.TetheringIdentifier);
595                 }
596                 if (technology.prop.TetheringPassphrase) {
597                     $('#input_wifi_tethering_passphrase').val(technology.prop.TetheringPassphrase);
598                 }
599             }
600         } else {
601             $('#toggle_tethering_' + technology.prop.Type).val('off').slider('refresh');
602         }
603     } else {
604         if (technology.prop.Type === 'wifi') {
605             $('#input_wifi_tethering_id').textinput('disable');
606             $('#input_wifi_tethering_passphrase').textinput('disable');
607         }
608         $('#toggle_tethering_' + technology.prop.Type).slider('disable');
609         $('#toggle_tethering_' + technology.prop.Type).slider('refresh');
610     }
611
612     $('#toggle_tethering_' + technology.prop.Type).change(function() {
613         if ($('#toggle_tethering_' + technology.prop.Type).val() === 'on') {
614             if (technology.prop.Type === 'wifi') {
615                 var tethering_id = $('#input_wifi_tethering_id').val();
616                 var tethering_passphrase = $('#input_wifi_tethering_passphrase').val();
617                 if (tethering_id === '' || tethering_passphrase === '') {
618                     connmanTetheringPageReload();
619                     showMsg('Error', 'Please provide identifier and passphrase');
620                     return;
621                 }
622
623                 technology.setTethering(true, tethering_id, tethering_passphrase, function() {
624                     /* success */
625                     console.log('Successfully tethered connman technology ' + technology.prop.Type);
626                     connmanTetheringPageReload();
627                 }, function(e) {
628                     /* error */
629                     connmanTetheringPageReload();
630                     showMsg('Error', 'Cannot tether ' + technology.prop.Type + ': ' + e);
631                 });
632             } else {
633                 technology.setTethering(true, '', '', function() {
634                     /* success */
635                     console.log('Successfully tethered connman technology ' + technology.prop.Type);
636                     connmanTetheringPageReload();
637                 }, function(e) {
638                     /* error */
639                     connmanTetheringPageReload();
640                     showMsg('Error', 'Cannot tether ' + technology.prop.Type + ': ' + e);
641                 });
642             }
643         } else {
644             technology.setTethering(false, '', '', function() {
645                 /* success */
646                 console.log('Successfully untethered connman technology ' + technology.prop.Type);
647                 connmanTetheringPageReload();
648             }, function(e) {
649                 /* error */
650                 connmanTetheringPageReload();
651                 showMsg('Error', 'Cannot untether ' + technology.prop.Type + ': ' + e);
652             });
653         }
654     });
655 }
656
657 function connmanUpdateService(service) {
658     connmanAppendToAvailableList(service);
659
660     /* update service button for allowed action */
661     connmanUpdateServiceButton(service);
662
663     /* update service connection status */
664     connmanUpdateConnectionStatus(service);
665
666     /* update service detail panel */
667     if ($.mobile.activePage.attr('id') === 'page_connman_service') {
668         var service_id = localStorage.getItem('connman_service_id');
669         if (service_id == undefined) return;
670         var service_object = $(jqId(service_id)).data('service-object');
671         if (service.id === service_object.id) {
672             connmanConstructServicePanel(service);
673         }
674     }
675 }
676
677 function connmanUpdateServiceButton(service) {
678     if (service.prop.State === 'ready') {
679         $(jqId(service.id)).find('div.service-action-button').find('span').text('Disconnect');
680     } else if (service.prop.State === 'idle' || service.prop.State === 'online') {
681         $(jqId(service.id)).find('div.service-action-button').find('span').text('Connect');
682     }
683 }
684
685 function connmanUpdateConnectionStatus(service) {
686     var status = 'disconnected';
687     if (service.prop.State === 'ready') {
688         $(jqId(service.id)).addClass('service-connected');
689         status = 'connected';
690     } else if (service.prop.State === 'idle' || service.prop.State === 'online') {
691         status = 'disconnected';
692         $(jqId(service.id)).removeClass('service-connected');
693     }
694
695     connmanUpdateConnectionStatusText(service, status);
696 }
697
698 function connmanUpdateConnectionStatusText(service, status) {
699     $(jqId(service.id)).find('div.service-status').text(status);
700 }
701
702 function connmanConstructServicePanel(service) {
703     var status_connected = 'No';
704
705     if (service == null) return;
706     if (service.prop.State === 'ready') status_connected = 'Yes';
707
708     $('#page_connman_service_content').html('');
709     var html = '<ul data-role="listview" id="listview_connman_service" data-inset="true" ' + 'class="service-list ui-listview">';
710     html += '<li id="connman_service_name"><h2>Name: ' + service.prop.Name + '</h2></li>';
711     html += '<li id="connman_service_type"><h2>Type: ' + service.prop.Type + '</h2></li>';
712     html += '<li id="connman_service_type"><h2>State: ' + service.prop.State + '</h2></li>';
713     if (service.prop.Type === 'ethernet' || service.prop.Type === 'wifi') {
714         if (service.prop.Type === 'wifi') {
715             html += '<li id="connman_service_bssid"><h2>SSID: ' + service.prop.BSSID + '</h2></li>';
716             html += '<li id="connman_service_encryption"><h2>Encryption: ' + service.prop.EncryptionMode + '</h2></li>';
717             html += '<li id="connman_service_strength"><h2>Signal Strength: ' + service.prop.Strength + '</h2></li>';
718         }
719         if (service.prop.State === 'ready') {
720             html += '<li id="connman_service_ip_address"><h2>IP Address: ' + service.prop.IPv4.Address + '</h2></li>';
721             html += '<li id="connman_servicel_gateway"><h2>Gateway: ' + service.prop.IPv4.Gateway + '</h2></li>';
722             html += '<li id="connman_service_netmask"><h2>Netmask: ' + service.prop.IPv4.Netmask + '</h2></li>';
723         }
724     }
725     html += '<li id="connman_service_connected"><h2>Connected: ' + status_connected + '</h2></li>';
726     html += '</ul>';
727     $('#page_connman_service_content').append(html).trigger('create');
728     $('#listview_connman_services').listview('refresh');
729
730     var html = '<ul data-role="listview" data-inset="true" class="ui-listview ui-listview-inset">';
731     html += '<li data-role="fieldcontain">';
732     html += '<label for="toggle_autoconnect" class="ui-slider">Auto Connect</label>';
733     html += '<select data-role="slider" name="toggle_autoconnect" ';
734     html += 'id="toggle_autoconnect" class="ui-slider-switch">';
735     html += '<option value="off">Off</option>';
736     html += '<option value="on">On</option>';
737     html += '</select></li></ul>';
738     $('#page_connman_service_content').append(html).trigger('create');
739
740     if (service.prop.AutoConnect) {
741         $('#toggle_autoconnect').val('on').slider('refresh');
742     } else {
743         $('#toggle_autoconnect').val('off').slider('refresh');
744     }
745
746     $('#toggle_autoconnect').change(function() {
747         if ($('#toggle_autoconnect').val() === 'on') {
748             service.setAutoConnect(true, function() {
749                 /* success */
750                 console.log('Successfully enabled autoconnect for ' + service.prop.Name);
751             }, function(e) {
752                 /* error */
753                 console.log('Cannot enable autoconnect: ' + e);
754             });
755         } else {
756             service.setAutoConnect(false, function() {
757                 /* success */
758                 console.log('Successfully disabled autoconnect for ' + service.prop.Name);
759             }, function(e) {
760                 /* error */
761                 console.log('Cannot disable autoconnect: ' + e);
762             });
763         }
764     });
765 }
766
767 function connmanUpdateServicePanel(service) {
768     var status_connected = 'No';
769
770     if (service == null) return;
771     if (service.prop.State === 'ready') status_connected = 'Yes';
772     $('#connman_service_connected').text(status_connected);
773     $('#listview_connman_service').listview('refresh');
774 }
775
776 function connmanToggleTechnology(technology_type, powered) {
777     setTimeout(function() {
778         if (powered) {
779             $('#toggle_connman_' + technology_type).val('on').slider('refresh');
780             console.log('Turn on toggle #toggle_connman_' + technology_type);
781         } else {
782             $('#toggle_connman_' + technology_type).val('off').slider('refresh');
783             console.log('Turn off toggle #toggle_connman_' + technology_type);
784         }
785     }, 1000);
786 }
787
788 function connmanConnectToService(service, passphrase, success_cb, error_cb) {
789     console.log('Connect to service: ' + service.prop.Name);
790     showSpinner(false, 'Connecting...');
791     service.connect(passphrase, function() {
792         /* success */
793         connmanSync(function() {
794             hideSpinner();
795             if (success_cb) {
796                 success_cb();
797             }
798         }, function(e) {
799             hideSpinner();
800             if (error_cb) {
801                 error_cb(e);
802             }
803         });
804     }, function(e) {
805         /* error */
806         hideSpinner();
807         if (error_cb) {
808             error_cb(e);
809         }
810     });
811 }
812
813 function connmanGetHiddenServicePath(security_type, success_cb, error_cb) {
814     if (security_type === undefined || success_cb === undefined || error_cb === undefined) return;
815     settings.connman.scan(function(services) {
816         connmanScanInProgress = false;
817         console.log('found ' + services.length + ' connman services');
818         for (var i = 0; i < services.length; i++) {
819             var service = services[i];
820             if (service.prop.Name === undefined && service.prop.Type === 'wifi') {
821                 console.log('Hidden network matched - ' + service.id);
822                 success_cb(service.id);
823                 return;
824             }
825         }
826         error_cb('No hidden network with security: ' + security_type);
827     }, function(e) {
828         connmanScanInProgress = false;
829         if (error_cb) {
830             error_cb(e);
831         }
832     });
833 }