mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
New build scripts
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5282 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
929
source/web/scripts/ajax/dojo/src/io/cometd.js
Normal file
929
source/web/scripts/ajax/dojo/src/io/cometd.js
Normal file
@@ -0,0 +1,929 @@
|
||||
/*
|
||||
Copyright (c) 2004-2006, The Dojo Foundation
|
||||
All Rights Reserved.
|
||||
|
||||
Licensed under the Academic Free License version 2.1 or above OR the
|
||||
modified BSD license. For more information on Dojo licensing, see:
|
||||
|
||||
http://dojotoolkit.org/community/licensing.shtml
|
||||
*/
|
||||
|
||||
dojo.require("dojo.io.common"); // io/common.js provides setIFrameSrc and the IO module
|
||||
dojo.provide("dojo.io.cometd");
|
||||
dojo.require("dojo.AdapterRegistry");
|
||||
dojo.require("dojo.json");
|
||||
dojo.require("dojo.io.BrowserIO"); // we need XHR for the handshake, etc.
|
||||
// FIXME: determine if we can use XMLHTTP to make x-domain posts despite not
|
||||
// being able to hear back about the result
|
||||
dojo.require("dojo.io.IframeIO");
|
||||
dojo.require("dojo.io.ScriptSrcIO"); // for x-domain long polling
|
||||
dojo.require("dojo.io.cookie"); // for peering
|
||||
dojo.require("dojo.event.*");
|
||||
dojo.require("dojo.lang.common");
|
||||
dojo.require("dojo.lang.func");
|
||||
|
||||
/*
|
||||
* this file defines Comet protocol client. Actual message transport is
|
||||
* deferred to one of several connection type implementations. The default is a
|
||||
* forever-frame implementation. A single global object named "cometd" is
|
||||
* used to mediate for these connection types in order to provide a stable
|
||||
* interface.
|
||||
*/
|
||||
|
||||
// TODO: the auth handling in this file is a *mess*. It should probably live in
|
||||
// the cometd object with the ability to mix in or call down to an auth-handler
|
||||
// object, the prototypical variant of which is a no-op
|
||||
|
||||
cometd = new function(){
|
||||
|
||||
this.initialized = false;
|
||||
this.connected = false;
|
||||
|
||||
this.connectionTypes = new dojo.AdapterRegistry(true);
|
||||
|
||||
this.version = 0.1;
|
||||
this.minimumVersion = 0.1;
|
||||
this.clientId = null;
|
||||
|
||||
this._isXD = false;
|
||||
this.handshakeReturn = null;
|
||||
this.currentTransport = null;
|
||||
this.url = null;
|
||||
this.lastMessage = null;
|
||||
this.globalTopicChannels = {};
|
||||
this.backlog = [];
|
||||
|
||||
this.tunnelInit = function(childLocation, childDomain){
|
||||
// placeholder
|
||||
}
|
||||
|
||||
this.tunnelCollapse = function(){
|
||||
dojo.debug("tunnel collapsed!");
|
||||
// placeholder
|
||||
}
|
||||
|
||||
this.init = function(props, root, bargs){
|
||||
// FIXME: if the root isn't from the same host, we should automatically
|
||||
// try to select an XD-capable transport
|
||||
props = props||{};
|
||||
// go ask the short bus server what we can support
|
||||
props.version = this.version;
|
||||
props.minimumVersion = this.minimumVersion;
|
||||
props.channel = "/meta/handshake";
|
||||
// FIXME: do we just assume that the props knows
|
||||
// everything we care about WRT to auth? Should we be trying to
|
||||
// call back into it for subsequent auth actions? Should we fire
|
||||
// local auth functions to ask for/get auth data?
|
||||
|
||||
// FIXME: what about ScriptSrcIO for x-domain comet?
|
||||
this.url = root||djConfig["cometdRoot"];
|
||||
if(!this.url){
|
||||
dojo.debug("no cometd root specified in djConfig and no root passed");
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: we need to select a way to handle JSONP-style stuff
|
||||
// generically here. We already know if the server is gonna be on
|
||||
// another domain (or can know it), so we should select appropriate
|
||||
// negotiation methods here as well as in final transport type
|
||||
// selection.
|
||||
var bindArgs = {
|
||||
url: this.url,
|
||||
method: "POST",
|
||||
mimetype: "text/json",
|
||||
load: dojo.lang.hitch(this, "finishInit"),
|
||||
content: { "message": dojo.json.serialize([props]) }
|
||||
};
|
||||
|
||||
// borrowed from dojo.uri.Uri in lieu of fixed host and port properties
|
||||
var regexp = "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$";
|
||||
var r = (""+window.location).match(new RegExp(regexp));
|
||||
if(r[4]){
|
||||
var tmp = r[4].split(":");
|
||||
var thisHost = tmp[0];
|
||||
var thisPort = tmp[1]||"80"; // FIXME: match 443
|
||||
|
||||
r = this.url.match(new RegExp(regexp));
|
||||
if(r[4]){
|
||||
tmp = r[4].split(":");
|
||||
var urlHost = tmp[0];
|
||||
var urlPort = tmp[1]||"80";
|
||||
if( (urlHost != thisHost)||
|
||||
(urlPort != thisPort) ){
|
||||
dojo.debug(thisHost, urlHost);
|
||||
dojo.debug(thisPort, urlPort);
|
||||
|
||||
this._isXD = true;
|
||||
bindArgs.transport = "ScriptSrcTransport";
|
||||
bindArgs.jsonParamName = "jsonp";
|
||||
bindArgs.method = "GET";
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bargs){
|
||||
dojo.lang.mixin(bindArgs, bargs);
|
||||
}
|
||||
return dojo.io.bind(bindArgs);
|
||||
}
|
||||
|
||||
this.finishInit = function(type, data, evt, request){
|
||||
data = data[0];
|
||||
this.handshakeReturn = data;
|
||||
// pick a transport
|
||||
if(data["authSuccessful"] == false){
|
||||
dojo.debug("cometd authentication failed");
|
||||
return;
|
||||
}
|
||||
if(data.version < this.minimumVersion){
|
||||
dojo.debug("cometd protocol version mismatch. We wanted", this.minimumVersion, "but got", data.version);
|
||||
return;
|
||||
}
|
||||
this.currentTransport = this.connectionTypes.match(
|
||||
data.supportedConnectionTypes,
|
||||
data.version,
|
||||
this._isXD
|
||||
);
|
||||
this.currentTransport.version = data.version;
|
||||
this.clientId = data.clientId;
|
||||
this.tunnelInit = dojo.lang.hitch(this.currentTransport, "tunnelInit");
|
||||
this.tunnelCollapse = dojo.lang.hitch(this.currentTransport, "tunnelCollapse");
|
||||
this.initialized = true;
|
||||
this.currentTransport.startup(data);
|
||||
while(this.backlog.length != 0){
|
||||
var cur = this.backlog.shift();
|
||||
var fn = cur.shift();
|
||||
this[fn].apply(this, cur);
|
||||
}
|
||||
}
|
||||
|
||||
this._getRandStr = function(){
|
||||
return Math.random().toString().substring(2, 10);
|
||||
}
|
||||
|
||||
// public API functions called by cometd or by the transport classes
|
||||
this.deliver = function(messages){
|
||||
dojo.lang.forEach(messages, this._deliver, this);
|
||||
}
|
||||
|
||||
this._deliver = function(message){
|
||||
// dipatch events along the specified path
|
||||
if(!message["channel"]){
|
||||
dojo.debug("cometd error: no channel for message!");
|
||||
return;
|
||||
}
|
||||
if(!this.currentTransport){
|
||||
this.backlog.push(["deliver", message]);
|
||||
return;
|
||||
}
|
||||
this.lastMessage = message;
|
||||
// check to see if we got a /meta channel message that we care about
|
||||
if( (message.channel.length > 5)&&
|
||||
(message.channel.substr(0, 5) == "/meta")){
|
||||
// check for various meta topic actions that we need to respond to
|
||||
switch(message.channel){
|
||||
case "/meta/subscribe":
|
||||
if(!message.successful){
|
||||
dojo.debug("cometd subscription error for channel", message.channel, ":", message.error);
|
||||
return;
|
||||
}
|
||||
this.subscribed(message.subscription, message);
|
||||
break;
|
||||
case "/meta/unsubscribe":
|
||||
if(!message.successful){
|
||||
dojo.debug("cometd unsubscription error for channel", message.channel, ":", message.error);
|
||||
return;
|
||||
}
|
||||
this.unsubscribed(message.subscription, message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// send the message down for processing by the transport
|
||||
this.currentTransport.deliver(message);
|
||||
|
||||
// dispatch the message to any locally subscribed listeners
|
||||
var tname = (this.globalTopicChannels[message.channel]) ? message.channel : "/cometd"+message.channel;
|
||||
dojo.event.topic.publish(tname, message);
|
||||
}
|
||||
|
||||
this.disconnect = function(){
|
||||
if(!this.currentTransport){
|
||||
dojo.debug("no current transport to disconnect from");
|
||||
return;
|
||||
}
|
||||
this.currentTransport.disconnect();
|
||||
}
|
||||
|
||||
// public API functions called by end users
|
||||
this.publish = function(/*string*/channel, /*object*/data, /*object*/properties){
|
||||
// summary:
|
||||
// publishes the passed message to the cometd server for delivery
|
||||
// on the specified topic
|
||||
// channel:
|
||||
// the destination channel for the message
|
||||
// data:
|
||||
// a JSON object containing the message "payload"
|
||||
// properties:
|
||||
// Optional. Other meta-data to be mixed into the top-level of the
|
||||
// message
|
||||
if(!this.currentTransport){
|
||||
this.backlog.push(["publish", channel, data, properties]);
|
||||
return;
|
||||
}
|
||||
var message = {
|
||||
data: data,
|
||||
channel: channel
|
||||
};
|
||||
if(properties){
|
||||
dojo.lang.mixin(message, properties);
|
||||
}
|
||||
return this.currentTransport.sendMessage(message);
|
||||
}
|
||||
|
||||
this.subscribe = function( /*string*/ channel,
|
||||
/*boolean, optional*/ useLocalTopics,
|
||||
/*object, optional*/ objOrFunc,
|
||||
/*string, optional*/ funcName){ // return: boolean
|
||||
// summary:
|
||||
// inform the server of this client's interest in channel
|
||||
// channel:
|
||||
// name of the cometd channel to subscribe to
|
||||
// useLocalTopics:
|
||||
// Determines if up a local event topic subscription to the passed
|
||||
// function using the channel name that was passed is constructed,
|
||||
// or if the topic name will be prefixed with some other
|
||||
// identifier for local message distribution. Setting this to
|
||||
// "true" is a good way to hook up server-sent message delivery to
|
||||
// pre-existing local topics.
|
||||
// objOrFunc:
|
||||
// an object scope for funcName or the name or reference to a
|
||||
// function to be called when messages are delivered to the
|
||||
// channel
|
||||
// funcName:
|
||||
// the second half of the objOrFunc/funcName pair for identifying
|
||||
// a callback function to notifiy upon channel message delivery
|
||||
if(!this.currentTransport){
|
||||
this.backlog.push(["subscribe", channel, useLocalTopics, objOrFunc, funcName]);
|
||||
return;
|
||||
}
|
||||
if(objOrFunc){
|
||||
var tname = (useLocalTopics) ? channel : "/cometd"+channel;
|
||||
if(useLocalTopics){
|
||||
this.globalTopicChannels[channel] = true;
|
||||
}
|
||||
dojo.event.topic.subscribe(tname, objOrFunc, funcName);
|
||||
}
|
||||
// FIXME: would we handle queuing of the subscription if not connected?
|
||||
// Or should the transport object?
|
||||
return this.currentTransport.sendMessage({
|
||||
channel: "/meta/subscribe",
|
||||
subscription: channel
|
||||
});
|
||||
}
|
||||
|
||||
this.subscribed = function( /*string*/ channel,
|
||||
/*obj*/ message){
|
||||
dojo.debug(channel);
|
||||
dojo.debugShallow(message);
|
||||
}
|
||||
|
||||
this.unsubscribe = function(/*string*/ channel,
|
||||
/*boolean, optional*/ useLocalTopics,
|
||||
/*object, optional*/ objOrFunc,
|
||||
/*string, optional*/ funcName){ // return: boolean
|
||||
// summary:
|
||||
// inform the server of this client's disinterest in channel
|
||||
// channel:
|
||||
// name of the cometd channel to subscribe to
|
||||
// useLocalTopics:
|
||||
// Determines if up a local event topic subscription to the passed
|
||||
// function using the channel name that was passed is destroyed,
|
||||
// or if the topic name will be prefixed with some other
|
||||
// identifier for stopping message distribution.
|
||||
// objOrFunc:
|
||||
// an object scope for funcName or the name or reference to a
|
||||
// function to be called when messages are delivered to the
|
||||
// channel
|
||||
// funcName:
|
||||
// the second half of the objOrFunc/funcName pair for identifying
|
||||
if(!this.currentTransport){
|
||||
this.backlog.push(["unsubscribe", channel, useLocalTopics, objOrFunc, funcName]);
|
||||
return;
|
||||
}
|
||||
// a callback function to notifiy upon channel message delivery
|
||||
if(objOrFunc){
|
||||
// FIXME: should actual local topic unsubscription be delayed for
|
||||
// successful unsubcribe notices from the other end? (guessing "no")
|
||||
// FIXME: if useLocalTopics is false, should we go ahead and
|
||||
// destroy the local topic?
|
||||
var tname = (useLocalTopics) ? channel : "/cometd"+channel;
|
||||
dojo.event.topic.unsubscribe(tname, objOrFunc, funcName);
|
||||
}
|
||||
return this.currentTransport.sendMessage({
|
||||
channel: "/meta/unsubscribe",
|
||||
subscription: channel
|
||||
});
|
||||
}
|
||||
|
||||
this.unsubscribed = function(/*string*/ channel,
|
||||
/*obj*/ message){
|
||||
dojo.debug(channel);
|
||||
dojo.debugShallow(message);
|
||||
}
|
||||
|
||||
// FIXME: add an "addPublisher" function
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
transport objects MUST expose the following methods:
|
||||
- check
|
||||
- startup
|
||||
- sendMessage
|
||||
- deliver
|
||||
- disconnect
|
||||
optional, standard but transport dependent methods are:
|
||||
- tunnelCollapse
|
||||
- tunnelInit
|
||||
|
||||
Transports SHOULD be namespaced under the cometd object and transports MUST
|
||||
register themselves with cometd.connectionTypes
|
||||
|
||||
here's a stub transport defintion:
|
||||
|
||||
cometd.blahTransport = new function(){
|
||||
this.connected = false;
|
||||
this.connectionId = null;
|
||||
this.authToken = null;
|
||||
this.lastTimestamp = null;
|
||||
this.lastId = null;
|
||||
|
||||
this.check = function(types, version, xdomain){
|
||||
// summary:
|
||||
// determines whether or not this transport is suitable given a
|
||||
// list of transport types that the server supports
|
||||
return dojo.lang.inArray(types, "blah");
|
||||
}
|
||||
|
||||
this.startup = function(){
|
||||
if(this.connected){ return; }
|
||||
// FIXME: fill in startup routine here
|
||||
this.connected = true;
|
||||
}
|
||||
|
||||
this.sendMessage = function(message){
|
||||
// FIXME: fill in message sending logic
|
||||
}
|
||||
|
||||
this.deliver = function(message){
|
||||
if(message["timestamp"]){
|
||||
this.lastTimestamp = message.timestamp;
|
||||
}
|
||||
if(message["id"]){
|
||||
this.lastId = message.id;
|
||||
}
|
||||
if( (message.channel.length > 5)&&
|
||||
(message.channel.substr(0, 5) == "/meta")){
|
||||
// check for various meta topic actions that we need to respond to
|
||||
// switch(message.channel){
|
||||
// case "/meta/connect":
|
||||
// // FIXME: fill in logic here
|
||||
// break;
|
||||
// // case ...: ...
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
this.disconnect = function(){
|
||||
if(!this.connected){ return; }
|
||||
// FIXME: fill in shutdown routine here
|
||||
this.connected = false;
|
||||
}
|
||||
}
|
||||
cometd.connectionTypes.register("blah", cometd.blahTransport.check, cometd.blahTransport);
|
||||
*/
|
||||
|
||||
cometd.iframeTransport = new function(){
|
||||
this.connected = false;
|
||||
this.connectionId = null;
|
||||
|
||||
this.rcvNode = null;
|
||||
this.rcvNodeName = "";
|
||||
this.phonyForm = null;
|
||||
this.authToken = null;
|
||||
this.lastTimestamp = null;
|
||||
this.lastId = null;
|
||||
this.backlog = [];
|
||||
|
||||
this.check = function(types, version, xdomain){
|
||||
return ((!xdomain)&&
|
||||
(!dojo.render.html.safari)&&
|
||||
(dojo.lang.inArray(types, "iframe")));
|
||||
}
|
||||
|
||||
this.tunnelInit = function(){
|
||||
// we've gotten our initialization document back in the iframe, so
|
||||
// now open up a connection and start passing data!
|
||||
this.postToIframe({
|
||||
message: dojo.json.serialize([
|
||||
{
|
||||
channel: "/meta/connect",
|
||||
clientId: cometd.clientId,
|
||||
connectionType: "iframe"
|
||||
// FIXME: auth not passed here!
|
||||
// "authToken": this.authToken
|
||||
}
|
||||
])
|
||||
});
|
||||
}
|
||||
|
||||
this.tunnelCollapse = function(){
|
||||
if(this.connected){
|
||||
// try to restart the tunnel
|
||||
this.connected = false;
|
||||
|
||||
this.postToIframe({
|
||||
message: dojo.json.serialize([
|
||||
{
|
||||
channel: "/meta/reconnect",
|
||||
clientId: cometd.clientId,
|
||||
connectionId: this.connectionId,
|
||||
timestamp: this.lastTimestamp,
|
||||
id: this.lastId
|
||||
// FIXME: no authToken provision!
|
||||
}
|
||||
])
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.deliver = function(message){
|
||||
// handle delivery details that this transport particularly cares
|
||||
// about. Most functions of should be handled by the main cometd object
|
||||
// with only transport-specific details and state being tracked here.
|
||||
if(message["timestamp"]){
|
||||
this.lastTimestamp = message.timestamp;
|
||||
}
|
||||
if(message["id"]){
|
||||
this.lastId = message.id;
|
||||
}
|
||||
// check to see if we got a /meta channel message that we care about
|
||||
if( (message.channel.length > 5)&&
|
||||
(message.channel.substr(0, 5) == "/meta")){
|
||||
// check for various meta topic actions that we need to respond to
|
||||
switch(message.channel){
|
||||
case "/meta/connect":
|
||||
if(!message.successful){
|
||||
dojo.debug("cometd connection error:", message.error);
|
||||
return;
|
||||
}
|
||||
this.connectionId = message.connectionId;
|
||||
this.connected = true;
|
||||
this.processBacklog();
|
||||
break;
|
||||
case "/meta/reconnect":
|
||||
if(!message.successful){
|
||||
dojo.debug("cometd reconnection error:", message.error);
|
||||
return;
|
||||
}
|
||||
this.connected = true;
|
||||
break;
|
||||
case "/meta/subscribe":
|
||||
if(!message.successful){
|
||||
dojo.debug("cometd subscription error for channel", message.channel, ":", message.error);
|
||||
return;
|
||||
}
|
||||
// this.subscribed(message.channel);
|
||||
dojo.debug(message.channel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.widenDomain = function(domainStr){
|
||||
// allow us to make reqests to the TLD
|
||||
var cd = domainStr||document.domain;
|
||||
if(cd.indexOf(".")==-1){ return; } // probably file:/// or localhost
|
||||
var dps = cd.split(".");
|
||||
if(dps.length<=2){ return; } // probably file:/// or an RFC 1918 address
|
||||
dps = dps.slice(dps.length-2);
|
||||
document.domain = dps.join(".");
|
||||
return document.domain;
|
||||
}
|
||||
|
||||
this.postToIframe = function(content, url){
|
||||
if(!this.phonyForm){
|
||||
if(dojo.render.html.ie){
|
||||
this.phonyForm = document.createElement("<form enctype='application/x-www-form-urlencoded' method='POST' style='display: none;'>");
|
||||
dojo.body().appendChild(this.phonyForm);
|
||||
}else{
|
||||
this.phonyForm = document.createElement("form");
|
||||
this.phonyForm.style.display = "none"; // FIXME: will this still work?
|
||||
dojo.body().appendChild(this.phonyForm);
|
||||
this.phonyForm.enctype = "application/x-www-form-urlencoded";
|
||||
this.phonyForm.method = "POST";
|
||||
}
|
||||
}
|
||||
|
||||
this.phonyForm.action = url||cometd.url;
|
||||
this.phonyForm.target = this.rcvNodeName;
|
||||
this.phonyForm.setAttribute("target", this.rcvNodeName);
|
||||
|
||||
while(this.phonyForm.firstChild){
|
||||
this.phonyForm.removeChild(this.phonyForm.firstChild);
|
||||
}
|
||||
|
||||
for(var x in content){
|
||||
var tn;
|
||||
if(dojo.render.html.ie){
|
||||
tn = document.createElement("<input type='hidden' name='"+x+"' value='"+content[x]+"'>");
|
||||
this.phonyForm.appendChild(tn);
|
||||
}else{
|
||||
tn = document.createElement("input");
|
||||
this.phonyForm.appendChild(tn);
|
||||
tn.type = "hidden";
|
||||
tn.name = x;
|
||||
tn.value = content[x];
|
||||
}
|
||||
}
|
||||
this.phonyForm.submit();
|
||||
}
|
||||
|
||||
this.processBacklog = function(){
|
||||
while(this.backlog.length > 0){
|
||||
this.sendMessage(this.backlog.shift(), true);
|
||||
}
|
||||
}
|
||||
|
||||
this.sendMessage = function(message, bypassBacklog){
|
||||
// FIXME: what about auth fields?
|
||||
if((bypassBacklog)||(this.connected)){
|
||||
message.connectionId = this.connectionId;
|
||||
message.clientId = cometd.clientId;
|
||||
var bindArgs = {
|
||||
url: cometd.url||djConfig["cometdRoot"],
|
||||
method: "POST",
|
||||
mimetype: "text/json",
|
||||
// FIXME: we should be able to do better than this given that we're sending an array!
|
||||
content: { message: dojo.json.serialize([ message ]) }
|
||||
};
|
||||
return dojo.io.bind(bindArgs);
|
||||
}else{
|
||||
this.backlog.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
this.startup = function(handshakeData){
|
||||
dojo.debug("startup!");
|
||||
dojo.debug(dojo.json.serialize(handshakeData));
|
||||
|
||||
if(this.connected){ return; }
|
||||
|
||||
// this.widenDomain();
|
||||
|
||||
// NOTE: we require the server to cooperate by hosting
|
||||
// cometdInit.html at the designated endpoint
|
||||
this.rcvNodeName = "cometdRcv_"+cometd._getRandStr();
|
||||
// the "forever frame" approach
|
||||
|
||||
var initUrl = cometd.url+"/?tunnelInit=iframe"; // &domain="+document.domain;
|
||||
if(false && dojo.render.html.ie){ // FIXME: DISALBED FOR NOW
|
||||
// use the "htmlfile hack" to prevent the background click junk
|
||||
this.rcvNode = new ActiveXObject("htmlfile");
|
||||
this.rcvNode.open();
|
||||
this.rcvNode.write("<html>");
|
||||
this.rcvNode.write("<script>document.domain = '"+document.domain+"'");
|
||||
this.rcvNode.write("</html>");
|
||||
this.rcvNode.close();
|
||||
|
||||
var ifrDiv = this.rcvNode.createElement("div");
|
||||
this.rcvNode.appendChild(ifrDiv);
|
||||
this.rcvNode.parentWindow.dojo = dojo;
|
||||
ifrDiv.innerHTML = "<iframe src='"+initUrl+"'></iframe>"
|
||||
}else{
|
||||
this.rcvNode = dojo.io.createIFrame(this.rcvNodeName, "", initUrl);
|
||||
// dojo.io.setIFrameSrc(this.rcvNode, initUrl);
|
||||
// we're still waiting on the iframe to call back up to use and
|
||||
// advertise that it's been initialized via tunnelInit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cometd.mimeReplaceTransport = new function(){
|
||||
this.connected = false;
|
||||
this.connectionId = null;
|
||||
this.xhr = null;
|
||||
|
||||
this.authToken = null;
|
||||
this.lastTimestamp = null;
|
||||
this.lastId = null;
|
||||
this.backlog = [];
|
||||
|
||||
this.check = function(types, version, xdomain){
|
||||
return ((!xdomain)&&
|
||||
(dojo.render.html.mozilla)&& // seems only Moz really supports this right now = (
|
||||
(dojo.lang.inArray(types, "mime-message-block")));
|
||||
}
|
||||
|
||||
this.tunnelInit = function(){
|
||||
if(this.connected){ return; }
|
||||
// FIXME: open up the connection here
|
||||
this.openTunnelWith({
|
||||
message: dojo.json.serialize([
|
||||
{
|
||||
channel: "/meta/connect",
|
||||
clientId: cometd.clientId,
|
||||
connectionType: "mime-message-block"
|
||||
// FIXME: auth not passed here!
|
||||
// "authToken": this.authToken
|
||||
}
|
||||
])
|
||||
});
|
||||
this.connected = true;
|
||||
}
|
||||
|
||||
this.tunnelCollapse = function(){
|
||||
if(this.connected){
|
||||
// try to restart the tunnel
|
||||
this.connected = false;
|
||||
this.openTunnelWith({
|
||||
message: dojo.json.serialize([
|
||||
{
|
||||
channel: "/meta/reconnect",
|
||||
clientId: cometd.clientId,
|
||||
connectionId: this.connectionId,
|
||||
timestamp: this.lastTimestamp,
|
||||
id: this.lastId
|
||||
// FIXME: no authToken provision!
|
||||
}
|
||||
])
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.deliver = cometd.iframeTransport.deliver;
|
||||
// the logic appears to be the same
|
||||
|
||||
this.handleOnLoad = function(resp){
|
||||
cometd.deliver(dojo.json.evalJson(this.xhr.responseText));
|
||||
}
|
||||
|
||||
this.openTunnelWith = function(content, url){
|
||||
// set up the XHR object and register the multipart callbacks
|
||||
this.xhr = dojo.hostenv.getXmlhttpObject();
|
||||
this.xhr.multipart = true; // FIXME: do Opera and Safari support this flag?
|
||||
if(dojo.render.html.mozilla){
|
||||
this.xhr.addEventListener("load", dojo.lang.hitch(this, "handleOnLoad"), false);
|
||||
}else if(dojo.render.html.safari){
|
||||
// Blah. WebKit doesn't actually populate responseText and/or responseXML. Useless.
|
||||
dojo.debug("Webkit is broken with multipart responses over XHR = (");
|
||||
this.xhr.onreadystatechange = dojo.lang.hitch(this, "handleOnLoad");
|
||||
}else{
|
||||
this.xhr.onload = dojo.lang.hitch(this, "handleOnLoad");
|
||||
}
|
||||
this.xhr.open("POST", (url||cometd.url), true); // async post
|
||||
this.xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
dojo.debug(dojo.json.serialize(content));
|
||||
this.xhr.send(dojo.io.argsFromMap(content, "utf8"));
|
||||
}
|
||||
|
||||
this.processBacklog = function(){
|
||||
while(this.backlog.length > 0){
|
||||
this.sendMessage(this.backlog.shift(), true);
|
||||
}
|
||||
}
|
||||
|
||||
this.sendMessage = function(message, bypassBacklog){
|
||||
// FIXME: what about auth fields?
|
||||
if((bypassBacklog)||(this.connected)){
|
||||
message.connectionId = this.connectionId;
|
||||
message.clientId = cometd.clientId;
|
||||
var bindArgs = {
|
||||
url: cometd.url||djConfig["cometdRoot"],
|
||||
method: "POST",
|
||||
mimetype: "text/json",
|
||||
content: { message: dojo.json.serialize([ message ]) }
|
||||
};
|
||||
return dojo.io.bind(bindArgs);
|
||||
}else{
|
||||
this.backlog.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
this.startup = function(handshakeData){
|
||||
dojo.debugShallow(handshakeData);
|
||||
if(this.connected){ return; }
|
||||
this.tunnelInit();
|
||||
}
|
||||
}
|
||||
|
||||
cometd.longPollTransport = new function(){
|
||||
this.connected = false;
|
||||
this.connectionId = null;
|
||||
|
||||
this.authToken = null;
|
||||
this.lastTimestamp = null;
|
||||
this.lastId = null;
|
||||
this.backlog = [];
|
||||
|
||||
this.check = function(types, version, xdomain){
|
||||
return ((!xdomain)&&(dojo.lang.inArray(types, "long-polling")));
|
||||
}
|
||||
|
||||
this.tunnelInit = function(){
|
||||
if(this.connected){ return; }
|
||||
// FIXME: open up the connection here
|
||||
this.openTunnelWith({
|
||||
message: dojo.json.serialize([
|
||||
{
|
||||
channel: "/meta/connect",
|
||||
clientId: cometd.clientId,
|
||||
connectionType: "long-polling"
|
||||
// FIXME: auth not passed here!
|
||||
// "authToken": this.authToken
|
||||
}
|
||||
])
|
||||
});
|
||||
this.connected = true;
|
||||
}
|
||||
|
||||
this.tunnelCollapse = function(){
|
||||
if(!this.connected){
|
||||
// try to restart the tunnel
|
||||
this.connected = false;
|
||||
dojo.debug("clientId:", cometd.clientId);
|
||||
this.openTunnelWith({
|
||||
message: dojo.json.serialize([
|
||||
{
|
||||
channel: "/meta/reconnect",
|
||||
connectionType: "long-polling",
|
||||
clientId: cometd.clientId,
|
||||
connectionId: this.connectionId,
|
||||
timestamp: this.lastTimestamp,
|
||||
id: this.lastId
|
||||
// FIXME: no authToken provision!
|
||||
}
|
||||
])
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.deliver = cometd.iframeTransport.deliver;
|
||||
// the logic appears to be the same
|
||||
|
||||
this.openTunnelWith = function(content, url){
|
||||
dojo.io.bind({
|
||||
url: (url||cometd.url),
|
||||
method: "post",
|
||||
content: content,
|
||||
mimetype: "text/json",
|
||||
load: dojo.lang.hitch(this, function(type, data, evt, args){
|
||||
// dojo.debug(evt.responseText);
|
||||
cometd.deliver(data);
|
||||
this.connected = false;
|
||||
this.tunnelCollapse();
|
||||
}),
|
||||
error: function(){ dojo.debug("tunnel opening failed"); }
|
||||
});
|
||||
this.connected = true;
|
||||
}
|
||||
|
||||
this.processBacklog = function(){
|
||||
while(this.backlog.length > 0){
|
||||
this.sendMessage(this.backlog.shift(), true);
|
||||
}
|
||||
}
|
||||
|
||||
this.sendMessage = function(message, bypassBacklog){
|
||||
// FIXME: what about auth fields?
|
||||
if((bypassBacklog)||(this.connected)){
|
||||
message.connectionId = this.connectionId;
|
||||
message.clientId = cometd.clientId;
|
||||
var bindArgs = {
|
||||
url: cometd.url||djConfig["cometdRoot"],
|
||||
method: "post",
|
||||
mimetype: "text/json",
|
||||
content: { message: dojo.json.serialize([ message ]) }
|
||||
};
|
||||
return dojo.io.bind(bindArgs);
|
||||
}else{
|
||||
this.backlog.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
this.startup = function(handshakeData){
|
||||
if(this.connected){ return; }
|
||||
this.tunnelInit();
|
||||
}
|
||||
}
|
||||
|
||||
cometd.callbackPollTransport = new function(){
|
||||
this.connected = false;
|
||||
this.connectionId = null;
|
||||
|
||||
this.authToken = null;
|
||||
this.lastTimestamp = null;
|
||||
this.lastId = null;
|
||||
this.backlog = [];
|
||||
|
||||
this.check = function(types, version, xdomain){
|
||||
// we handle x-domain!
|
||||
return dojo.lang.inArray(types, "callback-polling");
|
||||
}
|
||||
|
||||
this.tunnelInit = function(){
|
||||
if(this.connected){ return; }
|
||||
// FIXME: open up the connection here
|
||||
this.openTunnelWith({
|
||||
message: dojo.json.serialize([
|
||||
{
|
||||
channel: "/meta/connect",
|
||||
clientId: cometd.clientId,
|
||||
connectionType: "callback-polling"
|
||||
// FIXME: auth not passed here!
|
||||
// "authToken": this.authToken
|
||||
}
|
||||
])
|
||||
});
|
||||
this.connected = true;
|
||||
}
|
||||
|
||||
this.tunnelCollapse = function(){
|
||||
if(!this.connected){
|
||||
// try to restart the tunnel
|
||||
this.connected = false;
|
||||
this.openTunnelWith({
|
||||
message: dojo.json.serialize([
|
||||
{
|
||||
channel: "/meta/reconnect",
|
||||
connectionType: "long-polling",
|
||||
clientId: cometd.clientId,
|
||||
connectionId: this.connectionId,
|
||||
timestamp: this.lastTimestamp,
|
||||
id: this.lastId
|
||||
// FIXME: no authToken provision!
|
||||
}
|
||||
])
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.deliver = cometd.iframeTransport.deliver;
|
||||
// the logic appears to be the same
|
||||
|
||||
this.openTunnelWith = function(content, url){
|
||||
// create a <script> element to generate the request
|
||||
var req = dojo.io.bind({
|
||||
url: (url||cometd.url),
|
||||
content: content,
|
||||
mimetype: "text/json",
|
||||
transport: "ScriptSrcTransport",
|
||||
jsonParamName: "jsonp",
|
||||
load: dojo.lang.hitch(this, function(type, data, evt, args){
|
||||
dojo.debug(dojo.json.serialize(data));
|
||||
cometd.deliver(data);
|
||||
this.connected = false;
|
||||
this.tunnelCollapse();
|
||||
}),
|
||||
error: function(){ dojo.debug("tunnel opening failed"); }
|
||||
});
|
||||
this.connected = true;
|
||||
}
|
||||
|
||||
this.processBacklog = function(){
|
||||
while(this.backlog.length > 0){
|
||||
this.sendMessage(this.backlog.shift(), true);
|
||||
}
|
||||
}
|
||||
|
||||
this.sendMessage = function(message, bypassBacklog){
|
||||
// FIXME: what about auth fields?
|
||||
if((bypassBacklog)||(this.connected)){
|
||||
message.connectionId = this.connectionId;
|
||||
message.clientId = cometd.clientId;
|
||||
var bindArgs = {
|
||||
url: cometd.url||djConfig["cometdRoot"],
|
||||
mimetype: "text/json",
|
||||
transport: "ScriptSrcTransport",
|
||||
jsonParamName: "jsonp",
|
||||
content: { message: dojo.json.serialize([ message ]) }
|
||||
};
|
||||
return dojo.io.bind(bindArgs);
|
||||
}else{
|
||||
this.backlog.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
this.startup = function(handshakeData){
|
||||
if(this.connected){ return; }
|
||||
this.tunnelInit();
|
||||
}
|
||||
}
|
||||
|
||||
cometd.connectionTypes.register("mime-message-block", cometd.mimeReplaceTransport.check, cometd.mimeReplaceTransport);
|
||||
cometd.connectionTypes.register("long-polling", cometd.longPollTransport.check, cometd.longPollTransport);
|
||||
cometd.connectionTypes.register("callback-polling", cometd.callbackPollTransport.check, cometd.callbackPollTransport);
|
||||
cometd.connectionTypes.register("iframe", cometd.iframeTransport.check, cometd.iframeTransport);
|
||||
|
||||
// FIXME: need to implement fallback-polling, IE XML block
|
||||
|
||||
dojo.io.cometd = cometd;
|
Reference in New Issue
Block a user