1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
/*
* ***** BEGIN LICENSE BLOCK *****
* Copyright (c) 2011-2012 VMware, Inc.
*
* For the license see COPYING.
* ***** END LICENSE BLOCK *****
*/
// The simplest and most robust transport, using the well-know cross
// domain hack - JSONP. This transport is quite inefficient - one
// mssage could use up to one http request. But at least it works almost
// everywhere.
// Known limitations:
// o you will get a spinning cursor
// o for Konqueror a dumb timer is needed to detect errors
var JsonPTransport = SockJS['jsonp-polling'] = function(ri, trans_url) {
utils.polluteGlobalNamespace();
var that = this;
that.ri = ri;
that.trans_url = trans_url;
that.send_constructor(jsonPGenericSender);
that._schedule_recv();
};
// Inheritnace
JsonPTransport.prototype = new BufferedSender();
JsonPTransport.prototype._schedule_recv = function() {
var that = this;
var callback = function(data) {
that._recv_stop = null;
if (data) {
// no data - heartbeat;
if (!that._is_closing) {
that.ri._didMessage(data);
}
}
// The message can be a close message, and change is_closing state.
if (!that._is_closing) {
that._schedule_recv();
}
};
that._recv_stop = jsonPReceiverWrapper(that.trans_url + '/jsonp',
jsonPGenericReceiver, callback);
};
JsonPTransport.enabled = function() {
return true;
};
JsonPTransport.need_body = true;
JsonPTransport.prototype.doCleanup = function() {
var that = this;
that._is_closing = true;
if (that._recv_stop) {
that._recv_stop();
}
that.ri = that._recv_stop = null;
that.send_destructor();
};
// Abstract away code that handles global namespace pollution.
var jsonPReceiverWrapper = function(url, constructReceiver, user_callback) {
var id = 'a' + utils.random_string(6);
var url_id = url + '?c=' + escape(WPrefix + '.' + id);
// Unfortunately it is not possible to abort loading of the
// script. We need to keep track of frake close frames.
var aborting = 0;
// Callback will be called exactly once.
var callback = function(frame) {
switch(aborting) {
case 0:
// Normal behaviour - delete hook _and_ emit message.
delete _window[WPrefix][id];
user_callback(frame);
break;
case 1:
// Fake close frame - emit but don't delete hook.
user_callback(frame);
aborting = 2;
break;
case 2:
// Got frame after connection was closed, delete hook, don't emit.
delete _window[WPrefix][id];
break;
}
};
var close_script = constructReceiver(url_id, callback);
_window[WPrefix][id] = close_script;
var stop = function() {
if (_window[WPrefix][id]) {
aborting = 1;
_window[WPrefix][id](utils.closeFrame(1000, "JSONP user aborted read"));
}
};
return stop;
};
|