js: use version operation for connection checks
-- * src/Connection.js: isConnected was renamed to checkConnection, that returns a promise with either version information or Boolean * Connection checks have been adapted to reflect that checkConnection returns a Promise * BrowsertestExtension: tests/signTest.js was missing from my last commit
This commit is contained in:
parent
a4ba80c553
commit
eff27d6387
58
lang/js/BrowserTestExtension/tests/signTest.js
Normal file
58
lang/js/BrowserTestExtension/tests/signTest.js
Normal file
@ -0,0 +1,58 @@
|
||||
/* gpgme.js - Javascript integration for gpgme
|
||||
* Copyright (C) 2018 Bundesamt für Sicherheit in der Informationstechnik
|
||||
*
|
||||
* This file is part of GPGME.
|
||||
*
|
||||
* GPGME is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* GPGME is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
describe('Signing', function () {
|
||||
it('Sign a message', function (done) {
|
||||
let prm = Gpgmejs.init();
|
||||
prm.then(function (context) {
|
||||
let data = bigString(100);
|
||||
context.sign(
|
||||
data,
|
||||
inputvalues.encrypt.good.fingerprint).then(function (answer) {
|
||||
expect(answer).to.not.be.empty;
|
||||
expect(answer.data).to.be.a('string');
|
||||
expect(answer.data).to.include('BEGIN PGP SIGNATURE');
|
||||
expect(answer.data).to.include('END PGP SIGNATURE');
|
||||
expect(answer.data).to.include(data);
|
||||
context.connection.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
it('Detached sign a message', function (done) {
|
||||
let prm = Gpgmejs.init();
|
||||
prm.then(function (context) {
|
||||
let data = bigString(100);
|
||||
context.sign(
|
||||
data,
|
||||
inputvalues.encrypt.good.fingerprint,
|
||||
'detached'
|
||||
).then(function (answer) {
|
||||
expect(answer).to.not.be.empty;
|
||||
expect(answer.data).to.be.a('string');
|
||||
expect(answer.data).to.include(data);
|
||||
expect(answer.signature).to.be.a('string');
|
||||
expect(answer.signature).to.be.a('string');
|
||||
context.connection.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
@ -30,9 +30,6 @@
|
||||
expect(context.encrypt).to.be.a('function');
|
||||
expect(context.decrypt).to.be.a('function');
|
||||
done();
|
||||
}, function(errorr){
|
||||
expect(error).to.be.undefined;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
import { permittedOperations } from './permittedOperations'
|
||||
import { gpgme_error } from "./Errors"
|
||||
import { GPGME_Message } from "./Message";
|
||||
import { GPGME_Message, createMessage } from "./Message";
|
||||
|
||||
/**
|
||||
* A Connection handles the nativeMessaging interaction.
|
||||
@ -34,18 +34,42 @@ export class Connection{
|
||||
|
||||
constructor(){
|
||||
this.connect();
|
||||
let me = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* (Simple) Connection check.
|
||||
* @returns {Boolean} true if the onDisconnect event has not been fired.
|
||||
* Please note that the event listener of the port takes some time
|
||||
* (5 ms seems enough) to react after the port is created. Then this will
|
||||
* return undefined
|
||||
* Retrieves the information about the backend.
|
||||
* @param {Boolean} details (optional) If set to false, the promise will
|
||||
* just return a connection status
|
||||
* @returns {Promise<Object>}
|
||||
* {String} The property 'gpgme': Version number of gpgme
|
||||
* {Array<Object>} 'info' Further information about the backends.
|
||||
* Example:
|
||||
* "protocol": "OpenPGP",
|
||||
* "fname": "/usr/bin/gpg",
|
||||
* "version": "2.2.6",
|
||||
* "req_version": "1.4.0",
|
||||
* "homedir": "default"
|
||||
*/
|
||||
get isConnected(){
|
||||
return this._isConnected;
|
||||
checkConnection(details = true){
|
||||
if (details === true) {
|
||||
return this.post(createMessage('version'));
|
||||
} else {
|
||||
let me = this;
|
||||
return new Promise(function(resolve,reject) {
|
||||
Promise.race([
|
||||
me.post(createMessage('version')),
|
||||
new Promise(function(resolve, reject){
|
||||
setTimeout(function(){
|
||||
reject(gpgme_error('CONN_TIMEOUT'));
|
||||
}, 500);
|
||||
})
|
||||
]).then(function(result){
|
||||
resolve(true);
|
||||
}, function(reject){
|
||||
resolve(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -54,6 +78,7 @@ export class Connection{
|
||||
disconnect() {
|
||||
if (this._connection){
|
||||
this._connection.disconnect();
|
||||
this._connection = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,17 +86,8 @@ export class Connection{
|
||||
* Opens a nativeMessaging port.
|
||||
*/
|
||||
connect(){
|
||||
if (this._isConnected === true){
|
||||
gpgme_error('CONN_ALREADY_CONNECTED');
|
||||
} else {
|
||||
this._isConnected = true;
|
||||
if (!this._connection){
|
||||
this._connection = chrome.runtime.connectNative('gpgmejson');
|
||||
let me = this;
|
||||
this._connection.onDisconnect.addListener(
|
||||
function(){
|
||||
me._isConnected = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,8 +98,8 @@ export class Connection{
|
||||
* information.
|
||||
*/
|
||||
post(message){
|
||||
if (!this.isConnected){
|
||||
return Promise.reject(gpgme_error('CONN_DISCONNECTED'));
|
||||
if (!this._connection) {
|
||||
|
||||
}
|
||||
if (!message || !message instanceof GPGME_Message){
|
||||
return Promise.reject(gpgme_error('PARAM_WRONG'), message);
|
||||
@ -199,7 +215,7 @@ class Answer{
|
||||
if (!this._response.hasOwnProperty(key)){
|
||||
this._response[key] = [];
|
||||
}
|
||||
this._response.push(msg[key]);
|
||||
this._response[key].push(msg[key]);
|
||||
}
|
||||
else {
|
||||
return gpgme_error('CONN_UNEXPECTED_ANSWER');
|
||||
|
@ -25,10 +25,6 @@ const err_list = {
|
||||
+ ' established.',
|
||||
type: 'error'
|
||||
},
|
||||
'CONN_DISCONNECTED': {
|
||||
msg:'Connection with the nativeMessaging host was lost.',
|
||||
type: 'error'
|
||||
},
|
||||
'CONN_EMPTY_GPG_ANSWER':{
|
||||
msg: 'The nativeMessaging answer was empty.',
|
||||
type: 'error'
|
||||
|
@ -36,10 +36,7 @@ export class GPGME_Keyring {
|
||||
}
|
||||
get connection(){
|
||||
if (this._connection instanceof Connection){
|
||||
if (this._connection.isConnected){
|
||||
return this._connection;
|
||||
}
|
||||
return gpgme_error('CONN_DISCONNECTED');
|
||||
return this._connection;
|
||||
}
|
||||
return gpgme_error('CONN_NO_CONNECT');
|
||||
}
|
||||
@ -51,36 +48,35 @@ export class GPGME_Keyring {
|
||||
*
|
||||
*/
|
||||
getKeys(pattern, include_secret){
|
||||
let msg = createMessage('listkeys');
|
||||
if (msg instanceof Error){
|
||||
return Promise.reject(msg);
|
||||
}
|
||||
if (pattern && typeof(pattern) === 'string'){
|
||||
msg.setParameter('pattern', pattern);
|
||||
}
|
||||
if (include_secret){
|
||||
msg.setParameter('with-secret', true);
|
||||
}
|
||||
let me = this;
|
||||
|
||||
this.connection.post(msg).then(function(result){
|
||||
let fpr_list = [];
|
||||
let resultset = [];
|
||||
if (!Array.isArray(result.keys)){
|
||||
//TODO check assumption keys = Array<String fingerprints>
|
||||
fpr_list = [result.keys];
|
||||
} else {
|
||||
fpr_list = result.keys;
|
||||
return new Promise(function(resolve, reject) {
|
||||
let msg;
|
||||
msg = createMessage('listkeys');
|
||||
if (pattern && typeof(pattern) === 'string'){
|
||||
msg.setParameter('pattern', pattern);
|
||||
}
|
||||
for (let i=0; i < fpr_list.length; i++){
|
||||
let newKey = new GPGME_Key(fpr_list[i], me._connection);
|
||||
if (newKey instanceof GPGME_Key){
|
||||
resultset.push(newKey);
|
||||
if (include_secret){
|
||||
msg.setParameter('with-secret', true);
|
||||
}
|
||||
me.connection.post(msg).then(function(result){
|
||||
let fpr_list = [];
|
||||
let resultset = [];
|
||||
if (!Array.isArray(result.keys)){
|
||||
//TODO check assumption keys = Array<String fingerprints>
|
||||
fpr_list = [result.keys];
|
||||
} else {
|
||||
fpr_list = result.keys;
|
||||
}
|
||||
}
|
||||
return Promise.resolve(resultset);
|
||||
}, function(error){
|
||||
//TODO error handling
|
||||
for (let i=0; i < fpr_list.length; i++){
|
||||
let newKey = new GPGME_Key(fpr_list[i], me._connection);
|
||||
if (newKey instanceof GPGME_Key){
|
||||
resultset.push(newKey);
|
||||
}
|
||||
}
|
||||
resolve(resultset);
|
||||
}, function(error){
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -44,13 +44,7 @@ export class GpgME {
|
||||
}
|
||||
|
||||
get connection(){
|
||||
if (this._connection){
|
||||
if (this._connection.isConnected === true){
|
||||
return this._connection;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return undefined;
|
||||
return this._connection;
|
||||
}
|
||||
|
||||
set Keyring(keyring){
|
||||
|
@ -34,20 +34,16 @@ function init(config){
|
||||
}
|
||||
return new Promise(function(resolve, reject){
|
||||
let connection = new Connection;
|
||||
// TODO: Delayed reaction is ugly. We need to listen to the port's
|
||||
// event listener in isConnected, but in some cases this takes some
|
||||
// time (<5ms) to disconnect if there is no successfull connection.
|
||||
let delayedreaction = function(){
|
||||
if (connection === undefined) {
|
||||
connection.checkConnection(false).then(
|
||||
function(result){
|
||||
if (result === true) {
|
||||
resolve(new GpgME(connection, _conf));
|
||||
} else {
|
||||
reject(gpgme_error('CONN_NO_CONNECT'));
|
||||
}
|
||||
}, function(error){
|
||||
reject(gpgme_error('CONN_NO_CONNECT'));
|
||||
}
|
||||
if (connection.isConnected === true){
|
||||
resolve(new GpgME(connection, _conf));
|
||||
} else {
|
||||
reject(gpgme_error('CONN_NO_CONNECT'));
|
||||
}
|
||||
};
|
||||
setTimeout(delayedreaction, 5);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -39,34 +39,29 @@ function unittests (){
|
||||
|
||||
it('Connecting', function(done) {
|
||||
let conn0 = new Connection;
|
||||
let delayed = function(){
|
||||
expect(conn0.isConnected).to.be.true;
|
||||
expect(conn0.connect).to.be.a('function');
|
||||
conn0.checkConnection().then(function(answer) {
|
||||
expect(answer).to.not.be.empty;
|
||||
expect(answer.gpgme).to.not.be.undefined;
|
||||
expect(answer.gpgme).to.be.a('string');
|
||||
expect(answer.info).to.be.an('Array');
|
||||
expect(conn0.disconnect).to.be.a('function');
|
||||
expect(conn0.post).to.be.a('function');
|
||||
done();
|
||||
};
|
||||
setTimeout(delayed, 5);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('Disconnecting', function(done) {
|
||||
let conn0 = new Connection;
|
||||
let delayed = function(){
|
||||
conn0.disconnect(); // TODO fails!
|
||||
expect(conn0.isConnected).to.be.false;
|
||||
done();
|
||||
};
|
||||
setTimeout(delayed, 5);
|
||||
conn0.checkConnection(false).then(function(answer) {
|
||||
expect(answer).to.be.true;
|
||||
conn0.disconnect();
|
||||
conn0.checkConnection(false).then(function(result) {
|
||||
expect(result).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// broken
|
||||
// it('Connect info still only available after a delay', function(done){
|
||||
// // if false, all delayed connections can be refactored
|
||||
// let conn0 = new Connection;
|
||||
// expect(conn0.isConnected).to.be.undefined;
|
||||
// //
|
||||
// })
|
||||
});
|
||||
|
||||
describe('Error Object handling', function(){
|
||||
@ -181,14 +176,17 @@ function unittests (){
|
||||
// TODO not implemented yet: Further Key functionality
|
||||
});
|
||||
|
||||
it('Key can use the connection', function(){
|
||||
it('Key can use the connection', function(done){
|
||||
let conn = new Connection;
|
||||
let key = createKey(hp.validFingerprint, conn);
|
||||
|
||||
expect(key.connection.isConnected).to.be.true;
|
||||
|
||||
key.connection.disconnect();
|
||||
expect(key.connection.isConnected).to.be.false;
|
||||
key.connection.checkConnection(false).then(function(result){
|
||||
expect(result).to.be.true;
|
||||
key.connection.disconnect();
|
||||
key.connection.checkConnection(false).then(function(result2){
|
||||
expect(result2).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('createKey returns error if parameters are wrong', function(){
|
||||
@ -232,12 +230,15 @@ function unittests (){
|
||||
|
||||
it('Keyring should return errors if not connected', function(){
|
||||
let keyring = new GPGME_Keyring;
|
||||
|
||||
expect(keyring).to.be.an.instanceof(GPGME_Keyring);
|
||||
expect(keyring.connection).to.be.an.instanceof(Error);
|
||||
expect(keyring.connection.code).to.equal('CONN_NO_CONNECT');
|
||||
expect(keyring.getKeys).to.be.an.instanceof(Error);
|
||||
expect(keyring.getkeys.code).to.equal('CONN_NO_CONNECT');
|
||||
// not yet implemented:
|
||||
// keyring.getKeys().then(
|
||||
// function(result){},
|
||||
//function(reject){
|
||||
// expect(reject).to.be.an.instanceof(Error);
|
||||
// done();
|
||||
});
|
||||
//TODO not yet implemented:
|
||||
// getKeys(pattern, include_secret) //note: pattern can be null
|
||||
|
Loading…
Reference in New Issue
Block a user