summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core')
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.cc57
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_view.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/frame/root_frame_viewport.cc103
-rw-r--r--chromium/third_party/blink/renderer/core/frame/root_frame_viewport.h13
-rw-r--r--chromium/third_party/blink/renderer/core/frame/visual_viewport.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/visual_viewport.h13
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_loader.cc78
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_loader.h2
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h3
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h1
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h11
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollable_area.h13
17 files changed, 215 insertions, 149 deletions
diff --git a/chromium/third_party/blink/renderer/core/dom/document.cc b/chromium/third_party/blink/renderer/core/dom/document.cc
index 71bf6c19867..6a969b812da 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document.cc
@@ -2927,6 +2927,46 @@ void Document::UpdateStyleAndLayoutTreeForNode(const Node* node) {
UpdateStyleAndLayoutTree();
}
+void Document::ApplyScrollRestorationLogic() {
+ // If we're restoring a scroll position from history, that takes precedence
+ // over scrolling to the anchor in the URL.
+ View()->InvokeFragmentAnchor();
+ auto& frame_loader = GetFrame()->Loader();
+ auto& document_loader = *frame_loader.GetDocumentLoader();
+ if (frame_->IsLoading() &&
+ !FrameLoader::NeedsHistoryItemRestore(document_loader.LoadType()))
+ return;
+ auto* history_item = frame_loader.GetDocumentLoader()->GetHistoryItem();
+ if (!history_item || !history_item->GetViewState())
+ return;
+ bool should_restore_scroll =
+ history_item->ScrollRestorationType() != kScrollRestorationManual;
+ auto& scroll_offset = history_item->GetViewState()->scroll_offset_;
+ // This tries to balance:
+ // 1. restoring as soon as possible.
+ // 2. not overriding user scroll (TODO(majidvp): also respect user scale).
+ // 3. detecting clamping to avoid repeatedly popping the scroll position down
+ // as the page height increases.
+ // 4. ignoring clamp detection if scroll state is not being restored, if load
+ // is complete, or if the navigation is same-document (as the new page may
+ // be smaller than the previous page).
+ bool can_restore_without_clamping =
+ View()->LayoutViewport()->ClampScrollOffset(scroll_offset) ==
+ scroll_offset;
+ bool can_restore_without_annoying_user =
+ !document_loader.GetInitialScrollState().was_scrolled_by_user &&
+ (can_restore_without_clamping || !frame_->IsLoading() ||
+ !should_restore_scroll);
+ if (!can_restore_without_annoying_user)
+ return;
+ frame_loader.RestoreScrollPositionAndViewState();
+ if (View()->GetScrollableArea()->ApplyPendingHistoryRestoreScrollOffset()) {
+ if (ScrollingCoordinator* scrolling_coordinator =
+ View()->GetFrame().GetPage()->GetScrollingCoordinator())
+ scrolling_coordinator->FrameViewRootLayerDidChange(View());
+ }
+}
+
void Document::UpdateStyleAndLayoutTreeForSubtree(const Node* node) {
DCHECK(node);
if (!node->InActiveDocument()) {
@@ -2979,6 +3019,8 @@ void Document::UpdateStyleAndLayout(ForcedLayoutStatus status) {
if (Lifecycle().GetState() < DocumentLifecycle::kLayoutClean)
Lifecycle().AdvanceTo(DocumentLifecycle::kLayoutClean);
+ ApplyScrollRestorationLogic();
+
if (LocalFrameView* frame_view_anchored = View())
frame_view_anchored->PerformScrollAnchoringAdjustments();
@@ -2993,11 +3035,6 @@ void Document::LayoutUpdated() {
DCHECK(GetFrame());
DCHECK(View());
- // If we're restoring a scroll position from history, that takes precedence
- // over scrolling to the anchor in the URL.
- View()->InvokeFragmentAnchor();
- GetFrame()->Loader().RestoreScrollPositionAndViewState();
-
// Plugins can run script inside layout which can detach the page.
// TODO(dcheng): Does it make sense to do any of this work if detached?
if (GetFrame()) {
@@ -4101,6 +4138,16 @@ bool Document::CheckCompletedInternal() {
}
}
+ if (auto* view = View()) {
+ if (view->GetFragmentAnchor()) {
+ // Schedule an animation frame to process fragment anchors. The frame
+ // can't be scheduled when the fragment anchor is set because, per spec,
+ // we must wait for the document to be loaded before invoking fragment
+ // anchors.
+ View()->ScheduleAnimation();
+ }
+ }
+
return true;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/document.h b/chromium/third_party/blink/renderer/core/dom/document.h
index ee2f8012b78..b36d9bf62b3 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.h
+++ b/chromium/third_party/blink/renderer/core/dom/document.h
@@ -1630,6 +1630,8 @@ class CORE_EXPORT Document : public ContainerNode,
return use_count_fragment_directive_;
}
+ void ApplyScrollRestorationLogic();
+
protected:
void ClearXMLVersion() { xml_version_ = String(); }
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_view.cc b/chromium/third_party/blink/renderer/core/frame/local_frame_view.cc
index b48fd035e1e..6b02303b31e 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -455,6 +455,13 @@ void LocalFrameView::FrameRectsChanged(const IntRect& old_rect) {
if (frame_->IsMainFrame())
frame_->GetPage()->GetVisualViewport().MainFrameDidChangeSize();
GetFrame().Loader().RestoreScrollPositionAndViewState();
+ if (GetScrollableArea()) {
+ if (GetScrollableArea()->ApplyPendingHistoryRestoreScrollOffset()) {
+ if (ScrollingCoordinator* scrolling_coordinator =
+ GetFrame().GetPage()->GetScrollingCoordinator())
+ scrolling_coordinator->FrameViewRootLayerDidChange(this);
+ }
+ }
}
}
@@ -1368,11 +1375,11 @@ void LocalFrameView::ProcessUrlFragment(const KURL& url,
if (anchor) {
fragment_anchor_ = anchor;
fragment_anchor_->Installed();
-
- // Layout needs to be clean for scrolling but if layout is needed, we'll
- // invoke after layout is completed so no need to do it here.
- if (!NeedsLayout())
- InvokeFragmentAnchor();
+ // Post-load, same-document navigations need to schedule a frame in which
+ // the fragment anchor will be invoked. It will be done after layout as
+ // part of the lifecycle.
+ if (same_document_navigation)
+ ScheduleAnimation();
}
}
@@ -1458,9 +1465,6 @@ void LocalFrameView::HandleLoadCompleted() {
// reduce the size of the frame.
if (auto_size_info_)
auto_size_info_->AutoSizeIfNeeded();
-
- if (fragment_anchor_)
- fragment_anchor_->DidCompleteLoad();
}
void LocalFrameView::ClearLayoutSubtreeRoot(const LayoutObject& root) {
@@ -2895,6 +2899,10 @@ void LocalFrameView::UpdateStyleAndLayoutIfNeededRecursive() {
if (Lifecycle().GetState() < DocumentLifecycle::kLayoutClean)
Lifecycle().AdvanceTo(DocumentLifecycle::kLayoutClean);
+ // If we're restoring a scroll position from history, that takes precedence
+ // over scrolling to the anchor in the URL.
+ frame_->GetDocument()->ApplyScrollRestorationLogic();
+
if (AXObjectCache* cache = GetFrame().GetDocument()->ExistingAXObjectCache())
cache->ProcessUpdatesAfterLayout(*GetFrame().GetDocument());
diff --git a/chromium/third_party/blink/renderer/core/frame/root_frame_viewport.cc b/chromium/third_party/blink/renderer/core/frame/root_frame_viewport.cc
index 20c0849668e..af7fd711c54 100644
--- a/chromium/third_party/blink/renderer/core/frame/root_frame_viewport.cc
+++ b/chromium/third_party/blink/renderer/core/frame/root_frame_viewport.cc
@@ -8,6 +8,7 @@
#include "cc/input/snap_selection_strategy.h"
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/scroll_anchor.h"
#include "third_party/blink/renderer/core/page/scrolling/snap_coordinator.h"
@@ -48,7 +49,7 @@ FloatRect GetUserScrollableRect(const ScrollableArea& area) {
} // namespace
RootFrameViewport::RootFrameViewport(ScrollableArea& visual_viewport,
ScrollableArea& layout_viewport)
- : visual_viewport_(visual_viewport) {
+ : visual_viewport_(visual_viewport), should_restore_scroll_(false) {
SetLayoutViewport(layout_viewport);
}
@@ -94,15 +95,15 @@ PhysicalRect RootFrameViewport::RootContentsToLayoutViewportContents(
void RootFrameViewport::RestoreToAnchor(const ScrollOffset& target_offset) {
// Clamp the scroll offset of each viewport now so that we force any invalid
// offsets to become valid so we can compute the correct deltas.
- VisualViewport().SetScrollOffset(VisualViewport().GetScrollOffset(),
+ GetVisualViewport().SetScrollOffset(GetVisualViewport().GetScrollOffset(),
kProgrammaticScroll);
LayoutViewport().SetScrollOffset(LayoutViewport().GetScrollOffset(),
kProgrammaticScroll);
ScrollOffset delta = target_offset - GetScrollOffset();
- VisualViewport().SetScrollOffset(VisualViewport().GetScrollOffset() + delta,
- kProgrammaticScroll);
+ GetVisualViewport().SetScrollOffset(
+ GetVisualViewport().GetScrollOffset() + delta, kProgrammaticScroll);
delta = target_offset - GetScrollOffset();
@@ -120,8 +121,8 @@ void RootFrameViewport::RestoreToAnchor(const ScrollOffset& target_offset) {
kProgrammaticScroll);
delta = target_offset - GetScrollOffset();
- VisualViewport().SetScrollOffset(VisualViewport().GetScrollOffset() + delta,
- kProgrammaticScroll);
+ GetVisualViewport().SetScrollOffset(
+ GetVisualViewport().GetScrollOffset() + delta, kProgrammaticScroll);
}
void RootFrameViewport::DidUpdateVisualViewport() {
@@ -168,7 +169,7 @@ void RootFrameViewport::UpdateScrollAnimator() {
}
ScrollOffset RootFrameViewport::ScrollOffsetFromScrollAnimators() const {
- return VisualViewport().GetScrollAnimator().CurrentOffset() +
+ return GetVisualViewport().GetScrollAnimator().CurrentOffset() +
LayoutViewport().GetScrollAnimator().CurrentOffset();
}
@@ -176,7 +177,7 @@ IntRect RootFrameViewport::VisibleContentRect(
IncludeScrollbarsInRect scrollbar_inclusion) const {
return IntRect(
IntPoint(ScrollOffsetInt()),
- VisualViewport().VisibleContentRect(scrollbar_inclusion).Size());
+ GetVisualViewport().VisibleContentRect(scrollbar_inclusion).Size());
}
PhysicalRect RootFrameViewport::VisibleScrollSnapportRect(
@@ -190,9 +191,9 @@ PhysicalRect RootFrameViewport::VisibleScrollSnapportRect(
PhysicalRect visual_rect_in_content(
PhysicalOffset::FromFloatSizeRound(
LayoutViewport().GetScrollOffset() +
- VisualViewport().GetScrollAnimator().CurrentOffset()),
+ GetVisualViewport().GetScrollAnimator().CurrentOffset()),
PhysicalSize(
- VisualViewport().VisibleContentRect(scrollbar_inclusion).Size()));
+ GetVisualViewport().VisibleContentRect(scrollbar_inclusion).Size()));
PhysicalRect visible_scroll_snapport =
Intersection(visual_rect_in_content, frame_rect_in_content);
@@ -241,6 +242,50 @@ IntRect RootFrameViewport::ScrollCornerRect() const {
return LayoutViewport().ScrollCornerRect();
}
+bool RootFrameViewport::ApplyPendingHistoryRestoreScrollOffset() {
+ if (!pending_view_state_)
+ return false;
+ bool should_restore_scale = pending_view_state_->page_scale_factor_;
+ if (should_restore_scroll_) {
+ // TODO(pnoland): attempt to restore the anchor in more places than this.
+ // Anchor-based restore should allow for earlier restoration.
+ bool did_restore = LayoutViewport().RestoreScrollAnchor(
+ {pending_view_state_->scroll_anchor_data_.selector_,
+ LayoutPoint(pending_view_state_->scroll_anchor_data_.offset_.x,
+ pending_view_state_->scroll_anchor_data_.offset_.y),
+ pending_view_state_->scroll_anchor_data_.simhash_});
+ if (!did_restore) {
+ LayoutViewport().SetScrollOffset(pending_view_state_->scroll_offset_,
+ kProgrammaticScroll);
+ }
+ }
+ // For main frame restore scale and visual viewport position
+ ScrollOffset visual_viewport_offset(
+ pending_view_state_->visual_viewport_scroll_offset_);
+ // If the visual viewport's offset is (-1, -1) it means the history item
+ // is an old version of HistoryItem so distribute the scroll between
+ // the main frame and the visual viewport as best as we can.
+ if (visual_viewport_offset.Width() == -1 &&
+ visual_viewport_offset.Height() == -1) {
+ visual_viewport_offset = pending_view_state_->scroll_offset_ -
+ LayoutViewport().GetScrollOffset();
+ }
+ auto* visual_viewport = static_cast<VisualViewport*>(&GetVisualViewport());
+ if (should_restore_scale && should_restore_scroll_) {
+ visual_viewport->SetScaleAndLocation(
+ pending_view_state_->page_scale_factor_,
+ visual_viewport->IsPinchGestureActive(),
+ FloatPoint(visual_viewport_offset));
+ } else if (should_restore_scale) {
+ visual_viewport->SetScale(pending_view_state_->page_scale_factor_);
+ } else if (should_restore_scroll_) {
+ visual_viewport->SetLocation(FloatPoint(visual_viewport_offset));
+ }
+ should_restore_scroll_ = false;
+ pending_view_state_.reset();
+ return true;
+}
+
void RootFrameViewport::SetScrollOffset(const ScrollOffset& offset,
ScrollType scroll_type,
ScrollBehavior scroll_behavior,
@@ -279,7 +324,7 @@ ScrollOffset RootFrameViewport::ClampToUserScrollableOffset(
const ScrollOffset& offset) const {
ScrollOffset scroll_offset = offset;
FloatRect user_scrollable = GetUserScrollableRect(LayoutViewport()) +
- GetUserScrollableRect(VisualViewport());
+ GetUserScrollableRect(GetVisualViewport());
scroll_offset.SetWidth(clampTo(scroll_offset.Width(), user_scrollable.X(),
user_scrollable.MaxX()));
scroll_offset.SetHeight(clampTo(scroll_offset.Height(), user_scrollable.Y(),
@@ -367,9 +412,9 @@ void RootFrameViewport::DistributeScrollBetweenViewports(
}
ScrollableArea& primary =
- scroll_first == kVisualViewport ? VisualViewport() : LayoutViewport();
+ scroll_first == kVisualViewport ? GetVisualViewport() : LayoutViewport();
ScrollableArea& secondary =
- scroll_first == kVisualViewport ? LayoutViewport() : VisualViewport();
+ scroll_first == kVisualViewport ? LayoutViewport() : GetVisualViewport();
ScrollOffset target_offset = primary.ClampScrollOffset(
primary.GetScrollAnimator().CurrentOffset() + delta);
@@ -407,22 +452,22 @@ IntSize RootFrameViewport::ScrollOffsetInt() const {
ScrollOffset RootFrameViewport::GetScrollOffset() const {
return LayoutViewport().GetScrollOffset() +
- VisualViewport().GetScrollOffset();
+ GetVisualViewport().GetScrollOffset();
}
IntSize RootFrameViewport::MinimumScrollOffsetInt() const {
return IntSize(LayoutViewport().MinimumScrollOffsetInt() +
- VisualViewport().MinimumScrollOffsetInt());
+ GetVisualViewport().MinimumScrollOffsetInt());
}
IntSize RootFrameViewport::MaximumScrollOffsetInt() const {
return LayoutViewport().MaximumScrollOffsetInt() +
- VisualViewport().MaximumScrollOffsetInt();
+ GetVisualViewport().MaximumScrollOffsetInt();
}
ScrollOffset RootFrameViewport::MaximumScrollOffset() const {
return LayoutViewport().MaximumScrollOffset() +
- VisualViewport().MaximumScrollOffset();
+ GetVisualViewport().MaximumScrollOffset();
}
IntSize RootFrameViewport::ClampScrollOffset(
@@ -447,7 +492,7 @@ bool RootFrameViewport::ScrollbarsCanBeActive() const {
bool RootFrameViewport::UserInputScrollable(
ScrollbarOrientation orientation) const {
- return VisualViewport().UserInputScrollable(orientation) ||
+ return GetVisualViewport().UserInputScrollable(orientation) ||
LayoutViewport().UserInputScrollable(orientation);
}
@@ -500,7 +545,8 @@ ScrollResult RootFrameViewport::UserScroll(
// scroll delta, regardless of how much will actually scroll, but we need to
// know how much to leave for the layout viewport.
FloatSize visual_consumed_delta =
- VisualViewport().GetScrollAnimator().ComputeDeltaToConsume(pixel_delta);
+ GetVisualViewport().GetScrollAnimator().ComputeDeltaToConsume(
+ pixel_delta);
// Split the remaining delta between scrollable and unscrollable axes of the
// layout viewport. We only pass a delta to the scrollable axes and remember
@@ -530,7 +576,7 @@ ScrollResult RootFrameViewport::UserScroll(
// not through the ScrollableAreas?
if (visual_consumed_delta == pixel_delta) {
ScrollResult visual_result =
- VisualViewport().GetScrollAnimator().UserScroll(
+ GetVisualViewport().GetScrollAnimator().UserScroll(
granularity, visual_consumed_delta, run_on_return.Release());
return visual_result;
}
@@ -538,8 +584,9 @@ ScrollResult RootFrameViewport::UserScroll(
ScrollableArea::ScrollCallback callback = run_on_return.Release();
auto all_done = callback ? base::BarrierClosure(2, std::move(callback))
: base::RepeatingClosure();
- ScrollResult visual_result = VisualViewport().GetScrollAnimator().UserScroll(
- granularity, visual_consumed_delta, all_done);
+ ScrollResult visual_result =
+ GetVisualViewport().GetScrollAnimator().UserScroll(
+ granularity, visual_consumed_delta, all_done);
ScrollResult layout_result = LayoutViewport().GetScrollAnimator().UserScroll(
granularity, scrollable_axis_delta, all_done);
@@ -565,8 +612,8 @@ CompositorElementId RootFrameViewport::GetCompositorElementId() const {
CompositorElementId RootFrameViewport::GetScrollbarElementId(
ScrollbarOrientation orientation) {
- return VisualViewport().VisualViewportSuppliesScrollbars()
- ? VisualViewport().GetScrollbarElementId(orientation)
+ return GetVisualViewport().VisualViewportSuppliesScrollbars()
+ ? GetVisualViewport().GetScrollbarElementId(orientation)
: LayoutViewport().GetScrollbarElementId(orientation);
}
@@ -581,25 +628,25 @@ SmoothScrollSequencer* RootFrameViewport::GetSmoothScrollSequencer() const {
void RootFrameViewport::ServiceScrollAnimations(double monotonic_time) {
ScrollableArea::ServiceScrollAnimations(monotonic_time);
LayoutViewport().ServiceScrollAnimations(monotonic_time);
- VisualViewport().ServiceScrollAnimations(monotonic_time);
+ GetVisualViewport().ServiceScrollAnimations(monotonic_time);
}
void RootFrameViewport::UpdateCompositorScrollAnimations() {
ScrollableArea::UpdateCompositorScrollAnimations();
LayoutViewport().UpdateCompositorScrollAnimations();
- VisualViewport().UpdateCompositorScrollAnimations();
+ GetVisualViewport().UpdateCompositorScrollAnimations();
}
void RootFrameViewport::CancelProgrammaticScrollAnimation() {
ScrollableArea::CancelProgrammaticScrollAnimation();
LayoutViewport().CancelProgrammaticScrollAnimation();
- VisualViewport().CancelProgrammaticScrollAnimation();
+ GetVisualViewport().CancelProgrammaticScrollAnimation();
}
void RootFrameViewport::ClearScrollableArea() {
ScrollableArea::ClearScrollableArea();
LayoutViewport().ClearScrollableArea();
- VisualViewport().ClearScrollableArea();
+ GetVisualViewport().ClearScrollableArea();
}
ScrollbarTheme& RootFrameViewport::GetPageScrollbarTheme() const {
diff --git a/chromium/third_party/blink/renderer/core/frame/root_frame_viewport.h b/chromium/third_party/blink/renderer/core/frame/root_frame_viewport.h
index 9622a32ddf3..67449d770b1 100644
--- a/chromium/third_party/blink/renderer/core/frame/root_frame_viewport.h
+++ b/chromium/third_party/blink/renderer/core/frame/root_frame_viewport.h
@@ -121,6 +121,15 @@ class CORE_EXPORT RootFrameViewport final
unsigned = 0) const final;
scoped_refptr<base::SingleThreadTaskRunner> GetTimerTaskRunner() const final;
ScrollbarTheme& GetPageScrollbarTheme() const override;
+
+ void SetPendingHistoryRestoreScrollOffset(
+ const HistoryItem::ViewState& view_state,
+ bool should_restore_scroll) override {
+ pending_view_state_ = view_state;
+ should_restore_scroll_ = should_restore_scroll;
+ }
+ bool ApplyPendingHistoryRestoreScrollOffset() override;
+
const cc::SnapContainerData* GetSnapContainerData() const override;
void SetSnapContainerData(base::Optional<cc::SnapContainerData>) override;
@@ -143,7 +152,7 @@ class CORE_EXPORT RootFrameViewport final
// class' animator so use this method to pull updated values when necessary.
void UpdateScrollAnimator();
- ScrollableArea& VisualViewport() const {
+ ScrollableArea& GetVisualViewport() const {
DCHECK(visual_viewport_);
return *visual_viewport_;
}
@@ -152,6 +161,8 @@ class CORE_EXPORT RootFrameViewport final
Member<ScrollableArea> visual_viewport_;
Member<ScrollableArea> layout_viewport_;
+ base::Optional<HistoryItem::ViewState> pending_view_state_;
+ bool should_restore_scroll_;
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/frame/visual_viewport.cc b/chromium/third_party/blink/renderer/core/frame/visual_viewport.cc
index 1b4e8c96869..e31db459bf9 100644
--- a/chromium/third_party/blink/renderer/core/frame/visual_viewport.cc
+++ b/chromium/third_party/blink/renderer/core/frame/visual_viewport.cc
@@ -767,6 +767,12 @@ void VisualViewport::SetScrollOffset(const ScrollOffset& offset,
scroll_behavior, std::move(on_finish));
}
+void VisualViewport::SetScrollOffset(const ScrollOffset& offset,
+ ScrollType scroll_type,
+ ScrollBehavior scroll_behavior) {
+ SetScrollOffset(offset, scroll_type, scroll_behavior, ScrollCallback());
+}
+
PhysicalRect VisualViewport::ScrollIntoView(
const PhysicalRect& rect_in_absolute,
const WebScrollIntoViewParams& params) {
diff --git a/chromium/third_party/blink/renderer/core/frame/visual_viewport.h b/chromium/third_party/blink/renderer/core/frame/visual_viewport.h
index b675a62d691..2dff56c642b 100644
--- a/chromium/third_party/blink/renderer/core/frame/visual_viewport.h
+++ b/chromium/third_party/blink/renderer/core/frame/visual_viewport.h
@@ -97,10 +97,9 @@ struct PaintPropertyTreeBuilderFragmentContext;
// +- horizontal_scrollbar_effect_node_
// +- vertical_scrollbar_effect_node_
//
-class CORE_EXPORT VisualViewport final
- : public GarbageCollected<VisualViewport>,
- public GraphicsLayerClient,
- public ScrollableArea {
+class CORE_EXPORT VisualViewport : public GarbageCollected<VisualViewport>,
+ public GraphicsLayerClient,
+ public ScrollableArea {
USING_GARBAGE_COLLECTED_MIXIN(VisualViewport);
public:
@@ -190,6 +189,9 @@ class CORE_EXPORT VisualViewport final
ScrollType,
ScrollBehavior,
ScrollCallback on_finish) override;
+ void SetScrollOffset(const ScrollOffset&,
+ ScrollType,
+ ScrollBehavior = kScrollBehaviorInstant) override;
PhysicalRect ScrollIntoView(const PhysicalRect&,
const WebScrollIntoViewParams&) override;
bool IsThrottled() const override {
@@ -225,7 +227,8 @@ class CORE_EXPORT VisualViewport final
CompositorAnimationTimeline* GetCompositorAnimationTimeline() const override;
IntRect VisibleContentRect(
IncludeScrollbarsInRect = kExcludeScrollbars) const override;
- scoped_refptr<base::SingleThreadTaskRunner> GetTimerTaskRunner() const final;
+ scoped_refptr<base::SingleThreadTaskRunner> GetTimerTaskRunner()
+ const override;
WebColorScheme UsedColorScheme() const override;
// VisualViewport scrolling may involve pinch zoom and gets routed through
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_loader.cc b/chromium/third_party/blink/renderer/core/loader/frame_loader.cc
index e60598f9c8c..da3caa9fa14 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -134,7 +134,7 @@ bool IsReloadLoadType(WebFrameLoadType type) {
type == WebFrameLoadType::kReloadBypassingCache;
}
-static bool NeedsHistoryItemRestore(WebFrameLoadType type) {
+bool FrameLoader::NeedsHistoryItemRestore(WebFrameLoadType type) {
return type == WebFrameLoadType::kBackForward || IsReloadLoadType(type);
}
@@ -1153,79 +1153,9 @@ void FrameLoader::RestoreScrollPositionAndViewState(
if (!NeedsHistoryItemRestore(load_type))
return;
- bool should_restore_scroll =
- scroll_restoration_type != kScrollRestorationManual;
- bool should_restore_scale = view_state.page_scale_factor_;
-
- // This tries to balance:
- // 1. restoring as soon as possible.
- // 2. not overriding user scroll (TODO(majidvp): also respect user scale).
- // 3. detecting clamping to avoid repeatedly popping the scroll position down
- // as the page height increases.
- // 4. forcing a layout if necessary to avoid clamping.
- // 5. ignoring clamp detection if scroll state is not being restored, if load
- // is complete, or if the navigation is same-document (as the new page may
- // be smaller than the previous page).
- bool can_restore_without_clamping =
- view->LayoutViewport()->ClampScrollOffset(view_state.scroll_offset_) ==
- view_state.scroll_offset_;
-
- bool should_force_clamping = !frame_->IsLoading() || is_same_document;
- // Here |can_restore_without_clamping| is false, but layout might be necessary
- // to ensure correct content size.
- if (!can_restore_without_clamping && should_force_clamping)
- frame_->GetDocument()->UpdateStyleAndLayout();
-
- bool can_restore_without_annoying_user =
- !GetDocumentLoader()->GetInitialScrollState().was_scrolled_by_user &&
- (can_restore_without_clamping || should_force_clamping ||
- !should_restore_scroll);
- if (!can_restore_without_annoying_user)
- return;
-
- if (should_restore_scroll) {
- // TODO(pnoland): attempt to restore the anchor in more places than this.
- // Anchor-based restore should allow for earlier restoration.
- bool did_restore = view->LayoutViewport()->RestoreScrollAnchor(
- {view_state.scroll_anchor_data_.selector_,
- LayoutPoint(view_state.scroll_anchor_data_.offset_.x,
- view_state.scroll_anchor_data_.offset_.y),
- view_state.scroll_anchor_data_.simhash_});
- if (!did_restore) {
- view->LayoutViewport()->SetScrollOffset(view_state.scroll_offset_,
- kProgrammaticScroll);
- }
- }
-
- // For main frame restore scale and visual viewport position
- if (frame_->IsMainFrame()) {
- ScrollOffset visual_viewport_offset(
- view_state.visual_viewport_scroll_offset_);
-
- // If the visual viewport's offset is (-1, -1) it means the history item
- // is an old version of HistoryItem so distribute the scroll between
- // the main frame and the visual viewport as best as we can.
- if (visual_viewport_offset.Width() == -1 &&
- visual_viewport_offset.Height() == -1) {
- visual_viewport_offset =
- view_state.scroll_offset_ - view->LayoutViewport()->GetScrollOffset();
- }
-
- VisualViewport& visual_viewport = frame_->GetPage()->GetVisualViewport();
- if (should_restore_scale && should_restore_scroll) {
- visual_viewport.SetScaleAndLocation(
- view_state.page_scale_factor_, visual_viewport.IsPinchGestureActive(),
- FloatPoint(visual_viewport_offset));
- } else if (should_restore_scale) {
- visual_viewport.SetScale(view_state.page_scale_factor_);
- } else if (should_restore_scroll) {
- visual_viewport.SetLocation(FloatPoint(visual_viewport_offset));
- }
-
- if (ScrollingCoordinator* scrolling_coordinator =
- frame_->GetPage()->GetScrollingCoordinator())
- scrolling_coordinator->FrameViewRootLayerDidChange(view);
- }
+ view->GetScrollableArea()->SetPendingHistoryRestoreScrollOffset(
+ view_state, scroll_restoration_type != kScrollRestorationManual);
+ view->ScheduleAnimation();
GetDocumentLoader()->GetInitialScrollState().did_restore_from_history = true;
}
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_loader.h b/chromium/third_party/blink/renderer/core/loader/frame_loader.h
index c16d98c82a5..44731f0ed2f 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/frame_loader.h
@@ -231,6 +231,8 @@ class CORE_EXPORT FrameLoader final {
bool IsClientNavigationInitialHistoryLoad();
+ static bool NeedsHistoryItemRestore(WebFrameLoadType type);
+
private:
bool AllowRequestForThisFrame(const FrameLoadRequest&);
WebFrameLoadType DetermineFrameLoadType(const KURL& url,
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc b/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc
index 28b4377bb51..b6b885b848c 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc
@@ -167,16 +167,6 @@ void ElementFragmentAnchor::DidScroll(ScrollType type) {
needs_invoke_ = false;
}
-void ElementFragmentAnchor::DidCompleteLoad() {
- DCHECK(frame_);
- DCHECK(frame_->View());
-
- // If there is a pending layout, the fragment anchor will be cleared when it
- // finishes.
- if (!frame_->View()->NeedsLayout())
- needs_invoke_ = false;
-}
-
void ElementFragmentAnchor::Trace(blink::Visitor* visitor) {
visitor->Trace(anchor_node_);
visitor->Trace(frame_);
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h b/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h
index f51ce60afd2..4b5c885323f 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h
@@ -52,9 +52,6 @@ class CORE_EXPORT ElementFragmentAnchor final : public FragmentAnchor {
// so we can't do it in Invoke.
void PerformPreRafActions() override;
- // We can dispose of the fragment once load has been completed.
- void DidCompleteLoad() override;
-
// Does nothing as an element anchor does not have any dismissal work.
bool Dismiss() override;
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h b/chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h
index 7550d5674a9..5127fff25dd 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h
@@ -51,7 +51,6 @@ class CORE_EXPORT FragmentAnchor : public GarbageCollected<FragmentAnchor> {
virtual void DidScroll(ScrollType type) = 0;
virtual void PerformPreRafActions() = 0;
- virtual void DidCompleteLoad() = 0;
// Dismissing the fragment anchor removes indicators of the anchor, such as
// text highlighting on a text fragment anchor. If true, the anchor has been
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc
index 3d8b5cceabf..38ac2dd9f13 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc
@@ -176,15 +176,6 @@ void TextFragmentAnchor::PerformPreRafActions() {
}
}
-void TextFragmentAnchor::DidCompleteLoad() {
- if (search_finished_)
- return;
-
- // If there is a pending layout we'll finish the search from Invoke.
- if (!frame_->View()->NeedsLayout())
- DidFinishSearch();
-}
-
void TextFragmentAnchor::Trace(blink::Visitor* visitor) {
visitor->Trace(frame_);
visitor->Trace(element_fragment_anchor_);
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h
index 27d3da57a9a..9bcbfb58637 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h
@@ -53,8 +53,6 @@ class CORE_EXPORT TextFragmentAnchor final : public FragmentAnchor,
void PerformPreRafActions() override;
- void DidCompleteLoad() override;
-
// Removes text match highlights if any highlight is in view.
bool Dismiss() override;
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
index 399087fa006..b458c7cee0d 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -217,6 +217,23 @@ void PaintLayerScrollableArea::DisposeImpl() {
layer_ = nullptr;
}
+bool PaintLayerScrollableArea::ApplyPendingHistoryRestoreScrollOffset() {
+ if (!pending_view_state_)
+ return false;
+ // TODO(pnoland): attempt to restore the anchor in more places than this.
+ // Anchor-based restore should allow for earlier restoration.
+ bool did_restore = RestoreScrollAnchor(
+ {pending_view_state_->scroll_anchor_data_.selector_,
+ LayoutPoint(pending_view_state_->scroll_anchor_data_.offset_.x,
+ pending_view_state_->scroll_anchor_data_.offset_.y),
+ pending_view_state_->scroll_anchor_data_.simhash_});
+ if (!did_restore) {
+ SetScrollOffset(pending_view_state_->scroll_offset_, kProgrammaticScroll);
+ }
+ pending_view_state_.reset();
+ return true;
+}
+
void PaintLayerScrollableArea::Trace(blink::Visitor* visitor) {
visitor->Trace(scrollbar_manager_);
visitor->Trace(scroll_anchor_);
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h b/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
index dc9895c9284..540c8e7fe60 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
@@ -556,6 +556,16 @@ class CORE_EXPORT PaintLayerScrollableArea final
void DisposeImpl() override;
+ void SetPendingHistoryRestoreScrollOffset(
+ const HistoryItem::ViewState& view_state,
+ bool should_restore_scroll) override {
+ if (!should_restore_scroll)
+ return;
+ pending_view_state_ = view_state;
+ }
+
+ bool ApplyPendingHistoryRestoreScrollOffset() override;
+
private:
bool NeedsScrollbarReconstruction() const;
@@ -722,6 +732,7 @@ class CORE_EXPORT PaintLayerScrollableArea final
ScrollingBackgroundDisplayItemClient
scrolling_background_display_item_client_;
+ base::Optional<HistoryItem::ViewState> pending_view_state_;
};
DEFINE_TYPE_CASTS(PaintLayerScrollableArea,
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollable_area.h b/chromium/third_party/blink/renderer/core/scroll/scrollable_area.h
index b3066ee7056..7af64264d17 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollable_area.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollable_area.h
@@ -30,6 +30,7 @@
#include "third_party/blink/public/platform/web_color_scheme.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
+#include "third_party/blink/renderer/core/loader/history_item.h"
#include "third_party/blink/renderer/core/scroll/scrollbar.h"
#include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
@@ -102,9 +103,9 @@ class CORE_EXPORT ScrollableArea : public GarbageCollectedMixin {
ScrollType,
ScrollBehavior,
ScrollCallback on_finish);
- void SetScrollOffset(const ScrollOffset&,
- ScrollType,
- ScrollBehavior = kScrollBehaviorInstant);
+ virtual void SetScrollOffset(const ScrollOffset&,
+ ScrollType,
+ ScrollBehavior = kScrollBehaviorInstant);
void ScrollBy(const ScrollOffset&,
ScrollType,
ScrollBehavior = kScrollBehaviorInstant);
@@ -113,6 +114,12 @@ class CORE_EXPORT ScrollableArea : public GarbageCollectedMixin {
ScrollType,
ScrollBehavior = kScrollBehaviorInstant);
+ virtual void SetPendingHistoryRestoreScrollOffset(
+ const HistoryItem::ViewState& view_state,
+ bool should_restore_scroll) {}
+ // Returns true if it applied anything.
+ virtual bool ApplyPendingHistoryRestoreScrollOffset() { return false; }
+
// Scrolls the area so that the given rect, given in absolute coordinates,
// such that it's visible in the area. Returns the new location of the input
// rect in absolute coordinates.