Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.Sign up
Registering service workers for unique origins? #1437
I am looking for a way to register a service worker runs for a unique origin. The lifetime of the service worker would be tied to the lifetime of the page with that unique origin.
I develop VS Code's webview API, which lets VS Code extensions render arbitrary html inside of the VS Code editor. I am currently trying to set up a sandboxed environment for webviews using iframes + service workers. Here's the basic structure:
<!-- Serve up from a unique origin so that the iframe cannot effect our main page --> <iframe src="https://cdn.contoso.com" sandbox="allow-same-origin"> <html> <body> <!-- This is a static html page served up from cdn.contoso.com. It is where we have VS Code's scripts for managing webview content. This is also where we register a service worker for cdn.contoso.com. We use the service worker to implement a virtual `/vscode-resource/` endpoint that the untrusted html provided by extension can use to load resources from the user's workspace (we delegate the loading back to the main page, which lets us allow or deny this the request) --> <iframe width="100%" height="100%" sandbox="allow-same-origin"> <!-- Actual html content coming from an extension --> <img src="/vscode-resource/Users/matt/workspace/cat.git"> // This goes through the service worker </iframe> </body> </html> </webview>
The main issue with this approach is that all the webview content ends up being served from the same
A secondary issue is that we need to stand up
Here's the actual code that implements all this today:
I believe that allowing service workers to be registered in sandboxed iframe that does not set
Another approach would be an API for registering a one-time service worker that runs on a unique origin. The page would then be able to use the unique origin to serve up content. The lifetime of the worker would be the same as the page itself (similar to
For example, this could look something like:
const worker = await navigator.createServiceWorkerEndpoint('source of my virtual server worker'); const iframe = document.createElement('iframe'); iframe.src = worker.url; // This will result in a `fetch` against our worker for `/` at our unique origin document.body.appendChild(iframe);
The registered service worker itself would behave just like a normal service worker. However its lifetime would be linked to the page that created it. This would also simplify the creation of a virtual server for us (because we do not use many parts of service workers, such as them being shared across multiple pages).
Possibly Related issues
URL.createObjectURL I think is generally considered a regrettable decision we wouldn't want to imitate. As designed it encourages leaking resources, and as browsers need to implement it (at least Firefox), it's actually even more horrible under the hood.
Being able to register a single ServiceWorker on a special scope that's explicitly for opaque origins for this exact scenario might work, though. Like:
That makes sense. I mainly brought up the
What are the next steps in continuing this discussion? I don't think our use case is specific to our implementation of webviews for VS Code
To try to workaround this limitation, I've setup a domain that serves the same content on every subdomain you access (this way, the served up pages have a unique origin). These subdomains are only used once by a client and a service worker is registered for them.
However I do not know if this will cause perf issue for browsers in practice. What will happen as the number of service workers builds up as we keep accessing new subdomains? I've asked about this on StackOverflow. I think I may be able to call