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