Completed
Push — master ( f66285...6c7ad9 )
by Sander
17s
created

background.js ➔ ignoreURL   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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