Add a plugin for XEP-0357

Currently only allows enabling an "App Service", based on pass-in
configuration values.
This commit is contained in:
JC Brand 2018-06-06 11:07:59 +02:00
parent eed141b53e
commit 7ee71b0132
9 changed files with 363 additions and 44 deletions

View File

@ -9,6 +9,7 @@
"plugins": ["lodash"],
"extends": ["eslint:recommended", "plugin:lodash/canonical"],
"globals": {
"Promise": true,
"converse": true,
"window": true,
"sinon": true,

View File

@ -19,6 +19,7 @@
- Add a checkbox to indicate whether a trusted device is being used or not.
If the device is not trusted, sessionStorage is used and all user data is deleted from the browser cache upon logout.
If the device is trusted, localStorage is used and user data is cached indefinitely.
- Initial support for XEP-0357 Push Notifications, specifically registering an "App Server".
### Bugfixes

113
dist/converse.js vendored
View File

@ -64922,11 +64922,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
})(void 0, function (sizzle, Promise, _, f, polyfill, i18n, u, moment, Strophe, pluggable, Backbone) {
/* Cannot use this due to Safari bug.
* See https://github.com/jcbrand/converse.js/issues/196
*/
// "use strict";
// Strophe globals
"use strict"; // Strophe globals
const _Strophe = Strophe,
$build = _Strophe.$build,
$iq = _Strophe.$iq,
@ -64974,7 +64971,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
_.extend(_converse, Backbone.Events); // Core plugins are whitelisted automatically
_converse.core_plugins = ['converse-bookmarks', 'converse-chatboxes', 'converse-chatview', 'converse-caps', 'converse-controlbox', 'converse-core', 'converse-disco', 'converse-dragresize', 'converse-embedded', 'converse-fullscreen', 'converse-headline', 'converse-mam', 'converse-message-view', 'converse-minimize', 'converse-modal', 'converse-muc', 'converse-muc-views', 'converse-notification', 'converse-otr', 'converse-ping', 'converse-profile', 'converse-register', 'converse-roomslist', 'converse-roster', 'converse-rosterview', 'converse-singleton', 'converse-spoilers', 'converse-vcard']; // Make converse pluggable
_converse.core_plugins = ['converse-bookmarks', 'converse-caps', 'converse-chatboxes', 'converse-chatview', 'converse-controlbox', 'converse-core', 'converse-disco', 'converse-dragresize', 'converse-embedded', 'converse-fullscreen', 'converse-headline', 'converse-mam', 'converse-message-view', 'converse-minimize', 'converse-modal', 'converse-muc', 'converse-muc-views', 'converse-notification', 'converse-ping', 'converse-profile', 'converse-push', 'converse-register', 'converse-roomslist', 'converse-roster', 'converse-rosterview', 'converse-singleton', 'converse-spoilers', 'converse-vcard']; // Make converse pluggable
pluggable.enable(_converse, '_converse', 'pluggable'); // Module-level constants
@ -65004,6 +65001,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
_converse.LOGOUT = "logout";
_converse.OPENED = 'opened';
_converse.PREBIND = "prebind";
_converse.IQ_TIMEOUT = 30000;
_converse.CONNECTION_STATUS = {
0: 'ERROR',
1: 'CONNECTING',
@ -65173,8 +65171,6 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
_converse.router = new Backbone.Router();
_converse.initialize = function (settings, callback) {
"use strict";
settings = !_.isUndefined(settings) ? settings : {};
const init_promise = u.getResolveablePromise();
@ -65564,7 +65560,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
const id = b64_sha1('converse.bosh-session');
_converse.session.id = id; // Appears to be necessary for backbone.browserStorage
_converse.session.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
_converse.session.browserStorage = new Backbone.BrowserStorage.session(id);
_converse.session.fetch();
@ -65682,7 +65678,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
_converse.log('An error occured while trying to enable message carbons.', Strophe.LogLevel.ERROR);
} else {
this.session.save({
carbons_enabled: true
'carbons_enabled': true
});
_converse.log('Message carbons have been enabled.');
@ -66272,6 +66268,12 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
'send'(stanza) {
_converse.connection.send(stanza);
},
'sendIQ'(stanza) {
return new Promise((resolve, reject) => {
_converse.connection.sendIQ(stanza, resolve, reject, _converse.IQ_TIMEOUT);
});
}
}; // The public API
@ -73287,6 +73289,94 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
/***/ }),
/***/ "./src/converse-push.js":
/*!******************************!*\
!*** ./src/converse-push.js ***!
\******************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
// Converse.js
// https://conversejs.org
//
// Copyright (c) 2013-2018, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
/* This is a Converse.js plugin which add support for registering
* an "App Server" as defined in XEP-0357
*/
(function (root, factory) {
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
})(void 0, function (converse) {
"use strict";
const _converse$env = converse.env,
Strophe = _converse$env.Strophe,
$iq = _converse$env.$iq;
Strophe.addNamespace('PUSH', 'urn:xmpp:push:0');
converse.plugins.add('converse-push', {
initialize() {
/* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery.
*/
const _converse = this._converse,
__ = _converse.__;
_converse.api.settings.update({
'push_service': undefined,
'push_service_node': undefined,
'push_service_secret': undefined
});
function enablePush() {
if (_converse.session.get('push_enabled')) {
return;
}
if (_converse.push_service && _converse.push_service_node) {
Promise.all([_converse.api.disco.getIdentity('pubsub', 'push', _converse.push_service), _converse.api.disco.supports(Strophe.NS.PUSH, _converse.push_service)]).then(() => _converse.api.disco.supports(Strophe.NS.PUSH, _converse.bare_jid)).then(() => {
const stanza = $iq({
'type': 'set'
}).c('enable', {
'xmlns': Strophe.NS.PUSH,
'jid': _converse.push_service,
'node': _converse.push_service_node
});
if (_converse.push_service_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(_converse.push_service_secret);
}
_converse.api.sendIQ(stanza).then(() => _converse.session.set('push_enabled', true)).catch(e => {
_converse.log(`Could not enable push service for ${_converse.push_service}`, Strophe.LogLevel.ERROR);
_converse.log(e, Strophe.LogLevel.ERROR);
});
});
}
}
_converse.api.listen.on('statusInitialized', enablePush);
}
});
});
/***/ }),
/***/ "./src/converse-register.js":
/*!**********************************!*\
!*** ./src/converse-register.js ***!
@ -76844,7 +76934,8 @@ if (true) {
__webpack_require__(/*! converse-chatview */ "./src/converse-chatview.js"), // Renders standalone chat boxes for single user chat
__webpack_require__(/*! converse-controlbox */ "./src/converse-controlbox.js"), // The control box
__webpack_require__(/*! converse-dragresize */ "./src/converse-dragresize.js"), // Allows chat boxes to be resized by dragging them
__webpack_require__(/*! converse-embedded */ "./src/converse-embedded.js"), __webpack_require__(/*! converse-fullscreen */ "./src/converse-fullscreen.js"), __webpack_require__(/*! converse-headline */ "./src/converse-headline.js"), // Support for headline messages
__webpack_require__(/*! converse-embedded */ "./src/converse-embedded.js"), __webpack_require__(/*! converse-fullscreen */ "./src/converse-fullscreen.js"), __webpack_require__(/*! converse-push */ "./src/converse-push.js"), // XEP-0357 Push Notifications
__webpack_require__(/*! converse-headline */ "./src/converse-headline.js"), // Support for headline messages
__webpack_require__(/*! converse-mam */ "./src/converse-mam.js"), // XEP-0313 Message Archive Management
__webpack_require__(/*! converse-minimize */ "./src/converse-minimize.js"), // Allows chat boxes to be minimized
__webpack_require__(/*! converse-muc */ "./src/converse-muc.js"), // XEP-0045 Multi-user chat

View File

@ -7,10 +7,10 @@ Configuration
=============
The included minified JavaScript and CSS files can be used for demoing or testing, but
you'll want to configure *Converse.js* to suit your needs before you deploy it
you'll want to configure *Converse* to suit your needs before you deploy it
on your website.
*Converse.js* is passed its configuration settings when you call its *initialize* method.
*Converse* is passed its configuration settings when you call its *initialize* method.
You'll most likely want to call the *initialize* method in your HTML page. For
an example of how this is done, please see the bottom of the *./index.html* page.
@ -18,7 +18,7 @@ an example of how this is done, please see the bottom of the *./index.html* page
Please refer to the `Configuration settings`_ section below for info on
all the available configuration settings.
After you have configured *Converse.js*, you'll have to regenerate the minified
After you have configured *Converse*, you'll have to regenerate the minified
JavaScript file so that it will include the new settings. Please refer to the
:ref:`minification` section for more info on how to do this.
@ -83,7 +83,7 @@ requiring them to log in manually.
When a BOSH session is initially created, you'll receive three tokens.
A JID (jabber ID), SID (session ID) and RID (Request ID).
Converse.js needs these tokens in order to attach to that same session.
Converse needs these tokens in order to attach to that same session.
There are two complementary configuration settings to ``prebind``.
They are :ref:`keepalive` and `prebind_url`_.
@ -200,7 +200,7 @@ allow_public_bookmarks
Some XMPP servers don't support private PEP/PubSub nodes, as required for
private bookmarks and outlined in `XEP-0223 <https://xmpp.org/extensions/xep-0223.html>`_.
Even though Converse.js asks for the bookmarks to be kept private (via the
Even though Converse asks for the bookmarks to be kept private (via the
`<publish-options>` XML node), the server simply ignores the privacy settings
and publishes the node contents under the default privacy setting, which makes
the information available to all roster contacts.
@ -382,7 +382,7 @@ A list of plugin names that are blacklisted and will therefore not be
initialized once ``converse.initialize`` is called, even if the same plugin is
whitelisted.
From Converse.js 3.0 onwards most of the API is available only to plugins and
From Converse 3.0 onwards most of the API is available only to plugins and
all plugins need to be whitelisted first.
The usecase for blacklisting is generally to disable removed core plugins
@ -495,7 +495,7 @@ connection_options
* Default: ``{}``
* Type: Object
Converse.js relies on `Strophe.js <http://strophe.im>`_ to establish and
Converse relies on `Strophe.js <http://strophe.im>`_ to establish and
maintain a connection to the XMPP server.
This option allows you to pass a map of configuration options to be passed into
@ -725,7 +725,7 @@ The translations for that locale must be available in JSON format at the
If an explicit locale is specified via the ``i18n`` setting and the
translations for that locale are not found at the `locales_url``, then
then Converse.js will fall back to trying to determine the browser's language
then Converse will fall back to trying to determine the browser's language
and fetching those translations, or if that fails the default English texts
will be used.
@ -747,7 +747,7 @@ keepalive
* Default: ``true``
Determines whether Converse.js will maintain the chat session across page
Determines whether Converse will maintain the chat session across page
loads.
This setting should also be used in conjunction with ``authentication`` set to `prebind`_.
@ -785,7 +785,7 @@ locales
'ru', 'uk', 'zh'
]
This setting restricts the locales that are supported by Converse.js and
This setting restricts the locales that are supported by Converse and
therefore what may be given as value for the :ref:`i18n` option.
Any other locales will be ignored.
@ -800,7 +800,7 @@ locales_url
* Default: ``/locale/{{{locale}}}/LC_MESSAGES/converse.json``,
The URL from where Converse.js should fetch translation JSON.
The URL from where Converse should fetch translation JSON.
The three curly braces ``{{{ }}}`` are
`Mustache <https://github.com/janl/mustache.js#readme>`_-style
@ -812,7 +812,7 @@ The variable being interpolated via the curly braces is ``locale``, which is
the value passed in to the `i18n`_ setting, or the browser's locale or the
default local or `en` (resolved in that order).
From version 3.3.0, Converse.js no longer bundles all translations into its
From version 3.3.0, Converse no longer bundles all translations into its
final build file. Instead, only the relevant translations are fetched at
runtime.
@ -953,7 +953,7 @@ muc_show_join_leave
* Default; ``true``
Determines whether Converse.js will show info messages inside a chatroom
Determines whether Converse will show info messages inside a chatroom
whenever a user joins or leaves it.
nickname
@ -1007,7 +1007,7 @@ play_sounds
Plays a notification sound when you receive a personal message or when your
nickname is mentioned in a chatroom.
Inside the ``./sounds`` directory of the Converse.js repo you'll see MP3 and Ogg
Inside the ``./sounds`` directory of the Converse repo you'll see MP3 and Ogg
formatted sound files. We need both, because neither format is supported by all browsers.
You can set the URL where the sound files are hosted with the `sounds_path`_
@ -1047,12 +1047,12 @@ priority
* Type: Number
Determines the priority used for presence stanzas sent out from this resource
(i.e. this instance of Converse.js).
(i.e. this instance of Converse).
The priority of a given XMPP chat client determines the importance of its presence
stanzas in relation to stanzas received from other clients of the same user.
In Converse.js, the indicated chat status of a roster contact will be taken from the
In Converse, the indicated chat status of a roster contact will be taken from the
presence stanza (and associated resource) with the highest priority.
If multiple resources have the same top priority, then the chat status will be
@ -1068,6 +1068,39 @@ providers_link
The hyperlink on the registration form which points to a directory of public
XMPP servers.
push_service
------------
* Default: ``undefined``
This option allows you to specify a URI for the push notifications service
(called an "App Server" by `XEP-0357 <https://xmpp.org/extensions/xep-0357.html>`_).
If provided, together with a `push_service_node`_, then Converse will instruct
the user's XMPP server to send push notificatiosn to that URI.
push_service_node
-----------------
* Default: ``undefined``
This is the PubSub node of the push notifications service (aka "App Server") specified with the
`push_service`_ setting.
Push notifications will be sent to this node. If this value is not set, then
push notifications won't be sent out.
push_service_secret
-------------------
* Default: ``undefined``
Some push notification services (aka "App Servers") require a secret token to
be used when sending out notifications.
This setting enables you to provide such a secret to Converse which will
forward it to your XMPP server to be included in push notifications.
root
----
@ -1108,7 +1141,7 @@ configured.
.. note::
It's currently not possible to use converse.js to assign contacts to groups.
Converse.js can only show users and groups that were previously configured
Converse can only show users and groups that were previously configured
elsewhere.
show_chatstate_notifications
@ -1262,10 +1295,10 @@ loaded), then an error will be raised.
Otherwise a message will simply be logged and the override instruction ignored.
The Converse.js plugins architecture can have an :ref:`dependencies`
The Converse plugins architecture can have an :ref:`dependencies`
plugin attribute. This enables you to specify an array of other plugins which
this one depends on.
Converse.js (more specifically, `pluggable.js <https://jcbrand.github.io/pluggable.js/>`_)
Converse (more specifically, `pluggable.js <https://jcbrand.github.io/pluggable.js/>`_)
will first load these dependencies before executing the plugin's overrides and
calling its ``initialize`` method.
@ -1302,7 +1335,7 @@ This setting determines whether the default value of the "This is a trusted devi
When the current device is not trusted, then localStorage and sessionStorage
will be cleared when the user logs out, thereby removing all cached data.
Clearing the cache in this way makes Converse.js much slower when the user logs
Clearing the cache in this way makes Converse much slower when the user logs
in again, because all data needs to be fetch anew.
See also `storage`_.
@ -1323,7 +1356,7 @@ use_otr_by_default
* Default: ``false``
If set to ``true``, Converse.js will automatically try to initiate an OTR (off-the-record)
If set to ``true``, Converse will automatically try to initiate an OTR (off-the-record)
encrypted chat session every time you open a chatbox.
visible_toolbar_buttons
@ -1382,7 +1415,7 @@ support.
configuration setting).
.. note::
Converse.js does not yet support "keepalive" with websockets.
Converse does not yet support "keepalive" with websockets.
.. _`view_mode`:
@ -1448,7 +1481,7 @@ whitelisted_plugins
A list of plugin names that are whitelisted and will therefore be
initialized once ``converse.initialize`` is called.
From Converse.js 3.0 onwards most of the API is available only to plugins and
From Converse 3.0 onwards most of the API is available only to plugins and
all plugins need to be whitelisted first.
This is done to prevent malicious scripts from using the API to trick users or

119
spec/push.js Normal file
View File

@ -0,0 +1,119 @@
(function (root, factory) {
define(["jasmine", "mock", "test-utils"], factory);
} (this, function (jasmine, mock, test_utils) {
"use strict";
var $iq = converse.env.$iq;
var Strophe = converse.env.Strophe;
var _ = converse.env._;
describe("XEP-0357 Push Notifications", function () {
it("can be enabled by specifying a push_service and push_service_node",
mock.initConverseWithPromises(null,
['rosterGroupsFetched'], {
'push_service': 'push-5@client.example',
'push_service_node': 'yxs32uqsflafdk3iuqo'
}, function (done, _converse) {
const IQ_stanzas = _converse.connection.IQ_stanzas;
let stanza;
expect(_converse.push_service).toBe('push-5@client.example');
expect(_converse.push_service_node).toBe('yxs32uqsflafdk3iuqo');
expect(_converse.session.get('push_enabled')).toBeFalsy();
test_utils.waitUntilDiscoConfirmed(
_converse, _converse.push_service,
[{'category': 'pubsub', 'type':'push'}],
['urn:xmpp:push:0'], [], 'info')
.then(() => test_utils.waitUntilDiscoConfirmed(
_converse,
_converse.bare_jid,
[{'category': 'account', 'type':'registered'}],
['urn:xmpp:push:0'], [], 'info'))
.then(() => {
return test_utils.waitUntil(() => {
const node = _.filter(IQ_stanzas, function (iq) {
return iq.nodeTree.querySelector('iq[type="set"] enable[xmlns="urn:xmpp:push:0"]');
}).pop();
if (node) {
stanza = node.nodeTree;
return true;
}
})
}).then(() => {
expect(stanza.outerHTML).toEqual(
`<iq type="set" xmlns="jabber:client" id="${stanza.getAttribute('id')}">`+
'<enable xmlns="urn:xmpp:push:0" jid="push-5@client.example" node="yxs32uqsflafdk3iuqo"/>'+
'</iq>'
)
_converse.connection._dataRecv(test_utils.createRequest($iq({
'to': _converse.connection.jid,
'type': 'result',
'id': stanza.getAttribute('id')
})));
return test_utils.waitUntil(() => _converse.session.get('push_enabled'))
}).then(() => {
done();
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
}));
it("can require a secret token to be included",
mock.initConverseWithPromises(null,
['rosterGroupsFetched'], {
'push_service': 'push-5@client.example',
'push_service_node': 'yxs32uqsflafdk3iuqo',
'push_service_secret': 'eruio234vzxc2kla-91'
}, function (done, _converse) {
const IQ_stanzas = _converse.connection.IQ_stanzas;
let stanza;
expect(_converse.push_service).toBe('push-5@client.example');
expect(_converse.push_service_node).toBe('yxs32uqsflafdk3iuqo');
expect(_converse.push_service_secret).toBe('eruio234vzxc2kla-91');
expect(_converse.session.get('push_enabled')).toBeFalsy();
test_utils.waitUntilDiscoConfirmed(
_converse, _converse.push_service,
[{'category': 'pubsub', 'type':'push'}],
['urn:xmpp:push:0'], [], 'info')
.then(() => test_utils.waitUntilDiscoConfirmed(
_converse,
_converse.bare_jid,
[{'category': 'account', 'type':'registered'}],
['urn:xmpp:push:0'], [], 'info'))
.then(() => {
return test_utils.waitUntil(() => {
const node = _.filter(IQ_stanzas, function (iq) {
return iq.nodeTree.querySelector('iq[type="set"] enable[xmlns="urn:xmpp:push:0"]');
}).pop();
if (node) {
stanza = node.nodeTree;
return true;
}
})
}).then(() => {
expect(stanza.outerHTML).toEqual(
`<iq type="set" xmlns="jabber:client" id="${stanza.getAttribute('id')}">`+
'<enable xmlns="urn:xmpp:push:0" jid="push-5@client.example" node="yxs32uqsflafdk3iuqo">'+
'<x xmlns="jabber:x:data" type="submit">'+
'<field var="FORM_TYPE"><value>http://jabber.org/protocol/pubsub#publish-options</value></field>'+
'<field var="secret"><value>eruio234vzxc2kla-91</value></field>'+
'</x>'+
'</enable>'+
'</iq>'
)
_converse.connection._dataRecv(test_utils.createRequest($iq({
'to': _converse.connection.jid,
'type': 'result',
'id': stanza.getAttribute('id')
})));
return test_utils.waitUntil(() => _converse.session.get('push_enabled'))
}).then(() => {
done();
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
}));
});
}));

View File

@ -20,11 +20,7 @@
"backbone.browserStorage"
], factory);
}(this, function (sizzle, Promise, _, f, polyfill, i18n, u, moment, Strophe, pluggable, Backbone) {
/* Cannot use this due to Safari bug.
* See https://github.com/jcbrand/converse.js/issues/196
*/
// "use strict";
"use strict";
// Strophe globals
const { $build, $iq, $msg, $pres } = Strophe;
@ -72,9 +68,9 @@
// Core plugins are whitelisted automatically
_converse.core_plugins = [
'converse-bookmarks',
'converse-caps',
'converse-chatboxes',
'converse-chatview',
'converse-caps',
'converse-controlbox',
'converse-core',
'converse-disco',
@ -89,9 +85,9 @@
'converse-muc',
'converse-muc-views',
'converse-notification',
'converse-otr',
'converse-ping',
'converse-profile',
'converse-push',
'converse-register',
'converse-roomslist',
'converse-roster',
@ -131,6 +127,8 @@
_converse.OPENED = 'opened';
_converse.PREBIND = "prebind";
_converse.IQ_TIMEOUT = 30000;
_converse.CONNECTION_STATUS = {
0: 'ERROR',
1: 'CONNECTING',
@ -298,7 +296,6 @@
_converse.initialize = function (settings, callback) {
"use strict";
settings = !_.isUndefined(settings) ? settings : {};
const init_promise = u.getResolveablePromise();
@ -638,7 +635,7 @@
_converse.session = new Backbone.Model();
const id = b64_sha1('converse.bosh-session');
_converse.session.id = id; // Appears to be necessary for backbone.browserStorage
_converse.session.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
_converse.session.browserStorage = new Backbone.BrowserStorage.session(id);
_converse.session.fetch();
_converse.emit('sessionInitialized');
};
@ -739,7 +736,7 @@
'An error occured while trying to enable message carbons.',
Strophe.LogLevel.ERROR);
} else {
this.session.save({carbons_enabled: true});
this.session.save({'carbons_enabled': true});
_converse.log('Message carbons have been enabled.');
}
}, null, "iq", null, "enablecarbons");
@ -1289,6 +1286,11 @@
'send' (stanza) {
_converse.connection.send(stanza);
},
'sendIQ' (stanza) {
return new Promise((resolve, reject) => {
_converse.connection.sendIQ(stanza, resolve, reject, _converse.IQ_TIMEOUT);
});
}
};
// The public API

70
src/converse-push.js Normal file
View File

@ -0,0 +1,70 @@
// Converse.js
// https://conversejs.org
//
// Copyright (c) 2013-2018, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
/* This is a Converse.js plugin which add support for registering
* an "App Server" as defined in XEP-0357
*/
(function (root, factory) {
define(["converse-core"], factory);
}(this, function (converse) {
"use strict";
const { Strophe, $iq } = converse.env;
Strophe.addNamespace('PUSH', 'urn:xmpp:push:0');
converse.plugins.add('converse-push', {
initialize () {
/* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery.
*/
const { _converse } = this,
{ __ } = _converse;
_converse.api.settings.update({
'push_service': undefined,
'push_service_node': undefined,
'push_service_secret': undefined
});
function enablePush() {
if (_converse.session.get('push_enabled')) {
return;
}
if (_converse.push_service && _converse.push_service_node) {
Promise.all([
_converse.api.disco.getIdentity('pubsub', 'push', _converse.push_service),
_converse.api.disco.supports(Strophe.NS.PUSH, _converse.push_service)
]).then(() => _converse.api.disco.supports(Strophe.NS.PUSH, _converse.bare_jid))
.then(() => {
const stanza = $iq({'type': 'set'})
.c('enable', {
'xmlns': Strophe.NS.PUSH,
'jid': _converse.push_service,
'node': _converse.push_service_node
});
if (_converse.push_service_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(_converse.push_service_secret);
}
_converse.api.sendIQ(stanza)
.then(() => _converse.session.set('push_enabled', true))
.catch((e) => {
_converse.log(`Could not enable push service for ${_converse.push_service}`, Strophe.LogLevel.ERROR);
_converse.log(e, Strophe.LogLevel.ERROR);
});
});
}
}
_converse.api.listen.on('statusInitialized', enablePush);
}
});
}));

View File

@ -14,6 +14,7 @@ if (typeof define !== 'undefined') {
"converse-dragresize", // Allows chat boxes to be resized by dragging them
"converse-embedded",
"converse-fullscreen",
"converse-push", // XEP-0357 Push Notifications
"converse-headline", // Support for headline messages
"converse-mam", // XEP-0313 Message Archive Management
"converse-minimize", // Allows chat boxes to be minimized

View File

@ -191,6 +191,7 @@ var specs = [
"spec/presence",
"spec/eventemitter",
"spec/ping",
"spec/push",
"spec/xmppstatus",
"spec/mam",
// "spec/otr",