Fixes TIVI-2784 - Wifi password is not empty
[profile/ivi/SettingsApp.git] / js / websocket.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
10 /* Dummy backend for faking websocket daemon */
11 var dummyBackend = false;
12
13 var ERROR_SETTINGSD_DISCONNECTED = 'Settings daemon is not connected';
14
15 var WS_REQUEST_TYPE = {
16     CONNMAN_MANAGER: "connman::manager",
17     CONNMAN_TECHNOLOGY: "connman::technology",
18     CONNMAN_SERVICE: "connman::service",
19     BLUETOOTH: "bluetooth",
20     DISPLAY: "display",
21     SOUND: "sound",
22     DATETIME: "clock",
23     LOCALE: "locale"
24 };
25
26 var WS_EVENT_TYPE = {
27     CONNMAN: "connman",
28     BLUETOOTH: "bluetooth",
29     DISPLAY: "display",
30     SOUND: "sound",
31     DATETIME: "clock",
32     LOCALE: "locale"
33 };
34
35 /* web socket module to connect to the settings daemon */
36 var wsAPI = (function() {
37     /* number of connection retries to attempt if the socket closes */
38     var self = this;
39     this.connected = false;
40     this.event_callbacks = $.Callbacks();
41
42     /* default values for WebSocket */
43     this.socketUrl = 'ws://localhost:16000/';
44     this.socketProtocol = 'http-only';
45
46     this.timeouttime = 15000;
47     this.methodIdx = 0;
48     this.methodCalls = [];
49     for (var i = 0; i < 100; i++) {
50         this.methodCalls[i] = null;
51     }
52
53     this.MethodCall = function(id, name, success_cb, error_cb) {
54         var me = this;
55         this.successCB = success_cb;
56         this.errorCB = error_cb;
57         this.transactionid = id;
58         this.name = name;
59         this.done = false;
60         this.start = function() {
61             me.timeout = setTimeout(function() {
62                 if (me.errorCB !== undefined) {
63                     me.errorCB('\"' + me.name + '\" method timed out after ' + self.timeouttime + ' ms');
64                 }
65                 me.finish();
66             }, self.timeouttime);
67         }
68         this.finish = function() {
69             if (me.timeout !== undefined) {
70                 clearTimeout(me.timeout);
71             }
72             me.done = true;
73         }
74     }
75
76     this.EventObject = function(type, id, name, value) {
77         var me = this;
78         this.type = type;
79         this.id = id;
80         this.name = name;
81         this.value = value;
82     }
83
84     function connect(url, protocol, sucess_cb, error_cb) {
85         self.socketUrl = typeof url !== 'undefined' ? url : self.socketUrl;
86         self.socketProtocol = typeof protocol !== 'undefined' ? protocol : self.socketProtocol;
87         self.successCB = sucess_cb;
88         self.errorCB = error_cb;
89
90         if ('WebSocket' in window) {
91             if (self.socketProtocol.length > 0) {
92                 self.socket = new WebSocket(self.socketUrl, self.socketProtocol);
93             } else {
94                 self.socket = new WebSocket(self);
95             }
96             console.log('Connecting to websocket: ' + self.socketUrl);
97
98             self.socket.onopen = function() {
99                 self.connected = true;
100                 console.log('websocket opened');
101                 self.successCB();
102             };
103
104             self.socket.onclose = function(code, reason, remote) {
105                 self.connected = false;
106                 console.log('websocket closed - ' + reason);
107
108                 if (dummyBackend) {
109                     /* fake the connection for dummy backend */
110                     self.connected = true;
111                     self.successCB();
112                     return;
113                 }
114
115                 self.errorCB(reason);
116             };
117
118             self.socket.onerror = function(e) {
119                 if (dummyBackend) {
120                     /* ignore websocket error */
121                     return;
122                 }
123
124                 if (e.data) {
125                     self.errorCB('websocket error: ' + e.data);
126                 } else {
127                     self.errorCB('websocket error: unknown');
128                 }
129             };
130
131             self.socket.onmessage = function(e) {
132                 receive(e.data);
133             };
134         } else {
135             console.log('Websockets not supported');
136         }
137     }
138
139     function reconnect() {
140         if (this.connected) return;
141
142         setTimeout(function() {
143             connect(self.socketUrl, self.socketProtocol, self.successCB, self.errorCB);
144         }, 1000);
145     }
146
147     function send(msg, success_cb, error_cb) {
148         if (!this.connected) {
149             if (error_cb !== undefined) {
150                 error_cb(ERROR_SETTINGSD_DISCONNECTED);
151             }
152             return;
153         }
154         var i = this.methodIdx;
155         this.methodIdx = (this.methodIdx + 1) % 100;
156         this.methodCalls[i] = new this.MethodCall(msg.transactionid, msg.name, success_cb, error_cb);
157         this.methodCalls[i].start();
158
159         var jsonMsg = JSON.stringify(msg);
160         console.log('Sending json msg: ' + jsonMsg);
161         if (dummyBackend) {
162             /* fake with dummy data */
163             dummyBackendSend(msg);
164         } else {
165             this.socket.send(jsonMsg);
166         }
167     }
168
169     function fireEvent(type, id, name, value) {
170         var event = new this.EventObject(type, id, name, value);
171         console.log('Firing ' + type + ' event id=' + id + ', name=' + name + ', value=' + value);
172         event_callbacks.fire(event);
173     }
174
175     function receive(msg) {
176         var self = this;
177         var response;
178         try {
179             console.log("Received json msg: " + msg);
180             response = JSON.parse(msg);
181         } catch (e) {
182             console.error('Garbage message: ' + msg);
183             return;
184         }
185
186         if ((response === undefined) || (response.type === undefined)) {
187             console.error('Badly formed message: ' + msg);
188         } else if (response.type === 'event' && response.value !== undefined) {
189             if (response.value.interface_name === 'net.connman.Manager' || response.value.interface_name === 'net.connman.Service' || response.value.interface_name === 'net.connman.Technology') {
190                 if (response.value.signal_name === undefined || response.value.parameters === undefined) {
191                     console.error('Badly formed event: ' + msg);
192                     return;
193                 }
194                 if (response.value.signal_name === 'ServiceChanged' && response.value.parameters.length !== 2) {
195                     console.error('Badly formed event parameters: ' + msg);
196                     return;
197                 }
198
199                 if (response.value.object_path === '/' || response.value.object_path.indexOf('/net/connman/technology/') >= 0) {
200                     fireEvent(WS_EVENT_TYPE.CONNMAN, response.value.object_path, response.value.signal_name, response.value.parameters);
201                 } else {
202                     console.error('Unrecognized event object_path, skipping');
203                 }
204             } else {
205                 console.error('Unrecognized event, skipping');
206             }
207         } else if (response.transactionid === undefined) {
208             console.error('Badly formed response: ' + msg);
209         } else {
210             var calls = this.methodCalls;
211             for (var i = 0; i < calls.length; i++) {
212                 var call = calls[i];
213                 if (call && (!call.done) && (call.transactionid === response.transactionid)) {
214                     call.finish();
215                     if (response.result !== 'succeeded' && response.reason !== undefined && call.errorCB !== undefined) {
216                         call.errorCB(response.reason);
217                     } else if (call.successCB !== undefined) {
218                         if (response.value !== undefined) {
219                             call.successCB(response.value);
220                         } else {
221                             call.successCB();
222                         }
223                     }
224                     return;
225                 }
226             }
227         }
228     }
229
230     function generateTransactionId() {
231         var i, val = [];
232         for (i = 0; i < 8; i++) {
233             var num = Math.floor((Math.random() + 1) * 65536);
234             val[i] = num.toString(16).substring(1);
235         }
236         var uuid = val[0] + val[1] + '-' + val[2] + '-' + val[3] + '-' + val[4] + '-' + val[5] + val[6] + val[7];
237         return uuid;
238     }
239
240     function sendRequest(request_type, request_name, request_args, success_cb, error_cb) {
241         var msg = {
242             'type': request_type,
243             'transactionid': generateTransactionId(),
244             'name': request_name,
245             'value': request_args
246         };
247
248         send(msg, success_cb, error_cb);
249     }
250
251     function subscribeEvents(callback) {
252         event_callbacks.add(callback);
253     }
254
255     function unsubscribeEvents(callback) {
256         event_callbacks.remove(callback);
257     }
258
259     /* this is dummy data for testing purposes */
260     function dummyBackendSend(msg) {
261         if (dummyBackend) {
262             console.log('Sending to dummy server');
263
264             var calls = this.methodCalls;
265             var replyMsg = null;
266
267             for (var i = 0; i < calls.length; i++) {
268                 var call = calls[i];
269                 if (call && (!call.done) && (call.transactionid === msg.transactionid)) {
270                     call.finish();
271                     if (msg.error !== undefined) {
272                         if (call.errorCB) {
273                             call.errorCB(msg.error);
274                         }
275                     }
276                     if (msg.value !== undefined && call.successCB !== undefined) {
277                         switch (msg.type) {
278                         case WS_REQUEST_TYPE.CONNMAN_MANAGER:
279                         case WS_REQUEST_TYPE.CONNMAN_TECHNOLOGY:
280                             if (msg.name === 'get_technologies') {
281                                 var results = [
282                                     [
283                                         ["/net/connman/technology/ethernet",
284                                         {
285                                             "Name": "Wired",
286                                             "Type": "ethernet",
287                                             "Powered": true,
288                                             "Connected": true,
289                                             "Tethering": false
290                                         }],
291                                         ["/net/connman/technology/wifi",
292                                         {
293                                             "Name": "WiFi",
294                                             "Type": "wifi",
295                                             "Powered": true,
296                                             "Connected": true,
297                                             "Tethering": true,
298                                             "TetheringIdentifier": "tetherme",
299                                             "TetheringPassphrase": "0123456789"
300                                         }],
301                                         ["/net/connman/technology/bluetooth",
302                                         {
303                                             "Name": "Bluetooth",
304                                             "Type": "bluetooth",
305                                             "Powered": false,
306                                             "Connected": false,
307                                             "Tethering": false
308                                         }]
309                                     ]
310                                 ];
311
312                                 replyMsg = JSON.stringify(results);
313                                 call.successCB(results);
314                                 return;
315                             } else if (msg.name === 'enable' && msg.value[1] === true) {
316                                 call.successCB();
317                                 fireEvent(WS_EVENT_TYPE.CONNMAN, msg.value[0], 'PropertyChanged', ["Powered", true]);
318                                 return;
319                             } else if (msg.name === 'enable' && msg.value[1] === false) {
320                                 call.successCB();
321                                 fireEvent(WS_EVENT_TYPE.CONNMAN, msg.value[0], 'PropertyChanged', ["Powered", false]);
322                                 return;
323                             } else if (msg.name === 'tethering') {
324                                 call.successCB();
325                                 return;
326                             } else if (msg.name === 'get_services' || msg.name === 'scan') {
327                                 var results = [
328                                     [
329                                         ["/net/connman/service/ethernet_0010f32f5a70_cable",
330                                         {
331                                             "Type": "ethernet",
332                                             "Security": [],
333                                             "State": "ready",
334                                             "AutoConnect": true,
335                                             "Domains": ["ftrdhcpuser.net"],
336                                             "Domains.Configuration": [],
337                                             "Ethernet": {
338                                                 "Address": "10:20:F3:2F:5E:23",
339                                                 "Interface": "eno1",
340                                                 "MTU": 1500,
341                                                 "Method": "auto"
342                                             },
343                                             "Favorite": true,
344                                             "IPv4": {
345                                                 "Address": "192.168.1.20",
346                                                 "Gateway": "192.168.1.1",
347                                                 "Method": "dhcp",
348                                                 "Netmask": "255.255.255.0"
349                                             },
350                                             "IPv4.Configuration": {
351                                                 "Method": "dhcp"
352                                             },
353                                             "IPv6": {},
354                                             "IPv6.Configuration": {
355                                                 "Method": "auto",
356                                                 "Privacy": "disabled"
357                                             },
358                                             "Immutable": false,
359                                             "Name": "Wired",
360                                             "Nameservers": ["192.168.1.1", "184.11.12.13"],
361                                             "Nameservers.Configuration": [],
362                                             "Provider": {},
363                                             "Proxy": {
364                                                 "Method": "direct"
365                                             },
366                                             "Proxy.Configuration": {},
367                                             "Timeservers": ["192.168.1.1", "pool.ntp.org"],
368                                             "Timeservers.Configuration": []
369                                         }],
370                                         ["/net/connman/service/wifi_c8f733acdf96_3558364737_managed_psk",
371                                         {
372                                             "Type": "wifi",
373                                             "Security": ["psk"],
374                                             "State": "ready",
375                                             "Strength": 50,
376                                             "Favorite": false,
377                                             "Immutable": false,
378                                             "AutoConnect": false,
379                                             "Name": "Access Point 1",
380                                             "BSSID": "11:5d:49:88:3d:20",
381                                             "MaxRate": 54000000,
382                                             "Frequency": 2417,
383                                             "EncryptionMode": "none",
384                                             "Ethernet": {
385                                                 "Method": "auto",
386                                                 "Interface": "wlp1s0",
387                                                 "Address": "B2:D3:55:66:44:22",
388                                                 "MTU": 1500
389                                             },
390                                             "IPv4": {
391                                                 "Address": "192.168.1.20",
392                                                 "Gateway": "192.168.1.1",
393                                                 "Method": "dhcp",
394                                                 "Netmask": "255.255.255.0"
395                                             },
396                                             "IPv4.Configuration": {
397                                                 "Method": "dhcp"
398                                             },
399                                             "IPv6": {},
400                                             "IPv6.Configuration": {
401                                                 "Method": "auto",
402                                                 "Privacy": "disabled"
403                                             },
404                                             "Nameservers": [],
405                                             "Nameservers.Configuration": [],
406                                             "Timeservers": [],
407                                             "Timeservers.Configuration": [],
408                                             "Domains": [],
409                                             "Domains.Configuration": [],
410                                             "Proxy": {},
411                                             "Proxy.Configuration": {},
412                                             "Provider": {}
413                                         }],
414                                         ["/net/connman/service/wifi_c8f733acdf96_446f75636865626167_managed_psk",
415                                         {
416                                             "Type": "wifi",
417                                             "Security": ["psk"],
418                                             "State": "idle",
419                                             "Strength": 50,
420                                             "Favorite": false,
421                                             "Immutable": false,
422                                             "AutoConnect": false,
423                                             "Name": "Access Point 2",
424                                             "BSSID": "21:ef:30:b9:ad:86",
425                                             "MaxRate": 54000000,
426                                             "Frequency": 2417,
427                                             "EncryptionMode": "aes",
428                                             "Ethernet": {
429                                                 "Method": "auto",
430                                                 "Interface": "wlp1s0",
431                                                 "Address": "E8:F2:33:AC:DF:96",
432                                                 "MTU": 1500
433                                             },
434                                             "IPv4": {},
435                                             "IPv4.Configuration": {
436                                                 "Method": "dhcp"
437                                             },
438                                             "IPv6": {},
439                                             "IPv6.Configuration": {
440                                                 "Method": "auto",
441                                                 "Privacy": "disabled"
442                                             },
443                                             "Nameservers": [],
444                                             "Nameservers.Configuration": [],
445                                             "Timeservers": [],
446                                             "Timeservers.Configuration": [],
447                                             "Domains": [],
448                                             "Domains.Configuration": [],
449                                             "Proxy": {},
450                                             "Proxy.Configuration": {},
451                                             "Provider": {}
452                                         }],
453                                         ["/net/connman/service/wifi_c8f733acdf96_536563757265446f75636865626167_managed_psk",
454                                         {
455                                             "Type": "wifi",
456                                             "Security": ["psk"],
457                                             "State": "idle",
458                                             "Strength": 50,
459                                             "Favorite": false,
460                                             "Immutable": false,
461                                             "AutoConnect": false,
462                                             "Name": "Access Point 3",
463                                             "BSSID": "25:ad:44:b7:e3:66",
464                                             "MaxRate": 54000000,
465                                             "Frequency": 2417,
466                                             "EncryptionMode": "aes",
467                                             "Ethernet": {
468                                                 "Method": "auto",
469                                                 "Interface": "wlp1s0",
470                                                 "Address": "A9:28:44:AD:FF:26",
471                                                 "MTU": 1500
472                                             },
473                                             "IPv4": {},
474                                             "IPv4.Configuration": {
475                                                 "Method": "dhcp"
476                                             },
477                                             "IPv6": {},
478                                             "IPv6.Configuration": {
479                                                 "Method": "auto",
480                                                 "Privacy": "disabled"
481                                             },
482                                             "Nameservers": [],
483                                             "Nameservers.Configuration": [],
484                                             "Timeservers": [],
485                                             "Timeservers.Configuration": [],
486                                             "Domains": [],
487                                             "Domains.Configuration": [],
488                                             "Proxy": {},
489                                             "Proxy.Configuration": {},
490                                             "Provider": {}
491                                         }]
492                                     ]
493                                 ];
494
495                                 replyMsg = JSON.stringify(results);
496                                 /* simulate scan behavior */
497                                 setTimeout(function() {
498                                     call.successCB(results);
499                                 }, 2000);
500                                 return;
501                             }
502                         case WS_REQUEST_TYPE.CONNMAN_SERVICE:
503                             if (msg.name === 'connect') {
504                                 if (msg.value[0] === '/net/connman/service/wifi_c8f733acdf96_3558364737_managed_psk' && msg.value[1].Passphrase !== '123') {
505                                     call.errorCB('Invalid passphrase');
506                                 } else if (msg.value[0] === '/net/connman/service/wifi_c8f733acdf96_446f75636865626167_managed_psk' && msg.value[1].Passphrase !== '123') {
507                                     call.errorCB('Invalid passphrase');
508                                 } else {
509                                     call.successCB();
510                                     setTimeout(function() {
511                                         fireEvent(WS_EVENT_TYPE.CONNMAN, msg.value[0], 'PropertyChanged', ["Connected", true]);
512                                     }, 2000);
513                                 }
514                                 return;
515                             } else if (msg.name === 'disconnect') {
516                                 call.successCB();
517                                 setTimeout(function() {
518                                     fireEvent(WS_EVENT_TYPE.CONNMAN, msg.value[0], 'PropertyChanged', ["Connected", false]);
519                                 }, 2000);
520                                 return;
521                             } else if (msg.name === 'autoconnect') {
522                                 call.successCB();
523                                 return;
524                             } else {
525                                 if (call.errorCB) {
526                                     call.errorCB('Unsupported request: ' + msg.name + ', ' + msg.value);
527                                 }
528                                 return;
529                             }
530                             break;
531                         case WS_REQUEST_TYPE.DATETIME:
532                             if (msg.name === 'is_time_updates_auto' && msg.value !== undefined) {
533                                 /* default to manual */
534                                 call.successCB(false);
535                                 return;
536                             } else if (msg.name === 'is_timezone_updates_auto' && msg.value !== undefined) {
537                                 /* default to manual */
538                                 call.successCB(false);
539                                 return;
540                             } else if (msg.name === 'time' && msg.value !== undefined) {
541                                 call.successCB();
542                                 return;
543                             } else if (msg.name === 'timezone' && msg.value !== undefined) {
544                                 call.successCB();
545                                 return;
546                             } else if (msg.name === 'time_updates' && msg.value !== undefined) {
547                                 call.successCB();
548                                 return;
549                             } else if (msg.name === 'timezone_updates' && msg.value !== undefined) {
550                                 call.successCB();
551                                 return;
552                             } else {
553                                 if (call.errorCB) {
554                                     call.errorCB('Unsupported request: ' + msg.name + ', ' + msg.value);
555                                 }
556                                 return;
557                             }
558                             break;
559                         case WS_REQUEST_TYPE.DISPLAY:
560                         case WS_REQUEST_TYPE.SOUND:
561                         case WS_REQUEST_TYPE.LOCALE:
562                             if (call.errorCB) {
563                                 call.errorCB('Request not implemented');
564                             }
565                             return;
566                         default:
567                             if (call.errorCB) {
568                                 call.errorCB('Invalid request type: ' + msg.type);
569                             }
570                             return;
571                         }
572                     }
573                     return;
574                 }
575             }
576         }
577     }
578
579     return {
580         connect: connect,
581         reconnect: reconnect,
582         sendRequest: sendRequest,
583         subscribeEvents: subscribeEvents,
584         unsubscribeEvents: unsubscribeEvents
585     }
586 })();