1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-08-09 10:22:46 +03:00

Merge branch 'develop' into kegan/indexeddb

This commit is contained in:
Kegan Dougal
2017-02-10 16:11:05 +00:00
12 changed files with 256 additions and 85 deletions

View File

@@ -52,21 +52,21 @@ export default function TestClient(userId, deviceId, accessToken) {
/**
* start the client, and wait for it to initialise.
*
* @param {object?} existingDevices the list of our existing devices to return from
* the /query request. Defaults to empty device list
* @return {Promise}
*/
TestClient.prototype.start = function(existingDevices) {
TestClient.prototype.start = function() {
this.httpBackend.when("GET", "/pushrules").respond(200, {});
this.httpBackend.when("POST", "/filter").respond(200, { filter_id: "fid" });
this.expectKeyUpload(existingDevices);
this.expectKeyUpload();
this.client.startClient({
// set this so that we can get hold of failed events
pendingEventOrdering: 'detached',
});
return this.httpBackend.flush();
return this.httpBackend.flush().then(() => {
console.log('TestClient[' + this.userId + ']: started');
});
};
/**
@@ -78,22 +78,9 @@ TestClient.prototype.stop = function() {
/**
* Set up expectations that the client will upload device and one-time keys.
*
* @param {object?} existingDevices the list of our existing devices to return from
* the /query request. Defaults to empty device list
*/
TestClient.prototype.expectKeyUpload = function(existingDevices) {
TestClient.prototype.expectKeyUpload = function() {
const self = this;
this.httpBackend.when('POST', '/keys/query').respond(200, function(path, content) {
expect(Object.keys(content.device_keys)).toEqual([self.userId]);
expect(content.device_keys[self.userId]).toEqual({});
let res = existingDevices;
if (!res) {
res = { device_keys: {} };
res.device_keys[self.userId] = {};
}
return res;
});
this.httpBackend.when("POST", "/keys/upload").respond(200, function(path, content) {
expect(content.one_time_keys).toBe(undefined);
expect(content.device_keys).toBeTruthy();
@@ -111,6 +98,24 @@ TestClient.prototype.expectKeyUpload = function(existingDevices) {
});
};
/**
* Set up expectations that the client will query device keys.
*
* We check that the query contains each of the users in `response`.
*
* @param {Object} response response to the query.
*/
TestClient.prototype.expectKeyQuery = function(response) {
this.httpBackend.when('POST', '/keys/query').respond(
200, (path, content) => {
Object.keys(response.device_keys).forEach((userId) => {
expect(content.device_keys[userId]).toEqual({});
});
return response;
});
};
/**
* get the uploaded curve25519 device key
*

View File

@@ -393,7 +393,9 @@ describe("MatrixClient crypto", function() {
afterEach(function() {
aliTestClient.stop();
aliTestClient.httpBackend.verifyNoOutstandingExpectation();
bobTestClient.stop();
bobTestClient.httpBackend.verifyNoOutstandingExpectation();
});
it('Ali knows the difference between a new user and one with no devices',
@@ -620,16 +622,13 @@ describe("MatrixClient crypto", function() {
.then(function() {
aliTestClient.client.setDeviceBlocked(bobUserId, bobDeviceId, true);
const p1 = sendMessage(aliTestClient.client);
const p2 = expectAliQueryKeys()
.then(expectAliClaimKeys)
.then(function() {
return expectSendMessageRequest(aliTestClient.httpBackend);
}).then(function(sentContent) {
// no unblocked devices, so the ciphertext should be empty
expect(sentContent.ciphertext).toEqual({});
});
const p2 = expectSendMessageRequest(aliTestClient.httpBackend)
.then(function(sentContent) {
// no unblocked devices, so the ciphertext should be empty
expect(sentContent.ciphertext).toEqual({});
});
return q.all([p1, p2]);
}).catch(testUtils.failTest).nodeify(done);
}).nodeify(done);
});
it("Bob receives two pre-key messages", function(done) {
@@ -685,4 +684,44 @@ describe("MatrixClient crypto", function() {
}).then(expectAliQueryKeys)
.nodeify(done);
});
it("Ali does a key query when encryption is enabled", function(done) {
// enabling encryption in the room should make alice download devices
// for both members.
q()
.then(() => startClient(aliTestClient))
.then(() => {
const syncData = {
next_batch: '2',
rooms: {
join: {},
},
};
syncData.rooms.join[roomId] = {
state: {
events: [
testUtils.mkEvent({
type: 'm.room.encryption',
skey: '',
content: {
algorithm: 'm.olm.v1.curve25519-aes-sha2',
},
}),
],
},
};
aliTestClient.httpBackend.when('GET', '/sync').respond(
200, syncData);
return aliTestClient.httpBackend.flush('/sync', 1);
}).then(() => {
aliTestClient.expectKeyQuery({
device_keys: {
[aliUserId]: {},
[bobUserId]: {},
},
});
return aliTestClient.httpBackend.flush('/keys/query', 1);
}).nodeify(done);
});
});

View File

@@ -351,7 +351,6 @@ describe("MatrixClient", function() {
httpBackend.when("POST", "/keys/query").check(function(req) {
expect(req.data).toEqual({device_keys: {
'@alice:localhost': {},
'boris': {},
'chaz': {},
}});

View File

@@ -349,6 +349,69 @@ describe("megolm", function() {
}).nodeify(done);
});
it("Alice receives a megolm message before the session keys", function(done) {
// https://github.com/vector-im/riot-web/issues/2273
let roomKeyEncrypted;
return aliceTestClient.start().then(function() {
const p2pSession = createOlmSession(testOlmAccount, aliceTestClient);
const groupSession = new Olm.OutboundGroupSession();
groupSession.create();
// make the room_key event, but don't send it yet
roomKeyEncrypted = encryptGroupSessionKey({
senderKey: testSenderKey,
recipient: aliceTestClient,
p2pSession: p2pSession,
groupSession: groupSession,
room_id: ROOM_ID,
});
// encrypt a message with the group session
const messageEncrypted = encryptMegolmEvent({
senderKey: testSenderKey,
groupSession: groupSession,
room_id: ROOM_ID,
});
// Alice just gets the message event to start with
const syncResponse = {
next_batch: 1,
rooms: {
join: {},
},
};
syncResponse.rooms.join[ROOM_ID] = {
timeline: {
events: [messageEncrypted],
},
};
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse);
return aliceTestClient.httpBackend.flush("/sync", 1);
}).then(function() {
const room = aliceTestClient.client.getRoom(ROOM_ID);
const event = room.getLiveTimeline().getEvents()[0];
expect(event.getContent().msgtype).toEqual('m.bad.encrypted');
// now she gets the room_key event
const syncResponse = {
next_batch: 2,
to_device: {
events: [roomKeyEncrypted],
},
};
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse);
return aliceTestClient.httpBackend.flush("/sync", 1);
}).then(function() {
const room = aliceTestClient.client.getRoom(ROOM_ID);
const event = room.getLiveTimeline().getEvents()[0];
expect(event.getContent().body).toEqual('42');
}).nodeify(done);
});
it("Alice gets a second room_key message", function(done) {
return aliceTestClient.start().then(function() {
const p2pSession = createOlmSession(testOlmAccount, aliceTestClient);
@@ -672,9 +735,7 @@ describe("megolm", function() {
let inboundGroupSession;
let decrypted;
return aliceTestClient.start(
getTestKeysQueryResponse(aliceTestClient.userId),
).then(function() {
return aliceTestClient.start().then(function() {
// an encrypted room with just alice
const syncResponse = {
next_batch: 1,
@@ -701,6 +762,13 @@ describe("megolm", function() {
};
aliceTestClient.httpBackend.when('GET', '/sync').respond(200, syncResponse);
// the completion of the first initialsync hould make Alice
// invalidate the device cache for all members in e2e rooms (ie,
// herself), and do a key query.
aliceTestClient.expectKeyQuery(
getTestKeysQueryResponse(aliceTestClient.userId),
);
return aliceTestClient.httpBackend.flush();
}).then(function() {
aliceTestClient.client.setDeviceKnown(aliceTestClient.userId, 'DEVICE_ID');

View File

@@ -49,17 +49,17 @@ HttpBackend.prototype = {
const tryFlush = function() {
// if there's more real requests and more expected requests, flush 'em.
console.log(
" trying to flush queue => reqs=%s expected=%s [%s]",
self.requests.length, self.expectedRequests.length, path,
" trying to flush queue => reqs=[%s] expected=[%s]",
self.requests, self.expectedRequests.map((er) => er.path),
);
if (self._takeFromQueue(path)) {
// try again on the next tick.
console.log(" flushed. Trying for more. [%s]", path);
flushed += 1;
if (numToFlush && flushed === numToFlush) {
console.log(" [%s] Flushed assigned amount: %s", path, numToFlush);
console.log(" Flushed assigned amount: %s", numToFlush);
defer.resolve();
} else {
console.log(" flushed. Trying for more.");
setTimeout(tryFlush, 0);
}
} else if (flushed === 0 && !triedWaiting) {
@@ -68,7 +68,7 @@ HttpBackend.prototype = {
setTimeout(tryFlush, 5);
triedWaiting = true;
} else {
console.log(" no more flushes. [%s]", path);
console.log(" no more flushes.");
defer.resolve();
}
};