Commit 38a232fd authored by JC Brand's avatar JC Brand

Move BOSH code into a plugin

- Remove the `keepalive` configuration setting. It is now always implicitly `true`.
- Remove the `expose_rid_and_sid` configuration setting.
- A `prebind_url` is now mandatory when setting `authentication` to `prebind`.
- It's no longer possible to pass in `rid` and `sid` values to `converse.initialize.
parent 01fce557
# Changelog
## 5.0.0 (Unreleased)
- BOSH support has been moved to a plugin.
- Support for XEP-0410 to check whether we're still present in a room
- Initial support for the [CredentialsContainer](https://developer.mozilla.org/en-US/docs/Web/API/CredentialsContainer) web API
- Allow for synchronous events. When a synchronous event is fired, Converse will
......@@ -46,6 +47,10 @@
- `_converse.api.disco.supports` now returns a Promise which resolves to a Boolean instead of an Array.
- The `forward_messages` config option (which was set to `false` by default) has been removed.
Use [message_carbons](https://conversejs.org/docs/html/configuration.html#message-carbons) instead.
- Remove the `keepalive` configuration setting. It is now always implicitly `true`.
- Remove the `expose_rid_and_sid` configuration setting.
- A `prebind_url` is now mandatory when setting `authentication` to `prebind`.
It's no longer possible to pass in `rid` and `sid` values to `converse.initialize.
### API changes
......
......@@ -66,6 +66,8 @@ as soon as the page loads.
The server's domain is passed in via the `jid`_ setting.
.. _`prebind`:
prebind
~~~~~~~
......@@ -85,25 +87,15 @@ A JID (jabber ID), SID (session ID) and RID (Request ID).
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`_.
``keepalive`` can be used keep the session alive without having to pass in
new RID and SID tokens to ``converse.initialize`` every time you reload the page.
This removes the need to set up a new BOSH session every time a page loads.
You do however still need to supply the user's JID so that Converse can be
sure that the session it's resuming is for the right user.
In addition to setting ``authentication`` to ``prebind``, you'll also need to
set the `prebind_url`_ and `bosh-service-url`_.
`prebind_url`_ lets you specify a URL which Converse will call whenever a
new BOSH session needs to be set up.
Here's an example of Converse being initialized with these three options:
Here's an example of Converse being initialized with these options:
.. code-block:: javascript
converse.initialize({
bosh_service_url: 'https://bind.example.com',
keepalive: true,
jid: 'me@example.com',
authentication: 'prebind',
prebind_url: 'http://example.com/api/prebind',
......@@ -187,8 +179,8 @@ allow_non_roster_messaging
Determines whether you'll receive messages from users that are not in your
roster. The XMPP specification allows for this (similar to email).
Setting this to `true` increases your chances of receiving spam (when using a
federated server), while setting it to `false` means that people not on your
Setting this to ``true`` increases your chances of receiving spam (when using a
federated server), while setting it to ``false`` means that people not on your
roster can't contact you unless one (or both) of you subscribe to one another's
presence (i.e. adding as a roster contact).
......@@ -321,13 +313,13 @@ auto_reconnect
Automatically reconnect to the XMPP server if the connection drops
unexpectedly.
This option works best when you have `authentication` set to `prebind` and have
also specified a `prebind_url` URL, from where Converse can fetch the BOSH
This option works best when you have ``authentication`` set to ``prebind`` and have
also specified a ``prebind_url`` URL, from where Converse can fetch the BOSH
tokens. In this case, Converse will automaticallly reconnect when the
connection drops but also reestablish earlier lost connections (due to
network outages, closing your laptop etc.).
When `authentication` is set to `login`, then this option will only work when
When ``authentication`` is set to `login`, then this option will only work when
the page hasn't been reloaded yet, because then the user's password has been
wiped from memory. This configuration can however still be useful when using
Converse in desktop apps, for example those based on `CEF <https://bitbucket.org/chromiumembedded/cef>`_
......@@ -407,6 +399,7 @@ plugins from registering themselves under those names.
The core, and by default whitelisted, plugins are::
converse-bosh
converse-bookmarks
converse-chatboxes
converse-chatview
......@@ -427,8 +420,9 @@ The core, and by default whitelisted, plugins are::
converse-roomslist
converse-rosterview
converse-singleton
converse-smacks
converse-spoilers
converse-vcard'
converse-vcard
Example:
......@@ -519,7 +513,7 @@ credentials_url
* Default: ``null``
* Type: URL
This setting should be used in conjunction with ``authentication`` set to ``login`` and :ref:`keepalive` set to ``true``.
This setting should be used in conjunction with ``authentication`` set to ``login``.
It allows you to specify a URL which Converse will call when it needs to get
the username and password (or authentication token) which Converse will use
......@@ -644,18 +638,6 @@ Determines whether `XEP-0198 Stream Management <https://xmpp.org/extensions/xep-
support is turned on or not.
expose_rid_and_sid
------------------
* Default: ``false``
Allow the prebind tokens, RID (request ID) and SID (session ID), to be exposed
globally via the API. This allows other scripts served on the same page to use
these values.
*Beware*: a malicious script could use these tokens to assume your identity
and inject fake chat messages.
filter_by_resource
------------------
......@@ -744,37 +726,10 @@ The Jabber ID or "JID" of the current user. The JID uniquely identifies a user
on the XMPP network. It looks like an email address, but it's used for instant
messaging instead.
This value needs to be provided when using the :ref:`keepalive` option together
with `prebind`_.
This value may be provided together with a ``password`` instead of supplying a
`credentials_url`_ when setting ``auto_login`` to ``true``.
.. _`keepalive`:
keepalive
---------
* Default: ``true``
Determines whether Converse will maintain the chat session across page
loads.
This setting should also be used in conjunction with ``authentication`` set to `prebind`_.
When using ``keepalive`` and ``prebind``, you will have to provide the `jid`_
of the current user to ensure that a cached session is only resumed if it
belongs to the current user.
See also:
* :ref:`session-support`
.. note::
Currently the "keepalive" setting only works with BOSH and not with
websockets. This is because XMPP over websocket does not use the same
session token as with BOSH. A possible solution for this is to implement
`XEP-0198 <https://xmpp.org/extensions/xep-0198.html>`_, specifically
with regards to "stream resumption".
.. _`locales`:
locales
......@@ -818,7 +773,7 @@ injection attack could be attempted.
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).
default local or ``en`` (resolved in that order).
From version 3.3.0, Converse no longer bundles all translations into its
final build file. Instead, only the relevant translations are fetched at
......@@ -899,7 +854,7 @@ message_archiving_timeout
The amount of time (in milliseconds) to wait when requesting archived messages
from the XMPP server.
Used in conjunction with `message_archiving` and in context of `XEP-0313: Message Archive Management <https://xmpp.org/extensions/xep-0313.html>`_.
Used in conjunction with ``message_archiving`` and in context of `XEP-0313: Message Archive Management <https://xmpp.org/extensions/xep-0313.html>`_.
message_carbons
---------------
......@@ -1037,7 +992,7 @@ The nickname will be included in presence requests to other users and will also
be used as the default nickname when entering MUC chatrooms.
This value will have first preference ahead of other nickname sources, such as
the VCard `nickname` value.
the VCard ``nickname`` value.
notify_all_room_messages
......@@ -1141,7 +1096,7 @@ prebind_url
See also: :ref:`session-support`
This setting should be used in conjunction with ``authentication`` set to `prebind` and :ref:`keepalive` set to ``true``.
This setting should be used in conjunction with ``authentication`` set to `prebind`.
It allows you to specify a URL which Converse will call when it needs to get
the RID and SID (Request ID and Session ID) tokens of a BOSH connection, which
......@@ -1322,7 +1277,7 @@ If set to ``true``, notifications will be shown in the following cases:
* the browser is not visible nor focused and a private message is received.
* the browser is not visible nor focused and a groupchat message is received which mentions you.
* `auto_subscribe` is set to `false` and a new contact request is received.
* ``auto_subscribe`` is set to ``false`` and a new contact request is received.
If set to ``all``, notifications will be shown even if the above conditions are
not fulfilled.
......@@ -1457,7 +1412,7 @@ synchronize_availability
Valid options: ``true``, ``false``, ``a resource name``.
This option lets you synchronize your chat status (`online`, `busy`, `away`) with other chat clients. In other words,
if you change your status to `busy` in a different chat client, your status will change to `busy` in Converse as well.
if you change your status to ``busy`` in a different chat client, your status will change to ``busy`` in Converse as well.
If set to ``true``, Converse will synchronize with all other clients you are logged in with.
......@@ -1519,8 +1474,8 @@ time_format
Examples: ``HH:mm``, ``hh:mm``, ``hh:mm a``.
This option makes the time format for the time shown, for each message, configurable. Converse uses `DayJS <https://github.com/iamkun/dayjs>`_
for showing time. This option allows the configuration of the format in which `DayJS` will display the time for the messages. For detailed
description of time-format options available for `DayJS` you can check the
for showing time. This option allows the configuration of the format in which ``DayJS`` will display the time for the messages. For detailed
description of time-format options available for ``DayJS`` you can check the
`default formatting options <https://github.com/iamkun/dayjs/blob/dev/docs/en/API-reference.md#displaying>`_ and the
`advanced options <https://github.com/iamkun/dayjs/blob/master/docs/en/Plugin.md#advancedformat>`_.
......@@ -1577,13 +1532,6 @@ techniques for bidirectional HTTP (such as `BOSH <https://en.wikipedia.org/wiki/
Please refer to your XMPP server's documentation on how to enable websocket
support.
.. note::
Please note that not older browsers do not support websockets. For older
browsers you'll want to specify a BOSH URL. See the :ref:`bosh-service-url`
configuration setting).
.. note::
Converse does not yet support "keepalive" with websockets.
.. _`view_mode`:
......
......@@ -116,7 +116,6 @@ your components, for example:
'auto_reconnect': true,
'bosh_service_url': bosh_url,
'jid': bare_jid,
'keepalive': true,
'credentials_url': credentials_url,
'whitelisted_plugins': ['conversejs-angular-service']
});
......
......@@ -29,8 +29,7 @@ The diagram below shows a fairly common setup for a website or intranet:
* It communicates with the XMPP server via BOSH or websocket which is usually
reverse-proxied by a web-server in order to overcome cross-site scripting
restrictions in the browser. For more info on that, read the section:
`Overcoming cross-domain request restrictions`_
restrictions in the browser.
* Optionally the XMPP server is configured to use a SQL database for storing
archived chat messages.
......@@ -293,8 +292,7 @@ Single Session Support
It's possible to enable shared sessions whereby users already
logged in to your website will also automatically be logged in on the XMPP server,
Once a user is logged in, the session will be kept alive across page loads by
way of the :ref:`keepalive` setting.
Once a user is logged in, the session will be kept alive across page loads.
There are a few ways to let your users be automatically authenticated to an
XMPP server once they've logged in to your site.
......@@ -364,8 +362,7 @@ page load). Each page load is a new request which requires a new unique RID.
The best way to achieve this is to simply increment the RID with each page
load.
You'll need to configure Converse with the ``prebind``, :ref:`keepalive` and
:ref:`prebind_url` settings.
You'll need to configure Converse with the :ref:`prebind` :ref:`prebind_url` settings.
Please read the documentation on those settings for a fuller picture of what
needs to be done.
......
......@@ -23,37 +23,6 @@
_converse.connection = connection;
done();
}));
describe("with prebind", function () {
it("needs a jid when also using keepalive", mock.initConverse([], null, {'auto_login': false}, (done, _converse) => {
const authentication = _converse.authentication;
const jid = _converse.jid;
delete _converse.jid;
_converse.keepalive = true;
_converse.authentication = "prebind";
expect(_converse.api.user.login.bind(_converse)).toThrow(
new Error(
"restoreBOSHSession: tried to restore a \"keepalive\" session "+
"but we don't have the JID for the user!"));
_converse.authentication= authentication;
_converse.jid = jid;
_converse.keepalive = false;
done();
}));
it("needs jid, rid and sid values when not using keepalive", mock.initConverse((done, _converse) => {
const jid = _converse.jid;
delete _converse.jid;
_converse.keepalive = false;
_converse.authentication = "prebind";
expect(_converse.api.user.login.bind(_converse)).toThrow(
new Error("attemptPreboundSession: If you use prebind and not keepalive, then you MUST supply JID, RID and SID values or a prebind_url."));
_converse.bosh_service_url = undefined;
_converse.jid = jid;
done();
}));
});
});
describe("A chat state indication", function () {
......@@ -219,9 +188,6 @@
test_utils.createContacts(_converse, 'current');
const old_connection = _converse.connection;
_converse.connection._proto.rid = '1234';
_converse.expose_rid_and_sid = false;
expect(_converse.api.tokens.get('rid')).toBe(null);
_converse.expose_rid_and_sid = true;
expect(_converse.api.tokens.get('rid')).toBe('1234');
_converse.connection = undefined;
expect(_converse.api.tokens.get('rid')).toBe(null);
......@@ -234,9 +200,6 @@
test_utils.createContacts(_converse, 'current');
const old_connection = _converse.connection;
_converse.connection._proto.sid = '1234';
_converse.expose_rid_and_sid = false;
expect(_converse.api.tokens.get('sid')).toBe(null);
_converse.expose_rid_and_sid = true;
expect(_converse.api.tokens.get('sid')).toBe('1234');
_converse.connection = undefined;
expect(_converse.api.tokens.get('sid')).toBe(null);
......
// Converse.js
// http://conversejs.org
//
// Copyright (c) The Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
/* This is a Converse.js plugin which add support for XEP-0206: XMPP Over BOSH */
import BrowserStorage from "backbone.browserStorage";
import converse from "./converse-core";
const { Backbone, Strophe, _ } = converse.env;
const u = converse.env.utils;
converse.plugins.add('converse-bosh', {
initialize () {
const { _converse } = this;
_converse.api.settings.update({
bosh_service_url: undefined,
prebind_url: null
});
async function initBOSHSession () {
const id = 'converse.bosh-session';
if (!_converse.bosh_session) {
_converse.bosh_session = new Backbone.Model({id});
_converse.bosh_session.browserStorage = new BrowserStorage.session(id);
await new Promise(resolve => _converse.bosh_session.fetch({'success': resolve, 'error': resolve}));
}
if (_converse.jid && _converse.bosh_session.get('jid') === _converse.jid) {
_converse.bosh_session.clear({'silent': true });
_converse.bosh_session.save({'jid': _converse.jid, id});
}
return _converse.bosh_session;
}
_converse.startNewBOSHSession = function () {
if (!_converse.prebind_url) {
throw new Error(
"attemptPreboundSession: If you use prebind then you MUST supply a prebind_url");
}
const xhr = new XMLHttpRequest();
xhr.open('GET', _converse.prebind_url, true);
xhr.setRequestHeader('Accept', 'application/json, text/javascript');
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 400) {
const data = JSON.parse(xhr.responseText);
_converse.connection.attach(
data.jid,
data.sid,
data.rid,
_converse.onConnectStatusChanged
);
} else {
xhr.onerror();
}
};
xhr.onerror = function () {
delete _converse.connection;
/**
* Triggered when fetching prebind tokens failed
* @event _converse#noResumeableBOSHSession
* @type { _converse }
* @example _converse.api.listen.on('noResumeableBOSHSession', _converse => { ... });
*/
_converse.api.trigger('noResumeableBOSHSession', _converse);
};
xhr.send();
}
_converse.restoreBOSHSession = async function () {
if (!_converse.api.connection.isType('bosh')) {
return false;
}
const jid = (await initBOSHSession()).get('jid');
if (jid) {
try {
_converse.connection.restore(jid, _converse.onConnectStatusChanged);
return true;
} catch (e) {
_converse.log(
"Could not restore session for jid: "+
jid+" Error message: "+e.message, Strophe.LogLevel.WARN);
_converse.clearSession(); // We want to clear presences (see #555)
return false;
}
}
return false;
}
/************************ BEGIN Event Handlers ************************/
_converse.api.listen.on('clearSession', () => {
if (!_.isUndefined(_converse.bosh_session)) {
_converse.bosh_session.destroy();
delete _converse.bosh_session;
}
});
_converse.api.listen.on('setUserJID', () => {
if (!_.isUndefined(_converse.bosh_session)) {
_converse.bosh_session.save({'jid': _converse.jid});
}
});
/************************ END Event Handlers ************************/
/************************ BEGIN API ************************/
Object.assign(_converse.api, {
/**
* This namespace lets you access the BOSH tokens
*
* @namespace _converse.api.tokens
* @memberOf _converse.api
*/
tokens: {
/**
* @method _converse.api.tokens.get
* @param {string} [id] The type of token to return ('rid' or 'sid').
* @returns 'string' A token, either the RID or SID token depending on what's asked for.
* @example _converse.api.tokens.get('rid');
*/
get (id) {
if (_.isUndefined(_converse.connection)) {
return null;
}
if (id.toLowerCase() === 'rid') {
return _converse.connection.rid || _converse.connection._proto.rid;
} else if (id.toLowerCase() === 'sid') {
return _converse.connection.sid || _converse.connection._proto.sid;
}
}
}
});
/************************ end api ************************/
}
});
This diff is collapsed.
......@@ -192,7 +192,7 @@ converse.plugins.add('converse-smacks', {
_converse.connection.addHandler(sendAck, Strophe.NS.SM, 'r');
_converse.connection.addHandler(handleAck, Strophe.NS.SM, 'a');
if (_converse.connection._proto instanceof Strophe.Bosh &&
if (_converse.api.connection.isType('bosh') &&
_converse.connfeedback.get('connection_status') === Strophe.Status.ATTACHED) {
// No need to continue further when we have an existing BOSH session,
// since our existing session still exists server-side.
......
......@@ -3,6 +3,7 @@
* Any of the following components may be removed if they're not needed.
*/
import "./converse-bookmarks"; // XEP-0199 XMPP Ping
import "./converse-bosh"; // XEP-0115 Entity Capabilities
import "./converse-caps"; // XEP-0115 Entity Capabilities
import "./converse-chatboxes"; // Backbone Collection and Models for chat boxes
import "./converse-disco"; // XEP-0030 Service discovery
......
......@@ -87,6 +87,9 @@ u.isValidMUCJID = function (jid) {
};
u.isSameBareJID = function (jid1, jid2) {
if (!_.isString(jid1) || !_.isString(jid2)) {
return false;
}
return Strophe.getBareJidFromJid(jid1).toLowerCase() ===
Strophe.getBareJidFromJid(jid2).toLowerCase();
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment