source: Dev/branches/rest-dojo-ui/client/dojox/xmpp/bosh.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 6.9 KB
Line 
1dojo.provide("dojox.xmpp.bosh");
2
3dojo.require("dojo.io.script");
4dojo.require("dojo.io.iframe");
5dojo.require("dojox.xml.parser");
6
7/*=====
8dojo.declare("dojox.xmpp.bosh.__initArgs", null, {
9        constructor: function(){
10                //      summary:
11                //              The arguments passed to dojox.xmpp.bosh.initialize
12                //      iframes:
13                //              The number of iframes to use for transmission
14                //      load:
15                //              The function called when the first iframe is
16                //              loaded.  Generally used to signal when to send
17                //              login information
18                this.iframes = iframes;
19                this.load = load;
20        }
21});
22dojo.declare("dojox.xmpp.bosh.__ioArgs", dojo.__IoArgs, {
23        constructor: function(){
24                //      summary:
25                //              All the properties described in the dojo.__ioArgs type, apply to this
26                //              type as well, EXCEPT "handleAs". It is not applicable to
27                //              dojox.xmpp.bosh.get() calls, since it is implied that the
28                //              return will be a string of XML.
29                //      rid:
30                //              The rid of the message being sent.
31                this.rid = rid;
32        }
33});
34=====*/
35
36dojox.xmpp.bosh = {
37        transportIframes: [],
38        initialize: function(/*dojox.xmpp.bosh.__initArgs*/ args){
39                this.transportIframes = [];
40
41                var scopedObj = dojox._scopeName + '.xmpp.bosh';
42
43                var c = dojo.connect(dojo.getObject(scopedObj), '_iframeOnload', this, function(index){
44                        if(index==0){
45                                args.load();
46                                dojo.disconnect(c);
47                        }
48                });
49
50                for(var i = 0; i < args.iframes; i++){
51                        var fname = 'xmpp-transport-'+i;
52                        var iframe = dojo.byId('xmpp-transport-'+i);
53                        if(iframe){
54                                // we have to clean up the dojo.io.iframe references
55                                if(window[fname]){ window[fname] = null; }
56                                if(window.frames[fname]){ window.frames[fname] = null; }
57                                dojo.destroy(iframe);
58                        }
59                        iframe = dojo.io.iframe.create("xmpp-transport-" + i, scopedObj + "._iframeOnload("+i+");" );
60                        this.transportIframes.push(iframe);
61                }
62        },
63
64        _iframeOnload: function(index){
65                var doc = dojo.io.iframe.doc(dojo.byId("xmpp-transport-" + index));
66                doc.write("<script>var isLoaded=true; var rid=0; var transmiting=false; function _BOSH_(msg) { transmiting=false; parent.dojox.xmpp.bosh.handle(msg, rid); } </script>");
67        },
68
69        findOpenIframe: function() {
70                for(var i = 0; i < this.transportIframes.length; i++) {
71                        var iframe = this.transportIframes[i];
72                        var win = iframe.contentWindow;
73                        //console.log("Open transport?", win, win.isLoaded, win.transmiting);
74                       
75                        if(win.isLoaded && !win.transmiting) {
76                                return iframe;
77                        }
78                }
79                return false;
80        },
81
82        handle: function(msg, rid){
83                var dfd = this['rid'+rid];
84
85                var xmlMsg = dojox.xml.parser.parse(msg, 'text/xml');
86
87                if(xmlMsg){
88                        dfd.ioArgs.xmppMessage = xmlMsg;
89                }else{
90                        dfd.errback(new Error("Recieved bad document from server: " + msg));
91                }
92        },
93
94        get: function(/*dojox.xmpp.bosh.__ioArgs*/args){
95                //      summary:
96                //              sends a get request using a dynamically created script tag.
97                var iframe = this.findOpenIframe();
98                var iframeDoc = dojo.io.iframe.doc(iframe);
99
100                args.frameDoc = iframeDoc;
101
102                var dfd = this._makeScriptDeferred(args);
103                var ioArgs = dfd.ioArgs;
104
105                iframe.contentWindow.rid=ioArgs.rid;
106                iframe.contentWindow.transmiting=true;
107
108                dojo._ioAddQueryToUrl(ioArgs);
109                dojo._ioNotifyStart(dfd);
110
111                dojo.io.script.attach(ioArgs.id, ioArgs.url, iframeDoc);
112
113                dojo._ioWatch(dfd, this._validCheck, this._ioCheck, this._resHandle);
114                return dfd;
115        },
116
117        remove: function(/*String*/id, /*Document?*/frameDocument){
118                //summary: removes the script element with the given id, from the given frameDocument.
119                //If no frameDocument is passed, the current document is used.
120                dojo.destroy(dojo.byId(id, frameDocument));
121
122                //Remove the BOSH callback on dojox.xmpp.bosh, if it exists.
123                if(this[id]){
124                        delete this[id];
125                }
126        },
127
128        _makeScriptDeferred: function(/*Object*/args){
129                //summary:
130                //              sets up a Deferred object for an IO request.
131                var dfd = dojo._ioSetArgs(args, this._deferredCancel, this._deferredOk, this._deferredError);
132
133                var ioArgs = dfd.ioArgs;
134
135                ioArgs.id = 'rid' + args.rid;
136                ioArgs.rid = args.rid;
137                ioArgs.canDelete = true;
138                ioArgs.frameDoc = args.frameDoc;
139
140                this[ioArgs.id] = dfd;
141
142                return dfd; // dojo.Deferred
143        },
144
145        _deferredCancel: function(/*Deferred*/dfd){
146                //summary: canceller function for dojo._ioSetArgs call.
147
148                //DO NOT use "this" and expect it to be dojox.xmpp.bosh.
149                dfd.canceled = true;
150                if(dfd.ioArgs.canDelete){
151                        dojox.xmpp.bosh._addDeadScript(dfd.ioArgs);
152                }
153        },
154
155        _deferredOk: function(/*Deferred*/dfd){
156                //summary: okHandler function for dojo._ioSetArgs call.
157
158                //DO NOT use "this" and expect it to be dojo.xmpp.bosh.
159                var ioArgs = dfd.ioArgs;
160
161                //Add script to list of things that can be removed.
162                if(ioArgs.canDelete){
163                        dojox.xmpp.bosh._addDeadScript(ioArgs);
164                }
165
166                //Favor JSONP responses, script load events then lastly ioArgs.
167                //The ioArgs are goofy, but cannot return the dfd since that stops
168                //the callback chain in Deferred. The return value is not that important
169                //in that case, probably a checkString case.
170                return ioArgs.xmppMessage || ioArgs;
171        },
172
173        _deferredError: function(/*Error*/error, /*Deferred*/dfd){
174                //summary: errHandler function for dojo._ioSetArgs call.
175
176                if(dfd.ioArgs.canDelete){
177                        //DO NOT use "this" and expect it to be dojox.xmpp.bosh
178                        if(error.dojoType == "timeout"){
179                                //For timeouts, remove the script element immediately to
180                                //avoid a response from it coming back later and causing trouble.
181                                dojox.xmpp.bosh.remove(dfd.ioArgs.id, dfd.ioArgs.frameDoc);
182                        }else{
183                                dojox.xmpp.bosh._addDeadScript(dfd.ioArgs);
184                        }
185                }
186                return error;
187        },
188
189        _deadScripts: [],
190        _addDeadScript: function(/*Object*/ioArgs){
191                //summary: sets up an entry in the deadScripts array.
192                dojox.xmpp.bosh._deadScripts.push({id: ioArgs.id, frameDoc: ioArgs.frameDoc});
193                //Being extra paranoid about leaks:
194                ioArgs.frameDoc = null;
195        },
196
197        _validCheck: function(/*Deferred*/dfd){
198                //summary: inflight check function to see if dfd is still valid.
199
200                //Do script cleanup here. We wait for one inflight pass
201                //to make sure we don't get any weird things by trying to remove a script
202                //tag that is part of the call chain (IE 6 has been known to
203                //crash in that case).
204                var _self = dojox.xmpp.bosh;
205                var deadScripts = _self._deadScripts;
206                if(deadScripts && deadScripts.length > 0){
207                        for(var i = 0; i < deadScripts.length; i++){
208                                //Remove the script tag
209                                _self.remove(deadScripts[i].id, deadScripts[i].frameDoc);
210                                deadScripts[i].frameDoc = null;
211                        }
212                        dojox.xmpp.bosh._deadScripts = [];
213                }
214
215                return true;
216        },
217
218        _ioCheck: function(/*Deferred*/dfd){
219                //summary: inflight check function to see if IO finished.
220                var ioArgs = dfd.ioArgs;
221                //Check for returned message
222                if(ioArgs.xmppMessage){
223                        return true;
224                }
225                return false;
226        },
227
228        _resHandle: function(/*Deferred*/dfd){
229                //summary: inflight function to handle a completed response.
230                if(dojox.xmpp.bosh._ioCheck(dfd)){
231                        dfd.callback(dfd);
232                }else{
233                        //This path should never happen since the only way we can get
234                        //to _resHandle is if _ioCheck is true.
235                        dfd.errback(new Error("inconceivable dojox.xmpp.bosh._resHandle error"));
236                }
237        }
238};
Note: See TracBrowser for help on using the repository browser.