root / dojox / trunk / io / windowName.js

Revision 18120, 8.0 kB (checked in by kzyp, 15 months ago)

And refer to properties correctly (shouldn't have copy and pasted from some of the uglier dojo code out there)

  • Property svn:eol-style set to native
Line 
1dojo.provide("dojox.io.windowName");
2// Implements the window.name transport 
3
4dojox.io.windowName = {
5        send: function(/*String*/ method, /*dojo.__IoArgs*/ args){
6                // summary:
7                //              Provides secure cross-domain request capability.
8                //              Sends a request using an iframe (POST or GET) and reads the response through the
9                //              frame's window.name.
10                //
11                //      method:
12                //              The method to use to send the request, GET or POST
13                //
14                //      args:
15                //              See dojo.xhr
16                //
17                //      args.authElement: DOMNode?
18                //              By providing an authElement, this indicates that windowName should use the
19                //              authorized window.name protocol, relying on
20                //              the loaded XD resource to return to the provided return URL on completion
21                //              of authorization/authentication. The provided authElement will be used to place
22                //              the iframe in, so the user can interact with the server resource for authentication
23                //              and/or authorization to access the resource.
24                //
25                //      args.onAuthLoad: Function?
26                //              When using authorized access to resources, this function will be called when the
27                //              authorization page has been loaded. (When authorization is actually completed,
28                //              the deferred callback function is called with the result). The primary use for this
29                //              is to make the authElement visible to the user once the resource has loaded
30                //              (this can be preferable to showing the iframe while the resource is loading
31                //              since it may not require authorization, it may simply return the resource).
32                // 
33                //      description:
34                //              In order to provide a windowname transport accessible resources/web services, a server
35                //              should check for the presence of a parameter window.name=true and if a request includes
36                //              such a parameter, it should respond to the request with an HTML
37                //              document that sets it's window.name to the string that is to be
38                //              delivered to the client. For example, if a client makes a window.name request like:
39                //      |       http://othersite.com/greeting?windowname=true
40                //              And server wants to respond to the client with "Hello", it should return an html page:
41                // |    <html><script type="text/javascript">
42                // |    window.name="Hello";
43                // |    </script></html>
44                //              One can provide XML or JSON data by simply quoting the data as a string, and parsing the data
45                //              on the client.
46                //              If you use the authorization window.name protocol, the requester should include an
47                //              authElement element in the args, and a request will be created like:
48                //      |       http://othersite.com/greeting?windowname=auth
49                //              And the server can respond like this:
50                // |    <html><script type="text/javascript">
51                // |    var loc = window.name;
52                // |    authorizationButton.onclick = function(){       
53                // |            window.name="Hello";
54                // |            location = loc;
55                // |    };
56                // |    </script></html>
57                //              When using windowName from a XD Dojo build, make sure to set the
58                //              dojo.dojoBlankHtmlUrl property to a local URL.
59                args.url += (args.url.match(/\?/) ? '&' : '?') + "windowname=" + (args.authElement ? "auth" : true); // indicate our desire for window.name communication
60                var authElement = args.authElement;
61                var cleanup = function(result){
62                        try{
63                                // we have to do this to stop the wait cursor in FF
64                                var innerDoc = dfd.ioArgs.frame.contentWindow.document;
65                                innerDoc.write(" ");
66                                innerDoc.close();
67                        }catch(e){}
68                        (authElement || dojo.body()).removeChild(dfd.ioArgs.outerFrame); // clean up
69                        return result;
70                }
71                var dfd = dojo._ioSetArgs(args,cleanup,cleanup,cleanup);
72                if(args.timeout){
73                        setTimeout(function(){
74                                        if(dfd.fired == -1){
75                                                dfd.callback(new Error("Timeout"));
76                                        }
77                                },
78                                args.timeout
79                        );
80                }
81                var self = dojox.io.windowName;
82                if(dojo.body()){
83                        // the DOM is ready
84                        self._send(dfd, method, authElement, args.onAuthLoad);
85                }else{
86                        // we will wait for the DOM to be ready to proceed
87                        dojo.addOnLoad(function(){
88                                self._send(dfd, method, authElement, args.onAuthLoad);
89                        });
90                }
91                return dfd;
92        },
93        _send: function(dfd, method, authTarget, onAuthLoad){
94
95                var ioArgs = dfd.ioArgs;
96                var frameNum = dojox.io.windowName._frameNum++;
97                var sameDomainUrl = (dojo.config.dojoBlankHtmlUrl||dojo.config.dojoCallbackUrl||dojo.moduleUrl("dojo", "resources/blank.html")) + "#" + frameNum;
98                var frameName = new dojo._Url(window.location, sameDomainUrl);
99                var doc = dojo.doc;
100                var frameContainer = authTarget || dojo.body();
101                function styleFrame(frame){
102                        frame.style.width="100%";
103                        frame.style.height="100%";
104                        frame.style.border="0px";
105                }
106                if(dojo.isMoz && ![].reduce){
107                        // FF2 allows unsafe sibling frame modification,
108                        // the fix for this is to create nested frames with getters and setters to protect access
109                        var outerFrame = doc.createElement("iframe");
110                        styleFrame(outerFrame);
111                        if(!authTarget){
112                                outerFrame.style.display='none';
113                        }
114                        frameContainer.appendChild(outerFrame);
115                       
116                        var firstWindow = outerFrame.contentWindow;
117                        doc = firstWindow.document;
118                        doc.write("<html><body margin='0px'><iframe style='width:100%;height:100%;border:0px' name='protectedFrame'></iframe></body></html>");
119                        doc.close();
120                        var secondWindow = firstWindow[0]; 
121                        firstWindow.__defineGetter__(0,function(){});
122                        firstWindow.__defineGetter__("protectedFrame",function(){});
123                        doc = secondWindow.document;
124                        doc.write("<html><body margin='0px'></body></html>");
125                        doc.close();
126                        frameContainer = doc.body;
127                }
128
129                var frame = ioArgs.frame = frame = doc.createElement(dojo.isIE ? '<iframe name="' + frameName + '" onload="dojox.io.windowName['+frameNum+']()">' : 'iframe');
130                styleFrame(frame);
131                ioArgs.outerFrame = outerFrame = outerFrame || frame;
132                if(!authTarget){
133                        outerFrame.style.display='none';
134                }
135                var state = 0;
136                function getData(){
137                        var data = frame.contentWindow.name;
138                        if(typeof data == 'string'){
139                                if(data != frameName){
140                                        state = 2; // we are done now
141                                        dfd.ioArgs.hash = frame.contentWindow.location.hash;
142                                        dfd.callback(data);
143                                }
144                        }
145                }
146                dojox.io.windowName[frameNum] = frame.onload = function(){
147                        try{
148                                if(!dojo.isMoz && frame.contentWindow.location =='about:blank'){
149                                        // opera and safari will do an onload for about:blank first, we can ignore this first onload
150                                        return;
151                                }
152                        }catch(e){
153                                // if we are in the target domain, frame.contentWindow.location will throw an ignorable error
154                        }
155                        if(!state){
156                                // we have loaded the target resource, now time to navigate back to our domain so we can read the frame name
157                                state=1;
158                                if(authTarget){
159                                        // call the callback so it can make it visible
160                                        if(onAuthLoad){
161                                                onAuthLoad();
162                                        }
163                                }else{
164                                        // we are doing a synchronous capture, go directly to our same domain URL and retrieve the resource
165                                        frame.contentWindow.location = sameDomainUrl;
166                                }
167                        }
168                        // back to our domain, we should be able to access the frame name now
169                        try{
170                                if(state<2){
171                                        getData();
172                                }
173                        }
174                        catch(e){
175                        }
176                       
177                };
178                frame.name = frameName;
179                if(method.match(/GET/i)){
180                        // if it is a GET we can just the iframe our src url
181                        dojo._ioAddQueryToUrl(ioArgs);
182                        frame.src = ioArgs.url;
183                        frameContainer.appendChild(frame);
184                        if(frame.contentWindow){
185                                frame.contentWindow.location.replace(ioArgs.url);
186                        }
187                }else if(method.match(/POST/i)){
188                        // if it is a POST we will build a form to post it
189                        frameContainer.appendChild(frame);
190                        var form = dojo.doc.createElement("form");
191                        dojo.body().appendChild(form);
192                        var query = dojo.queryToObject(ioArgs.query);
193                        for(var i in query){
194                                var values = query[i];
195                                values = values instanceof Array ? values : [values];
196                                for(var j = 0; j < values.length; j++){
197                                        // create hidden inputs for all the parameters
198                                        var input = doc.createElement("input");
199                                        input.type = 'hidden';
200                                        input.name = i;
201                                        input.value = values[j];
202                                        form.appendChild(input);
203                                }
204                        }
205                        form.method = 'POST';
206                        form.action = ioArgs.url;
207                        form.target = frameName;// connect the form to the iframe
208                       
209                        form.submit();
210                        form.parentNode.removeChild(form);
211                }else{
212                        throw new Error("Method " + method + " not supported with the windowName transport");
213                }
214                if(frame.contentWindow){
215                        frame.contentWindow.name = frameName; // IE likes it afterwards
216                }
217        },
218        _frameNum: 0 
219       
220}
Note: See TracBrowser for help on using the browser.