-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsandbox.html
More file actions
50 lines (48 loc) · 2.19 KB
/
Copy pathsandbox.html
File metadata and controls
50 lines (48 loc) · 2.19 KB
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
<!doctype html>
<meta charset="utf-8">
<title>XRPL Academy code sandbox</title>
<script>
// XRPL Academy code-sandbox shell — protocol v1.
//
// Served from a SEPARATE origin so the academy app can give this frame
// `allow-scripts allow-same-origin` safely: a real origin makes CDN scripts,
// import maps and dynamic import() work, while remaining unable to touch the
// app's cookies, storage or APIs (different origin).
//
// Protocol (all via postMessage):
// parent -> shell : { type: 'run', html: '<full program document>' }
// shell -> parent: { type: '__sandbox_ready__' } once, on load
// inner -> shell -> parent: every message from the program frame is relayed
// verbatim (console bridge, __cr_done__, errors).
//
// Hardening: the parent's origin is pinned from the first accepted 'run'
// message; relays go only to that origin, and only messages from the CURRENT
// program frame are relayed (not popups or stale frames).
//
// This file is mirrored from the academy app repo (public/sandbox.html).
// It must stay backward-compatible: never require a new field of an old app.
let parentOrigin = null
let inner = null
window.addEventListener('message', (event) => {
const { data, source, origin } = event
if (source === parent) {
if (!data || data.type !== 'run' || typeof data.html !== 'string') return
if (parentOrigin === null) parentOrigin = origin
if (origin !== parentOrigin) return
const url = URL.createObjectURL(new Blob([data.html], { type: 'text/html' }))
const f = document.getElementById('r') || document.createElement('iframe')
f.id = 'r'
f.style.cssText = 'position:absolute;inset:0;width:100%;height:100%;border:none'
f.src = url
if (!f.parentNode) document.body.appendChild(f)
inner = f.contentWindow
return
}
// Relay ONLY the current program frame, ONLY to the pinned parent.
if (parentOrigin === null || inner === null || source !== inner) return
parent.postMessage(data, parentOrigin)
})
// Ready handshake: parent origin is not yet known, so this one goes to '*'.
// It carries no data, and the app ignores ready messages from other origins.
parent.postMessage({ type: '__sandbox_ready__' }, '*')
</script>