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.encrypt).to.be.a('function');
|
||||||
expect(context.decrypt).to.be.a('function');
|
expect(context.decrypt).to.be.a('function');
|
||||||
done();
|
done();
|
||||||
}, function(errorr){
|
|
||||||
expect(error).to.be.undefined;
|
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
import { permittedOperations } from './permittedOperations'
|
import { permittedOperations } from './permittedOperations'
|
||||||
import { gpgme_error } from "./Errors"
|
import { gpgme_error } from "./Errors"
|
||||||
import { GPGME_Message } from "./Message";
|
import { GPGME_Message, createMessage } from "./Message";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Connection handles the nativeMessaging interaction.
|
* A Connection handles the nativeMessaging interaction.
|
||||||
@ -34,18 +34,42 @@ export class Connection{
|
|||||||
|
|
||||||
constructor(){
|
constructor(){
|
||||||
this.connect();
|
this.connect();
|
||||||
let me = this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (Simple) Connection check.
|
* Retrieves the information about the backend.
|
||||||
* @returns {Boolean} true if the onDisconnect event has not been fired.
|
* @param {Boolean} details (optional) If set to false, the promise will
|
||||||
* Please note that the event listener of the port takes some time
|
* just return a connection status
|
||||||
* (5 ms seems enough) to react after the port is created. Then this will
|
* @returns {Promise<Object>}
|
||||||
* return undefined
|
* {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(){
|
checkConnection(details = true){
|
||||||
return this._isConnected;
|
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() {
|
disconnect() {
|
||||||
if (this._connection){
|
if (this._connection){
|
||||||
this._connection.disconnect();
|
this._connection.disconnect();
|
||||||
|
this._connection = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,17 +86,8 @@ export class Connection{
|
|||||||
* Opens a nativeMessaging port.
|
* Opens a nativeMessaging port.
|
||||||
*/
|
*/
|
||||||
connect(){
|
connect(){
|
||||||
if (this._isConnected === true){
|
if (!this._connection){
|
||||||
gpgme_error('CONN_ALREADY_CONNECTED');
|
|
||||||
} else {
|
|
||||||
this._isConnected = true;
|
|
||||||
this._connection = chrome.runtime.connectNative('gpgmejson');
|
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.
|
* information.
|
||||||
*/
|
*/
|
||||||
post(message){
|
post(message){
|
||||||
if (!this.isConnected){
|
if (!this._connection) {
|
||||||
return Promise.reject(gpgme_error('CONN_DISCONNECTED'));
|
|
||||||
}
|
}
|
||||||
if (!message || !message instanceof GPGME_Message){
|
if (!message || !message instanceof GPGME_Message){
|
||||||
return Promise.reject(gpgme_error('PARAM_WRONG'), message);
|
return Promise.reject(gpgme_error('PARAM_WRONG'), message);
|
||||||
@ -199,7 +215,7 @@ class Answer{
|
|||||||
if (!this._response.hasOwnProperty(key)){
|
if (!this._response.hasOwnProperty(key)){
|
||||||
this._response[key] = [];
|
this._response[key] = [];
|
||||||
}
|
}
|
||||||
this._response.push(msg[key]);
|
this._response[key].push(msg[key]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return gpgme_error('CONN_UNEXPECTED_ANSWER');
|
return gpgme_error('CONN_UNEXPECTED_ANSWER');
|
||||||
|
@ -25,10 +25,6 @@ const err_list = {
|
|||||||
+ ' established.',
|
+ ' established.',
|
||||||
type: 'error'
|
type: 'error'
|
||||||
},
|
},
|
||||||
'CONN_DISCONNECTED': {
|
|
||||||
msg:'Connection with the nativeMessaging host was lost.',
|
|
||||||
type: 'error'
|
|
||||||
},
|
|
||||||
'CONN_EMPTY_GPG_ANSWER':{
|
'CONN_EMPTY_GPG_ANSWER':{
|
||||||
msg: 'The nativeMessaging answer was empty.',
|
msg: 'The nativeMessaging answer was empty.',
|
||||||
type: 'error'
|
type: 'error'
|
||||||
|
@ -36,10 +36,7 @@ export class GPGME_Keyring {
|
|||||||
}
|
}
|
||||||
get connection(){
|
get connection(){
|
||||||
if (this._connection instanceof Connection){
|
if (this._connection instanceof Connection){
|
||||||
if (this._connection.isConnected){
|
return this._connection;
|
||||||
return this._connection;
|
|
||||||
}
|
|
||||||
return gpgme_error('CONN_DISCONNECTED');
|
|
||||||
}
|
}
|
||||||
return gpgme_error('CONN_NO_CONNECT');
|
return gpgme_error('CONN_NO_CONNECT');
|
||||||
}
|
}
|
||||||
@ -51,36 +48,35 @@ export class GPGME_Keyring {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
getKeys(pattern, include_secret){
|
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;
|
let me = this;
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
this.connection.post(msg).then(function(result){
|
let msg;
|
||||||
let fpr_list = [];
|
msg = createMessage('listkeys');
|
||||||
let resultset = [];
|
if (pattern && typeof(pattern) === 'string'){
|
||||||
if (!Array.isArray(result.keys)){
|
msg.setParameter('pattern', pattern);
|
||||||
//TODO check assumption keys = Array<String fingerprints>
|
|
||||||
fpr_list = [result.keys];
|
|
||||||
} else {
|
|
||||||
fpr_list = result.keys;
|
|
||||||
}
|
}
|
||||||
for (let i=0; i < fpr_list.length; i++){
|
if (include_secret){
|
||||||
let newKey = new GPGME_Key(fpr_list[i], me._connection);
|
msg.setParameter('with-secret', true);
|
||||||
if (newKey instanceof GPGME_Key){
|
}
|
||||||
resultset.push(newKey);
|
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;
|
||||||
}
|
}
|
||||||
}
|
for (let i=0; i < fpr_list.length; i++){
|
||||||
return Promise.resolve(resultset);
|
let newKey = new GPGME_Key(fpr_list[i], me._connection);
|
||||||
}, function(error){
|
if (newKey instanceof GPGME_Key){
|
||||||
//TODO error handling
|
resultset.push(newKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve(resultset);
|
||||||
|
}, function(error){
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,13 +44,7 @@ export class GpgME {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get connection(){
|
get connection(){
|
||||||
if (this._connection){
|
return this._connection;
|
||||||
if (this._connection.isConnected === true){
|
|
||||||
return this._connection;
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set Keyring(keyring){
|
set Keyring(keyring){
|
||||||
|
@ -34,20 +34,16 @@ function init(config){
|
|||||||
}
|
}
|
||||||
return new Promise(function(resolve, reject){
|
return new Promise(function(resolve, reject){
|
||||||
let connection = new Connection;
|
let connection = new Connection;
|
||||||
// TODO: Delayed reaction is ugly. We need to listen to the port's
|
connection.checkConnection(false).then(
|
||||||
// event listener in isConnected, but in some cases this takes some
|
function(result){
|
||||||
// time (<5ms) to disconnect if there is no successfull connection.
|
if (result === true) {
|
||||||
let delayedreaction = function(){
|
resolve(new GpgME(connection, _conf));
|
||||||
if (connection === undefined) {
|
} else {
|
||||||
|
reject(gpgme_error('CONN_NO_CONNECT'));
|
||||||
|
}
|
||||||
|
}, function(error){
|
||||||
reject(gpgme_error('CONN_NO_CONNECT'));
|
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) {
|
it('Connecting', function(done) {
|
||||||
let conn0 = new Connection;
|
let conn0 = new Connection;
|
||||||
let delayed = function(){
|
conn0.checkConnection().then(function(answer) {
|
||||||
expect(conn0.isConnected).to.be.true;
|
expect(answer).to.not.be.empty;
|
||||||
expect(conn0.connect).to.be.a('function');
|
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.disconnect).to.be.a('function');
|
||||||
expect(conn0.post).to.be.a('function');
|
expect(conn0.post).to.be.a('function');
|
||||||
done();
|
done();
|
||||||
};
|
});
|
||||||
setTimeout(delayed, 5);
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Disconnecting', function(done) {
|
it('Disconnecting', function(done) {
|
||||||
let conn0 = new Connection;
|
let conn0 = new Connection;
|
||||||
let delayed = function(){
|
conn0.checkConnection(false).then(function(answer) {
|
||||||
conn0.disconnect(); // TODO fails!
|
expect(answer).to.be.true;
|
||||||
expect(conn0.isConnected).to.be.false;
|
conn0.disconnect();
|
||||||
done();
|
conn0.checkConnection(false).then(function(result) {
|
||||||
};
|
expect(result).to.be.false;
|
||||||
setTimeout(delayed, 5);
|
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(){
|
describe('Error Object handling', function(){
|
||||||
@ -181,14 +176,17 @@ function unittests (){
|
|||||||
// TODO not implemented yet: Further Key functionality
|
// 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 conn = new Connection;
|
||||||
let key = createKey(hp.validFingerprint, conn);
|
let key = createKey(hp.validFingerprint, conn);
|
||||||
|
key.connection.checkConnection(false).then(function(result){
|
||||||
expect(key.connection.isConnected).to.be.true;
|
expect(result).to.be.true;
|
||||||
|
key.connection.disconnect();
|
||||||
key.connection.disconnect();
|
key.connection.checkConnection(false).then(function(result2){
|
||||||
expect(key.connection.isConnected).to.be.false;
|
expect(result2).to.be.false;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('createKey returns error if parameters are wrong', function(){
|
it('createKey returns error if parameters are wrong', function(){
|
||||||
@ -232,12 +230,15 @@ function unittests (){
|
|||||||
|
|
||||||
it('Keyring should return errors if not connected', function(){
|
it('Keyring should return errors if not connected', function(){
|
||||||
let keyring = new GPGME_Keyring;
|
let keyring = new GPGME_Keyring;
|
||||||
|
|
||||||
expect(keyring).to.be.an.instanceof(GPGME_Keyring);
|
expect(keyring).to.be.an.instanceof(GPGME_Keyring);
|
||||||
expect(keyring.connection).to.be.an.instanceof(Error);
|
expect(keyring.connection).to.be.an.instanceof(Error);
|
||||||
expect(keyring.connection.code).to.equal('CONN_NO_CONNECT');
|
expect(keyring.connection.code).to.equal('CONN_NO_CONNECT');
|
||||||
expect(keyring.getKeys).to.be.an.instanceof(Error);
|
// not yet implemented:
|
||||||
expect(keyring.getkeys.code).to.equal('CONN_NO_CONNECT');
|
// keyring.getKeys().then(
|
||||||
|
// function(result){},
|
||||||
|
//function(reject){
|
||||||
|
// expect(reject).to.be.an.instanceof(Error);
|
||||||
|
// done();
|
||||||
});
|
});
|
||||||
//TODO not yet implemented:
|
//TODO not yet implemented:
|
||||||
// getKeys(pattern, include_secret) //note: pattern can be null
|
// getKeys(pattern, include_secret) //note: pattern can be null
|
||||||
|
Loading…
Reference in New Issue
Block a user