diff --git a/spec/omemo.js b/spec/omemo.js index c2a377dba..aa03b1655 100644 --- a/spec/omemo.js +++ b/spec/omemo.js @@ -6,38 +6,6 @@ var $iq = converse.env.$iq; var _ = converse.env._; - window.libsignal = { - 'KeyHelper': { - 'generateIdentityKeyPair': function () { - return Promise.resolve({ - 'pubKey': 1234, - 'privKey': 4321 - }); - }, - 'generateRegistrationId': function () { - return '31415'; - }, - 'generatePreKey': function (keyid) { - return Promise.resolve({ - 'keyId': keyid, - 'keyPair': { - 'pubKey': 1234, - 'privKey': 4321 - } - }); - }, - 'generateSignedPreKey': function (identity_keypair, keyid) { - return Promise.resolve({ - 'keyId': keyid, - 'keyPair': { - 'pubKey': 1234, - 'privKey': 4321 - } - }); - } - } - }; - describe("The OMEMO module", function() { it("will add processing hints to sent out encrypted stanzas", @@ -114,6 +82,31 @@ expect(devicelist.devices.at(0).get('id')).toBe('482886413b977930064a5888b92134fe'); test_utils.openChatBoxFor(_converse, contact_jid); + return test_utils.waitUntil(() => { + return _.filter(_converse.connection.IQ_stanzas, function (iq) { + const node = iq.nodeTree.querySelector('publish[xmlns="eu.siacs.conversations.axolotl.devicelist"]'); + if (node) { iq_stanza = iq.nodeTree; } + return node; + }).length; + }); + }).then(function () { + expect(iq_stanza.outerHTML).toBe( + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''); + const stanza = $iq({ + 'from': _converse.bare_jid, + 'id': iq_stanza.getAttribute('id'), + 'to': _converse.bare_jid, + 'type': 'result'}); + _converse.connection._dataRecv(test_utils.createRequest(stanza)); return test_utils.waitUntil(() => { return _.filter( _converse.connection.IQ_stanzas, diff --git a/spec/presence.js b/spec/presence.js index 0a4390d01..f77cdaa2b 100644 --- a/spec/presence.js +++ b/spec/presence.js @@ -47,7 +47,7 @@ ""+ "Hello world"+ "0"+ - ""+ + ""+ "" ); _converse.priority = 2; @@ -57,7 +57,7 @@ "away"+ "Going jogging"+ "2"+ - ""+ + ""+ "" ); @@ -68,7 +68,7 @@ "dnd"+ "Doing taxes"+ "0"+ - ""+ + ""+ "" ); })); @@ -97,7 +97,7 @@ .toBe(""+ "My custom status"+ "0"+ - ""+ + ""+ "") return test_utils.waitUntil(function () { @@ -113,7 +113,7 @@ modal.el.querySelector('[type="submit"]').click(); expect(_converse.connection.send.calls.mostRecent().args[0].toLocaleString()) .toBe("dndMy custom status0"+ - ""+ + ""+ "") done(); }); diff --git a/src/converse-omemo.js b/src/converse-omemo.js index a10398d8b..44e8a984f 100644 --- a/src/converse-omemo.js +++ b/src/converse-omemo.js @@ -188,6 +188,27 @@ reject, _converse.IQ_TIMEOUT); }); + }, + + addDeviceToList () { + /* Add this device to our list of devices stored on the + * server. + * https://xmpp.org/extensions/xep-0384.html#usecases-announcing + */ + return new Promise((resolve, reject) => { + const stanza = $iq({ + 'from': _converse.bare_jid, + 'type': 'set' + }).c('pubsub', {'xmlns': Strophe.NS.PUBSUB}) + .c('publish', {'xmlns': Strophe.NS.OMEMO_DEVICELIST}) + .c('item') + .c('list', {'xmlns': Strophe.NS.OMEMO}).up() + + this.devices.each((device) => { + stanza.c('device', {'id': device.get('id')}).up(); + }); + _converse.connection.sendIQ(stanza, resolve, reject, _converse.IQ_TIMEOUT); + }).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR)); } }); @@ -226,10 +247,7 @@ return new Promise((resolve, reject) => _converse.devicelists.fetch({'success': resolve})); } - function updateOwnDeviceList () { - /* If our own device is not on the list, add it. - * Also, deduplicate devices if necessary. - */ + function fetchOwnDevices () { return new Promise((resolve, reject) => { fetchDeviceLists().then(() => { let own_devicelist = _converse.devicelists.get(_converse.bare_jid); @@ -237,12 +255,23 @@ own_devicelist = _converse.devicelists.create({'jid': _converse.bare_jid}); } own_devicelist.fetchDevices().then(resolve).catch(reject); - // TODO: if our own device is not onthe list, add it. - // TODO: deduplicate }); }); } + function updateOwnDeviceList () { + /* If our own device is not on the list, add it. + * Also, deduplicate devices if necessary. + */ + return new Promise((resolve, reject) => { + const devicelist = _converse.devicelists.get(_converse.bare_jid); + if (!devicelist.devices.findWhere({'id': _converse.omemo_store.get('device_id')})) { + return devicelist.addDeviceToList().then(resolve).catch(reject); + } + resolve(); + }); + } + function updateDevicesFromStanza (stanza) { // TODO: check whether our own device_id is still on the list, // otherwise we need to update it. @@ -268,6 +297,7 @@ _converse.connection.addHandler((message) => { if (message.querySelector('event[xmlns="'+Strophe.NS.PUBSUB+'#event"]')) { updateDevicesFromStanza(message); + updateOwnDeviceList(); } }, null, 'message', 'headline', null, _converse.bare_jid); } @@ -298,6 +328,7 @@ ); restoreOMEMOSession() .then(() => publishBundle()) + .then(() => fetchOwnDevices()) .then(() => updateOwnDeviceList()) .then(() => _converse.emit('OMEMOInitialized')) .catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR)); diff --git a/tests/mock.js b/tests/mock.js index 1f5fa2e64..8b9969812 100644 --- a/tests/mock.js +++ b/tests/mock.js @@ -5,8 +5,40 @@ var Promise = converse.env.Promise; var Strophe = converse.env.Strophe; var $iq = converse.env.$iq; - var mock = {}; + window.libsignal = { + 'KeyHelper': { + 'generateIdentityKeyPair': function () { + return Promise.resolve({ + 'pubKey': 1234, + 'privKey': 4321 + }); + }, + 'generateRegistrationId': function () { + return '31415'; + }, + 'generatePreKey': function (keyid) { + return Promise.resolve({ + 'keyId': keyid, + 'keyPair': { + 'pubKey': 1234, + 'privKey': 4321 + } + }); + }, + 'generateSignedPreKey': function (identity_keypair, keyid) { + return Promise.resolve({ + 'keyId': keyid, + 'keyPair': { + 'pubKey': 1234, + 'privKey': 4321 + } + }); + } + } + }; + + var mock = {}; mock.view_mode = 'overlayed'; // Names from http://www.fakenamegenerator.com/