1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef DOMIntersectionObserver_h 8 #define DOMIntersectionObserver_h 9 10 #include "mozilla/Attributes.h" 11 #include "mozilla/dom/IntersectionObserverBinding.h" 12 #include "mozilla/ServoStyleConsts.h" 13 #include "mozilla/Variant.h" 14 #include "nsTArray.h" 15 16 namespace mozilla { 17 namespace dom { 18 19 class DOMIntersectionObserver; 20 21 class DOMIntersectionObserverEntry final : public nsISupports, 22 public nsWrapperCache { 23 ~DOMIntersectionObserverEntry() = default; 24 25 public: DOMIntersectionObserverEntry(nsISupports * aOwner,DOMHighResTimeStamp aTime,RefPtr<DOMRect> aRootBounds,RefPtr<DOMRect> aBoundingClientRect,RefPtr<DOMRect> aIntersectionRect,bool aIsIntersecting,Element * aTarget,double aIntersectionRatio)26 DOMIntersectionObserverEntry(nsISupports* aOwner, DOMHighResTimeStamp aTime, 27 RefPtr<DOMRect> aRootBounds, 28 RefPtr<DOMRect> aBoundingClientRect, 29 RefPtr<DOMRect> aIntersectionRect, 30 bool aIsIntersecting, Element* aTarget, 31 double aIntersectionRatio) 32 : mOwner(aOwner), 33 mTime(aTime), 34 mRootBounds(std::move(aRootBounds)), 35 mBoundingClientRect(std::move(aBoundingClientRect)), 36 mIntersectionRect(std::move(aIntersectionRect)), 37 mIsIntersecting(aIsIntersecting), 38 mTarget(aTarget), 39 mIntersectionRatio(aIntersectionRatio) {} 40 NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMIntersectionObserverEntry)41 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMIntersectionObserverEntry) 42 43 nsISupports* GetParentObject() const { return mOwner; } 44 WrapObject(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)45 JSObject* WrapObject(JSContext* aCx, 46 JS::Handle<JSObject*> aGivenProto) override { 47 return IntersectionObserverEntry_Binding::Wrap(aCx, this, aGivenProto); 48 } 49 Time()50 DOMHighResTimeStamp Time() const { return mTime; } 51 GetRootBounds()52 DOMRect* GetRootBounds() { return mRootBounds; } 53 BoundingClientRect()54 DOMRect* BoundingClientRect() { return mBoundingClientRect; } 55 IntersectionRect()56 DOMRect* IntersectionRect() { return mIntersectionRect; } 57 IsIntersecting()58 bool IsIntersecting() const { return mIsIntersecting; } 59 IntersectionRatio()60 double IntersectionRatio() const { return mIntersectionRatio; } 61 Target()62 Element* Target() { return mTarget; } 63 64 protected: 65 nsCOMPtr<nsISupports> mOwner; 66 DOMHighResTimeStamp mTime; 67 RefPtr<DOMRect> mRootBounds; 68 RefPtr<DOMRect> mBoundingClientRect; 69 RefPtr<DOMRect> mIntersectionRect; 70 bool mIsIntersecting; 71 RefPtr<Element> mTarget; 72 double mIntersectionRatio; 73 }; 74 75 #define NS_DOM_INTERSECTION_OBSERVER_IID \ 76 { \ 77 0x8570a575, 0xe303, 0x4d18, { \ 78 0xb6, 0xb1, 0x4d, 0x2b, 0x49, 0xd8, 0xef, 0x94 \ 79 } \ 80 } 81 82 class DOMIntersectionObserver final : public nsISupports, 83 public nsWrapperCache { ~DOMIntersectionObserver()84 virtual ~DOMIntersectionObserver() { Disconnect(); } 85 86 typedef void (*NativeCallback)( 87 const Sequence<OwningNonNull<DOMIntersectionObserverEntry>>& aEntries); 88 DOMIntersectionObserver(Document&, NativeCallback); 89 90 public: DOMIntersectionObserver(already_AddRefed<nsPIDOMWindowInner> && aOwner,dom::IntersectionCallback & aCb)91 DOMIntersectionObserver(already_AddRefed<nsPIDOMWindowInner>&& aOwner, 92 dom::IntersectionCallback& aCb) 93 : mOwner(aOwner), 94 mDocument(mOwner->GetExtantDoc()), 95 mCallback(RefPtr<dom::IntersectionCallback>(&aCb)), 96 mConnected(false) {} 97 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 98 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMIntersectionObserver) 99 NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOM_INTERSECTION_OBSERVER_IID) 100 101 static already_AddRefed<DOMIntersectionObserver> Constructor( 102 const GlobalObject&, dom::IntersectionCallback&, ErrorResult&); 103 static already_AddRefed<DOMIntersectionObserver> Constructor( 104 const GlobalObject&, dom::IntersectionCallback&, 105 const IntersectionObserverInit&, ErrorResult&); 106 WrapObject(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)107 JSObject* WrapObject(JSContext* aCx, 108 JS::Handle<JSObject*> aGivenProto) override { 109 return IntersectionObserver_Binding::Wrap(aCx, this, aGivenProto); 110 } 111 GetParentObject()112 nsISupports* GetParentObject() const { return mOwner; } 113 GetRoot()114 nsINode* GetRoot() const { return mRoot; } 115 116 void GetRootMargin(DOMString& aRetVal); 117 void GetThresholds(nsTArray<double>& aRetVal); 118 void Observe(Element& aTarget); 119 void Unobserve(Element& aTarget); 120 121 void UnlinkTarget(Element& aTarget); 122 void Disconnect(); 123 124 void TakeRecords(nsTArray<RefPtr<DOMIntersectionObserverEntry>>& aRetVal); 125 126 bool SetRootMargin(const nsAString& aString); 127 128 void Update(Document* aDocument, DOMHighResTimeStamp time); 129 MOZ_CAN_RUN_SCRIPT void Notify(); 130 131 static already_AddRefed<DOMIntersectionObserver> CreateLazyLoadObserver( 132 Document&); 133 134 protected: 135 void Connect(); 136 void QueueIntersectionObserverEntry(Element* aTarget, 137 DOMHighResTimeStamp time, 138 const Maybe<nsRect>& aRootRect, 139 const nsRect& aTargetRect, 140 const Maybe<nsRect>& aIntersectionRect, 141 bool aIsIntersecting, 142 double aIntersectionRatio); 143 144 nsCOMPtr<nsPIDOMWindowInner> mOwner; 145 RefPtr<Document> mDocument; 146 Variant<RefPtr<dom::IntersectionCallback>, NativeCallback> mCallback; 147 RefPtr<nsINode> mRoot; 148 StyleRect<LengthPercentage> mRootMargin; 149 nsTArray<double> mThresholds; 150 151 // Holds raw pointers which are explicitly cleared by UnlinkTarget(). 152 nsTArray<Element*> mObservationTargets; 153 154 nsTArray<RefPtr<DOMIntersectionObserverEntry>> mQueuedEntries; 155 bool mConnected; 156 }; 157 158 NS_DEFINE_STATIC_IID_ACCESSOR(DOMIntersectionObserver, 159 NS_DOM_INTERSECTION_OBSERVER_IID) 160 161 } // namespace dom 162 } // namespace mozilla 163 164 #endif 165