js: created TestExtension and smaller fixes

--

* Extensions:

  - Moved testapplication to Demoextension
  - Created BrowserTestExtension.
    Includes mocha and chai. For running tests that cannot be run
    outside a WebExtension

  Both Extensions can be found zipped in build/extensions after
  running build_extensions.sh

* Code changes:
  - src/Config: Place for the configuration
  - small fixes raised during testing in Keyring.js, Message.js,
  - src/gpgmejs_openpgpjs.js don't offer direct GpgME object to the
    outside, as it only causes confusion
  - index.js init() now checks the config for validity

* Tests:
  - Reordered tests in test/.
  - Input values are now in a separate file which may be of use for
    bulk testing

* moved the build directory from dist to build
This commit is contained in:
Maximilian Krambach 2018-04-26 17:13:34 +02:00
parent 3685913bf5
commit 1f7b19512c
28 changed files with 429 additions and 143 deletions

View File

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="libs/mocha.css" rel="stylesheet" />
</head>
<body>
<h3>Browsertest</h3>
<div id="mocha"></div>
<!-- load unit tests -->
<script src="libs/mocha.js"></script>
<script src="libs/chai.js"></script>
<script src="setup_testing.js"></script>
<script src="libs/gpgmejs.bundle.js"></script>
<script src="tests/inputvalues.js"></script>
<!-- insert tests here-->
<script src="tests/startup.js"></script>
<script src="tests/encryptTest.js"></script>
<!-- run tests -->
<script src="runbrowsertest.js"></script>
</body>
</html>

View File

@ -0,0 +1,13 @@
{
"manifest_version": 2,
"name": "Browsertests for gpgmejs",
"description": "Run the browsertests.",
"version": "0.1",
"content_security_policy": "default-src 'self' filesystem:",
"browser_action": {
"default_icon": "testicon.png",
"default_popup": "popup.html"
},
"permissions": ["nativeMessaging", "activeTab"]
}

View File

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="popup.js"></script>
</head>
<body>
</body>
</html>

View File

@ -0,0 +1,44 @@
/* 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+
*/
/* 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+
*/
document.addEventListener('DOMContentLoaded', function() {
chrome.tabs.create({
url: './browsertest.html'
});
});

View File

@ -0,0 +1,21 @@
/* 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+
*/
mocha.run();

View File

@ -0,0 +1,22 @@
/* 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+
*/
mocha.setup('bdd');
var expect = chai.expect;
chai.config.includeStack = true;

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,28 @@
/* 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+
*/
var inputvalues = {
encrypt: {
good:{
data : 'Hello World.',
keyid : 'CDC3A2B2860625CCBFC5A5A9FC6D1B604967FC40'
}
}
};

View File

@ -0,0 +1,51 @@
/* 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('GPGME context', function(){
it('Starting a GpgME instance', function(done){
Gpgmejs.init().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();
}, function(err){
done(err);
});
});
it('Starting an openpgp mode GPGME instance', function(done){
Gpgmejs.init({api_style:"gpgme_openpgpjs"}).then(
function(context){
console.log(context);
done();
// expect(context).to.be.an('object');
// expect(context.connection).to.be.undefined;
// expect(context.Keyring).to.be.an('object');
// expect(context.encrypt).to.be.a('function');
// expect(context.decrypt).to.be.a('function');
// done();
}, function(err){
done(err);
});
});
});

View File

@ -8,8 +8,8 @@ receiving an answer
replicating Openpgpjs API:
[*] Message handling (encrypt, verify, sign)
[x] encrypt
[*] Message handling (encrypt, decrypt verify, sign)
[x] encrypt, decrypt
[ ] verify
[ ] sign
[*] Key handling (import/export, modifying, status queries)
@ -23,6 +23,6 @@ Communication with other implementations
Management:
[*] Define the gpgme interface
[ ] check Permissions (e.g. csp) for the different envs
[x] check Permissions (e.g. csp) for the different envs
[X] agree on license
[ ] tests
[*] tests

View File

@ -1,9 +1,3 @@
- Checklist for build/install:
browsers' manifests (see README) need allowedextension added, and the path set
manifest.json/ csp needs adaption
/dist should be built which is used by the example app.
csp in manifest.json MUST NOT contain "unsafe-eval" in production!

View File

@ -20,6 +20,6 @@
*/
document.addEventListener('DOMContentLoaded', function() {
chrome.tabs.create({
url: './ui2.html'
url: './uimainui.html'
});
});

View File

@ -3,8 +3,8 @@
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="ui.css"/>
<script src="dist/gpgmejs.bundle.js"></script>
<script src="testapplication.js"></script>
<script src="gpgmejs.bundle.js"></script>
<script src="maindemo.js"></script>
</head>
<body>
<ul>

View File

@ -2,13 +2,13 @@
"manifest_version": 2,
"name": "gpgme-json with native Messaging",
"description": "This should be able to encrypt a text using gpgme-json",
"description": "A simple demo application",
"version": "0.1",
"content_security_policy": "default-src 'self' 'unsafe-eval' filesystem:",
"content_security_policy": "default-src 'self' filesystem:",
"browser_action": {
"default_icon": "testicon.png",
"default_title": "gpgme.js",
"default_popup": "testapplication_index.html"
"default_popup": "popup.html"
},
"permissions": ["nativeMessaging", "activeTab"]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

14
lang/js/build_extensions.sh Executable file
View File

@ -0,0 +1,14 @@
#/!bin/bash
npx webpack --config webpack.conf.js
mkdir -p BrowserTestExtension/libs
cp node_modules/chai/chai.js \
node_modules/mocha/mocha.css \
node_modules/mocha/mocha.js \
build/gpgmejs.bundle.js BrowserTestExtension/libs
mkdir -p build/extensions
zip -r build/extensions/browsertest.zip BrowserTestExtension
mkdir -p DemoExtension/libs
cp build/gpgmejs.bundle.js DemoExtension/libs
zip -r build/extensions/demoextension.zip DemoExtension

31
lang/js/src/Config.js Normal file
View File

@ -0,0 +1,31 @@
/* 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+
*/
export const availableConf = {
api_style: ['gpgme', 'gpgme_openpgpjs'],
null_expire_is_never: [true, false],
unconsidered_params: ['warn','reject', 'ignore'],
};
export const defaultConf = {
api_style: 'gpgme',
null_expire_is_never: false,
unconsidered_params: 'reject',
};

View File

@ -22,6 +22,7 @@ import {createMessage} from './Message'
import {GPGME_Key} from './Key'
import { isFingerprint, isLongId } from './Helpers';
import { gpgme_error } from './Errors';
import { Connection } from './Connection';
export class GPGME_Keyring {
constructor(connection){

View File

@ -36,7 +36,7 @@ export function createMessage(operation){
* ./permittedOperations.
* @param {String} operation
*/
class GPGME_Message {
export class GPGME_Message {
//TODO getter
constructor(operation){

View File

@ -50,18 +50,12 @@
if (!this._GPGME){
this._GpgME = new GpgME(connection, config);
}
if (!this._Keyring){
this._Keyring = new GPGME_Keyring_openpgpmode(connection);
if (!this._keyring){
this._keyring = new GPGME_Keyring_openpgpmode(connection);
}
}
}
get GpgME(){
if (this._GpGME){
return this._GpGME;
}
}
/**
* Encrypt Message
* Supported:
@ -115,7 +109,7 @@
return Promise.reject(GPMGEJS_Error('NOT_IMPLEMENTED'));
}
}
return this.GpgME.encrypt(data, translateKeyInput(publicKeys), wildcard);
return this._GpgME.encrypt(data, translateKeyInput(publicKeys), wildcard);
}
/** Decrypt Message
@ -152,7 +146,7 @@
return Promise.reject(GPMGEJS_Error('NOT_IMPLEMENTED'));
}
}
return this.GpgME.decrypt(message);
return this._GpgME.decrypt(message);
// TODO: translate between:
// openpgp:
// { data:Uint8Array|String,

View File

@ -22,16 +22,17 @@ import { GpgME } from "./gpgmejs";
import { gpgme_error } from "./Errors";
import { GpgME_openpgpmode } from "./gpgmejs_openpgpjs";
import { Connection } from "./Connection";
import { defaultConf, availableConf } from "./Config";
/**
* Initializes a nativeMessaging Connection and returns a GPGMEjs object
* @param {*} conf Configuration. TBD
* @param {Object} config Configuration. See Config.js for available parameters. Still TODO
*/
function init( config = {
api_style: 'gpgme', // | gpgme_openpgpjs
null_expire_is_never: true, // Boolean
unconsidered_params: 'warn'//'warn' || 'reject'
}){
function init(config){
let _conf = parseconfiguration(config);
if (_conf instanceof Error){
return Promise.reject(_conf);
}
return new Promise(function(resolve, reject){
let connection = new Connection;
// TODO: Delayed reaction is ugly. We need to listen to the port's
@ -39,10 +40,8 @@ function init( config = {
// disconnect if there is no successfull connection.
let delayedreaction = function(){
if (connection.isConnected === true){
let gpgme = null;
if (config.api_style && config.api_style === 'gpgme_openpgpjs'){
resolve(
new GpgME_openpgpmode(connection, config));
if (_conf.api_style && _conf.api_style === 'gpgme_openpgpjs'){
resolve(new GpgME_openpgpmode(connection, _conf));
} else {
resolve(new GpgME(connection));
}
@ -52,6 +51,31 @@ function init( config = {
};
setTimeout(delayedreaction, 5);
});
}
function parseconfiguration(config){
if (!config){
return defaultConf;
}
if ( typeof(config) !== 'object'){
return gpgme_error('PARAM_WRONG');
};
let result_config = defaultConf;
let conf_keys = Object.keys(config);
for (let i=0; i < conf_keys; i++){
if (availableConf.hasOwnProperty(conf_keys[i])){
let value = config[conf_keys[i]];
if (availableConf[conf_keys[i]].indexOf(value) < 0){
return gpgme_error('PARAM_WRONG');
} else {
result_config[conf_keys[i]] = value;
}
}
else {
return gpgme_error('PARAM_WRONG');
}
}
return result_config;
};
export default {

View File

@ -22,24 +22,9 @@ import { expect } from "../node_modules/chai/chai";
import { gpgme_error} from "../src/Errors";
import { GPGME_Key } from "../src/Key";
import { isLongId, isFingerprint, toKeyIdArray } from "../src/Helpers"
import { helper_params } from "./inputvalues";
const helper_params = {
validLongId: '0A0A0A0A0A0A0A0A',
validGPGME_Key: new GPGME_Key('ADDBC303B6D31026F5EB4591A27EABDF283121BB'),
validKeys: [new GPGME_Key('A1E3BC45BDC8E87B74F4392D53B151A1368E50F3'),
'ADDBC303B6D31026F5EB4591A27EABDF283121BB',
new GPGME_Key('EE17AEE730F88F1DE7713C54BBE0A4FF7851650A')],
validFingerprint: '9A9A7A7A8A9A9A7A7A8A9A9A7A7A8A9A9A7A7A8A',
invalidLongId: '9A9A7A7A8A9A9A7A7A8A',
invalidFingerprint: [{hello:'World'}],
invalidKeyArray: {curiosity:'uncat'},
invalidKeyArray_OneBad: [
new GPGME_Key('12AE9F3E41B33BF77DF52B6BE8EE1992D7909B08'),
'E1D18E6E994FA9FE9360Bx0E687B940FEFEB095A',
'3AEA7FE4F5F416ED18CEC63DD519450D9C0FAEE5'],
invalidErrorCode: 'Please type in all your passwords.'
}
function Helpertest(){
describe('Error Object handling', function(){
it('check the Timeout error', function(){
let test0 = gpgme_error('CONN_TIMEOUT');
@ -108,3 +93,5 @@ describe('Converting to Fingerprint', function(){
});
});
});
};
export default Helpertest;

View File

@ -21,10 +21,9 @@
import { expect } from "../node_modules/chai/chai";
import { GPGME_Message, createMessage } from "../src/Message";
const message_params = {
invalid_op_action : 'dance',
invalid_op_type : [234, 34, '<>'],
}
import { message_params } from "./inputvalues";
function Messagetest(){
describe('Message Object', function(){
describe('incorrect initialization', function(){
@ -40,3 +39,5 @@ describe('Message Object', function(){
});
});
});
};
export default Messagetest;

View File

@ -0,0 +1,29 @@
import {GPGME_Key} from "../src/Key"
export const helper_params = {
validLongId: '0A0A0A0A0A0A0A0A',
validGPGME_Key: new GPGME_Key('ADDBC303B6D31026F5EB4591A27EABDF283121BB'),
validKeys: [new GPGME_Key('A1E3BC45BDC8E87B74F4392D53B151A1368E50F3'),
'ADDBC303B6D31026F5EB4591A27EABDF283121BB',
new GPGME_Key('EE17AEE730F88F1DE7713C54BBE0A4FF7851650A')],
validFingerprint: '9A9A7A7A8A9A9A7A7A8A9A9A7A7A8A9A9A7A7A8A',
invalidLongId: '9A9A7A7A8A9A9A7A7A8A',
invalidFingerprint: [{hello:'World'}],
invalidKeyArray: {curiosity:'uncat'},
invalidKeyArray_OneBad: [
new GPGME_Key('12AE9F3E41B33BF77DF52B6BE8EE1992D7909B08'),
'E1D18E6E994FA9FE9360Bx0E687B940FEFEB095A',
'3AEA7FE4F5F416ED18CEC63DD519450D9C0FAEE5'],
invalidErrorCode: 'Please type in all your passwords.'
}
export const message_params = {
invalid_op_action : 'dance',
invalid_op_type : [234, 34, '<>'],
}
export default {
helper_params: helper_params,
message_params: message_params
}

View File

@ -26,7 +26,7 @@ module.exports = {
// mode: 'development',
mode: 'production',
output: {
path: path.resolve(__dirname, 'dist'),
path: path.resolve(__dirname, 'build'),
filename: 'gpgmejs.bundle.js',
libraryTarget: 'var',
libraryExport: 'default',