@codingame/monaco-vscode-extensions-service-override
Version:
VSCode public API plugged on the monaco editor - extensions service-override
124 lines (111 loc) • 4.02 kB
HTML
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="
default-src 'none';
child-src 'self' data: blob:;
script-src 'self' 'unsafe-eval' 'sha256-OTnWt0xD0mDGlMgzQref1DqApnE9MipgFz2t0Q/3vcE=' https:;
connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*;"/>
</head>
<body>
<script>
(function() {
const searchParams = new URL(document.location.href).searchParams;
const vscodeWebWorkerExtHostId = searchParams.get('vscodeWebWorkerExtHostId') || '';
const name = searchParams.get('debugged') ? 'DebugWorkerExtensionHost' : 'WorkerExtensionHost';
const parentOrigin = searchParams.get('parentOrigin') || window.origin;
const salt = searchParams.get('salt');
const vscodeExtHostWorkerSrc = searchParams.get('vscodeExtHostWorkerSrc');
const vscodeExtHostWorkerOptions = JSON.parse(searchParams.get('vscodeExtHostWorkerOptions') ?? '{}');
(async function() {
const hostnameValidationMarker = 'v--';
const hostname = location.hostname;
if (!hostname.startsWith(hostnameValidationMarker)) {
// validation not requested
return start();
}
if (!crypto.subtle) {
// cannot validate, not running in a secure context
return sendError(new Error(`Cannot validate in current context!`));
}
// Here the `parentOriginHash()` function from `src/vs/workbench/common/webview.ts` is inlined
// compute a sha-256 composed of `parentOrigin` and `salt` converted to base 32
let parentOriginHash;
try {
const strData = JSON.stringify({ parentOrigin, salt });
const encoder = new TextEncoder();
const arrData = encoder.encode(strData);
const hash = await crypto.subtle.digest('sha-256', arrData);
const hashArray = Array.from(new Uint8Array(hash));
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
// sha256 has 256 bits, so we need at most ceil(lg(2^256-1)/lg(32)) = 52 chars to represent it in base 32
parentOriginHash = BigInt(`0x${hashHex}`).toString(32).padStart(52, '0');
} catch(err) {
return sendError(err instanceof Error ? err : new Error(String(err)));
}
const requiredSubdomain = `${hostnameValidationMarker}${parentOriginHash}.`;
if (hostname.substring(0, requiredSubdomain.length) === requiredSubdomain) {
// validation succeeded!
return start();
}
return sendError(new Error(`Expected '${requiredSubdomain}' as subdomain!`));
})();
function sendError(error) {
window.parent.postMessage({
vscodeWebWorkerExtHostId,
error: {
name: error ? error.name : '',
message: error ? error.message : '',
stack: error ? error.stack : []
}
}, '*');
}
function start() {
try {
let workerUrl = vscodeExtHostWorkerSrc
if(globalThis.crossOriginIsolated) {
workerUrl += '?vscode-coi=2'; // COEP
}
const worker = new Worker(workerUrl, Object.assign({ name }, vscodeExtHostWorkerOptions));
const nestedWorkers = new Map();
worker.onmessage = (event) => {
const { data } = event;
if (data?.type === '_newWorker') {
const { id, port, url, options } = data;
const newWorker = new Worker(url, options);
newWorker.postMessage(port, [port]);
worker.onerror = console.error.bind(console);
nestedWorkers.set(id, newWorker);
} else if (data?.type === '_terminateWorker') {
const { id } = data;
if(nestedWorkers.has(id)) {
nestedWorkers.get(id).terminate();
nestedWorkers.delete(id);
}
} else {
worker.onerror = console.error.bind(console);
window.parent.postMessage({
vscodeWebWorkerExtHostId,
data
}, parentOrigin, [data]);
}
};
worker.onerror = (event) => {
console.error(event.message, event.error);
sendError(event.error);
};
self.onmessage = (event) => {
if (event.origin !== parentOrigin) {
return;
}
worker.postMessage(event.data, event.ports);
}
} catch(err) {
console.error(err);
sendError(err);
}
}
})();
</script>
</body>
</html>