Skip to content

Commit 762717d

Browse files
committed
Bugfix. streamFeaturesAdded triggered too soon.
`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.
1 parent e23c7ce commit 762717d

File tree

1 file changed

+51
-31
lines changed

1 file changed

+51
-31
lines changed

src/headless/converse-disco.js

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ converse.plugins.add('converse-disco', {
206206
if (stanza.querySelector(`feature[var="${Strophe.NS.DISCO_ITEMS}"]`)) {
207207
this.queryForItems();
208208
}
209-
_.forEach(stanza.querySelectorAll('feature'), feature => {
209+
Array.from(stanza.querySelectorAll('feature')).forEach(feature => {
210210
this.features.create({
211211
'var': feature.getAttribute('var'),
212212
'from': stanza.getAttribute('from')
@@ -243,6 +243,7 @@ converse.plugins.add('converse-disco', {
243243
}
244244
});
245245

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

267+
266268
function initStreamFeatures () {
267-
const bare_jid = Strophe.getBareJidFromJid(_converse.jid);
268-
const id = `converse.stream-features-${bare_jid}`;
269-
if (!_converse.stream_features || _converse.stream_features.browserStorage.name !== id) {
269+
// Initialize the stream_features collection, and if we're
270+
// re-attaching to a pre-existing BOSH session, we restore the
271+
// features from cache.
272+
// Otherwise the features will be created once we've received them
273+
// from the server (see populateStreamFeatures).
274+
if (!_converse.stream_features) {
275+
const bare_jid = Strophe.getBareJidFromJid(_converse.jid);
276+
const id = `converse.stream-features-${bare_jid}`;
277+
_converse.api.promises.add('streamFeaturesAdded');
270278
_converse.stream_features = new _converse.Collection();
271279
_converse.stream_features.browserStorage = _converse.createStore(id, "session");
272-
_converse.stream_features.fetch({
273-
success (collection) {
274-
if (collection.length === 0 && _converse.connection.features) {
275-
Array.from(_converse.connection.features.childNodes)
276-
.forEach(feature => {
277-
_converse.stream_features.create({
278-
'name': feature.nodeName,
279-
'xmlns': feature.getAttribute('xmlns')
280-
});
281-
});
282-
}
283-
/**
284-
* Triggered as soon as Converse has processed the stream features as advertised by
285-
* the server. If you want to check whether a stream feature is supported before
286-
* proceeding, then you'll first want to wait for this event.
287-
* @event _converse#streamFeaturesAdded
288-
* @example _converse.api.listen.on('streamFeaturesAdded', () => { ... });
289-
*/
290-
_converse.api.trigger('streamFeaturesAdded');
291-
},
292-
error (m, e) {
293-
log.error(e);
294-
}
295-
});
296280
}
297281
}
298282

283+
284+
function populateStreamFeatures () {
285+
// Strophe.js sets the <stream:features> element on the
286+
// Strophe.Connection instance (_converse.connection).
287+
//
288+
// Once this is done, we populate the _converse.stream_features collection
289+
// and trigger streamFeaturesAdded.
290+
initStreamFeatures();
291+
Array.from(_converse.connection.features.childNodes).forEach(feature => {
292+
_converse.stream_features.create({
293+
'name': feature.nodeName,
294+
'xmlns': feature.getAttribute('xmlns')
295+
});
296+
});
297+
notifyStreamFeaturesAdded();
298+
}
299+
300+
301+
function notifyStreamFeaturesAdded () {
302+
/**
303+
* Triggered as soon as the stream features are known.
304+
* If you want to check whether a stream feature is supported before proceeding,
305+
* then you'll first want to wait for this event.
306+
* @event _converse#streamFeaturesAdded
307+
* @example _converse.api.listen.on('streamFeaturesAdded', () => { ... });
308+
*/
309+
_converse.api.trigger('streamFeaturesAdded');
310+
}
311+
312+
299313
const plugin = this;
300314
plugin._identities = [];
301315
plugin._features = [];
@@ -355,9 +369,15 @@ converse.plugins.add('converse-disco', {
355369

356370
/******************** Event Handlers ********************/
357371

358-
// Re-create promise upon reconnection
359-
_converse.api.listen.on('userSessionInitialized', initStreamFeatures);
360-
_converse.api.listen.on('beforeResourceBinding', initStreamFeatures);
372+
_converse.api.listen.on('userSessionInitialized', async () => {
373+
initStreamFeatures();
374+
if (_converse.connfeedback.get('connection_status') === Strophe.Status.ATTACHED) {
375+
// When re-attaching to a BOSH session, we fetch the stream features from the cache.
376+
await new Promise((success, error) => _converse.stream_features.fetch({ success, error }));
377+
notifyStreamFeaturesAdded();
378+
}
379+
});
380+
_converse.api.listen.on('beforeResourceBinding', populateStreamFeatures);
361381

362382
_converse.api.listen.on('reconnected', initializeDisco);
363383
_converse.api.listen.on('connected', initializeDisco);

0 commit comments

Comments
 (0)