Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

workerStart should be clearly defined as applicable to the last SW #100

Closed
yoavweiss opened this issue Dec 20, 2018 · 15 comments
Closed

workerStart should be clearly defined as applicable to the last SW #100

yoavweiss opened this issue Dec 20, 2018 · 15 comments

Comments

@yoavweiss
Copy link
Contributor

Spinoff from w3c/resource-timing#118

Currently, in the case of multiple redirects, each with it's own SW, it's not clear which worker start time should be reflected in workerStart. We should clarify that it's either the last SW applicable, or the active SW of the final document. The latter seems to be a more consistent definition.

@yoavweiss yoavweiss added this to the Level 2 milestone Mar 8, 2019
@yoavweiss
Copy link
Contributor Author

/cc @nhelfman

@nicjansma
Copy link

Addressed in #131.

Defined as the ServiceWorker startup time of the first request in the final same-origin redirect chain.

Scenarios (a.com and b.com have SWs, c.com does not)

  1. a.com -> b.com: b.com's SW startup
  2. a.com -> b.com/1 -> b.com/2: b.com/1 SW startup
  3. a.com -> b.com/1 -> a.com -> b.com/2: b.com/2 SW startup
  4. a.com -> b.com/1 -> c.com -> b.com/2: b.com/2 SW startup
  5. a.com -> b.com/1 -> c.com -> b.com/2 -> b.com/3: b.com/2 SW startup
  6. a.com -> b.com -> c.com: 0 (c.com does not have SW)

@noamr
Copy link
Contributor

noamr commented Dec 4, 2021

What does it mean to be "intercepted" by a SW?
The first interpretation is: "the service worker captures the FetchEvent, sends out a new fetch and calls respondWith with the response coming from that fetch".

In the above case the timing details of the "internal" fetch (the one initiated by the SW) are totally opaque to the caller of the external fetch (the navigation). Think of the SW in this case as a transparent proxy server of sorts, it knows its own timing but "hides" them from the client.

So any redirects that are a result of a fetch() call inside a SW would appear as timing info in the SW performance timeline but not as part of the navigation, and only the external SW (which would be the first to respond) would reports its workerStart to navigation timing.

The second interpretation is: "the service worker constructs a Response object with a redirect status".
In this case, the fetchStart and workerStart in navigation timing are always the ones for the final navigation after redirectEnd, so the initial redirect responses would not be visible there.

@yoavweiss
Copy link
Contributor Author

I think we typically refer to your first interpretation, but both seem valid.

In the above case the timing details of the "internal" fetch (the one initiated by the SW) are totally opaque to the caller of the external fetch (the navigation). Think of the SW in this case as a transparent proxy server of sorts, it knows its own timing but "hides" them from the client.

At the same time, if we expose the workerStart time of an early redirect to the eventual document, which may be on a different origin, that could create a cross-origin leak. The final redirect is always same-origin with the document that would receive this info. In the case of NavigationTiming, the "navigation" is not a concept that gets any info, the committed document is. We need to keep that in mind.

@noamr
Copy link
Contributor

noamr commented Dec 13, 2021

I think we typically refer to your first interpretation, but both seem valid.

In the above case the timing details of the "internal" fetch (the one initiated by the SW) are totally opaque to the caller of the external fetch (the navigation). Think of the SW in this case as a transparent proxy server of sorts, it knows its own timing but "hides" them from the client.

At the same time, if we expose the workerStart time of an early redirect to the eventual document, which may be on a different origin, that could create a cross-origin leak. The final redirect is always same-origin with the document that would receive this info. In the case of NavigationTiming, the "navigation" is not a concept that gets any info, the committed document is. We need to keep that in mind.

I don't think this is a problem.
The scenario here, as I understand it, would be:

  • A navigation occurs
  • A SW captures the FetchEvent, and responds with the response from a new fetch to a different origin.
  • The RT entry for that fetch in the SW performance timeline would have redirect timing info only if that different origin response had TAO
  • The navigation timing entry would not have any redirect information, but would have a workerStart that corresponds to something that happened in the same-origin worker.

@yoavweiss
Copy link
Contributor Author

I think we can have multiple cases:
a) Origin A's SW is responding with a Response from origin B
b) Origin A's SW fetches a resource from origin A, which redirects to B
c) Origin A's SW responds with a redirect response to origin B

I think it's OK to expose the workerStart time of Origin A's SW only in the case of (a), but not in (b) and (c).
The reason is that in (a), the SW is making a contious decision to return a response from B to Origin A, and A's SW is the only one involved. In the other scenarios, multiple SWs can be involved.

@noamr
Copy link
Contributor

noamr commented Dec 13, 2021

b) Origin A's SW fetches a resource from origin A, which redirects to B

That redirect is completely hidden from the document. As far as the document knows, the document is in origin (A). Only the SW knows that something here is cross-origin at all. It's no different from the SW loading some cross-origin JSON and constructing the HTML for the navigation response by itself.

c) Origin A's SW responds with a redirect response to origin B

This is like the second scenario in my original comment - "the service worker constructs a Response object with a redirect status".
In that scenario, workerStart would not be present as the navigation is involved in the redirect.

@noamr
Copy link
Contributor

noamr commented Dec 13, 2021

Note that if the worker in origin (B) constructs a redirect response, there is no mechanism for worker (A) to forward it to the navigation. Worker (A), and any client of FETCH, only gets the response back after all the redirects are resolved (this is an important part of how FETCH works).

@yoavweiss
Copy link
Contributor Author

As far as the document knows, the document is in origin (A).

The document in is origin B in that case, and is oblivious to the initial redirect from origin A (modulo referrers).

Only the SW knows that something here is cross-origin at all

Maybe we're not talking about the same scenario. I'm thinking about A's SW, fetching example.html, which then gets redirected (by the server, and below the SW in the network stack) to B/example.html.
A's SW will see an opaque response in that case, IIUC.

This is like the second scenario in my original comment - "the service worker constructs a Response object with a redirect status".

Yeah.

In that scenario, workerStart would not be present as the navigation is involved in the redirect.

I'm not sure I understand the connection.

@noamr
Copy link
Contributor

noamr commented Dec 13, 2021

As far as the document knows, the document is in origin (A).

The document in is origin B in that case, and is oblivious to the initial redirect from origin A (modulo referrers).

Only the SW knows that something here is cross-origin at all

Maybe we're not talking about the same scenario. I'm thinking about A's SW, fetching example.html, which then gets redirected (by the server, and below the SW in the network stack) to B/example.html. A's SW will see an opaque response in that case, IIUC.

That opaque response is what would be brought back to the navigation, at least according to the spec.
The A->B redirect would be handled internally in the SW's fetch, and the navigation would not know anything about it, and should not, for example, set the address bar to (B).

This is like the second scenario in my original comment - "the service worker constructs a Response object with a redirect status".

Yeah.

In that scenario, workerStart would not be present as the navigation is involved in the redirect.

I'm not sure I understand the connection.

In the FETCH spec, workerStart is mapped to the response that comes after all the known redirects of that fetch are resolved. A constructed redirect from a worker is known to that FETCH, so it "trumps" the workerStart.

@yoavweiss
Copy link
Contributor Author

The A->B redirect would be handled internally in the SW's fetch, and the navigation would not know anything about it, and should not, for example, set the address bar to (B).

That seems odd. So a cross-origin redirect that modifies the URL bar without a SW would now not do that once a SW is introduced?

@noamr
Copy link
Contributor

noamr commented Dec 13, 2021

The A->B redirect would be handled internally in the SW's fetch, and the navigation would not know anything about it, and should not, for example, set the address bar to (B).

That seems odd. So a cross-origin redirect that modifies the URL bar without a SW would now not do that once a SW is introduced?

Yes, the SW fetch masks that redirect like a transparent proxy. The SW basically does the equivalent of CORS-fetching the HTML data and returns it to the browsing context as data stream (modified if it so chooses).

@noamr
Copy link
Contributor

noamr commented Dec 13, 2021

The A->B redirect would be handled internally in the SW's fetch, and the navigation would not know anything about it, and should not, for example, set the address bar to (B).

That seems odd. So a cross-origin redirect that modifies the URL bar without a SW would now not do that once a SW is introduced?

Yes, the SW fetch masks that redirect like a transparent proxy. The SW basically does the equivalent of CORS-fetching the HTML data and returns it to the browsing context as data stream (modified if it so chooses).

OK, so the SW can override this by sending the internal fetch with redirect mode set to "manual", and forwarding the redirect to the caller. In this case, workerState of the original SW will not be available. The "manual" redirect mode exists exactly for this purpose.

@noamr
Copy link
Contributor

noamr commented Dec 14, 2021

@yoavweiss I think this can be closed?

@noamr
Copy link
Contributor

noamr commented Jan 18, 2022

Closing, feel free to reopen.

@noamr noamr closed this as completed Jan 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants