omemo.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. (function (root, factory) {
  2. define(["jasmine", "mock", "converse-core", "test-utils"], factory);
  3. } (this, function (jasmine, mock, converse, test_utils) {
  4. var Strophe = converse.env.Strophe;
  5. var b64_sha1 = converse.env.b64_sha1;
  6. var $iq = converse.env.$iq;
  7. var _ = converse.env._;
  8. window.libsignal = {
  9. 'KeyHelper': {
  10. 'generateIdentityKeyPair': function () {
  11. return Promise.resolve({
  12. 'pubKey': 1234,
  13. 'privKey': 4321
  14. });
  15. },
  16. 'generateRegistrationId': function () {
  17. return '31415';
  18. },
  19. 'generatePreKey': function (keyid) {
  20. return Promise.resolve({
  21. 'keyId': keyid,
  22. 'keyPair': {
  23. 'pubKey': 1234,
  24. 'privKey': 4321
  25. }
  26. });
  27. },
  28. 'generateSignedPreKey': function (identity_keypair, keyid) {
  29. return Promise.resolve({
  30. 'keyId': keyid,
  31. 'keyPair': {
  32. 'pubKey': 1234,
  33. 'privKey': 4321
  34. }
  35. });
  36. }
  37. }
  38. };
  39. describe("The OMEMO module", function() {
  40. it("will add processing hints to sent out encrypted <message> stanzas",
  41. mock.initConverseWithPromises(
  42. null, ['rosterGroupsFetched'], {},
  43. function (done, _converse) {
  44. // TODO
  45. done();
  46. }));
  47. it("adds a toolbar button for starting an encrypted chat session",
  48. mock.initConverseWithPromises(
  49. null, ['rosterGroupsFetched'], {},
  50. function (done, _converse) {
  51. let iq_stanza;
  52. test_utils.createContacts(_converse, 'current');
  53. const contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost';
  54. test_utils.waitUntil(function () {
  55. return _.filter(_converse.connection.IQ_stanzas, function (iq) {
  56. const node = iq.nodeTree.querySelector('publish[node="eu.siacs.conversations.axolotl.bundles:31415"]');
  57. if (node) { iq_stanza = iq.nodeTree; }
  58. return node;
  59. }).length;
  60. }).then(function () {
  61. expect(iq_stanza.getAttributeNames().sort().join()).toBe(["from", "type", "xmlns", "id"].sort().join());
  62. expect(iq_stanza.querySelector('prekeys').childNodes.length).toBe(100);
  63. const signed_prekeys = iq_stanza.querySelectorAll('signedPreKeyPublic');
  64. expect(signed_prekeys.length).toBe(1);
  65. const signed_prekey = signed_prekeys[0];
  66. expect(signed_prekey.getAttribute('signedPreKeyId')).toBe('0')
  67. expect(iq_stanza.querySelectorAll('signedPreKeySignature').length).toBe(1);
  68. expect(iq_stanza.querySelectorAll('identityKey').length).toBe(1);
  69. const stanza = $iq({
  70. 'from': _converse.bare_jid,
  71. 'id': iq_stanza.getAttribute('id'),
  72. 'to': _converse.bare_jid,
  73. 'type': 'result'});
  74. _converse.connection._dataRecv(test_utils.createRequest(stanza));
  75. return test_utils.waitUntil(() => {
  76. return _.filter(
  77. _converse.connection.IQ_stanzas,
  78. (iq) => {
  79. const node = iq.nodeTree.querySelector('iq[to="'+_converse.bare_jid+'"] query[node="eu.siacs.conversations.axolotl.devicelist"]');
  80. if (node) { iq_stanza = iq.nodeTree;}
  81. return node;
  82. }).length;
  83. });
  84. }).then(function () {
  85. expect(iq_stanza.outerHTML).toBe(
  86. '<iq type="get" from="dummy@localhost" to="dummy@localhost" xmlns="jabber:client" id="'+iq_stanza.getAttribute("id")+'">'+
  87. '<query xmlns="http://jabber.org/protocol/disco#items" '+
  88. 'node="eu.siacs.conversations.axolotl.devicelist"/>'+
  89. '</iq>');
  90. const stanza = $iq({
  91. 'from': contact_jid,
  92. 'id': iq_stanza.getAttribute('id'),
  93. 'to': _converse.bare_jid,
  94. 'type': 'result',
  95. }).c('query', {
  96. 'xmlns': 'http://jabber.org/protocol/disco#items',
  97. 'node': 'eu.siacs.conversations.axolotl.devicelist'
  98. }).c('device', {'id': '482886413b977930064a5888b92134fe'}).up()
  99. _converse.connection._dataRecv(test_utils.createRequest(stanza));
  100. expect(_converse.devicelists.length).toBe(1);
  101. const devicelist = _converse.devicelists.get(_converse.bare_jid);
  102. expect(devicelist.devices.length).toBe(1);
  103. expect(devicelist.devices.at(0).get('id')).toBe('482886413b977930064a5888b92134fe');
  104. test_utils.openChatBoxFor(_converse, contact_jid);
  105. return test_utils.waitUntil(() => {
  106. return _.filter(
  107. _converse.connection.IQ_stanzas,
  108. (iq) => {
  109. const node = iq.nodeTree.querySelector('iq[to="'+contact_jid+'"] query[node="eu.siacs.conversations.axolotl.devicelist"]');
  110. if (node) { iq_stanza = iq.nodeTree; }
  111. return node;
  112. }).length;});
  113. }).then(function () {
  114. expect(iq_stanza.outerHTML).toBe(
  115. '<iq type="get" from="dummy@localhost" to="'+contact_jid+'" xmlns="jabber:client" id="'+iq_stanza.getAttribute("id")+'">'+
  116. '<query xmlns="http://jabber.org/protocol/disco#items" '+
  117. 'node="eu.siacs.conversations.axolotl.devicelist"/>'+
  118. '</iq>');
  119. const stanza = $iq({
  120. 'from': contact_jid,
  121. 'id': iq_stanza.getAttribute('id'),
  122. 'to': _converse.bare_jid,
  123. 'type': 'result',
  124. }).c('query', {
  125. 'xmlns': 'http://jabber.org/protocol/disco#items',
  126. 'node': 'eu.siacs.conversations.axolotl.devicelist'
  127. }).c('device', {'id': '368866411b877c30064a5f62b917cffe'}).up()
  128. .c('device', {'id': '3300659945416e274474e469a1f0154c'}).up()
  129. .c('device', {'id': '4e30f35051b7b8b42abe083742187228'}).up()
  130. .c('device', {'id': 'ae890ac52d0df67ed7cfdf51b644e901'});
  131. _converse.connection._dataRecv(test_utils.createRequest(stanza));
  132. expect(_converse.devicelists.length).toBe(2);
  133. const devicelist = _converse.devicelists.get(contact_jid);
  134. expect(devicelist.devices.length).toBe(4);
  135. expect(devicelist.devices.at(0).get('id')).toBe('368866411b877c30064a5f62b917cffe');
  136. expect(devicelist.devices.at(1).get('id')).toBe('3300659945416e274474e469a1f0154c');
  137. expect(devicelist.devices.at(2).get('id')).toBe('4e30f35051b7b8b42abe083742187228');
  138. expect(devicelist.devices.at(3).get('id')).toBe('ae890ac52d0df67ed7cfdf51b644e901');
  139. return test_utils.waitUntil(() => _converse.chatboxviews.get(contact_jid).el.querySelector('.chat-toolbar'));
  140. }).then(function () {
  141. const view = _converse.chatboxviews.get(contact_jid);
  142. const toolbar = view.el.querySelector('.chat-toolbar');
  143. expect(_.isNull(toolbar.querySelector('.toggle-omemo'))).toBe(false);
  144. spyOn(view, 'toggleOMEMO').and.callThrough();
  145. view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
  146. toolbar.querySelector('.toggle-omemo').click();
  147. expect(view.toggleOMEMO).toHaveBeenCalled();
  148. done();
  149. }).catch(_.partial(console.error, _));
  150. }));
  151. });
  152. describe("A chatbox with an active OMEMO session", function() {
  153. it("will not show the spoiler toolbar button",
  154. mock.initConverseWithPromises(
  155. null, ['rosterGroupsFetched'], {},
  156. function (done, _converse) {
  157. // TODO
  158. done()
  159. }));
  160. });
  161. }));