Skip to content

Commit 736ca26

Browse files
feat(Sky): Add VS Code CDN and file scheme CSP permissions
Add Content Security Policy permissions required for VS Code extension host and webview functionality: 1. frame-src: Allow vscode-webview.net, *.vscode-cdn.net, *.vscode-webview.net for extension iframe loading 2. script-src/style-src/connect-src: Allow vscode-file: and vscode-file://vscode-app for local file access in extensions 3. connect-src: Allow blob: and ipc: for extension host communication Additionally, implement a Blob constructor patch in Workbench.ts that intercepts VS Code worker bootstrap blobs and injects the __name shim. This ensures extension host blob workers have access to esbuild's __name helper without requiring external fetches. These changes enable VS Code extensions to load properly from CDN sources and access local file resources.
1 parent 8e17e47 commit 736ca26

6 files changed

Lines changed: 115 additions & 19 deletions

File tree

Source/Workbench/Electron/Workbench.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ if (typeof window.requestIdleCallback !== "function") {
7777
return setTimeout(() => {
7878
Callback({
7979
didTimeout: Timeout <= 0,
80-
timeRemaining: () => Math.max(0, Timeout - (Date.now() - Start)),
80+
timeRemaining: () =>
81+
Math.max(0, Timeout - (Date.now() - Start)),
8182
});
8283
}, Timeout) as unknown as number;
8384
};
@@ -106,6 +107,34 @@ if (typeof (globalThis as any).__name !== "function") {
106107
};
107108
}
108109

110+
// Inject __name into blob workers via Blob constructor patch (zero-cost).
111+
// VS Code's getWorkerBootstrapUrl builds blobs from string arrays. We intercept
112+
// Blob creation and prepend the __name shim to any application/javascript blob
113+
// that contains the VS Code worker marker. No XHR, no re-fetch — just string
114+
// prepend at construction time.
115+
{
116+
const OriginalBlob = globalThis.Blob;
117+
const NameShim =
118+
"var __defProp=Object.defineProperty;var __name=(t,v)=>__defProp(t,'name',{value:v,configurable:true});\n";
119+
120+
(globalThis as any).Blob = function PatchedBlob(
121+
Parts?: BlobPart[],
122+
Options?: BlobPropertyBag,
123+
) {
124+
if (
125+
Options?.type === "application/javascript" &&
126+
Parts?.length &&
127+
typeof Parts[0] === "string" &&
128+
Parts[0].includes("_VSCODE_NLS_MESSAGES")
129+
) {
130+
// This is a VS Code worker bootstrap blob — prepend __name shim
131+
Parts = [NameShim, ...Parts];
132+
}
133+
return new OriginalBlob(Parts, Options);
134+
} as unknown as typeof Blob;
135+
(globalThis as any).Blob.prototype = OriginalBlob.prototype;
136+
}
137+
109138
try {
110139
const WorkbenchUrl =
111140
"/Static/Application/vs/code/electron-browser/workbench/workbench.js";

Source/pages/Browser.astro

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ const Worker = `/Worker.js?BASE_REMOTE=${encodeURIComponent(Astro.url.origin)}`;
8282
"frame-src": [
8383
"'self'",
8484
"vscode-webview:",
85+
"vscode-webview.net",
86+
"*.vscode-cdn.net",
87+
"*.vscode-webview.net",
8588
"http://localhost:*",
8689
"https://tauri.localhost",
8790
],
@@ -90,17 +93,24 @@ const Worker = `/Worker.js?BASE_REMOTE=${encodeURIComponent(Astro.url.origin)}`;
9093
"'unsafe-inline'",
9194
"'unsafe-eval'",
9295
"blob:",
96+
"vscode-file:",
97+
"vscode-file://vscode-app",
9398
"http://localhost:*",
9499
"https://tauri.localhost",
95100
],
96101
"style-src": [
97102
"'self'",
98103
"'unsafe-inline'",
104+
"vscode-file:",
99105
"http://localhost:*",
100106
"https://tauri.localhost",
101107
],
102108
"connect-src": [
103109
"'self'",
110+
"blob:",
111+
"ipc:",
112+
"vscode-file:",
113+
"vscode-file://vscode-app",
104114
"http://localhost:*",
105115
"https://tauri.localhost",
106116
"wss://tauri.localhost",
@@ -136,6 +146,9 @@ const Worker = `/Worker.js?BASE_REMOTE=${encodeURIComponent(Astro.url.origin)}`;
136146
"frame-src": [
137147
"'self'",
138148
"vscode-webview:",
149+
"vscode-webview.net",
150+
"*.vscode-cdn.net",
151+
"*.vscode-webview.net",
139152
"http://localhost:*",
140153
"https://tauri.localhost",
141154
"https://*.vscode-cdn.net",

Source/pages/BrowserProxy.astro

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ const Worker = `/Worker.js?BASE_REMOTE=${encodeURIComponent(Astro.url.origin)}`;
8282
"frame-src": [
8383
"'self'",
8484
"vscode-webview:",
85+
"vscode-webview.net",
86+
"*.vscode-cdn.net",
87+
"*.vscode-webview.net",
8588
"http://localhost:*",
8689
"https://tauri.localhost",
8790
],
@@ -90,17 +93,24 @@ const Worker = `/Worker.js?BASE_REMOTE=${encodeURIComponent(Astro.url.origin)}`;
9093
"'unsafe-inline'",
9194
"'unsafe-eval'",
9295
"blob:",
96+
"vscode-file:",
97+
"vscode-file://vscode-app",
9398
"http://localhost:*",
9499
"https://tauri.localhost",
95100
],
96101
"style-src": [
97102
"'self'",
98103
"'unsafe-inline'",
104+
"vscode-file:",
99105
"http://localhost:*",
100106
"https://tauri.localhost",
101107
],
102108
"connect-src": [
103109
"'self'",
110+
"blob:",
111+
"ipc:",
112+
"vscode-file:",
113+
"vscode-file://vscode-app",
104114
"http://localhost:*",
105115
"https://tauri.localhost",
106116
"wss://tauri.localhost",

Source/pages/Electron.astro

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ const Worker = `/Worker.js?BASE_REMOTE=${encodeURIComponent(Astro.url.origin)}`;
8282
"frame-src": [
8383
"'self'",
8484
"vscode-webview:",
85+
"vscode-webview.net",
86+
"*.vscode-cdn.net",
87+
"*.vscode-webview.net",
8588
"http://localhost:*",
8689
"https://tauri.localhost",
8790
],
@@ -91,6 +94,7 @@ const Worker = `/Worker.js?BASE_REMOTE=${encodeURIComponent(Astro.url.origin)}`;
9194
"'unsafe-eval'",
9295
"blob:",
9396
"vscode-file:",
97+
"vscode-file://vscode-app",
9498
"http://localhost:*",
9599
"https://tauri.localhost",
96100
],
@@ -103,8 +107,10 @@ const Worker = `/Worker.js?BASE_REMOTE=${encodeURIComponent(Astro.url.origin)}`;
103107
],
104108
"connect-src": [
105109
"'self'",
110+
"blob:",
106111
"ipc:",
107112
"vscode-file:",
113+
"vscode-file://vscode-app",
108114
"http://localhost:*",
109115
"https://tauri.localhost",
110116
"wss://tauri.localhost",

Source/pages/Mountain.astro

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ const Worker = `/Worker.js?BASE_REMOTE=${encodeURIComponent(Astro.url.origin)}`;
8282
"frame-src": [
8383
"'self'",
8484
"vscode-webview:",
85+
"vscode-webview.net",
86+
"*.vscode-cdn.net",
87+
"*.vscode-webview.net",
8588
"http://localhost:*",
8689
"https://tauri.localhost",
8790
],
@@ -90,17 +93,24 @@ const Worker = `/Worker.js?BASE_REMOTE=${encodeURIComponent(Astro.url.origin)}`;
9093
"'unsafe-inline'",
9194
"'unsafe-eval'",
9295
"blob:",
96+
"vscode-file:",
97+
"vscode-file://vscode-app",
9398
"http://localhost:*",
9499
"https://tauri.localhost",
95100
],
96101
"style-src": [
97102
"'self'",
98103
"'unsafe-inline'",
104+
"vscode-file:",
99105
"http://localhost:*",
100106
"https://tauri.localhost",
101107
],
102108
"connect-src": [
103109
"'self'",
110+
"blob:",
111+
"ipc:",
112+
"vscode-file:",
113+
"vscode-file://vscode-app",
104114
"http://localhost:*",
105115
"https://tauri.localhost",
106116
"wss://tauri.localhost",
@@ -163,14 +173,27 @@ const Worker = `/Worker.js?BASE_REMOTE=${encodeURIComponent(Astro.url.origin)}`;
163173

164174
<!-- Inject folderUri from URL into workbench config (must run before module scripts) -->
165175
<script is:inline slot="Meta">
166-
(function() {
167-
var FolderParam = new URLSearchParams(window.location.search).get("folder");
176+
(function () {
177+
var FolderParam = new URLSearchParams(window.location.search).get(
178+
"folder",
179+
);
168180
if (FolderParam) {
169-
var Element = document.getElementById("vscode-workbench-web-configuration");
181+
var Element = document.getElementById(
182+
"vscode-workbench-web-configuration",
183+
);
170184
if (Element) {
171-
var Settings = JSON.parse(Element.getAttribute("data-settings") || "{}");
172-
Settings.folderUri = { scheme: "file", path: FolderParam, authority: "" };
173-
Element.setAttribute("data-settings", JSON.stringify(Settings));
185+
var Settings = JSON.parse(
186+
Element.getAttribute("data-settings") || "{}",
187+
);
188+
Settings.folderUri = {
189+
scheme: "file",
190+
path: FolderParam,
191+
authority: "",
192+
};
193+
Element.setAttribute(
194+
"data-settings",
195+
JSON.stringify(Settings),
196+
);
174197
}
175198
}
176199
})();

Source/pages/index.astro

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import MountainWorkbench from "../Workbench/Mountain.astro";
2626
2727
// Environment detection ONLY
2828
const Bundle = process.env["Bundle"] === "true";
29-
const Browser = process.env["Browser"] === "true";
3029
const Mountain = process.env["Mountain"] === "true";
3130
const Electron = process.env["Electron"] === "true";
3231
const BrowserProxy = process.env["BrowserProxy"] === "true";
@@ -35,11 +34,12 @@ const BrowserProxy = process.env["BrowserProxy"] === "true";
3534
// Mountain uses the Electron workbench — it has the full IPC chain
3635
// (TauriMainProcessService → Mountain WindServiceHandlers → tokio::fs)
3736
// for real filesystem access. The browser workbench uses IndexedDB.
38-
const WorkbenchType = Electron || Mountain
39-
? "Electron"
40-
: BrowserProxy
41-
? "BrowserProxy"
42-
: "Browser"; // Default, not null
37+
const WorkbenchType =
38+
Electron || Mountain
39+
? "Electron"
40+
: BrowserProxy
41+
? "BrowserProxy"
42+
: "Browser"; // Default, not null
4343
4444
// Determine embedder identifier
4545
const EmbedderId = Electron || Mountain ? "desktop" : "browser";
@@ -93,6 +93,7 @@ const Worker = `/Worker.js?BASE_REMOTE=${encodeURIComponent(Astro.url.origin)}`;
9393
"'unsafe-eval'",
9494
"blob:",
9595
"vscode-file:",
96+
"vscode-file://vscode-app",
9697
"http://localhost:*",
9798
"https://tauri.localhost",
9899
],
@@ -107,6 +108,7 @@ const Worker = `/Worker.js?BASE_REMOTE=${encodeURIComponent(Astro.url.origin)}`;
107108
"'self'",
108109
"ipc:",
109110
"vscode-file:",
111+
"vscode-file://vscode-app",
110112
"http://localhost:*",
111113
"https://tauri.localhost",
112114
"wss://tauri.localhost",
@@ -198,14 +200,27 @@ const Worker = `/Worker.js?BASE_REMOTE=${encodeURIComponent(Astro.url.origin)}`;
198200

199201
<!-- Inject folderUri from URL into workbench config (must run before module scripts) -->
200202
<script is:inline slot="Meta">
201-
(function() {
202-
var FolderParam = new URLSearchParams(window.location.search).get("folder");
203+
(function () {
204+
var FolderParam = new URLSearchParams(window.location.search).get(
205+
"folder",
206+
);
203207
if (FolderParam) {
204-
var Element = document.getElementById("vscode-workbench-web-configuration");
208+
var Element = document.getElementById(
209+
"vscode-workbench-web-configuration",
210+
);
205211
if (Element) {
206-
var Settings = JSON.parse(Element.getAttribute("data-settings") || "{}");
207-
Settings.folderUri = { scheme: "file", path: FolderParam, authority: "" };
208-
Element.setAttribute("data-settings", JSON.stringify(Settings));
212+
var Settings = JSON.parse(
213+
Element.getAttribute("data-settings") || "{}",
214+
);
215+
Settings.folderUri = {
216+
scheme: "file",
217+
path: FolderParam,
218+
authority: "",
219+
};
220+
Element.setAttribute(
221+
"data-settings",
222+
JSON.stringify(Settings),
223+
);
209224
}
210225
}
211226
})();

0 commit comments

Comments
 (0)