Source/WebCore/ChangeLog

 12017-03-06 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 NOBODY (OOPS!).
 8
 9 Add Mac 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-04 Myles C. Maxfield <mmaxfield@apple.com>
250
351 Update CSSFontSelector's matching algorithm to understand ranges

Source/WebKit2/ChangeLog

 12017-03-07 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 NOBODY (OOPS!).
 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-04 Eric Carlson <eric.carlson@apple.com>
265
366 [iOS] The web process should inherit application state from UI process

Source/WebCore/history/HistoryItem.cpp

@@static void defaultNotifyHistoryItemChanged(HistoryItem*)
5656WEBCORE_EXPORT void (*notifyHistoryItemChanged)(HistoryItem*) = defaultNotifyHistoryItemChanged;
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)
6562{

@@HistoryItem::HistoryItem(const String& urlString, const String& title)
6966 : m_urlString(urlString)
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())
7771 , m_pruningReason(PruningReason::None)

@@HistoryItem::HistoryItem(const String& urlString, const String& title, const Str
8579 , m_title(title)
8680 , m_displayTitle(alternateTitle)
8781 , m_pageScaleFactor(0)
88  , m_lastVisitWasFailure(false)
89  , m_isTargetItem(false)
9082 , m_itemSequenceNumber(generateSequenceNumber())
9183 , m_documentSequenceNumber(generateSequenceNumber())
9284 , m_pruningReason(PruningReason::None)

@@void HistoryItem::clearScrollPosition()
271263 m_scrollPosition = IntPoint();
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{
276278 return m_pageScaleFactor;

Source/WebCore/history/HistoryItem.h

@@public:
102102 WEBCORE_EXPORT const IntPoint& scrollPosition() const;
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;
107110 WEBCORE_EXPORT void setPageScaleFactor(float);

@@private:
215218 String m_displayTitle;
216219
217220 IntPoint m_scrollPosition;
218  float m_pageScaleFactor;
 221 float m_pageScaleFactor { 0 }; // 0 indicates "unset".
219222 Vector<String> m_documentState;
220223
221224 ShouldOpenExternalURLsPolicy m_shouldOpenExternalURLsPolicy { ShouldOpenExternalURLsPolicy::ShouldNotAllow };
222225
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
230234 // clones of one another. Traversing history from one such HistoryItem to

Source/WebCore/loader/FrameLoader.cpp

@@void FrameLoader::loadInSameDocument(const URL& url, SerializedScriptValue* stat
10551055
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;
10611061 checkCompleted();

@@bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission, const S
28682868 && !m_frame.document()->isFrameSet();
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();
28742884 if (!view)

@@void FrameLoader::scrollToFragmentWithParentBoundary(const URL& url)
28802890 if (boundaryFrame)
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)
28862897 boundaryFrame->view()->setSafeToPropagateScrollToParent(true);

@@void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest& reque
30823093 setPolicyDocumentLoader(nullptr);
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())) {
30883099 if (Page* page = m_frame.page()) {

Source/WebCore/loader/FrameLoader.h

@@private:
334334 void continueFragmentScrollAfterNavigationPolicy(const ResourceRequest&, bool shouldContinue);
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();
340340

Source/WebCore/loader/HistoryController.cpp

@@void HistoryController::restoreScrollPositionAndViewState()
158158 // Don't restore scroll point on iOS as FrameLoaderClient::restoreViewState() does that.
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())
164164 page->setPageScaleFactor(m_currentItem->pageScaleFactor() * page->viewScaleFactor(), desiredScrollPosition);

@@bool HistoryController::shouldStopLoadingForHistoryItem(HistoryItem& targetItem)
291291// This includes recursion to handle loading into framesets properly
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
296298 // shouldGoToHistoryItem is a private delegate method. This is needed to fix:

@@void HistoryController::pushState(RefPtr<SerializedScriptValue>&& stateObject, c
853855 Page* page = m_frame.page();
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);
858862

@@void HistoryController::pushState(RefPtr<SerializedScriptValue>&& stateObject, c
861865 m_currentItem->setTitle(title);
862866 m_currentItem->setStateObject(WTFMove(stateObject));
863867 m_currentItem->setURLString(urlString);
 868 m_currentItem->setShouldRestoreScrollPosition(shouldRestoreScrollPosition);
864869
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());
 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));
868873

@@void HistoryController::replaceState(RefPtr<SerializedScriptValue>&& stateObject
878883 if (!m_currentItem)
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())
884889 m_currentItem->setURLString(urlString);

Source/WebCore/page/History.cpp

@@unsigned History::length() const
5959 return page->backForward().count();
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{
6488 m_lastStateObjectRequested = stateInternal();

Source/WebCore/page/History.h

@@public:
4141 static Ref<History> create(Frame& frame) { return adoptRef(*new History(frame)); }
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();
4655 void forward();

Source/WebCore/page/History.idl

2727 GenerateIsReachable=ImplFrame,
2828] interface History {
2929 readonly attribute unsigned long length;
 30 [SetterMayThrowException, GetterMayThrowException] attribute ScrollRestoration scrollRestoration;
3031 [CachedAttribute, Custom] readonly attribute SerializedScriptValue state;
3132
3233 [CallWith=Document, ForwardDeclareInHeader] void back();

3637 [Custom, MayThrowException] void pushState(any data, DOMString title, optional USVString? url = null);
3738 [Custom, MayThrowException] void replaceState(any data, DOMString title, optional USVString? url = null);
3839};
 40
 41enum ScrollRestoration { "auto", "manual" };

Source/WebKit2/Shared/SessionState.cpp

@@void FrameState::encode(IPC::Encoder& encoder) const
114114 encoder << itemSequenceNumber;
115115
116116 encoder << scrollPosition;
 117 encoder << shouldRestoreScrollPosition;
117118 encoder << pageScaleFactor;
118119
119120 encoder << httpBody;

@@bool FrameState::decode(IPC::Decoder& decoder, FrameState& result)
152153
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;
157160

Source/WebKit2/Shared/SessionState.h

@@struct FrameState {
9696 int64_t itemSequenceNumber;
9797
9898 WebCore::IntPoint scrollPosition;
 99 bool shouldRestoreScrollPosition;
99100 float pageScaleFactor;
100101
101102 std::optional<HTTPBody> httpBody;

Source/WebKit2/Shared/WebBackForwardListItem.h

@@public:
5252 uint64_t pageID() const { return m_pageID; }
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; }
5758 const String& url() const { return m_itemState.pageState.mainFrameState.urlString; }

Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm

@@@implementation WKWebView {
251251 std::optional<CGRect> _frozenVisibleContentRect;
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;
263261

@@- (void)_processDidExit
13691367 _needsResetViewStateAfterCommitLoadForMainFrame = NO;
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;
13761374 _hadDelayedUpdateVisibleContentRects = NO;

@@- (void)_didCommitLayerTree:(const WebKit::RemoteLayerTreeTransaction&)layerTree
14901488 needUpdateVisbleContentRects = YES;
14911489 }
14921490
1493  bool isTransactionAfterPageRestore = layerTreeTransaction.transactionID() >= _firstTransactionIDAfterPageRestore;
 1491 if (layerTreeTransaction.transactionID() >= _firstTransactionIDAfterPageRestore) {
 1492 if (_scrollOffsetToRestore) {
 1493 WebCore::FloatPoint scaledScrollOffset = _scrollOffsetToRestore.value();
 1494 _scrollOffsetToRestore = std::nullopt;
14941495
1495  if (_needsToRestoreScrollPosition && isTransactionAfterPageRestore) {
1496  _needsToRestoreScrollPosition = NO;
 1496 if (areEssentiallyEqualAsFloat(contentZoomScale(self), _scaleToRestore)) {
 1497 scaledScrollOffset.scale(_scaleToRestore);
 1498 WebCore::FloatPoint contentOffsetInScrollViewCoordinates = scaledScrollOffset - _obscuredInsetWhenSaved;
14971499
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();
 1500 changeContentOffsetBoundedInValidRange(_scrollView.get(), contentOffsetInScrollViewCoordinates);
 1501 _commitDidRestoreScrollPosition = YES;
 1502 }
15081503 }
1509 
1510  needUpdateVisbleContentRects = YES;
1511  }
15121504
1513  if (_needsToRestoreUnobscuredCenter && isTransactionAfterPageRestore) {
1514  _needsToRestoreUnobscuredCenter = NO;
 1505 if (_unobscuredCenterToRestore) {
 1506 WebCore::FloatPoint unobscuredCenterToRestore = _unobscuredCenterToRestore.value();
 1507 _unobscuredCenterToRestore = std::nullopt;
15151508
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);
 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);
15201513
1521  topLeftInDocumentCoordinates.scale(_scaleToRestore);
1522  topLeftInDocumentCoordinates.moveBy(WebCore::FloatPoint(-_obscuredInsets.left, -_obscuredInsets.top));
 1514 topLeftInDocumentCoordinates.scale(_scaleToRestore);
 1515 topLeftInDocumentCoordinates.moveBy(WebCore::FloatPoint(-_obscuredInsets.left, -_obscuredInsets.top));
15231516
1524  changeContentOffsetBoundedInValidRange(_scrollView.get(), topLeftInDocumentCoordinates);
1525  if (_gestureController)
1526  _gestureController->didRestoreScrollPosition();
 1517 changeContentOffsetBoundedInValidRange(_scrollView.get(), topLeftInDocumentCoordinates);
 1518 }
15271519 }
15281520
15291521 needUpdateVisbleContentRects = YES;
 1522
 1523 if (_gestureController)
 1524 _gestureController->didRestoreScrollPosition();
15301525 }
15311526
15321527 if (needUpdateVisbleContentRects)

@@- (void)_couldNotRestorePageState
15681563 _gestureController->didRestoreScrollPosition();
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)
15741569 return;

@@- (void)_restorePageScrollPosition:(WebCore::FloatPoint)scrollPosition scrollOri
15761571 if (![self usesStandardContentView])
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)
15911587 return;

@@- (void)_restorePageStateToUnobscuredCenter:(WebCore::FloatPoint)center scale:(d
15931589 if (![self usesStandardContentView])
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}
16021597

Source/WebKit2/UIProcess/API/Cocoa/WKWebViewInternal.h

@@struct PrintInfo;
8181
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;
8888

Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp

@@void PageClientImpl::requestScroll(const WebCore::FloatPoint&, const WebCore::In
7575 notImplemented();
7676}
7777
 78WebCore::FloatPoint PageClientImpl::viewScrollPosition()
 79{
 80 return { };
 81}
 82
7883WebCore::IntSize PageClientImpl::viewSize()
7984{
8085 auto* drawingArea = static_cast<DrawingAreaProxyImpl*>(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_viewWidget))->drawingArea());

Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h

@@private:
5757 std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy() override;
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;
6263 bool isViewFocused() override;

Source/WebKit2/UIProcess/PageClient.h

@@public:
100100 // Tell the view to scroll to the given position, and whether this was a programmatic scroll.
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;
105108

@@public:
293296
294297 virtual void dynamicViewportUpdateChangedTarget(double newScale, const WebCore::FloatPoint& newScrollPosition, uint64_t transactionID) = 0;
295298 virtual void couldNotRestorePageState() = 0;
296  virtual void restorePageState(const WebCore::FloatPoint& scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatSize& obscuredInsetOnSave, double scale) = 0;
297  virtual void restorePageCenterAndScale(const WebCore::FloatPoint& center, double scale) = 0;
 299 virtual void restorePageState(std::optional<WebCore::FloatPoint> scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatSize& obscuredInsetOnSave, double scale) = 0;
 300 virtual void restorePageCenterAndScale(std::optional<WebCore::FloatPoint> center, double scale) = 0;
298301
299302 virtual void startAssistingNode(const AssistedNodeInformation&, bool userIsInteracting, bool blurPreviousNode, API::Object* userData) = 0;
300303 virtual void stopAssistingNode() = 0;

Source/WebKit2/UIProcess/WebPageProxy.cpp

@@void WebPageProxy::requestScroll(const FloatPoint& scrollPosition, const IntPoin
14331433 m_pageClient.requestScroll(scrollPosition, scrollOrigin, isProgrammaticScroll);
14341434}
14351435
 1436WebCore::FloatPoint WebPageProxy::viewScrollPosition() const
 1437{
 1438 return m_pageClient.viewScrollPosition();
 1439}
 1440
14361441void WebPageProxy::setSuppressVisibilityUpdates(bool flag)
14371442{
14381443 if (m_suppressVisibilityUpdates == flag)

Source/WebKit2/UIProcess/WebPageProxy.h

@@public:
446446 void setViewNeedsDisplay(const WebCore::Region&);
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; }
451453

@@private:
15111513
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);
15181520

Source/WebKit2/UIProcess/WebPageProxy.messages.in

@@messages -> WebPageProxy {
376376#if PLATFORM(IOS)
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
383383 StartAssistingNode(struct WebKit::AssistedNodeInformation information, bool userIsInteracting, bool blurPreviousNode, WebKit::UserData userData)

Source/WebKit2/UIProcess/ios/PageClientImplIOS.h

@@private:
5151 std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy() override;
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;
5657 bool isViewFocused() override;

@@private:
121122
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;
128129 void stopAssistingNode() override;

Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm

@@void PageClientImpl::requestScroll(const FloatPoint& scrollPosition, const IntPo
137137 [m_webView _scrollToContentScrollPosition:scrollPosition scrollOrigin:scrollOrigin];
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{
142150 if (UIScrollView *scroller = [m_contentView _scroller])

@@void PageClientImpl::couldNotRestorePageState()
521529 [m_webView _couldNotRestorePageState];
522530}
523531
524 void PageClientImpl::restorePageState(const WebCore::FloatPoint& scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatSize& obscuredInsetOnSave, double scale)
 532void PageClientImpl::restorePageState(std::optional<WebCore::FloatPoint> scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatSize& obscuredInsetOnSave, double scale)
525533{
526534 [m_webView _restorePageScrollPosition:scrollPosition scrollOrigin:scrollOrigin previousObscuredInset:obscuredInsetOnSave scale:scale];
527535}
528536
529 void PageClientImpl::restorePageCenterAndScale(const WebCore::FloatPoint& center, double scale)
 537void PageClientImpl::restorePageCenterAndScale(std::optional<WebCore::FloatPoint> center, double scale)
530538{
531539 [m_webView _restorePageStateToUnobscuredCenter:center scale:scale];
532540}

Source/WebKit2/UIProcess/ios/ViewGestureControllerIOS.mm

@@void ViewGestureController::beginSwipeGesture(_UINavigationInteractiveTransition
194194 float deviceScaleFactor = m_webPageProxy.deviceScaleFactor();
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();
200204 if (coreColor.isValid())

Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm

@@void WebPageProxy::couldNotRestorePageState()
906906 m_pageClient.couldNotRestorePageState();
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);
917917}

Source/WebKit2/UIProcess/mac/PageClientImpl.h

@@private:
6464 std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy() override;
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;
6970 bool isViewWindowActive() override;

Source/WebKit2/UIProcess/mac/PageClientImpl.mm

@@void PageClientImpl::requestScroll(const FloatPoint& scrollPosition, const IntPo
126126 ASSERT_NOT_REACHED();
127127}
128128
 129WebCore::FloatPoint PageClientImpl::viewScrollPosition()
 130{
 131 return { };
 132}
 133
129134IntSize PageClientImpl::viewSize()
130135{
131136 return IntSize([m_view bounds].size);

Source/WebKit2/UIProcess/mac/ViewSnapshotStore.h

2727#define ViewSnapshotStore_h
2828
2929#include <WebCore/Color.h>
 30#include <WebCore/IntPoint.h>
3031#include <WebCore/IntSize.h>
3132#include <WebCore/IOSurface.h>
3233#include <wtf/ListHashSet.h>

@@public:
7071
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; }
7579 float deviceScaleFactor() const { return m_deviceScaleFactor; }

@@private:
104108 uint64_t m_renderTreeSize;
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
109114class ViewSnapshotStore {

Source/WebKit2/UIProcess/mac/ViewSnapshotStore.mm

@@void ViewSnapshotStore::recordSnapshot(WebPageProxy& webPageProxy, WebBackForwar
120120 snapshot->setRenderTreeSize(webPageProxy.renderTreeSize());
121121 snapshot->setDeviceScaleFactor(webPageProxy.deviceScaleFactor());
122122 snapshot->setBackgroundColor(webPageProxy.pageExtendedBackgroundColor());
 123 snapshot->setViewScrollPosition(WebCore::roundedIntPoint(webPageProxy.viewScrollPosition()));
123124
124125 item.setSnapshot(WTFMove(snapshot));
125126}

Source/WebKit2/WebProcess/WebCoreSupport/SessionStateConversion.cpp

@@static FrameState toFrameState(const HistoryItem& historyItem)
8585 frameState.itemSequenceNumber = historyItem.itemSequenceNumber();
8686
8787 frameState.scrollPosition = historyItem.scrollPosition();
 88 frameState.shouldRestoreScrollPosition = historyItem.shouldRestoreScrollPosition();
8889 frameState.pageScaleFactor = historyItem.pageScaleFactor();
8990
9091 if (FormData* formData = const_cast<HistoryItem&>(historyItem).formData()) {

@@static void applyFrameState(HistoryItem& historyItem, const FrameState& frameSta
161162 historyItem.setItemSequenceNumber(frameState.itemSequenceNumber);
162163
163164 historyItem.setScrollPosition(frameState.scrollPosition);
 165 historyItem.setShouldRestoreScrollPosition(frameState.shouldRestoreScrollPosition);
164166 historyItem.setPageScaleFactor(frameState.pageScaleFactor);
165167
166168 if (frameState.httpBody) {

Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp

@@void WebFrameLoaderClient::restoreViewState()
12261226 if (FrameView* view = frame.view()) {
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
12331235 // Inform the UI process of the scale factor.

Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm

@@void WebPage::restorePageState(const HistoryItem& historyItem)
312312 float boundedScale = std::min<float>(m_viewportConfiguration.maximumScale(), std::max<float>(m_viewportConfiguration.minimumScale(), historyItem.pageScaleFactor()));
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();
320323 IntSize newContentSize = frameView.contentsSize();

@@void WebPage::restorePageState(const HistoryItem& historyItem)
322325
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 }
344339}

LayoutTests/ChangeLog

 12017-03-06 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 NOBODY (OOPS!).
 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-04 Myles C. Maxfield <mmaxfield@apple.com>
223
324 Update CSSFontSelector's matching algorithm to understand ranges

LayoutTests/imported/w3c/ChangeLog

 12017-03-06 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 NOBODY (OOPS!).
 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-04 Chris Dumez <cdumez@apple.com>
217
318 Rebaseline W3C test after r213412.

LayoutTests/TestExpectations

@@fast/viewport/ios [ Skip ]
2525fast/visual-viewport/ios/ [ Skip ]
2626fast/events/ios [ Skip ]
2727fast/events/touch/ios [ Skip ]
 28fast/history/ios [ Skip ]
2829fast/scrolling/ios [ Skip ]
2930scrollingcoordinator/ios [ Skip ]
3031fast/content-observation [ Skip ]

@@webkit.org/b/168175 imported/w3c/web-platform-tests/html/semantics/embedded-cont
10481049webkit.org/b/168175 imported/w3c/web-platform-tests/html/browsers/browsing-the-web/history-traversal/same-url.html [ Pass Failure ]
10491050webkit.org/b/168175 imported/w3c/web-platform-tests/html/browsers/offline/browser-state/navigator_online_online.html [ Pass Failure ]
10501051webkit.org/b/168175 imported/w3c/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-download-click.html [ Timeout Pass ]
 1052webkit.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 ]
10511053
10521054webkit.org/b/168066 performance-api/performance-now-api.html [ Pass Failure ]
10531055webkit.org/b/168005 performance-api/performance-now-time-origin-in-worker.html [ Pass Failure ]

LayoutTests/fast/dom/Window/window-appendages-cleared-expected.txt

@@PASS history.go == "LEFTOVER" is false
44PASS history.length == "LEFTOVER" is false
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
910PASS location.assign == "LEFTOVER" is false

LayoutTests/fast/history/history-scroll-restoration-attribute-expected.txt

 1Tests the history.scrollRestoration attribute
 2
 3On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 4
 5
 6PASS 'scrollRestoration' in history is true
 7PASS history.scrollRestoration is "auto"
 8PASS history.scrollRestoration is "manual"
 9PASS history.scrollRestoration is "manual"
 10PASS history.scrollRestoration is "auto"
 11PASS successfullyParsed is true
 12
 13TEST COMPLETE
 14

LayoutTests/fast/history/history-scroll-restoration-attribute.html

 1<html>
 2<head>
 3<script src="../../resources/js-test-pre.js"></script>
 4</head>
 5<body>
 6<script>
 7 description("Tests the history.scrollRestoration attribute");
 8
 9 if (window.testRunner)
 10 testRunner.clearBackForwardList();
 11
 12 shouldBeTrue("'scrollRestoration' in history");
 13
 14 history.scrollRestoration = 'auto';
 15 shouldBeEqualToString('history.scrollRestoration', 'auto');
 16
 17 history.scrollRestoration = 'manual';
 18 shouldBeEqualToString('history.scrollRestoration', 'manual');
 19
 20 history.scrollRestoration = 'bananas';
 21 shouldBeEqualToString('history.scrollRestoration', 'manual');
 22
 23 history.scrollRestoration = 'auto';
 24 shouldBeEqualToString('history.scrollRestoration', 'auto');
 25
 26</script>
 27<script src="../../resources/js-test-post.js"></script>
 28</body>
 29</html>

LayoutTests/fast/history/history-scroll-restoration-expected.txt

 1Tests that history.scrollRestoration works for same-document navigations
 2
 3On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 4
 5
 6PASS 'scrollRestoration' in history is true
 7PASS history.scrollRestoration is "auto"
 8PASS window.scrollX is 123
 9PASS window.scrollY is 456
 10PASS history.scrollRestoration is "manual"
 11PASS window.scrollX is 333
 12PASS window.scrollY is 555
 13PASS successfullyParsed is true
 14
 15TEST COMPLETE
 16

LayoutTests/fast/history/history-scroll-restoration.html

 1<html>
 2<head>
 3<script src="../../resources/js-test-pre.js"></script>
 4<style>
 5 body {
 6 height: 2000px;
 7 width: 2000px;
 8 }
 9</style>
 10</head>
 11<body>
 12<script>
 13 var jsTestIsAsync = true;
 14
 15 description("Tests that history.scrollRestoration works for same-document navigations");
 16
 17 if (window.testRunner)
 18 testRunner.clearBackForwardList();
 19
 20 shouldBeTrue("'scrollRestoration' in history");
 21
 22 // Can't create history entries inside the onload handler.
 23 window.setTimeout(testAutoScrollRestoration, 0);
 24
 25 function testAutoScrollRestoration()
 26 {
 27 history.scrollRestoration = 'auto';
 28 shouldBeEqualToString('history.scrollRestoration', 'auto');
 29
 30 window.scrollTo(123, 456);
 31 history.pushState(null, '', '#1');
 32 window.scrollTo(0, 0);
 33 history.back();
 34
 35 window.setTimeout(function () {
 36 shouldBe('window.scrollX', '123');
 37 shouldBe('window.scrollY', '456');
 38
 39 testManualScrollRestoration();
 40 }, 0);
 41 }
 42
 43 function testManualScrollRestoration()
 44 {
 45 history.scrollRestoration = 'manual';
 46 shouldBeEqualToString('history.scrollRestoration', 'manual');
 47
 48 window.scrollTo(234, 567);
 49 history.pushState(null, '', '#2');
 50 window.scrollTo(333, 555);
 51 history.back();
 52
 53 window.setTimeout(function() {
 54 shouldBe('window.scrollX', '333');
 55 shouldBe('window.scrollY', '555');
 56 window.scrollTo(0, 0);
 57 finishJSTest();
 58 }, 0);
 59 }
 60
 61</script>
 62<script src="../../resources/js-test-post.js"></script>
 63</body>
 64</html>

LayoutTests/fast/history/ios/history-scroll-restoration-expected.txt

 1Tests that history.scrollRestoration works for same-document navigations
 2
 3On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 4
 5
 6PASS 'scrollRestoration' in history is true
 7PASS history.scrollRestoration is "auto"
 8PASS window.scrollX is 123
 9PASS window.scrollY is 456
 10PASS history.scrollRestoration is "manual"
 11PASS window.scrollX is 333
 12PASS window.scrollY is 555
 13PASS successfullyParsed is true
 14
 15TEST COMPLETE
 16

LayoutTests/fast/history/ios/history-scroll-restoration.html

 1<html>
 2<head>
 3<script src="../../../resources/js-test-pre.js"></script>
 4<style>
 5 body {
 6 height: 2000px;
 7 width: 2000px;
 8 }
 9</style>
 10</head>
 11<body>
 12<script>
 13 var jsTestIsAsync = true;
 14
 15 description("Tests that history.scrollRestoration works for same-document navigations");
 16
 17 if (window.testRunner)
 18 testRunner.clearBackForwardList();
 19
 20 shouldBeTrue("'scrollRestoration' in history");
 21
 22 // Can't create history entries inside the onload handler.
 23 window.setTimeout(testAutoScrollRestoration, 0);
 24
 25 function waitForPresentationUpdateUIScript()
 26 {
 27 return `(function() {
 28 uiController.doAfterPresentationUpdate(function() {
 29 uiController.uiScriptComplete();
 30 });
 31 })()`;
 32 }
 33
 34 function testAutoScrollRestoration()
 35 {
 36 history.scrollRestoration = 'auto';
 37 shouldBeEqualToString('history.scrollRestoration', 'auto');
 38
 39 window.scrollTo(123, 456);
 40 history.pushState(null, '', '#1');
 41 window.scrollTo(0, 0);
 42 history.back();
 43
 44 testRunner.runUIScript(waitForPresentationUpdateUIScript(), function () {
 45 shouldBe('window.scrollX', '123');
 46 shouldBe('window.scrollY', '456');
 47
 48 testManualScrollRestoration();
 49 });
 50 }
 51
 52 function testManualScrollRestoration()
 53 {
 54 history.scrollRestoration = 'manual';
 55 shouldBeEqualToString('history.scrollRestoration', 'manual');
 56
 57 window.scrollTo(234, 567);
 58 history.pushState(null, '', '#2');
 59 window.scrollTo(333, 555);
 60 history.back();
 61
 62 testRunner.runUIScript(waitForPresentationUpdateUIScript(), function () {
 63 shouldBe('window.scrollX', '333');
 64 shouldBe('window.scrollY', '555');
 65
 66 window.scrollTo(0, 0);
 67 finishJSTest();
 68 });
 69 }
 70
 71</script>
 72<script src="../../../resources/js-test-post.js"></script>
 73</body>
 74</html>

LayoutTests/imported/w3c/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-basic-expected.txt

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

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

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
6 
7 TIMEOUT Manual scroll restoration should take precedent over scrolling to fragment in cross origin navigation Test timed out
 4PASS Manual scroll restoration should take precedent over scrolling to fragment in cross origin navigation
85

LayoutTests/imported/w3c/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin-expected.txt

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

LayoutTests/imported/w3c/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc-expected.txt

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

LayoutTests/platform/ios-simulator-wk2/TestExpectations

66# Platform-specific directories. Skipped globally, then re-enabled here.
77#//////////////////////////////////////////////////////////////////////////////////////////
88
 9fast/history/ios [ Pass ]
910fast/scrolling/ios [ Pass ]
1011fast/viewport/ios [ Pass ]
1112fast/visual-viewport/ios/ [ Pass ]

@@fast/history/form-submit-in-frame.html
783784fast/history/gesture-before-onload-form-submit.html
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
788790fast/images/animate-list-item-image-assertion.html

LayoutTests/platform/ios-simulator/TestExpectations

@@webkit.org/b/152935 fast/scrolling/scroll-position-on-reload-rtl.html [ Failure
24392439
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
24442446# displaylist tests are flaky on ios-simulator wk2