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