w3c / ServiceWorker

Service Workers
https://w3c.github.io/ServiceWorker/
Other
3.63k stars 312 forks source link

[Feature request] Expose parent client ID for iframe navigations #1556

Open AshleyScirra opened 3 years ago

AshleyScirra commented 3 years ago

Ref: https://lists.w3.org/Archives/Public/public-webapps/2020OctDec/0028.html

We have a use case that involves serving local Blobs via a map of URL to Blob. (This is part of previewing locally developed content in our web-based game development IDE.) For example the map might associate myimage.png with a Blob of a PNG image. Then this can be served for a request to example.com/myimage.png. The map is stored per client ID, so each client has its own independent map of blobs to serve.

We'd like this to propagate through iframes too - so if a client using that map opens a (same-origin, same path) iframe, then content in that iframe can also successfully request example.com/myimage.png.

However when loading an iframe, its navigate request reaches the Service Worker with an empty clientId, instead only having a resultingClientId. However I need to know the clientId of the parent client, so I can propagate the parent's map of blobs to also apply to the resultingClientId. But it seems there's no way to get the parent client ID from an iframe's FetchEvent.

Perhaps there could be a parentClientId field on FetchEvent to cover this?

asutherland commented 3 years ago

Do you need to be able to derive the exact iframe hierarchy, or is just being able to bin all iframes by their browsing context group and/or agent cluster sufficient?

AshleyScirra commented 3 years ago

In this case it's sufficient only to know the parent client ID in an iframe navigation fetch, since that allows us to propagate client state through iframes recursively.

asutherland commented 3 years ago

Is the mechanism resilient to the ServiceWorker being restarted independent of the lifetimes of the pages?

AshleyScirra commented 3 years ago

If the SW restarted while a page was still open, that would break our URL-to-blob mapping. I didn't know that was possible with SW lifecycles - how would we ensure this mapping keeps working in that case? If the browser can remove the SW at an arbitrary time, how do we guarantee that these SW-reliant URLs continue to load? Our fallback without a SW would be a blob URL, but that would still break certain features, such as a JavaScript module import URL that we can't dynamically update.

asutherland commented 3 years ago

The root of the issue seems to be that you're using the same URL space multiple times and you're trying to use the transitive graph of client id's to differentiate them. Can you elaborate more on why you need to reuse the same URLs? What would it take to be able to assign each game it own URL space?

An important note is that the scope only matters for initial navigations of pages that are controlled by ServiceWorkers. Once the ServiceWorker is controlling a page (whether by navigation or inheriting in the case of about:blank iframes), all of its subresource requests go to the ServiceWorker, even if they are notionally for resources that are hosted on other origins. This can never be used to spoof the UI, but does allow some level of emulating resources stored on sub-domains, other origins, etc., other than the need to have an in-scope URL for the initial navigation. (This may require use of new Response(response.body, response) in order to drop the URL field from any responses that actually did come from the network, however, in order for the controlled page's fetch to act like the response came from the Request URL).

I know previously in other issues you referenced problems with dealing with multiple versions of ServiceWorkers, is the choice in relation to that? There has been work to allow changing the scopes of ServiceWorkers which might be of help with that.

AshleyScirra commented 3 years ago

Can you elaborate more on why you need to reuse the same URLs?

I don't see why we need to use unique URLs as a kind of identifier when we already have the client ID as an identifier. It works fine for everything else, but only causes a slight hurdle with iframe navigations.

I know previously in other issues you referenced problems with dealing with multiple versions of ServiceWorkers, is the choice in relation to that?

No, this does not involve multiple service workers.

jakearchibald commented 3 years ago

Exposing the client id of a containing document seems reasonable to me in cases where they're same origin.

There are other relationships that we might want to expose as part of the client API:

It might be time to think of what a client API would look like outside of service worker.

futurist commented 2 years ago

Any update on this feature? This is needed for below use case:

  1. A top window contains several iframes, which contains other iframes, each iframe's content intercepted and injected by ServiceWorker
  2. The inner iframes should know it's parent clientId, otherwise the the content will go to the wrong iframe parent.

Without this parentClientId feature, it's very hard to make above work right.