New issue
Advanced search Search tips

Issue 721262 link

Starred by 2 users

Issue metadata

Status: Fixed
Owner:
Closed: Jul 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 3
Type: Bug-Regression



Sign in to add a comment

Chrome scroll restoration does not work when the "next" page is shorter than the "previous" page

Reported by erik.ziv...@gmail.com, May 11 2017

Issue description

UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36

Example URL:
https://bes.github.io/scroll-restore-test/

Steps to reproduce the problem:
1. Go to https://bes.github.io/scroll-restore-test/
2. Follow the instructions. 
TL;DR: scroll to the bottom of the page and try the two links.

What is the expected behavior?
Scroll restoration should work properly regardless of if the "next" page is long or short.

This works properly on Firefox and Safari, but not Chrome or Opera.

What went wrong?
Scroll restoration does not work when going from a "long" to a "short" page and then back to the "long" page.

Does it occur on multiple sites: Yes

Is it a problem with a plugin? No 

Did this work before? N/A 

Does this work in other browsers? Yes

Chrome version: 58.0.3029.110  Channel: stable
OS Version: OS X 10.12.4
Flash Version: 

The source code for the example can be found at https://github.com/bes/scroll-restore-test
 
Labels: Needs-Triage-M58
Updated github repo & and example URL with MS Edge result (passes both tests).
Components: -Blink Blink>Scroll
Labels: -Type-Bug M-60 has-bisect-per-revision OS-Linux OS-Windows Type-Bug-Regression
Status: Untriaged (was: Unconfirmed)
Able to reproduce the issue on windows 7, Ubuntu 14.04 and Mac 10.12.4 using chrome version 58.0.3029.110 and canary 60.0.3099.0.
This is regression issue broken in M49.Please find the bisect information as below

Narrow bisect::
Good::49.0.2620.0  --   (build revision 369070)
Bad:: 49.0.2621.0   --   (build revision 369281)

Change Log::
https://chromium.googlesource.com/chromium/src/+log/fa15e24628fbc6f499f6d5ea8ec8531e83d5bed0..91e6e97ccdc0d6cdd4e3543102ccc0f90a6da004

Unable to find the suspect from the CL.Could any one from dev team please look into this issue.

Thanks,

Comment 4 by bokan@chromium.org, May 18 2017

Cc: bokan@chromium.org
Labels: -OS-Linux -OS-Windows -Pri-2 -OS-Mac Hotlist-Input-Dev OS-All Pri-3
Owner: chaopeng@chromium.org
Status: Assigned (was: Untriaged)
Weird, I can definitely repro. Chao, mind taking a look?
Cc: majidvp@chromium.org
I test it on Mac. Long page restored to a wrong position. Short page did not restore.

Suspect it is from this cl 91e6e97ccdc0d6cdd4e3543102ccc0f90a6da004.
I tried to not restore scroll position until page has enough content. It can fix this issue and not break  issue 574487 , but lots test case failed. majidvp@ WDYT?
Cc: skobes@chromium.org japhet@chromium.org
> I tried to not restore scroll position until page has enough content.

The proposed fix for waiting on the page to have enough content is something we
already do for scroll restoration. In particular during a navigation we re-try
restoring the scroll position every time the page size changes (until it is
successful). However note that we only do so *during a navigation* which means
that blink doesn't try to restore scroll position once navigation is considered
complete.


I think this I think the above model gives a predictable and mostly correct
behavior. In particular, once navigation is finished, the page content can
change (and resize) to reflect a transition in the application state. Trying to
restore the old scroll position for this new application state is incorrect. In
fact, this is in exactly what CL in #3 fixes by correcting a bug where our
navigation state was not correctly updated at the end of a same document
navigation.

A same document navigation (e.g., when clicking back/forward on a entry that was
added via history API) is considered complete after "popstate" event is
dispatched. So if the page content is not at the right size after popstate we
may not be able to restore the scroll position correctly.

I suspect the above page is not creating its page content as part of the
"popstate" event which explains the issue in Blink. chaopeng@ can you look at
the page and confirm this is the case. I am also curious how Safari/Firefox behave
differently here as it seem they manage to restore position even when resize is
occurring after popstate.

I can see two potential fixes here:
 - Change Blink current definition for completion of a same page navigation to
   allow some async work. Perhaps we can have "restore scroll position" to
   occur not just immediately after popstate event but also once all the tasks
   posted by popstate are serviced. Note sure if this is even possible.

  - A more intelligent scroll anchoring logic that is not position dependent.
    This allows us to decouple scroll restoration from exact semantic of
    navigation. For example I think something like Scroll Anchor Serialization
    ( Issue 734679 ) can potentially fix this.


/cc skobes@ and japhet@ in case they have ideas here.

Comment 8 by skobes@chromium.org, Jun 22 2017

Scroll anchor serialization won't help if the content is loading after the navigation is finished.  I think we need more investigation of what's happening in this test case.
I agree we need more investigation/evidence before deciding to change current behavior. chaopeng@
is going to look into this.

In particular, I am skeptical that any heuristic that tries to guess when the SPA UI has changed
enough to correctly "restore scroll position". So I prefer the current simple model + existing
escape hatch (i.e., history.scrollRestoration = 'manual';).

Regarding the scroll anchor serialization suggestion, the idea was to wait on restoring the scroll
position until the "anchor element" becomes available even if it is after when we consider the
navigation to be complete. Again, this depends on actually investigating and confirming that this
is needed.

Details of this case:

This case is using react + react router + history. 

1. The popstate event listener is history createBrowserHistory handlePopState [1]. 
2. react is using their home make vdom. They actually update DOM tree in react-dom DOMLazyTree replaceChildWithTree [2].

Add a break point at [2] we can see the stack is not async.

Add log to the FrameLoader::LoadInSameDocument[3], we can see no Layout happens in popstate. That is why the content size is incorrect.

[1] https://github.com/ReactTraining/history/blob/93992e8596e2cf97024b69915eb45b4da871c736/modules/createBrowserHistory.js#L90
[2] https://github.com/facebook/react/blob/b1768b5/src/renderers/dom/stack/client/DOMLazyTree.js#L82
[3] https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/loader/FrameLoader.cpp?rcl=588d17e4f4b4d8f73bca38924c24037ae4717dea&l=563
This is a simple example for this issue.
URL: http://ht.chaopeng.me/scroll-restore-incorrect.html
scroll-restore-incorrect.html
521 bytes View Download
Project Member

Comment 12 by bugdroid1@chromium.org, Jul 7 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/87030295c8093dfd90b209aa099f080b278a8289

commit 87030295c8093dfd90b209aa099f080b278a8289
Author: chaopeng <chaopeng@chromium.org>
Date: Fri Jul 07 16:19:13 2017

Force layout for SameDocumentLoad when content size is not enough for restore.

This issue is caused by in navigation backward (LoadInSameDocument) for Single
Page App, developer change DOM in onpopstate but not trigger a layout, then we
don't have correct content size for restore scroll position.

In this patch, we add a layout in RestoreScrollPositionAndViewState when the
size is not enough for restore scroll position. This change should only effect
SameDocumentLoad.

Bug:  721262 
Change-Id: I2b2956828634884b926b4c5b3073210170f42263
Reviewed-on: https://chromium-review.googlesource.com/556979
Commit-Queue: Jianpeng Chao <chaopeng@chromium.org>
Reviewed-by: Majid Valipour <majidvp@chromium.org>
Reviewed-by: Mike West <mkwst@chromium.org>
Cr-Commit-Position: refs/heads/master@{#484944}
[add] https://crrev.com/87030295c8093dfd90b209aa099f080b278a8289/third_party/WebKit/LayoutTests/fast/history/scroll-restoration/scroll-restoration-same-doc.html
[modify] https://crrev.com/87030295c8093dfd90b209aa099f080b278a8289/third_party/WebKit/Source/core/loader/FrameLoader.cpp
[modify] https://crrev.com/87030295c8093dfd90b209aa099f080b278a8289/third_party/WebKit/Source/core/loader/FrameLoader.h

Status: Fixed (was: Assigned)

Sign in to add a comment