source: desktop/foneradownloader/trunk/chrome/content/js/fonera.js @ 2383

Last change on this file since 2383 was 2383, checked in by matthijs, 4 years ago

Move from nsIJSON to native JSON

The nsIJSON interface is deprecated, so switch to the native JSON
interface that is available since Firefox 3.5. Also bump the minimum
version.

File size: 11.7 KB
Line 
1/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
2
3/*
4
5 fonera.js : Fonera Javascript helper
6 (C) Fon
7 Author: Javier Monteagudo (Javier.monteagudo@fon.com)
8
9 This program is free software: you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License along
20 with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22
23*/
24
25
26
27let EXPORTED_SYMBOLS = ["Fonera"];
28
29let Fonera = {
30
31    Application : Components.classes["@mozilla.org/fuel/application;1"]
32        .getService(Components.interfaces.fuelIApplication),
33
34    Preferences : Components.classes["@mozilla.org/preferences-service;1"]
35        .getService(Components.interfaces.nsIPrefService),
36
37    nsLoginInfo : new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
38                                             Components.interfaces.nsILoginInfo,
39                                             "init"),
40    passwordManager : Components.classes["@mozilla.org/login-manager;1"].
41        getService(Components.interfaces.nsILoginManager),
42
43    // authentication status:
44    AUTHTOKEN : "authToken",
45    authError : "ERROR", // Cannot reach the fonera
46    authFailed : "FAILED", // Cannot log in
47
48    // discs status:
49    DISKS : "disks",
50    noDisk : "NODISK", // no disk attached
51
52    // Errors:
53    LASTERROR : "foneralasterror",
54    // Events:
55    onCheckFoneraAvailable : [],
56    onAuthenticate : [],
57    onCheckDisks : [],
58
59    addEventListener : function(event, callback) {
60        try {
61            // example: event == onCheckFoneraAvailable
62            Fonera[event].push(callback);
63        } catch (e) {
64            Fonera.Application.console.log("invalid registration for event "
65                                    + event + ": " + callback + ": " + e);
66        }
67    },
68
69    removeEventListener : function(event, callback) {
70        try {
71            // example: event == onCheckFoneraAvailable
72            let eventCallbacks = Fonera[event];
73            for (let i in eventCallbacks)
74                if (callback == eventCallbacks[i])
75                    // remove from index i, 1 element
76                    eventCallbacks.splice(i,1);
77        } catch (e) {
78            Fonera.Application.console.log("invalid registration for event "
79                                    + event + ": " + callback + ": " + e);
80        }
81    },
82
83    notify : function(aEvent) {
84        for (let i in aEvent) {
85            let aCallback = aEvent[i];
86            aCallback();
87        }
88    },
89
90    getUserPref : function(preference) {
91        let Preferences = Components.classes["@mozilla.org/preferences-service;1"]
92            .getService(Components.interfaces.nsIPrefService);
93        let prefs = Preferences.getBranch("extensions.foneradownloader."); // the final . is needed
94        if (prefs.prefHasUserValue(preference))
95            return prefs.getCharPref(preference);
96        else
97            return null;
98    },
99
100    getUsername : function() {
101        return "fonero";
102    },
103
104    isPluginEnabled : function() {
105        let prefs = Fonera.Preferences.getBranch("extensions.foneradownloader."); // the final . is needed
106        if (prefs.prefHasUserValue("enabled"))
107            return prefs.getBoolPref("enabled");
108        else
109            return true;
110    },
111
112    getPassword : function() {
113        let password = '';
114        let username = Fonera.getUsername();
115
116        // retrieve password with password manager
117        try {
118            let logins = Fonera.passwordManager.findLogins({}, 'chrome://foneradownloader', null, 'Fonera user Login');
119                for (let i = 0; i < logins.length; i++) {
120                    if (logins[i].username == username) {
121                        password = logins[i].password;
122                        break;
123                    }
124                }
125        } catch(e) {
126            Fonera.Application.console.log(e);
127        }
128        return password;
129    },
130
131    // url for reaching the fonera.
132    foneraURL : function () {
133        let prefs = Fonera.Preferences.getBranch("extensions.foneradownloader."); // the final . is needed
134        let onwan = prefs.getBoolPref("onwan");
135        let password = Fonera.getPassword();
136        if (!onwan)
137            return "http://" + this.getUserPref("foneraip") + "/luci";
138        else {
139            return "https://" + this.getUsername() + ":" + encodeURIComponent(password) + "@"
140                + this.getUserPref("foneraip") + "/luci";
141        }
142    },
143
144    authenticated : function(authToken) {
145        if (!Fonera.isPluginEnabled())
146            return false;
147        return (authToken != null && authToken != Fonera.authFailed
148                && authToken != Fonera.authError);
149    },
150
151    notifyAllEvents : function() {
152        this.notify(this.onCheckFoneraAvailable);
153        this.notify(this.onAuthenticate);
154        this.notify(this.onCheckDisks);
155    },
156
157    checkFoneraAvailable: function() {
158        // do we want to re-authenticate?
159        let reAuth = false;
160        reAuth = (arguments.length == 1 && arguments[0] == true);
161        let authToken = Fonera.Application.storage.get(this.AUTHTOKEN, null);
162        if (reAuth) {
163            // disable sessions:
164            Fonera.Application.console.log("Disable session storage");
165            Fonera.Application.storage.set(this.AUTHTOKEN, null);
166            Fonera.Application.storage.set(this.FONERADOWNLOADS, []);
167            Fonera.Application.storage.set(this.FONERATORRENTS, []);
168            Fonera.Application.storage.set(this.DISKS, null);
169            this.notifyAllEvents();
170        }
171
172        if (!this.isPluginEnabled()) {
173            if (!reAuth) {
174                this.notifyAllEvents();
175            }
176            return;
177        }
178
179        if (!reAuth && this.authenticated(authToken)) {
180            Fonera.Application.console.log("already authenticated\n");
181            this.notify(this.onAuthenticate);
182            return;
183        }
184
185        // checks if we can reach the luci interface
186        let req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
187            .createInstance(Components.interfaces.nsIXMLHttpRequest);
188
189        let url = this.foneraURL();
190        Fonera.Application.console.log("Checking URL : " + url + "\n");
191        req.open('GET', url, true); /* asynchronous! */
192        req.channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE;
193        req.onreadystatechange = function (aEvt) {
194            if (req.readyState == 4) {
195                if(req.status == 200) {
196                    Fonera.authenticate(reAuth);
197                } else {
198                    Fonera.Application.storage.set(Fonera.AUTHTOKEN, Fonera.authError);
199                    Fonera.Application.console.log("Fonera NOT ready\n");
200                }
201                Fonera.notify(Fonera.onCheckFoneraAvailable);
202            }
203        };
204        req.send(null);
205    },
206
207    authenticate: function(reAuth) {
208        let authToken = Fonera.Application.storage.get(this.AUTHTOKEN, null);
209        if (!reAuth && this.authenticated(authToken)) {
210            Fonera.Application.console.log("already authenticated\n");
211            this.notify(this.onAuthenticate);
212            return;
213        }
214
215        // Send
216        let req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
217            .createInstance(Components.interfaces.nsIXMLHttpRequest);
218        let url =  this.foneraURL() + "/fon_rpc/ff/auth";
219        let stream = JSON.stringify({"method": "plain",
220            "params" : [this.getUsername(),
221                        Fonera.getPassword()] });
222
223        Fonera.Application.console.log("Authenticating to URL : " + url + "\n");
224        Fonera.Application.console.log("POST : " + stream + "\n");
225
226        req.open('POST', url, true); /* asynchronous! */
227        req.channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE;
228        req.setRequestHeader('Content-Type', "application/json");
229
230        req.onreadystatechange = function (aEvt) {
231            if (req.readyState == 4) {
232                Fonera.Application.console.log("Response :" + req.responseText + "\n");
233                if(req.status == 200) {
234                    let response = JSON.parse(req.responseText);
235                    if (response.error == null && response.result != null) {
236                        Fonera.Application.console.log(Fonera.AUTHTOKEN + " : " + response.result);
237                        Fonera.Application.storage.set(Fonera.AUTHTOKEN, response.result);
238                        // Fonera.checkDisks();
239                    } else {
240                        Fonera.Application.storage.set(Fonera.AUTHTOKEN, Fonera.authFailed);
241                        Fonera.Application.console.log("Authentication FAILED\n");
242                    }
243                    Fonera.notify(Fonera.onAuthenticate);
244                }
245            }
246        };
247        req.send(stream);
248    },
249
250    checkDisks : function() {
251        let Application = Components.classes["@mozilla.org/fuel/application;1"]
252            .getService(Components.interfaces.fuelIApplication);
253
254        let authToken = Fonera.Application.storage.get(Fonera.AUTHTOKEN, null);
255        if (!Fonera.authenticated(authToken)) {
256            Fonera.Application.console.log("Not authenticated\n");
257            return;
258        }
259
260        // https://developer.mozilla.org/En/Using_XMLHttpRequest
261        // Send
262        let req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
263            .createInstance(Components.interfaces.nsIXMLHttpRequest);
264
265        //luci/fon_rpc/ff?auth=62BAAF5E1E2A16D78C31AEB7C5F8D9C8
266        let url =  Fonera.foneraURL() + "/fon_rpc/ff?auth=" + authToken;
267        let rpcCall = {"method": "get_discs"};
268        let stream = JSON.stringify(rpcCall);
269
270        Fonera.Application.console.log("POST : " + stream + "\n");
271
272        // async even if dialog is closed:
273        req.mozBackgroundRequest = true;
274        req.open('POST', url, true); /* asynchronous! */
275        req.channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE;
276        req.setRequestHeader('Content-Type', "application/json");
277
278        req.onload = function (aEvt) {
279            if (req.readyState == 4) {
280                Fonera.Application.console.log("Response :" + req.responseText + "\n");
281                if (req.status == 200) {
282                    let response = JSON.parse(req.responseText);
283                    if (response.error == null) {
284                        if (response.result == null) {
285                            Fonera.Application.console.log("No disks found");
286                            Fonera.Application.storage.set(Fonera.DISKS, Fonera.noDisk);
287                        } else {
288                            Fonera.Application.storage.set(Fonera.DISKS, response.result);
289                        }
290                    } else {
291                        Fonera.Application.console.log("Response Error: " + response.error + "\n");
292                    }
293                    Fonera.notify(Fonera.onCheckDisks);
294                } else {
295                    Fonera.Application.console.log("Http Status Error :" + req.status + "\n");
296                }
297            }
298        };
299        req.send(stream);
300    },
301
302    hasDisk : function() {
303        let disks = Fonera.Application.storage.get(Fonera.DISKS, Fonera.noDisk);
304        return (disks != Fonera.noDisk);
305    },
306
307    loadEvents : function() {
308        Fonera.addEventListener("onAuthenticate",
309                                Fonera.checkDisks);
310    },
311
312    unloadEvents : function() {
313        Fonera.removeEventListener("onAuthenticate",
314                                Fonera.checkDisks);
315    }
316
317};
Note: See TracBrowser for help on using the repository browser.