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