Completed
Push — master ( b28cb5...a65932 )
by Sander
01:06
created

background.js ➔ getActiveTab   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 9
rs 9.6666
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
            if (msg === 'credential_amount') {
11
                port.postMessage('credential_amount:' + local_credentials.length);
12
            }
13
14
        });
15
16
    });
17
18
    var master_password = null;
19
20
    function getMasterPasswordSet() {
21
        return (master_password !== null);
22
    }
23
24
    _self.getMasterPasswordSet = getMasterPasswordSet;
25
26
    function setMasterPassword(opts) {
27
        master_password = opts.password;
28
        if (opts.hasOwnProperty('savePassword') && opts.savePassword === true) {
29
            // Save the password in plain text on user request.
30
            // No secure local storage is available :/
31
            storage.set('master_password', opts.password);
32
        } else {
33
            storage.set('master_password', null);
34
        }
35
36
        if (opts.password) {
37
            getSettings();
38
        } else {
39
            displayLogoutIcons();
40
        }
41
42
    }
43
44
    _self.setMasterPassword = setMasterPassword;
45
46
47
    var testMasterPasswordAgainst;
48
49
    function isMasterPasswordValid(password) {
50
        //return true;
51
        try {
52
            PAPI.decryptString(testMasterPasswordAgainst, password);
53
            return true;
54
        } catch (e) {
55
            return false;
56
        }
57
    }
58
59
    _self.isMasterPasswordValid = isMasterPasswordValid;
60
61
62
    var local_credentials = [];
63
    var local_vault = [];
64
    var encryptedFieldSettings = ['default_vault', 'nextcloud_host', 'nextcloud_username', 'nextcloud_password', 'vault_password'];
65
    _self.settings = {};
66
    _self.ticker = null;
67
    _self.running = false;
68
    function getSettings() {
69
70
        storage.get('settings').then(function (_settings) {
71
72
            if (!_settings || !_settings.hasOwnProperty('nextcloud_host')) {
73
                return;
74
            }
75
76
            if (!master_password && _settings.hasOwnProperty('nextcloud_username') && _settings.hasOwnProperty('vault_password')) {
77
                _self.settings.isInstalled = 1;
78
                testMasterPasswordAgainst = _settings.nextcloud_username;
79
                return;
80
            }
81
82
            for (var i = 0; i < encryptedFieldSettings.length; i++) {
83
                var field = encryptedFieldSettings[i];
84
                _settings[field] = JSON.parse(PAPI.decryptString(_settings[field], master_password));
85
            }
86
87
88
            _self.settings = _settings;
89
90
91
            PAPI.host = _settings.nextcloud_host;
92
            PAPI.username = _settings.nextcloud_username;
93
            PAPI.password = _settings.nextcloud_password;
94
            if (!_settings.vault_password) {
95
                return;
96
            }
97
            if (PAPI.credentialsSet()) {
98
                getCredentials();
99
                if (_self.running) {
100
                    clearInterval(_self.ticker);
101
                }
102
103
                _self.running = true;
104
                _self.ticker = setInterval(function () {
105
                    getCredentials();
106
                }, _self.settings.refreshTime * 1000);
107
            } else {
108
                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...
109
            }
110
        });
111
    }
112
113
    _self.getSettings = getSettings;
114
115
    function getRuntimeSettings() {
116
        return _self.settings;
117
    }
118
119
    _self.getRuntimeSettings = getRuntimeSettings;
120
121
    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...
122
        for (var i = 0; i < encryptedFieldSettings.length; i++) {
123
            var field = encryptedFieldSettings[i];
124
            settings[field] = PAPI.encryptString(JSON.stringify(settings[field]), master_password);
125
        }
126
        PAPI.host = settings.nextcloud_host;
127
        PAPI.username = settings.nextcloud_username;
128
        PAPI.password = settings.nextcloud_password;
129
        //window.settings contains the run-time settings
130
        _self.settings = settings;
131
132
133
        storage.set('settings', settings).then(function () {
134
            getSettings();
135
        });
136
137
    }
138
139
    _self.saveSettings = saveSettings;
140
141
142
    function getCredentials() {
143
        //console.log('Loading vault with the following settings: ', settings);
144
        var tmpList = [];
145
        PAPI.getVault(_self.settings.default_vault.guid, function (vault) {
146
            if(vault.hasOwnProperty('error')){
147
                return;
148
            }
149
            var _credentials = vault.credentials;
150
            for (var i = 0; i < _credentials.length; i++) {
151
                var key = _self.settings.vault_password;
152
                var credential = _credentials[i];
153
                if (credential.hidden === 1) {
154
                    continue;
155
                }
156
                var usedKey = key;
157
                //Shared credentials are not implemented yet
158
                if (credential.hasOwnProperty('shared_key') && credential.shared_key) {
159
                    usedKey = PAPI.decryptString(credential.shared_key, key);
160
161
                }
162
                credential = PAPI.decryptCredential(credential, usedKey);
163
                if(credential.delete_time === 0){
164
                    tmpList.push(credential);
165
                }
166
167
            }
168
            delete vault.credentials;
169
            local_vault = vault;
170
            local_credentials = tmpList;
171
            updateTabsIcon();
172
        });
173
    }
174
175
    _self.getCredentials = getCredentials;
176
177
    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...
178
        if (!master_password) {
179
            return [];
180
        }
181
        if(!_url || _url === '' ){
182
            return [];
183
        }
184
        var url = processURL(_url, _self.settings.ignoreProtocol, _self.settings.ignoreSubdomain, _self.settings.ignorePath, _self.settings.ignorePort);
185
        var found_list = [];
186
        for (var i = 0; i < local_credentials.length; i++) {
187
            if (local_credentials[i].url && local_credentials[i].username && local_credentials[i].password) {
188
                if (local_credentials[i].url.indexOf(url) !== -1) {
189
                    found_list.push(local_credentials[i]);
190
                }
191
            }
192
        }
193
        return found_list;
194
    }
195
196
    _self.getCredentialsByUrl = getCredentialsByUrl;
197
198
199
    function getCredentialForHTTPAuth(req){
200
        return getCredentialsByUrl(req.url)[0];
201
    }
202
203
    _window.getCredentialForHTTPAuth = getCredentialForHTTPAuth;
204
205
    var mined_data = [];
206
207
    function minedForm(data, sender) {
208
        var url = sender.url;
209
        var existingLogins = getCredentialsByUrl(sender.url);
210
        var title = "Detected new login:";
211
        var minedMatchingID = null;
212
        for (var j = 0; j < existingLogins.length; j++) {
213
            var login = existingLogins[j];
214
            if (login.username === data.username) {
215
                if (login.password !== data.password) {
216
                    minedMatchingID = login.guid;
217
                    title = "Detected changed password for user:";
218
                }
219
                else {
220
                    //console.log('No changes detected');
221
                    delete mined_data[sender.tab.id];
222
                    return;
223
                }
224
            }
225
        }
226
        mined_data[sender.tab.id] = {
227
            title: title,
228
            url: url,
229
            username: data.username,
230
            password: data.password,
231
            label: sender.title,
232
            guid: minedMatchingID
233
        };
234
235
        //console.log('Done mining, ', mined_data, sender.tab.id);
236
    }
237
238
    _self.minedForm = minedForm;
239
240
    function getMinedData(args, sender) {
241
        //console.log('Fecthing  mined data for tab id', sender.tab.id)
242
        return mined_data[sender.tab.id];
243
    }
244
245
    _self.getMinedData = getMinedData;
246
247
    function clearMined(args, sender) {
248
        delete mined_data[sender.tab.id];
249
    }
250
251
    _self.clearMined = clearMined;
252
253
    function saveMinedCallback(args) {
254
        createIconForTab(args.sender.tab);
255
        API.tabs.query({active: true, currentWindow: true}).then(function (tabs) {
256
            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...
257
            });
258
        });
259
    }
260
261
    function passToParent(args,sender) {
262
        API.tabs.sendMessage(sender.tab.id, {method: args.injectMethod, args: 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...
263
        });
264
    }
265
    _self.passToParent = passToParent;
266
267
    function getActiveTab(opt) {
268
        console.log(opt)
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...
269
        API.tabs.query({active: true, currentWindow: true}).then(function (tabs) {
270
            console.log(tabs);
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...
271
            var tab = tabs[0];
272
            API.tabs.sendMessage(tab.id, {method: opt.returnFn, args: tab}).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...
273
            });
274
        });
275
    }
276
    _self.getActiveTab = getActiveTab;
277
278
    function saveMined(args, sender) {
279
        var data = mined_data[sender.tab.id];
280
        var credential,
281
            credential_index;
282
283
        if (data.guid === null) {
284
            credential = PAPI.newCredential();
285
        } else {
286
            for (var i = 0; i < local_credentials.length; i++) {
287
                if (local_credentials[i].guid === data.guid) {
288
                    credential = local_credentials[i];
289
                    credential_index = i;
290
                    return;
291
                }
292
            }
293
        }
294
        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...
295
        credential.password = data.password;
296
        credential.url = sender.tab.url;
297
        if (credential.guid !== null) {
298
            PAPI.updateCredential(credential, _self.settings.vault_password, function (updatedCredential) {
299
                local_credentials[credential_index] = updatedCredential;
300
                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...
301
                delete mined_data[sender.tab.id];
302
            });
303
        } else {
304
            credential.label = sender.tab.title;
305
            credential.vault_id = local_vault.vault_id;
306
            PAPI.createCredential(credential, _self.settings.vault_password, function (createdCredential) {
307
                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...
308
                local_credentials.push(createdCredential);
309
                delete mined_data[sender.tab.id];
310
            });
311
        }
312
    }
313
314
    _self.saveMined = saveMined;
315
316
317
    function injectCreateCredential(args, sender) {
318
        var credential = PAPI.newCredential();
319
        credential.label = args.label;
320
        credential.username = args.username;
321
        credential.password = args.username;
322
        credential.vault_id = local_vault.vault_id;
323
        credential.url = sender.tab.url;
324
        PAPI.createCredential(credential, _self.settings.vault_password, function (createdCredential) {
325
            saveMinedCallback({credential: credential, updated: false, sender: sender, selfAdded: true});
326
            local_credentials.push(createdCredential);
327
328
        });
329
    }
330
    self.injectCreateCredential = injectCreateCredential;
0 ignored issues
show
Bug introduced by
The variable self seems to be never declared. If this is a global, consider adding a /** global: self */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
331
332
    function isVaultKeySet() {
333
        return (_self.settings.vault_password !== null);
334
    }
335
336
    _self.isVaultKeySet = isVaultKeySet;
337
338
    function isAutoFillEnabled() {
339
        if(!_self.settings.hasOwnProperty('disableAutoFill')){
340
            return true;
341
        }
342
        return (_self.settings.disableAutoFill === false);
343
    }
344
345
    _self.isAutoFillEnabled = isAutoFillEnabled;
346
347
    API.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
348
        console.log('Method call', msg.method, 'args: ', msg.args);
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...
349
350
        if (!msg || !msg.hasOwnProperty('method')) {
351
            return;
352
        }
353
        var result = false;
354
        if(_self[msg.method]) {
355
            result = _self[msg.method](msg.args, sender);
356
        } else {
357
            console.log('[NOT FOUND] Method call', msg.method, 'args: ', msg.args);
358
        }
359
360
        sendResponse(result);
361
    });
362
363
    var defaultColor = '#0082c9';
364
    function createIconForTab(tab) {
365
        if (!master_password) {
366
            return;
367
        }
368
        var tabUrl = tab.url;
369
        var logins = getCredentialsByUrl(tabUrl);
370
        if(tab.active) {
371
            window.contextMenu.setContextItems(logins);
372
        }
373
        var credentialAmount = logins.length;
374
            API.browserAction.setBadgeText({
375
            text: credentialAmount.toString(),
376
            tabId: tab.id
377
        });
378
        API.browserAction.setBadgeBackgroundColor({
379
            color: defaultColor,
380
            tabId: tab.id
381
        });
382
        var plural = (credentialAmount === 1) ? 'credential' : 'credentials';
383
        API.browserAction.setTitle({
384
            title: 'Passman - ' + credentialAmount.toString() + ' '+ plural +' found for this page',
385
            tabId: tab.id
386
        });
387
    }
388
389
    function displayLogoutIcons() {
390
        if(_self.settings) {
391
            API.tabs.query({}).then(function (tabs) {
392
                for (var t = 0; t < tabs.length; t++) {
393
                    var tab = tabs[t];
394
                    API.browserAction.setBadgeText({
395
                        text: '🔑',
396
                        tabId: tab.id
397
                    });
398
                    API.browserAction.setBadgeBackgroundColor({
399
                        color: '#ff0000',
400
                        tabId: tab.id
401
                    });
402
                    API.browserAction.setTitle({
403
                        title: 'Passman - Locked',
404
                        tabId: tab.id
405
                    });
406
                }
407
            });
408
        }
409
    }
410
411
    function updateTabsIcon() {
412
        API.tabs.query({}).then(function (tabs) {
413
            for (var t = 0; t < tabs.length; t++) {
414
                var tab = tabs[t];
415
                createIconForTab(tab);
416
            }
417
        });
418
    }
419
420
421
    API.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
422
        if(master_password){
423
            createIconForTab(tab);
424
        } else {
425
            displayLogoutIcons();
426
        }
427
    });
428
429
    API.tabs.onActivated.addListener(function () {
430
        API.tabs.query({active: true, currentWindow: true}).then(function (tabs) {
431
            if(master_password){
432
                createIconForTab(tabs[0]);
433
            } else {
434
                displayLogoutIcons();
435
            }
436
        });
437
    });
438
439
    displayLogoutIcons();
440
441
    storage.get('master_password').then(function (password) {
442
        if (password) {
443
            master_password = password;
444
            API.api.browserAction.setBadgeBackgroundColor({
445
                color: defaultColor
446
            });
447
        }
448
        getSettings();
449
    }).error(function (error) {
450
        if (error === "Data not found") {
451
            getSettings();
452
        }
453
    });
454
    return _window;
455
}());
456
457