diff --git a/dist/converse.js b/dist/converse.js index cd96023ce..f121e38ef 100644 --- a/dist/converse.js +++ b/dist/converse.js @@ -73489,100 +73489,128 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ 'push_app_servers': [] }); - function disablePushAppServer(push_app_server) { + async function disablePushAppServer(domain, push_app_server) { if (!push_app_server.jid) { return; } - Promise.all([_converse.api.disco.supports(Strophe.NS.PUSH, _converse.bare_jid)]).then(result => { - if (!result[0].length && !result[1].length) { - return _converse.log(`Not disabling push app server "${push_app_server.jid}", no disco support from your server.`, Strophe.LogLevel.WARN); - } + const result = await _converse.api.disco.supports(Strophe.NS.PUSH, domain || _converse.bare_jid); - const stanza = $iq({ - 'type': 'set' - }).c('disable', { - 'xmlns': Strophe.NS.PUSH, - 'jid': push_app_server.jid + if (!result.length) { + return _converse.log(`Not disabling push app server "${push_app_server.jid}", no disco support from your server.`, Strophe.LogLevel.WARN); + } + + const stanza = $iq({ + 'type': 'set' + }); + + if (domain !== _converse.bare_jid) { + stanza.attrs({ + 'to': domain }); + } - if (push_app_server.node) { - stanza.attrs({ - 'node': push_app_server.node - }); - } + stanza.c('disable', { + 'xmlns': Strophe.NS.PUSH, + 'jid': push_app_server.jid + }); - _converse.api.sendIQ(stanza).then(() => _converse.session.set('push_enabled', true)).catch(e => { - _converse.log(`Could not enable push app server for ${push_app_server.jid}`, Strophe.LogLevel.ERROR); - - _converse.log(e, Strophe.LogLevel.ERROR); + if (push_app_server.node) { + stanza.attrs({ + 'node': push_app_server.node }); - }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); + } + + _converse.api.sendIQ(stanza).catch(e => { + _converse.log(`Could not disable push app server for ${push_app_server.jid}`, Strophe.LogLevel.ERROR); + + _converse.log(e, Strophe.LogLevel.ERROR); + }); } - function enablePushAppServer(push_app_server) { + async function enablePushAppServer(domain, push_app_server) { if (!push_app_server.jid || !push_app_server.node) { return; } - _converse.api.disco.getIdentity('pubsub', 'push', push_app_server.jid).then(identity => { - if (!identity) { - return _converse.log(`Not enabling push the service "${push_app_server.jid}", it doesn't have the right disco identtiy.`, Strophe.LogLevel.WARN); - } + const identity = await _converse.api.disco.getIdentity('pubsub', 'push', push_app_server.jid); - return Promise.all([_converse.api.disco.supports(Strophe.NS.PUSH, push_app_server.jid), _converse.api.disco.supports(Strophe.NS.PUSH, _converse.bare_jid)]).then(result => { - if (!result[0].length && !result[1].length) { - return _converse.log(`Not enabling push app server "${push_app_server.jid}", no disco support from your server.`, Strophe.LogLevel.WARN); - } + if (!identity) { + return _converse.log(`Not enabling push the service "${push_app_server.jid}", it doesn't have the right disco identtiy.`, Strophe.LogLevel.WARN); + } - const stanza = $iq({ - 'type': 'set' - }).c('enable', { - 'xmlns': Strophe.NS.PUSH, - 'jid': push_app_server.jid, - 'node': push_app_server.node - }); + const result = await Promise.all([_converse.api.disco.supports(Strophe.NS.PUSH, push_app_server.jid), _converse.api.disco.supports(Strophe.NS.PUSH, domain)]); - if (push_app_server.secret) { - stanza.c('x', { - 'xmlns': Strophe.NS.XFORM, - 'type': 'submit' - }).c('field', { - 'var': 'FORM_TYPE' - }).c('value').t(`${Strophe.NS.PUBSUB}#publish-options`).up().up().c('field', { - 'var': 'secret' - }).c('value').t(push_app_server.secret); - } + if (!result[0].length && !result[1].length) { + return _converse.log(`Not enabling push app server "${push_app_server.jid}", no disco support from your server.`, Strophe.LogLevel.WARN); + } - _converse.api.sendIQ(stanza).then(() => _converse.session.save('push_enabled', true)).catch(e => { - _converse.log(`Could not enable push app server for ${push_app_server.jid}`, Strophe.LogLevel.ERROR); + const stanza = $iq({ + 'type': 'set' + }); - _converse.log(e, Strophe.LogLevel.ERROR); - }); - }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); - }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); + if (domain !== _converse.bare_jid) { + stanza.attrs({ + 'to': domain + }); + } + + stanza.c('enable', { + 'xmlns': Strophe.NS.PUSH, + 'jid': push_app_server.jid, + 'node': push_app_server.node + }); + + if (push_app_server.secret) { + stanza.c('x', { + 'xmlns': Strophe.NS.XFORM, + 'type': 'submit' + }).c('field', { + 'var': 'FORM_TYPE' + }).c('value').t(`${Strophe.NS.PUBSUB}#publish-options`).up().up().c('field', { + 'var': 'secret' + }).c('value').t(push_app_server.secret); + } + + return _converse.api.sendIQ(stanza); } - function enablePush() { - if (_converse.session.get('push_enabled')) { - // XXX: this code is still a bit naive. We set push_enabled - // to true as soon as the first push app server has been set. - // - // When enabling or disabling multiple push app servers, - // we won't wait until we have confirmation that all have been set. + async function enablePush(domain) { + domain = domain || _converse.bare_jid; + const push_enabled = _converse.session.get('push_enabled') || []; + + if (_.includes(push_enabled, domain)) { return; } const enabled_services = _.reject(_converse.push_app_servers, 'disable'); - _.each(enabled_services, enablePushAppServer); + try { + await Promise.all(_.map(enabled_services, _.partial(enablePushAppServer, domain))); + } catch (e) { + _converse.log('Could not enable push App Server', Strophe.LogLevel.ERROR); + + if (e) _converse.log(e, Strophe.LogLevel.ERROR); + } finally { + push_enabled.push(domain); + } const disabled_services = _.filter(_converse.push_app_servers, 'disable'); - _.each(disabled_services, disablePushAppServer); + _.each(disabled_services, _.partial(disablePushAppServer, domain)); + + _converse.session.save('push_enabled', push_enabled); } - _converse.api.listen.on('statusInitialized', enablePush); + function onChatBoxAdded(model) { + if (model.get('type') == _converse.CHATROOMS_TYPE) { + enablePush(Strophe.getDomainFromJid(model.get('jid'))); + } + } + + _converse.api.listen.on('statusInitialized', () => enablePush()); + + _converse.api.listen.on('chatBoxesInitialized', () => _converse.chatboxes.on('add', onChatBoxAdded)); } }); diff --git a/spec/push.js b/spec/push.js index 975fa38aa..20bf667e0 100644 --- a/spec/push.js +++ b/spec/push.js @@ -5,6 +5,7 @@ var $iq = converse.env.$iq; var Strophe = converse.env.Strophe; var _ = converse.env._; + var f = converse.env.f; describe("XEP-0357 Push Notifications", function () { @@ -53,9 +54,48 @@ 'id': stanza.getAttribute('id') }))); return test_utils.waitUntil(() => _converse.session.get('push_enabled')) + }).then(done).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); + })); + + it("can enabled for a MUC domain", + mock.initConverseWithPromises(null, + ['rosterGroupsFetched'], { + 'push_app_servers': [{ + 'jid': 'push-5@client.example', + 'node': 'yxs32uqsflafdk3iuqo' + }] + }, function (done, _converse) { + + const IQ_stanzas = _converse.connection.IQ_stanzas, + room_jid = 'coven@chat.shakespeare.lit'; + expect(_converse.session.get('push_enabled')).toBeFalsy(); + + test_utils.openAndEnterChatRoom(_converse, 'coven', 'chat.shakespeare.lit', 'oldhag') + .then(() => test_utils.waitUntilDiscoConfirmed( + _converse, _converse.push_app_servers[0].jid, + [{'category': 'pubsub', 'type':'push'}], + ['urn:xmpp:push:0'], [], 'info')) + .then(() => { + return test_utils.waitUntilDiscoConfirmed( + _converse, 'chat.shakespeare.lit', + [{'category': 'account', 'type':'registered'}], + ['urn:xmpp:push:0'], [], 'info') }).then(() => { - done(); - }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); + return test_utils.waitUntil( + () => _.filter(IQ_stanzas, (iq) => iq.nodeTree.querySelector('iq[type="set"] enable[xmlns="urn:xmpp:push:0"]')).pop()) + }).then(stanza => { + expect(stanza.nodeTree.outerHTML).toEqual( + ``+ + ''+ + '' + ) + _converse.connection._dataRecv(test_utils.createRequest($iq({ + 'to': _converse.connection.jid, + 'type': 'result', + 'id': stanza.nodeTree.getAttribute('id') + }))); + return test_utils.waitUntil(() => f.includes('chat.shakespeare.lit', _converse.session.get('push_enabled'))); + }).then(done).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); })); it("can be disabled", @@ -100,9 +140,7 @@ 'id': stanza.getAttribute('id') }))); return test_utils.waitUntil(() => _converse.session.get('push_enabled')) - }).then(() => { - done(); - }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); + }).then(done).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); })); @@ -156,9 +194,7 @@ 'id': stanza.getAttribute('id') }))); return test_utils.waitUntil(() => _converse.session.get('push_enabled')) - }).then(() => { - done(); - }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); + }).then(done).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); })); }); })); diff --git a/src/converse-push.js b/src/converse-push.js index e1da96879..973d85fdc 100644 --- a/src/converse-push.js +++ b/src/converse-push.js @@ -30,98 +30,103 @@ 'push_app_servers': [], }); - function disablePushAppServer (push_app_server) { + async function disablePushAppServer (domain, push_app_server) { if (!push_app_server.jid) { return; } - Promise.all([ - _converse.api.disco.supports(Strophe.NS.PUSH, _converse.bare_jid) - ]).then(result => { - if (!result[0].length && !result[1].length) { - return _converse.log( - `Not disabling push app server "${push_app_server.jid}", no disco support from your server.`, - Strophe.LogLevel.WARN - ); - } - const stanza = $iq({'type': 'set'}) - .c('disable', { - 'xmlns': Strophe.NS.PUSH, - 'jid': push_app_server.jid, - }); - if (push_app_server.node) { - stanza.attrs({'node': push_app_server.node}); - } - - _converse.api.sendIQ(stanza) - .then(() => _converse.session.set('push_enabled', true)) - .catch((e) => { - _converse.log(`Could not enable push app server for ${push_app_server.jid}`, Strophe.LogLevel.ERROR); - _converse.log(e, Strophe.LogLevel.ERROR); - }); - }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); + const result = await _converse.api.disco.supports(Strophe.NS.PUSH, domain || _converse.bare_jid) + if (!result.length) { + return _converse.log( + `Not disabling push app server "${push_app_server.jid}", no disco support from your server.`, + Strophe.LogLevel.WARN + ); + } + const stanza = $iq({'type': 'set'}); + if (domain !== _converse.bare_jid) { + stanza.attrs({'to': domain}); + } + stanza.c('disable', { + 'xmlns': Strophe.NS.PUSH, + 'jid': push_app_server.jid, + }); + if (push_app_server.node) { + stanza.attrs({'node': push_app_server.node}); + } + _converse.api.sendIQ(stanza) + .catch(e => { + _converse.log(`Could not disable push app server for ${push_app_server.jid}`, Strophe.LogLevel.ERROR); + _converse.log(e, Strophe.LogLevel.ERROR); + }); } - function enablePushAppServer (push_app_server) { + async function enablePushAppServer (domain, push_app_server) { if (!push_app_server.jid || !push_app_server.node) { return; } - _converse.api.disco.getIdentity('pubsub', 'push', push_app_server.jid) - .then(identity => { - if (!identity) { - return _converse.log( - `Not enabling push the service "${push_app_server.jid}", it doesn't have the right disco identtiy.`, - Strophe.LogLevel.WARN - ); - } - return Promise.all([ - _converse.api.disco.supports(Strophe.NS.PUSH, push_app_server.jid), - _converse.api.disco.supports(Strophe.NS.PUSH, _converse.bare_jid) - ]).then((result) => { - if (!result[0].length && !result[1].length) { - return _converse.log( - `Not enabling push app server "${push_app_server.jid}", no disco support from your server.`, - Strophe.LogLevel.WARN - ); - } - const stanza = $iq({'type': 'set'}) - .c('enable', { - 'xmlns': Strophe.NS.PUSH, - 'jid': push_app_server.jid, - 'node': push_app_server.node - }); - if (push_app_server.secret) { - stanza.c('x', {'xmlns': Strophe.NS.XFORM, 'type': 'submit'}) - .c('field', {'var': 'FORM_TYPE'}) - .c('value').t(`${Strophe.NS.PUBSUB}#publish-options`).up().up() - .c('field', {'var': 'secret'}) - .c('value').t(push_app_server.secret); - } - _converse.api.sendIQ(stanza) - .then(() => _converse.session.save('push_enabled', true)) - .catch((e) => { - _converse.log(`Could not enable push app server for ${push_app_server.jid}`, Strophe.LogLevel.ERROR); - _converse.log(e, Strophe.LogLevel.ERROR); - }); - }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); - }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); + const identity = await _converse.api.disco.getIdentity('pubsub', 'push', push_app_server.jid); + if (!identity) { + return _converse.log( + `Not enabling push the service "${push_app_server.jid}", it doesn't have the right disco identtiy.`, + Strophe.LogLevel.WARN + ); + } + const result = await Promise.all([ + _converse.api.disco.supports(Strophe.NS.PUSH, push_app_server.jid), + _converse.api.disco.supports(Strophe.NS.PUSH, domain) + ]); + if (!result[0].length && !result[1].length) { + return _converse.log( + `Not enabling push app server "${push_app_server.jid}", no disco support from your server.`, + Strophe.LogLevel.WARN + ); + } + const stanza = $iq({'type': 'set'}); + if (domain !== _converse.bare_jid) { + stanza.attrs({'to': domain}); + } + stanza.c('enable', { + 'xmlns': Strophe.NS.PUSH, + 'jid': push_app_server.jid, + 'node': push_app_server.node + }); + if (push_app_server.secret) { + stanza.c('x', {'xmlns': Strophe.NS.XFORM, 'type': 'submit'}) + .c('field', {'var': 'FORM_TYPE'}) + .c('value').t(`${Strophe.NS.PUBSUB}#publish-options`).up().up() + .c('field', {'var': 'secret'}) + .c('value').t(push_app_server.secret); + } + return _converse.api.sendIQ(stanza); } - function enablePush () { - if (_converse.session.get('push_enabled')) { - // XXX: this code is still a bit naive. We set push_enabled - // to true as soon as the first push app server has been set. - // - // When enabling or disabling multiple push app servers, - // we won't wait until we have confirmation that all have been set. + async function enablePush (domain) { + domain = domain || _converse.bare_jid; + const push_enabled = _converse.session.get('push_enabled') || []; + if (_.includes(push_enabled, domain)) { return; } const enabled_services = _.reject(_converse.push_app_servers, 'disable'); - _.each(enabled_services, enablePushAppServer); - + try { + await Promise.all(_.map(enabled_services, _.partial(enablePushAppServer, domain))) + } catch (e) { + _converse.log('Could not enable push App Server', Strophe.LogLevel.ERROR); + if (e) _converse.log(e, Strophe.LogLevel.ERROR); + } finally { + push_enabled.push(domain); + } const disabled_services = _.filter(_converse.push_app_servers, 'disable'); - _.each(disabled_services, disablePushAppServer); + _.each(disabled_services, _.partial(disablePushAppServer, domain)); + _converse.session.save('push_enabled', push_enabled); } - _converse.api.listen.on('statusInitialized', enablePush); + + function onChatBoxAdded (model) { + if (model.get('type') == _converse.CHATROOMS_TYPE) { + enablePush(Strophe.getDomainFromJid(model.get('jid'))); + } + } + + _converse.api.listen.on('statusInitialized', () => enablePush()); + _converse.api.listen.on('chatBoxesInitialized', () => _converse.chatboxes.on('add', onChatBoxAdded)); } }); })); diff --git a/tests/utils.js b/tests/utils.js index a97232f5e..3d8133412 100644 --- a/tests/utils.js +++ b/tests/utils.js @@ -117,7 +117,7 @@ modal.el.querySelector('input[name="nickname"]').value = nick; modal.el.querySelector('form input[type="submit"]').click(); resolve(); - }).catch(_.partial(console.error, _)); + }); }).catch(_.partial(console.error, _)); };