1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-25 05:23:13 +03:00

Merge branch 'develop' into travis/upgrade-notifications

This commit is contained in:
Travis Ralston
2019-11-26 10:29:40 -07:00
committed by GitHub
22 changed files with 309 additions and 243 deletions

View File

@@ -203,7 +203,7 @@ function aliSendsFirstMessage() {
expectAliQueryKeys() expectAliQueryKeys()
.then(expectAliClaimKeys) .then(expectAliClaimKeys)
.then(expectAliSendMessageRequest), .then(expectAliSendMessageRequest),
]).spread(function(_, ciphertext) { ]).then(function([_, ciphertext]) {
return ciphertext; return ciphertext;
}); });
} }
@@ -218,7 +218,7 @@ function aliSendsMessage() {
return Promise.all([ return Promise.all([
sendMessage(aliTestClient.client), sendMessage(aliTestClient.client),
expectAliSendMessageRequest(), expectAliSendMessageRequest(),
]).spread(function(_, ciphertext) { ]).then(function([_, ciphertext]) {
return ciphertext; return ciphertext;
}); });
} }
@@ -234,7 +234,7 @@ function bobSendsReplyMessage() {
sendMessage(bobTestClient.client), sendMessage(bobTestClient.client),
expectBobQueryKeys() expectBobQueryKeys()
.then(expectBobSendMessageRequest), .then(expectBobSendMessageRequest),
]).spread(function(_, ciphertext) { ]).then(function([_, ciphertext]) {
return ciphertext; return ciphertext;
}); });
} }
@@ -279,16 +279,17 @@ function sendMessage(client) {
function expectSendMessageRequest(httpBackend) { function expectSendMessageRequest(httpBackend) {
const path = "/send/m.room.encrypted/"; const path = "/send/m.room.encrypted/";
const deferred = Promise.defer(); const prom = new Promise((resolve) => {
httpBackend.when("PUT", path).respond(200, function(path, content) { httpBackend.when("PUT", path).respond(200, function(path, content) {
deferred.resolve(content); resolve(content);
return { return {
event_id: "asdfgh", event_id: "asdfgh",
}; };
});
}); });
// it can take a while to process the key query // it can take a while to process the key query
return httpBackend.flush(path, 1).then(() => deferred.promise); return httpBackend.flush(path, 1).then(() => prom);
} }
function aliRecvMessage() { function aliRecvMessage() {
@@ -491,7 +492,7 @@ describe("MatrixClient crypto", function() {
aliTestClient.client.getStoredDevicesForUser(bobUserId), aliTestClient.client.getStoredDevicesForUser(bobUserId),
aliTestClient.client.getStoredDevicesForUser(eveUserId), aliTestClient.client.getStoredDevicesForUser(eveUserId),
]); ]);
}).spread((bobDevices, eveDevices) => { }).then(([bobDevices, eveDevices]) => {
// should get an empty list // should get an empty list
expect(bobDevices).toEqual([]); expect(bobDevices).toEqual([]);
expect(eveDevices).toEqual([]); expect(eveDevices).toEqual([]);

View File

@@ -83,18 +83,19 @@ function startClient(httpBackend, client) {
client.startClient(); client.startClient();
// set up a promise which will resolve once the client is initialised // set up a promise which will resolve once the client is initialised
const deferred = Promise.defer(); const prom = new Promise((resolve) => {
client.on("sync", function(state) { client.on("sync", function(state) {
logger.log("sync", state); logger.log("sync", state);
if (state != "SYNCING") { if (state != "SYNCING") {
return; return;
} }
deferred.resolve(); resolve();
});
}); });
return Promise.all([ return Promise.all([
httpBackend.flushAllExpected(), httpBackend.flushAllExpected(),
deferred.promise, prom,
]); ]);
} }
@@ -343,25 +344,25 @@ describe("MatrixClient event timelines", function() {
}; };
}); });
const deferred = Promise.defer(); const prom = new Promise((resolve, reject) => {
client.on("sync", function() { client.on("sync", function() {
client.getEventTimeline(timelineSet, EVENTS[2].event_id, client.getEventTimeline(timelineSet, EVENTS[2].event_id,
).then(function(tl) { ).then(function(tl) {
expect(tl.getEvents().length).toEqual(4); expect(tl.getEvents().length).toEqual(4);
expect(tl.getEvents()[0].event).toEqual(EVENTS[1]); expect(tl.getEvents()[0].event).toEqual(EVENTS[1]);
expect(tl.getEvents()[1].event).toEqual(EVENTS[2]); expect(tl.getEvents()[1].event).toEqual(EVENTS[2]);
expect(tl.getEvents()[3].event).toEqual(EVENTS[3]); expect(tl.getEvents()[3].event).toEqual(EVENTS[3]);
expect(tl.getPaginationToken(EventTimeline.BACKWARDS)) expect(tl.getPaginationToken(EventTimeline.BACKWARDS))
.toEqual("start_token"); .toEqual("start_token");
// expect(tl.getPaginationToken(EventTimeline.FORWARDS)) // expect(tl.getPaginationToken(EventTimeline.FORWARDS))
// .toEqual("s_5_4"); // .toEqual("s_5_4");
}).done(() => deferred.resolve(), }).done(resolve, reject);
(e) => deferred.reject(e)); });
}); });
return Promise.all([ return Promise.all([
httpBackend.flushAllExpected(), httpBackend.flushAllExpected(),
deferred.promise, prom,
]); ]);
}); });

View File

@@ -691,12 +691,12 @@ describe("MatrixClient syncing", function() {
include_leave: true }}); include_leave: true }});
}).respond(200, { filter_id: "another_id" }); }).respond(200, { filter_id: "another_id" });
const defer = Promise.defer(); const prom = new Promise((resolve) => {
httpBackend.when("GET", "/sync").check(function(req) {
httpBackend.when("GET", "/sync").check(function(req) { expect(req.queryParams.filter).toEqual("another_id");
expect(req.queryParams.filter).toEqual("another_id"); resolve();
defer.resolve(); }).respond(200, {});
}).respond(200, {}); });
client.syncLeftRooms(); client.syncLeftRooms();
@@ -707,7 +707,7 @@ describe("MatrixClient syncing", function() {
// flush the syncs // flush the syncs
return httpBackend.flushAllExpected(); return httpBackend.flushAllExpected();
}), }),
defer.promise, prom,
]); ]);
}); });

View File

@@ -25,8 +25,8 @@ describe("Crypto", function() {
return; return;
} }
beforeEach(function(done) { beforeAll(function() {
Olm.init().then(done); return Olm.init();
}); });
it("Crypto exposes the correct olm library version", function() { it("Crypto exposes the correct olm library version", function() {

View File

@@ -25,14 +25,16 @@ describe("MegolmDecryption", function() {
return; return;
} }
beforeAll(function() {
return Olm.init();
});
let megolmDecryption; let megolmDecryption;
let mockOlmLib; let mockOlmLib;
let mockCrypto; let mockCrypto;
let mockBaseApis; let mockBaseApis;
beforeEach(async function() { beforeEach(async function() {
await Olm.init();
mockCrypto = testUtils.mock(Crypto, 'Crypto'); mockCrypto = testUtils.mock(Crypto, 'Crypto');
mockBaseApis = {}; mockBaseApis = {};

View File

@@ -48,12 +48,14 @@ describe("OlmDecryption", function() {
return; return;
} }
beforeAll(function() {
return global.Olm.init();
});
let aliceOlmDevice; let aliceOlmDevice;
let bobOlmDevice; let bobOlmDevice;
beforeEach(async function() { beforeEach(async function() {
await global.Olm.init();
aliceOlmDevice = makeOlmDevice(); aliceOlmDevice = makeOlmDevice();
bobOlmDevice = makeOlmDevice(); bobOlmDevice = makeOlmDevice();
await aliceOlmDevice.init(); await aliceOlmDevice.init();

View File

@@ -128,6 +128,10 @@ describe("MegolmBackup", function() {
return; return;
} }
beforeAll(function() {
return Olm.init();
});
let olmDevice; let olmDevice;
let mockOlmLib; let mockOlmLib;
let mockCrypto; let mockCrypto;
@@ -136,7 +140,6 @@ describe("MegolmBackup", function() {
let cryptoStore; let cryptoStore;
let megolmDecryption; let megolmDecryption;
beforeEach(async function() { beforeEach(async function() {
await Olm.init();
mockCrypto = testUtils.mock(Crypto, 'Crypto'); mockCrypto = testUtils.mock(Crypto, 'Crypto');
mockCrypto.backupKey = new Olm.PkEncryption(); mockCrypto.backupKey = new Olm.PkEncryption();
mockCrypto.backupKey.set_recipient_key( mockCrypto.backupKey.set_recipient_key(

View File

@@ -55,8 +55,8 @@ describe("Cross Signing", function() {
return; return;
} }
beforeEach(async function() { beforeAll(function() {
await global.Olm.init(); return global.Olm.init();
}); });
it("should sign the master key with the device key", async function() { it("should sign the master key with the device key", async function() {

View File

@@ -40,8 +40,8 @@ describe("Secrets", function() {
return; return;
} }
beforeEach(async function() { beforeAll(function() {
await global.Olm.init(); return global.Olm.init();
}); });
it("should store and retrieve a secret", async function() { it("should store and retrieve a secret", async function() {

View File

@@ -33,8 +33,8 @@ describe("QR code verification", function() {
return; return;
} }
beforeEach(async function() { beforeAll(function() {
await Olm.init(); return Olm.init();
}); });
describe("showing", function() { describe("showing", function() {

View File

@@ -35,8 +35,8 @@ describe("verification request", function() {
return; return;
} }
beforeEach(async function() { beforeAll(function() {
await Olm.init(); return Olm.init();
}); });
it("should request and accept a verification", async function() { it("should request and accept a verification", async function() {

View File

@@ -45,8 +45,8 @@ describe("SAS verification", function() {
return; return;
} }
beforeEach(async function() { beforeAll(function() {
await Olm.init(); return Olm.init();
}); });
it("should error on an unexpected event", async function() { it("should error on an unexpected event", async function() {
@@ -169,6 +169,12 @@ describe("SAS verification", function() {
} }
}); });
}); });
afterEach(async function() {
await Promise.all([
alice.stop(),
bob.stop(),
]);
});
it("should verify a key", async function() { it("should verify a key", async function() {
let macMethod; let macMethod;

View File

@@ -73,7 +73,7 @@ function keysFromRecoverySession(sessions, decryptionKey, roomId) {
decrypted.room_id = roomId; decrypted.room_id = roomId;
keys.push(decrypted); keys.push(decrypted);
} catch (e) { } catch (e) {
logger.log("Failed to decrypt session from backup"); logger.log("Failed to decrypt megolm session from backup", e);
} }
} }
return keys; return keys;
@@ -1626,7 +1626,7 @@ MatrixClient.prototype._restoreKeyBackup = function(
key.session_id = targetSessionId; key.session_id = targetSessionId;
keys.push(key); keys.push(key);
} catch (e) { } catch (e) {
logger.log("Failed to decrypt session from backup"); logger.log("Failed to decrypt megolm session from backup", e);
} }
} }
@@ -1872,33 +1872,33 @@ MatrixClient.prototype.joinRoom = function(roomIdOrAlias, opts, callback) {
const reqOpts = {qsStringifyOptions: {arrayFormat: 'repeat'}}; const reqOpts = {qsStringifyOptions: {arrayFormat: 'repeat'}};
const defer = Promise.defer();
const self = this; const self = this;
sign_promise.then(function(signed_invite_object) { const prom = new Promise((resolve, reject) => {
const data = {}; sign_promise.then(function(signed_invite_object) {
if (signed_invite_object) { const data = {};
data.third_party_signed = signed_invite_object; if (signed_invite_object) {
} data.third_party_signed = signed_invite_object;
}
const path = utils.encodeUri("/join/$roomid", { $roomid: roomIdOrAlias}); const path = utils.encodeUri("/join/$roomid", { $roomid: roomIdOrAlias});
return self._http.authedRequest( return self._http.authedRequest(
undefined, "POST", path, queryString, data, reqOpts); undefined, "POST", path, queryString, data, reqOpts);
}).then(function(res) { }).then(function(res) {
const roomId = res.room_id; const roomId = res.room_id;
const syncApi = new SyncApi(self, self._clientOpts); const syncApi = new SyncApi(self, self._clientOpts);
const room = syncApi.createRoom(roomId); const room = syncApi.createRoom(roomId);
if (opts.syncRoom) { if (opts.syncRoom) {
// v2 will do this for us // v2 will do this for us
// return syncApi.syncRoom(room); // return syncApi.syncRoom(room);
} }
return Promise.resolve(room); return Promise.resolve(room);
}).done(function(room) { }).done(function(room) {
_resolve(callback, defer, room); _resolve(callback, resolve, room);
}, function(err) { }, function(err) {
_reject(callback, defer, err); _reject(callback, reject, err);
});
}); });
return defer.promise; return prom;
}; };
/** /**
@@ -3214,42 +3214,45 @@ MatrixClient.prototype.scrollback = function(room, limit, callback) {
// reduce the required number of events appropriately // reduce the required number of events appropriately
limit = limit - numAdded; limit = limit - numAdded;
const defer = Promise.defer(); const self = this;
const prom = new Promise((resolve, reject) => {
// wait for a time before doing this request
// (which may be 0 in order not to special case the code paths)
sleep(timeToWaitMs).then(function() {
return self._createMessagesRequest(
room.roomId,
room.oldState.paginationToken,
limit,
'b');
}).done(function(res) {
const matrixEvents = utils.map(res.chunk, _PojoToMatrixEventMapper(self));
if (res.state) {
const stateEvents = utils.map(res.state, _PojoToMatrixEventMapper(self));
room.currentState.setUnknownStateEvents(stateEvents);
}
room.addEventsToTimeline(matrixEvents, true, room.getLiveTimeline());
room.oldState.paginationToken = res.end;
if (res.chunk.length === 0) {
room.oldState.paginationToken = null;
}
self.store.storeEvents(room, matrixEvents, res.end, true);
self._ongoingScrollbacks[room.roomId] = null;
_resolve(callback, resolve, room);
}, function(err) {
self._ongoingScrollbacks[room.roomId] = {
errorTs: Date.now(),
};
_reject(callback, reject, err);
});
});
info = { info = {
promise: defer.promise, promise: prom,
errorTs: null, errorTs: null,
}; };
const self = this;
// wait for a time before doing this request
// (which may be 0 in order not to special case the code paths)
sleep(timeToWaitMs).then(function() {
return self._createMessagesRequest(
room.roomId,
room.oldState.paginationToken,
limit,
'b');
}).done(function(res) {
const matrixEvents = utils.map(res.chunk, _PojoToMatrixEventMapper(self));
if (res.state) {
const stateEvents = utils.map(res.state, _PojoToMatrixEventMapper(self));
room.currentState.setUnknownStateEvents(stateEvents);
}
room.addEventsToTimeline(matrixEvents, true, room.getLiveTimeline());
room.oldState.paginationToken = res.end;
if (res.chunk.length === 0) {
room.oldState.paginationToken = null;
}
self.store.storeEvents(room, matrixEvents, res.end, true);
self._ongoingScrollbacks[room.roomId] = null;
_resolve(callback, defer, room);
}, function(err) {
self._ongoingScrollbacks[room.roomId] = {
errorTs: Date.now(),
};
_reject(callback, defer, err);
});
this._ongoingScrollbacks[room.roomId] = info; this._ongoingScrollbacks[room.roomId] = info;
return defer.promise; return prom;
}; };
/** /**
@@ -3867,7 +3870,7 @@ MatrixClient.prototype.setRoomMutePushRule = function(scope, roomId, mute) {
} else if (!hasDontNotifyRule) { } else if (!hasDontNotifyRule) {
// Remove the existing one before setting the mute push rule // Remove the existing one before setting the mute push rule
// This is a workaround to SYN-590 (Push rule update fails) // This is a workaround to SYN-590 (Push rule update fails)
deferred = Promise.defer(); deferred = utils.defer();
this.deletePushRule(scope, "room", roomPushRule.rule_id) this.deletePushRule(scope, "room", roomPushRule.rule_id)
.done(function() { .done(function() {
self.addPushRule(scope, "room", roomId, { self.addPushRule(scope, "room", roomId, {
@@ -3886,26 +3889,26 @@ MatrixClient.prototype.setRoomMutePushRule = function(scope, roomId, mute) {
} }
if (deferred) { if (deferred) {
// Update this.pushRules when the operation completes return new Promise((resolve, reject) => {
const ruleRefreshDeferred = Promise.defer(); // Update this.pushRules when the operation completes
deferred.done(function() { deferred.done(function() {
self.getPushRules().done(function(result) { self.getPushRules().done(function(result) {
self.pushRules = result; self.pushRules = result;
ruleRefreshDeferred.resolve(); resolve();
}, function(err) {
reject(err);
});
}, function(err) { }, function(err) {
ruleRefreshDeferred.reject(err); // Update it even if the previous operation fails. This can help the
}); // app to recover when push settings has been modifed from another client
}, function(err) { self.getPushRules().done(function(result) {
// Update it even if the previous operation fails. This can help the self.pushRules = result;
// app to recover when push settings has been modifed from another client reject(err);
self.getPushRules().done(function(result) { }, function(err2) {
self.pushRules = result; reject(err);
ruleRefreshDeferred.reject(err); });
}, function(err2) {
ruleRefreshDeferred.reject(err);
}); });
}); });
return ruleRefreshDeferred.promise;
} }
}; };
@@ -4705,7 +4708,7 @@ function setupCallEventHandler(client) {
const content = event.getContent(); const content = event.getContent();
let call = content.call_id ? client.callList[content.call_id] : undefined; let call = content.call_id ? client.callList[content.call_id] : undefined;
let i; let i;
//console.log("RECV %s content=%s", event.getType(), JSON.stringify(content)); //console.info("RECV %s content=%s", event.getType(), JSON.stringify(content));
if (event.getType() === "m.call.invite") { if (event.getType() === "m.call.invite") {
if (event.getSender() === client.credentials.userId) { if (event.getSender() === client.credentials.userId) {
@@ -4876,18 +4879,18 @@ function checkTurnServers(client) {
}); });
} }
function _reject(callback, defer, err) { function _reject(callback, reject, err) {
if (callback) { if (callback) {
callback(err); callback(err);
} }
defer.reject(err); reject(err);
} }
function _resolve(callback, defer, res) { function _resolve(callback, resolve, res) {
if (callback) { if (callback) {
callback(null, res); callback(null, res);
} }
defer.resolve(res); resolve(res);
} }
function _PojoToMatrixEventMapper(client) { function _PojoToMatrixEventMapper(client) {

View File

@@ -462,7 +462,7 @@ OlmDevice.prototype.createInboundSession = async function(
*/ */
OlmDevice.prototype.getSessionIdsForDevice = async function(theirDeviceIdentityKey) { OlmDevice.prototype.getSessionIdsForDevice = async function(theirDeviceIdentityKey) {
if (this._sessionsInProgress[theirDeviceIdentityKey]) { if (this._sessionsInProgress[theirDeviceIdentityKey]) {
logger.log("waiting for session to be created"); logger.log("waiting for olm session to be created");
try { try {
await this._sessionsInProgress[theirDeviceIdentityKey]; await this._sessionsInProgress[theirDeviceIdentityKey];
} catch (e) { } catch (e) {
@@ -543,7 +543,7 @@ OlmDevice.prototype.getSessionIdForDevice = async function(
*/ */
OlmDevice.prototype.getSessionInfoForDevice = async function(deviceIdentityKey, nowait) { OlmDevice.prototype.getSessionInfoForDevice = async function(deviceIdentityKey, nowait) {
if (this._sessionsInProgress[deviceIdentityKey] && !nowait) { if (this._sessionsInProgress[deviceIdentityKey] && !nowait) {
logger.log("waiting for session to be created"); logger.log("waiting for olm session to be created");
try { try {
await this._sessionsInProgress[deviceIdentityKey]; await this._sessionsInProgress[deviceIdentityKey];
} catch (e) { } catch (e) {
@@ -595,8 +595,8 @@ OlmDevice.prototype.encryptMessage = async function(
(txn) => { (txn) => {
this._getSession(theirDeviceIdentityKey, sessionId, txn, (sessionInfo) => { this._getSession(theirDeviceIdentityKey, sessionId, txn, (sessionInfo) => {
const sessionDesc = sessionInfo.session.describe(); const sessionDesc = sessionInfo.session.describe();
console.log( logger.log(
"Session ID " + sessionId + " to " + "encryptMessage: Olm Session ID " + sessionId + " to " +
theirDeviceIdentityKey + ": " + sessionDesc, theirDeviceIdentityKey + ": " + sessionDesc,
); );
res = sessionInfo.session.encrypt(payloadString); res = sessionInfo.session.encrypt(payloadString);
@@ -627,8 +627,8 @@ OlmDevice.prototype.decryptMessage = async function(
(txn) => { (txn) => {
this._getSession(theirDeviceIdentityKey, sessionId, txn, (sessionInfo) => { this._getSession(theirDeviceIdentityKey, sessionId, txn, (sessionInfo) => {
const sessionDesc = sessionInfo.session.describe(); const sessionDesc = sessionInfo.session.describe();
console.log( logger.log(
"Session ID " + sessionId + " to " + "decryptMessage: Olm Session ID " + sessionId + " from " +
theirDeviceIdentityKey + ": " + sessionDesc, theirDeviceIdentityKey + ": " + sessionDesc,
); );
payloadString = sessionInfo.session.decrypt(messageType, ciphertext); payloadString = sessionInfo.session.decrypt(messageType, ciphertext);
@@ -740,6 +740,8 @@ OlmDevice.prototype.createOutboundGroupSession = function() {
OlmDevice.prototype.encryptGroupMessage = function(sessionId, payloadString) { OlmDevice.prototype.encryptGroupMessage = function(sessionId, payloadString) {
const self = this; const self = this;
logger.log(`encrypting msg with megolm session ${sessionId}`);
checkPayloadLength(payloadString); checkPayloadLength(payloadString);
return this._getOutboundGroupSession(sessionId, function(session) { return this._getOutboundGroupSession(sessionId, function(session) {
@@ -886,7 +888,9 @@ OlmDevice.prototype.addInboundGroupSession = async function(
<= session.first_known_index()) { <= session.first_known_index()) {
// existing session has lower index (i.e. can // existing session has lower index (i.e. can
// decrypt more), so keep it // decrypt more), so keep it
logger.log("Keeping existing session"); logger.log(
`Keeping existing megolm session ${sessionId}`,
);
return; return;
} }
} }

View File

@@ -104,7 +104,7 @@ OutboundSessionInfo.prototype.sharedWithTooManyDevices = function(
} }
if (!devicesInRoom.hasOwnProperty(userId)) { if (!devicesInRoom.hasOwnProperty(userId)) {
logger.log("Starting new session because we shared with " + userId); logger.log("Starting new megolm session because we shared with " + userId);
return true; return true;
} }
@@ -115,7 +115,7 @@ OutboundSessionInfo.prototype.sharedWithTooManyDevices = function(
if (!devicesInRoom[userId].hasOwnProperty(deviceId)) { if (!devicesInRoom[userId].hasOwnProperty(deviceId)) {
logger.log( logger.log(
"Starting new session because we shared with " + "Starting new megolm session because we shared with " +
userId + ":" + deviceId, userId + ":" + deviceId,
); );
return true; return true;
@@ -200,6 +200,8 @@ MegolmEncryption.prototype._ensureOutboundSession = function(devicesInRoom) {
if (!session) { if (!session) {
logger.log(`Starting new megolm session for room ${self._roomId}`); logger.log(`Starting new megolm session for room ${self._roomId}`);
session = await self._prepareNewSession(); session = await self._prepareNewSession();
logger.log(`Started new megolm session ${session.sessionId} ` +
`for room ${self._roomId}`);
self._outboundSessions[session.sessionId] = session; self._outboundSessions[session.sessionId] = session;
} }
@@ -278,7 +280,7 @@ MegolmEncryption.prototype._prepareNewSession = async function() {
).catch((e) => { ).catch((e) => {
// This throws if the upload failed, but this is fine // This throws if the upload failed, but this is fine
// since it will have written it to the db and will retry. // since it will have written it to the db and will retry.
logger.log("Failed to back up group session", e); logger.log("Failed to back up megolm session", e);
}); });
} }
@@ -440,19 +442,19 @@ MegolmEncryption.prototype.reshareKeyWithDevice = async function(
) { ) {
const obSessionInfo = this._outboundSessions[sessionId]; const obSessionInfo = this._outboundSessions[sessionId];
if (!obSessionInfo) { if (!obSessionInfo) {
logger.debug("Session ID " + sessionId + " not found: not re-sharing keys"); logger.debug(`megolm session ${sessionId} not found: not re-sharing keys`);
return; return;
} }
// The chain index of the key we previously sent this device // The chain index of the key we previously sent this device
if (obSessionInfo.sharedWithDevices[userId] === undefined) { if (obSessionInfo.sharedWithDevices[userId] === undefined) {
logger.debug("Session ID " + sessionId + " never shared with user " + userId); logger.debug(`megolm session ${sessionId} never shared with user ${userId}`);
return; return;
} }
const sentChainIndex = obSessionInfo.sharedWithDevices[userId][device.deviceId]; const sentChainIndex = obSessionInfo.sharedWithDevices[userId][device.deviceId];
if (sentChainIndex === undefined) { if (sentChainIndex === undefined) {
logger.debug( logger.debug(
"Session ID " + sessionId + " never shared with device " + "megolm session ID " + sessionId + " never shared with device " +
userId + ":" + device.deviceId, userId + ":" + device.deviceId,
); );
return; return;
@@ -466,7 +468,7 @@ MegolmEncryption.prototype.reshareKeyWithDevice = async function(
if (!key) { if (!key) {
logger.warn( logger.warn(
"No outbound session key found for " + sessionId + ": not re-sharing keys", `No inbound session key found for megolm ${sessionId}: not re-sharing keys`,
); );
return; return;
} }
@@ -513,9 +515,8 @@ MegolmEncryption.prototype.reshareKeyWithDevice = async function(
[device.deviceId]: encryptedContent, [device.deviceId]: encryptedContent,
}, },
}); });
logger.debug( logger.debug(`Re-shared key for megolm session ${sessionId} ` +
`Re-shared key for session ${sessionId} with ${userId}:${device.deviceId}`, `with ${userId}:${device.deviceId}`);
);
}; };
/** /**
@@ -550,10 +551,10 @@ MegolmEncryption.prototype._shareKeyWithDevices = async function(session, device
await this._encryptAndSendKeysToDevices( await this._encryptAndSendKeysToDevices(
session, key.chain_index, userDeviceMaps[i], payload, session, key.chain_index, userDeviceMaps[i], payload,
); );
logger.log(`Completed megolm keyshare in ${this._roomId} ` logger.log(`Completed megolm keyshare for ${session.sessionId} `
+ `(slice ${i + 1}/${userDeviceMaps.length})`); + `in ${this._roomId} (slice ${i + 1}/${userDeviceMaps.length})`);
} catch (e) { } catch (e) {
logger.log(`megolm keyshare in ${this._roomId} ` logger.log(`megolm keyshare for ${session.sessionId} in ${this._roomId} `
+ `(slice ${i + 1}/${userDeviceMaps.length}) failed`); + `(slice ${i + 1}/${userDeviceMaps.length}) failed`);
throw e; throw e;
@@ -922,7 +923,7 @@ MegolmDecryption.prototype.onRoomKeyEvent = function(event) {
keysClaimed = event.getKeysClaimed(); keysClaimed = event.getKeysClaimed();
} }
logger.log(`Adding key for megolm session ${senderKey}|${sessionId}`); logger.log(`Received and adding key for megolm session ${senderKey}|${sessionId}`);
return this._olmDevice.addInboundGroupSession( return this._olmDevice.addInboundGroupSession(
content.room_id, senderKey, forwardingKeyChain, sessionId, content.room_id, senderKey, forwardingKeyChain, sessionId,
content.session_key, keysClaimed, content.session_key, keysClaimed,
@@ -955,7 +956,7 @@ MegolmDecryption.prototype.onRoomKeyEvent = function(event) {
).catch((e) => { ).catch((e) => {
// This throws if the upload failed, but this is fine // This throws if the upload failed, but this is fine
// since it will have written it to the db and will retry. // since it will have written it to the db and will retry.
logger.log("Failed to back up group session", e); logger.log("Failed to back up megolm session", e);
}); });
} }
}).catch((e) => { }).catch((e) => {
@@ -1088,7 +1089,7 @@ MegolmDecryption.prototype.importRoomKey = function(session) {
).catch((e) => { ).catch((e) => {
// This throws if the upload failed, but this is fine // This throws if the upload failed, but this is fine
// since it will have written it to the db and will retry. // since it will have written it to the db and will retry.
logger.log("Failed to back up group session", e); logger.log("Failed to back up megolm session", e);
}); });
} }
// have another go at decrypting events sent with this session. // have another go at decrypting events sent with this session.

View File

@@ -139,7 +139,7 @@ OlmEncryption.prototype.encryptMessage = async function(room, eventType, content
} }
} }
return await Promise.all(promises).return(encryptedContent); return await Promise.all(promises).then(() => encryptedContent);
}; };
/** /**

View File

@@ -1638,7 +1638,7 @@ Crypto.prototype.setRoomEncryption = async function(roomId, config, inhibitDevic
// It would otherwise just throw later as an unknown algorithm would, but we may // It would otherwise just throw later as an unknown algorithm would, but we may
// as well catch this here // as well catch this here
if (!config.algorithm) { if (!config.algorithm) {
console.log("Ignoring setRoomEncryption with no algorithm"); logger.log("Ignoring setRoomEncryption with no algorithm");
return; return;
} }
@@ -1824,17 +1824,15 @@ Crypto.prototype.exportRoomKeys = async function() {
* @return {module:client.Promise} a promise which resolves once the keys have been imported * @return {module:client.Promise} a promise which resolves once the keys have been imported
*/ */
Crypto.prototype.importRoomKeys = function(keys) { Crypto.prototype.importRoomKeys = function(keys) {
return Promise.map( return Promise.all(keys.map((key) => {
keys, (key) => { if (!key.room_id || !key.algorithm) {
if (!key.room_id || !key.algorithm) { logger.warn("ignoring room key entry with missing fields", key);
logger.warn("ignoring room key entry with missing fields", key); return null;
return null; }
}
const alg = this._getRoomDecryptor(key.room_id, key.algorithm); const alg = this._getRoomDecryptor(key.room_id, key.algorithm);
return alg.importRoomKey(key); return alg.importRoomKey(key);
}, }));
);
}; };
/** /**
@@ -2296,6 +2294,9 @@ Crypto.prototype._getTrackedE2eRooms = function() {
Crypto.prototype._onToDeviceEvent = function(event) { Crypto.prototype._onToDeviceEvent = function(event) {
try { try {
logger.log(`received to_device ${event.getType()} from: ` +
`${event.getSender()} id: ${event.getId()}`);
if (event.getType() == "m.room_key" if (event.getType() == "m.room_key"
|| event.getType() == "m.forwarded_room_key") { || event.getType() == "m.forwarded_room_key") {
this._onRoomKeyEvent(event); this._onRoomKeyEvent(event);
@@ -2858,14 +2859,10 @@ Crypto.prototype._processReceivedRoomKeyRequests = async function() {
// cancellation (and end up with a cancelled request), rather than the // cancellation (and end up with a cancelled request), rather than the
// cancellation before the request (and end up with an outstanding // cancellation before the request (and end up with an outstanding
// request which should have been cancelled.) // request which should have been cancelled.)
await Promise.map( await Promise.all(requests.map((req) =>
requests, (req) => this._processReceivedRoomKeyRequest(req)));
this._processReceivedRoomKeyRequest(req), await Promise.all(cancellations.map((cancellation) =>
); this._processReceivedRoomKeyRequestCancellation(cancellation)));
await Promise.map(
cancellations, (cancellation) =>
this._processReceivedRoomKeyRequestCancellation(cancellation),
);
} catch (e) { } catch (e) {
logger.error(`Error processing room key requsts: ${e}`); logger.error(`Error processing room key requsts: ${e}`);
} finally { } finally {

View File

@@ -287,12 +287,12 @@ async function _verifyKeyAndStartSession(olmDevice, oneTimeKey, userId, deviceIn
); );
} catch (e) { } catch (e) {
// possibly a bad key // possibly a bad key
logger.error("Error starting session with device " + logger.error("Error starting olm session with device " +
userId + ":" + deviceId + ": " + e); userId + ":" + deviceId + ": " + e);
return null; return null;
} }
logger.log("Started new sessionid " + sid + logger.log("Started new olm sessionid " + sid +
" for device " + userId + ":" + deviceId); " for device " + userId + ":" + deviceId);
return sid; return sid;
} }

View File

@@ -58,35 +58,34 @@ export class Backend {
getOrAddOutgoingRoomKeyRequest(request) { getOrAddOutgoingRoomKeyRequest(request) {
const requestBody = request.requestBody; const requestBody = request.requestBody;
const deferred = Promise.defer(); return new Promise((resolve, reject) => {
const txn = this._db.transaction("outgoingRoomKeyRequests", "readwrite"); const txn = this._db.transaction("outgoingRoomKeyRequests", "readwrite");
txn.onerror = deferred.reject; txn.onerror = reject;
// first see if we already have an entry for this request. // first see if we already have an entry for this request.
this._getOutgoingRoomKeyRequest(txn, requestBody, (existing) => { this._getOutgoingRoomKeyRequest(txn, requestBody, (existing) => {
if (existing) { if (existing) {
// this entry matches the request - return it. // this entry matches the request - return it.
logger.log(
`already have key request outstanding for ` +
`${requestBody.room_id} / ${requestBody.session_id}: ` +
`not sending another`,
);
resolve(existing);
return;
}
// we got to the end of the list without finding a match
// - add the new request.
logger.log( logger.log(
`already have key request outstanding for ` + `enqueueing key request for ${requestBody.room_id} / ` +
`${requestBody.room_id} / ${requestBody.session_id}: ` + requestBody.session_id,
`not sending another`,
); );
deferred.resolve(existing); txn.oncomplete = () => { resolve(request); };
return; const store = txn.objectStore("outgoingRoomKeyRequests");
} store.add(request);
});
// we got to the end of the list without finding a match
// - add the new request.
logger.log(
`enqueueing key request for ${requestBody.room_id} / ` +
requestBody.session_id,
);
txn.oncomplete = () => { deferred.resolve(request); };
const store = txn.objectStore("outgoingRoomKeyRequests");
store.add(request);
}); });
return deferred.promise;
} }
/** /**
@@ -100,15 +99,14 @@ export class Backend {
* not found * not found
*/ */
getOutgoingRoomKeyRequest(requestBody) { getOutgoingRoomKeyRequest(requestBody) {
const deferred = Promise.defer(); return new Promise((resolve, reject) => {
const txn = this._db.transaction("outgoingRoomKeyRequests", "readonly");
txn.onerror = reject;
const txn = this._db.transaction("outgoingRoomKeyRequests", "readonly"); this._getOutgoingRoomKeyRequest(txn, requestBody, (existing) => {
txn.onerror = deferred.reject; resolve(existing);
});
this._getOutgoingRoomKeyRequest(txn, requestBody, (existing) => {
deferred.resolve(existing);
}); });
return deferred.promise;
} }
/** /**

View File

@@ -287,7 +287,9 @@ export default class IndexedDBCryptoStore {
* @param {function(string)} func Called with the account pickle * @param {function(string)} func Called with the account pickle
*/ */
getAccount(txn, func) { getAccount(txn, func) {
this._backendPromise.value().getAccount(txn, func); this._backendPromise.then(backend => {
backend.getAccount(txn, func);
});
} }
/** /**
@@ -298,7 +300,9 @@ export default class IndexedDBCryptoStore {
* @param {string} newData The new account pickle to store. * @param {string} newData The new account pickle to store.
*/ */
storeAccount(txn, newData) { storeAccount(txn, newData) {
this._backendPromise.value().storeAccount(txn, newData); this._backendPromise.then(backend => {
backend.storeAccount(txn, newData);
});
} }
/** /**
@@ -310,7 +314,9 @@ export default class IndexedDBCryptoStore {
* { key_type: base64 encoded seed } where key type = user_signing_key_seed or self_signing_key_seed * { key_type: base64 encoded seed } where key type = user_signing_key_seed or self_signing_key_seed
*/ */
getCrossSigningKeys(txn, func) { getCrossSigningKeys(txn, func) {
this._backendPromise.value().getCrossSigningKeys(txn, func); this._backendPromise.then(backend => {
backend.getCrossSigningKeys(txn, func);
});
} }
/** /**
@@ -320,7 +326,9 @@ export default class IndexedDBCryptoStore {
* @param {string} keys keys object as getCrossSigningKeys() * @param {string} keys keys object as getCrossSigningKeys()
*/ */
storeCrossSigningKeys(txn, keys) { storeCrossSigningKeys(txn, keys) {
this._backendPromise.value().storeCrossSigningKeys(txn, keys); this._backendPromise.then(backend => {
backend.storeCrossSigningKeys(txn, keys);
});
} }
// Olm sessions // Olm sessions
@@ -331,7 +339,9 @@ export default class IndexedDBCryptoStore {
* @param {function(int)} func Called with the count of sessions * @param {function(int)} func Called with the count of sessions
*/ */
countEndToEndSessions(txn, func) { countEndToEndSessions(txn, func) {
this._backendPromise.value().countEndToEndSessions(txn, func); this._backendPromise.then(backend => {
backend.countEndToEndSessions(txn, func);
});
} }
/** /**
@@ -347,7 +357,9 @@ export default class IndexedDBCryptoStore {
* a message. * a message.
*/ */
getEndToEndSession(deviceKey, sessionId, txn, func) { getEndToEndSession(deviceKey, sessionId, txn, func) {
this._backendPromise.value().getEndToEndSession(deviceKey, sessionId, txn, func); this._backendPromise.then(backend => {
backend.getEndToEndSession(deviceKey, sessionId, txn, func);
});
} }
/** /**
@@ -362,7 +374,9 @@ export default class IndexedDBCryptoStore {
* a message. * a message.
*/ */
getEndToEndSessions(deviceKey, txn, func) { getEndToEndSessions(deviceKey, txn, func) {
this._backendPromise.value().getEndToEndSessions(deviceKey, txn, func); this._backendPromise.then(backend => {
backend.getEndToEndSessions(deviceKey, txn, func);
});
} }
/** /**
@@ -373,7 +387,9 @@ export default class IndexedDBCryptoStore {
* and session keys. * and session keys.
*/ */
getAllEndToEndSessions(txn, func) { getAllEndToEndSessions(txn, func) {
this._backendPromise.value().getAllEndToEndSessions(txn, func); this._backendPromise.then(backend => {
backend.getAllEndToEndSessions(txn, func);
});
} }
/** /**
@@ -384,12 +400,14 @@ export default class IndexedDBCryptoStore {
* @param {*} txn An active transaction. See doTxn(). * @param {*} txn An active transaction. See doTxn().
*/ */
storeEndToEndSession(deviceKey, sessionId, sessionInfo, txn) { storeEndToEndSession(deviceKey, sessionId, sessionInfo, txn) {
this._backendPromise.value().storeEndToEndSession( this._backendPromise.then(backend => {
deviceKey, sessionId, sessionInfo, txn, backend.storeEndToEndSession(
); deviceKey, sessionId, sessionInfo, txn,
);
});
} }
// Inbound group saessions // Inbound group sessions
/** /**
* Retrieve the end-to-end inbound group session for a given * Retrieve the end-to-end inbound group session for a given
@@ -401,9 +419,11 @@ export default class IndexedDBCryptoStore {
* to Base64 end-to-end session. * to Base64 end-to-end session.
*/ */
getEndToEndInboundGroupSession(senderCurve25519Key, sessionId, txn, func) { getEndToEndInboundGroupSession(senderCurve25519Key, sessionId, txn, func) {
this._backendPromise.value().getEndToEndInboundGroupSession( this._backendPromise.then(backend => {
senderCurve25519Key, sessionId, txn, func, backend.getEndToEndInboundGroupSession(
); senderCurve25519Key, sessionId, txn, func,
);
});
} }
/** /**
@@ -414,7 +434,9 @@ export default class IndexedDBCryptoStore {
* sessionData}, then once with null to indicate the end of the list. * sessionData}, then once with null to indicate the end of the list.
*/ */
getAllEndToEndInboundGroupSessions(txn, func) { getAllEndToEndInboundGroupSessions(txn, func) {
this._backendPromise.value().getAllEndToEndInboundGroupSessions(txn, func); this._backendPromise.then(backend => {
backend.getAllEndToEndInboundGroupSessions(txn, func);
});
} }
/** /**
@@ -427,9 +449,11 @@ export default class IndexedDBCryptoStore {
* @param {*} txn An active transaction. See doTxn(). * @param {*} txn An active transaction. See doTxn().
*/ */
addEndToEndInboundGroupSession(senderCurve25519Key, sessionId, sessionData, txn) { addEndToEndInboundGroupSession(senderCurve25519Key, sessionId, sessionData, txn) {
this._backendPromise.value().addEndToEndInboundGroupSession( this._backendPromise.then(backend => {
senderCurve25519Key, sessionId, sessionData, txn, backend.addEndToEndInboundGroupSession(
); senderCurve25519Key, sessionId, sessionData, txn,
);
});
} }
/** /**
@@ -442,9 +466,11 @@ export default class IndexedDBCryptoStore {
* @param {*} txn An active transaction. See doTxn(). * @param {*} txn An active transaction. See doTxn().
*/ */
storeEndToEndInboundGroupSession(senderCurve25519Key, sessionId, sessionData, txn) { storeEndToEndInboundGroupSession(senderCurve25519Key, sessionId, sessionData, txn) {
this._backendPromise.value().storeEndToEndInboundGroupSession( this._backendPromise.then(backend => {
senderCurve25519Key, sessionId, sessionData, txn, backend.storeEndToEndInboundGroupSession(
); senderCurve25519Key, sessionId, sessionData, txn,
);
});
} }
// End-to-end device tracking // End-to-end device tracking
@@ -460,7 +486,9 @@ export default class IndexedDBCryptoStore {
* @param {*} txn An active transaction. See doTxn(). * @param {*} txn An active transaction. See doTxn().
*/ */
storeEndToEndDeviceData(deviceData, txn) { storeEndToEndDeviceData(deviceData, txn) {
this._backendPromise.value().storeEndToEndDeviceData(deviceData, txn); this._backendPromise.then(backend => {
backend.storeEndToEndDeviceData(deviceData, txn);
});
} }
/** /**
@@ -471,7 +499,9 @@ export default class IndexedDBCryptoStore {
* device data * device data
*/ */
getEndToEndDeviceData(txn, func) { getEndToEndDeviceData(txn, func) {
this._backendPromise.value().getEndToEndDeviceData(txn, func); this._backendPromise.then(backend => {
backend.getEndToEndDeviceData(txn, func);
});
} }
// End to End Rooms // End to End Rooms
@@ -483,7 +513,9 @@ export default class IndexedDBCryptoStore {
* @param {*} txn An active transaction. See doTxn(). * @param {*} txn An active transaction. See doTxn().
*/ */
storeEndToEndRoom(roomId, roomInfo, txn) { storeEndToEndRoom(roomId, roomInfo, txn) {
this._backendPromise.value().storeEndToEndRoom(roomId, roomInfo, txn); this._backendPromise.then(backend => {
backend.storeEndToEndRoom(roomId, roomInfo, txn);
});
} }
/** /**
@@ -492,7 +524,9 @@ export default class IndexedDBCryptoStore {
* @param {function(Object)} func Function called with the end to end encrypted rooms * @param {function(Object)} func Function called with the end to end encrypted rooms
*/ */
getEndToEndRooms(txn, func) { getEndToEndRooms(txn, func) {
this._backendPromise.value().getEndToEndRooms(txn, func); this._backendPromise.then(backend => {
backend.getEndToEndRooms(txn, func);
});
} }
// session backups // session backups

View File

@@ -17,6 +17,7 @@ limitations under the License.
import Promise from 'bluebird'; import Promise from 'bluebird';
import logger from '../logger'; import logger from '../logger';
import {defer} from '../utils';
/** /**
* An IndexedDB store backend where the actual backend sits in a web * An IndexedDB store backend where the actual backend sits in a web
@@ -152,7 +153,7 @@ RemoteIndexedDBStoreBackend.prototype = {
// the promise automatically gets rejected // the promise automatically gets rejected
return Promise.resolve().then(() => { return Promise.resolve().then(() => {
const seq = this._nextSeq++; const seq = this._nextSeq++;
const def = Promise.defer(); const def = defer();
this._inFlight[seq] = def; this._inFlight[seq] = def;

View File

@@ -718,3 +718,16 @@ module.exports.sleep = (ms, value) => new Promise((resolve => {
module.exports.isNullOrUndefined = function(val) { module.exports.isNullOrUndefined = function(val) {
return val === null || val === undefined; return val === null || val === undefined;
}; };
// Returns a Deferred
module.exports.defer = () => {
let resolve;
let reject;
const promise = new Promise((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
});
return {resolve, reject, promise};
};