Skip to content

Commit

Permalink
Merge branch 'session-handling'
Browse files Browse the repository at this point in the history
  • Loading branch information
jcbrand committed Jun 19, 2015
2 parents c8ccfee + 8c8eeb5 commit fa0a59f
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 33 deletions.
15 changes: 11 additions & 4 deletions src/bosh.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,12 @@ Strophe.Bosh.prototype = {
rid: this.rid++,
xmlns: Strophe.NS.HTTPBIND
});

if (this.sid !== null) {
bodyWrap.attrs({sid: this.sid});
}

if (this._conn.options.keepalive) {
this._cacheSession();
}
return bodyWrap;
},

Expand Down Expand Up @@ -323,7 +324,13 @@ Strophe.Bosh.prototype = {
_restore: function (jid, callback, wait, hold, wind)
{
var session = JSON.parse(window.sessionStorage.getItem('strophe-bosh-session'));
if (typeof session !== "undefined" && session !== null && session.rid && session.sid && session.jid) {
if (typeof session !== "undefined" &&
session !== null &&
session.rid &&
session.sid &&
session.jid &&
(typeof jid === "undefined" || Strophe.getBareJidFromJid(session.jid) == Strophe.getBareJidFromJid(jid)))
{
this._conn.restored = true;
this._attach(session.jid, session.sid, session.rid, callback, wait, hold, wind);
} else {
Expand All @@ -340,7 +347,7 @@ Strophe.Bosh.prototype = {
*/
_cacheSession: function ()
{
if (this._conn.connected) {
if (this._conn.authenticated) {
if (this._conn.jid && this.rid && this.sid) {
window.sessionStorage.setItem('strophe-bosh-session', JSON.stringify({
'jid': this._conn.jid,
Expand Down
12 changes: 0 additions & 12 deletions src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -1539,18 +1539,6 @@ Strophe.Connection = function (service, options)
this._proto = new Strophe.Bosh(this);
}

if (this.options.keepalive && this._proto instanceof Strophe.Bosh) {
if ('onbeforeunload' in window) {
window.addEventListener("beforeunload", this._proto._cacheSession.bind(this._proto), false);
} else if ('onunload' in window) {
window.addEventListener("unload", this._proto._cacheSession.bind(this._proto), false);
} else if ('onpagehide' in window) {
// Mobile Safari (at least older versions) doesn't support unload or beforeunload.
// Apple recommends "pagehide" instead.
window.addEventListener("pagehide", this._proto._cacheSession.bind(this._proto), false);
}
}

/* The connected JID. */
this.jid = "";
/* the JIDs domain */
Expand Down
105 changes: 88 additions & 17 deletions tests/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -428,12 +428,46 @@ define([

module("BOSH Session resumption");

test("When passing in {keepalive: true} to Strophe.Connection, a beforeunload listener is registered", function () {
var addEventListenerSpy = sinon.spy(window, "addEventListener");
equal(addEventListenerSpy.called, false);
test("When passing in {keepalive: true} to Strophe.Connection, then the session tokens get cached automatically", function () {
var conn = new Strophe.Connection("", {"keepalive": true});
equal(addEventListenerSpy.calledWith("beforeunload"), true);
});
conn.jid = 'dummy@localhost';
conn._proto.sid = "5332346";
var cacheSpy = sinon.spy(conn._proto, '_cacheSession');
equal(cacheSpy.called, false);
conn._proto._buildBody();
equal(cacheSpy.called, true);
equal(window.sessionStorage.getItem('strophe-bosh-session'), null);
conn.authenticated = true;
conn._proto._buildBody();
ok(window.sessionStorage.getItem('strophe-bosh-session'));
equal(cacheSpy.called, true);
conn.authenticated = false;
conn._proto._buildBody();
equal(window.sessionStorage.getItem('strophe-bosh-session'), null);
equal(cacheSpy.called, true);
});

test('the request ID (RID) has the proper value whenever a session is restored', function () {
window.sessionStorage.removeItem('strophe-bosh-session');
var conn = new Strophe.Connection("", {"keepalive": true});
conn.authenticated = true;
conn.jid = 'dummy@localhost';
conn._proto.rid = '123456';
conn._proto.sid = '987654321';
conn._proto._cacheSession();
delete conn._proto.rid;
conn.restore();
var body = conn._proto._buildBody();
equal(body.tree().getAttribute('rid'), '123456');
body = conn._proto._buildBody();
equal(body.tree().getAttribute('rid'), '123457');
body = conn._proto._buildBody();
equal(body.tree().getAttribute('rid'), '123458');
delete conn._proto.rid;
conn.restore();
body = conn._proto._buildBody();
equal(body.tree().getAttribute('rid'), '123459');
});

test("restore can only be called with BOSH and when {keepalive: true} is passed to Strophe.Connection", function () {
var conn = new Strophe.Connection("");
Expand Down Expand Up @@ -463,6 +497,22 @@ define([
equal(conn.restored, false);
});

test('the _cacheSession method caches the BOSH session tokens', function () {
window.sessionStorage.removeItem('strophe-bosh-session');
var conn = new Strophe.Connection("http://fake", {"keepalive": true});
// Nothing gets cached if there aren't tokens to cache
conn._proto._cacheSession();
equal(window.sessionStorage.getItem('strophe-bosh-session'), null);
// Let's create some tokens to cache
conn.authenticated = true;
conn.jid = 'dummy@localhost';
conn._proto.rid = '123456';
conn._proto.sid = '987654321';
equal(window.sessionStorage.getItem('strophe-bosh-session'), null);
conn._proto._cacheSession();
notEqual(window.sessionStorage.getItem('strophe-bosh-session'), null);
});

test('when calling "restore" without a restorable session, an exception is raised', function () {
window.sessionStorage.removeItem('strophe-bosh-session');
var conn = new Strophe.Connection("", {"keepalive": true});
Expand All @@ -480,42 +530,63 @@ define([
equal(checkSpy.called, true);
});

test('the _cacheSession method caches the BOSH session tokens', function () {
test('"restore" takes an optional JID argument for more precise session verification', function () {
window.sessionStorage.removeItem('strophe-bosh-session');
var conn = new Strophe.Connection("http://fake", {"keepalive": true});
// Nothing gets cached if there aren't tokens to cache
conn._proto._cacheSession();
equal(window.sessionStorage.getItem('strophe-bosh-session'), undefined);
var conn = new Strophe.Connection("", {"keepalive": true});
var boshSpy = sinon.spy(conn._proto, "_restore");
var checkSpy = sinon.spy(conn, "_sessionCachingSupported");
// Let's create some tokens to cache
conn.connected = true;
conn.authenticated = true;
conn.jid = 'dummy@localhost';
conn._proto.rid = '123456';
conn._proto.sid = '987654321';
equal(window.sessionStorage.getItem('strophe-bosh-session'), undefined);
conn._proto.rid = '1234567';
conn._proto.sid = '9876543210';
conn._proto._cacheSession();
notEqual(window.sessionStorage.getItem('strophe-bosh-session'), undefined);

// Check that giving a different jid causes an exception to be
// raised.
try {
conn.restore('differentdummy@localhost');
} catch (e) {
equal(e.name, "StropheSessionError");
equal(e.message, "_restore: no restoreable session.");
}
equal(conn.restored, false);
equal(boshSpy.called, true);
equal(checkSpy.called, true);

// Check that passing in the right jid but with a resource is not a problem.
conn.restore('dummy@localhost/with_resource');
equal(conn.jid,'dummy@localhost');
equal(conn._proto.rid,'1234567');
equal(conn._proto.sid,'9876543210');
equal(conn.restored, true);
});

test('when calling "restore" with a restorable session, bosh._attach is called with the session tokens', function () {
window.sessionStorage.removeItem('strophe-bosh-session');
var conn = new Strophe.Connection("", {"keepalive": true});
conn.connected = true;
conn.authenticated = true;
conn.jid = 'dummy@localhost';
conn._proto.rid = '123456';
conn._proto.sid = '987654321';
conn._proto._cacheSession();
delete conn._proto.rid;
delete conn._proto.sid;
delete conn._proto.jid;
equal(conn.restored, false);

var boshSpy = sinon.spy(conn._proto, "_restore");
var checkSpy = sinon.spy(conn, "_sessionCachingSupported");
var attachSpsy = sinon.spy(conn._proto, "_attach");
conn.restore();
equal(conn.jid,'dummy@localhost');
equal(conn._proto.rid,'123456');
equal(conn._proto.sid,'987654321');
equal(conn.restored, true);
equal(boshSpy.called, true);
equal(checkSpy.called, true);
equal(attachSpsy.called, true);
});

};
return {run: run};
});

0 comments on commit fa0a59f

Please sign in to comment.