9
9
10
10
const sw = /** @type {ServiceWorkerGlobalScope } */ ( /** @type {any } */ ( self ) ) ;
11
11
12
- const VERSION = 3 ;
12
+ const VERSION = 4 ;
13
13
14
14
const resourceCacheName = `vscode-resource-cache-${ VERSION } ` ;
15
15
@@ -127,41 +127,33 @@ const notFound = () =>
127
127
const methodNotAllowed = ( ) =>
128
128
new Response ( 'Method Not Allowed' , { status : 405 , } ) ;
129
129
130
- const vscodeMessageChannel = new MessageChannel ( ) ;
131
-
132
- sw . addEventListener ( 'message' , event => {
130
+ sw . addEventListener ( 'message' , async ( event ) => {
133
131
switch ( event . data . channel ) {
134
- case 'init ' :
132
+ case 'version ' :
135
133
{
136
134
const source = /** @type {Client } */ ( event . source ) ;
137
135
sw . clients . get ( source . id ) . then ( client => {
138
- client ?. postMessage ( {
139
- channel : 'init' ,
140
- version : VERSION
141
- } , [ vscodeMessageChannel . port2 ] ) ;
136
+ if ( client ) {
137
+ client . postMessage ( {
138
+ channel : 'version' ,
139
+ version : VERSION
140
+ } ) ;
141
+ }
142
142
} ) ;
143
143
return ;
144
144
}
145
- default :
146
- console . log ( 'Unknown message' ) ;
147
- return ;
148
- }
149
- } ) ;
150
-
151
- vscodeMessageChannel . port1 . onmessage = ( event ) => {
152
- switch ( event . data . channel ) {
153
145
case 'did-load-resource' :
154
146
{
155
147
/** @type {ResourceResponse } */
156
- const response = event . data ;
148
+ const response = event . data . data ;
157
149
if ( ! resourceRequestStore . resolve ( response . id , response ) ) {
158
150
console . log ( 'Could not resolve unknown resource' , response . path ) ;
159
151
}
160
152
return ;
161
153
}
162
154
case 'did-load-localhost' :
163
155
{
164
- const data = event . data ;
156
+ const data = event . data . data ;
165
157
if ( ! localhostRequestStore . resolve ( data . id , data . location ) ) {
166
158
console . log ( 'Could not resolve unknown localhost' , data . origin ) ;
167
159
}
@@ -171,7 +163,7 @@ vscodeMessageChannel.port1.onmessage = (event) => {
171
163
console . log ( 'Unknown message' ) ;
172
164
return ;
173
165
}
174
- } ;
166
+ } ) ;
175
167
176
168
sw . addEventListener ( 'fetch' , ( event ) => {
177
169
const requestUrl = new URL ( event . request . url ) ;
@@ -193,7 +185,7 @@ sw.addEventListener('fetch', (event) => {
193
185
} ) ;
194
186
195
187
sw . addEventListener ( 'install' , ( event ) => {
196
- event . waitUntil ( sw . skipWaiting ( ) ) ;
188
+ event . waitUntil ( sw . skipWaiting ( ) ) ; // Activate worker immediately
197
189
} ) ;
198
190
199
191
sw . addEventListener ( 'activate' , ( event ) => {
@@ -205,6 +197,18 @@ sw.addEventListener('activate', (event) => {
205
197
* @param {URL } requestUrl
206
198
*/
207
199
async function processResourceRequest ( event , requestUrl ) {
200
+ const client = await sw . clients . get ( event . clientId ) ;
201
+ if ( ! client ) {
202
+ console . error ( 'Could not find inner client for request' ) ;
203
+ return notFound ( ) ;
204
+ }
205
+
206
+ const webviewId = getWebviewIdForClient ( client ) ;
207
+ if ( ! webviewId ) {
208
+ console . error ( 'Could not resolve webview id' ) ;
209
+ return notFound ( ) ;
210
+ }
211
+
208
212
const shouldTryCaching = ( event . request . method === 'GET' ) ;
209
213
210
214
/**
@@ -254,6 +258,12 @@ async function processResourceRequest(event, requestUrl) {
254
258
return response . clone ( ) ;
255
259
} ;
256
260
261
+ const parentClients = await getOuterIframeClient ( webviewId ) ;
262
+ if ( ! parentClients . length ) {
263
+ console . log ( 'Could not find parent client for request' ) ;
264
+ return notFound ( ) ;
265
+ }
266
+
257
267
/** @type {Response | undefined } */
258
268
let cached ;
259
269
if ( shouldTryCaching ) {
@@ -267,15 +277,17 @@ async function processResourceRequest(event, requestUrl) {
267
277
const scheme = firstHostSegment . split ( '+' , 1 ) [ 0 ] ;
268
278
const authority = firstHostSegment . slice ( scheme . length + 1 ) ; // may be empty
269
279
270
- vscodeMessageChannel . port1 . postMessage ( {
271
- channel : 'load-resource' ,
272
- id : requestId ,
273
- path : requestUrl . pathname ,
274
- scheme,
275
- authority,
276
- query : requestUrl . search . replace ( / ^ \? / , '' ) ,
277
- ifNoneMatch : cached ?. headers . get ( 'ETag' ) ,
278
- } ) ;
280
+ for ( const parentClient of parentClients ) {
281
+ parentClient . postMessage ( {
282
+ channel : 'load-resource' ,
283
+ id : requestId ,
284
+ path : requestUrl . pathname ,
285
+ scheme,
286
+ authority,
287
+ query : requestUrl . search . replace ( / ^ \? / , '' ) ,
288
+ ifNoneMatch : cached ?. headers . get ( 'ETag' ) ,
289
+ } ) ;
290
+ }
279
291
280
292
return promise . then ( entry => resolveResourceEntry ( entry , cached ) ) ;
281
293
}
@@ -292,6 +304,11 @@ async function processLocalhostRequest(event, requestUrl) {
292
304
// that are not spawned by vs code
293
305
return fetch ( event . request ) ;
294
306
}
307
+ const webviewId = getWebviewIdForClient ( client ) ;
308
+ if ( ! webviewId ) {
309
+ console . error ( 'Could not resolve webview id' ) ;
310
+ return fetch ( event . request ) ;
311
+ }
295
312
296
313
const origin = requestUrl . origin ;
297
314
@@ -312,13 +329,42 @@ async function processLocalhostRequest(event, requestUrl) {
312
329
} ) ;
313
330
} ;
314
331
315
- const { requestId, promise } = localhostRequestStore . create ( ) ;
332
+ const parentClients = await getOuterIframeClient ( webviewId ) ;
333
+ if ( ! parentClients . length ) {
334
+ console . log ( 'Could not find parent client for request' ) ;
335
+ return notFound ( ) ;
336
+ }
316
337
317
- vscodeMessageChannel . port1 . postMessage ( {
318
- channel : 'load-localhost' ,
319
- origin : origin ,
320
- id : requestId ,
321
- } ) ;
338
+ const { requestId, promise } = localhostRequestStore . create ( ) ;
339
+ for ( const parentClient of parentClients ) {
340
+ parentClient . postMessage ( {
341
+ channel : 'load-localhost' ,
342
+ origin : origin ,
343
+ id : requestId ,
344
+ } ) ;
345
+ }
322
346
323
347
return promise . then ( resolveRedirect ) ;
324
348
}
349
+
350
+ /**
351
+ * @param {Client } client
352
+ * @returns {string | null }
353
+ */
354
+ function getWebviewIdForClient ( client ) {
355
+ const requesterClientUrl = new URL ( client . url ) ;
356
+ return requesterClientUrl . searchParams . get ( 'id' ) ;
357
+ }
358
+
359
+ /**
360
+ * @param {string } webviewId
361
+ * @returns {Promise<Client[]> }
362
+ */
363
+ async function getOuterIframeClient ( webviewId ) {
364
+ const allClients = await sw . clients . matchAll ( { includeUncontrolled : true } ) ;
365
+ return allClients . filter ( client => {
366
+ const clientUrl = new URL ( client . url ) ;
367
+ const hasExpectedPathName = ( clientUrl . pathname === `${ rootPath } /` || clientUrl . pathname === `${ rootPath } /index.html` ) ;
368
+ return hasExpectedPathName && clientUrl . searchParams . get ( 'id' ) === webviewId ;
369
+ } ) ;
370
+ }
0 commit comments