Completed
Push — master ( bba01d...8c82ac )
by Sander
01:20
created

background.js ➔ createIconForTab   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 24
rs 8.6845
1
/* global API */
2
3
(function () {
4
    var storage = new API.Storage();
5
    var _self = this;
6
    API.runtime.onConnect.addListener(function (port) {
7
8
        port.onMessage.addListener(function (msg) {
9
10
            if (msg === 'credential_amount') {
11
                port.postMessage('credential_amount:' + local_credentials.length);
12
            }
13
            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...
14
15
            }
16
17
        });
18
19
    });
20
21
    var master_password = null;
22
23
    function getMasterPasswordSet() {
24
        return (master_password !== null);
25
    }
26
27
    _self.getMasterPasswordSet = getMasterPasswordSet;
28
29
    function setMasterPassword(opts) {
30
        master_password = opts.password;
31
        if (opts.hasOwnProperty('savePassword') && opts.savePassword === true) {
32
            // Save the password in plain text on user request.
33
            // No secure local storage is available :/
34
            storage.set('master_password', opts.password);
35
        } else {
36
            storage.set('master_password', null);
37
        }
38
39
        if (opts.password) {
40
            getSettings();
41
        } else {
42
            displayLogoutIcons();
43
        }
44
45
    }
46
47
    _self.setMasterPassword = setMasterPassword;
48
49
50
    var testMasterPasswordAgainst;
51
52
    function isMasterPasswordValid(password) {
53
        //return true;
54
        try {
55
            PAPI.decryptString(testMasterPasswordAgainst, password);
0 ignored issues
show
Bug introduced by
The variable PAPI seems to be never declared. If this is a global, consider adding a /** global: PAPI */ 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...
56
            return true;
57
        } catch (e) {
58
            return false;
59
        }
60
    }
61
62
    _self.isMasterPasswordValid = isMasterPasswordValid;
63
64
65
    var local_credentials = [];
66
    var local_vault = [];
67
    var encryptedFieldSettings = ['default_vault', 'nextcloud_host', 'nextcloud_username', 'nextcloud_password', 'vault_password'];
68
    _self.settings = {};
69
    _self.ticker = null;
70
    _self.running = false;
71
    function getSettings() {
72
73
        storage.get('settings').then(function (_settings) {
74
75
            if (!_settings || !_settings.hasOwnProperty('nextcloud_host')) {
76
                return;
77
            }
78
79
            if (!master_password && _settings.hasOwnProperty('nextcloud_username') && _settings.hasOwnProperty('vault_password')) {
80
                _self.settings.isInstalled = 1;
81
                testMasterPasswordAgainst = _settings.nextcloud_username;
82
                return;
83
            }
84
85
            for (var i = 0; i < encryptedFieldSettings.length; i++) {
86
                var field = encryptedFieldSettings[i];
87
                _settings[field] = JSON.parse(PAPI.decryptString(_settings[field], master_password));
0 ignored issues
show
Bug introduced by
The variable PAPI seems to be never declared. If this is a global, consider adding a /** global: PAPI */ 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...
88
            }
89
90
91
            _self.settings = _settings;
92
93
94
            PAPI.host = _settings.nextcloud_host;
95
            PAPI.username = _settings.nextcloud_username;
96
            PAPI.password = _settings.nextcloud_password;
97
            if (!_settings.vault_password) {
98
                return;
99
            }
100
            if (PAPI.credentialsSet()) {
101
                getCredentials();
102
                if (_self.running) {
103
                    clearInterval(_self.ticker);
104
                }
105
106
                _self.running = true;
107
                _self.ticker = setInterval(function () {
108
                    getCredentials();
109
                }, _self.settings.refreshTime * 1000);
110
            } else {
111
                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...
112
            }
113
        });
114
    }
115
116
    _self.getSettings = getSettings;
117
118
    function getRuntimeSettings() {
119
        return _self.settings;
120
    }
121
122
    _self.getRuntimeSettings = getRuntimeSettings;
123
124
    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...
125
        for (var i = 0; i < encryptedFieldSettings.length; i++) {
126
            var field = encryptedFieldSettings[i];
127
            settings[field] = PAPI.encryptString(JSON.stringify(settings[field]), master_password);
0 ignored issues
show
Bug introduced by
The variable PAPI seems to be never declared. If this is a global, consider adding a /** global: PAPI */ 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...
128
        }
129
        PAPI.host = settings.nextcloud_host;
130
        PAPI.username = settings.nextcloud_username;
131
        PAPI.password = settings.nextcloud_password;
132
        //window.settings contains the run-time settings
133
        _self.settings = settings;
134
135
136
        storage.set('settings', settings).then(function () {
137
            getSettings();
138
        });
139
140
    }
141
142
    _self.saveSettings = saveSettings;
143
144
145
    function getCredentials() {
146
        //console.log('Loading vault with the following settings: ', settings);
147
        var tmpList = [];
148
        PAPI.getVault(_self.settings.default_vault.guid, function (vault) {
0 ignored issues
show
Bug introduced by
The variable PAPI seems to be never declared. If this is a global, consider adding a /** global: PAPI */ 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...
149
            if(vault.hasOwnProperty('error')){
150
                return;
151
            }
152
            var _credentials = vault.credentials;
153
            for (var i = 0; i < _credentials.length; i++) {
154
                var key = _self.settings.vault_password;
155
                var credential = _credentials[i];
156
                if (credential.hidden === 1) {
157
                    continue;
158
                }
159
                var usedKey = key;
160
                //Shared credentials are not implemented yet
161
                if (credential.hasOwnProperty('shared_key') && credential.shared_key) {
162
                    usedKey = PAPI.decryptString(credential.shared_key, key);
0 ignored issues
show
Bug introduced by
The variable PAPI seems to be never declared. If this is a global, consider adding a /** global: PAPI */ 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...
163
164
                }
165
                credential = PAPI.decryptCredential(credential, usedKey);
166
                tmpList.push(credential);
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
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
    var mined_data = [];
197
198
    function minedForm(data, sender) {
199
        var url = sender.url;
200
        var existingLogins = getCredentialsByUrl(sender.url);
201
        var title = "Detected new login:";
202
        var minedMatchingID = null;
203
        for (var j = 0; j < existingLogins.length; j++) {
204
            var login = existingLogins[j];
205
            if (login.username === data.username) {
206
                if (login.password !== data.password) {
207
                    minedMatchingID = login.guid;
208
                    title = "Detected changed password for user:";
209
                }
210
                else {
211
                    //console.log('No changes detected');
212
                    delete mined_data[sender.tab.id];
213
                    return;
214
                }
215
            }
216
        }
217
        mined_data[sender.tab.id] = {
218
            title: title,
219
            url: url,
220
            username: data.username,
221
            password: data.password,
222
            label: sender.title,
223
            guid: minedMatchingID
224
        };
225
226
        //console.log('Done mining, ', mined_data, sender.tab.id);
227
    }
228
229
    _self.minedForm = minedForm;
230
231
    function getMinedData(args, sender) {
232
        //console.log('Fecthing  mined data for tab id', sender.tab.id)
233
        return mined_data[sender.tab.id];
234
    }
235
236
    _self.getMinedData = getMinedData;
237
238
    function clearMined(args, sender) {
239
        delete mined_data[sender.tab.id];
240
    }
241
242
    _self.clearMined = clearMined;
243
244
    function saveMinedCallback(args) {
245
        createIconForTab(args.sender.tab);
246
        API.tabs.query({active: true, currentWindow: true}).then(function (tabs) {
247
            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...
248
            });
249
        });
250
    }
251
252
    function saveMined(args, sender) {
253
        var data = mined_data[sender.tab.id];
254
        var credential,
255
            credential_index;
256
257
        if (data.guid === null) {
258
            credential = PAPI.newCredential();
0 ignored issues
show
Bug introduced by
The variable PAPI seems to be never declared. If this is a global, consider adding a /** global: PAPI */ 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...
259
        } else {
260
            for (var i = 0; i < local_credentials.length; i++) {
261
                if (local_credentials[i].guid === data.guid) {
262
                    credential = local_credentials[i];
263
                    credential_index = i;
264
                    return;
265
                }
266
            }
267
        }
268
        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...
269
        credential.password = data.password;
270
        credential.url = sender.tab.url;
271
        if (credential.guid !== null) {
272
            PAPI.updateCredential(credential, _self.settings.vault_password, function (updatedCredential) {
273
                local_credentials[credential_index] = updatedCredential;
274
                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...
275
                delete mined_data[sender.tab.id];
276
            });
277
        } else {
278
            credential.label = sender.tab.title;
279
            credential.vault_id = local_vault.vault_id;
280
            PAPI.createCredential(credential, _self.settings.vault_password, function (createdCredential) {
0 ignored issues
show
Bug introduced by
The variable PAPI seems to be never declared. If this is a global, consider adding a /** global: PAPI */ 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...
281
                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...
282
                local_credentials.push(createdCredential);
283
                delete mined_data[sender.tab.id];
284
            });
285
        }
286
    }
287
288
    _self.saveMined = saveMined;
289
290
291
    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...
292
        var credential = PAPI.newCredential();
0 ignored issues
show
Bug introduced by
The variable PAPI seems to be never declared. If this is a global, consider adding a /** global: PAPI */ 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...
293
        credential.label = args.label;
294
        credential.username = args.username;
295
        credential.password = args.username;
296
        credential.vault_id = local_vault.vault_id;
297
        credential.url = sender.tab.url;
298
        PAPI.createCredential(credential, _self.settings.vault_password, function (createdCredential) {
299
            saveMinedCallback({credential: credential, updated: false, sender: sender, selfAdded: true});
300
            local_credentials.push(createdCredential);
301
302
        });
303
    }
304
305
    function isVaultKeySet() {
306
        return (_self.settings.vault_password !== null);
307
    }
308
309
    _self.isVaultKeySet = isVaultKeySet;
310
311
    function isAutoFillEnabled() {
312
        if(!_self.settings.hasOwnProperty('disableAutoFill')){
313
            return true;
314
        }
315
        return (_self.settings.disableAutoFill === false);
316
    }
317
318
    _self.isAutoFillEnabled = isAutoFillEnabled;
319
320
    API.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
321
        //console.log('Method call', msg.method);
322
323
        if (!msg || !msg.hasOwnProperty('method')) {
324
            return;
325
        }
326
327
        var result = _self[msg.method](msg.args, sender);
328
329
        sendResponse(result);
330
    });
331
332
    var defaultColor = '#0082c9';
333
    function createIconForTab(tab) {
334
        if (!master_password) {
335
            return;
336
        }
337
        var tabUrl = tab.url;
338
        var logins = getCredentialsByUrl(tabUrl);
339
        if(tab.active) {
340
            window.contextMenu.setContextItems(logins);
341
        }
342
        var credentialAmount = logins.length;
343
            API.browserAction.setBadgeText({
344
            text: credentialAmount.toString(),
345
            tabId: tab.id
346
        });
347
        API.browserAction.setBadgeBackgroundColor({
348
            color: defaultColor,
349
            tabId: tab.id
350
        });
351
        var plural = (credentialAmount == 1) ? 'credential' : 'credentials';
352
        API.browserAction.setTitle({
353
            title: 'Passman - ' + credentialAmount.toString() + ' '+ plural +' found for this page',
354
            tabId: tab.id
355
        });
356
    }
357
358
    function displayLogoutIcons() {
359
        if(_self.settings) {
360
            API.tabs.query({}).then(function (tabs) {
361
                for (var t = 0; t < tabs.length; t++) {
362
                    var tab = tabs[t];
363
                    API.browserAction.setBadgeText({
364
                        text: '🔑',
365
                        tabId: tab.id
366
                    });
367
                    API.browserAction.setBadgeBackgroundColor({
368
                        color: '#ff0000',
369
                        tabId: tab.id
370
                    });
371
                    API.browserAction.setTitle({
372
                        title: 'Passman - Locked',
373
                        tabId: tab.id
374
                    })
375
                }
376
            })
377
        }
378
    }
379
380
    function updateTabsIcon() {
381
        API.tabs.query({}).then(function (tabs) {
382
            for (var t = 0; t < tabs.length; t++) {
383
                var tab = tabs[t];
384
                createIconForTab(tab);
385
            }
386
        })
387
    }
388
389
390
    API.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
391
        if(master_password){
392
            createIconForTab(tab)
393
        } else {
394
            displayLogoutIcons();
395
        }
396
    });
397
398
    API.tabs.onActivated.addListener(function () {
399
        API.tabs.query({active: true, currentWindow: true}).then(function (tabs) {
400
            if(master_password){
401
                createIconForTab(tabs[0])
402
            } else {
403
                displayLogoutIcons();
404
            }
405
        });
406
    });
407
408
    displayLogoutIcons();
409
410
    storage.get('master_password').then(function (password) {
411
        if (password) {
412
            master_password = password;
413
            API.api.browserAction.setBadgeBackgroundColor({
414
                color: defaultColor
415
            });
416
        }
417
        getSettings();
418
    }).error(function (error) {
419
        if (error === "Data not found") {
420
            getSettings();
421
        }
422
    })
423
424
}());
425
426