Merge pull request #7385 from vector-im/dbkr/wasm

Support WebAssembly version of Olm
This commit is contained in:
David Baker 2018-10-25 15:58:24 +01:00 committed by GitHub
commit 9b80aa76ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 60 deletions

View file

@ -146,7 +146,7 @@
"webpack-dev-server": "^3.1.9"
},
"optionalDependencies": {
"olm": "https://matrix.org/packages/npm/olm/olm-2.2.1.tgz"
"olm": "https://matrix.org/packages/npm/olm/olm-3.0.0.tgz"
},
"build": {
"appId": "im.riot.app",

View file

@ -57,6 +57,11 @@ const COPY_LIST = [
["res/themes/**", "webapp/themes"],
["node_modules/emojione/assets/svg/*", "webapp/emojione/svg/"],
["node_modules/emojione/assets/png/*", "webapp/emojione/png/"],
// XXX: This is tied quite heavily to the matching olm.js so it really should be
// in the bundle dir with the js to avoid caching issues giving us wasm that
// doesn't match our js, but I cannot find any way to get webpack to do this.
["node_modules/olm/olm.wasm", "webapp", { directwatch: 1 }],
["node_modules/olm/olm_legacy.js", "webapp", { directwatch: 1 }],
["./config.json", "webapp", { directwatch: 1 }],
];

View file

@ -54,6 +54,8 @@ import SettingsStore, {SettingLevel} from "matrix-react-sdk/lib/settings/Setting
import Tinter from 'matrix-react-sdk/lib/Tinter';
import SdkConfig from "matrix-react-sdk/lib/SdkConfig";
import Olm from 'olm';
import rageshake from "matrix-react-sdk/lib/rageshake/rageshake";
import CallHandler from 'matrix-react-sdk/lib/CallHandler';
@ -229,6 +231,8 @@ async function loadApp() {
window.addEventListener('hashchange', onHashChange);
await loadOlm();
await loadLanguage();
const fragparts = parseQsFromFragment(window.location);
@ -362,6 +366,42 @@ async function loadApp() {
}
}
function loadOlm() {
/* Load Olm. We try the WebAssembly version first, and then the legacy,
* asm.js version if that fails. For this reason we need to wait for this
* to finish before continuing to load the rest of the app. In future
* we could somehow pass a promise down to react-sdk and have it wait on
* that so olm can be loading in parallel with the rest of the app.
*
* We also need to tell the Olm js to look for its wasm file at the same
* level as index.html. It really should be in the same place as the js,
* ie. in the bundle directory, to avoid caching issues, but as far as I
* can tell this is completely impossible with webpack.
*/
return Olm.init({
locateFile: () => 'olm.wasm',
}).then(() => {
console.log("Using WebAssembly Olm");
}).catch((e) => {
console.log("Failed to load Olm: trying legacy version");
return new Promise((resolve, reject) => {
const s = document.createElement('script');
s.src = 'olm_legacy.js';
s.onload = resolve;
s.onerror = reject;
document.body.appendChild(s);
}).then(() => {
// Init window.Olm, ie. the one just loaded by the script tag,
// not 'Olm' which is still the failed wasm version.
return window.Olm.init();
}).then(() => {
console.log("Using legacy Olm");
}).catch((e) => {
console.log("Both WebAssembly and asm.js Olm failed!", e);
});
});
}
async function loadLanguage() {
const prefLang = SettingsStore.getValue("language", null, /*excludeDefault=*/true);
let langs = [];

View file

@ -1,41 +0,0 @@
/*
Copyright 2016 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* a very thin shim for loading olm.js: just sets the global OLM_OPTIONS and
* requires the actual olm.js library.
*
* olm.js reads global.OLM_OPTIONS and defines global.Olm. The latter is fine for us,
* but we need to prepare the former.
*
* We can't use webpack's definePlugin to do this, because we tell webpack not
* to parse olm.js. We also can't put this code in index.js, because olm and
* index.js are loaded in parallel, and we need to make sure OLM_OPTIONS is set
* before olm.js is loaded.
*/
/* total_memory must be a power of two, and at least twice the stack.
*
* We don't need a lot of stack, but we do need about 128K of heap to encrypt a
* 64K event (enough to store the ciphertext and the plaintext, bearing in mind
* that the plaintext can only be 48K because base64). We also have about 36K
* of statics. So let's have 256K of memory.
*/
global.OLM_OPTIONS = {
TOTAL_STACK: 64*1024,
TOTAL_MEMORY: 256*1024,
};
require('olm/olm.js');

View file

@ -15,15 +15,6 @@ module.exports = {
"mobileguide": "./src/vector/mobile_guide/index.js",
// We ship olm.js as a separate lump of javascript. This makes it get
// loaded via a separate <script/> tag in index.html (which loads it
// into the browser global `Olm`, where js-sdk expects to find it).
//
// (we should probably make js-sdk load it asynchronously at some
// point, so that it doesn't block the pageload, but that is a separate
// problem)
"olm": "./src/vector/olm-loader.js",
// CSS themes
"theme-light": "./node_modules/matrix-react-sdk/res/themes/light/css/light.scss",
"theme-dark": "./node_modules/matrix-react-sdk/res/themes/dark/css/dark.scss",
@ -171,12 +162,3 @@ module.exports = {
inline: false,
},
};
// olm is an optional dependency. Ignore it if it's not installed, to avoid a
// scary-looking error.
try {
require('olm');
} catch (e) {
console.log("Olm is not installed; not shipping it");
delete(module.exports.entry["olm"]);
}