1
|
|
|
/* global API */ |
2
|
|
|
|
3
|
|
|
var background = (function () { |
4
|
|
|
var storage = new API.Storage(); |
5
|
|
|
var _self = this; |
6
|
|
|
var _window = {}; |
7
|
|
|
|
8
|
|
|
|
9
|
|
|
API.runtime.onConnect.addListener(function (port) { |
10
|
|
|
|
11
|
|
|
port.onMessage.addListener(function (msg) { |
12
|
|
|
if (msg === 'credential_amount') { |
13
|
|
|
port.postMessage('credential_amount:' + local_credentials.length); |
14
|
|
|
} |
15
|
|
|
|
16
|
|
|
}); |
17
|
|
|
|
18
|
|
|
}); |
19
|
|
|
|
20
|
|
|
API.runtime.onInstalled.addListener(function () { |
21
|
|
|
storage.get('settings').error(function () { |
22
|
|
|
var prot = (typeof browser !== 'undefined') ? 'moz-extension' : 'chrome-extension'; |
|
|
|
|
23
|
|
|
var url = prot + '://' + API.runtime.id + '/html/browser_action/browser_action.html'; |
24
|
|
|
API.tabs.create({url: url}); |
25
|
|
|
}); |
26
|
|
|
}); |
27
|
|
|
|
28
|
|
|
var master_password = null; |
29
|
|
|
|
30
|
|
|
function getMasterPasswordSet() { |
31
|
|
|
return (master_password !== null); |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
_self.getMasterPasswordSet = getMasterPasswordSet; |
35
|
|
|
|
36
|
|
|
function setMasterPassword(opts) { |
37
|
|
|
master_password = opts.password; |
38
|
|
|
if (opts.hasOwnProperty('savePassword') && opts.savePassword === true) { |
39
|
|
|
// Save the password in plain text on user request. |
40
|
|
|
// No secure local storage is available :/ |
41
|
|
|
storage.set('master_password', opts.password); |
42
|
|
|
} else { |
43
|
|
|
storage.set('master_password', null); |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
if (opts.password) { |
47
|
|
|
getSettings(); |
48
|
|
|
} else { |
49
|
|
|
displayLogoutIcons(); |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
_self.setMasterPassword = setMasterPassword; |
55
|
|
|
|
56
|
|
|
|
57
|
|
|
var testMasterPasswordAgainst; |
58
|
|
|
|
59
|
|
|
function isMasterPasswordValid(password) { |
60
|
|
|
try { |
61
|
|
|
PAPI.decryptString(testMasterPasswordAgainst, password); |
62
|
|
|
return true; |
63
|
|
|
} catch (e) { |
64
|
|
|
return false; |
65
|
|
|
} |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
_self.isMasterPasswordValid = isMasterPasswordValid; |
69
|
|
|
|
70
|
|
|
|
71
|
|
|
var local_credentials = []; |
72
|
|
|
var local_vault = []; |
|
|
|
|
73
|
|
|
var encryptedFieldSettings = ['accounts']; |
74
|
|
|
_self.settings = {}; |
75
|
|
|
_self.ticker = null; |
76
|
|
|
_self.running = false; |
77
|
|
|
function getSettings() { |
78
|
|
|
|
79
|
|
|
storage.get('settings').then(function (_settings) { |
80
|
|
|
if ((!_settings || Object.keys(_settings).length === 0 || !_settings.hasOwnProperty('accounts')) && !master_password) { |
81
|
|
|
return; |
82
|
|
|
} |
83
|
|
|
if (!master_password && _settings.hasOwnProperty('accounts') && _settings.accounts.length > 0) { |
84
|
|
|
_self.settings.isInstalled = 1; |
85
|
|
|
testMasterPasswordAgainst = _settings.accounts; |
86
|
|
|
return; |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
for (var i = 0; i < encryptedFieldSettings.length; i++) { |
90
|
|
|
var field = encryptedFieldSettings[i]; |
91
|
|
|
_settings[field] = JSON.parse(PAPI.decryptString(_settings[field], master_password)); |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
_self.settings = _settings; |
95
|
|
|
|
96
|
|
|
if (!_self.settings.hasOwnProperty('ignored_sites')) { |
97
|
|
|
_self.settings.ignored_sites = []; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
if (!_self.settings.hasOwnProperty('no_results_found_tab')) { |
101
|
|
|
_self.settings.no_results_found_tab = 'list'; |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
if (!_self.settings.hasOwnProperty('enablePasswordPicker')) { |
105
|
|
|
_self.settings.enablePasswordPicker = !_self.settings.disablePasswordPicker; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
if (!_self.settings.hasOwnProperty('enableAutoFill')) { |
109
|
|
|
_self.settings.enableAutoFill = !_self.settings.disableAutoFill; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
if (!_self.settings.hasOwnProperty('enableUpdateUrl')) { |
113
|
|
|
_self.settings.enableUpdateUrl = true; |
114
|
|
|
} |
115
|
|
|
if (!_self.settings.hasOwnProperty('passwordPickerGotoList')) { |
116
|
|
|
_self.settings.passwordPickerGotoList = false; |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
getCredentials(); |
120
|
|
|
|
121
|
|
|
if (_self.running) { |
122
|
|
|
clearInterval(_self.ticker); |
123
|
|
|
} |
124
|
|
|
_self.running = true; |
125
|
|
|
_self.ticker = setInterval(function () { |
126
|
|
|
|
127
|
|
|
}, _self.settings.refreshTime * 1000); |
128
|
|
|
|
129
|
|
|
}); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
_self.getSettings = getSettings; |
133
|
|
|
|
134
|
|
|
function getRuntimeSettings() { |
135
|
|
|
return _self.settings; |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
_self.getRuntimeSettings = getRuntimeSettings; |
139
|
|
|
|
140
|
|
|
function getSetting(name) { |
141
|
|
|
return _self.settings[name]; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
_self.getSetting = getSetting; |
145
|
|
|
|
146
|
|
|
function saveSettings(settings, cb) { |
|
|
|
|
147
|
|
|
for (var i = 0; i < encryptedFieldSettings.length; i++) { |
148
|
|
|
var field = encryptedFieldSettings[i]; |
149
|
|
|
settings[field] = PAPI.encryptString(JSON.stringify(settings[field]), master_password); |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
if (!settings.hasOwnProperty('ignored_sites')) { |
153
|
|
|
settings.ignored_sites = []; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
if (!_self.settings.hasOwnProperty('password_picker_first_tab')) { |
157
|
|
|
_self.settings.disable_browser_autofill = 'list'; |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
//window.settings contains the run-time settings |
161
|
|
|
_self.settings = settings; |
162
|
|
|
|
163
|
|
|
|
164
|
|
|
storage.set('settings', settings).then(function () { |
165
|
|
|
getSettings(); |
166
|
|
|
}); |
167
|
|
|
|
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
_self.saveSettings = saveSettings; |
171
|
|
|
|
172
|
|
|
function resetSettings() { |
173
|
|
|
storage.set('settings', {}); |
174
|
|
|
_self.settings = {}; |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
_self.resetSettings = resetSettings; |
178
|
|
|
|
179
|
|
|
|
180
|
|
|
function getCredentials() { |
181
|
|
|
if (!master_password) { |
182
|
|
|
return; |
183
|
|
|
} |
184
|
|
|
//console.log('Loading vault with the following settings: ', settings); |
185
|
|
|
var tmpList = []; |
186
|
|
|
|
187
|
|
|
for (var i = 0; i < _self.settings.accounts.length; i++) { |
188
|
|
|
var account = _self.settings.accounts[i]; |
189
|
|
|
/* jshint ignore:start */ |
190
|
|
|
(function (inner_account) { |
191
|
|
|
PAPI.getVault(inner_account, function (vault) { |
192
|
|
|
if (vault.hasOwnProperty('error')) { |
193
|
|
|
return; |
194
|
|
|
} |
195
|
|
|
var _credentials = vault.credentials; |
196
|
|
|
for (var i = 0; i < _credentials.length; i++) { |
197
|
|
|
var key = inner_account.vault_password; |
198
|
|
|
var credential = _credentials[i]; |
199
|
|
|
if (credential.hidden === 1) { |
200
|
|
|
continue; |
201
|
|
|
} |
202
|
|
|
var usedKey = key; |
203
|
|
|
//Shared credentials are not implemented yet |
204
|
|
|
if (credential.hasOwnProperty('shared_key') && credential.shared_key) { |
205
|
|
|
usedKey = PAPI.decryptString(credential.shared_key, key); |
206
|
|
|
|
207
|
|
|
} |
208
|
|
|
credential = PAPI.decryptCredential(credential, usedKey); |
209
|
|
|
credential.account = inner_account; |
210
|
|
|
if (credential.delete_time === 0) { |
211
|
|
|
tmpList.push(credential); |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
} |
215
|
|
|
delete vault.credentials; |
216
|
|
|
local_vault = vault; |
|
|
|
|
217
|
|
|
local_credentials = tmpList; |
218
|
|
|
|
219
|
|
|
getSharedCredentials(inner_account); |
220
|
|
|
|
221
|
|
|
|
222
|
|
|
}); |
223
|
|
|
}(account)); |
224
|
|
|
/* jshint ignore:end */ |
225
|
|
|
} |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
_self.getCredentials = getCredentials; |
229
|
|
|
|
230
|
|
|
function getSharedCredentials(account) { |
231
|
|
|
PAPI.getCredendialsSharedWithUs(account, account.vault.guid, function (credentials) { |
232
|
|
|
for (var i = 0; i < credentials.length; i++) { |
233
|
|
|
var _shared_credential = credentials[i]; |
234
|
|
|
var _shared_credential_data; |
235
|
|
|
var sharedKey = PAPI.decryptString(_shared_credential.shared_key, account.vault_password); |
236
|
|
|
try { |
237
|
|
|
_shared_credential_data = PAPI.decryptSharedCredential(_shared_credential.credential_data, sharedKey); |
238
|
|
|
} catch (e) { |
|
|
|
|
239
|
|
|
|
240
|
|
|
} |
241
|
|
|
if (_shared_credential_data) { |
242
|
|
|
delete _shared_credential.credential_data; |
243
|
|
|
_shared_credential_data.acl = _shared_credential; |
244
|
|
|
_shared_credential_data.acl.permissions = new SharingACL(_shared_credential_data.acl.permissions); |
|
|
|
|
245
|
|
|
_shared_credential_data.tags_raw = _shared_credential_data.tags; |
246
|
|
|
_shared_credential_data.account = account; |
247
|
|
|
local_credentials.push(_shared_credential_data); |
248
|
|
|
} |
249
|
|
|
} |
250
|
|
|
updateTabsIcon(); |
251
|
|
|
}); |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
function getCredentialsByUrl(_url, sender) { |
|
|
|
|
255
|
|
|
if (!master_password) { |
256
|
|
|
return []; |
257
|
|
|
} |
258
|
|
|
if (!_url || _url === '') { |
259
|
|
|
return []; |
260
|
|
|
} |
261
|
|
|
if (Array.isArray(_url)) { |
262
|
|
|
_url = _url.pop(); |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
var p = document.createElement('a'); |
266
|
|
|
p.href = _url; |
267
|
|
|
if (p.pathname) { |
268
|
|
|
//_url = _url.substring(0, _url.lastIndexOf("/")); |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
var url = processURL(_url, _self.settings.ignoreProtocol, _self.settings.ignoreSubdomain, _self.settings.ignorePath, _self.settings.ignorePort); |
272
|
|
|
var found_list = []; |
273
|
|
|
for (var i = 0; i < local_credentials.length; i++) { |
274
|
|
|
var credential_url = local_credentials[i].url; |
275
|
|
|
if (!/^(ht)tps?:\/\//i.test(credential_url) && credential_url !== '' && _url) { |
276
|
|
|
try { |
277
|
|
|
var protocol = _url.split('://').shift(); |
278
|
|
|
credential_url = protocol + "://" + credential_url; |
279
|
|
|
} catch (e) { |
280
|
|
|
//ignore |
281
|
|
|
} |
282
|
|
|
} |
283
|
|
|
credential_url = processURL(credential_url, _self.settings.ignoreProtocol, _self.settings.ignoreSubdomain, _self.settings.ignorePath, _self.settings.ignorePort); |
284
|
|
|
if (credential_url) { |
285
|
|
|
if (credential_url.split("\n").indexOf(url) !== -1) { |
286
|
|
|
found_list.push(local_credentials[i]); |
287
|
|
|
} |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
} |
291
|
|
|
return found_list; |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
_self.getCredentialsByUrl = getCredentialsByUrl; |
295
|
|
|
|
296
|
|
|
|
297
|
|
|
function saveCredential(credential) { |
298
|
|
|
//@TODO save shared password |
299
|
|
|
if (!credential.credential_id) { |
300
|
|
|
PAPI.createCredential(credential.account, credential, credential.account.vault_password, function (createdCredential) { |
301
|
|
|
local_credentials.push(createdCredential); |
302
|
|
|
}); |
303
|
|
|
} else { |
304
|
|
|
var credential_index; |
305
|
|
|
for (var i = 0; i < local_credentials.length; i++) { |
306
|
|
|
if (local_credentials[i].guid === credential.guid) { |
307
|
|
|
credential_index = i; |
308
|
|
|
break; |
309
|
|
|
} |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
if (credential.hasOwnProperty('acl')) { |
313
|
|
|
var permissons = new SharingACL(credential.acl.permissions.permission); |
|
|
|
|
314
|
|
|
if (!permissons.hasPermission(0x02)) { |
315
|
|
|
return; |
316
|
|
|
} |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
PAPI.updateCredential(credential.account, credential, credential.account.vault_password, function (updatedCredential) { |
320
|
|
|
if (credential_index) { |
321
|
|
|
local_credentials[credential_index] = updatedCredential; |
322
|
|
|
} |
323
|
|
|
}); |
324
|
|
|
} |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
_self.saveCredential = saveCredential; |
328
|
|
|
|
329
|
|
|
function getCredentialByGuid(guid) { |
330
|
|
|
for (var i = 0; i < local_credentials.length; i++) { |
331
|
|
|
var credential = local_credentials[i]; |
332
|
|
|
if (credential.guid === guid) { |
333
|
|
|
return credential; |
334
|
|
|
} |
335
|
|
|
} |
|
|
|
|
336
|
|
|
} |
337
|
|
|
|
338
|
|
|
_self.getCredentialByGuid = getCredentialByGuid; |
339
|
|
|
|
340
|
|
|
function getCredentialForHTTPAuth(req) { |
341
|
|
|
return getCredentialsByUrl(req.url)[0]; |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
_window.getCredentialForHTTPAuth = getCredentialForHTTPAuth; |
345
|
|
|
|
346
|
|
|
var mined_data = []; |
347
|
|
|
|
348
|
|
|
function minedForm(data, sender) { |
349
|
|
|
var url = sender.url; |
350
|
|
|
var existingLogins = getCredentialsByUrl(sender.url); |
351
|
|
|
var title = API.i18n.getMessage('detected_new_login') + ':'; |
352
|
|
|
var minedMatchingID = null; |
353
|
|
|
for (var j = 0; j < existingLogins.length; j++) { |
354
|
|
|
var login = existingLogins[j]; |
355
|
|
|
if (login.username === data.username) { |
356
|
|
|
if (login.password !== data.password) { |
357
|
|
|
minedMatchingID = login.guid; |
358
|
|
|
title = API.i18n.getMessage('detected_changed_login') + ':'; |
359
|
|
|
} |
360
|
|
|
else { |
361
|
|
|
//console.log('No changes detected'); |
362
|
|
|
delete mined_data[sender.tab.id]; |
363
|
|
|
return; |
364
|
|
|
} |
365
|
|
|
} |
366
|
|
|
} |
367
|
|
|
mined_data[sender.tab.id] = { |
368
|
|
|
title: title, |
369
|
|
|
url: url, |
370
|
|
|
username: data.username, |
371
|
|
|
password: data.password, |
372
|
|
|
label: sender.title, |
373
|
|
|
guid: minedMatchingID |
374
|
|
|
}; |
375
|
|
|
|
376
|
|
|
//console.log('Done mining, ', mined_data, sender.tab.id); |
377
|
|
|
} |
378
|
|
|
|
379
|
|
|
_self.minedForm = minedForm; |
380
|
|
|
|
381
|
|
|
function getMinedData(args, sender) { |
382
|
|
|
//console.log('Fecthing mined data for tab id', sender.tab.id) |
383
|
|
|
var senderUrl = sender.tab.url; |
384
|
|
|
var site = processURL(senderUrl, _self.settings.ignoreProtocol, _self.settings.ignoreSubdomain, _self.settings.ignorePath, _self.settings.ignorePort); |
385
|
|
|
if (!_self.settings) { |
386
|
|
|
return null; |
387
|
|
|
} |
388
|
|
|
if (!_self.settings.hasOwnProperty('ignored_sites')) { |
389
|
|
|
return mined_data[sender.tab.id]; |
390
|
|
|
} |
391
|
|
|
var matches = _self.settings.ignored_sites.filter(function (item) { |
392
|
|
|
return typeof item === 'string' && site.indexOf(item) > -1; |
393
|
|
|
}); |
394
|
|
|
|
395
|
|
|
if (matches.length !== 0) { |
396
|
|
|
return null; |
397
|
|
|
} |
398
|
|
|
return mined_data[sender.tab.id]; |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
_self.getMinedData = getMinedData; |
402
|
|
|
|
403
|
|
|
function clearMined(args, sender) { |
404
|
|
|
delete mined_data[sender.tab.id]; |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
_self.clearMined = clearMined; |
408
|
|
|
|
409
|
|
|
function saveMinedCallback(args) { |
410
|
|
|
createIconForTab(args.sender.tab); |
411
|
|
|
API.tabs.query({active: true, currentWindow: true}).then(function (tabs) { |
412
|
|
|
API.tabs.sendMessage(args.sender.tab.id, {method: "minedLoginSaved", args: args}).then(function (response) { |
|
|
|
|
413
|
|
|
}); |
414
|
|
|
}); |
415
|
|
|
} |
416
|
|
|
|
417
|
|
|
function ignoreSite(_url) { |
418
|
|
|
if (!_self.settings.hasOwnProperty('ignored_sites')) { |
419
|
|
|
_self.settings.ignored_sites = []; |
420
|
|
|
} |
421
|
|
|
var site = processURL(_url, false, false, true, false); |
422
|
|
|
if (_self.settings.ignored_sites.indexOf(site) === -1) { |
423
|
|
|
_self.settings.ignored_sites.push(site); |
424
|
|
|
saveSettings(_self.settings); |
425
|
|
|
} |
426
|
|
|
clearMined(); |
427
|
|
|
} |
428
|
|
|
|
429
|
|
|
_self.ignoreSite = ignoreSite; |
430
|
|
|
|
431
|
|
|
function ignoreURL(url) { |
432
|
|
|
if (!_self.settings.hasOwnProperty('ignored_sites')) { |
433
|
|
|
_self.settings.ignored_sites = []; |
434
|
|
|
} |
435
|
|
|
if (_self.settings.ignored_sites.indexOf(url) === -1) { |
436
|
|
|
_self.settings.ignored_sites.push(url); |
437
|
|
|
saveSettings(_self.settings); |
438
|
|
|
} |
439
|
|
|
} |
440
|
|
|
|
441
|
|
|
_self.ignoreURL = ignoreURL; |
442
|
|
|
|
443
|
|
|
function passToParent(args, sender) { |
444
|
|
|
API.tabs.sendMessage(sender.tab.id, {method: args.injectMethod, args: args.args}).then(function (response) { |
|
|
|
|
445
|
|
|
}); |
446
|
|
|
} |
447
|
|
|
|
448
|
|
|
_self.passToParent = passToParent; |
449
|
|
|
|
450
|
|
|
function getActiveTab(opt) { |
451
|
|
|
API.tabs.query({active: true, currentWindow: true}).then(function (tabs) { |
452
|
|
|
var tab = tabs[0]; |
453
|
|
|
API.tabs.sendMessage(tab.id, {method: opt.returnFn, args: tab}).then(function (response) { |
|
|
|
|
454
|
|
|
}); |
455
|
|
|
}); |
456
|
|
|
} |
457
|
|
|
|
458
|
|
|
_self.getActiveTab = getActiveTab; |
459
|
|
|
|
460
|
|
|
function updateCredentialUrlDoorhanger(login) { |
461
|
|
|
if(!_self.settings.enableUpdateUrl){ |
462
|
|
|
return; |
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
API.tabs.query({active: true, currentWindow: true}).then(function (tabs) { |
466
|
|
|
var tab = tabs[0]; |
467
|
|
|
var data = login; |
468
|
|
|
data.url = tab.url; |
469
|
|
|
data.title = API.i18n.getMessage('detected_changed_url') + ':'; |
470
|
|
|
API.tabs.sendMessage(tab.id, { |
471
|
|
|
method: 'showUrlUpdateDoorhanger', |
472
|
|
|
args: {data: data} |
473
|
|
|
}); |
474
|
|
|
}); |
475
|
|
|
} |
476
|
|
|
|
477
|
|
|
_self.updateCredentialUrlDoorhanger = updateCredentialUrlDoorhanger; |
478
|
|
|
|
479
|
|
|
function updateCredentialUrl(data, sender) { |
480
|
|
|
mined_data[sender.tab.id] = data; |
481
|
|
|
saveMined({}, sender); |
482
|
|
|
|
483
|
|
|
} |
484
|
|
|
|
485
|
|
|
_self.updateCredentialUrl = updateCredentialUrl; |
486
|
|
|
|
487
|
|
|
function saveMined(args, sender) { |
488
|
|
|
var data = mined_data[sender.tab.id]; |
489
|
|
|
var credential = {}, |
490
|
|
|
credential_index; |
491
|
|
|
|
492
|
|
|
if (data.guid === null) { |
493
|
|
|
credential = PAPI.newCredential(); |
494
|
|
|
} else { |
495
|
|
|
for (var i = 0; i < local_credentials.length; i++) { |
496
|
|
|
if (local_credentials[i].guid === data.guid) { |
497
|
|
|
credential = local_credentials[i]; |
498
|
|
|
credential_index = i; |
499
|
|
|
break; |
500
|
|
|
} |
501
|
|
|
} |
502
|
|
|
} |
503
|
|
|
if (!credential.hasOwnProperty('account')) { |
504
|
|
|
credential.account = args.account; |
505
|
|
|
} |
506
|
|
|
credential.username = data.username; |
507
|
|
|
credential.password = data.password; |
508
|
|
|
credential.url = sender.tab.url; |
509
|
|
|
if (credential.guid !== null) { |
510
|
|
|
PAPI.updateCredential(credential.account, credential, credential.account.vault_password, function (updatedCredential) { |
511
|
|
|
updatedCredential.account = credential.account; |
512
|
|
|
if (credential_index) { |
513
|
|
|
local_credentials[credential_index] = updatedCredential; |
514
|
|
|
} |
515
|
|
|
saveMinedCallback({credential: credential, updated: true, sender: sender}); |
516
|
|
|
delete mined_data[sender.tab.id]; |
517
|
|
|
}); |
518
|
|
|
} else { |
519
|
|
|
credential.label = sender.tab.title; |
520
|
|
|
credential.vault_id = credential.account.vault.vault_id; |
521
|
|
|
PAPI.createCredential(credential.account, credential, credential.account.vault_password, function (createdCredential) { |
522
|
|
|
createdCredential.account = args.account; |
523
|
|
|
saveMinedCallback({credential: credential, updated: false, sender: sender}); |
524
|
|
|
local_credentials.push(createdCredential); |
525
|
|
|
delete mined_data[sender.tab.id]; |
526
|
|
|
}); |
527
|
|
|
} |
528
|
|
|
} |
529
|
|
|
|
530
|
|
|
_self.saveMined = saveMined; |
531
|
|
|
|
532
|
|
|
function searchCredential(searchText) { |
533
|
|
|
searchText = searchText.toLowerCase(); |
534
|
|
|
var searchFields = ['label', 'username', 'email', 'url', 'description']; |
535
|
|
|
var results = []; |
536
|
|
|
for (var i = 0; i < local_credentials.length; i++) { |
537
|
|
|
var credential = local_credentials[i]; |
538
|
|
|
for (var f = 0; f < searchFields.length; f++) { |
539
|
|
|
var field = searchFields[f]; |
540
|
|
|
if (!credential[field]) { |
541
|
|
|
continue; |
542
|
|
|
} |
543
|
|
|
|
544
|
|
|
var field_value = credential[field].toLowerCase(); |
545
|
|
|
if (field_value.indexOf(searchText) !== -1) { |
546
|
|
|
results.push(credential); |
547
|
|
|
break; |
548
|
|
|
} |
549
|
|
|
} |
550
|
|
|
} |
551
|
|
|
return results; |
552
|
|
|
} |
553
|
|
|
|
554
|
|
|
_self.searchCredential = searchCredential; |
555
|
|
|
|
556
|
|
|
|
557
|
|
|
function injectCreateCredential(args, sender) { |
558
|
|
|
var account = getRuntimeSettings().accounts[parseInt(args.vaultIndex)]; |
559
|
|
|
var credential = PAPI.newCredential(); |
560
|
|
|
credential.label = args.label; |
561
|
|
|
credential.username = args.username; |
562
|
|
|
credential.password = args.password; |
563
|
|
|
credential.url = sender.tab.url; |
564
|
|
|
credential.vault_id = account.vault.vault_id; |
565
|
|
|
PAPI.createCredential(account, credential, account.vault_password, function (createdCredential) { |
566
|
|
|
credential.account = account; |
567
|
|
|
saveMinedCallback({credential: credential, updated: false, sender: sender, selfAdded: true}); |
568
|
|
|
local_credentials.push(createdCredential); |
569
|
|
|
|
570
|
|
|
}); |
571
|
|
|
} |
572
|
|
|
|
573
|
|
|
self.injectCreateCredential = injectCreateCredential; |
|
|
|
|
574
|
|
|
|
575
|
|
|
function isVaultKeySet() { |
576
|
|
|
return (_self.settings.vault_password !== null); |
577
|
|
|
} |
578
|
|
|
|
579
|
|
|
_self.isVaultKeySet = isVaultKeySet; |
580
|
|
|
|
581
|
|
|
function isAutoFillEnabled() { |
582
|
|
|
if (!_self.settings.hasOwnProperty('enableAutoFill')) { |
583
|
|
|
return true; |
584
|
|
|
} |
585
|
|
|
return _self.settings.enableAutoFill; |
586
|
|
|
} |
587
|
|
|
|
588
|
|
|
_self.isAutoFillEnabled = isAutoFillEnabled; |
589
|
|
|
|
590
|
|
|
function isAutoSubmitEnabled() { |
591
|
|
|
if (!_self.settings.hasOwnProperty('enableAutoSubmit')) { |
592
|
|
|
return false; |
593
|
|
|
} |
594
|
|
|
return _self.settings.enableAutoSubmit; |
595
|
|
|
} |
596
|
|
|
|
597
|
|
|
_self.isAutoSubmitEnabled = isAutoSubmitEnabled; |
598
|
|
|
|
599
|
|
|
var doorhangerData = null; |
600
|
|
|
|
601
|
|
|
function setDoorhangerData(data) { |
602
|
|
|
doorhangerData = data; |
603
|
|
|
} |
604
|
|
|
|
605
|
|
|
_self.setDoorhangerData = setDoorhangerData; |
606
|
|
|
|
607
|
|
|
function getDoorhangerData() { |
608
|
|
|
return doorhangerData; |
609
|
|
|
} |
610
|
|
|
|
611
|
|
|
_self.getDoorhangerData = getDoorhangerData; |
612
|
|
|
|
613
|
|
|
function closeSetupTab() { |
614
|
|
|
API.tabs.query({url: 'chrome-extension://' + API.runtime.id + '/html/browser_action/browser_action.html'}).then(function (tabs) { |
615
|
|
|
if (tabs && tabs[0]) { |
616
|
|
|
API.tabs.remove(tabs[0].id); |
617
|
|
|
} |
618
|
|
|
}); |
619
|
|
|
} |
620
|
|
|
|
621
|
|
|
_self.closeSetupTab = closeSetupTab; |
622
|
|
|
|
623
|
|
|
API.runtime.onMessage.addListener(function (msg, sender, sendResponse) { |
624
|
|
|
|
625
|
|
|
if (!msg || !msg.hasOwnProperty('method')) { |
626
|
|
|
return; |
627
|
|
|
} |
628
|
|
|
var result = false; |
629
|
|
|
if (_self[msg.method]) { |
630
|
|
|
result = _self[msg.method](msg.args, sender); |
631
|
|
|
} else { |
632
|
|
|
console.warn('[NOT FOUND] Method call', msg.method, 'args: ', msg.args); |
633
|
|
|
} |
634
|
|
|
|
635
|
|
|
sendResponse(result); |
636
|
|
|
}); |
637
|
|
|
|
638
|
|
|
var defaultColor = '#0082c9'; |
639
|
|
|
|
640
|
|
|
function createIconForTab(tab) { |
641
|
|
|
if (!master_password) { |
642
|
|
|
return; |
643
|
|
|
} |
644
|
|
|
var tabUrl = tab.url; |
645
|
|
|
var logins = getCredentialsByUrl(tabUrl); |
646
|
|
|
if (tab.active) { |
647
|
|
|
window.contextMenu.setContextItems(logins); |
648
|
|
|
} |
649
|
|
|
var credentialAmount = logins.length; |
650
|
|
|
API.browserAction.setBadgeText({ |
651
|
|
|
text: credentialAmount.toString(), |
652
|
|
|
tabId: tab.id |
653
|
|
|
}); |
654
|
|
|
API.browserAction.setBadgeBackgroundColor({ |
655
|
|
|
color: defaultColor, |
656
|
|
|
tabId: tab.id |
657
|
|
|
}); |
658
|
|
|
|
659
|
|
|
var plural = (credentialAmount === 1) ? API.i18n.getMessage('credential') : API.i18n.getMessage('credentials'); |
660
|
|
|
API.browserAction.setTitle({ |
661
|
|
|
title: API.i18n.getMessage('browser_action_title_login', [credentialAmount.toString(), plural.toString()]), |
662
|
|
|
tabId: tab.id |
663
|
|
|
}); |
664
|
|
|
} |
665
|
|
|
|
666
|
|
|
function displayLogoutIcons() { |
667
|
|
|
if (_self.settings) { |
668
|
|
|
API.tabs.query({}).then(function (tabs) { |
669
|
|
|
for (var t = 0; t < tabs.length; t++) { |
670
|
|
|
var tab = tabs[t]; |
671
|
|
|
API.browserAction.setBadgeText({ |
672
|
|
|
text: '🔑', |
673
|
|
|
tabId: tab.id |
674
|
|
|
}); |
675
|
|
|
API.browserAction.setBadgeBackgroundColor({ |
676
|
|
|
color: '#ff0000', |
677
|
|
|
tabId: tab.id |
678
|
|
|
}); |
679
|
|
|
API.browserAction.setTitle({ |
680
|
|
|
title: API.i18n.getMessage('browser_action_title_locked'), |
681
|
|
|
tabId: tab.id |
682
|
|
|
}); |
683
|
|
|
} |
684
|
|
|
}); |
685
|
|
|
} |
686
|
|
|
} |
687
|
|
|
|
688
|
|
|
function updateTabsIcon() { |
689
|
|
|
API.tabs.query({}).then(function (tabs) { |
690
|
|
|
for (var t = 0; t < tabs.length; t++) { |
691
|
|
|
var tab = tabs[t]; |
692
|
|
|
createIconForTab(tab); |
693
|
|
|
} |
694
|
|
|
}); |
695
|
|
|
} |
696
|
|
|
|
697
|
|
|
|
698
|
|
|
API.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) { |
699
|
|
|
if (master_password) { |
700
|
|
|
createIconForTab(tab); |
701
|
|
|
} else { |
702
|
|
|
displayLogoutIcons(); |
703
|
|
|
} |
704
|
|
|
}); |
705
|
|
|
|
706
|
|
|
API.tabs.onActivated.addListener(function () { |
707
|
|
|
API.tabs.query({active: true, currentWindow: true}).then(function (tabs) { |
708
|
|
|
if (master_password) { |
709
|
|
|
createIconForTab(tabs[0]); |
710
|
|
|
} else { |
711
|
|
|
displayLogoutIcons(); |
712
|
|
|
} |
713
|
|
|
}); |
714
|
|
|
}); |
715
|
|
|
|
716
|
|
|
displayLogoutIcons(); |
717
|
|
|
|
718
|
|
|
|
719
|
|
|
storage.get('master_password').then(function (password) { |
720
|
|
|
if (password) { |
721
|
|
|
master_password = password; |
722
|
|
|
API.api.browserAction.setBadgeBackgroundColor({ |
723
|
|
|
color: defaultColor |
724
|
|
|
}); |
725
|
|
|
} |
726
|
|
|
getSettings(); |
727
|
|
|
}).error(function (error) { |
728
|
|
|
if (error === "Data not found") { |
729
|
|
|
getSettings(); |
730
|
|
|
} |
731
|
|
|
}); |
732
|
|
|
return _window; |
733
|
|
|
}()); |
734
|
|
|
|
735
|
|
|
|
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.