You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-29 16:43:09 +03:00
Support Olm with WebAssembly
wasm Olm has a new interface: it now has an init method that needs to be called and the promise it returns waited on before the Olm module is used. Support that, and allow Crypto etc to be imported whether Olm is enabled or not. Change whether olm is enabled to be async since now it will be unavailable if the async module init fails. Don't call getOlmVersion() until the Olm.init() is done.
This commit is contained in:
@@ -1,20 +1,23 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
import 'source-map-support/register';
|
import 'source-map-support/register';
|
||||||
|
import Crypto from '../../lib/crypto';
|
||||||
|
import expect from 'expect';
|
||||||
|
|
||||||
const sdk = require("../..");
|
const sdk = require("../..");
|
||||||
let Crypto;
|
|
||||||
if (sdk.CRYPTO_ENABLED) {
|
|
||||||
Crypto = require("../../lib/crypto");
|
|
||||||
}
|
|
||||||
|
|
||||||
import expect from 'expect';
|
|
||||||
|
|
||||||
describe("Crypto", function() {
|
describe("Crypto", function() {
|
||||||
if (!sdk.CRYPTO_ENABLED) {
|
if (!sdk.CRYPTO_ENABLED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
beforeEach(function(done) {
|
||||||
|
Olm.init().then(done);
|
||||||
|
});
|
||||||
|
|
||||||
it("Crypto exposes the correct olm library version", function() {
|
it("Crypto exposes the correct olm library version", function() {
|
||||||
|
console.log(Crypto);
|
||||||
expect(Crypto.getOlmVersion()[0]).toEqual(2);
|
expect(Crypto.getOlmVersion()[0]).toEqual(2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,14 +13,8 @@ import WebStorageSessionStore from '../../../../lib/store/session/webstorage';
|
|||||||
import MemoryCryptoStore from '../../../../lib/crypto/store/memory-crypto-store.js';
|
import MemoryCryptoStore from '../../../../lib/crypto/store/memory-crypto-store.js';
|
||||||
import MockStorageApi from '../../../MockStorageApi';
|
import MockStorageApi from '../../../MockStorageApi';
|
||||||
import testUtils from '../../../test-utils';
|
import testUtils from '../../../test-utils';
|
||||||
|
import OlmDevice from '../../../../lib/crypto/OlmDevice';
|
||||||
// Crypto and OlmDevice won't import unless we have global.Olm
|
import Crypto from '../../../../lib/crypto';
|
||||||
let OlmDevice;
|
|
||||||
let Crypto;
|
|
||||||
if (global.Olm) {
|
|
||||||
OlmDevice = require('../../../../lib/crypto/OlmDevice');
|
|
||||||
Crypto = require('../../../../lib/crypto');
|
|
||||||
}
|
|
||||||
|
|
||||||
const MatrixEvent = sdk.MatrixEvent;
|
const MatrixEvent = sdk.MatrixEvent;
|
||||||
const MegolmDecryption = algorithms.DECRYPTION_CLASSES['m.megolm.v1.aes-sha2'];
|
const MegolmDecryption = algorithms.DECRYPTION_CLASSES['m.megolm.v1.aes-sha2'];
|
||||||
@@ -69,7 +63,8 @@ describe("MegolmDecryption", function() {
|
|||||||
|
|
||||||
describe('receives some keys:', function() {
|
describe('receives some keys:', function() {
|
||||||
let groupSession;
|
let groupSession;
|
||||||
beforeEach(function() {
|
beforeEach(async function() {
|
||||||
|
await Olm.init();
|
||||||
groupSession = new global.Olm.OutboundGroupSession();
|
groupSession = new global.Olm.OutboundGroupSession();
|
||||||
groupSession.create();
|
groupSession.create();
|
||||||
|
|
||||||
@@ -98,7 +93,7 @@ describe("MegolmDecryption", function() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return event.attemptDecryption(mockCrypto).then(() => {
|
await event.attemptDecryption(mockCrypto).then(() => {
|
||||||
megolmDecryption.onRoomKeyEvent(event);
|
megolmDecryption.onRoomKeyEvent(event);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ const ContentHelpers = require("./content-helpers");
|
|||||||
import ReEmitter from './ReEmitter';
|
import ReEmitter from './ReEmitter';
|
||||||
import RoomList from './crypto/RoomList';
|
import RoomList from './crypto/RoomList';
|
||||||
|
|
||||||
|
import Crypto from './crypto';
|
||||||
|
import { isCryptoAvailable } from './crypto';
|
||||||
|
|
||||||
const LAZY_LOADING_MESSAGES_FILTER = {
|
const LAZY_LOADING_MESSAGES_FILTER = {
|
||||||
lazy_load_members: true,
|
lazy_load_members: true,
|
||||||
@@ -58,14 +60,7 @@ const LAZY_LOADING_SYNC_FILTER = {
|
|||||||
|
|
||||||
|
|
||||||
const SCROLLBACK_DELAY_MS = 3000;
|
const SCROLLBACK_DELAY_MS = 3000;
|
||||||
let CRYPTO_ENABLED = false;
|
let CRYPTO_ENABLED = isCryptoAvailable();
|
||||||
|
|
||||||
try {
|
|
||||||
var Crypto = require("./crypto");
|
|
||||||
CRYPTO_ENABLED = true;
|
|
||||||
} catch (e) {
|
|
||||||
console.warn("Unable to load crypto module: crypto will be disabled: " + e);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a Matrix Client. Only directly construct this if you want to use
|
* Construct a Matrix Client. Only directly construct this if you want to use
|
||||||
@@ -140,6 +135,8 @@ function MatrixClient(opts) {
|
|||||||
|
|
||||||
MatrixBaseApis.call(this, opts);
|
MatrixBaseApis.call(this, opts);
|
||||||
|
|
||||||
|
this.olmVersion = null; // Populated after initCrypto is done
|
||||||
|
|
||||||
this.reEmitter = new ReEmitter(this);
|
this.reEmitter = new ReEmitter(this);
|
||||||
|
|
||||||
this.store = opts.store || new StubStore();
|
this.store = opts.store || new StubStore();
|
||||||
@@ -192,10 +189,6 @@ function MatrixClient(opts) {
|
|||||||
|
|
||||||
this._forceTURN = opts.forceTURN || false;
|
this._forceTURN = opts.forceTURN || false;
|
||||||
|
|
||||||
if (CRYPTO_ENABLED) {
|
|
||||||
this.olmVersion = Crypto.getOlmVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
// List of which rooms have encryption enabled: separate from crypto because
|
// List of which rooms have encryption enabled: separate from crypto because
|
||||||
// we still want to know which rooms are encrypted even if crypto is disabled:
|
// we still want to know which rooms are encrypted even if crypto is disabled:
|
||||||
// we don't want to start sending unencrypted events to them.
|
// we don't want to start sending unencrypted events to them.
|
||||||
@@ -385,6 +378,14 @@ MatrixClient.prototype.setNotifTimelineSet = function(notifTimelineSet) {
|
|||||||
* successfully initialised.
|
* successfully initialised.
|
||||||
*/
|
*/
|
||||||
MatrixClient.prototype.initCrypto = async function() {
|
MatrixClient.prototype.initCrypto = async function() {
|
||||||
|
if (!isCryptoAvailable()) {
|
||||||
|
throw new Error(
|
||||||
|
`End-to-end encryption not supported in this js-sdk build: did ` +
|
||||||
|
`you remember to load the olm library?`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this._crypto) {
|
if (this._crypto) {
|
||||||
console.warn("Attempt to re-initialise e2e encryption on MatrixClient");
|
console.warn("Attempt to re-initialise e2e encryption on MatrixClient");
|
||||||
return;
|
return;
|
||||||
@@ -402,13 +403,6 @@ MatrixClient.prototype.initCrypto = async function() {
|
|||||||
// initialise the list of encrypted rooms (whether or not crypto is enabled)
|
// initialise the list of encrypted rooms (whether or not crypto is enabled)
|
||||||
await this._roomList.init();
|
await this._roomList.init();
|
||||||
|
|
||||||
if (!CRYPTO_ENABLED) {
|
|
||||||
throw new Error(
|
|
||||||
`End-to-end encryption not supported in this js-sdk build: did ` +
|
|
||||||
`you remember to load the olm library?`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const userId = this.getUserId();
|
const userId = this.getUserId();
|
||||||
if (userId === null) {
|
if (userId === null) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@@ -440,6 +434,9 @@ MatrixClient.prototype.initCrypto = async function() {
|
|||||||
|
|
||||||
await crypto.init();
|
await crypto.init();
|
||||||
|
|
||||||
|
this.olmVersion = Crypto.getOlmVersion();
|
||||||
|
|
||||||
|
|
||||||
// if crypto initialisation was successful, tell it to attach its event
|
// if crypto initialisation was successful, tell it to attach its event
|
||||||
// handlers.
|
// handlers.
|
||||||
crypto.registerEventHandlers(this);
|
crypto.registerEventHandlers(this);
|
||||||
|
|||||||
@@ -23,9 +23,6 @@ import IndexedDBCryptoStore from './store/indexeddb-crypto-store';
|
|||||||
* @module crypto/OlmDevice
|
* @module crypto/OlmDevice
|
||||||
*/
|
*/
|
||||||
const Olm = global.Olm;
|
const Olm = global.Olm;
|
||||||
if (!Olm) {
|
|
||||||
throw new Error("global.Olm is not defined");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// The maximum size of an event is 65K, and we base64 the content, so this is a
|
// The maximum size of an event is 65K, and we base64 the content, so this is a
|
||||||
|
|||||||
@@ -36,6 +36,12 @@ const DeviceList = require('./DeviceList').default;
|
|||||||
import OutgoingRoomKeyRequestManager from './OutgoingRoomKeyRequestManager';
|
import OutgoingRoomKeyRequestManager from './OutgoingRoomKeyRequestManager';
|
||||||
import IndexedDBCryptoStore from './store/indexeddb-crypto-store';
|
import IndexedDBCryptoStore from './store/indexeddb-crypto-store';
|
||||||
|
|
||||||
|
const Olm = global.Olm;
|
||||||
|
|
||||||
|
export function isCryptoAvailable() {
|
||||||
|
return Boolean(Olm);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cryptography bits
|
* Cryptography bits
|
||||||
*
|
*
|
||||||
@@ -62,7 +68,7 @@ import IndexedDBCryptoStore from './store/indexeddb-crypto-store';
|
|||||||
*
|
*
|
||||||
* @param {RoomList} roomList An initialised RoomList object
|
* @param {RoomList} roomList An initialised RoomList object
|
||||||
*/
|
*/
|
||||||
function Crypto(baseApis, sessionStore, userId, deviceId,
|
export default function Crypto(baseApis, sessionStore, userId, deviceId,
|
||||||
clientStore, cryptoStore, roomList) {
|
clientStore, cryptoStore, roomList) {
|
||||||
this._baseApis = baseApis;
|
this._baseApis = baseApis;
|
||||||
this._sessionStore = sessionStore;
|
this._sessionStore = sessionStore;
|
||||||
@@ -124,6 +130,10 @@ utils.inherits(Crypto, EventEmitter);
|
|||||||
* Returns a promise which resolves once the crypto module is ready for use.
|
* Returns a promise which resolves once the crypto module is ready for use.
|
||||||
*/
|
*/
|
||||||
Crypto.prototype.init = async function() {
|
Crypto.prototype.init = async function() {
|
||||||
|
// Olm is just an object with a .then, not a fully-fledged promise, so
|
||||||
|
// pass it into bluebird to make it a proper promise.
|
||||||
|
await Olm.init();
|
||||||
|
|
||||||
const sessionStoreHasAccount = Boolean(this._sessionStore.getEndToEndAccount());
|
const sessionStoreHasAccount = Boolean(this._sessionStore.getEndToEndAccount());
|
||||||
let cryptoStoreHasAccount;
|
let cryptoStoreHasAccount;
|
||||||
await this._cryptoStore.doTxn(
|
await this._cryptoStore.doTxn(
|
||||||
@@ -1518,6 +1528,3 @@ class IncomingRoomKeyRequestCancellation {
|
|||||||
* @event module:client~MatrixClient#"crypto.warning"
|
* @event module:client~MatrixClient#"crypto.warning"
|
||||||
* @param {string} type One of the strings listed above
|
* @param {string} type One of the strings listed above
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** */
|
|
||||||
module.exports = Crypto;
|
|
||||||
|
|||||||
Reference in New Issue
Block a user