Skip to content

Portals and Session history #19

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

Open
lucasgadani opened this issue Jul 31, 2018 · 15 comments
Open

Portals and Session history #19

lucasgadani opened this issue Jul 31, 2018 · 15 comments
Labels
design work needed An acknowledged gap in the proposal that needs design work to resolve

Comments

@lucasgadani
Copy link
Collaborator

When a portal is activated, its contents will take the whole tab, so it makes sense from a users perspective to treat this the same way we treat a navigation and add the portal's last entry to the session history. That ensures that the back button has a reasonably expected behavior, even though it may not be as seamless/smooth as the portal activation.

Other than that, we'll rely on the previous page to restore its state on back navigation, which can be accomplished by using push/replace state APIs before a portal activation.

@ericfs
Copy link

ericfs commented Jul 31, 2018

What about on deactivation in the case where the an activated portal adopts its predecessor?

That is:

  • A contains portal to B
  • B is activated and adopts A
  • A is activated

What does the history stack look like at that point? Is it [A, B, A]? Is there some way to have it be [A] as if there were a back navigation?

@ericfs
Copy link

ericfs commented Jul 31, 2018

Even more complicated:

  • A contains portal to B
  • B is activated and adopts A
  • B pushes B#state
  • A is activated

@lucasgadani
Copy link
Collaborator Author

In this case:

A contains portal to B
B is activated and adopts A
A is activated

If the session history was initially empty, I would expect it to first have [A], as the user navigated to A, then when B is activated, it would have [A, B], then when A is activated we would have [A,B,A]. If the user pressed the back button in the second step instead, then the history would have [A,B] where A is the current entry (i.e. the forward button would be active). This is the same behavior as a navigation, and I think the most intuitive to the user.

On the second example:

A contains portal to B
B is activated and adopts A
B pushes B#state
A is activated

Then the session history would have [A,B,B#state,A]. B could also use replaceState if it would want to avoid creating a new entry.

@ericfs
Copy link

ericfs commented Jul 31, 2018

So in this case:

Other than that, we'll rely on the previous page to restore its state on back navigation, which can be accomplished by using push/replace state APIs before a portal activation.

Will this back navigation behave differently depending on whether B adopts A or not?

In the case of:

  • A contains portal to B
  • B is activated and adopts A
  • history.back()

Will A receive the popstate event and will it be able to deactivate B to enable a smooth transition? You said:

it may not be as seamless/smooth as the portal activation.

Does that mean it's impossible to make it smooth or just that it may not be smooth if A isn't adopted and thus able to handle the navigation smoothly?

@lucasgadani
Copy link
Collaborator Author

This is something we considered, but we didn't find a way for the user agent to know the intent of the page when navigating back, so it would be hard to define something other than navigating.

Achieving your desired behavior (smooth transition back) would still be possible though, the page would have to:

  1. A contains a portal to B
  2. B is activated and adopts A
  3. B uses pushState to store its state.
  4. When the user navigates back, B receives a popstate and has a chance to activate A instead.

@ericfs
Copy link

ericfs commented Jul 31, 2018

Just want to make sure I understand this:

B uses pushState to store its state.

You're saying there will be an extra state on the stack? Like [A, B {base:true}, B {base:false} ]

So when the user navigates back, B can check history.state.base is true and then activate A. Activating A will still result in stack like [A, B {base:true}, A] which is not ideal.

@lucasgadani
Copy link
Collaborator Author

So when the user navigates back, B can check history.state.base is true and then activate A. Activating A will still result in stack like [A, B {base:true}, A] which is not ideal.

Yes, that's right.

We have also considered having an optional parameter, or a different method to activate the portal that would replace the entry in the session history, similar to location.replace, but we weren't sure there was a use case for it. Do you think that could help achieve what you have in mind? I think it still wouldn't be possible to achieve something similar to a back navigation.

@ericfs
Copy link

ericfs commented Aug 1, 2018

Yeah, I agree that it doesn't seem like supporting replace would fix back navigation case.

I could still image replace being useful. For the cases from Key Scenarios I think it would probably be preferable for "Carousel of articles from different websites" and "Publication with an infinite list of articles" to use replace rather than push. I think push could work for these, but I also think it could be potentially surprising to develop a large history stack while scrolling or swiping through documents.

@dvoytenko
Copy link

History is a very loaded topic. Do you think any history API would be available to portal in a non-activated mode? This area might deserve a separate issue.

With activation/deactivation: I think some control w.r.t. push/replace should be available to both A and B. However, the [A,B,B#state,A] from an example above would seem very undesirable. At least in some use cases, it'd be a lot better to "detach" local portal's history from global stack when deactivated, and re-attach it again when activated again.

E.g. consider this:

  1. User activates some features in A. The stack is [A1, A2, A3]
  2. The user activates B. The stack is [A0, A1, A2, [B0]]
  3. The user activates some features in B. The stack is [A0, A1, A2, [B0, B1]]
  4. The user explicitly deactivates B. The stack should be [A0, A1, A2]. But ideally the [B0, B1] is preserved in B in case it gets reactivated.

@ericfs
Copy link

ericfs commented Aug 15, 2018

@jeremyroman raised some concerns with the complexity of this "stack of stacks" idea that @dvoytenko
proposed.

We discussed some ideas to try and allow JS to fake this, such as by providing some sort of identifier for a history state so that history can reliably pop to a specific state. This isn't perfect since it would still require popping states. That is instead of [A0, A1, A2, [B0, B1]] -> [A0, A1, A2] you would have to do: [A0, A1, A2, B0, B1] -> [A0, A1, A2, B0] -> [A0, A1, A2]. If B was then reactivated, it would be in its base state, B0, instead of B1.

I like Dima's suggestion that the history stack for a document should be preserved in a deactivated portal.

@dvoytenko
Copy link

@jeremyroman @ericfs One thing to note: Firefox is actually doing some stack of stack management of iframes. For instance, an iframe can push into the global history as one would expect. But when an iframe is removed, all history items associated with it are removed from global history stack. Comparing to that, Chrome handling is actually less elegant - the global history stack simply breaks. See https://bugs.chromium.org/p/chromium/issues/detail?id=705550. Also, there are some security implications as described in the https://bugs.chromium.org/p/chromium/issues/detail?id=705583.

@matthewp
Copy link

matthewp commented May 8, 2019

I've run into this while playing around with the flagged implementation in Canary. I want to be able to do:

A -> B (adopt A) <- (back button) -> A

While retaining the same history as you would get if portals were not used.

@jeremyroman
Copy link
Collaborator

A few points raised by @annevk that relate to history:

History currently hangs off the browsing context (and BC group) in the specification, but our current thinking on this would seem to allow navigating back to the history of a browsing context that has since been discarded (e.g. because it wasn't adopted). It might make sense to change how this association is structured so that history entries can survive.

Also, we don't have as crisp an understanding as we would like about how history.length, history.go(-1), etc. are used in practice. Anne thinks that we might be able to have these not span the browsing context boundaries in the combined session history. Contrary to what I said at the time, @kjmcnee tells me that this aligns with the latest draft of our session history proposal for portals.

@juliadou
Copy link

juliadou commented Dec 9, 2019

Any updates on this? I think allowing back button to work is crucial for many adaptions.

@jeremyroman
Copy link
Collaborator

Implementation bug. Fixed in later Chrome releases, with more improvements coming down the pipe. See #163 (comment).

@domenic domenic added the design work needed An acknowledged gap in the proposal that needs design work to resolve label May 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design work needed An acknowledged gap in the proposal that needs design work to resolve
Projects
None yet
Development

No branches or pull requests

7 participants