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
|
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Bounce!</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<p id="test-config"></p>
<script>
const SET_STATE_HANDLERS = {
"cookie-client": setCookie,
"localStorage": setLocalStorage,
"indexedDB": setIndexedDB,
};
function setCookie(id) {
let cookie = document.cookie;
if (cookie) {
console.info("Received cookie", cookie);
} else {
let newCookie = `id=${id}`;
console.info("Setting new cookie", newCookie);
document.cookie = newCookie;
}
}
function setLocalStorage(id) {
let entry = localStorage.getItem("id");
if (entry) {
console.info("Found localStorage entry. id", entry);
} else {
console.info("Setting new localStorage entry. id", id);
localStorage.setItem(id, id);
}
}
function setIndexedDB() {
return new Promise((resolve, reject) => {
let request = window.indexedDB.open("bounce", 1);
request.onsuccess = () => {
console.info("Opened indexedDB");
resolve()
};
request.onerror = (event) => {
console.error("Error opening indexedDB", event);
reject();
};
request.onupgradeneeded = (event) => {
console.info("Initializing indexedDB");
let db = event.target.result;
db.createObjectStore("bounce");
};
});
}
function setIndexedDBInWorker(nested = false) {
let worker = new Worker("file_web_worker.js");
let msg = nested ? "setIndexedDBNested" : "setIndexedDB";
worker.postMessage(msg);
return new Promise((resolve, reject) => {
worker.onmessage = () => {
console.info("IndexedDB set in worker");
resolve();
};
worker.onerror = (event) => {
console.error("Error setting indexedDB in worker", event);
reject();
};
});
}
/**
* Set a state in a child frame.
*/
function setStateInFrame() {
// Embed self
let iframe = document.createElement("iframe");
let src = new URL(location.href);
// Remove search params we don't need for the iframe.
src.searchParams.delete("target");
src.searchParams.delete("redirectDelay");
src.searchParams.delete("setStateSameSiteFrame");
iframe.src = src.href;
let frameReadyPromise = new Promise((resolve) => {
iframe.addEventListener("load", () => {
iframe.contentWindow.readyPromise.then(resolve);
});
});
document.body.appendChild(iframe);
return frameReadyPromise;
}
// Wrap the entire block so we can run async code. Store the result in a
// promise so that parent windows can wait for us to be ready.
window.readyPromise = (async () => {
let url = new URL(location.href);
// Display the test config in the body.
document.getElementById("test-config").innerText = JSON.stringify(Object.fromEntries(url.searchParams), null, 2);
if (url.searchParams.get("setStateSameSiteFrame") === "true") {
// Set state in a child frame.
await setStateInFrame(url);
} else if(url.searchParams.get("setStateInWebWorker") === "true") {
// Set state in a worker.
await setIndexedDBInWorker();
} else if(url.searchParams.get("setStateInNestedWebWorker") === "true") {
// Set state in a nested worker.
await setIndexedDBInWorker(true);
} else {
// Set a state in this window.
let setState = url.searchParams.get("setState");
if (setState) {
let id = Math.random().toString();
let handler = SET_STATE_HANDLERS[setState];
if (!handler) {
throw new Error("Unknown state handler: " + setState);
}
await handler(id);
}
}
// Redirect to the target URL after a delay.
// If no target is specified, do nothing.
let redirectDelay = url.searchParams.get("redirectDelay");
if (redirectDelay != null) {
redirectDelay = Number.parseInt(redirectDelay);
} else {
redirectDelay = 50;
}
let target = url.searchParams.get("target");
if (target) {
console.info("Redirecting to", target);
setTimeout(() => {
location.href = target;
}, redirectDelay);
}
})();
</script>
</body>
</html>
|