Completed
Push — master ( 4e8691...51d7d6 )
by Sander
55s
created

background.js ➔ resetSettings   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
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
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
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
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
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
        var url = processURL(_url, _self.settings.ignoreProtocol, _self.settings.ignoreSubdomain, _self.settings.ignorePath, _self.settings.ignorePort);
247
        var found_list = [];
248
        for (var i = 0; i < local_credentials.length; i++) {
249
            var credential_url = local_credentials[i].url;
250
            if (!/^(ht)tps?:\/\//i.test(credential_url) && credential_url !== '' && _url) {
251
                try {
252
                    var protocol = _url.split('://').shift();
253
                    credential_url = protocol + "://" + credential_url;
254
                } catch (e){
255
                    //ignore
256
                }
257
            }
258
            credential_url = processURL(credential_url, _self.settings.ignoreProtocol, _self.settings.ignoreSubdomain, _self.settings.ignorePath, _self.settings.ignorePort);
259
            if (credential_url) {
260
                if (credential_url.indexOf(url) !== -1) {
261
                    found_list.push(local_credentials[i]);
262
                }
263
            }
264
265
        }
266
        return found_list;
267
    }
268
269
    _self.getCredentialsByUrl = getCredentialsByUrl;
270
271
272
    function saveCredential(credential) {
273
        //@TODO save shared password
274
        if (!credential.credential_id) {
275
            PAPI.createCredential(credential.account, credential, credential.account.vault_password, function (createdCredential) {
276
                local_credentials.push(createdCredential);
277
            });
278
        } else {
279
            var credential_index;
280
            for (var i = 0; i < local_credentials.length; i++) {
281
                if (local_credentials[i].guid === credential.guid) {
282
                    credential_index = i;
283
                    break;
284
                }
285
            }
286
287
            if (credential.hasOwnProperty('acl')) {
288
                var permissons = new SharingACL(credential.acl.permissions.permission);
0 ignored issues
show
Bug introduced by
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...
289
                if (!permissons.hasPermission(0x02)) {
290
                    return;
291
                }
292
            }
293
294
            PAPI.updateCredential(credential.account, credential, credential.account.vault_password, function (updatedCredential) {
295
                if (credential_index) {
296
                    local_credentials[credential_index] = updatedCredential;
297
                }
298
            });
299
        }
300
    }
301
302
    _self.saveCredential = saveCredential;
303
304
    function getCredentialByGuid(guid) {
305
        for (var i = 0; i < local_credentials.length; i++) {
306
            var credential = local_credentials[i];
307
            if (credential.guid === guid) {
308
                return credential;
309
            }
310
        }
0 ignored issues
show
Best Practice introduced by
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...
311
    }
312
313
    _self.getCredentialByGuid = getCredentialByGuid;
314
315
    function getCredentialForHTTPAuth(req) {
316
        return getCredentialsByUrl(req.url)[0];
317
    }
318
319
    _window.getCredentialForHTTPAuth = getCredentialForHTTPAuth;
320
321
    var mined_data = [];
322
323
    function minedForm(data, sender) {
324
        var url = sender.url;
325
        var existingLogins = getCredentialsByUrl(sender.url);
326
        var title = API.i18n.getMessage('detected_new_login') + ':';
327
        var minedMatchingID = null;
328
        for (var j = 0; j < existingLogins.length; j++) {
329
            var login = existingLogins[j];
330
            if (login.username === data.username) {
331
                if (login.password !== data.password) {
332
                    minedMatchingID = login.guid;
333
                    title = API.i18n.getMessage('detected_changed_login') + ':';
334
                }
335
                else {
336
                    //console.log('No changes detected');
337
                    delete mined_data[sender.tab.id];
338
                    return;
339
                }
340
            }
341
        }
342
        mined_data[sender.tab.id] = {
343
            title: title,
344
            url: url,
345
            username: data.username,
346
            password: data.password,
347
            label: sender.title,
348
            guid: minedMatchingID
349
        };
350
351
        //console.log('Done mining, ', mined_data, sender.tab.id);
352
    }
353
354
    _self.minedForm = minedForm;
355
356
    function getMinedData(args, sender) {
357
        //console.log('Fecthing  mined data for tab id', sender.tab.id)
358
        var senderUrl = sender.tab.url;
359
        var site = processURL(senderUrl, _self.settings.ignoreProtocol, _self.settings.ignoreSubdomain, _self.settings.ignorePath, _self.settings.ignorePort);
360
        if (!_self.settings) {
361
            return null;
362
        }
363
        if (!_self.settings.hasOwnProperty('ignored_sites')) {
364
            return mined_data[sender.tab.id];
365
        }
366
        var matches = _self.settings.ignored_sites.filter(function (item) {
367
            return typeof item === 'string' && site.indexOf(item) > -1;
368
        });
369
370
        if (matches.length !== 0) {
371
            return null;
372
        }
373
        return mined_data[sender.tab.id];
374
    }
375
376
    _self.getMinedData = getMinedData;
377
378
    function clearMined(args, sender) {
379
        delete mined_data[sender.tab.id];
380
    }
381
382
    _self.clearMined = clearMined;
383
384
    function saveMinedCallback(args) {
385
        createIconForTab(args.sender.tab);
386
        API.tabs.query({active: true, currentWindow: true}).then(function (tabs) {
387
            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...
388
            });
389
        });
390
    }
391
392
    function ignoreSite(_url) {
393
        if (!_self.settings.hasOwnProperty('ignored_sites')) {
394
            _self.settings.ignored_sites = [];
395
        }
396
        var site = processURL(_url, _self.settings.ignoreProtocol, _self.settings.ignoreSubdomain, _self.settings.ignorePath, _self.settings.ignorePort);
397
        if (_self.settings.ignored_sites.indexOf(site) === -1) {
398
            _self.settings.ignored_sites.push(site);
399
            saveSettings(_self.settings);
400
        }
401
    }
402
403
    _self.ignoreSite = ignoreSite;
404
405
    function passToParent(args, sender) {
406
        API.tabs.sendMessage(sender.tab.id, {method: args.injectMethod, args: args.args}).then(function (response) {
0 ignored issues
show
Unused Code introduced by
The parameter response is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
407
        });
408
    }
409
410
    _self.passToParent = passToParent;
411
412
    function getActiveTab(opt) {
413
        API.tabs.query({active: true, currentWindow: true}).then(function (tabs) {
414
            var tab = tabs[0];
415
            API.tabs.sendMessage(tab.id, {method: opt.returnFn, args: tab}).then(function (response) {
0 ignored issues
show
Unused Code introduced by
The parameter response is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
416
            });
417
        });
418
    }
419
420
    _self.getActiveTab = getActiveTab;
421
422
    function updateCredentialUrlDoorhanger(login) {
423
        API.tabs.query({active: true, currentWindow: true}).then(function (tabs) {
424
            var tab = tabs[0];
425
            var data = login;
426
            data.url = tab.url;
427
            data.title = API.i18n.getMessage('detected_changed_url') + ':';
428
            API.tabs.sendMessage(tab.id, {
429
                method: 'showUrlUpdateDoorhanger',
430
                args: {data: data}
431
            });
432
        });
433
    }
434
435
    _self.updateCredentialUrlDoorhanger = updateCredentialUrlDoorhanger;
436
437
    function updateCredentialUrl(data, sender) {
438
        mined_data[sender.tab.id] = data;
439
        saveMined({}, sender);
440
441
    }
442
443
    _self.updateCredentialUrl = updateCredentialUrl;
444
445
    function saveMined(args, sender) {
446
        var data = mined_data[sender.tab.id];
447
        var credential = {},
448
            credential_index;
449
450
        if (data.guid === null) {
451
            credential = PAPI.newCredential();
452
        } else {
453
            for (var i = 0; i < local_credentials.length; i++) {
454
                if (local_credentials[i].guid === data.guid) {
455
                    credential = local_credentials[i];
456
                    credential_index = i;
457
                    break;
458
                }
459
            }
460
        }
461
        if (!credential.hasOwnProperty('account')) {
462
            credential.account = args.account;
463
        }
464
        credential.username = data.username;
465
        credential.password = data.password;
466
        credential.url = sender.tab.url;
467
        if (credential.guid !== null) {
468
            PAPI.updateCredential(credential.account, credential, credential.account.vault_password, function (updatedCredential) {
469
                updatedCredential.account = credential.account;
470
                if (credential_index) {
471
                    local_credentials[credential_index] = updatedCredential;
472
                }
473
                saveMinedCallback({credential: credential, updated: true, sender: sender});
474
                delete mined_data[sender.tab.id];
475
            });
476
        } else {
477
            credential.label = sender.tab.title;
478
            credential.vault_id =  credential.account.vault.vault_id;
479
            PAPI.createCredential(credential.account, credential, credential.account.vault_password, function (createdCredential) {
480
                createdCredential.account = credential.account;
481
                saveMinedCallback({credential: credential, updated: false, sender: sender});
482
                local_credentials.push(createdCredential);
483
                delete mined_data[sender.tab.id];
484
            });
485
        }
486
    }
487
488
    _self.saveMined = saveMined;
489
490
    function searchCredential(searchText) {
491
        searchText = searchText.toLowerCase();
492
        var searchFields = ['label', 'username', 'email', 'url', 'description'];
493
        var results = [];
494
        for (var i = 0; i < local_credentials.length; i++) {
495
            var credential = local_credentials[i];
496
            for (var f = 0; f < searchFields.length; f++) {
497
                var field = searchFields[f];
498
                if (!credential[field]) {
499
                    continue;
500
                }
501
502
                var field_value = credential[field].toLowerCase();
503
                if (field_value.indexOf(searchText) !== -1) {
504
                    results.push(credential);
505
                    break;
506
                }
507
            }
508
        }
509
        return results;
510
    }
511
512
    _self.searchCredential = searchCredential;
513
514
515
    function injectCreateCredential(args, sender) {
516
        var account = getRuntimeSettings().accounts[args.vaultIndex];
517
        var credential = PAPI.newCredential();
518
        credential.label = args.label;
519
        credential.username = args.username;
520
        credential.password = args.password;
521
        credential.vault_id = local_vault.vault_id;
522
        credential.url = sender.tab.url;
523
        PAPI.createCredential(account, credential, account.vault_password, function (createdCredential) {
524
            saveMinedCallback({credential: credential, updated: false, sender: sender, selfAdded: true});
525
            local_credentials.push(createdCredential);
526
527
        });
528
    }
529
530
    self.injectCreateCredential = injectCreateCredential;
0 ignored issues
show
Bug introduced by
The variable self seems to be never declared. If this is a global, consider adding a /** global: self */ comment.

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

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

Loading history...
531
532
    function isVaultKeySet() {
533
        return (_self.settings.vault_password !== null);
534
    }
535
536
    _self.isVaultKeySet = isVaultKeySet;
537
538
    function isAutoFillEnabled() {
539
        if (!_self.settings.hasOwnProperty('enableAutoFill')) {
540
            return true;
541
        }
542
        return _self.settings.enableAutoFill;
543
    }
544
545
    _self.isAutoFillEnabled = isAutoFillEnabled;
546
547
    function isAutoSubmitEnabled() {
548
        if (!_self.settings.hasOwnProperty('enableAutoSubmit')) {
549
            return false;
550
        }
551
        return _self.settings.enableAutoSubmit;
552
    }
553
554
    _self.isAutoSubmitEnabled = isAutoSubmitEnabled;
555
556
    var doorhangerData = null;
557
558
    function setDoorhangerData(data) {
559
        doorhangerData = data;
560
    }
561
562
    _self.setDoorhangerData = setDoorhangerData;
563
564
    function getDoorhangerData() {
565
        return doorhangerData;
566
    }
567
568
    _self.getDoorhangerData = getDoorhangerData;
569
570
    function closeSetupTab() {
571
        API.tabs.query({url: 'chrome-extension://' + API.runtime.id + '/html/browser_action/browser_action.html'}).then(function (tabs) {
572
            if (tabs && tabs[0]) {
573
                API.tabs.remove(tabs[0].id);
574
            }
575
        });
576
    }
577
578
    _self.closeSetupTab = closeSetupTab;
579
580
    API.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
581
582
        if (!msg || !msg.hasOwnProperty('method')) {
583
            return;
584
        }
585
        var result = false;
586
        if (_self[msg.method]) {
587
            result = _self[msg.method](msg.args, sender);
588
        } else {
589
            console.warn('[NOT FOUND] Method call', msg.method, 'args: ', msg.args);
590
        }
591
592
        sendResponse(result);
593
    });
594
595
    var defaultColor = '#0082c9';
596
597
    function createIconForTab(tab) {
598
        if (!master_password) {
599
            return;
600
        }
601
        var tabUrl = tab.url;
602
        var logins = getCredentialsByUrl(tabUrl);
603
        if (tab.active) {
604
            window.contextMenu.setContextItems(logins);
605
        }
606
        var credentialAmount = logins.length;
607
        API.browserAction.setBadgeText({
608
            text: credentialAmount.toString(),
609
            tabId: tab.id
610
        });
611
        API.browserAction.setBadgeBackgroundColor({
612
            color: defaultColor,
613
            tabId: tab.id
614
        });
615
616
        var plural = (credentialAmount === 1) ? API.i18n.getMessage('credential') : API.i18n.getMessage('credentials');
617
        API.browserAction.setTitle({
618
            title: API.i18n.getMessage('browser_action_title_login', [credentialAmount.toString(), plural.toString()]),
619
            tabId: tab.id
620
        });
621
    }
622
623
    function displayLogoutIcons() {
624
        if (_self.settings) {
625
            API.tabs.query({}).then(function (tabs) {
626
                for (var t = 0; t < tabs.length; t++) {
627
                    var tab = tabs[t];
628
                    API.browserAction.setBadgeText({
629
                        text: '🔑',
630
                        tabId: tab.id
631
                    });
632
                    API.browserAction.setBadgeBackgroundColor({
633
                        color: '#ff0000',
634
                        tabId: tab.id
635
                    });
636
                    API.browserAction.setTitle({
637
                        title: API.i18n.getMessage('browser_action_title_locked'),
638
                        tabId: tab.id
639
                    });
640
                }
641
            });
642
        }
643
    }
644
645
    function updateTabsIcon() {
646
        API.tabs.query({}).then(function (tabs) {
647
            for (var t = 0; t < tabs.length; t++) {
648
                var tab = tabs[t];
649
                createIconForTab(tab);
650
            }
651
        });
652
    }
653
654
655
    API.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
656
        if (master_password) {
657
            createIconForTab(tab);
658
        } else {
659
            displayLogoutIcons();
660
        }
661
    });
662
663
    API.tabs.onActivated.addListener(function () {
664
        API.tabs.query({active: true, currentWindow: true}).then(function (tabs) {
665
            if (master_password) {
666
                createIconForTab(tabs[0]);
667
            } else {
668
                displayLogoutIcons();
669
            }
670
        });
671
    });
672
673
    displayLogoutIcons();
674
675
676
    storage.get('master_password').then(function (password) {
677
        if (password) {
678
            master_password = password;
679
            API.api.browserAction.setBadgeBackgroundColor({
680
                color: defaultColor
681
            });
682
        }
683
        getSettings();
684
    }).error(function (error) {
685
        if (error === "Data not found") {
686
            getSettings();
687
        }
688
    });
689
    return _window;
690
}());
691
692