| // Copyright 2016 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_INTERSECTION_OBSERVER_INTERSECTION_OBSERVER_H_ |
| #define THIRD_PARTY_BLINK_RENDERER_CORE_INTERSECTION_OBSERVER_INTERSECTION_OBSERVER_H_ |
| |
| #include "base/callback.h" |
| #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h" |
| #include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h" |
| #include "third_party/blink/renderer/core/intersection_observer/intersection_observation.h" |
| #include "third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h" |
| #include "third_party/blink/renderer/platform/bindings/exception_state.h" |
| #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" |
| #include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h" |
| #include "third_party/blink/renderer/platform/geometry/length.h" |
| #include "third_party/blink/renderer/platform/heap/handle.h" |
| #include "third_party/blink/renderer/platform/wtf/hash_set.h" |
| #include "third_party/blink/renderer/platform/wtf/vector.h" |
| |
| namespace blink { |
| |
| class Document; |
| class Element; |
| class ExceptionState; |
| class IntersectionObserverDelegate; |
| class IntersectionObserverInit; |
| class ScriptState; |
| class V8IntersectionObserverCallback; |
| |
| class CORE_EXPORT IntersectionObserver final |
| : public ScriptWrappable, |
| public ActiveScriptWrappable<IntersectionObserver>, |
| public ContextClient { |
| USING_GARBAGE_COLLECTED_MIXIN(IntersectionObserver); |
| DEFINE_WRAPPERTYPEINFO(); |
| |
| public: |
| using EventCallback = base::RepeatingCallback<void( |
| const HeapVector<Member<IntersectionObserverEntry>>&)>; |
| |
| // The IntersectionObserver can be configured to notify based on changes to |
| // how much of the target element's area intersects with the root, or based on |
| // changes to how much of the root element's area intersects with the |
| // target. Examples illustrating the distinction: |
| // |
| // 1.0 of target, 0.5 of target, 1.0 of target, |
| // 0.25 of root 0.5 of root 1.0 of root |
| // +------------------+ +------------------+ *~~~~~~~~~~~~~~~~~~* |
| // | ////////// | | | ;//////////////////; |
| // | ////////// | | | ;//////////////////; |
| // | ////////// | ;//////////////////; ;//////////////////; |
| // | | ;//////////////////; ;//////////////////; |
| // +------------------+ *~~~~~~~~~~~~~~~~~~* *~~~~~~~~~~~~~~~~~~* |
| // //////////////////// |
| // //////////////////// |
| // //////////////////// |
| enum ThresholdInterpretation { kFractionOfTarget, kFractionOfRoot }; |
| |
| static IntersectionObserver* Create(const IntersectionObserverInit*, |
| IntersectionObserverDelegate&, |
| ExceptionState&); |
| static IntersectionObserver* Create(ScriptState*, |
| V8IntersectionObserverCallback*, |
| const IntersectionObserverInit*, |
| ExceptionState&); |
| |
| // Creates an IntersectionObserver that monitors changes to the intersection |
| // between its target element relative to its implicit root and notifies via |
| // the given |callback|. |thresholds| should be in the range [0,1], and are |
| // interpreted according to the given |semantics|. |delay| specifies the |
| // minimum period between change notifications. |
| // |
| // TODO(crbug.com/915495): The |delay| feature is broken. See comments in |
| // intersection_observation.cc. |
| static IntersectionObserver* Create( |
| const Vector<Length>& root_margin, |
| const Vector<float>& thresholds, |
| Document* document, |
| EventCallback callback, |
| ThresholdInterpretation semantics = kFractionOfTarget, |
| DOMHighResTimeStamp delay = 0, |
| bool track_visbility = false, |
| bool always_report_root_bounds = false, |
| ExceptionState& = ASSERT_NO_EXCEPTION); |
| |
| static void ResumeSuspendedObservers(); |
| |
| explicit IntersectionObserver(IntersectionObserverDelegate&, |
| Element*, |
| const Vector<Length>& root_margin, |
| const Vector<float>& thresholds, |
| ThresholdInterpretation semantics, |
| DOMHighResTimeStamp delay, |
| bool track_visibility, |
| bool always_report_root_bounds); |
| |
| // API methods. |
| void observe(Element*, ExceptionState& = ASSERT_NO_EXCEPTION); |
| void unobserve(Element*, ExceptionState& = ASSERT_NO_EXCEPTION); |
| void disconnect(ExceptionState& = ASSERT_NO_EXCEPTION); |
| HeapVector<Member<IntersectionObserverEntry>> takeRecords(ExceptionState&); |
| |
| // API attributes. |
| Element* root() const { return root_.Get(); } |
| String rootMargin() const; |
| const Vector<float>& thresholds() const { return thresholds_; } |
| DOMHighResTimeStamp delay() const { return delay_; } |
| bool trackVisibility() const { return track_visibility_; } |
| bool trackFractionOfRoot() const { return track_fraction_of_root_; } |
| |
| // An observer can either track intersections with an explicit root Element, |
| // or with the the top-level frame's viewport (the "implicit root"). When |
| // tracking the implicit root, root_ will be null, but because root_ is a |
| // weak pointer, we cannot surmise that this observer tracks the implicit |
| // root just because root_ is null. Hence root_is_implicit_. |
| bool RootIsImplicit() const { return root_is_implicit_; } |
| |
| bool AlwaysReportRootBounds() const { return always_report_root_bounds_; } |
| |
| DOMHighResTimeStamp GetTimeStamp() const; |
| DOMHighResTimeStamp GetEffectiveDelay() const; |
| const Length& TopMargin() const { return top_margin_; } |
| const Length& RightMargin() const { return right_margin_; } |
| const Length& BottomMargin() const { return bottom_margin_; } |
| const Length& LeftMargin() const { return left_margin_; } |
| unsigned FirstThresholdGreaterThan(float ratio) const; |
| void Deliver(); |
| |
| // Returns false if this observer has an explicit root element which has been |
| // deleted; true otherwise. |
| bool RootIsValid() const; |
| |
| // ScriptWrappable override: |
| bool HasPendingActivity() const override; |
| |
| void Trace(blink::Visitor*) override; |
| |
| // Enable/disable throttling of visibility checking, so we don't have to add |
| // sleep() calls to tests to wait for notifications to show up. |
| static void SetThrottleDelayEnabledForTesting(bool); |
| |
| private: |
| void ClearWeakMembers(Visitor*); |
| |
| const TraceWrapperMember<IntersectionObserverDelegate> delegate_; |
| WeakMember<Element> root_; |
| HeapLinkedHashSet<WeakMember<IntersectionObservation>> observations_; |
| Vector<float> thresholds_; |
| DOMHighResTimeStamp delay_; |
| Length top_margin_; |
| Length right_margin_; |
| Length bottom_margin_; |
| Length left_margin_; |
| unsigned root_is_implicit_ : 1; |
| unsigned track_visibility_ : 1; |
| unsigned track_fraction_of_root_ : 1; |
| unsigned always_report_root_bounds_ : 1; |
| }; |
| |
| } // namespace blink |
| |
| #endif // THIRD_PARTY_BLINK_RENDERER_CORE_INTERSECTION_OBSERVER_INTERSECTION_OBSERVER_H_ |