Merge branch 'master' into develop

# Conflicts:
#	release-notes.md
This commit is contained in:
antelle 2019-10-16 22:49:45 +02:00
commit 7a22746f67
8 changed files with 140 additions and 87 deletions

View File

@ -100,9 +100,9 @@ class StorageWebDav extends StorageBase {
const that = this; const that = this;
this._request( this._request(
{ {
...saveOpts,
op: 'Save:stat', op: 'Save:stat',
method: 'HEAD', method: 'HEAD'
...saveOpts
}, },
(err, xhr, stat) => { (err, xhr, stat) => {
let useTmpPath = this.appSettings.webdavSaveMethod !== 'put'; let useTmpPath = this.appSettings.webdavSaveMethod !== 'put';
@ -120,12 +120,12 @@ class StorageWebDav extends StorageBase {
if (useTmpPath) { if (useTmpPath) {
that._request( that._request(
{ {
...saveOpts,
op: 'Save:put', op: 'Save:put',
method: 'PUT', method: 'PUT',
path: tmpPath, path: tmpPath,
data, data,
nostat: true, nostat: true
...saveOpts
}, },
err => { err => {
if (err) { if (err) {
@ -133,17 +133,17 @@ class StorageWebDav extends StorageBase {
} }
that._request( that._request(
{ {
...saveOpts,
op: 'Save:stat', op: 'Save:stat',
method: 'HEAD', method: 'HEAD'
...saveOpts
}, },
(err, xhr, stat) => { (err, xhr, stat) => {
if (err) { if (err) {
that._request({ that._request({
...saveOpts,
op: 'Save:delete', op: 'Save:delete',
method: 'DELETE', method: 'DELETE',
path: tmpPath, path: tmpPath
...saveOpts
}); });
return cb(err, xhr, stat); return cb(err, xhr, stat);
} }
@ -156,10 +156,10 @@ class StorageWebDav extends StorageBase {
rev rev
); );
that._request({ that._request({
...saveOpts,
op: 'Save:delete', op: 'Save:delete',
method: 'DELETE', method: 'DELETE',
path: tmpPath, path: tmpPath
...saveOpts
}); });
return cb({ revConflict: true }, xhr, stat); return cb({ revConflict: true }, xhr, stat);
} }
@ -176,6 +176,7 @@ class StorageWebDav extends StorageBase {
} }
that._request( that._request(
{ {
...saveOpts,
op: 'Save:move', op: 'Save:move',
method: 'MOVE', method: 'MOVE',
path: tmpPath, path: tmpPath,
@ -183,8 +184,7 @@ class StorageWebDav extends StorageBase {
headers: { headers: {
Destination: encodeURI(movePath), Destination: encodeURI(movePath),
'Overwrite': 'T' 'Overwrite': 'T'
}, }
...saveOpts
}, },
err => { err => {
if (err) { if (err) {
@ -192,9 +192,9 @@ class StorageWebDav extends StorageBase {
} }
that._request( that._request(
{ {
...saveOpts,
op: 'Save:stat', op: 'Save:stat',
method: 'HEAD', method: 'HEAD'
...saveOpts
}, },
(err, xhr, stat) => { (err, xhr, stat) => {
cb(err, xhr, stat); cb(err, xhr, stat);
@ -209,11 +209,11 @@ class StorageWebDav extends StorageBase {
} else { } else {
that._request( that._request(
{ {
...saveOpts,
op: 'Save:put', op: 'Save:put',
method: 'PUT', method: 'PUT',
data, data,
nostat: true, nostat: true
...saveOpts
}, },
err => { err => {
if (err) { if (err) {
@ -221,9 +221,9 @@ class StorageWebDav extends StorageBase {
} }
that._request( that._request(
{ {
...saveOpts,
op: 'Save:stat', op: 'Save:stat',
method: 'HEAD', method: 'HEAD'
...saveOpts
}, },
(err, xhr, stat) => { (err, xhr, stat) => {
cb(err, xhr, stat); cb(err, xhr, stat);

View File

@ -16,6 +16,7 @@ const Features = {
!isDesktop && !isDesktop &&
!/^http(s?):\/\/((localhost:8085)|((app|beta)\.keeweb\.info))/.test(location.href), !/^http(s?):\/\/((localhost:8085)|((app|beta)\.keeweb\.info))/.test(location.href),
needFixClicks: /Edge\/14/.test(navigator.appVersion), needFixClicks: /Edge\/14/.test(navigator.appVersion),
canUseWasmInWebWorker: !isDesktop && !/Chrome/.test(navigator.appVersion),
supportsTitleBarStyles() { supportsTitleBarStyles() {
return this.isMac; return this.isMac;

View File

@ -1,5 +1,6 @@
import kdbxweb from 'kdbxweb'; import kdbxweb from 'kdbxweb';
import { Logger } from 'util/logger'; import { Logger } from 'util/logger';
import { Features } from 'util/features';
const logger = new Logger('argon2'); const logger = new Logger('argon2');
@ -43,69 +44,116 @@ const KdbxwebInit = {
totalMemory totalMemory
); );
const memoryDecl = `var wasmMemory=new WebAssembly.Memory({initial:${initialMemory},maximum:${totalMemory}});`; if (Features.canUseWasmInWebWorker) {
const moduleDecl = const memoryDecl = `var wasmMemory=new WebAssembly.Memory({initial:${initialMemory},maximum:${totalMemory}});`;
'var Module={' + const moduleDecl =
'wasmJSMethod: "native-wasm",' + 'var Module={' +
'wasmBinary: Uint8Array.from(atob("' + 'wasmJSMethod: "native-wasm",' +
wasmBinaryBase64 + 'wasmBinary: Uint8Array.from(atob("' +
'"), c => c.charCodeAt(0)),' + wasmBinaryBase64 +
'print(...args) { postMessage({op:"log",args}) },' + '"), c => c.charCodeAt(0)),' +
'printErr(...args) { postMessage({op:"log",args}) },' + 'print(...args) { postMessage({op:"log",args}) },' +
'postRun:' + 'printErr(...args) { postMessage({op:"log",args}) },' +
this.workerPostRun.toString() + 'postRun:' +
',' + this.workerPostRun.toString() +
'calcHash:' + ',' +
this.calcHash.toString() + 'calcHash:' +
',' + this.calcHash.toString() +
'wasmMemory:wasmMemory,' + ',' +
'buffer:wasmMemory.buffer,' + 'wasmMemory:wasmMemory,' +
'TOTAL_MEMORY:' + 'buffer:wasmMemory.buffer,' +
initialMemory * WASM_PAGE_SIZE + 'TOTAL_MEMORY:' +
'}'; initialMemory * WASM_PAGE_SIZE +
const script = argon2LoaderCode.replace(/^var Module.*?}/, memoryDecl + moduleDecl); '}';
const blob = new Blob([script], { type: 'application/javascript' }); const script = argon2LoaderCode.replace(
const objectUrl = URL.createObjectURL(blob); /^var Module.*?}/,
const worker = new Worker(objectUrl); memoryDecl + moduleDecl
const onMessage = e => { );
switch (e.data.op) { const blob = new Blob([script], { type: 'application/javascript' });
case 'log': const objectUrl = URL.createObjectURL(blob);
logger.debug(...e.data.args); const worker = new Worker(objectUrl);
break; const onMessage = e => {
case 'postRun': switch (e.data.op) {
logger.debug('WebAssembly runtime loaded', logger.ts(ts)); case 'log':
URL.revokeObjectURL(objectUrl); logger.debug(...e.data.args);
break;
case 'postRun':
logger.debug(
'WebAssembly runtime loaded (web worker)',
logger.ts(ts)
);
URL.revokeObjectURL(objectUrl);
clearTimeout(loadTimeout);
worker.removeEventListener('message', onMessage);
this.runtimeModule = {
hash(args) {
return new Promise((resolve, reject) => {
worker.postMessage(args);
const onHashMessage = e => {
worker.removeEventListener(
'message',
onHashMessage
);
worker.terminate();
KdbxwebInit.runtimeModule = null;
if (!e.data || e.data.error || !e.data.hash) {
const ex =
(e.data && e.data.error) ||
'unexpected error';
logger.error('Worker error', ex);
reject(ex);
} else {
resolve(e.data.hash);
}
};
worker.addEventListener('message', onHashMessage);
});
}
};
resolve(this.runtimeModule);
break;
default:
logger.error('Unknown message', e.data);
URL.revokeObjectURL(objectUrl);
reject('Load error');
}
};
worker.addEventListener('message', onMessage);
} else {
// Chrome and Electron crash if we use WASM in WebWorker
// see https://github.com/keeweb/keeweb/issues/1263
const wasmMemory = new WebAssembly.Memory({
initial: initialMemory,
maximum: totalMemory
});
global.Module = {
wasmJSMethod: 'native-wasm',
wasmBinary: Uint8Array.from(atob(wasmBinaryBase64), c => c.charCodeAt(0)),
print(...args) {
logger.debug(...args);
},
printErr(...args) {
logger.debug(...args);
},
postRun: () => {
logger.debug('WebAssembly runtime loaded (main thread)', logger.ts(ts));
clearTimeout(loadTimeout); clearTimeout(loadTimeout);
worker.removeEventListener('message', onMessage); resolve({
this.runtimeModule = { hash: args => {
hash(args) { const hash = this.calcHash(global.Module, args);
return new Promise((resolve, reject) => { global.Module.unloadRuntime();
worker.postMessage(args); global.Module = undefined;
const onHashMessage = e => { return Promise.resolve(hash);
worker.removeEventListener('message', onHashMessage);
worker.terminate();
KdbxwebInit.runtimeModule = null;
if (!e.data || e.data.error || !e.data.hash) {
const ex =
(e.data && e.data.error) || 'unexpected error';
logger.error('Worker error', ex);
reject(ex);
}
resolve(e.data.hash);
};
worker.addEventListener('message', onHashMessage);
});
} }
}; });
resolve(this.runtimeModule); },
break; wasmMemory,
default: buffer: wasmMemory.buffer,
logger.error('Unknown message', e.data); TOTAL_MEMORY: initialMemory * WASM_PAGE_SIZE
URL.revokeObjectURL(objectUrl); };
reject('Load error'); // eslint-disable-next-line no-eval
} eval(argon2LoaderCode);
}; }
worker.addEventListener('message', onMessage);
} catch (err) { } catch (err) {
reject(err); reject(err);
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "KeeWeb", "name": "KeeWeb",
"version": "1.11.9", "version": "1.11.10",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@ -1,6 +1,6 @@
{ {
"name": "KeeWeb", "name": "KeeWeb",
"version": "1.11.9", "version": "1.11.10",
"description": "Free cross-platform password manager compatible with KeePass", "description": "Free cross-platform password manager compatible with KeePass",
"main": "main.js", "main": "main.js",
"homepage": "https://keeweb.info", "homepage": "https://keeweb.info",

8
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "keeweb", "name": "keeweb",
"version": "1.11.9", "version": "1.11.10",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -1369,9 +1369,9 @@
} }
}, },
"argon2-browser": { "argon2-browser": {
"version": "1.11.1", "version": "1.12.0",
"resolved": "https://registry.npmjs.org/argon2-browser/-/argon2-browser-1.11.1.tgz", "resolved": "https://registry.npmjs.org/argon2-browser/-/argon2-browser-1.12.0.tgz",
"integrity": "sha512-C+WsBLSkwQExkDYB7vriugrBTXq2z+fTRDlGWqr2zm89TaKo7zYtSGARMgoBxpDnmNNzduNlZJmpY2j0Dp7ZOQ==" "integrity": "sha512-qdEW311acXGGLTjslqO5f7cKG3foP6QUkeuav9au00aRY/B5AvNrqAVlL47a2MUdr6i7dx8Xp+5OreRGoXvCgQ=="
}, },
"argparse": { "argparse": {
"version": "1.0.10", "version": "1.0.10",

View File

@ -1,6 +1,6 @@
{ {
"name": "keeweb", "name": "keeweb",
"version": "1.11.9", "version": "1.11.10",
"description": "Free cross-platform password manager compatible with KeePass", "description": "Free cross-platform password manager compatible with KeePass",
"main": "Gruntfile.js", "main": "Gruntfile.js",
"private": true, "private": true,
@ -14,7 +14,7 @@
"@babel/plugin-external-helpers": "^7.2.0", "@babel/plugin-external-helpers": "^7.2.0",
"@babel/plugin-proposal-class-properties": "^7.5.5", "@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/preset-env": "^7.6.2", "@babel/preset-env": "^7.6.2",
"argon2-browser": "1.11.1", "argon2-browser": "1.12.0",
"autoprefixer": "^9.6.1", "autoprefixer": "^9.6.1",
"babel-cli": "^6.26.0", "babel-cli": "^6.26.0",
"babel-eslint": "^10.0.3", "babel-eslint": "^10.0.3",

View File

@ -9,6 +9,10 @@ Release notes
`+` #480: option to launch the app minimized `+` #480: option to launch the app minimized
`-` fix #1273: untranslated menu items `-` fix #1273: untranslated menu items
##### v1.11.10 (2019-10-16)
`-` fix #1305: WebDAV issues
`-` fix #1263: desktop apps crashes when argon2 is used
##### v1.11.9 (2019-10-13) ##### v1.11.9 (2019-10-13)
`-` fix #1300: selecting auto-type sequence items issues `-` fix #1300: selecting auto-type sequence items issues
`-` fix #1290: generator popup positioning in custom themes `-` fix #1290: generator popup positioning in custom themes