From a15dffbb3abfceeac19b94c8f9ba1a9b51ce12de Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Sat, 17 Sep 2016 17:44:15 +0100 Subject: [PATCH] Pull user device list on join When a new user joins a room, make sure we download their device list if we don't already have it. This should fix at least one cause of https://github.com/vector-im/vector-web/issues/2249. --- lib/crypto/algorithms/megolm.js | 27 +++++++++++++++++++++++++-- lib/crypto/index.js | 7 ++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/lib/crypto/algorithms/megolm.js b/lib/crypto/algorithms/megolm.js index 58321978d..695cb615d 100644 --- a/lib/crypto/algorithms/megolm.js +++ b/lib/crypto/algorithms/megolm.js @@ -169,7 +169,11 @@ MegolmEncryption.prototype._prepareNewSession = function(room) { * @private * * @param {string} session_id + * * @param {Object|boolean>} shareMap + * Map from userid to true (meaning this is a new user in the room, so all + * of his devices need the keys), or a map from deviceid to true (meaning + * this user has one or more new devices, which need the keys). * * @return {module:client.Promise} Promise which resolves once the key sharing * message has been sent. @@ -189,6 +193,9 @@ MegolmEncryption.prototype._shareKeyWithDevices = function(session_id, shareMap) } }; + // we downloaded the user's device list when they joined the room, or when + // the new device announced itself, so there is no need to do so now. + return self._crypto.ensureOlmSessionsForUsers( utils.keys(shareMap) ).then(function(devicemap) { @@ -292,8 +299,7 @@ MegolmEncryption.prototype.onRoomMembership = function(event, member, oldMembers var newMembership = member.membership; if (newMembership === 'join') { - // new member in the room. - this._devicesPendingKeyShare[member.userId] = true; + this._onNewRoomMember(member.userId); return; } @@ -318,6 +324,23 @@ MegolmEncryption.prototype.onRoomMembership = function(event, member, oldMembers } }; +/** + * handle a new user joining a room + * + * @param {string} userId new member + */ +MegolmEncryption.prototype._onNewRoomMember = function(userId) { + // make sure we have a list of this user's devices. We are happy to use a + // cached version here: we assume that if we already have a list of the + // user's devices, then we already share an e2e room with them, which means + // that they will have announced any new devices via an m.new_device. + this._crypto.downloadKeys([userId], false).done(); + + // also flag this user up for needing a keyshare. + this._devicesPendingKeyShare[userId] = true; +}; + + /** * @inheritdoc * diff --git a/lib/crypto/index.js b/lib/crypto/index.js index b1b8a294e..dc4ff67f4 100644 --- a/lib/crypto/index.js +++ b/lib/crypto/index.js @@ -1042,9 +1042,10 @@ Crypto.prototype._onRoomKeyEvent = function(event) { */ Crypto.prototype._onRoomMembership = function(event, member, oldMembership) { - // this event handler is registered on the *client* (as opposed to the - // room member itself), which means it is only called on changes to the - // *live* membership state (ie, it is not called when we back-paginate). + // this event handler is registered on the *client* (as opposed to the room + // member itself), which means it is only called on changes to the *live* + // membership state (ie, it is not called when we back-paginate, nor when + // we load the state in the initialsync). // // Further, it is automatically registered and called when new members // arrive in the room.