diff --git a/lib/client.js b/lib/client.js index 7f19ad7e1..ccef2626c 100644 --- a/lib/client.js +++ b/lib/client.js @@ -378,10 +378,12 @@ MatrixClient.prototype.uploadKeys = function(maxKeys, deferred) { * store. * @param {Array} userIds The users to fetch. * @param {bool} forceDownload Always download the keys even if cached. - * @return {object} A promise that will resolve when the keys are downloadded. + * + * @return {object} A promise that will resolve when the keys are downloaded; + * resolves to a map userId->deviceId->device info */ MatrixClient.prototype.downloadKeys = function(userIds, forceDownload) { - if (!CRYPTO_ENABLED || this.sessionStore === null) { + if (this.sessionStore === null) { return q.reject(new Error("End-to-end encryption disabled")); } var stored = {}; @@ -399,30 +401,29 @@ MatrixClient.prototype.downloadKeys = function(userIds, forceDownload) { downloadKeys = true; notStored[userId] = {}; } - var deferred = q.defer(); - if (downloadKeys) { - var path = "/keys/query"; - var content = {device_keys: notStored}; - var self = this; - this._http.authedRequestWithPrefix( - undefined, "POST", path, undefined, content, - httpApi.PREFIX_UNSTABLE - ).then(function(res) { - for (var userId in res.device_keys) { - if (userId in notStored) { - self.sessionStore.storeEndToEndDevicesForUser( - userId, res.device_keys[userId] - ); - // TODO: validate the ed25519 signature. - stored[userId] = res.device_keys[userId]; - } - } - deferred.resolve(stored); - }); - } else { - deferred.resolve(stored); + + if (!downloadKeys) { + return q(stored); } - return deferred.promise; + + var path = "/keys/query"; + var content = {device_keys: notStored}; + var self = this; + return this._http.authedRequestWithPrefix( + undefined, "POST", path, undefined, content, + httpApi.PREFIX_UNSTABLE + ).then(function(res) { + for (var userId in res.device_keys) { + if (userId in notStored) { + self.sessionStore.storeEndToEndDevicesForUser( + userId, res.device_keys[userId] + ); + // TODO: validate the ed25519 signature. + stored[userId] = res.device_keys[userId]; + } + } + return stored; + }); }; /** diff --git a/spec/integ/matrix-client-methods.spec.js b/spec/integ/matrix-client-methods.spec.js index fb6567efe..c34ce6956 100644 --- a/spec/integ/matrix-client-methods.spec.js +++ b/spec/integ/matrix-client-methods.spec.js @@ -6,10 +6,11 @@ var Room = publicGlobals.Room; var MatrixInMemoryStore = publicGlobals.MatrixInMemoryStore; var Filter = publicGlobals.Filter; var utils = require("../test-utils"); +var MockStorageApi = require("../MockStorageApi"); describe("MatrixClient", function() { var baseUrl = "http://localhost.or.something"; - var client, httpBackend, store; + var client, httpBackend, store, sessionStore; var userId = "@alice:localhost"; var accessToken = "aseukfgwef"; @@ -17,12 +18,17 @@ describe("MatrixClient", function() { utils.beforeEach(this); httpBackend = new HttpBackend(); store = new MatrixInMemoryStore(); + + var mockStorage = new MockStorageApi(); + sessionStore = new sdk.WebStorageSessionStore(mockStorage); + sdk.request(httpBackend.requestFn); client = sdk.createClient({ baseUrl: baseUrl, userId: userId, accessToken: accessToken, - store: store + store: store, + sessionStore: sessionStore, }); }); @@ -173,4 +179,45 @@ describe("MatrixClient", function() { }); }); }); + + + describe("downloadKeys", function() { + it("should do an HTTP request and then store the keys", function(done) { + var borisKeys = {dev1: {a: 1}}; + var chazKeys = {dev2: {a: 2}}; + + httpBackend.when("POST", "/keys/query").check(function(req) { + expect(req.data).toEqual({device_keys: {boris: {}, chaz: {}}}); + }).respond(200, { + device_keys: { + boris: borisKeys, + chaz: chazKeys, + }, + }); + + client.downloadKeys(["boris", "chaz"]).then(function(res) { + expect(res).toEqual({ + boris: borisKeys, + chaz: chazKeys + }); + }).catch(utils.failTest).done(done); + + httpBackend.flush(); + }); + + it("should return a rejected promise if the request fails", function(done) { + httpBackend.when("POST", "/keys/query").respond(400); + + var exceptionThrown; + client.downloadKeys(["bottom"]).then(function() { + fail("download didn't fail"); + }, function(err) { + exceptionThrown = err; + }).then(function() { + expect(exceptionThrown).toBeTruthy(); + }).catch(utils.failTest).done(done); + + httpBackend.flush(); + }); + }); });