aboutsummaryrefslogtreecommitdiffstats
path: root/lang/js
diff options
context:
space:
mode:
authorMaximilian Krambach <[email protected]>2019-06-19 10:57:20 +0000
committerMaximilian Krambach <[email protected]>2019-06-19 10:58:44 +0000
commitf5e27a12d3fd22b95e83c03a5650659bfa2299b9 (patch)
tree7ddac98f4f0a20ffc6d6a2aaf2ec25ddd5a7efd3 /lang/js
parentPost release updates (diff)
downloadgpgme-f5e27a12d3fd22b95e83c03a5650659bfa2299b9.tar.gz
gpgme-f5e27a12d3fd22b95e83c03a5650659bfa2299b9.zip
js: Error handling for browser errors
-- * Connection.js - Add some meaningful nativeMessaging feedback for failing communication due to misconfiguration or other browser-originated fails - add an "isDisconnected" property - "isNativeHostUnknown" tries to match browser's feedback string if the browser does not find gpgme-json * init.js - initialization will now reject with a more meaningful error if the configuration is not set up or other browser-based errors (chrome.runtime.lastError) are present. This should speed up the normal initialization (not having to waiting for a timeout any more in case of improper setup) * errors.js - CONN_NATIVEMESSAGE: New error that passes the browser's nativeMessaging error - CONN_NO_CONFIG: native messaging error indicating that the nativeMessaging host was not set up properly * unittests.js: - added the "isDisconnected" property to the startup tests - added tests for proper behavior of connection checks
Diffstat (limited to 'lang/js')
-rw-r--r--lang/js/src/Connection.js68
-rw-r--r--lang/js/src/Errors.js12
-rw-r--r--lang/js/src/index.js14
-rw-r--r--lang/js/unittests.js32
4 files changed, 99 insertions, 27 deletions
diff --git a/lang/js/src/Connection.js b/lang/js/src/Connection.js
index 8a965479..923698a4 100644
--- a/lang/js/src/Connection.js
+++ b/lang/js/src/Connection.js
@@ -40,7 +40,15 @@ import { decode, atobArray, Utf8ArrayToStr } from './Helpers';
export class Connection{
constructor (){
+ this._connectionError = null;
this._connection = chrome.runtime.connectNative('gpgmejson');
+ this._connection.onDisconnect.addListener(() => {
+ if (chrome.runtime.lastError) {
+ this._connectionError = chrome.runtime.lastError.message;
+ } else {
+ this._connectionError = 'Disconnected without error message';
+ }
+ });
}
/**
@@ -50,9 +58,16 @@ export class Connection{
if (this._connection){
this._connection.disconnect();
this._connection = null;
+ this._connectionError = 'Disconnect requested by gpgmejs';
}
}
+ /**
+ * Checks if the connection terminated with an error state
+ */
+ get isDisconnected (){
+ return this._connectionError !== null;
+ }
/**
* @typedef {Object} backEndDetails
@@ -126,9 +141,17 @@ export class Connection{
this.disconnect();
return Promise.reject(gpgme_error('MSG_INCOMPLETE'));
}
+ if (this.isDisconnected) {
+ if ( this.isNativeHostUnknown === true) {
+ return Promise.reject(gpgme_error('CONN_NO_CONFIG'));
+ } else {
+ return Promise.reject(gpgme_error(
+ 'CONN_NO_CONNECT', this._connectionError));
+ }
+ }
let chunksize = message.chunksize;
const me = this;
- return new Promise(function (resolve, reject){
+ const nativeCommunication = new Promise(function (resolve, reject){
let answer = new Answer(message);
let listener = function (msg) {
if (!msg){
@@ -161,29 +184,21 @@ export class Connection{
}
};
me._connection.onMessage.addListener(listener);
- if (permittedOperations[message.operation].pinentry){
- return me._connection.postMessage(message.message);
- } else {
- return Promise.race([
- me._connection.postMessage(message.message),
- function (resolve, reject){
- setTimeout(function (){
- me._connection.disconnect();
- reject(gpgme_error('CONN_TIMEOUT'));
- }, 5000);
- }
- ]).then(function (result){
- return result;
- }, function (reject){
- if (!(reject instanceof Error)) {
- me._connection.disconnect();
- return gpgme_error('GNUPG_ERROR', reject);
- } else {
- return reject;
- }
- });
- }
+ me._connection.postMessage(message.message);
});
+ if (permittedOperations[message.operation].pinentry === true) {
+ return nativeCommunication;
+ } else {
+ return Promise.race([
+ nativeCommunication,
+ new Promise(function (resolve, reject){
+ setTimeout(function (){
+ me._connection.disconnect();
+ reject(gpgme_error('CONN_TIMEOUT'));
+ }, 5000);
+ })
+ ]);
+ }
}
}
@@ -213,6 +228,13 @@ class Answer{
}
/**
+ * Checks if an error matching browsers 'host not known' messages occurred
+ */
+ get isNativeHostUnknown () {
+ return this._connectionError === 'Specified native messaging host not found.';
+ }
+
+ /**
* Adds incoming base64 encoded data to the existing response
* @param {*} msg base64 encoded data.
* @returns {Boolean}
diff --git a/lang/js/src/Errors.js b/lang/js/src/Errors.js
index bf52cce7..6189414f 100644
--- a/lang/js/src/Errors.js
+++ b/lang/js/src/Errors.js
@@ -35,6 +35,14 @@ export const err_list = {
msg: 'The nativeMessaging answer was empty.',
type: 'error'
},
+ 'CONN_NO_CONFIG':{
+ msg: 'The browser does not recognize the nativeMessaging host.',
+ type: 'error'
+ },
+ 'CONN_NATIVEMESSAGE':{
+ msg: 'The native messaging was not successful.',
+ type: 'error'
+ },
'CONN_TIMEOUT': {
msg: 'A connection timeout was exceeded.',
type: 'error'
@@ -156,8 +164,8 @@ export function gpgme_error (code = 'GENERIC_ERROR', info){
*/
class GPGME_Error extends Error{
constructor (code = 'GENERIC_ERROR', msg=''){
-
- if (code === 'GNUPG_ERROR' && typeof (msg) === 'string'){
+ const verboseErrors = ['GNUPG_ERROR', 'CONN_NATIVEMESSAGE'];
+ if (verboseErrors.includes(code) && typeof (msg) === 'string'){
super(msg);
} else if (err_list.hasOwnProperty(code)){
if (msg){
diff --git a/lang/js/src/index.js b/lang/js/src/index.js
index 106086fb..3c31a047 100644
--- a/lang/js/src/index.js
+++ b/lang/js/src/index.js
@@ -33,7 +33,7 @@ import { Connection } from './Connection';
* An unsuccessful attempt will reject as a GPGME_Error.
* @param {Object} config (optional) configuration options
* @param {Number} config.timeout set the timeout for the initial connection
- * check. On some machines and operating systems a default timeout of 500 ms is
+ * check. On some machines and operating systems a default timeout of 1000 ms is
* too low, so a higher number might be attempted.
* @returns {Promise<GpgME>}
* @async
@@ -46,7 +46,17 @@ function init ({ timeout = 1000 } = {}){
if (result === true) {
resolve(new GpgME());
} else {
- reject(gpgme_error('CONN_NO_CONNECT'));
+ if (connection._connectionError) {
+ if (connection.isNativeHostUnknown){
+ reject(gpgme_error('CONN_NO_CONFIG'));
+ } else {
+ reject(gpgme_error('CONN_NATIVEMESSAGE',
+ connection._connectionError)
+ );
+ }
+ } else {
+ reject(gpgme_error('CONN_TIMEOUT'));
+ }
}
}, function (){ // unspecific connection error. Should not happen
reject(gpgme_error('CONN_NO_CONNECT'));
diff --git a/lang/js/unittests.js b/lang/js/unittests.js
index 414d18d1..45e2b93c 100644
--- a/lang/js/unittests.js
+++ b/lang/js/unittests.js
@@ -49,11 +49,42 @@ function unittests (){
expect(answer.info).to.be.an('Array');
expect(conn0.disconnect).to.be.a('function');
expect(conn0.post).to.be.a('function');
+ expect(conn0.isDisconnected).to.be.false;
done();
});
});
+ it('Simple connection check', function (done) {
+ let conn0 = new Connection;
+ conn0.checkConnection(false, connectionTimeout).then(
+ function (answer) {
+ expect(answer).to.be.true;
+ expect(conn0.isDisconnected).to.be.false;
+ done();
+ });
+ });
+
+ it('Connection check with backend information', function (done) {
+ let conn0 = new Connection;
+ conn0.checkConnection(true, connectionTimeout).then(
+ function (answer) {
+ expect(answer).to.be.an('Object');
+ expect(answer.gpgme).to.be.a('String');
+ expect(answer.info).to.be.an('Array');
+ expect(answer.info.length).to.be.above(0);
+ for (const item of answer.info) {
+ expect(item).to.have.property('protocol');
+ expect(item).to.have.property('fname');
+ expect(item).to.have.property('version');
+ expect(item).to.have.property('req_version');
+ expect(item).to.have.property('homedir');
+ }
+ expect(conn0.isDisconnected).to.be.false;
+ done();
+ });
+ });
+
it('Disconnecting', function (done) {
let conn0 = new Connection;
conn0.checkConnection(false, connectionTimeout).then(
@@ -63,6 +94,7 @@ function unittests (){
conn0.checkConnection(false, connectionTimeout).then(
function (result) {
expect(result).to.be.false;
+ expect(conn0.isDisconnected).to.be.true;
done();
});
});