js: Treat a connection as a gpgme Context
authorMaximilian Krambach <maximilian.krambach@intevation.de>
Mon, 28 May 2018 14:52:50 +0000 (16:52 +0200)
committerMaximilian Krambach <maximilian.krambach@intevation.de>
Mon, 28 May 2018 14:52:50 +0000 (16:52 +0200)
--

* After an operation a connection should be disconnected again.
  The "end of operation" is now assumed to be either an error as
  answer, or a message not including a "more"

* GPGME, GPGME_Key, GPGME_Keyring don't require a connection
  anymore
* Message.js: The Message.post() method will open a connection as
  required

12 files changed:
lang/js/BrowserTestExtension/tests/encryptDecryptTest.js
lang/js/BrowserTestExtension/tests/encryptTest.js
lang/js/BrowserTestExtension/tests/longRunningTests.js
lang/js/BrowserTestExtension/tests/signTest.js
lang/js/BrowserTestExtension/tests/startup.js
lang/js/src/Connection.js
lang/js/src/Key.js
lang/js/src/Keyring.js
lang/js/src/Message.js
lang/js/src/gpgmejs.js
lang/js/src/index.js
lang/js/unittests.js

index 2fe955e..f5d2be1 100644 (file)
@@ -34,7 +34,6 @@ describe('Encryption and Decryption', function () {
                         expect(result).to.not.be.empty;
                         expect(result.data).to.be.a('string');
                         expect(result.data).to.equal(inputvalues.encrypt.good.data);
-                        context.connection.disconnect();
                         done();
                     });
                 });
@@ -75,7 +74,6 @@ describe('Encryption and Decryption', function () {
                                 expect(result).to.not.be.empty;
                                 expect(result.data).to.be.a('string');
                                 expect(result.data).to.equal(data);
-                                context.connection.disconnect();
                                 done();
 
                             });
@@ -108,7 +106,6 @@ describe('Encryption and Decryption', function () {
                                     expect(result).to.not.be.empty;
                                     expect(result.data).to.be.a('string');
                                     expect(result.data).to.equal(data);
-                                    context.connection.disconnect();
                                     done();
                                 });
                         });
@@ -134,7 +131,6 @@ describe('Encryption and Decryption', function () {
                             expect(result).to.not.be.empty;
                             expect(result.data).to.be.a('string');
                             expect(result.data).to.equal(data);
-                            context.connection.disconnect();
                             done();
                         });
                 });
@@ -160,7 +156,6 @@ describe('Encryption and Decryption', function () {
                             expect(result).to.not.be.empty;
                             expect(result.data).to.be.a('string');
                             expect(data).to.equal(data);
-                            context.connection.disconnect();
                             done();
                         });
                 });
@@ -187,7 +182,6 @@ describe('Encryption and Decryption', function () {
                             expect(result).to.not.be.empty;
                             expect(result.data).to.be.a('string');
                             expect(result.data).to.equal(data);
-                            context.connection.disconnect();
                             done();
                         });
                 });
@@ -214,7 +208,6 @@ describe('Encryption and Decryption', function () {
                             expect(result).to.not.be.empty;
                             expect(result.data).to.be.a('string');
                             expect(result.data).to.equal(b64data);
-                            context.connection.disconnect();
                             done();
                         });
                 });
index 521ed27..a16f993 100644 (file)
@@ -28,7 +28,6 @@ describe('Encryption', function () {
                     expect(answer.data).to.be.a("string");
                     expect(answer.data).to.include('BEGIN PGP MESSAGE');
                     expect(answer.data).to.include('END PGP MESSAGE');
-                    context.connection.disconnect();
                     done();
                 });
         });
@@ -45,7 +44,6 @@ describe('Encryption', function () {
                     expect(answer.data).to.be.a("string");
                     expect(answer.data).to.include('BEGIN PGP MESSAGE');
                     expect(answer.data).to.include('END PGP MESSAGE');
-                    context.connection.disconnect();
                     done();
                 });
         });
@@ -62,7 +60,6 @@ describe('Encryption', function () {
                     expect(answer.data).to.be.a("string");
                     expect(answer.data).to.include('BEGIN PGP MESSAGE');
                     expect(answer.data).to.include('END PGP MESSAGE');
-                    context.connection.disconnect();
                     done();
                 });
         });
@@ -79,7 +76,6 @@ describe('Encryption', function () {
                     expect(answer.data).to.be.a("string");
                     expect(answer.data).to.include('BEGIN PGP MESSAGE');
                     expect(answer.data).to.include('END PGP MESSAGE');
-                    context.connection.disconnect();
                     done();
                 });
         });
@@ -95,7 +91,6 @@ describe('Encryption', function () {
                 }, function(error){
                     expect(error).to.be.an('Error');
                     expect(error.code).to.equal('MSG_INCOMPLETE');
-                    context.connection.disconnect();
                     done();
                 });
         });
@@ -110,7 +105,6 @@ describe('Encryption', function () {
                 }, function (error) {
                     expect(error).to.be.an.instanceof(Error);
                     expect(error.code).to.equal('MSG_INCOMPLETE');
-                    context.connection.disconnect();
                     done();
                 });
         });
@@ -127,7 +121,6 @@ describe('Encryption', function () {
                     expect(error).to.be.an('Error');
                     expect(error.code).to.not.be.undefined;
                     expect(error.code).to.equal('GNUPG_ERROR');
-                    context.connection.disconnect();
                     done();
                 });
         });
@@ -146,7 +139,6 @@ describe('Encryption', function () {
                     // TODO: there is a 64 MB hard limit at least in chrome at:
                     // chromium//extensions/renderer/messaging_util.cc:
                     // kMaxMessageLength
-                    context.connection.disconnect();
                     done();
                 });
         });
index 4e55fd2..5c588f2 100644 (file)
@@ -29,7 +29,6 @@ describe('Long running Encryption/Decryption', function () {
                                             }
                                         }
                                         expect(result.data).to.equal(data);
-                                        context.connection.disconnect();
                                         done();
                                 });
                         });
index e332372..2e5edb3 100644 (file)
@@ -30,7 +30,6 @@ describe('Signing', function () {
                     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();
             });
         });
@@ -49,7 +48,6 @@ describe('Signing', function () {
                     expect(answer.data).to.include(data);
                     expect(answer.signature).to.be.a('string');
                     expect(answer.signature).to.be.a('string');
-                    context.connection.disconnect();
                     done();
             });
         });
index ebecf4f..7d13ea4 100644 (file)
         let prm = Gpgmejs.init();
         prm.then(
          function(context){
-            expect(context.connection).to.not.be.undefined;
             expect(context).to.be.an('object');
-            expect(context.connection).to.be.an('object');
-            expect(context.Keyring).to.be.undefined;
             expect(context.encrypt).to.be.a('function');
             expect(context.decrypt).to.be.a('function');
             done();
index 3b44262..3480d81 100644 (file)
@@ -102,9 +102,11 @@ export class Connection{
 
         }
         if (!message || !message instanceof GPGME_Message){
+            this.disconnect();
             return Promise.reject(gpgme_error('PARAM_WRONG'), message);
         }
         if (message.isComplete !== true){
+            this.disconnect();
             return Promise.reject(gpgme_error('MSG_INCOMPLETE'));
         }
         let me = this;
@@ -113,25 +115,27 @@ export class Connection{
             let listener = function(msg) {
                 if (!msg){
                     me._connection.onMessage.removeListener(listener)
+                    me._connection.disconnect();
                     reject(gpgme_error('CONN_EMPTY_GPG_ANSWER'));
                 } else if (msg.type === "error"){
                     me._connection.onMessage.removeListener(listener);
+                    me._connection.disconnect();
                     reject(gpgme_error('GNUPG_ERROR', msg.msg));
                 } else {
                     let answer_result = answer.add(msg);
                     if (answer_result !== true){
                         me._connection.onMessage.removeListener(listener);
+                        me._connection.disconnect();
                         reject(answer_result);
-                    }
-                    if (msg.more === true){
+                    } else if (msg.more === true){
                         me._connection.postMessage({'op': 'getmore'});
                     } else {
                         me._connection.onMessage.removeListener(listener)
+                        me._connection.disconnect();
                         resolve(answer.message);
                     }
                 }
             };
-
             me._connection.onMessage.addListener(listener);
             if (permittedOperations[message.operation].pinentry){
                 return me._connection.postMessage(message.message);
@@ -140,12 +144,14 @@ export class Connection{
                     me._connection.postMessage(message.message),
                     function(resolve, reject){
                         setTimeout(function(){
+                            me._connection.disconnect();
                             reject(gpgme_error('CONN_TIMEOUT'));
                         }, 5000);
                     }]).then(function(result){
-                    return result;
+                        return result;
                 }, function(reject){
                     if(!reject instanceof Error) {
+                        me._connection.disconnect();
                         return gpgme_error('GNUPG_ERROR', reject);
                     } else {
                         return reject;
index 7d3d82b..13c9954 100644 (file)
@@ -30,27 +30,16 @@ import { isFingerprint, isLongId } from './Helpers'
 import { gpgme_error } from './Errors'
 import { createMessage } from './Message';
 import { permittedOperations } from './permittedOperations';
-import { Connection } from './Connection';
 
 /**
- * Validates the fingerprint, and checks for tha availability of a connection.
- * If both are available, a Key will be returned.
+ * Validates the fingerprint.
  * @param {String} fingerprint
- * @param {Object} parent Either a Connection, or the invoking object with a
- * Connection (e.g. Keyring)
  */
-export function createKey(fingerprint, parent){
+export function createKey(fingerprint){
     if (!isFingerprint(fingerprint)){
         return gpgme_error('PARAM_WRONG');
     }
-    if ( parent instanceof Connection){
-        return new GPGME_Key(fingerprint, parent);
-    } else if ( parent.hasOwnProperty('connection') &&
-        parent.connection instanceof Connection){
-            return new GPGME_Key(fingerprint, parent.connection);
-    } else {
-        return gpgme_error('PARAM_WRONG');
-    }
+    else return new GPGME_Key(fingerprint);
 }
 
 /**
@@ -58,28 +47,8 @@ export function createKey(fingerprint, parent){
  */
 export class GPGME_Key {
 
-    constructor(fingerprint, connection){
+    constructor(fingerprint){
         this.fingerprint = fingerprint;
-        this.connection = connection;
-    }
-
-    set connection(conn){
-        if (this._connection instanceof Connection) {
-            gpgme_error('CONN_ALREADY_CONNECTED');
-        } else if (conn instanceof Connection ) {
-            this._connection = conn;
-        }
-    }
-
-    get connection(){
-        if (!this._data.fingerprint){
-            return gpgme_error('KEY_INVALID');
-        }
-        if (!this._connection instanceof Connection){
-            return gpgme_error('CONN_NO_CONNECT');
-        } else {
-            return this._connection;
-        }
     }
 
     set fingerprint(fpr){
@@ -219,7 +188,8 @@ export class GPGME_Key {
             let msg = createMessage('keylist');
             msg.setParameter('sigs', true);
             msg.setParameter('keys', me._data.fingerprint);
-            me.connection.post(msg).then(function(result){
+            console.log(msg);
+            msg.post().then(function(result){
                 if (result.keys.length === 1){
                     me.setKeydata(result.keys[0]);
                     resolve(me);
index 80792f7..9abb9ec 100644 (file)
@@ -22,23 +22,9 @@ import {createMessage} from './Message'
 import {GPGME_Key} from './Key'
 import { isFingerprint } from './Helpers';
 import { gpgme_error } from './Errors';
-import { Connection } from './Connection';
 
 export class GPGME_Keyring {
-    constructor(connection){
-        this.connection = connection;
-    }
-
-    set connection(connection){
-        if (!this._connection && connection instanceof Connection){
-            this._connection = connection;
-        }
-    }
-    get connection(){
-        if (this._connection instanceof Connection){
-            return this._connection;
-        }
-        return gpgme_error('CONN_NO_CONNECT');
+    constructor(){
     }
 
     /**
@@ -58,7 +44,7 @@ export class GPGME_Keyring {
             if (include_secret){
                 msg.setParameter('with-secret', true);
             }
-            me.connection.post(msg).then(function(result){
+            msg.post().then(function(result){
                 let fpr_list = [];
                 let resultset = [];
                 if (!Array.isArray(result.keys)){
@@ -68,7 +54,7 @@ export class GPGME_Keyring {
                     fpr_list = result.keys;
                 }
                 for (let i=0; i < fpr_list.length; i++){
-                    let newKey = new GPGME_Key(fpr_list[i], me._connection);
+                    let newKey = new GPGME_Key(fpr_list[i]);
                     if (newKey instanceof GPGME_Key){
                         resultset.push(newKey);
                     }
index 932212a..5664f72 100644 (file)
@@ -19,6 +19,7 @@
  */
 import { permittedOperations } from './permittedOperations'
 import { gpgme_error } from './Errors'
+import { Connection } from './Connection';
 
 export function createMessage(operation){
     if (typeof(operation) !== 'string'){
@@ -193,4 +194,21 @@ export class GPGME_Message {
         }
 
     }
+
+    post(){
+        let me = this;
+        return new Promise(function(resolve, reject) {
+            if (me.isComplete === true) {
+                let conn  = new Connection;
+                conn.post(me).then(function(response) {
+                    resolve(response);
+                }, function(reason) {
+                    reject(gpgme_error('GNUPG_ERROR', reason));
+                });
+            }
+            else {
+                reject(gpgme_error('MSG_INCOMPLETE'));
+            }
+        });
+    }
 }
index c182c17..88a91a6 100644 (file)
@@ -18,7 +18,6 @@
  * SPDX-License-Identifier: LGPL-2.1+
  */
 
-import {Connection} from "./Connection"
 import {GPGME_Message, createMessage} from './Message'
 import {toKeyIdArray} from "./Helpers"
 import { gpgme_error } from "./Errors"
@@ -29,31 +28,20 @@ export class GpgME {
      * initializes GpgME by opening a nativeMessaging port
      * TODO: add configuration
      */
-    constructor(connection){
-        this.connection = connection;
+    constructor(config){ //TODO config not parsed
+        this._config = config;
     }
 
-    set connection(conn){
-        if (this._connection instanceof Connection){
-            gpgme_error('CONN_ALREADY_CONNECTED');
-        } else if (conn instanceof Connection){
-            this._connection = conn;
-        } else {
-            gpgme_error('PARAM_WRONG');
-        }
-    }
-
-    get connection(){
-        return this._connection;
-    }
-
-    set Keyring(keyring){
+   set Keyring(keyring){
         if (keyring && keyring instanceof GPGME_Keyring){
             this._Keyring = keyring;
         }
     }
 
     get Keyring(){
+        if (!this._Keyring){
+            this._Keyring = new GPGME_Keyring;
+        }
         return this._Keyring;
     }
 
@@ -81,7 +69,7 @@ export class GpgME {
             msg.setParameter('throw-keyids', true);
         };
         if (msg.isComplete === true){
-            return this.connection.post(msg);
+            return msg.post();
         } else {
             return Promise.reject(gpgme_error('MSG_INCOMPLETE'));
         }
@@ -110,7 +98,7 @@ export class GpgME {
             return Promise.reject(msg);
         }
         putData(msg, data);
-        return this.connection.post(msg);
+        return msg.post();
 
     }
 
@@ -135,7 +123,7 @@ export class GpgME {
         }
         let me = this;
         return new Promise(function(resolve,reject) {
-            me.connection.post(msg).then( function(message) {
+            msg.post().then( function(message) {
                 if (mode === 'clearsign'){
                     resolve({
                         data: message.data}
@@ -174,20 +162,7 @@ export class GpgME {
             // TBD
         }
         if (msg.isComplete === true){
-            this.connection.post(msg).then(function(success){
-                // TODO: it seems that there is always errors coming back:
-            }, function(error){
-                switch (error.msg){
-                case 'ERR_NO_ERROR':
-                    return Promise.resolve('okay'); //TBD
-                default:
-                    return Promise.reject(gpgme_error('TODO') ); //
-                    // INV_VALUE,
-                    // GPG_ERR_NO_PUBKEY,
-                    // GPG_ERR_AMBIGUOUS_NAME,
-                    // GPG_ERR_CONFLICT
-                }
-            });
+            return msg.post();
         } else {
             return Promise.reject(gpgme_error('MSG_INCOMPLETE'));
         }
index 7f969fe..220a698 100644 (file)
@@ -37,7 +37,7 @@ function init(config){
         connection.checkConnection(false).then(
             function(result){
                 if (result === true) {
-                    resolve(new GpgME(connection, _conf));
+                    resolve(new GpgME(_conf));
                 } else {
                     reject(gpgme_error('CONN_NO_CONNECT'));
                 }
index bb06309..9830a2c 100644 (file)
@@ -47,7 +47,6 @@ function unittests (){
                 expect(answer.info).to.be.an('Array');
                 expect(conn0.disconnect).to.be.a('function');
                 expect(conn0.post).to.be.a('function');
-                conn0.disconnect();
                 done();
             });
 
@@ -170,15 +169,11 @@ function unittests (){
     describe('GPGME_Key', function(){
 
         it('correct Key initialization', function(){
-            let conn = new Connection;
-            let key = createKey(kp.validKeyFingerprint, conn);
+            let key = createKey(kp.validKeyFingerprint);
             expect(key).to.be.an.instanceof(GPGME_Key);
-            expect(key.connection).to.be.an.instanceof(Connection);
-            conn.disconnect();
         });
         it('Key has data after a first refresh', function(done) {
-            let conn = new Connection;
-            let key = createKey(kp.validKeyFingerprint, conn);
+            let key = createKey(kp.validKeyFingerprint);
             key.refreshKey().then(function(key2){
                 expect(key2).to.be.an.instanceof(GPGME_Key);
                 expect(key2.get).to.be.a('function');
@@ -192,74 +187,42 @@ function unittests (){
                     key2.get('fingerprint')).to.equal(kp.validKeyFingerprint);
                 expect(
                     key2.get('fingerprint')).to.equal(key.fingerprint);
-                conn.disconnect();
                 done();
             });
         });
 
         it('Non-cached key async data retrieval', function (done){
-            let conn = new Connection;
-            let key = createKey(kp.validKeyFingerprint, conn);
+            let key = createKey(kp.validKeyFingerprint);
             key.get('can_authenticate',false).then(function(result){
                 expect(result).to.be.a('boolean');
-                conn.disconnect();
                 done();
             });
         })
 
         it('Querying non-existing Key returns an error', function(done) {
-            let conn = new Connection;
-            let key = createKey(kp.invalidKeyFingerprint, conn);
+            let key = createKey(kp.invalidKeyFingerprint);
             key.refreshKey().then(function(){},
                 function(error){
                     expect(error).to.be.an.instanceof(Error);
                     expect(error.code).to.equal('KEY_NOKEY');
-                    conn.disconnect();
-                    done();
-            });
-        });
-
-
-        it('Key can use the connection', function(done){
-            let conn = new Connection;
-            let key = createKey(hp.validFingerprint, conn);
-            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;
-                    conn.disconnect();
                     done();
-                });
             });
         });
 
         it('createKey returns error if parameters are wrong', function(){
-            let conn = new Connection;
             for (let i=0; i< 4; i++){
-                let key0 = createKey(wp.four_invalid_params[i], conn);
-
+                let key0 = createKey(wp.four_invalid_params[i]);
                 expect(key0).to.be.an.instanceof(Error);
                 expect(key0.code).to.equal('PARAM_WRONG');
             }
-            for (let i=0; i< 4; i++){
-                let key0 = createKey(
-                    hp.validFingerprint, wp.four_invalid_params[i]);
-
-                expect(key0).to.be.an.instanceof(Error);
-                expect(key0.code).to.equal('PARAM_WRONG');
-            }
-            conn.disconnect();
         });
 
         it('malformed GPGME_Key cannot be used', function(){
-            let conn = new Connection;
             for (let i=0; i < 4; i++){
-                let key = new GPGME_Key(wp.four_invalid_params[i], conn);
+                let key = new GPGME_Key(wp.four_invalid_params[i]);
                 expect(key.fingerprint).to.be.an.instanceof(Error);
                 expect(key.fingerprint.code).to.equal('KEY_INVALID');
             }
-            conn.disconnect();
         });
 
         // TODO: tests for subkeys
@@ -269,27 +232,18 @@ function unittests (){
 
     describe('GPGME_Keyring', function(){
 
-        it('correct initialization', function(){
-            let conn = new Connection;
-            let keyring = new GPGME_Keyring(conn);
-
+        it('correct Keyring initialization', function(){
+            let keyring = new GPGME_Keyring;
             expect(keyring).to.be.an.instanceof(GPGME_Keyring);
-            expect(keyring.connection).to.be.an.instanceof(Connection);
             expect(keyring.getKeys).to.be.a('function');
             expect(keyring.getSubset).to.be.a('function');
         });
 
-        it('Keyring should return errors if not connected', function(){
+        it('correct initialization', 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');
-            // not yet implemented:
-            // keyring.getKeys().then(
-                // function(result){},
-                //function(reject){
-                    // expect(reject).to.be.an.instanceof(Error);
-                    // done();
+            expect(keyring.getKeys).to.be.a('function');
+            expect(keyring.getSubset).to.be.a('function');
         });
             //TODO not yet implemented:
             //  getKeys(pattern, include_secret) //note: pattern can be null