Changeset 213590 in webkit


Ignore:
Timestamp:
Mar 8, 2017 12:01:15 PM (7 years ago)
Author:
Simon Fraser
Message:

Add support for history.scrollRestoration
https://bugs.webkit.org/show_bug.cgi?id=147782
rdar://problem/22614568

Reviewed by Sam Weinig.
LayoutTests/imported/w3c:

New passing baselines.

  • web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-basic-expected.txt:
  • web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin-expected.txt:
  • web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin-expected.txt:
  • web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc-expected.txt:

Source/WebCore:

Add support for history.scrollRestoration, per spec:
<https://html.spec.whatwg.org/multipage/browsers.html#dom-history-scroll-restoration>

This is a new attribute on the History interface. On setting, sets the "shouldRestoreScrollPosition"
state on the current history item, and the getter returns that state. pushState() inherits the
state from the current item.

HistoryController::restoreScrollPositionAndViewState() consults this state, and if set to "manual"
("don't restore) it just uses the current scroll position (we need something to pass to
setPageScaleFactor() so can't just avoid the restoration).

FrameLoader::scrollToFragmentWithParentBoundary() also needs to consult the historyItem
to know if it's OK to scroll to a fragment, on back/forward same-document loads.

Tests: fast/history/history-scroll-restoration-attribute.html

fast/history/history-scroll-restoration.html

  • history/HistoryItem.cpp:

(WebCore::HistoryItem::HistoryItem):
(WebCore::HistoryItem::shouldRestoreScrollPosition):
(WebCore::HistoryItem::setShouldRestoreScrollPosition):

  • history/HistoryItem.h:
  • loader/FrameLoader.cpp:

(WebCore::FrameLoader::loadInSameDocument):
(WebCore::itemAllowsScrollRestoration):
(WebCore::isSameDocumentReload):
(WebCore::FrameLoader::scrollToFragmentWithParentBoundary):
(WebCore::FrameLoader::continueLoadAfterNavigationPolicy):

  • loader/FrameLoader.h:
  • loader/HistoryController.cpp:

(WebCore::HistoryController::restoreScrollPositionAndViewState):
(WebCore::HistoryController::goToItem):
(WebCore::HistoryController::pushState):
(WebCore::HistoryController::replaceState):

  • page/History.cpp:

(WebCore::History::scrollRestoration):
(WebCore::History::setScrollRestoration):

  • page/History.h:
  • page/History.idl:

Source/WebKit2:

Need to send shouldRestoreScrollPosition to the UI process in SessionState,
WKWebView now stores _unobscuredCenterToRestore and _scrollOffsetToRestore as
std::optionals, and they will be nullopt if scroll restoration should not happen.

ViewGestureControllerIOS also needs knowledge of whether scroll restoration will
happen, and compares UI-process scroll position vs. the position at snapshot time
to know if the snapshot should be shown (this prevents showing a misleading snapshot
when swiping back on a navigation where scroll restoration is disabled).

  • Shared/SessionState.cpp:

(WebKit::FrameState::encode):
(WebKit::FrameState::decode):

  • Shared/SessionState.h:
  • Shared/WebBackForwardListItem.h:

(WebKit::WebBackForwardListItem::pageState):

  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView _processDidExit]):
(-[WKWebView _didCommitLayerTree:]):
(-[WKWebView _restorePageScrollPosition:scrollOrigin:previousObscuredInset:scale:]):
(-[WKWebView _restorePageStateToUnobscuredCenter:scale:]):

  • UIProcess/API/Cocoa/WKWebViewInternal.h:
  • UIProcess/API/gtk/PageClientImpl.cpp:

(WebKit::PageClientImpl::viewScrollPosition):

  • UIProcess/API/gtk/PageClientImpl.h:
  • UIProcess/PageClient.h:
  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::viewScrollPosition):

  • UIProcess/WebPageProxy.h:
  • UIProcess/WebPageProxy.messages.in:
  • UIProcess/ios/PageClientImplIOS.h:
  • UIProcess/ios/PageClientImplIOS.mm:

(WebKit::PageClientImpl::viewScrollPosition):
(WebKit::PageClientImpl::restorePageState):
(WebKit::PageClientImpl::restorePageCenterAndScale):

  • UIProcess/ios/ViewGestureControllerIOS.mm:

(WebKit::ViewGestureController::beginSwipeGesture):

  • UIProcess/ios/WebPageProxyIOS.mm:

(WebKit::WebPageProxy::restorePageState):
(WebKit::WebPageProxy::restorePageCenterAndScale):

  • UIProcess/mac/PageClientImpl.h:
  • UIProcess/mac/PageClientImpl.mm:

(WebKit::PageClientImpl::viewScrollPosition):

  • UIProcess/mac/ViewSnapshotStore.h:

(WebKit::ViewSnapshot::setViewScrollPosition):
(WebKit::ViewSnapshot::viewScrollPosition):

  • UIProcess/mac/ViewSnapshotStore.mm:

(WebKit::ViewSnapshotStore::recordSnapshot):

  • WebProcess/WebCoreSupport/SessionStateConversion.cpp:

(WebKit::toFrameState):
(WebKit::applyFrameState):

  • WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:

(WebKit::WebFrameLoaderClient::restoreViewState):

  • WebProcess/WebPage/ios/WebPageIOS.mm:

(WebKit::WebPage::restorePageState):

LayoutTests:

Sadly history-scroll-restoration.html needs to be cloned for iOS and to use uiController.doAfterPresentationUpdate()
there, since restoration involves a trip to the UI process, and this same test did not work for Mac WK1 (dispatch_async()
doesn't seem to give the right timing in DRT).

  • TestExpectations:
  • fast/dom/Window/window-appendages-cleared-expected.txt:
  • fast/history/history-scroll-restoration-attribute-expected.txt: Added.
  • fast/history/history-scroll-restoration-attribute.html: Added.
  • fast/history/history-scroll-restoration-expected.txt: Added.
  • fast/history/history-scroll-restoration.html: Added.
  • platform/ios-simulator-wk2/TestExpectations:
  • platform/ios-simulator/TestExpectations:
Location:
trunk
Files:
7 added
42 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r213589 r213590  
     12017-03-08  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Add support for history.scrollRestoration
     4        https://bugs.webkit.org/show_bug.cgi?id=147782
     5        rdar://problem/22614568
     6
     7        Reviewed by Sam Weinig.
     8
     9        Sadly history-scroll-restoration.html needs to be cloned for iOS and to use uiController.doAfterPresentationUpdate()
     10        there, since restoration involves a trip to the UI process, and this same test did not work for Mac WK1 (dispatch_async()
     11        doesn't seem to give the right timing in DRT).
     12
     13        * TestExpectations:
     14        * fast/dom/Window/window-appendages-cleared-expected.txt:
     15        * fast/history/history-scroll-restoration-attribute-expected.txt: Added.
     16        * fast/history/history-scroll-restoration-attribute.html: Added.
     17        * fast/history/history-scroll-restoration-expected.txt: Added.
     18        * fast/history/history-scroll-restoration.html: Added.
     19        * platform/ios-simulator-wk2/TestExpectations:
     20        * platform/ios-simulator/TestExpectations:
     21
    1222017-03-08  Chris Dumez  <cdumez@apple.com>
    223
  • trunk/LayoutTests/TestExpectations

    r213511 r213590  
    2626fast/events/ios [ Skip ]
    2727fast/events/touch/ios [ Skip ]
     28fast/history/ios [ Skip ]
    2829fast/scrolling/ios [ Skip ]
    2930scrollingcoordinator/ios [ Skip ]
     
    10591060webkit.org/b/168175 imported/w3c/web-platform-tests/html/browsers/offline/browser-state/navigator_online_online.html [ Pass Failure ]
    10601061webkit.org/b/168175 imported/w3c/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-download-click.html [ Timeout Pass ]
     1062webkit.org/b/169264 imported/w3c/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc.html [ Failure ]
    10611063
    10621064webkit.org/b/168066 performance-api/performance-now-api.html [ Pass Failure ]
  • trunk/LayoutTests/fast/dom/Window/window-appendages-cleared-expected.txt

    r204953 r213590  
    55PASS history.pushState == "LEFTOVER" is false
    66PASS history.replaceState == "LEFTOVER" is false
     7PASS history.scrollRestoration == "LEFTOVER" is false
    78PASS history.state == "LEFTOVER" is false
    89PASS location.ancestorOrigins == "LEFTOVER" is false
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r213560 r213590  
     12017-03-08  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Add support for history.scrollRestoration
     4        https://bugs.webkit.org/show_bug.cgi?id=147782
     5        rdar://problem/22614568
     6
     7        Reviewed by Sam Weinig.
     8       
     9        New passing baselines.
     10
     11        * web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-basic-expected.txt:
     12        * web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin-expected.txt:
     13        * web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin-expected.txt:
     14        * web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc-expected.txt:
     15
    1162017-03-07  Jiewen Tan  <jiewen_tan@apple.com>
    217
  • trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-basic-expected.txt

    r204844 r213590  
    11
    2 FAIL Default value is "auto" assert_equals: expected (string) "auto" but got (undefined) undefined
     2PASS Default value is "auto"
    33PASS It is writable
    4 FAIL Invalid values are ignored assert_equals: setting to invalid value (3.1415) should be ignored expected (string) "auto" but got (number) 3.1415
     4PASS Invalid values are ignored
    55
  • trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin-expected.txt

    r211930 r213590  
    11Blocked access to external URL http://www.localhost:8800/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/blank1.html
    2 CONSOLE MESSAGE: line 2451: Error: assert_equals: navigating back should retain scrollRestoration value expected (string) "manual" but got (undefined) undefined
    32
    43
    5 Harness Error (TIMEOUT), message = null
     4PASS Manual scroll restoration should take precedent over scrolling to fragment in cross origin navigation
    65
    7 TIMEOUT Manual scroll restoration should take precedent over scrolling to fragment in cross origin navigation Test timed out
    8 
  • trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin-expected.txt

    r204844 r213590  
    11
    22
    3 FAIL Navigating to new page should reset to "auto" and navigating back should restore and respect scroll restoration mode assert_equals: new page loads should set scrollRestoration to "auto" expected (string) "auto" but got (undefined) undefined
     3PASS Navigating to new page should reset to "auto" and navigating back should restore and respect scroll restoration mode
    44
  • trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc-expected.txt

    r204844 r213590  
    11
    2 FAIL history.{push,replace}State retain scroll restoration mode and navigation in the same document respects it assert_equals: scrollX is correct for #4 expected 555 but got 200
     2PASS history.{push,replace}State retain scroll restoration mode and navigation in the same document respects it
    33
  • trunk/LayoutTests/platform/ios-simulator-wk2/TestExpectations

    r213476 r213590  
    77#//////////////////////////////////////////////////////////////////////////////////////////
    88
     9fast/history/ios [ Pass ]
    910fast/scrolling/ios [ Pass ]
    1011fast/viewport/ios [ Pass ]
     
    784785fast/history/gesture-before-onload-location-href.html
    785786fast/history/history_reload.html
     787fast/history/history-scroll-restoration.html [ Skip ]
    786788fast/history/timed-refresh-in-cached-frame.html
    787789fast/history/window-open.html
  • trunk/LayoutTests/platform/ios-simulator/TestExpectations

    r213460 r213590  
    24402440webkit.org/b/153371 imported/w3c/web-platform-tests/XMLHttpRequest/getresponseheader-chunked-trailer.htm [ Pass Failure ]
    24412441
     2442webkit.org/b/169210 imported/w3c/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc.html [ Failure ]
     2443
    24422444webkit.org/b/153498 svg/dom/SVGScriptElement/script-change-externalResourcesRequired-while-loading.svg [ Pass Timeout ]
    24432445
  • trunk/Source/WebCore/ChangeLog

    r213589 r213590  
     12017-03-08  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Add support for history.scrollRestoration
     4        https://bugs.webkit.org/show_bug.cgi?id=147782
     5        rdar://problem/22614568
     6
     7        Reviewed by Sam Weinig.
     8
     9        Add support for history.scrollRestoration, per spec:
     10        <https://html.spec.whatwg.org/multipage/browsers.html#dom-history-scroll-restoration>
     11
     12        This is a new attribute on the History interface. On setting, sets the "shouldRestoreScrollPosition"
     13        state on the current history item, and the getter returns that state. pushState() inherits the
     14        state from the current item.
     15
     16        HistoryController::restoreScrollPositionAndViewState() consults this state, and if set to "manual"
     17        ("don't restore) it just uses the current scroll position (we need something to pass to
     18        setPageScaleFactor() so can't just avoid the restoration).
     19
     20        FrameLoader::scrollToFragmentWithParentBoundary() also needs to consult the historyItem
     21        to know if it's OK to scroll to a fragment, on back/forward same-document loads.
     22
     23        Tests: fast/history/history-scroll-restoration-attribute.html
     24               fast/history/history-scroll-restoration.html
     25
     26        * history/HistoryItem.cpp:
     27        (WebCore::HistoryItem::HistoryItem):
     28        (WebCore::HistoryItem::shouldRestoreScrollPosition):
     29        (WebCore::HistoryItem::setShouldRestoreScrollPosition):
     30        * history/HistoryItem.h:
     31        * loader/FrameLoader.cpp:
     32        (WebCore::FrameLoader::loadInSameDocument):
     33        (WebCore::itemAllowsScrollRestoration):
     34        (WebCore::isSameDocumentReload):
     35        (WebCore::FrameLoader::scrollToFragmentWithParentBoundary):
     36        (WebCore::FrameLoader::continueLoadAfterNavigationPolicy):
     37        * loader/FrameLoader.h:
     38        * loader/HistoryController.cpp:
     39        (WebCore::HistoryController::restoreScrollPositionAndViewState):
     40        (WebCore::HistoryController::goToItem):
     41        (WebCore::HistoryController::pushState):
     42        (WebCore::HistoryController::replaceState):
     43        * page/History.cpp:
     44        (WebCore::History::scrollRestoration):
     45        (WebCore::History::setScrollRestoration):
     46        * page/History.h:
     47        * page/History.idl:
     48
    1492017-03-08  Chris Dumez  <cdumez@apple.com>
    250
  • trunk/Source/WebCore/history/HistoryItem.cpp

    r207580 r213590  
    5757
    5858HistoryItem::HistoryItem()
    59     : m_pageScaleFactor(0)
    60     , m_lastVisitWasFailure(false)
    61     , m_isTargetItem(false)
    62     , m_itemSequenceNumber(generateSequenceNumber())
     59    : m_itemSequenceNumber(generateSequenceNumber())
    6360    , m_documentSequenceNumber(generateSequenceNumber())
    6461    , m_pruningReason(PruningReason::None)
     
    7067    , m_originalURLString(urlString)
    7168    , m_title(title)
    72     , m_pageScaleFactor(0)
    73     , m_lastVisitWasFailure(false)
    74     , m_isTargetItem(false)
    7569    , m_itemSequenceNumber(generateSequenceNumber())
    7670    , m_documentSequenceNumber(generateSequenceNumber())
     
    8680    , m_displayTitle(alternateTitle)
    8781    , m_pageScaleFactor(0)
    88     , m_lastVisitWasFailure(false)
    89     , m_isTargetItem(false)
    9082    , m_itemSequenceNumber(generateSequenceNumber())
    9183    , m_documentSequenceNumber(generateSequenceNumber())
     
    272264}
    273265
     266bool HistoryItem::shouldRestoreScrollPosition() const
     267{
     268    return m_shouldRestoreScrollPosition;
     269}
     270
     271void HistoryItem::setShouldRestoreScrollPosition(bool shouldRestore)
     272{
     273    m_shouldRestoreScrollPosition = shouldRestore;
     274}
     275
    274276float HistoryItem::pageScaleFactor() const
    275277{
  • trunk/Source/WebCore/history/HistoryItem.h

    r209292 r213590  
    103103    WEBCORE_EXPORT void setScrollPosition(const IntPoint&);
    104104    void clearScrollPosition();
     105
     106    WEBCORE_EXPORT bool shouldRestoreScrollPosition() const;
     107    WEBCORE_EXPORT void setShouldRestoreScrollPosition(bool);
    105108   
    106109    WEBCORE_EXPORT float pageScaleFactor() const;
     
    216219   
    217220    IntPoint m_scrollPosition;
    218     float m_pageScaleFactor;
     221    float m_pageScaleFactor { 0 }; // 0 indicates "unset".
    219222    Vector<String> m_documentState;
    220223
     
    223226    Vector<Ref<HistoryItem>> m_children;
    224227   
    225     bool m_lastVisitWasFailure;
    226     bool m_isTargetItem;
     228    bool m_lastVisitWasFailure { false };
     229    bool m_isTargetItem { false };
    227230    bool m_wasRestoredFromSession { false };
     231    bool m_shouldRestoreScrollPosition { true };
    228232
    229233    // If two HistoryItems have the same item sequence number, then they are
  • trunk/Source/WebCore/loader/FrameLoader.cpp

    r213311 r213590  
    10561056    // We need to scroll to the fragment whether or not a hash change occurred, since
    10571057    // the user might have scrolled since the previous navigation.
    1058     scrollToFragmentWithParentBoundary(url);
     1058    scrollToFragmentWithParentBoundary(url, isNewNavigation);
    10591059   
    10601060    m_isComplete = false;
     
    28692869}
    28702870
    2871 void FrameLoader::scrollToFragmentWithParentBoundary(const URL& url)
     2871static bool itemAllowsScrollRestoration(HistoryItem* historyItem)
     2872{
     2873    return historyItem && historyItem->shouldRestoreScrollPosition();
     2874}
     2875
     2876static bool isSameDocumentReload(bool isNewNavigation, FrameLoadType loadType)
     2877{
     2878    return !isNewNavigation && !isBackForwardLoadType(loadType);
     2879}
     2880
     2881void FrameLoader::scrollToFragmentWithParentBoundary(const URL& url, bool isNewNavigation)
    28722882{
    28732883    FrameView* view = m_frame.view();
     
    28812891        boundaryFrame->view()->setSafeToPropagateScrollToParent(false);
    28822892
    2883     view->scrollToFragment(url);
     2893    if (isSameDocumentReload(isNewNavigation, m_loadType) || itemAllowsScrollRestoration(history().currentItem()))
     2894        view->scrollToFragment(url);
    28842895
    28852896    if (boundaryFrame)
     
    30833094
    30843095        // If the navigation request came from the back/forward menu, and we punt on it, we have the
    3085         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity,
     3096        // problem that we have optimistically moved the b/f cursor already, so move it back. For sanity,
    30863097        // we only do this when punting a navigation for the target frame or top-level frame. 
    30873098        if ((isTargetItem || m_frame.isMainFrame()) && isBackForwardLoadType(policyChecker().loadType())) {
  • trunk/Source/WebCore/loader/FrameLoader.h

    r211033 r213590  
    335335
    336336    bool shouldPerformFragmentNavigation(bool isFormSubmission, const String& httpMethod, FrameLoadType, const URL&);
    337     void scrollToFragmentWithParentBoundary(const URL&);
     337    void scrollToFragmentWithParentBoundary(const URL&, bool isNewNavigation = true);
    338338
    339339    void checkLoadCompleteForThisFrame();
  • trunk/Source/WebCore/loader/HistoryController.cpp

    r212484 r213590  
    159159    if (view && !view->wasScrolledByUser()) {
    160160        Page* page = m_frame.page();
    161         auto desiredScrollPosition = m_currentItem->scrollPosition();
     161        auto desiredScrollPosition = m_currentItem->shouldRestoreScrollPosition() ? m_currentItem->scrollPosition() : view->scrollPosition();
    162162        LOG(Scrolling, "HistoryController::restoreScrollPositionAndViewState scrolling to %d,%d", desiredScrollPosition.x(), desiredScrollPosition.y());
    163163        if (page && m_frame.isMainFrame() && m_currentItem->pageScaleFactor())
     
    292292void HistoryController::goToItem(HistoryItem& targetItem, FrameLoadType type)
    293293{
     294    LOG(History, "HistoryController %p goToItem %p type=%d", this, &targetItem, type);
     295
    294296    ASSERT(!m_frame.tree().parent());
    295297   
     
    854856    ASSERT(page);
    855857
     858    bool shouldRestoreScrollPosition = m_currentItem->shouldRestoreScrollPosition();
     859   
    856860    // Get a HistoryItem tree for the current frame tree.
    857861    Ref<HistoryItem> topItem = m_frame.mainFrame().loader().history().createItemTree(m_frame, false);
     
    862866    m_currentItem->setStateObject(WTFMove(stateObject));
    863867    m_currentItem->setURLString(urlString);
    864 
    865     LOG(History, "HistoryController %p pushState: Adding top item %p, setting url of current item %p to %s", this, topItem.ptr(), m_currentItem.get(), urlString.ascii().data());
     868    m_currentItem->setShouldRestoreScrollPosition(shouldRestoreScrollPosition);
     869
     870    LOG(History, "HistoryController %p pushState: Adding top item %p, setting url of current item %p to %s, scrollRestoration is %s", this, topItem.ptr(), m_currentItem.get(), urlString.ascii().data(), topItem->shouldRestoreScrollPosition() ? "auto" : "manual");
    866871
    867872    page->backForward().addItem(WTFMove(topItem));
     
    879884        return;
    880885
    881     LOG(History, "HistoryController %p replaceState: Setting url of current item %p to %s", this, m_currentItem.get(), urlString.ascii().data());
     886    LOG(History, "HistoryController %p replaceState: Setting url of current item %p to %s scrollRestoration %s", this, m_currentItem.get(), urlString.ascii().data(), m_currentItem->shouldRestoreScrollPosition() ? "auto" : "manual");
    882887
    883888    if (!urlString.isEmpty())
  • trunk/Source/WebCore/page/History.cpp

    r212250 r213590  
    6060}
    6161
     62ExceptionOr<History::ScrollRestoration> History::scrollRestoration() const
     63{
     64    if (!m_frame)
     65        return Exception { SECURITY_ERR };
     66
     67    auto* historyItem = m_frame->loader().history().currentItem();
     68    if (!historyItem)
     69        return ScrollRestoration::Auto;
     70   
     71    return historyItem->shouldRestoreScrollPosition() ? ScrollRestoration::Auto : ScrollRestoration::Manual;
     72}
     73
     74ExceptionOr<void> History::setScrollRestoration(ScrollRestoration scrollRestoration)
     75{
     76    if (!m_frame)
     77        return Exception { SECURITY_ERR };
     78
     79    auto* historyItem = m_frame->loader().history().currentItem();
     80    if (historyItem)
     81        historyItem->setShouldRestoreScrollPosition(scrollRestoration == ScrollRestoration::Auto);
     82
     83    return { };
     84}
     85
    6286SerializedScriptValue* History::state()
    6387{
  • trunk/Source/WebCore/page/History.h

    r206976 r213590  
    4242
    4343    unsigned length() const;
     44   
     45    enum class ScrollRestoration {
     46        Auto,
     47        Manual
     48    };
     49
     50    ExceptionOr<ScrollRestoration> scrollRestoration() const;
     51    ExceptionOr<void> setScrollRestoration(ScrollRestoration);
     52
    4453    SerializedScriptValue* state();
    4554    void back();
  • trunk/Source/WebCore/page/History.idl

    r206976 r213590  
    2828] interface History {
    2929    readonly attribute unsigned long length;
     30    [SetterMayThrowException, GetterMayThrowException] attribute ScrollRestoration scrollRestoration;
    3031    [CachedAttribute, Custom] readonly attribute SerializedScriptValue state;
    3132
     
    3738    [Custom, MayThrowException] void replaceState(any data, DOMString title, optional USVString? url = null);
    3839};
     40
     41enum ScrollRestoration { "auto", "manual" };
  • trunk/Source/WebKit2/ChangeLog

    r213586 r213590  
     12017-03-08  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Add support for history.scrollRestoration
     4        https://bugs.webkit.org/show_bug.cgi?id=147782
     5        rdar://problem/22614568
     6
     7        Reviewed by Sam Weinig.
     8       
     9        Need to send shouldRestoreScrollPosition to the UI process in SessionState,
     10        WKWebView now stores _unobscuredCenterToRestore and _scrollOffsetToRestore as
     11        std::optionals, and they will be nullopt if scroll restoration should not happen.
     12
     13        ViewGestureControllerIOS also needs knowledge of whether scroll restoration will
     14        happen, and compares UI-process scroll position vs. the position at snapshot time
     15        to know if the snapshot should be shown (this prevents showing a misleading snapshot
     16        when swiping back on a navigation where scroll restoration is disabled).
     17
     18        * Shared/SessionState.cpp:
     19        (WebKit::FrameState::encode):
     20        (WebKit::FrameState::decode):
     21        * Shared/SessionState.h:
     22        * Shared/WebBackForwardListItem.h:
     23        (WebKit::WebBackForwardListItem::pageState):
     24        * UIProcess/API/Cocoa/WKWebView.mm:
     25        (-[WKWebView _processDidExit]):
     26        (-[WKWebView _didCommitLayerTree:]):
     27        (-[WKWebView _restorePageScrollPosition:scrollOrigin:previousObscuredInset:scale:]):
     28        (-[WKWebView _restorePageStateToUnobscuredCenter:scale:]):
     29        * UIProcess/API/Cocoa/WKWebViewInternal.h:
     30        * UIProcess/API/gtk/PageClientImpl.cpp:
     31        (WebKit::PageClientImpl::viewScrollPosition):
     32        * UIProcess/API/gtk/PageClientImpl.h:
     33        * UIProcess/PageClient.h:
     34        * UIProcess/WebPageProxy.cpp:
     35        (WebKit::WebPageProxy::viewScrollPosition):
     36        * UIProcess/WebPageProxy.h:
     37        * UIProcess/WebPageProxy.messages.in:
     38        * UIProcess/ios/PageClientImplIOS.h:
     39        * UIProcess/ios/PageClientImplIOS.mm:
     40        (WebKit::PageClientImpl::viewScrollPosition):
     41        (WebKit::PageClientImpl::restorePageState):
     42        (WebKit::PageClientImpl::restorePageCenterAndScale):
     43        * UIProcess/ios/ViewGestureControllerIOS.mm:
     44        (WebKit::ViewGestureController::beginSwipeGesture):
     45        * UIProcess/ios/WebPageProxyIOS.mm:
     46        (WebKit::WebPageProxy::restorePageState):
     47        (WebKit::WebPageProxy::restorePageCenterAndScale):
     48        * UIProcess/mac/PageClientImpl.h:
     49        * UIProcess/mac/PageClientImpl.mm:
     50        (WebKit::PageClientImpl::viewScrollPosition):
     51        * UIProcess/mac/ViewSnapshotStore.h:
     52        (WebKit::ViewSnapshot::setViewScrollPosition):
     53        (WebKit::ViewSnapshot::viewScrollPosition):
     54        * UIProcess/mac/ViewSnapshotStore.mm:
     55        (WebKit::ViewSnapshotStore::recordSnapshot):
     56        * WebProcess/WebCoreSupport/SessionStateConversion.cpp:
     57        (WebKit::toFrameState):
     58        (WebKit::applyFrameState):
     59        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
     60        (WebKit::WebFrameLoaderClient::restoreViewState):
     61        * WebProcess/WebPage/ios/WebPageIOS.mm:
     62        (WebKit::WebPage::restorePageState):
     63
    1642017-03-08  Matt Rajca  <mrajca@apple.com>
    265
  • trunk/Source/WebKit2/Shared/SessionState.cpp

    r204668 r213590  
    115115
    116116    encoder << scrollPosition;
     117    encoder << shouldRestoreScrollPosition;
    117118    encoder << pageScaleFactor;
    118119
     
    153154    if (!decoder.decode(result.scrollPosition))
    154155        return false;
     156    if (!decoder.decode(result.shouldRestoreScrollPosition))
     157        return false;
    155158    if (!decoder.decode(result.pageScaleFactor))
    156159        return false;
  • trunk/Source/WebKit2/Shared/SessionState.h

    r208985 r213590  
    9797
    9898    WebCore::IntPoint scrollPosition;
     99    bool shouldRestoreScrollPosition;
    99100    float pageScaleFactor;
    100101
  • trunk/Source/WebKit2/Shared/WebBackForwardListItem.h

    r210042 r213590  
    5353
    5454    void setPageState(PageState pageState) { m_itemState.pageState = WTFMove(pageState); }
     55    const PageState& pageState() const { return m_itemState.pageState; }
    5556
    5657    const String& originalURL() const { return m_itemState.pageState.mainFrameState.originalURLString; }
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm

    r213272 r213590  
    252252    std::optional<CGRect> _frozenUnobscuredContentRect;
    253253
    254     BOOL _needsToRestoreScrollPosition;
    255254    BOOL _commitDidRestoreScrollPosition;
    256     WebCore::FloatPoint _scrollOffsetToRestore;
     255    std::optional<WebCore::FloatPoint> _scrollOffsetToRestore;
    257256    WebCore::FloatSize _obscuredInsetWhenSaved;
    258257
    259     BOOL _needsToRestoreUnobscuredCenter;
    260     WebCore::FloatPoint _unobscuredCenterToRestore;
     258    std::optional<WebCore::FloatPoint> _unobscuredCenterToRestore;
    261259    uint64_t _firstTransactionIDAfterPageRestore;
    262260    double _scaleToRestore;
     
    13701368    _dynamicViewportUpdateMode = DynamicViewportUpdateMode::NotResizing;
    13711369    [_contentView setHidden:NO];
    1372     _needsToRestoreScrollPosition = NO;
    1373     _needsToRestoreUnobscuredCenter = NO;
     1370    _scrollOffsetToRestore = std::nullopt;
     1371    _unobscuredCenterToRestore = std::nullopt;
    13741372    _scrollViewBackgroundColor = WebCore::Color();
    13751373    _delayUpdateVisibleContentRects = NO;
     
    14911489    }
    14921490
    1493     bool isTransactionAfterPageRestore = layerTreeTransaction.transactionID() >= _firstTransactionIDAfterPageRestore;
    1494 
    1495     if (_needsToRestoreScrollPosition && isTransactionAfterPageRestore) {
    1496         _needsToRestoreScrollPosition = NO;
    1497 
    1498         if (areEssentiallyEqualAsFloat(contentZoomScale(self), _scaleToRestore)) {
    1499             WebCore::FloatPoint scaledScrollOffset = _scrollOffsetToRestore;
    1500             scaledScrollOffset.scale(_scaleToRestore);
    1501             WebCore::FloatPoint contentOffsetInScrollViewCoordinates = scaledScrollOffset - _obscuredInsetWhenSaved;
    1502 
    1503             changeContentOffsetBoundedInValidRange(_scrollView.get(), contentOffsetInScrollViewCoordinates);
    1504             _commitDidRestoreScrollPosition = YES;
    1505 
    1506             if (_gestureController)
    1507                 _gestureController->didRestoreScrollPosition();
     1491    if (layerTreeTransaction.transactionID() >= _firstTransactionIDAfterPageRestore) {
     1492        if (_scrollOffsetToRestore) {
     1493            WebCore::FloatPoint scaledScrollOffset = _scrollOffsetToRestore.value();
     1494            _scrollOffsetToRestore = std::nullopt;
     1495
     1496            if (areEssentiallyEqualAsFloat(contentZoomScale(self), _scaleToRestore)) {
     1497                scaledScrollOffset.scale(_scaleToRestore);
     1498                WebCore::FloatPoint contentOffsetInScrollViewCoordinates = scaledScrollOffset - _obscuredInsetWhenSaved;
     1499
     1500                changeContentOffsetBoundedInValidRange(_scrollView.get(), contentOffsetInScrollViewCoordinates);
     1501                _commitDidRestoreScrollPosition = YES;
     1502            }
    15081503        }
    1509        
     1504
     1505        if (_unobscuredCenterToRestore) {
     1506            WebCore::FloatPoint unobscuredCenterToRestore = _unobscuredCenterToRestore.value();
     1507            _unobscuredCenterToRestore = std::nullopt;
     1508
     1509            if (areEssentiallyEqualAsFloat(contentZoomScale(self), _scaleToRestore)) {
     1510                CGRect unobscuredRect = UIEdgeInsetsInsetRect(self.bounds, _obscuredInsets);
     1511                WebCore::FloatSize unobscuredContentSizeAtNewScale(unobscuredRect.size.width / _scaleToRestore, unobscuredRect.size.height / _scaleToRestore);
     1512                WebCore::FloatPoint topLeftInDocumentCoordinates(unobscuredCenterToRestore.x() - unobscuredContentSizeAtNewScale.width() / 2, unobscuredCenterToRestore.y() - unobscuredContentSizeAtNewScale.height() / 2);
     1513
     1514                topLeftInDocumentCoordinates.scale(_scaleToRestore);
     1515                topLeftInDocumentCoordinates.moveBy(WebCore::FloatPoint(-_obscuredInsets.left, -_obscuredInsets.top));
     1516
     1517                changeContentOffsetBoundedInValidRange(_scrollView.get(), topLeftInDocumentCoordinates);
     1518            }
     1519        }
     1520
    15101521        needUpdateVisbleContentRects = YES;
    1511     }
    1512 
    1513     if (_needsToRestoreUnobscuredCenter && isTransactionAfterPageRestore) {
    1514         _needsToRestoreUnobscuredCenter = NO;
    1515 
    1516         if (areEssentiallyEqualAsFloat(contentZoomScale(self), _scaleToRestore)) {
    1517             CGRect unobscuredRect = UIEdgeInsetsInsetRect(self.bounds, _obscuredInsets);
    1518             WebCore::FloatSize unobscuredContentSizeAtNewScale(unobscuredRect.size.width / _scaleToRestore, unobscuredRect.size.height / _scaleToRestore);
    1519             WebCore::FloatPoint topLeftInDocumentCoordinates(_unobscuredCenterToRestore.x() - unobscuredContentSizeAtNewScale.width() / 2, _unobscuredCenterToRestore.y() - unobscuredContentSizeAtNewScale.height() / 2);
    1520 
    1521             topLeftInDocumentCoordinates.scale(_scaleToRestore);
    1522             topLeftInDocumentCoordinates.moveBy(WebCore::FloatPoint(-_obscuredInsets.left, -_obscuredInsets.top));
    1523 
    1524             changeContentOffsetBoundedInValidRange(_scrollView.get(), topLeftInDocumentCoordinates);
    1525             if (_gestureController)
    1526                 _gestureController->didRestoreScrollPosition();
    1527         }
    1528 
    1529         needUpdateVisbleContentRects = YES;
     1522
     1523        if (_gestureController)
     1524            _gestureController->didRestoreScrollPosition();
    15301525    }
    15311526
     
    15691564}
    15701565
    1571 - (void)_restorePageScrollPosition:(WebCore::FloatPoint)scrollPosition scrollOrigin:(WebCore::FloatPoint)scrollOrigin previousObscuredInset:(WebCore::FloatSize)obscuredInset scale:(double)scale
     1566- (void)_restorePageScrollPosition:(std::optional<WebCore::FloatPoint>)scrollPosition scrollOrigin:(WebCore::FloatPoint)scrollOrigin previousObscuredInset:(WebCore::FloatSize)obscuredInset scale:(double)scale
    15721567{
    15731568    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing)
     
    15771572        return;
    15781573
    1579     _needsToRestoreUnobscuredCenter = NO;
    1580     _needsToRestoreScrollPosition = YES;
    15811574    _firstTransactionIDAfterPageRestore = downcast<WebKit::RemoteLayerTreeDrawingAreaProxy>(*_page->drawingArea()).nextLayerTreeTransactionID();
    1582    
    1583     _scrollOffsetToRestore = WebCore::ScrollableArea::scrollOffsetFromPosition(WebCore::FloatPoint(scrollPosition), WebCore::toFloatSize(scrollOrigin));
     1575    if (scrollPosition)
     1576        _scrollOffsetToRestore = WebCore::ScrollableArea::scrollOffsetFromPosition(WebCore::FloatPoint(scrollPosition.value()), WebCore::toFloatSize(scrollOrigin));
     1577    else
     1578        _scrollOffsetToRestore = std::nullopt;
     1579
    15841580    _obscuredInsetWhenSaved = obscuredInset;
    15851581    _scaleToRestore = scale;
    15861582}
    15871583
    1588 - (void)_restorePageStateToUnobscuredCenter:(WebCore::FloatPoint)center scale:(double)scale
     1584- (void)_restorePageStateToUnobscuredCenter:(std::optional<WebCore::FloatPoint>)center scale:(double)scale
    15891585{
    15901586    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing)
     
    15941590        return;
    15951591
    1596     _needsToRestoreScrollPosition = NO;
    1597     _needsToRestoreUnobscuredCenter = YES;
    15981592    _firstTransactionIDAfterPageRestore = downcast<WebKit::RemoteLayerTreeDrawingAreaProxy>(*_page->drawingArea()).nextLayerTreeTransactionID();
    1599     _unobscuredCenterToRestore = center;
     1593    _unobscuredCenterToRestore = center.value();
     1594   
    16001595    _scaleToRestore = scale;
    16011596}
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewInternal.h

    r212459 r213590  
    8282- (void)_dynamicViewportUpdateChangedTargetToScale:(double)newScale position:(CGPoint)newScrollPosition nextValidLayerTreeTransactionID:(uint64_t)nextValidLayerTreeTransactionID;
    8383- (void)_couldNotRestorePageState;
    84 - (void)_restorePageScrollPosition:(WebCore::FloatPoint)scrollPosition scrollOrigin:(WebCore::FloatPoint)scrollOrigin previousObscuredInset:(WebCore::FloatSize)topInset scale:(double)scale;
    85 - (void)_restorePageStateToUnobscuredCenter:(WebCore::FloatPoint)center scale:(double)scale; // FIXME: needs scroll origin?
     84- (void)_restorePageScrollPosition:(std::optional<WebCore::FloatPoint>)scrollPosition scrollOrigin:(WebCore::FloatPoint)scrollOrigin previousObscuredInset:(WebCore::FloatSize)topInset scale:(double)scale;
     85- (void)_restorePageStateToUnobscuredCenter:(std::optional<WebCore::FloatPoint>)center scale:(double)scale; // FIXME: needs scroll origin?
    8686
    8787- (PassRefPtr<WebKit::ViewSnapshot>)_takeViewSnapshot;
  • trunk/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp

    r206256 r213590  
    7676}
    7777
     78WebCore::FloatPoint PageClientImpl::viewScrollPosition()
     79{
     80    return { };
     81}
     82
    7883WebCore::IntSize PageClientImpl::viewSize()
    7984{
  • trunk/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h

    r206256 r213590  
    5858    void setViewNeedsDisplay(const WebCore::Region&) override;
    5959    void requestScroll(const WebCore::FloatPoint& scrollPosition, const WebCore::IntPoint& scrollOrigin, bool isProgrammaticScroll) override;
     60    WebCore::FloatPoint viewScrollPosition() override;
    6061    WebCore::IntSize viewSize() override;
    6162    bool isViewWindowActive() override;
  • trunk/Source/WebKit2/UIProcess/PageClient.h

    r213584 r213590  
    101101    virtual void requestScroll(const WebCore::FloatPoint& scrollPosition, const WebCore::IntPoint& scrollOrigin, bool isProgrammaticScroll) = 0;
    102102
     103    // Return the current scroll position (not necessarily the same as the WebCore scroll position, because of scaling, insets etc.)
     104    virtual WebCore::FloatPoint viewScrollPosition() = 0;
     105
    103106    // Return the size of the view the page is associated with.
    104107    virtual WebCore::IntSize viewSize() = 0;
     
    295298    virtual void dynamicViewportUpdateChangedTarget(double newScale, const WebCore::FloatPoint& newScrollPosition, uint64_t transactionID) = 0;
    296299    virtual void couldNotRestorePageState() = 0;
    297     virtual void restorePageState(const WebCore::FloatPoint& scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatSize& obscuredInsetOnSave, double scale) = 0;
    298     virtual void restorePageCenterAndScale(const WebCore::FloatPoint& center, double scale) = 0;
     300    virtual void restorePageState(std::optional<WebCore::FloatPoint> scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatSize& obscuredInsetOnSave, double scale) = 0;
     301    virtual void restorePageCenterAndScale(std::optional<WebCore::FloatPoint> center, double scale) = 0;
    299302
    300303    virtual void startAssistingNode(const AssistedNodeInformation&, bool userIsInteracting, bool blurPreviousNode, API::Object* userData) = 0;
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp

    r213444 r213590  
    14361436}
    14371437
     1438WebCore::FloatPoint WebPageProxy::viewScrollPosition() const
     1439{
     1440    return m_pageClient.viewScrollPosition();
     1441}
     1442
    14381443void WebPageProxy::setSuppressVisibilityUpdates(bool flag)
    14391444{
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.h

    r213584 r213590  
    447447    void requestScroll(const WebCore::FloatPoint& scrollPosition, const WebCore::IntPoint& scrollOrigin, bool isProgrammaticScroll);
    448448   
     449    WebCore::FloatPoint viewScrollPosition() const;
     450
    449451    void setDelegatesScrolling(bool delegatesScrolling) { m_delegatesScrolling = delegatesScrolling; }
    450452    bool delegatesScrolling() const { return m_delegatesScrolling; }
     
    15121514    void dynamicViewportUpdateChangedTarget(double newTargetScale, const WebCore::FloatPoint& newScrollPosition, uint64_t dynamicViewportSizeUpdateID);
    15131515    void couldNotRestorePageState();
    1514     void restorePageState(const WebCore::FloatPoint& scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatSize& obscuredInsetOnSave, double scale);
    1515     void restorePageCenterAndScale(const WebCore::FloatPoint&, double scale);
     1516    void restorePageState(std::optional<WebCore::FloatPoint> scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatSize& obscuredInsetOnSave, double scale);
     1517    void restorePageCenterAndScale(std::optional<WebCore::FloatPoint>, double scale);
    15161518
    15171519    void didGetTapHighlightGeometries(uint64_t requestID, const WebCore::Color& color, const Vector<WebCore::FloatQuad>& geometries, const WebCore::IntSize& topLeftRadius, const WebCore::IntSize& topRightRadius, const WebCore::IntSize& bottomLeftRadius, const WebCore::IntSize& bottomRightRadius);
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in

    r213584 r213590  
    377377    DynamicViewportUpdateChangedTarget(double newTargetScale, WebCore::FloatPoint newScrollPosition, uint64_t dynamicViewportSizeUpdateID)
    378378    CouldNotRestorePageState()
    379     RestorePageState(WebCore::FloatPoint scrollPosition, WebCore::FloatPoint scrollOrigin, WebCore::FloatSize obscuredInsetOnSave, double scale)
    380     RestorePageCenterAndScale(WebCore::FloatPoint unobscuredCenter, double scale)
     379    RestorePageState(std::optional<WebCore::FloatPoint> scrollPosition, WebCore::FloatPoint scrollOrigin, WebCore::FloatSize obscuredInsetOnSave, double scale)
     380    RestorePageCenterAndScale(std::optional<WebCore::FloatPoint> unobscuredCenter, double scale)
    381381    DidGetTapHighlightGeometries(uint64_t requestID, WebCore::Color color, Vector<WebCore::FloatQuad> geometries, WebCore::IntSize topLeftRadius, WebCore::IntSize topRightRadius, WebCore::IntSize bottomLeftRadius, WebCore::IntSize bottomRightRadius)
    382382
  • trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h

    r213584 r213590  
    5252    void setViewNeedsDisplay(const WebCore::Region&) override;
    5353    void requestScroll(const WebCore::FloatPoint& scrollPosition, const WebCore::IntPoint& scrollOrigin, bool isProgrammaticScroll) override;
     54    WebCore::FloatPoint viewScrollPosition() override;
    5455    WebCore::IntSize viewSize() override;
    5556    bool isViewWindowActive() override;
     
    122123    void dynamicViewportUpdateChangedTarget(double newScale, const WebCore::FloatPoint& newScrollPosition, uint64_t transactionID) override;
    123124    void couldNotRestorePageState() override;
    124     void restorePageState(const WebCore::FloatPoint&, const WebCore::FloatPoint&, const WebCore::FloatSize&, double) override;
    125     void restorePageCenterAndScale(const WebCore::FloatPoint&, double) override;
     125    void restorePageState(std::optional<WebCore::FloatPoint>, const WebCore::FloatPoint&, const WebCore::FloatSize&, double) override;
     126    void restorePageCenterAndScale(std::optional<WebCore::FloatPoint>, double) override;
    126127
    127128    void startAssistingNode(const AssistedNodeInformation&, bool userIsInteracting, bool blurPreviousNode, API::Object* userData) override;
  • trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm

    r213584 r213590  
    138138}
    139139
     140WebCore::FloatPoint PageClientImpl::viewScrollPosition()
     141{
     142    if (UIScrollView *scroller = [m_contentView _scroller])
     143        return scroller.contentOffset;
     144
     145    return { };
     146}
     147
    140148IntSize PageClientImpl::viewSize()
    141149{
     
    527535}
    528536
    529 void PageClientImpl::restorePageState(const WebCore::FloatPoint& scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatSize& obscuredInsetOnSave, double scale)
     537void PageClientImpl::restorePageState(std::optional<WebCore::FloatPoint> scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatSize& obscuredInsetOnSave, double scale)
    530538{
    531539    [m_webView _restorePageScrollPosition:scrollPosition scrollOrigin:scrollOrigin previousObscuredInset:obscuredInsetOnSave scale:scale];
    532540}
    533541
    534 void PageClientImpl::restorePageCenterAndScale(const WebCore::FloatPoint& center, double scale)
     542void PageClientImpl::restorePageCenterAndScale(std::optional<WebCore::FloatPoint> center, double scale)
    535543{
    536544    [m_webView _restorePageStateToUnobscuredCenter:center scale:scale];
  • trunk/Source/WebKit2/UIProcess/ios/ViewGestureControllerIOS.mm

    r211929 r213590  
    195195        FloatSize swipeLayerSizeInDeviceCoordinates(liveSwipeViewFrame.size);
    196196        swipeLayerSizeInDeviceCoordinates.scale(deviceScaleFactor);
    197         if (snapshot->hasImage() && snapshot->size() == swipeLayerSizeInDeviceCoordinates && deviceScaleFactor == snapshot->deviceScaleFactor())
     197       
     198        BOOL shouldRestoreScrollPosition = targetItem->pageState().mainFrameState.shouldRestoreScrollPosition;
     199        IntPoint currentScrollPosition = roundedIntPoint(m_webPageProxy.viewScrollPosition());
     200
     201        if (snapshot->hasImage() && snapshot->size() == swipeLayerSizeInDeviceCoordinates && deviceScaleFactor == snapshot->deviceScaleFactor() && (shouldRestoreScrollPosition || (currentScrollPosition == snapshot->viewScrollPosition())))
    198202            [m_snapshotView layer].contents = snapshot->asLayerContents();
    199203        Color coreColor = snapshot->backgroundColor();
  • trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm

    r213584 r213590  
    907907}
    908908
    909 void WebPageProxy::restorePageState(const WebCore::FloatPoint& scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatSize& obscuredInsetOnSave, double scale)
     909void WebPageProxy::restorePageState(std::optional<WebCore::FloatPoint> scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatSize& obscuredInsetOnSave, double scale)
    910910{
    911911    m_pageClient.restorePageState(scrollPosition, scrollOrigin, obscuredInsetOnSave, scale);
    912912}
    913913
    914 void WebPageProxy::restorePageCenterAndScale(const WebCore::FloatPoint& center, double scale)
     914void WebPageProxy::restorePageCenterAndScale(std::optional<WebCore::FloatPoint> center, double scale)
    915915{
    916916    m_pageClient.restorePageCenterAndScale(center, scale);
  • trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.h

    r212669 r213590  
    6565    void setViewNeedsDisplay(const WebCore::Region&) override;
    6666    void requestScroll(const WebCore::FloatPoint& scrollPosition, const WebCore::IntPoint& scrollOrigin, bool isProgrammaticScroll) override;
     67    WebCore::FloatPoint viewScrollPosition() override;
    6768
    6869    WebCore::IntSize viewSize() override;
  • trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.mm

    r212669 r213590  
    127127}
    128128
     129WebCore::FloatPoint PageClientImpl::viewScrollPosition()
     130{
     131    return { };
     132}
     133
    129134IntSize PageClientImpl::viewSize()
    130135{
  • trunk/Source/WebKit2/UIProcess/mac/ViewSnapshotStore.h

    r206829 r213590  
    2828
    2929#include <WebCore/Color.h>
     30#include <WebCore/IntPoint.h>
    3031#include <WebCore/IntSize.h>
    3132#include <WebCore/IOSurface.h>
     
    7172    void setBackgroundColor(WebCore::Color color) { m_backgroundColor = color; }
    7273    WebCore::Color backgroundColor() const { return m_backgroundColor; }
     74   
     75    void setViewScrollPosition(WebCore::IntPoint scrollPosition) { m_viewScrollPosition = scrollPosition; }
     76    WebCore::IntPoint viewScrollPosition() const { return m_viewScrollPosition; }
    7377
    7478    void setDeviceScaleFactor(float deviceScaleFactor) { m_deviceScaleFactor = deviceScaleFactor; }
     
    105109    float m_deviceScaleFactor;
    106110    WebCore::Color m_backgroundColor;
     111    WebCore::IntPoint m_viewScrollPosition; // Scroll position at snapshot time. Integral to make comparison reliable.
    107112};
    108113
  • trunk/Source/WebKit2/UIProcess/mac/ViewSnapshotStore.mm

    r206829 r213590  
    121121    snapshot->setDeviceScaleFactor(webPageProxy.deviceScaleFactor());
    122122    snapshot->setBackgroundColor(webPageProxy.pageExtendedBackgroundColor());
     123    snapshot->setViewScrollPosition(WebCore::roundedIntPoint(webPageProxy.viewScrollPosition()));
    123124
    124125    item.setSnapshot(WTFMove(snapshot));
  • trunk/Source/WebKit2/WebProcess/WebCoreSupport/SessionStateConversion.cpp

    r208985 r213590  
    8686
    8787    frameState.scrollPosition = historyItem.scrollPosition();
     88    frameState.shouldRestoreScrollPosition = historyItem.shouldRestoreScrollPosition();
    8889    frameState.pageScaleFactor = historyItem.pageScaleFactor();
    8990
     
    162163
    163164    historyItem.setScrollPosition(frameState.scrollPosition);
     165    historyItem.setShouldRestoreScrollPosition(frameState.shouldRestoreScrollPosition);
    164166    historyItem.setPageScaleFactor(frameState.pageScaleFactor);
    165167
  • trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp

    r212557 r213590  
    12271227        if (m_frame->isMainFrame())
    12281228            m_frame->page()->restorePageState(*currentItem);
    1229         else if (!view->wasScrolledByUser())
     1229        else if (!view->wasScrolledByUser()) {
     1230            WTFLogAlways("WebFrameLoaderClient::restoreViewState restoring scroll position %d,%d", currentItem->scrollPosition().x(), currentItem->scrollPosition().y());
    12301231            view->setScrollPosition(currentItem->scrollPosition());
     1232        }
    12311233    }
    12321234#else
  • trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm

    r213584 r213590  
    313313        scalePage(boundedScale, IntPoint());
    314314
    315         m_drawingArea->setExposedContentRect(historyItem.exposedContentRect());
    316 
    317         send(Messages::WebPageProxy::RestorePageState(historyItem.scrollPosition(), frameView.scrollOrigin(), historyItem.obscuredInset(), boundedScale));
     315        std::optional<FloatPoint> scrollPosition;
     316        if (historyItem.shouldRestoreScrollPosition()) {
     317            m_drawingArea->setExposedContentRect(historyItem.exposedContentRect());
     318            scrollPosition = FloatPoint(historyItem.scrollPosition());
     319        }
     320        send(Messages::WebPageProxy::RestorePageState(scrollPosition, frameView.scrollOrigin(), historyItem.obscuredInset(), boundedScale));
    318321    } else {
    319322        IntSize oldContentSize = historyItem.contentSize();
     
    323326        double newScale = scaleAfterViewportWidthChange(historyItem.pageScaleFactor(), !historyItem.scaleIsInitial(), m_viewportConfiguration, currentMinimumLayoutSizeInScrollViewCoordinates.width(), newContentSize, oldContentSize, visibleHorizontalFraction);
    324327
    325         FloatPoint newCenter;
    326         if (!oldContentSize.isEmpty() && !newContentSize.isEmpty() && newContentSize != oldContentSize)
    327             newCenter = relativeCenterAfterContentSizeChange(historyItem.unobscuredContentRect(), oldContentSize, newContentSize);
    328         else
    329             newCenter = FloatRect(historyItem.unobscuredContentRect()).center();
    330 
    331         FloatSize unobscuredRectAtNewScale = frameView.customSizeForResizeEvent();
    332         unobscuredRectAtNewScale.scale(1 / newScale);
    333 
    334         FloatRect oldExposedRect = frameView.exposedContentRect();
    335         FloatRect adjustedExposedRect = adjustExposedRectForNewScale(oldExposedRect, m_page->pageScaleFactor(), newScale);
    336 
    337         FloatPoint oldCenter = adjustedExposedRect.center();
    338         adjustedExposedRect.move(newCenter - oldCenter);
     328        std::optional<FloatPoint> newCenter;
     329        if (historyItem.shouldRestoreScrollPosition()) {
     330            if (!oldContentSize.isEmpty() && !newContentSize.isEmpty() && newContentSize != oldContentSize)
     331                newCenter = relativeCenterAfterContentSizeChange(historyItem.unobscuredContentRect(), oldContentSize, newContentSize);
     332            else
     333                newCenter = FloatRect(historyItem.unobscuredContentRect()).center();
     334        }
    339335
    340336        scalePage(newScale, IntPoint());
    341 
    342337        send(Messages::WebPageProxy::RestorePageCenterAndScale(newCenter, newScale));
    343338    }
Note: See TracChangeset for help on using the changeset viewer.