diff --git a/CHANGELOG b/CHANGELOG index c05713b..170ce63 100755 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +1.8.8.1 (2023-10-03) +========================= +- Fix handling message timeouts [#1999] + 1.8.8 (2023-09-21) ========================= - Add support for monochrome toolbar icons (Contributor PR) [#1938] diff --git a/keepassxc-browser/background/client.js b/keepassxc-browser/background/client.js index 0e926df..0f6a5df 100644 --- a/keepassxc-browser/background/client.js +++ b/keepassxc-browser/background/client.js @@ -55,26 +55,38 @@ const messageBuffer = { this.buffer.push(message); }, - removeMessageFromIndex(index) { + // Returns corresponding message from the response. If the response is an error, + // return the first matching action from the buffer. + getMessage(response) { + const isError = Boolean(!response.nonce && response.error && response.errorCode); + return this.buffer.find(b => keepassClient.incrementedNonce(b.request.nonce) === response.nonce + || (isError && b.request?.action === response?.action)); + }, + + removeMessage(message) { + const index = this.buffer.indexOf(message); if (index >= 0 && index < this.buffer.length) { this.buffer.splice(index, 1); } - } + }, }; // Basic class for a message to be sent. The Promise inside the class will be resolved when // the response to the message is received. class Message { constructor(request, enableTimeout, timeoutValue) { + this.enableTimeout = enableTimeout; + this.request = request; + this.timeout = undefined; + this.promise = new Promise((resolve, reject) => { this.reject = reject; this.resolve = resolve; - this.enableTimeout = enableTimeout; const messageTimeout = timeoutValue || keepassClient.messageTimeout; // Handle timeout - if (enableTimeout) { + if (this.enableTimeout) { this.timeout = setTimeout(() => { const errorMessage = { action: request.action, @@ -88,6 +100,11 @@ class Message { } }); } + + cancelTimeout() { + this.enableTimeout = false; + clearTimeout(this.timeout); + } } //-------------------------------------------------------------------------- @@ -102,36 +119,33 @@ keepassClient.sendNativeMessage = async function(request, enableTimeout = false, const message = new Message(request, enableTimeout, timeoutValue); await navigator.locks.request('messageBuffer', async (lock) => { - messageBuffer.addMessage({ request: request, message: message }); + messageBuffer.addMessage(message); }); keepassClient.nativePort.postMessage(request); - return await message.promise; + + const response = await message.promise; + + // Remove a timeouted message + if (response.error && response?.errorCode === kpErrors.TIMEOUT_OR_NOT_CONNECTED) { + messageBuffer.removeMessage(message); + } + + return response; }; keepassClient.handleNativeMessage = async function(response) { - const isError = Boolean(!response.nonce && response.error && response.errorCode); - // Parse through the message buffer to find the corresponding Promise. await navigator.locks.request('messageBuffer', async (lock) => { - for (let i = 0; i < messageBuffer.buffer.length; ++i) { - if (!messageBuffer.buffer[i]) { - continue; + const message = messageBuffer.getMessage(response); + if (message) { + if (message.enableTimeout) { + message.cancelTimeout(); } - const request = messageBuffer.buffer[i]?.request; - const message = messageBuffer.buffer[i]?.message; - const errorFound = isError && request?.action === response?.action; - - if ((response.nonce && response.nonce === keepassClient.incrementedNonce(request.nonce)) || errorFound) { - if (message.enableTimeout) { - clearTimeout(message.timeout); - } - - message.resolve(response); - messageBuffer.removeMessageFromIndex(i); - return; - } + message.resolve(response); + messageBuffer.removeMessage(message); + return; } debugLogMessage('Corresponding request not found in the message buffer for response: ', response); diff --git a/keepassxc-browser/background/keepass.js b/keepassxc-browser/background/keepass.js index 3a749f0..19ea3b1 100755 --- a/keepassxc-browser/background/keepass.js +++ b/keepassxc-browser/background/keepass.js @@ -268,10 +268,6 @@ keepass.testAssociation = async function(tab, args = []) { return false; } - if (keepass.isAssociated()) { - return true; - } - if (!keepass.serverPublicKey) { if (tab && page.tabs[tab.id]) { keepass.handleError(tab, kpErrors.PUBLIC_KEY_NOT_FOUND); @@ -387,8 +383,9 @@ keepass.getDatabaseHash = async function(tab, args = []) { keepass.databaseHash = ''; keepass.isDatabaseClosed = true; - if (response.message && response.message === '') { + if ((response.message && response.message === '') || response.errorCode === kpErrors.TIMEOUT_OR_NOT_CONNECTED) { keepass.isKeePassXCAvailable = false; + keepass.isConnected = false; keepass.handleError(tab, kpErrors.TIMEOUT_OR_NOT_CONNECTED); } else { keepass.handleError(tab, response.errorCode, response.error); diff --git a/keepassxc-browser/manifest.json b/keepassxc-browser/manifest.json index ee3f251..e3a4177 100755 --- a/keepassxc-browser/manifest.json +++ b/keepassxc-browser/manifest.json @@ -1,8 +1,8 @@ { "manifest_version": 2, "name": "KeePassXC-Browser", - "version": "1.8.8", - "version_name": "1.8.8", + "version": "1.8.8.1", + "version_name": "1.8.8.1", "minimum_chrome_version": "93", "description": "__MSG_extensionDescription__", "author": "KeePassXC Team", diff --git a/package-lock.json b/package-lock.json index 04ce3fa..9251418 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "keepassxc-browser", - "version": "1.8.8", + "version": "1.8.8.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "keepassxc-browser", - "version": "1.8.8", + "version": "1.8.8.1", "license": "GPL-3.0", "dependencies": { "@npmcli/fs": "^2.1.0", diff --git a/package.json b/package.json index a481bbe..5f4dd74 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "keepassxc-browser", - "version": "1.8.8", + "version": "1.8.8.1", "description": "KeePassXC-Browser", "main": "build.js", "devDependencies": {