浏览代码

Smacks: Handle MUC messages received before the MUC exists

JC Brand 5 年之前
父节点
当前提交
0137eb88ae
共有 6 个文件被更改,包括 117 次插入14 次删除
  1. 7 7
      package-lock.json
  2. 88 0
      spec/smacks.js
  3. 0 4
      src/headless/converse-mam.js
  4. 15 0
      src/headless/converse-muc.js
  5. 6 2
      tests/mock.js
  6. 1 1
      webpack.html

+ 7 - 7
package-lock.json

@@ -14188,7 +14188,7 @@
 				},
 				},
 				"camelcase-keys": {
 				"camelcase-keys": {
 					"version": "2.1.0",
 					"version": "2.1.0",
-					"resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+					"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
 					"integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
 					"integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
 					"dev": true,
 					"dev": true,
 					"requires": {
 					"requires": {
@@ -14198,7 +14198,7 @@
 				},
 				},
 				"chalk": {
 				"chalk": {
 					"version": "1.1.3",
 					"version": "1.1.3",
-					"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+					"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
 					"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
 					"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
 					"dev": true,
 					"dev": true,
 					"requires": {
 					"requires": {
@@ -14240,7 +14240,7 @@
 				},
 				},
 				"load-json-file": {
 				"load-json-file": {
 					"version": "1.1.0",
 					"version": "1.1.0",
-					"resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+					"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
 					"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
 					"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
 					"dev": true,
 					"dev": true,
 					"requires": {
 					"requires": {
@@ -14259,7 +14259,7 @@
 				},
 				},
 				"meow": {
 				"meow": {
 					"version": "3.7.0",
 					"version": "3.7.0",
-					"resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+					"resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
 					"integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
 					"integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
 					"dev": true,
 					"dev": true,
 					"requires": {
 					"requires": {
@@ -19126,7 +19126,7 @@
 		},
 		},
 		"pinkie-promise": {
 		"pinkie-promise": {
 			"version": "2.0.1",
 			"version": "2.0.1",
-			"resolved": "http://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+			"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
 			"integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
 			"integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
 			"dev": true,
 			"dev": true,
 			"requires": {
 			"requires": {
@@ -20617,7 +20617,7 @@
 				},
 				},
 				"load-json-file": {
 				"load-json-file": {
 					"version": "1.1.0",
 					"version": "1.1.0",
-					"resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+					"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
 					"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
 					"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
 					"dev": true,
 					"dev": true,
 					"requires": {
 					"requires": {
@@ -20630,7 +20630,7 @@
 				},
 				},
 				"os-locale": {
 				"os-locale": {
 					"version": "1.4.0",
 					"version": "1.4.0",
-					"resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
+					"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
 					"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
 					"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
 					"dev": true,
 					"dev": true,
 					"requires": {
 					"requires": {

+ 88 - 0
spec/smacks.js

@@ -3,6 +3,7 @@
 } (this, function (jasmine, mock, test_utils) {
 } (this, function (jasmine, mock, test_utils) {
     "use strict";
     "use strict";
     const $iq = converse.env.$iq;
     const $iq = converse.env.$iq;
+    const $msg = converse.env.$msg;
     const Strophe = converse.env.Strophe;
     const Strophe = converse.env.Strophe;
     const sizzle = converse.env.sizzle;
     const sizzle = converse.env.sizzle;
     const u = converse.env.utils;
     const u = converse.env.utils;
@@ -178,5 +179,92 @@
             await test_utils.waitForRoster(_converse, 'current', 1);
             await test_utils.waitForRoster(_converse, 'current', 1);
             done();
             done();
         }));
         }));
+
+
+        it("can cause MUC messages to be received before chatboxes are initialized",
+            mock.initConverse(
+                ['chatBoxesInitialized'],
+                { 'auto_login': false,
+                  'enable_smacks': true,
+                  'show_controlbox_by_default': true,
+                  'blacklisted_plugins': 'converse-mam',
+                  'smacks_max_unacked_stanzas': 2
+                },
+                async function (done, _converse) {
+
+            const key = "converse-test-session/converse.session-romeo@montague.lit-converse.session-romeo@montague.lit";
+            sessionStorage.setItem(
+                key,
+                JSON.stringify({
+                    "id": "converse.session-romeo@montague.lit",
+                    "jid": "romeo@montague.lit/converse.js-100020907",
+                    "bare_jid": "romeo@montague.lit",
+                    "resource": "converse.js-100020907",
+                    "domain": "montague.lit",
+                    "active": false,
+                    "smacks_enabled": true,
+                    "num_stanzas_handled": 580,
+                    "num_stanzas_handled_by_server": 525,
+                    "num_stanzas_since_last_ack": 0,
+                    "unacked_stanzas": [],
+                    "smacks_stream_id": "some-long-sm-id",
+                    "push_enabled": ["romeo@montague.lit"],
+                    "carbons_enabled": true,
+                    "roster_cached": true
+                })
+            );
+
+            const muc_jid = 'lounge@montague.lit';
+            const chatkey = `converse.chatboxes-romeo@montague.lit-${muc_jid}`;
+            sessionStorage.setItem('converse.chatboxes-romeo@montague.lit', JSON.stringify([chatkey]));
+            sessionStorage.setItem(chatkey,
+                JSON.stringify({
+                    hidden: false,
+                    message_type: "groupchat",
+                    name: "lounge",
+                    num_unread: 0,
+                    type: "chatroom",
+                    jid: muc_jid,
+                    id: muc_jid,
+                    box_id: "box-YXJnQGNvbmZlcmVuY2UuY2hhdC5leGFtcGxlLm9yZw==",
+                    nick: "romeo"
+                })
+            );
+
+            _converse.no_connection_on_bind = true; // XXX Don't trigger CONNECTED in tests/mock.js
+            _converse.api.user.login('romeo@montague.lit', 'secret');
+            delete _converse.no_connection_on_bind;
+
+            const sent_stanzas = _converse.connection.sent_stanzas;
+            const stanza = await u.waitUntil(() => sent_stanzas.filter(s => (s.tagName === 'resume')).pop());
+            expect(Strophe.serialize(stanza)).toEqual('<resume h="580" previd="some-long-sm-id" xmlns="urn:xmpp:sm:3"/>');
+
+            const result = u.toStanza(`<resumed xmlns="urn:xmpp:sm:3" h="another-sequence-number" previd="some-long-sm-id"/>`);
+            _converse.connection._dataRecv(test_utils.createRequest(result));
+            expect(_converse.session.get('smacks_enabled')).toBe(true);
+
+            const func = _converse.chatboxes.onChatBoxesFetched;
+            spyOn(_converse.chatboxes, 'onChatBoxesFetched').and.callFake(collection => {
+                const muc = new _converse.ChatRoom({'jid': muc_jid, 'id': muc_jid}, {'collection': _converse.chatboxes});
+                _converse.chatboxes.add(muc);
+                func.call(_converse.chatboxes, collection);
+            });
+
+            // A MUC message gets received
+            const msg = $msg({
+                    from: `${muc_jid}/juliet`,
+                    id: u.getUniqueId(),
+                    to: 'romeo@montague.lit',
+                    type: 'groupchat'
+                }).c('body').t('First message').tree();
+
+            _converse.connection._dataRecv(test_utils.createRequest(msg));
+
+            await _converse.api.waitUntil('chatBoxesFetched');
+            const muc = _converse.chatboxes.get(muc_jid);
+            await u.waitUntil(() => muc.messages.length === 1);
+            expect(muc.messages.at(0).get('message')).toBe('First message')
+            done();
+        }));
     });
     });
 }));
 }));

+ 0 - 4
src/headless/converse-mam.js

@@ -130,10 +130,6 @@ converse.plugins.add('converse-mam', {
         Object.assign(_converse.ChatBox.prototype, MAMEnabledChat);
         Object.assign(_converse.ChatBox.prototype, MAMEnabledChat);
 
 
 
 
-        Object.assign(_converse.ChatRoom.prototype, {
-        });
-
-
         _converse.onMAMError = function (iq) {
         _converse.onMAMError = function (iq) {
             if (iq && iq.querySelectorAll('feature-not-implemented').length) {
             if (iq && iq.querySelectorAll('feature-not-implemented').length) {
                 log.warn("Message Archive Management (XEP-0313) not supported by this server");
                 log.warn("Message Archive Management (XEP-0313) not supported by this server");

+ 15 - 0
src/headless/converse-muc.js

@@ -2398,6 +2398,21 @@ converse.plugins.add('converse-muc', {
         _converse.api.listen.on('chatBoxesFetched', autoJoinRooms);
         _converse.api.listen.on('chatBoxesFetched', autoJoinRooms);
 
 
 
 
+        _converse.api.listen.on('beforeResourceBinding', () => {
+            _converse.connection.addHandler(stanza => {
+                const muc_jid = Strophe.getBareJidFromJid(stanza.getAttribute('from'));
+                if (!_converse.chatboxes.get(muc_jid)) {
+                    _converse.api.waitUntil('chatBoxesFetched')
+                        .then(() => {
+                            const muc = _converse.chatboxes.get(muc_jid);
+                            muc && muc.message_handler.run(stanza);
+                        });
+                }
+                return true;
+            }, null, 'message', 'groupchat')
+        });
+
+
         function disconnectChatRooms () {
         function disconnectChatRooms () {
             /* When disconnecting, mark all groupchats as
             /* When disconnecting, mark all groupchats as
              * disconnected, so that they will be properly entered again
              * disconnected, so that they will be properly entered again

+ 6 - 2
tests/mock.js

@@ -155,6 +155,8 @@
     };
     };
 
 
 
 
+    let _converse;
+
     const OriginalConnection = Strophe.Connection;
     const OriginalConnection = Strophe.Connection;
 
 
     function MockConnection (service, options) {
     function MockConnection (service, options) {
@@ -210,7 +212,9 @@
         this.bind = () => {
         this.bind = () => {
             this.authenticated = true;
             this.authenticated = true;
             this.authenticated = true;
             this.authenticated = true;
-            this._changeConnectStatus(Strophe.Status.CONNECTED);
+            if (!_converse.no_connection_on_bind) {
+                this._changeConnectStatus(Strophe.Status.CONNECTED);
+            }
         };
         };
 
 
         this._proto._disconnect = () => this._onDisconnectTimeout();
         this._proto._disconnect = () => this._onDisconnectTimeout();
@@ -254,7 +258,7 @@
         clearStores();
         clearStores();
         await clearIndexedDB();
         await clearIndexedDB();
 
 
-        const _converse = await converse.initialize(Object.assign({
+        _converse = await converse.initialize(Object.assign({
             'animate': false,
             'animate': false,
             'auto_subscribe': false,
             'auto_subscribe': false,
             'bosh_service_url': 'montague.lit/http-bind',
             'bosh_service_url': 'montague.lit/http-bind',

+ 1 - 1
webpack.html

@@ -29,7 +29,7 @@
         persistent_store: 'IndexedDB',
         persistent_store: 'IndexedDB',
         muc_domain: 'conference.chat.example.org',
         muc_domain: 'conference.chat.example.org',
         muc_respect_autojoin: true,
         muc_respect_autojoin: true,
-        view_mode: 'overlayed',
+        view_mode: 'fullscreen',
         websocket_url: 'ws://chat.example.org:5380/xmpp-websocket',
         websocket_url: 'ws://chat.example.org:5380/xmpp-websocket',
         // bosh_service_url: 'http://chat.example.org:5280/http-bind',
         // bosh_service_url: 'http://chat.example.org:5280/http-bind',
         muc_show_logs_before_join: true,
         muc_show_logs_before_join: true,