diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h')
-rw-r--r-- | chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h | 77 |
1 files changed, 77 insertions, 0 deletions
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 new file mode 100644 index 00000000000..32ee9d16142 --- /dev/null +++ b/chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h @@ -0,0 +1,77 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_FRAGMENT_ANCHOR_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_FRAGMENT_ANCHOR_H_ + +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/scroll/scroll_types.h" + +namespace blink { + +class LocalFrame; +class KURL; + +// This class encapsulates the behavior of a "fragment anchor". A fragment +// anchor allows a page to link to a specific part of a page by specifying an +// element id in the URL fragment. The fragment is the part after the '#' +// character. E.g. navigating to www.example.com/index.html#section3 will find +// the element with id "section3" and focus and scroll it into view. +// +// While the page is loading, the fragment anchor tries to repeatedly scroll +// the element into view since it's position may change as a result of layouts. +// TODO(bokan): Maybe we no longer need the repeated scrolling since that +// should be handled by scroll-anchoring? +class CORE_EXPORT FragmentAnchor : public GarbageCollected<FragmentAnchor> { + public: + // Parses the fragment string and tries to create a FragmentAnchor object. If + // an appropriate target was found based on the given fragment, this method + // will create and return a FragmentAnchor object that can be used to keep it + // in view. Otherwise, this will return nullptr. In either case, + // side-effects on the document will be performed, for example, + // setting/clearing :target and svgView(). If needs_invoke is false, only the + // side effects will be performed, the element won't be scrolled/focused and + // this method returns nullptr (e.g. used during history navigation where we + // don't want to clobber the history scroll restoration). + static FragmentAnchor* TryCreate(const KURL& url, + bool needs_invoke, + LocalFrame& frame); + + FragmentAnchor(Node& anchor_node, LocalFrame& frame); + virtual ~FragmentAnchor() = default; + + // Invoking the fragment anchor scrolls it into view and performs any other + // desired actions. This is called repeatedly during loading as the lifecycle + // is updated to keep the element in view. If true, the anchor should be kept + // alive and invoked again. Otherwise it may be disposed. + bool Invoke(); + + // Used to let the fragment know the frame's been scrolled and so we should + // abort keeping the fragment target in view to avoid fighting with user + // scrolls. + void DidScroll(ScrollType type); + + void PerformPreRafActions(); + + void DidCompleteLoad(); + + void Trace(blink::Visitor*); + + private: + void ApplyFocusIfNeeded(); + + WeakMember<Node> anchor_node_; + Member<LocalFrame> frame_; + bool needs_focus_; + + // While this is true, the fragment is still "active" in the sense that we + // want the owner to continue calling Invoke(). Once this is false, calling + // Invoke has no effect and the fragment can be disposed. + bool needs_invoke_ = true; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_FRAGMENT_ANCHOR_H_ |