diff --git a/CHANGELOG b/CHANGELOG index fa98f6f..c5d27b6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +0.3.8 (??-??-2017) +========================= +- Use browser.local.storage instead of localStorage +- Switched some functions to promise + 0.3.7 (22-10-2017) ========================= - Improved credentials check (does not use protocol requests for polling) diff --git a/keepassxc-browser/background/browserAction.js b/keepassxc-browser/background/browserAction.js index 3a67a12..34547a5 100644 --- a/keepassxc-browser/background/browserAction.js +++ b/keepassxc-browser/background/browserAction.js @@ -70,7 +70,7 @@ browserAction.showDefault = function(callback, tab) { iconType: 'normal', popup: 'popup.html' }; - keepass.isConfigured((response) => { + keepass.isConfigured().then((response) => { if (!response || keepass.isDatabaseClosed || !keepass.isKeePassXCAvailable || page.tabs[tab.id].errorMessage) { stackData.iconType = 'cross'; } diff --git a/keepassxc-browser/background/event.js b/keepassxc-browser/background/event.js index 2b0a440..bf9b5d2 100644 --- a/keepassxc-browser/background/event.js +++ b/keepassxc-browser/background/event.js @@ -100,32 +100,37 @@ kpxcEvent.showStatus = function(configured, tab, callback) { }; kpxcEvent.onLoadSettings = function(callback, tab) { - page.settings = (typeof(localStorage.settings) === 'undefined') ? {} : JSON.parse(localStorage.settings); + browser.storage.local.get({'settings': {}}).then((item) => { + callback(item.settings); + }, (err) => { + console.log('error loading settings: ' + err); + }); }; kpxcEvent.onLoadKeyRing = function(callback, tab) { - keepass.keyRing = (typeof(localStorage.keyRing) === 'undefined') ? {} : JSON.parse(localStorage.keyRing); - if (keepass.isAssociated() && !keepass.keyRing[keepass.associated.hash]) { - keepass.associated = { - value: false, - hash: null - }; - } -}; - -kpxcEvent.onGetSettings = function(callback, tab) { - kpxcEvent.onLoadSettings(); - callback({ data: page.settings }); + browser.storage.local.get({'keyRing': {}}).then(function(item) { + keepass.keyRing = item.keyRing; + if (keepass.isAssociated() && !keepass.keyRing[keepass.associated.hash]) { + keepass.associated = { + "value": false, + "hash": null + }; + } + callback(item.keyRing); + }, (err) => { + console.log('error loading keyRing: ' + err); + }); }; kpxcEvent.onSaveSettings = function(callback, tab, settings) { - localStorage.settings = JSON.stringify(settings); - kpxcEvent.onLoadSettings(); + browser.storage.local.set({'settings': settings}).then(function() { + kpxcEvent.onLoadSettings(); + }); }; kpxcEvent.onGetStatus = function(callback, tab) { keepass.testAssociation((response) => { - keepass.isConfigured((configured) => { + keepass.isConfigured().then((configured) => { kpxcEvent.showStatus(configured, tab, callback); }); }, tab, true); @@ -137,13 +142,13 @@ kpxcEvent.onReconnect = function(callback, tab) { // Add a small timeout after reconnecting. Just to make sure. It's not pretty, I know :( setTimeout(() => { keepass.generateNewKeyPair(); - keepass.changePublicKeys(tab, (pkRes) => { + keepass.changePublicKeys(tab).then((pkRes) => { keepass.getDatabaseHash((gdRes) => { if (gdRes) { keepass.testAssociation((response) => { - keepass.isConfigured((configured) => { + keepass.isConfigured().then((configured) => { kpxcEvent.showStatus(configured, tab, callback); - }); + }).catch((e) => {console.log(e);}); }, tab); } }, null); @@ -152,9 +157,9 @@ kpxcEvent.onReconnect = function(callback, tab) { }; kpxcEvent.lockDatabase = function(callback, tab) { - keepass.lockDatabase((response) => { + keepass.lockDatabase(tab).then((response => { kpxcEvent.showStatus(true, tab, callback); - }, tab); + })); }; kpxcEvent.onPopStack = function(callback, tab) { @@ -175,12 +180,13 @@ kpxcEvent.onGetConnectedDatabase = function(callback, tab) { }; kpxcEvent.onGetKeePassXCVersions = function(callback, tab) { - if (keepass.currentKeePassXC.version === 0) { - keepass.getDatabaseHash((response) => { - callback({current: keepass.currentKeePassXC.version, latest: keepass.latestKeePassXC.version}); + if(keepass.currentKeePassXC.version == 0) { + keepass.getDatabaseHash((res) => { + callback({"current": keepass.currentKeePassXC.version, "latest": keepass.currentKeePassXC.version}); }, tab); - } - callback({current: keepass.currentKeePassXC.version, latest: keepass.latestKeePassXC.version}); + } else { + callback({"current": keepass.currentKeePassXC.version, "latest": keepass.currentKeePassXC.version}); +} }; kpxcEvent.onCheckUpdateKeePassXC = function(callback, tab) { @@ -254,7 +260,6 @@ kpxcEvent.messageHandlers = { 'check_update_keepassxc': kpxcEvent.onCheckUpdateKeePassXC, 'get_connected_database': kpxcEvent.onGetConnectedDatabase, 'get_keepassxc_versions': kpxcEvent.onGetKeePassXCVersions, - 'get_settings': kpxcEvent.onGetSettings, 'get_status': kpxcEvent.onGetStatus, 'get_tab_information': kpxcEvent.onGetTabInformation, 'load_keyring': kpxcEvent.onLoadKeyRing, diff --git a/keepassxc-browser/background/init.js b/keepassxc-browser/background/init.js index 6bc33c1..127f4d6 100644 --- a/keepassxc-browser/background/init.js +++ b/keepassxc-browser/background/init.js @@ -1,13 +1,15 @@ -keepass.convertKeyToKeyRing(); -page.initSettings(); -page.initOpenedTabs(); -keepass.connectToNative(); -keepass.generateNewKeyPair(); -keepass.changePublicKeys(null, (pkRes) => { - keepass.getDatabaseHash((gdRes) => {}, null); +keepass.migrateKeyRing().then(() => { + page.initSettings().then(() => { + page.initOpenedTabs().then(() => { + keepass.connectToNative(); + keepass.generateNewKeyPair(); + keepass.changePublicKeys(null, keepass.messageTimeout).then((pkRes) => { + keepass.getDatabaseHash((gdRes) => {}, null); + }); + }); + }); }); - // Milliseconds for intervall (e.g. to update browserAction) let _interval = 250; diff --git a/keepassxc-browser/background/keepass.js b/keepassxc-browser/background/keepass.js index 39be7cb..0134883 100644 --- a/keepassxc-browser/background/keepass.js +++ b/keepassxc-browser/background/keepass.js @@ -11,7 +11,6 @@ keepass.isDatabaseClosed = false; keepass.isKeePassXCAvailable = false; keepass.isEncryptionKeyUnrecognized = false; keepass.currentKeePassXC = {'version': 0, 'versionParsed': 0}; -keepass.latestKeePassXC = (typeof(localStorage.latestKeePassXC) === 'undefined') ? {'version': 0, 'versionParsed': 0, 'lastChecked': null} : JSON.parse(localStorage.latestKeePassXC); keepass.requiredKeePassXC = 220; keepass.nativeHostName = 'com.varjolintu.keepassxc_browser'; keepass.nativePort = null; @@ -19,7 +18,6 @@ keepass.keySize = 24; keepass.latestVersionUrl = 'https://api.github.com/repos/keepassxreboot/keepassxc/releases/latest'; keepass.cacheTimeout = 30 * 1000; // milliseconds keepass.databaseHash = 'no-hash'; //no-hash = KeePassXC is too old and does not return a hash value -keepass.keyRing = (typeof(localStorage.keyRing) === 'undefined') ? {} : JSON.parse(localStorage.keyRing); keepass.keyId = 'keepassxc-browser-cryptokey-name'; keepass.keyBody = 'keepassxc-browser-key'; keepass.messageTimeout = 500; // milliseconds @@ -77,6 +75,55 @@ const kpErrors = { } }; +browser.storage.local.get({ + 'latestKeePassXC': {'version': 0, 'versionParsed': 0, 'lastChecked': null}, + 'keyRing': {}}).then((item) => { + keepass.latestKeePassXC = item.latestKeePassXC; + keepass.keyRing = item.keyRing; +}); + +keepass.sendNativeMessage = function(request, enableTimeout = false) { + return new Promise((resolve, reject) => { + let timeout; + let action = request.action; + let ev = keepass.nativePort.onMessage; + + let listener = ((port, action) => { + let handler = (msg) => { + if (msg && msg.action === action) { + port.removeListener(handler); + if (enableTimeout) { + clearTimeout(timeout); + } + resolve(msg); + } + }; + return handler; + })(ev, action); + ev.addListener(listener); + + + // Handle timeouts + if (enableTimeout) { + timeout = setTimeout(() => { + const errorMessage = { + action: action, + error: kpErrors.getError(kpErrors.TIMEOUT_OR_NOT_CONNECTED), + errorCode: kpErrors.TIMEOUT_OR_NOT_CONNECTED + }; + keepass.isKeePassXCAvailable = false; + ev.removeListener(listener.handler); + resolve(errorMessage); + }, keepass.messageTimeout); + } + + // Send the request + if (keepass.nativePort) { + keepass.nativePort.postMessage(request); + } + }); +}; + keepass.addCredentials = function(callback, tab, username, password, url) { keepass.updateCredentials(callback, tab, null, username, password, url); }; @@ -116,9 +163,8 @@ keepass.updateCredentials = function(callback, tab, entryId, username, password, nonce: keepass.b64e(nonce), clientID: keepass.clientID }; - console.log(request); - keepass.callbackOnId(keepass.nativePort.onMessage, kpAction, tab, (response) => { + keepass.sendNativeMessage(request).then((response) => { if (response.message && response.nonce) { const res = keepass.decrypt(response.message, response.nonce); if (res) { @@ -134,7 +180,6 @@ keepass.updateCredentials = function(callback, tab, entryId, username, password, browserAction.showDefault(null, tab); } }); - keepass.nativePort.postMessage(request); }); }; @@ -180,7 +225,7 @@ keepass.retrieveCredentials = function(callback, tab, url, submiturl, forceCallb clientID: keepass.clientID }; - keepass.callbackOnId(keepass.nativePort.onMessage, kpAction, tab, (response) => { + keepass.sendNativeMessage(request).then((response) => { if (response.message && response.nonce) { const res = keepass.decrypt(response.message, response.nonce); if (res) { @@ -210,42 +255,9 @@ keepass.retrieveCredentials = function(callback, tab, url, submiturl, forceCallb browserAction.showDefault(null, tab); } }); - keepass.nativePort.postMessage(request); }, tab); }; -// Redirects the callback to a listener (handleReply()) -keepass.callbackOnId = function(ev, action, tab, callback, enableTimeout = false) { - let timeout; - let listener = ((port, action) => { - let handler = (msg) => { - if (msg && msg.action === action) { - ev.removeListener(handler); - if (enableTimeout) { - clearTimeout(timeout); - } - callback(msg); - } - }; - return handler; - })(ev, action, tab, callback); - ev.addListener(listener); - - // Handle timeouts - if (enableTimeout) { - timeout = setTimeout(() => { - const errorMessage = { - action: action, - error: kpErrors.getError(5), - errorCode: 5 - }; - keepass.isKeePassXCAvailable = false; - callback(errorMessage); - ev.removeListener(listener.handler); - }, keepass.messageTimeout); - } -}; - keepass.generatePassword = function(callback, tab, forceCallback) { if (!keepass.isConnected) { callback([]); @@ -277,10 +289,10 @@ keepass.generatePassword = function(callback, tab, forceCallback) { clientID: keepass.clientID }; - keepass.callbackOnId(keepass.nativePort.onMessage, kpAction, tab, (response) => { + keepass.sendNativeMessage(request).then((response) => { if (response.message && response.nonce) { const res = keepass.decrypt(response.message, response.nonce); - if (res) { + if (res) { const message = nacl.util.encodeUTF8(res); const parsed = JSON.parse(message); keepass.setcurrentKeePassXCVersion(parsed.version); @@ -304,7 +316,6 @@ keepass.generatePassword = function(callback, tab, forceCallback) { keepass.handleError(tab, response.errorCode, response.error); } }); - keepass.nativePort.postMessage(request); }, tab); }; @@ -338,7 +349,7 @@ keepass.associate = function(callback, tab) { clientID: keepass.clientID }; - keepass.callbackOnId(keepass.nativePort.onMessage, kpAction, tab, (response) => { + keepass.sendNativeMessage(request).then((response) => { if (response.message && response.nonce) { const res = keepass.decrypt(response.message, response.nonce); if (res) { @@ -363,7 +374,6 @@ keepass.associate = function(callback, tab) { keepass.handleError(tab, response.errorCode, response.error); } }); - keepass.nativePort.postMessage(request); }, tab); }; @@ -421,7 +431,7 @@ keepass.testAssociation = function(callback, tab, enableTimeout = false) { clientID: keepass.clientID }; - keepass.callbackOnId(keepass.nativePort.onMessage, kpAction, tab, (response) => { + keepass.sendNativeMessage(request, enableTimeout).then((response) => { if (response.message && response.nonce) { const res = keepass.decrypt(response.message, response.nonce); if (res) { @@ -453,7 +463,6 @@ keepass.testAssociation = function(callback, tab, enableTimeout = false) { } callback(keepass.isAssociated()); }); - keepass.nativePort.postMessage(request); }, tab, enableTimeout); }; @@ -465,7 +474,7 @@ keepass.getDatabaseHash = function(callback, tab, enableTimeout = false) { } if (!keepass.serverPublicKey) { - keepass.changePublicKeys(tab, null); + keepass.changePublicKeys(tab); } const kpAction = kpActions.GET_DATABASE_HASH; @@ -489,7 +498,7 @@ keepass.getDatabaseHash = function(callback, tab, enableTimeout = false) { clientID: keepass.clientID }; - keepass.callbackOnId(keepass.nativePort.onMessage, kpAction, tab, (response) => { + keepass.sendNativeMessage(request, enableTimeout).then((response) => { if (response.message && response.nonce) { const res = keepass.decrypt(response.message, response.nonce); if (res) { @@ -521,8 +530,8 @@ keepass.getDatabaseHash = function(callback, tab, enableTimeout = false) { else { keepass.databaseHash = 'no-hash'; keepass.isDatabaseClosed = true; - keepass.isKeePassXCAvailable = false; - if (response.message === "") { + if (response.message === '') { + keepass.isKeePassXCAvailable = false; keepass.handleError(tab, kpErrors.TIMEOUT_OR_NOT_CONNECTED); } else { @@ -530,90 +539,90 @@ keepass.getDatabaseHash = function(callback, tab, enableTimeout = false) { } callback(keepass.databaseHash); } - }, enableTimeout); - keepass.nativePort.postMessage(request); -}; - -keepass.changePublicKeys = function(tab, callback) { - if (!keepass.isConnected) { - callback([]); - return; - } - - const kpAction = kpActions.CHANGE_PUBLIC_KEYS; - const key = keepass.b64e(keepass.keyPair.publicKey); - let nonce = nacl.randomBytes(keepass.keySize); - nonce = keepass.b64e(nonce); - keepass.clientID = keepass.b64e(nacl.randomBytes(keepass.keySize)); - - const message = { - action: kpAction, - publicKey: key, - proxyPort: (page.settings.port ? page.settings.port : 19700), - nonce: nonce, - clientID: keepass.clientID - }; - - keepass.callbackOnId(keepass.nativePort.onMessage, kpAction, tab, (response) => { - keepass.setcurrentKeePassXCVersion(response.version); - - if (!keepass.verifyKeyResponse(response, key, nonce)) { - if (tab && page.tabs[tab.id]) { - keepass.handleError(tab, kpErrors.KEY_CHANGE_FAILED); - callback(false); - } - } - else { - keepass.isKeePassXCAvailable = true; - console.log('Server public key: ' + keepass.b64e(keepass.serverPublicKey)); - } - callback(true); }); - keepass.nativePort.postMessage(message); }; -keepass.lockDatabase = function(callback, tab, forceCallback) { - if (!keepass.isConnected) { - keepass.handleError(tab, kpErrors.TIMEOUT_OR_NOT_CONNECTED); - callback([]); - return; - } +keepass.changePublicKeys = function(tab, enableTimeout = false) { + return new Promise((resolve, reject) => { + if (!keepass.isConnected) { + reject(false); + } - const kpAction = kpActions.LOCK_DATABASE; - const nonce = nacl.randomBytes(keepass.keySize); + const kpAction = kpActions.CHANGE_PUBLIC_KEYS; + const key = keepass.b64e(keepass.keyPair.publicKey); + let nonce = nacl.randomBytes(keepass.keySize); + nonce = keepass.b64e(nonce); + keepass.clientID = keepass.b64e(nacl.randomBytes(keepass.keySize)); - const messageData = { - action: kpAction - }; + const request = { + action: kpAction, + publicKey: key, + proxyPort: (page.settings.port ? page.settings.port : 19700), + nonce: nonce, + clientID: keepass.clientID + }; - const request = { - action: kpAction, - message: keepass.encrypt(messageData, nonce), - nonce: keepass.b64e(nonce), - clientID: keepass.clientID - }; + keepass.sendNativeMessage(request, enableTimeout).then((response) => { + keepass.setcurrentKeePassXCVersion(response.version); - keepass.callbackOnId(keepass.nativePort.onMessage, kpAction, tab, (response) => { - if (response.message && response.nonce) { - const res = keepass.decrypt(response.message, response.nonce); - if (res) { - const message = nacl.util.encodeUTF8(res); - const parsed = JSON.parse(message); - keepass.setcurrentKeePassXCVersion(parsed.version); - - if (keepass.verifyResponse(parsed, response.nonce)) { - keepass.isDatabaseClosed = true; - keepass.handleError(tab, kpErrors.DATABASE_NOT_OPENED); - callback(false); + if (!keepass.verifyKeyResponse(response, key, nonce)) { + if (tab && page.tabs[tab.id]) { + keepass.handleError(tab, kpErrors.KEY_CHANGE_FAILED); + reject(false); } } - } - else if (response.error && response.errorCode) { - keepass.handleError(tab, response.errorCode, response.error); - } - callback(false); + else { + keepass.isKeePassXCAvailable = true; + console.log('Server public key: ' + keepass.b64e(keepass.serverPublicKey)); + } + resolve(true); + }); + }); +}; + +keepass.lockDatabase = function(tab) { + return new Promise((resolve, reject) => { + if (!keepass.isConnected) { + keepass.handleError(tab, kpErrors.TIMEOUT_OR_NOT_CONNECTED); + reject(false); + } + + const kpAction = kpActions.LOCK_DATABASE; + const nonce = nacl.randomBytes(keepass.keySize); + + const messageData = { + action: kpAction + }; + + const request = { + action: kpAction, + message: keepass.encrypt(messageData, nonce), + nonce: keepass.b64e(nonce), + clientID: keepass.clientID + }; + + keepass.sendNativeMessage(request).then((response) => { + if (response.message && response.nonce) { + const res = keepass.decrypt(response.message, response.nonce); + if (res) { + const message = nacl.util.encodeUTF8(res); + const parsed = JSON.parse(message); + keepass.setcurrentKeePassXCVersion(parsed.version); + + if (keepass.verifyResponse(parsed, response.nonce)) { + keepass.isDatabaseClosed = true; + keepass.handleError(tab, kpErrors.DATABASE_NOT_OPENED); + resolve(false); + } + } + } + else if (response.error && response.errorCode) { + keepass.isDatabaseClosed = true; + keepass.handleError(tab, response.errorCode, response.error); + } + resolve(false); + }); }); - keepass.nativePort.postMessage(request); }; keepass.generateNewKeyPair = function() { @@ -621,15 +630,16 @@ keepass.generateNewKeyPair = function() { //console.log(keepass.b64e(keepass.keyPair.publicKey) + ' ' + keepass.b64e(keepass.keyPair.secretKey)); }; -keepass.isConfigured = function(callback) { - if (typeof(keepass.databaseHash) === 'undefined') { - keepass.getDatabaseHash((dbHash) => { - callback(keepass.databaseHash in keepass.keyRing); - }, null); - } - else { - callback(keepass.databaseHash in keepass.keyRing); - } +keepass.isConfigured = function() { + return new Promise((resolve, reject) => { + if (typeof(keepass.databaseHash) === 'undefined' || keepass.databaseHash === 'no-hash') { + keepass.getDatabaseHash((hash) => { + resolve(hash in keepass.keyRing); + }); + } else { + resolve(keepass.databaseHash in keepass.keyRing); + } + }); }; keepass.checkDatabaseHash = function(callback, tab) { @@ -640,22 +650,33 @@ keepass.isAssociated = function() { return (keepass.associated.value && keepass.associated.hash && keepass.associated.hash === keepass.databaseHash); }; -keepass.convertKeyToKeyRing = function() { - if (keepass.keyId in localStorage && keepass.keyBody in localStorage && !('keyRing' in localStorage)) { - keepass.getDatabaseHash((hash) => { - keepass.saveKey(hash, localStorage[keepass.keyId], localStorage[keepass.keyBody]); - - if ('keyRing' in localStorage) { - delete localStorage[keepass.keyId]; - delete localStorage[keepass.keyBody]; +keepass.migrateKeyRing = function() { + return new Promise((resolve, reject) => { + browser.storage.local.get('keyRing').then((item) => { + const keyring = item.keyRing; + // Change dates to numbers, for compatibilty with Chromium based browsers + if (keyring) { + let num = 0; + for (let keyHash in keyring) { + let key = keyring[keyHash]; + ['created', 'lastUsed'].forEach((fld) => { + let v = key[fld]; + if (v instanceof Date && v.valueOf() >= 0) { + key[fld] = v.valueOf(); + num++; + } else if (typeof v !== 'number') { + key[fld] = Date.now().valueOf(); + num++; + } + }); + } + if (num > 0) { + browser.storage.local.set({ keyRing: keyring }); + } } - }, null); - } - - if ('keyRing' in localStorage) { - delete localStorage[keepass.keyId]; - delete localStorage[keepass.keyBody]; - } + resolve(); + }); + }); }; keepass.saveKey = function(hash, id, key) { @@ -664,8 +685,8 @@ keepass.saveKey = function(hash, id, key) { id: id, key: key, hash: hash, - created: new Date(), - lastUsed: new Date() + created: new Date().valueOf(), + lastUsed: new Date().valueOf() }; } else { @@ -673,19 +694,19 @@ keepass.saveKey = function(hash, id, key) { keepass.keyRing[hash].key = key; keepass.keyRing[hash].hash = hash; } - localStorage.keyRing = JSON.stringify(keepass.keyRing); + browser.storage.local.set({'keyRing': keepass.keyRing}); }; keepass.updateLastUsed = function(hash) { if ((hash in keepass.keyRing)) { - keepass.keyRing[hash].lastUsed = new Date(); - localStorage.keyRing = JSON.stringify(keepass.keyRing); + keepass.keyRing[hash].lastUsed = new Date().valueOf(); + browser.storage.local.set({'keyRing': keepass.keyRing}); } }; keepass.deleteKey = function(hash) { delete keepass.keyRing[hash]; - localStorage.keyRing = JSON.stringify(keepass.keyRing); + browser.storage.local.set({'keyRing': keepass.keyRing}); }; keepass.setcurrentKeePassXCVersion = function(version) { @@ -699,7 +720,7 @@ keepass.setcurrentKeePassXCVersion = function(version) { keepass.keePassXCUpdateAvailable = function() { if (page.settings.checkUpdateKeePassXC && page.settings.checkUpdateKeePassXC > 0) { - const lastChecked = (keepass.latestKeePassXC.lastChecked) ? new Date(keepass.latestKeePassXC.lastChecked) : new Date('11/21/1986'); + const lastChecked = (keepass.latestKeePassXC.lastChecked) ? new Date(keepass.latestKeePassXC.lastChecked) : new Date(1986, 11, 21); const daysSinceLastCheck = Math.floor(((new Date()).getTime()-lastChecked.getTime())/86400000); if (daysSinceLastCheck >= page.settings.checkUpdateKeePassXC) { keepass.checkForNewKeePassXCVersion(); @@ -724,7 +745,7 @@ keepass.checkForNewKeePassXCVersion = function() { } if (version !== -1) { - localStorage.latestKeePassXC = JSON.stringify(keepass.latestKeePassXC); + browser.storage.local.set({'latestKeePassXC': keepass.latestKeePassXC}); } }; @@ -739,13 +760,14 @@ keepass.checkForNewKeePassXCVersion = function() { catch (ex) { console.log(ex); } - keepass.latestKeePassXC.lastChecked = new Date(); + keepass.latestKeePassXC.lastChecked = new Date().valueOf(); }; keepass.connectToNative = function() { - if (!keepass.isConnected) { - keepass.nativeConnect(); + if (keepass.nativePort) { + keepass.nativePort.disconnect(); } + keepass.nativeConnect(); }; keepass.onNativeMessage = function(response) { @@ -754,7 +776,7 @@ keepass.onNativeMessage = function(response) { // Handle database lock/unlock status if (response.action === kpActions.DATABASE_LOCKED || response.action === kpActions.DATABASE_UNLOCKED) { keepass.testAssociation((response) => { - keepass.isConfigured((configured) => { + keepass.isConfigured().then((configured) => { let data = page.tabs[page.currentTabId].stack[page.tabs[page.currentTabId].stack.length - 1]; data.iconType = configured ? 'normal' : 'cross'; browserAction.show(null, {'id': page.currentTabId}); diff --git a/keepassxc-browser/background/page.js b/keepassxc-browser/background/page.js index d6ee9fc..8e868d3 100644 --- a/keepassxc-browser/background/page.js +++ b/keepassxc-browser/background/page.js @@ -10,50 +10,56 @@ const defaultSettings = { var page = {}; page.tabs = {}; - page.currentTabId = -1; -page.settings = (typeof(localStorage.settings) === 'undefined') ? {} : JSON.parse(localStorage.settings); page.blockedTabs = {}; page.initSettings = function() { - kpxcEvent.onLoadSettings(); - if (!('checkUpdateKeePassXC' in page.settings)) { - page.settings.checkUpdateKeePassXC = defaultSettings.checkUpdateKeePassXC; - } - if (!('autoCompleteUsernames' in page.settings)) { - page.settings.autoCompleteUsernames = defaultSettings.autoCompleteUsernames; - } - if (!('autoFillAndSend' in page.settings)) { - page.settings.autoFillAndSend = defaultSettings.autoFillAndSend; - } - if (!('usePasswordGenerator' in page.settings)) { - page.settings.usePasswordGenerator = defaultSettings.usePasswordGenerator; - } - if (!('autoFillSingleEntry' in page.settings)) { - page.settings.autoFillSingleEntry = defaultSettings.autoFillSingleEntry; - } - if (!('autoRetrieveCredentials' in page.settings)) { - page.settings.autoRetrieveCredentials = defaultSettings.autoRetrieveCredentials; - } - if (!('port' in page.settings)) { - page.settings.port = defaultSettings.proxyPort; - } - localStorage.settings = JSON.stringify(page.settings); + return new Promise((resolve, reject) => { + kpxcEvent.onLoadSettings((settings) => { + page.settings = settings; + if (!('checkUpdateKeePassXC' in page.settings)) { + page.settings.checkUpdateKeePassXC = defaultSettings.checkUpdateKeePassXC; + } + if (!('autoCompleteUsernames' in page.settings)) { + page.settings.autoCompleteUsernames = defaultSettings.autoCompleteUsernames; + } + if (!('autoFillAndSend' in page.settings)) { + page.settings.autoFillAndSend = defaultSettings.autoFillAndSend; + } + if (!('usePasswordGenerator' in page.settings)) { + page.settings.usePasswordGenerator = defaultSettings.usePasswordGenerator; + } + if (!('autoFillSingleEntry' in page.settings)) { + page.settings.autoFillSingleEntry = defaultSettings.autoFillSingleEntry; + } + if (!('autoRetrieveCredentials' in page.settings)) { + page.settings.autoRetrieveCredentials = defaultSettings.autoRetrieveCredentials; + } + if (!('port' in page.settings)) { + page.settings.port = defaultSettings.proxyPort; + } + browser.storage.local.set({'settings': page.settings}); + resolve(); + }); + }); }; page.initOpenedTabs = function() { - browser.tabs.query({}).then((tabs) => { - for (const i of tabs) { - page.createTabEntry(i.id); - } - - // set initial tab-ID - browser.tabs.query({ "active": true, "currentWindow": true }).then((tabs) => { - if (tabs.length === 0) { - return; // For example: only the background devtools or a popup are opened + return new Promise((resolve, reject) => { + browser.tabs.query({}).then((tabs) => { + for (const i of tabs) { + page.createTabEntry(i.id); } - page.currentTabId = tabs[0].id; - browserAction.show(null, tabs[0]); + + // set initial tab-ID + browser.tabs.query({ "active": true, "currentWindow": true }).then((tabs) => { + if (tabs.length === 0) { + return; // For example: only the background devtools or a popup are opened + } + page.currentTabId = tabs[0].id; + browserAction.show(null, tabs[0]); + resolve(); + }); }); }); }; diff --git a/keepassxc-browser/keepassxc-browser.js b/keepassxc-browser/keepassxc-browser.js index af6ecbc..41962ac 100644 --- a/keepassxc-browser/keepassxc-browser.js +++ b/keepassxc-browser/keepassxc-browser.js @@ -54,7 +54,7 @@ browser.runtime.onMessage.addListener(function(req, sender, callback) { } else if (req.action === 'redetect_fields') { browser.runtime.sendMessage({ - action: 'get_settings', + action: 'load_settings', }).then((response) => { cip.settings = response.data; cip.initCredentialFields(true); @@ -1109,9 +1109,9 @@ jQuery(function() { cip.init = function() { browser.runtime.sendMessage({ - action: 'get_settings', + action: 'load_settings', }).then((response) => { - cip.settings = response.data; + cip.settings = response; cip.initCredentialFields(); }); }; @@ -1134,7 +1134,7 @@ cip.detectNewActiveFields = function() { // Try to do this in a way that database value if checked without polling the KeePassXC.. too many messages jumping around // Switch credentials if database is changed or closed cip.detectDatabaseChange = function() { - const dbDetectInterval = setInterval(function() { + let dbDetectInterval = setInterval(function() { if (document.visibilityState !== 'hidden') { browser.runtime.sendMessage({ action: 'check_databasehash' @@ -1153,9 +1153,9 @@ cip.detectDatabaseChange = function() { } else { if (response.new !== 'no-hash' && response.new !== response.old) { browser.runtime.sendMessage({ - action: 'get_settings', + action: 'load_settings', }).then((response) => { - cip.settings = response.data; + cip.settings = response; cip.initCredentialFields(true); }); } diff --git a/keepassxc-browser/manifest.json b/keepassxc-browser/manifest.json index 9d8273b..0ae891e 100644 --- a/keepassxc-browser/manifest.json +++ b/keepassxc-browser/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "keepassxc-browser", - "version": "0.3.7", + "version": "0.3.8", "description": "KeePassXC integration for modern web browsers", "author": "Sami Vänttinen", "icons": { diff --git a/keepassxc-browser/options/options.js b/keepassxc-browser/options/options.js index 446ccb2..6328a29 100644 --- a/keepassxc-browser/options/options.js +++ b/keepassxc-browser/options/options.js @@ -3,18 +3,21 @@ if (jQuery) { } $(function() { - options.initMenu(); - options.initGeneralSettings(); - options.initConnectedDatabases(); - options.initSpecifiedCredentialFields(); - options.initAbout(); + browser.runtime.sendMessage({ action: 'load_settings' }).then((settings) => { + options.settings = settings; + browser.runtime.sendMessage({ action: 'load_keyring' }).then((keyRing) => { + options.keyRing = keyRing; + options.initMenu(); + options.initGeneralSettings(); + options.initConnectedDatabases(); + options.initSpecifiedCredentialFields(); + options.initAbout(); + }); + }); }); var options = options || {}; -options.settings = typeof(localStorage.settings) === 'undefined' ? {} : JSON.parse(localStorage.settings); -options.keyRing = typeof(localStorage.keyRing) === 'undefined' ? {} : JSON.parse(localStorage.keyRing); - options.initMenu = function() { $('.navbar:first ul.nav:first li a').click(function(e) { e.preventDefault(); @@ -32,22 +35,21 @@ options.saveSetting = function(name) { $($id).closest('.control-group').removeClass('error').addClass('success'); setTimeout(() => { $($id).closest('.control-group').removeClass('success'); }, 2500); - localStorage.settings = JSON.stringify(options.settings); - + browser.storage.local.set({'settings': options.settings}); browser.runtime.sendMessage({ action: 'load_settings' }); }; options.saveSettings = function() { - localStorage.settings = JSON.stringify(options.settings); + browser.storage.local.set({'settings': options.settings}); browser.runtime.sendMessage({ action: 'load_settings' }); }; options.saveKeyRing = function() { - localStorage.keyRing = JSON.stringify(options.keyRing); + browser.storage.local.set({'keyRing': options.keyRing}); browser.runtime.sendMessage({ action: 'load_keyring' }); @@ -107,7 +109,7 @@ options.initGeneralSettings = function() { $('#blinkTimeoutButton').click(function(){ const blinkTimeout = $.trim($('#blinkTimeout').val()); const blinkTimeoutval = Number(blinkTimeout); - + options.settings['blinkTimeout'] = String(blinkTimeoutval); options.saveSetting('blinkTimeout'); }); @@ -115,7 +117,7 @@ options.initGeneralSettings = function() { $('#blinkMinTimeoutButton').click(function(){ const blinkMinTimeout = $.trim($('#blinkMinTimeout').val()); const blinkMinTimeoutval = Number(blinkMinTimeout); - + options.settings['blinkMinTimeout'] = String(blinkMinTimeoutval); options.saveSetting('blinkMinTimeout'); }); @@ -123,7 +125,7 @@ options.initGeneralSettings = function() { $('#allowedRedirectButton').click(function(){ const allowedRedirect = $.trim($('#allowedRedirect').val()); const allowedRedirectval = Number(allowedRedirect); - + options.settings['allowedRedirect'] = String(allowedRedirectval); options.saveSetting('allowedRedirect'); });