Skip to content

Commit

Permalink
Bugfix. streamFeaturesAdded triggered too soon.
Browse files Browse the repository at this point in the history
`streamFeaturesAdded` should only be triggered once we've received them
from the server.

This appears to be a timing bug, likely introduced by the IndexedDB
refactoring.
  • Loading branch information
jcbrand committed Nov 26, 2019
1 parent e23c7ce commit 762717d
Showing 1 changed file with 51 additions and 31 deletions.
82 changes: 51 additions & 31 deletions src/headless/converse-disco.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ converse.plugins.add('converse-disco', {
if (stanza.querySelector(`feature[var="${Strophe.NS.DISCO_ITEMS}"]`)) {
this.queryForItems();
}
_.forEach(stanza.querySelectorAll('feature'), feature => {
Array.from(stanza.querySelectorAll('feature')).forEach(feature => {
this.features.create({
'var': feature.getAttribute('var'),
'from': stanza.getAttribute('from')
Expand Down Expand Up @@ -243,6 +243,7 @@ converse.plugins.add('converse-disco', {
}
});


function addClientFeatures () {
// See https://xmpp.org/registrar/disco-categories.html
_converse.api.disco.own.identities.add('client', 'web', 'Converse');
Expand All @@ -263,39 +264,52 @@ converse.plugins.add('converse-disco', {
return this;
}


function initStreamFeatures () {
const bare_jid = Strophe.getBareJidFromJid(_converse.jid);
const id = `converse.stream-features-${bare_jid}`;
if (!_converse.stream_features || _converse.stream_features.browserStorage.name !== id) {
// Initialize the stream_features collection, and if we're
// re-attaching to a pre-existing BOSH session, we restore the
// features from cache.
// Otherwise the features will be created once we've received them
// from the server (see populateStreamFeatures).
if (!_converse.stream_features) {
const bare_jid = Strophe.getBareJidFromJid(_converse.jid);
const id = `converse.stream-features-${bare_jid}`;
_converse.api.promises.add('streamFeaturesAdded');
_converse.stream_features = new _converse.Collection();
_converse.stream_features.browserStorage = _converse.createStore(id, "session");
_converse.stream_features.fetch({
success (collection) {
if (collection.length === 0 && _converse.connection.features) {
Array.from(_converse.connection.features.childNodes)
.forEach(feature => {
_converse.stream_features.create({
'name': feature.nodeName,
'xmlns': feature.getAttribute('xmlns')
});
});
}
/**
* Triggered as soon as Converse has processed the stream features as advertised by
* the server. If you want to check whether a stream feature is supported before
* proceeding, then you'll first want to wait for this event.
* @event _converse#streamFeaturesAdded
* @example _converse.api.listen.on('streamFeaturesAdded', () => { ... });
*/
_converse.api.trigger('streamFeaturesAdded');
},
error (m, e) {
log.error(e);
}
});
}
}


function populateStreamFeatures () {
// Strophe.js sets the <stream:features> element on the
// Strophe.Connection instance (_converse.connection).
//
// Once this is done, we populate the _converse.stream_features collection
// and trigger streamFeaturesAdded.
initStreamFeatures();
Array.from(_converse.connection.features.childNodes).forEach(feature => {
_converse.stream_features.create({
'name': feature.nodeName,
'xmlns': feature.getAttribute('xmlns')
});
});
notifyStreamFeaturesAdded();
}


function notifyStreamFeaturesAdded () {
/**
* Triggered as soon as the stream features are known.
* If you want to check whether a stream feature is supported before proceeding,
* then you'll first want to wait for this event.
* @event _converse#streamFeaturesAdded
* @example _converse.api.listen.on('streamFeaturesAdded', () => { ... });
*/
_converse.api.trigger('streamFeaturesAdded');
}


const plugin = this;
plugin._identities = [];
plugin._features = [];
Expand Down Expand Up @@ -355,9 +369,15 @@ converse.plugins.add('converse-disco', {

/******************** Event Handlers ********************/

// Re-create promise upon reconnection
_converse.api.listen.on('userSessionInitialized', initStreamFeatures);
_converse.api.listen.on('beforeResourceBinding', initStreamFeatures);
_converse.api.listen.on('userSessionInitialized', async () => {
initStreamFeatures();
if (_converse.connfeedback.get('connection_status') === Strophe.Status.ATTACHED) {
// When re-attaching to a BOSH session, we fetch the stream features from the cache.
await new Promise((success, error) => _converse.stream_features.fetch({ success, error }));
notifyStreamFeaturesAdded();
}
});
_converse.api.listen.on('beforeResourceBinding', populateStreamFeatures);

_converse.api.listen.on('reconnected', initializeDisco);
_converse.api.listen.on('connected', initializeDisco);
Expand Down

0 comments on commit 762717d

Please sign in to comment.