quickblox 2.24.1-alpha.0 → 2.24.1-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "quickblox",
3
3
  "description": "QuickBlox JavaScript SDK",
4
- "version": "2.24.1-alpha.0",
4
+ "version": "2.24.1-alpha.1",
5
5
  "homepage": "https://quickblox.com/developers/Javascript",
6
6
  "main": "src/qbMain.js",
7
7
  "types": "quickblox.d.ts",
package/quickblox.js CHANGED
@@ -30507,6 +30507,13 @@ var chatUtils = require('./qbChatHelpers'),
30507
30507
 
30508
30508
  var unsupportedError = 'This function isn\'t supported outside of the browser (...yet)';
30509
30509
 
30510
+ /**
30511
+ * [CROS-1061] How long to wait for the server to answer a Notice enable/disable
30512
+ * IQ before reporting an error to the caller. Without a bound the callback is
30513
+ * never invoked when the server stays silent.
30514
+ */
30515
+ var NOTICE_IQ_TIMEOUT_MS = 10000;
30516
+
30510
30517
  var XMPP;
30511
30518
 
30512
30519
  /** create StropheJS or NodeXMPP connection object */
@@ -32348,6 +32355,22 @@ ChatProxy.prototype = {
32348
32355
  self._isConnecting = false;
32349
32356
  self._sessionHasExpired = false;
32350
32357
 
32358
+ // [CROS-1061] A new XMPP session never carries the previous session's
32359
+ // Notice subscription: the server binds <enable xmlns="urn:xmpp:notice:0"/>
32360
+ // to the stream, so it is gone once the stream is gone. Without this
32361
+ // reset the flag stays `true` after a transport reconnect while no
32362
+ // notices are delivered any more, and isNoticesEnabled() misleads the
32363
+ // application into skipping the re-enable (verified against a live
32364
+ // server: socket break -> reconnect -> flag true, zero notice stanzas;
32365
+ // clearing the flag and re-sending <enable> restored delivery).
32366
+ //
32367
+ // Placed in the shared preamble, above the isInitialConnect branch, and
32368
+ // above the onReconnectListener call below: with
32369
+ // config.pingLocalhostTimeInterval === 0 that listener fires
32370
+ // synchronously from this function, and a consumer re-enabling notices
32371
+ // from it must not observe a stale `true`.
32372
+ self._isNoticesEnabled = false;
32373
+
32351
32374
  self._enableCarbons();
32352
32375
 
32353
32376
  if (isInitialConnect) {
@@ -32358,7 +32381,6 @@ ChatProxy.prototype = {
32358
32381
  self._isConnectionVerified = true;
32359
32382
  self._isReconnectListenerPending = false;
32360
32383
 
32361
- // TODO(2.25.0): auto-enable Notice Feature here (see qbChat.js enableNotices JSDoc).
32362
32384
  self.roster.get(function (contacts) {
32363
32385
  xmppClient.send(presence);
32364
32386
 
@@ -32366,7 +32388,24 @@ ChatProxy.prototype = {
32366
32388
  callback(self.roster.contacts);
32367
32389
  });
32368
32390
  } else {
32391
+ // [CROS-1061] Union of the rooms still tracked on this instance and
32392
+ // the ones an explicit reconnect() had to drop. Consumed once —
32393
+ // clearing it here keeps a later session (or another user after
32394
+ // logout) from resurrecting a stale list.
32395
+ //
32396
+ // Safe to build the join stanzas at this point: setUserCurrentJid()
32397
+ // above has already installed the new JID, and muc.join() derives
32398
+ // the presence `from` out of it. Moving this block above that call
32399
+ // would send from="".
32369
32400
  var rooms = Object.keys(self.muc.joinedRooms);
32401
+ var remembered = self.muc._roomsToRejoin || [];
32402
+
32403
+ for (var r = 0; r < remembered.length; r++) {
32404
+ if (rooms.indexOf(remembered[r]) === -1) {
32405
+ rooms.push(remembered[r]);
32406
+ }
32407
+ }
32408
+ self.muc._roomsToRejoin = [];
32370
32409
 
32371
32410
  xmppClient.send(presence);
32372
32411
 
@@ -32589,6 +32628,11 @@ ChatProxy.prototype = {
32589
32628
  // connection had a chance to verify itself.
32590
32629
  this._isConnectionVerified = false;
32591
32630
  this._isReconnectListenerPending = false;
32631
+ // [CROS-1061] Remember the rooms before dropping them, so the re-join
32632
+ // loop in _postConnectActions has something to restore. Without this the
32633
+ // list is lost and group dialogs stop receiving message-level notices
32634
+ // until the page is reloaded.
32635
+ this.muc._roomsToRejoin = Object.keys(this.muc.joinedRooms);
32592
32636
  this.muc.joinedRooms = {};
32593
32637
  this.helpers.setUserCurrentJid('');
32594
32638
 
@@ -32982,6 +33026,9 @@ ChatProxy.prototype = {
32982
33026
  this._checkConnectionTimer = undefined;
32983
33027
  this._checkExpiredSessionTimer = undefined;
32984
33028
  this.muc.joinedRooms = {};
33029
+ // [CROS-1061] Never carry rooms across a logout: re-joining the previous
33030
+ // user's rooms from a new JID is answered with 403/407 by the server.
33031
+ this.muc._roomsToRejoin = [];
32985
33032
  // [QC-1550] Reset XMPP verification state on explicit disconnect so the
32986
33033
  // next connect() starts from a clean slate. _isLogout guard below also
32987
33034
  // prevents firing of deferred listeners if a pong arrives in flight,
@@ -33016,17 +33063,26 @@ ChatProxy.prototype = {
33016
33063
  * NoticeCreatedDialog / NoticeUpdatedDialog / NoticeDeletedDialog
33017
33064
  * headline stanzas.
33018
33065
  *
33019
- * The local enabled flag is reset to false on chat disconnect consumers
33020
- * must call enableNotices() again after a reconnect (intentional divergence
33021
- * from the Android SDK, which auto-restores the subscription).
33066
+ * The subscription belongs to the XMPP session, so it does not survive a
33067
+ * reconnect: the local enabled flag is reset to false whenever a new session
33068
+ * is established (initial connect and every reconnect alike) as well as on
33069
+ * disconnect. Consumers must call enableNotices() again after a reconnect —
33070
+ * an intentional divergence from the Android SDK, which auto-restores the
33071
+ * subscription. Reacting to onReconnectListener is the supported way to do
33072
+ * that.
33022
33073
  *
33023
- * TODO(2.25.0): make auto-enable SDK-internal fire on initial connect and
33024
- * on relogin after session-expired, skip on Stream-Management reconnect.
33025
- * Spec & three-state matrix are tracked in the internal 2.25.0 backlog
33026
- * (auto-enable notices).
33074
+ * Concurrent calls are safe: each IQ carries its own unique id, responses
33075
+ * are dispatched per id, and the flag is set independently for each result.
33076
+ * Calling enableNotices() again before the previous callback fires is
33077
+ * therefore allowed — for example when a second reconnect arrives while the
33078
+ * first enable is still in flight.
33027
33079
  *
33028
- * Do not call enableNotices again before the previous callback fires
33029
- * concurrent enable calls are not specified.
33080
+ * If the server does not answer, the callback receives an error after a
33081
+ * timeout instead of never being called.
33082
+ *
33083
+ * TODO(2.25.0): make auto-enable SDK-internal — fire on initial connect and
33084
+ * on every reconnect. Spec & three-state matrix are tracked in the internal
33085
+ * 2.25.0 backlog (auto-enable notices).
33030
33086
  *
33031
33087
  * @memberof QB.chat
33032
33088
  * @param {enableNoticesCallback} callback - Called with (error, result) on IQ result.
@@ -33065,7 +33121,10 @@ ChatProxy.prototype = {
33065
33121
  * Returns the local Notice Feature subscription flag.
33066
33122
  * @memberof QB.chat
33067
33123
  * @return {Boolean} true after a successful enableNotices(), false otherwise.
33068
- * Reset to false on chat disconnect; not synchronized with the server.
33124
+ * Reset to false on disconnect and whenever a new XMPP session is
33125
+ * established, so after a reconnect it reports false until the consumer
33126
+ * enables notices again. Not synchronized with the server: it reflects
33127
+ * what this client last requested, not the server's own state.
33069
33128
  * @since 2.24.0
33070
33129
  */
33071
33130
  isNoticesEnabled: function () {
@@ -33118,10 +33177,34 @@ ChatProxy.prototype = {
33118
33177
  }
33119
33178
 
33120
33179
  if (Utils.getEnv().browser) {
33121
- self.connection.sendIQ(iq, _onSuccess, _onError);
33180
+ // [CROS-1061] Without the 4th argument Strophe never times the IQ out,
33181
+ // so a server that stays silent leaves the caller without any callback
33182
+ // at all — the application spins forever. On timeout Strophe calls
33183
+ // _onError(null), which reports a 'cancel' error and leaves the flag
33184
+ // untouched.
33185
+ //
33186
+ // Note: this covers "server does not answer". It does NOT cover
33187
+ // "socket died", because the timeout is an addTimedHandler and
33188
+ // connection.reset() (called from the DISCONNECTED branch) clears
33189
+ // timedHandlers. That case is covered by the consumer-side timeout.
33190
+ self.connection.sendIQ(iq, _onSuccess, _onError, NOTICE_IQ_TIMEOUT_MS);
33122
33191
  } else {
33123
33192
  // Node/NativeScript path: register callback in nodeStanzasCallbacks map.
33193
+ // This path does not go through sendIQ, so the timeout is ours to run.
33194
+ var noticeIqTimer = setTimeout(function () {
33195
+ // Drop the pending entry first: _onIQ only dispatches while the
33196
+ // entry exists, so a late answer after this point is ignored
33197
+ // instead of invoking the callback a second time.
33198
+ delete self.nodeStanzasCallbacks[iqParams.id];
33199
+ _onError(null);
33200
+ }, NOTICE_IQ_TIMEOUT_MS);
33201
+
33124
33202
  self.nodeStanzasCallbacks[iqParams.id] = function (stanza) {
33203
+ // Must be first: otherwise a timely answer still leaves the timer
33204
+ // armed, and it would fire later and call the callback a second
33205
+ // time with an error.
33206
+ clearTimeout(noticeIqTimer);
33207
+
33125
33208
  // The map handler receives the result/error stanza. Inspect type to dispatch.
33126
33209
  var iqType = chatUtils.getAttr(stanza, 'type');
33127
33210
  if (iqType === 'result') {
@@ -33450,6 +33533,20 @@ function MucProxy(options) {
33450
33533
  this.nodeStanzasCallbacks = options.nodeStanzasCallbacks;
33451
33534
  //
33452
33535
  this.joinedRooms = {};
33536
+
33537
+ /**
33538
+ * [CROS-1061] Rooms carried across an explicit QB.chat.reconnect().
33539
+ *
33540
+ * reconnect() has to clear joinedRooms — the new session holds no presence
33541
+ * yet — but until now it dropped the list without keeping a copy, so the
33542
+ * re-join loop in _postConnectActions found nothing to restore and group
33543
+ * dialogs silently stopped receiving message-level notices.
33544
+ *
33545
+ * Written only by reconnect(), read and cleared once by _postConnectActions,
33546
+ * and cleared by disconnect() so one user's rooms can never be re-joined
33547
+ * from another user's JID.
33548
+ */
33549
+ this._roomsToRejoin = [];
33453
33550
  }
33454
33551
 
33455
33552
  MucProxy.prototype = {
@@ -40623,7 +40720,7 @@ module.exports = StreamManagement;
40623
40720
  */
40624
40721
 
40625
40722
  var config = {
40626
- version: '2.24.1-alpha.0',
40723
+ version: '2.24.1-alpha.1',
40627
40724
  buildNumber: '1181',
40628
40725
  creds: {
40629
40726
  'appId': 0,