Skip to content

Commit 08777c0

Browse files
committed
fix window size on oauth plugin.
1 parent cf5472a commit 08777c0

1 file changed

Lines changed: 311 additions & 2 deletions

File tree

src/plugins/oauth.js

Lines changed: 311 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ Hook.Plugin.OAuth.prototype.popup = function(provider, options) {
1212
var self = this,
1313
href = this.client.url + "oauth/" + provider + "?X-App-Id=" + this.client.app_id + "&X-App-Key=" + this.client.key,
1414
href_relay = this.client.url + "oauth/relay_frame" + "?X-App-Id=" + this.client.app_id + "&X-App-Key=" + this.client.key,
15-
deferred = when.defer();
15+
deferred = when.defer(),
16+
window_width = 500,
17+
window_height = 500,
18+
window_left = (screen.width/2) - (window_width/2),
19+
window_top = (screen.height/2) - (window_height/2);
1620

1721
href += "&" + this.client.serialize({options: options});
1822

@@ -24,7 +28,7 @@ Hook.Plugin.OAuth.prototype.popup = function(provider, options) {
2428
WinChan.open({
2529
url: href,
2630
relay_url: href_relay,
27-
window_features: "menubar=0,location=0,resizable=0,scrollbars=0,status=0,dialog=1,width=700,height=375",
31+
window_features: "menubar=0,location=0,resizable=0,scrollbars=0,status=0,dialog=1,width="+window_width+",height="+window_height+",top="+window_top+",left=" + window_left
2832
}, function(err, r) {
2933
// err is a string on failure, otherwise r is the response object
3034

@@ -42,8 +46,313 @@ Hook.Plugin.OAuth.prototype.popup = function(provider, options) {
4246
});
4347
}
4448

49+
4550
return deferred.promise;
4651
};
4752

4853
// Register plugin
4954
Hook.Plugin.Manager.register('oauth', Hook.Plugin.OAuth);
55+
56+
57+
/*
58+
*
59+
* winchan
60+
* https://github.com/mozilla/winchan
61+
*
62+
*/
63+
64+
;WinChan = (function() {
65+
var RELAY_FRAME_NAME = "__winchan_relay_frame";
66+
var CLOSE_CMD = "die";
67+
68+
// a portable addListener implementation
69+
function addListener(w, event, cb) {
70+
if(w.attachEvent) w.attachEvent('on' + event, cb);
71+
else if (w.addEventListener) w.addEventListener(event, cb, false);
72+
}
73+
74+
// a portable removeListener implementation
75+
function removeListener(w, event, cb) {
76+
if(w.detachEvent) w.detachEvent('on' + event, cb);
77+
else if (w.removeEventListener) w.removeEventListener(event, cb, false);
78+
}
79+
80+
81+
// checking for IE8 or above
82+
function isInternetExplorer() {
83+
var rv = -1; // Return value assumes failure.
84+
var ua = navigator.userAgent;
85+
if (navigator.appName === 'Microsoft Internet Explorer') {
86+
var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
87+
if (re.exec(ua) != null)
88+
rv = parseFloat(RegExp.$1);
89+
}
90+
// IE > 11
91+
else if (ua.indexOf("Trident") > -1) {
92+
var re = new RegExp("rv:([0-9]{2,2}[\.0-9]{0,})");
93+
if (re.exec(ua) !== null) {
94+
rv = parseFloat(RegExp.$1);
95+
}
96+
}
97+
98+
return rv >= 8;
99+
}
100+
101+
// checking Mobile Firefox (Fennec)
102+
function isFennec() {
103+
try {
104+
// We must check for both XUL and Java versions of Fennec. Both have
105+
// distinct UA strings.
106+
var userAgent = navigator.userAgent;
107+
return (userAgent.indexOf('Fennec/') != -1) || // XUL
108+
(userAgent.indexOf('Firefox/') != -1 && userAgent.indexOf('Android') != -1); // Java
109+
} catch(e) {}
110+
return false;
111+
}
112+
113+
// feature checking to see if this platform is supported at all
114+
function isSupported() {
115+
return (window.JSON && window.JSON.stringify &&
116+
window.JSON.parse && window.postMessage);
117+
}
118+
119+
// given a URL, extract the origin
120+
function extractOrigin(url) {
121+
if (!/^https?:\/\//.test(url)) url = window.location.href;
122+
var a = document.createElement('a');
123+
a.href = url;
124+
return a.protocol + "//" + a.host;
125+
}
126+
127+
// find the relay iframe in the opener
128+
function findRelay() {
129+
var loc = window.location;
130+
var frames = window.opener.frames;
131+
for (var i = frames.length - 1; i >= 0; i--) {
132+
try {
133+
if (frames[i].location.protocol === window.location.protocol &&
134+
frames[i].location.host === window.location.host &&
135+
frames[i].name === RELAY_FRAME_NAME)
136+
{
137+
return frames[i];
138+
}
139+
} catch(e) { }
140+
}
141+
return;
142+
}
143+
144+
var isIE = isInternetExplorer();
145+
146+
if (isSupported()) {
147+
/* General flow:
148+
* 0. user clicks
149+
* (IE SPECIFIC) 1. caller adds relay iframe (served from trusted domain) to DOM
150+
* 2. caller opens window (with content from trusted domain)
151+
* 3. window on opening adds a listener to 'message'
152+
* (IE SPECIFIC) 4. window on opening finds iframe
153+
* 5. window checks if iframe is "loaded" - has a 'doPost' function yet
154+
* (IE SPECIFIC5) 5a. if iframe.doPost exists, window uses it to send ready event to caller
155+
* (IE SPECIFIC5) 5b. if iframe.doPost doesn't exist, window waits for frame ready
156+
* (IE SPECIFIC5) 5bi. once ready, window calls iframe.doPost to send ready event
157+
* 6. caller upon reciept of 'ready', sends args
158+
*/
159+
return {
160+
open: function(opts, cb) {
161+
if (!cb) throw "missing required callback argument";
162+
163+
// test required options
164+
var err;
165+
if (!opts.url) err = "missing required 'url' parameter";
166+
if (!opts.relay_url) err = "missing required 'relay_url' parameter";
167+
if (err) setTimeout(function() { cb(err); }, 0);
168+
169+
// supply default options
170+
if (!opts.window_name) opts.window_name = null;
171+
if (!opts.window_features || isFennec()) opts.window_features = undefined;
172+
173+
// opts.params may be undefined
174+
175+
var iframe;
176+
177+
// sanity check, are url and relay_url the same origin?
178+
var origin = extractOrigin(opts.url);
179+
if (origin !== extractOrigin(opts.relay_url)) {
180+
return setTimeout(function() {
181+
cb('invalid arguments: origin of url and relay_url must match');
182+
}, 0);
183+
}
184+
185+
var messageTarget;
186+
187+
if (isIE) {
188+
// first we need to add a "relay" iframe to the document that's served
189+
// from the target domain. We can postmessage into a iframe, but not a
190+
// window
191+
iframe = document.createElement("iframe");
192+
// iframe.setAttribute('name', framename);
193+
iframe.setAttribute('src', opts.relay_url);
194+
iframe.style.display = "none";
195+
iframe.setAttribute('name', RELAY_FRAME_NAME);
196+
document.body.appendChild(iframe);
197+
messageTarget = iframe.contentWindow;
198+
}
199+
200+
var w = window.open(opts.url, opts.window_name, opts.window_features);
201+
202+
if (!messageTarget) messageTarget = w;
203+
204+
// lets listen in case the window blows up before telling us
205+
var closeInterval = setInterval(function() {
206+
if (w && w.closed) {
207+
cleanup();
208+
if (cb) {
209+
cb('unknown closed window');
210+
cb = null;
211+
}
212+
}
213+
}, 500);
214+
215+
var req = JSON.stringify({a: 'request', d: opts.params});
216+
217+
// cleanup on unload
218+
function cleanup() {
219+
if (iframe) document.body.removeChild(iframe);
220+
iframe = undefined;
221+
if (closeInterval) closeInterval = clearInterval(closeInterval);
222+
removeListener(window, 'message', onMessage);
223+
removeListener(window, 'unload', cleanup);
224+
if (w) {
225+
try {
226+
w.close();
227+
} catch (securityViolation) {
228+
// This happens in Opera 12 sometimes
229+
// see https://github.com/mozilla/browserid/issues/1844
230+
messageTarget.postMessage(CLOSE_CMD, origin);
231+
}
232+
}
233+
w = messageTarget = undefined;
234+
}
235+
236+
addListener(window, 'unload', cleanup);
237+
238+
function onMessage(e) {
239+
if (e.origin !== origin) { return; }
240+
try {
241+
var d = JSON.parse(e.data);
242+
if (d.a === 'ready') messageTarget.postMessage(req, origin);
243+
else if (d.a === 'error') {
244+
cleanup();
245+
if (cb) {
246+
cb(d.d);
247+
cb = null;
248+
}
249+
} else if (d.a === 'response') {
250+
cleanup();
251+
if (cb) {
252+
cb(null, d.d);
253+
cb = null;
254+
}
255+
}
256+
} catch(err) { }
257+
}
258+
259+
addListener(window, 'message', onMessage);
260+
261+
return {
262+
close: cleanup,
263+
focus: function() {
264+
if (w) {
265+
try {
266+
w.focus();
267+
} catch (e) {
268+
// IE7 blows up here, do nothing
269+
}
270+
}
271+
}
272+
};
273+
},
274+
onOpen: function(cb) {
275+
var o = "*";
276+
var msgTarget = isIE ? findRelay() : window.opener;
277+
if (!msgTarget) throw "can't find relay frame";
278+
function doPost(msg) {
279+
msg = JSON.stringify(msg);
280+
if (isIE) msgTarget.doPost(msg, o);
281+
else msgTarget.postMessage(msg, o);
282+
}
283+
284+
function onMessage(e) {
285+
// only one message gets through, but let's make sure it's actually
286+
// the message we're looking for (other code may be using
287+
// postmessage) - we do this by ensuring the payload can
288+
// be parsed, and it's got an 'a' (action) value of 'request'.
289+
var d;
290+
try {
291+
d = JSON.parse(e.data);
292+
} catch(err) { }
293+
if (!d || d.a !== 'request') return;
294+
removeListener(window, 'message', onMessage);
295+
o = e.origin;
296+
if (cb) {
297+
// this setTimeout is critically important for IE8 -
298+
// in ie8 sometimes addListener for 'message' can synchronously
299+
// cause your callback to be invoked. awesome.
300+
setTimeout(function() {
301+
cb(o, d.d, function(r) {
302+
cb = undefined;
303+
doPost({a: 'response', d: r});
304+
});
305+
}, 0);
306+
}
307+
}
308+
309+
function onDie(e) {
310+
if (e.data === CLOSE_CMD) {
311+
try { window.close(); } catch (o_O) {}
312+
}
313+
}
314+
addListener(isIE ? msgTarget : window, 'message', onMessage);
315+
addListener(isIE ? msgTarget : window, 'message', onDie);
316+
317+
// we cannot post to our parent that we're ready before the iframe
318+
// is loaded. (IE specific possible failure)
319+
try {
320+
doPost({a: "ready"});
321+
} catch(e) {
322+
// this code should never be exectued outside IE
323+
addListener(msgTarget, 'load', function(e) {
324+
doPost({a: "ready"});
325+
});
326+
}
327+
328+
// if window is unloaded and the client hasn't called cb, it's an error
329+
var onUnload = function() {
330+
try {
331+
// IE8 doesn't like this...
332+
removeListener(isIE ? msgTarget : window, 'message', onDie);
333+
} catch (ohWell) { }
334+
if (cb) doPost({ a: 'error', d: 'client closed window' });
335+
cb = undefined;
336+
// explicitly close the window, in case the client is trying to reload or nav
337+
try { window.close(); } catch (e) { }
338+
};
339+
addListener(window, 'unload', onUnload);
340+
return {
341+
detach: function() {
342+
removeListener(window, 'unload', onUnload);
343+
}
344+
};
345+
}
346+
};
347+
} else {
348+
return {
349+
open: function(url, winopts, arg, cb) {
350+
setTimeout(function() { cb("unsupported browser"); }, 0);
351+
},
352+
onOpen: function(cb) {
353+
setTimeout(function() { cb("unsupported browser"); }, 0);
354+
}
355+
};
356+
}
357+
})();
358+

0 commit comments

Comments
 (0)