source: Dev/trunk/src/client/dojox/xmpp/bosh.js @ 532

Last change on this file since 532 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

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:
119                //              removes the script element with the given id, from the given frameDocument.
120                //              If no frameDocument is passed, the current document is used.
121                dojo.destroy(dojo.byId(id, frameDocument));
122
123                //Remove the BOSH callback on dojox.xmpp.bosh, if it exists.
124                if(this[id]){
125                        delete this[id];
126                }
127        },
128
129        _makeScriptDeferred: function(/*Object*/args){
130                // summary:
131                //              sets up a Deferred object for an IO request.
132                var dfd = dojo._ioSetArgs(args, this._deferredCancel, this._deferredOk, this._deferredError);
133
134                var ioArgs = dfd.ioArgs;
135
136                ioArgs.id = 'rid' + args.rid;
137                ioArgs.rid = args.rid;
138                ioArgs.canDelete = true;
139                ioArgs.frameDoc = args.frameDoc;
140
141                this[ioArgs.id] = dfd;
142
143                return dfd; // dojo.Deferred
144        },
145
146        _deferredCancel: function(/*Deferred*/dfd){
147                // summary:
148                //              canceller function for dojo._ioSetArgs call.
149
150                //DO NOT use "this" and expect it to be dojox.xmpp.bosh.
151                dfd.canceled = true;
152                if(dfd.ioArgs.canDelete){
153                        dojox.xmpp.bosh._addDeadScript(dfd.ioArgs);
154                }
155        },
156
157        _deferredOk: function(/*Deferred*/dfd){
158                // summary:
159                //              okHandler function for dojo._ioSetArgs call.
160
161                //DO NOT use "this" and expect it to be dojo.xmpp.bosh.
162                var ioArgs = dfd.ioArgs;
163
164                //Add script to list of things that can be removed.
165                if(ioArgs.canDelete){
166                        dojox.xmpp.bosh._addDeadScript(ioArgs);
167                }
168
169                //Favor JSONP responses, script load events then lastly ioArgs.
170                //The ioArgs are goofy, but cannot return the dfd since that stops
171                //the callback chain in Deferred. The return value is not that important
172                //in that case, probably a checkString case.
173                return ioArgs.xmppMessage || ioArgs;
174        },
175
176        _deferredError: function(/*Error*/error, /*Deferred*/dfd){
177                // summary:
178                //              errHandler function for dojo._ioSetArgs call.
179
180                if(dfd.ioArgs.canDelete){
181                        //DO NOT use "this" and expect it to be dojox.xmpp.bosh
182                        if(error.dojoType == "timeout"){
183                                //For timeouts, remove the script element immediately to
184                                //avoid a response from it coming back later and causing trouble.
185                                dojox.xmpp.bosh.remove(dfd.ioArgs.id, dfd.ioArgs.frameDoc);
186                        }else{
187                                dojox.xmpp.bosh._addDeadScript(dfd.ioArgs);
188                        }
189                }
190                return error;
191        },
192
193        _deadScripts: [],
194        _addDeadScript: function(/*Object*/ioArgs){
195                // summary:
196                //              sets up an entry in the deadScripts array.
197                dojox.xmpp.bosh._deadScripts.push({id: ioArgs.id, frameDoc: ioArgs.frameDoc});
198                //Being extra paranoid about leaks:
199                ioArgs.frameDoc = null;
200        },
201
202        _validCheck: function(/*Deferred*/dfd){
203                // summary:
204                //              inflight check function to see if dfd is still valid.
205
206                //Do script cleanup here. We wait for one inflight pass
207                //to make sure we don't get any weird things by trying to remove a script
208                //tag that is part of the call chain (IE 6 has been known to
209                //crash in that case).
210                var _self = dojox.xmpp.bosh;
211                var deadScripts = _self._deadScripts;
212                if(deadScripts && deadScripts.length > 0){
213                        for(var i = 0; i < deadScripts.length; i++){
214                                //Remove the script tag
215                                _self.remove(deadScripts[i].id, deadScripts[i].frameDoc);
216                                deadScripts[i].frameDoc = null;
217                        }
218                        dojox.xmpp.bosh._deadScripts = [];
219                }
220
221                return true;
222        },
223
224        _ioCheck: function(/*Deferred*/dfd){
225                // summary:
226                //              inflight check function to see if IO finished.
227                var ioArgs = dfd.ioArgs;
228                //Check for returned message
229                if(ioArgs.xmppMessage){
230                        return true;
231                }
232                return false;
233        },
234
235        _resHandle: function(/*Deferred*/dfd){
236                // summary:
237                //              inflight function to handle a completed response.
238                if(dojox.xmpp.bosh._ioCheck(dfd)){
239                        dfd.callback(dfd);
240                }else{
241                        //This path should never happen since the only way we can get
242                        //to _resHandle is if _ioCheck is true.
243                        dfd.errback(new Error("inconceivable dojox.xmpp.bosh._resHandle error"));
244                }
245        }
246};
Note: See TracBrowser for help on using the repository browser.