File size: 1,714 Bytes
bee6636
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { ScramjetClient } from "../client";
import { SCRAMJETCLIENT } from "../../symbols";
import { rewriteUrl } from "../../shared/rewriters/url";

export default function (client: ScramjetClient) {
	client.Proxy("window.open", {
		apply(ctx) {
			if (ctx.args[0]) ctx.args[0] = rewriteUrl(ctx.args[0], client.meta);

			if (ctx.args[1] === "_top" || ctx.args[1] === "_unfencedTop")
				ctx.args[1] = client.meta.topFrameName;
			if (ctx.args[1] === "_parent") ctx.args[1] = client.meta.parentFrameName;

			const realwin = ctx.call();

			if (!realwin) return ctx.return(realwin);

			if (SCRAMJETCLIENT in realwin) {
				return ctx.return(realwin[SCRAMJETCLIENT].globalProxy);
			} else {
				const newclient = new ScramjetClient(realwin);
				// hook the opened window
				newclient.hook();

				return ctx.return(newclient.globalProxy);
			}
		},
	});

	// opener will refer to the real window if it was opened by window.open
	client.Trap("opener", {
		get(ctx) {
			const realwin = ctx.get() as Window;

			if (realwin && SCRAMJETCLIENT in realwin) {
				return realwin[SCRAMJETCLIENT].globalProxy;
			} else {
				// the opener has to have been already hooked, so if we reach here then it's a real window
				return undefined;
			}
		},
	});

	client.Trap("window.frameElement", {
		get(ctx) {
			const f = ctx.get() as HTMLIFrameElement | null;
			if (!f) return f;

			const win = f.ownerDocument.defaultView;
			if (win[SCRAMJETCLIENT]) {
				// then this is a subframe in a scramjet context, and it's safe to pass back the real iframe
				return f;
			} else {
				// no, the top frame is outside the sandbox
				return null;
			}
		},
	});
}