Completed
Push — master ( 39fb8c...529c14 )
by Sander
01:17
created

background.constructor   B

Complexity

Conditions 1
Paths 2

Size

Total Lines 430

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 430
rs 8.2857

39 Functions

Rating   Name   Duplication   Size   Complexity  
A background.js ➔ getRuntimeSettings 0 3 1
A API.runtime.onConnect.addListener 0 14 1
A background.js ➔ ... ➔ PAPI.updateCredential 0 5 1
A storage.then 0 9 2
A background.js ➔ ... ➔ API.tabs.then 0 4 1
A API.tabs.onActivated.addListener 0 7 2
A background.js ➔ isMasterPasswordValid 0 9 2
A background.js ➔ saveMinedCallback 0 7 1
A storage.error 0 5 2
B background.js ➔ getSettings 0 44 1
A API.runtime.onConnect.addListener 0 10 3
A background.js ➔ getCredentialForHTTPAuth 0 4 1
A background.js ➔ isVaultKeySet 0 3 1
A background.js ➔ displayLogoutIcons 0 21 2
A background.js ➔ ... ➔ storage.then 0 3 1
B background.js ➔ minedForm 0 30 4
A background.js ➔ ... ➔ setInterval 0 3 1
A background.js ➔ ... ➔ PAPI.createCredential 0 5 1
B background.js ➔ ... ➔ PAPI.getVault 0 25 6
A background.js ➔ updateTabsIcon 0 8 1
A background.js ➔ setMasterPassword 0 17 4
B background.js ➔ createIconForTab 0 24 4
A background.js ➔ ... ➔ PAPI.createCredential 0 5 1
A background.js ➔ getMinedData 0 4 1
B background.js ➔ saveMined 0 35 5
A background.js ➔ getMasterPasswordSet 0 3 1
A API.runtime.onMessage.addListener 0 11 3
B background.js ➔ getCredentialsByUrl 0 15 7
A background.js ➔ ... ➔ API.tabs.then 0 2 1
B background.js ➔ getCredentials 0 29 1
A API.tabs.onActivated.addListener 0 9 1
D background.js ➔ ... ➔ storage.then 0 41 10
A background.js ➔ clearMined 0 3 1
A background.js ➔ injectCreateCredential 0 13 1
A background.js ➔ isAutoFillEnabled 0 6 2
A background.js ➔ saveSettings 0 17 2
A API.tabs.onUpdated.addListener 0 7 2
A background.js ➔ ... ➔ API.tabs.then 0 17 2
A background.js ➔ ... ➔ API.tabs.then 0 6 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
/* global API */
2
3
var background = (function () {
4
    var storage = new API.Storage();
5
    var _self = this;
6
    var _window = {};
7
    API.runtime.onConnect.addListener(function (port) {
8
9
        port.onMessage.addListener(function (msg) {
10
11
            if (msg === 'credential_amount') {
12
                port.postMessage('credential_amount:' + local_credentials.length);
13
            }
14
            if (msg === 'getByUrl') {
0 ignored issues
show
Comprehensibility Documentation Best Practice introduced by
This code block is empty. Consider removing it or adding a comment to explain.
Loading history...
15
16
            }
17
18
        });
19
20
    });
21
22
    var master_password = null;
23
24
    function getMasterPasswordSet() {
25
        return (master_password !== null);
26
    }
27
28
    _self.getMasterPasswordSet = getMasterPasswordSet;
29
30
    function setMasterPassword(opts) {
31
        master_password = opts.password;
32
        if (opts.hasOwnProperty('savePassword') && opts.savePassword === true) {
33
            // Save the password in plain text on user request.
34
            // No secure local storage is available :/
35
            storage.set('master_password', opts.password);
36
        } else {
37
            storage.set('master_password', null);
38
        }
39
40
        if (opts.password) {
41
            getSettings();
42
        } else {
43
            displayLogoutIcons();
44
        }
45
46
    }
47
48
    _self.setMasterPassword = setMasterPassword;
49
50
51
    var testMasterPasswordAgainst;
52
53
    function isMasterPasswordValid(password) {
54
        //return true;
55
        try {
56
            PAPI.decryptString(testMasterPasswordAgainst, password);
57
            return true;
58
        } catch (e) {
59
            return false;
60
        }
61
    }
62
63
    _self.isMasterPasswordValid = isMasterPasswordValid;
64
65
66
    var local_credentials = [];
67
    var local_vault = [];
68
    var encryptedFieldSettings = ['default_vault', 'nextcloud_host', 'nextcloud_username', 'nextcloud_password', 'vault_password'];
69
    _self.settings = {};
70
    _self.ticker = null;
71
    _self.running = false;
72
    function getSettings() {
73
74
        storage.get('settings').then(function (_settings) {
75
76
            if (!_settings || !_settings.hasOwnProperty('nextcloud_host')) {
77
                return;
78
            }
79
80
            if (!master_password && _settings.hasOwnProperty('nextcloud_username') && _settings.hasOwnProperty('vault_password')) {
81
                _self.settings.isInstalled = 1;
82
                testMasterPasswordAgainst = _settings.nextcloud_username;
83
                return;
84
            }
85
86
            for (var i = 0; i < encryptedFieldSettings.length; i++) {
87
                var field = encryptedFieldSettings[i];
88
                _settings[field] = JSON.parse(PAPI.decryptString(_settings[field], master_password));
89
            }
90
91
92
            _self.settings = _settings;
93
94
95
            PAPI.host = _settings.nextcloud_host;
96
            PAPI.username = _settings.nextcloud_username;
97
            PAPI.password = _settings.nextcloud_password;
98
            if (!_settings.vault_password) {
99
                return;
100
            }
101
            if (PAPI.credentialsSet()) {
102
                getCredentials();
103
                if (_self.running) {
104
                    clearInterval(_self.ticker);
105
                }
106
107
                _self.running = true;
108
                _self.ticker = setInterval(function () {
109
                    getCredentials();
110
                }, _self.settings.refreshTime * 1000);
111
            } else {
112
                console.log('Login details are missing!');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
113
            }
114
        });
115
    }
116
117
    _self.getSettings = getSettings;
118
119
    function getRuntimeSettings() {
120
        return _self.settings;
121
    }
122
123
    _self.getRuntimeSettings = getRuntimeSettings;
124
125
    function saveSettings(settings, cb) {
0 ignored issues
show
Unused Code introduced by
The parameter cb is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
126
        for (var i = 0; i < encryptedFieldSettings.length; i++) {
127
            var field = encryptedFieldSettings[i];
128
            settings[field] = PAPI.encryptString(JSON.stringify(settings[field]), master_password);
129
        }
130
        PAPI.host = settings.nextcloud_host;
131
        PAPI.username = settings.nextcloud_username;
132
        PAPI.password = settings.nextcloud_password;
133
        //window.settings contains the run-time settings
134
        _self.settings = settings;
135
136
137
        storage.set('settings', settings).then(function () {
138
            getSettings();
139
        });
140
141
    }
142
143
    _self.saveSettings = saveSettings;
144
145
146
    function getCredentials() {
147
        //console.log('Loading vault with the following settings: ', settings);
148
        var tmpList = [];
149
        PAPI.getVault(_self.settings.default_vault.guid, function (vault) {
150
            if(vault.hasOwnProperty('error')){
151
                return;
152
            }
153
            var _credentials = vault.credentials;
154
            for (var i = 0; i < _credentials.length; i++) {
155
                var key = _self.settings.vault_password;
156
                var credential = _credentials[i];
157
                if (credential.hidden === 1) {
158
                    continue;
159
                }
160
                var usedKey = key;
161
                //Shared credentials are not implemented yet
162
                if (credential.hasOwnProperty('shared_key') && credential.shared_key) {
163
                    usedKey = PAPI.decryptString(credential.shared_key, key);
164
165
                }
166
                credential = PAPI.decryptCredential(credential, usedKey);
167
                tmpList.push(credential);
168
            }
169
            delete vault.credentials;
170
            local_vault = vault;
171
            local_credentials = tmpList;
172
            updateTabsIcon();
173
        });
174
    }
175
176
    _self.getCredentials = getCredentials;
177
178
    function getCredentialsByUrl(_url, sender) {
0 ignored issues
show
Unused Code introduced by
The parameter sender is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
179
        if (!master_password) {
180
            return [];
181
        }
182
        var url = processURL(_url, _self.settings.ignoreProtocol, _self.settings.ignoreSubdomain, _self.settings.ignorePath, _self.settings.ignorePort);
183
        var found_list = [];
184
        for (var i = 0; i < local_credentials.length; i++) {
185
            if (local_credentials[i].url && local_credentials[i].username && local_credentials[i].password) {
186
                if (local_credentials[i].url.indexOf(url) !== -1) {
187
                    found_list.push(local_credentials[i]);
188
                }
189
            }
190
        }
191
        return found_list;
192
    }
193
194
    _self.getCredentialsByUrl = getCredentialsByUrl;
195
196
197
    function getCredentialForHTTPAuth(req){
198
        console.log(req)
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
199
        return getCredentialsByUrl(req.url)[0];
200
    }
201
202
    _window.getCredentialForHTTPAuth = getCredentialForHTTPAuth;
203
204
    var mined_data = [];
205
206
    function minedForm(data, sender) {
207
        var url = sender.url;
208
        var existingLogins = getCredentialsByUrl(sender.url);
209
        var title = "Detected new login:";
210
        var minedMatchingID = null;
211
        for (var j = 0; j < existingLogins.length; j++) {
212
            var login = existingLogins[j];
213
            if (login.username === data.username) {
214
                if (login.password !== data.password) {
215
                    minedMatchingID = login.guid;
216
                    title = "Detected changed password for user:";
217
                }
218
                else {
219
                    //console.log('No changes detected');
220
                    delete mined_data[sender.tab.id];
221
                    return;
222
                }
223
            }
224
        }
225
        mined_data[sender.tab.id] = {
226
            title: title,
227
            url: url,
228
            username: data.username,
229
            password: data.password,
230
            label: sender.title,
231
            guid: minedMatchingID
232
        };
233
234
        //console.log('Done mining, ', mined_data, sender.tab.id);
235
    }
236
237
    _self.minedForm = minedForm;
238
239
    function getMinedData(args, sender) {
240
        //console.log('Fecthing  mined data for tab id', sender.tab.id)
241
        return mined_data[sender.tab.id];
242
    }
243
244
    _self.getMinedData = getMinedData;
245
246
    function clearMined(args, sender) {
247
        delete mined_data[sender.tab.id];
248
    }
249
250
    _self.clearMined = clearMined;
251
252
    function saveMinedCallback(args) {
253
        createIconForTab(args.sender.tab);
254
        API.tabs.query({active: true, currentWindow: true}).then(function (tabs) {
255
            API.tabs.sendMessage(args.sender.tab.id, {method: "minedLoginSaved", args: args}).then(function (response) {
0 ignored issues
show
Unused Code introduced by
The parameter response is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
256
            });
257
        });
258
    }
259
260
    function saveMined(args, sender) {
261
        var data = mined_data[sender.tab.id];
262
        var credential,
263
            credential_index;
264
265
        if (data.guid === null) {
266
            credential = PAPI.newCredential();
267
        } else {
268
            for (var i = 0; i < local_credentials.length; i++) {
269
                if (local_credentials[i].guid === data.guid) {
270
                    credential = local_credentials[i];
271
                    credential_index = i;
272
                    return;
273
                }
274
            }
275
        }
276
        credential.username = data.username;
0 ignored issues
show
Bug introduced by
The variable credential seems to not be initialized for all possible execution paths.
Loading history...
277
        credential.password = data.password;
278
        credential.url = sender.tab.url;
279
        if (credential.guid !== null) {
280
            PAPI.updateCredential(credential, _self.settings.vault_password, function (updatedCredential) {
281
                local_credentials[credential_index] = updatedCredential;
282
                saveMinedCallback({credential: credential, updated: true, sender: sender});
0 ignored issues
show
Bug introduced by
The variable credential seems to not be initialized for all possible execution paths.
Loading history...
283
                delete mined_data[sender.tab.id];
284
            });
285
        } else {
286
            credential.label = sender.tab.title;
287
            credential.vault_id = local_vault.vault_id;
288
            PAPI.createCredential(credential, _self.settings.vault_password, function (createdCredential) {
289
                saveMinedCallback({credential: credential, updated: false, sender: sender});
0 ignored issues
show
Bug introduced by
The variable credential seems to not be initialized for all possible execution paths.
Loading history...
290
                local_credentials.push(createdCredential);
291
                delete mined_data[sender.tab.id];
292
            });
293
        }
294
    }
295
296
    _self.saveMined = saveMined;
297
298
299
    function injectCreateCredential(args, sender) {
0 ignored issues
show
introduced by
The function injectCreateCredential does not seem to be used and can be removed.
Loading history...
300
        var credential = PAPI.newCredential();
301
        credential.label = args.label;
302
        credential.username = args.username;
303
        credential.password = args.username;
304
        credential.vault_id = local_vault.vault_id;
305
        credential.url = sender.tab.url;
306
        PAPI.createCredential(credential, _self.settings.vault_password, function (createdCredential) {
307
            saveMinedCallback({credential: credential, updated: false, sender: sender, selfAdded: true});
308
            local_credentials.push(createdCredential);
309
310
        });
311
    }
312
313
    function isVaultKeySet() {
314
        return (_self.settings.vault_password !== null);
315
    }
316
317
    _self.isVaultKeySet = isVaultKeySet;
318
319
    function isAutoFillEnabled() {
320
        if(!_self.settings.hasOwnProperty('disableAutoFill')){
321
            return true;
322
        }
323
        return (_self.settings.disableAutoFill === false);
324
    }
325
326
    _self.isAutoFillEnabled = isAutoFillEnabled;
327
328
    API.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
329
        //console.log('Method call', msg.method);
330
331
        if (!msg || !msg.hasOwnProperty('method')) {
332
            return;
333
        }
334
335
        var result = _self[msg.method](msg.args, sender);
336
337
        sendResponse(result);
338
    });
339
340
    var defaultColor = '#0082c9';
341
    function createIconForTab(tab) {
342
        if (!master_password) {
343
            return;
344
        }
345
        var tabUrl = tab.url;
346
        var logins = getCredentialsByUrl(tabUrl);
347
        if(tab.active) {
348
            window.contextMenu.setContextItems(logins);
349
        }
350
        var credentialAmount = logins.length;
351
            API.browserAction.setBadgeText({
352
            text: credentialAmount.toString(),
353
            tabId: tab.id
354
        });
355
        API.browserAction.setBadgeBackgroundColor({
356
            color: defaultColor,
357
            tabId: tab.id
358
        });
359
        var plural = (credentialAmount === 1) ? 'credential' : 'credentials';
360
        API.browserAction.setTitle({
361
            title: 'Passman - ' + credentialAmount.toString() + ' '+ plural +' found for this page',
362
            tabId: tab.id
363
        });
364
    }
365
366
    function displayLogoutIcons() {
367
        if(_self.settings) {
368
            API.tabs.query({}).then(function (tabs) {
369
                for (var t = 0; t < tabs.length; t++) {
370
                    var tab = tabs[t];
371
                    API.browserAction.setBadgeText({
372
                        text: '🔑',
373
                        tabId: tab.id
374
                    });
375
                    API.browserAction.setBadgeBackgroundColor({
376
                        color: '#ff0000',
377
                        tabId: tab.id
378
                    });
379
                    API.browserAction.setTitle({
380
                        title: 'Passman - Locked',
381
                        tabId: tab.id
382
                    });
383
                }
384
            });
385
        }
386
    }
387
388
    function updateTabsIcon() {
389
        API.tabs.query({}).then(function (tabs) {
390
            for (var t = 0; t < tabs.length; t++) {
391
                var tab = tabs[t];
392
                createIconForTab(tab);
393
            }
394
        });
395
    }
396
397
398
    API.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
399
        if(master_password){
400
            createIconForTab(tab);
401
        } else {
402
            displayLogoutIcons();
403
        }
404
    });
405
406
    API.tabs.onActivated.addListener(function () {
407
        API.tabs.query({active: true, currentWindow: true}).then(function (tabs) {
408
            if(master_password){
409
                createIconForTab(tabs[0]);
410
            } else {
411
                displayLogoutIcons();
412
            }
413
        });
414
    });
415
416
    displayLogoutIcons();
417
418
    storage.get('master_password').then(function (password) {
419
        if (password) {
420
            master_password = password;
421
            API.api.browserAction.setBadgeBackgroundColor({
422
                color: defaultColor
423
            });
424
        }
425
        getSettings();
426
    }).error(function (error) {
427
        if (error === "Data not found") {
428
            getSettings();
429
        }
430
    });
431
    return _window;
432
}());
433
434