Bug 1665252 - remove allowpaymentrequest attribute from HTMLIFrameElement r=dom-worke...
[gecko.git] / dom / base / ResizeObserver.h
blob2b6bdf2ebc86b8b2c8d6ee36203c57ed8ccf67e8
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
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
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_ResizeObserver_h
8 #define mozilla_dom_ResizeObserver_h
10 #include "js/TypeDecls.h"
11 #include "mozilla/AppUnits.h"
12 #include "mozilla/Attributes.h"
13 #include "mozilla/ErrorResult.h"
14 #include "mozilla/LinkedList.h"
15 #include "mozilla/WritingModes.h"
16 #include "mozilla/dom/BindingDeclarations.h"
17 #include "mozilla/dom/ResizeObserverBinding.h"
18 #include "nsCoord.h"
19 #include "nsCycleCollectionParticipant.h"
20 #include "nsRefPtrHashtable.h"
21 #include "nsTArray.h"
22 #include "nsWrapperCache.h"
24 namespace mozilla {
25 namespace dom {
27 class Element;
29 } // namespace dom
30 } // namespace mozilla
32 namespace mozilla {
33 namespace dom {
35 // For the internal implementation in ResizeObserver. Normally, this is owned by
36 // ResizeObserver.
37 class ResizeObservation final : public LinkedListElement<ResizeObservation> {
38 public:
39 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(ResizeObservation)
40 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(ResizeObservation)
42 ResizeObservation(Element& aTarget, ResizeObserverBoxOptions aBox,
43 const WritingMode aWM)
44 : mTarget(&aTarget),
45 mObservedBox(aBox),
46 // This starts us with a 0,0 last-reported-size:
47 mLastReportedSize(aWM),
48 mLastReportedWM(aWM) {
49 MOZ_ASSERT(mTarget, "Need a non-null target element");
52 Element* Target() const { return mTarget; }
54 ResizeObserverBoxOptions BoxOptions() const { return mObservedBox; }
56 /**
57 * Returns whether the observed target element size differs from the saved
58 * mLastReportedSize.
60 bool IsActive() const;
62 /**
63 * Update current mLastReportedSize with size from aSize.
65 void UpdateLastReportedSize(const nsSize& aSize);
67 protected:
68 ~ResizeObservation() = default;
70 nsCOMPtr<Element> mTarget;
72 const ResizeObserverBoxOptions mObservedBox;
74 // The latest recorded size of observed target.
75 // Per the spec, observation.lastReportedSize should be entry.borderBoxSize
76 // or entry.contentBoxSize (i.e. logical size), instead of entry.contentRect
77 // (i.e. physical rect), so we store this as LogicalSize.
78 LogicalSize mLastReportedSize;
79 WritingMode mLastReportedWM;
82 /**
83 * ResizeObserver interfaces and algorithms are based on
84 * https://drafts.csswg.org/resize-observer/#api
86 class ResizeObserver final : public nsISupports, public nsWrapperCache {
87 public:
88 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
89 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObserver)
91 ResizeObserver(nsCOMPtr<nsPIDOMWindowInner>&& aOwner, Document* aDocument,
92 ResizeObserverCallback& aCb)
93 : mOwner(std::move(aOwner)), mDocument(aDocument), mCallback(&aCb) {
94 MOZ_ASSERT(mOwner, "Need a non-null owner window");
95 MOZ_ASSERT(mDocument, "Need a non-null doc");
96 MOZ_ASSERT(mDocument == mOwner->GetExtantDoc());
99 nsISupports* GetParentObject() const { return mOwner; }
101 JSObject* WrapObject(JSContext* aCx,
102 JS::Handle<JSObject*> aGivenProto) override {
103 return ResizeObserver_Binding::Wrap(aCx, this, aGivenProto);
106 static already_AddRefed<ResizeObserver> Constructor(
107 const GlobalObject& aGlobal, ResizeObserverCallback& aCb,
108 ErrorResult& aRv);
110 void Observe(Element& aTarget, const ResizeObserverOptions& aOptions,
111 ErrorResult& aRv);
113 void Unobserve(Element& target, ErrorResult& aRv);
115 void Disconnect();
118 * Gather all observations which have an observed target with size changed
119 * since last BroadcastActiveObservations() in this ResizeObserver.
120 * An observation will be skipped if the depth of its observed target is less
121 * or equal than aDepth. All gathered observations will be added to
122 * mActiveTargets.
124 void GatherActiveObservations(uint32_t aDepth);
127 * Returns whether this ResizeObserver has any active observations
128 * since last GatherActiveObservations().
130 bool HasActiveObservations() const { return !mActiveTargets.IsEmpty(); }
133 * Returns whether this ResizeObserver has any skipped observations
134 * since last GatherActiveObservations().
136 bool HasSkippedObservations() const { return mHasSkippedTargets; }
139 * Invoke the callback function in JavaScript for all active observations
140 * and pass the sequence of ResizeObserverEntry so JavaScript can access them.
141 * The active observations' mLastReportedSize fields will be updated, and
142 * mActiveTargets will be cleared. It also returns the shallowest depth of
143 * elements from active observations or numeric_limits<uint32_t>::max() if
144 * there are not any active observations.
146 MOZ_CAN_RUN_SCRIPT uint32_t BroadcastActiveObservations();
148 protected:
149 ~ResizeObserver() { mObservationList.clear(); }
151 nsCOMPtr<nsPIDOMWindowInner> mOwner;
152 // The window's document at the time of ResizeObserver creation.
153 RefPtr<Document> mDocument;
154 RefPtr<ResizeObserverCallback> mCallback;
155 nsTArray<RefPtr<ResizeObservation>> mActiveTargets;
156 // The spec uses a list to store the skipped targets. However, it seems what
157 // we want is to check if there are any skipped targets (i.e. existence).
158 // Therefore, we use a boolean value to represent the existence of skipped
159 // targets.
160 bool mHasSkippedTargets;
162 // Combination of HashTable and LinkedList so we can iterate through
163 // the elements of HashTable in order of insertion time, so we can deliver
164 // observations in the correct order
165 // FIXME: it will be nice if we have our own data structure for this in the
166 // future, and mObservationMap should be considered the "owning" storage for
167 // the observations, so it'd be better to drop mObservationList later.
168 nsRefPtrHashtable<nsPtrHashKey<Element>, ResizeObservation> mObservationMap;
169 LinkedList<ResizeObservation> mObservationList;
173 * ResizeObserverEntry is the entry that contains the information for observed
174 * elements. This object is the one that's visible to JavaScript in callback
175 * function that is fired by ResizeObserver.
177 class ResizeObserverEntry final : public nsISupports, public nsWrapperCache {
178 public:
179 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
180 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObserverEntry)
182 ResizeObserverEntry(nsISupports* aOwner, Element& aTarget,
183 const nsSize& aBorderBoxSize,
184 const nsSize& aContentBoxSize)
185 : mOwner(aOwner), mTarget(&aTarget) {
186 MOZ_ASSERT(mOwner, "Need a non-null owner");
187 MOZ_ASSERT(mTarget, "Need a non-null target element");
189 SetBorderBoxSize(aBorderBoxSize);
190 SetContentRectAndSize(aContentBoxSize);
193 nsISupports* GetParentObject() const { return mOwner; }
195 JSObject* WrapObject(JSContext* aCx,
196 JS::Handle<JSObject*> aGivenProto) override {
197 return ResizeObserverEntry_Binding::Wrap(aCx, this, aGivenProto);
200 Element* Target() const { return mTarget; }
203 * Returns the DOMRectReadOnly of target's content rect so it can be
204 * accessed from JavaScript in callback function of ResizeObserver.
206 DOMRectReadOnly* ContentRect() const { return mContentRect; }
209 * Returns target's logical border-box size and content-box size as
210 * ResizeObserverSize.
212 ResizeObserverSize* BorderBoxSize() const { return mBorderBoxSize; }
213 ResizeObserverSize* ContentBoxSize() const { return mContentBoxSize; }
215 private:
216 ~ResizeObserverEntry() = default;
218 // Set borderBoxSize.
219 void SetBorderBoxSize(const nsSize& aSize);
220 // Set contentRect and contentBoxSize.
221 void SetContentRectAndSize(const nsSize& aSize);
223 nsCOMPtr<nsISupports> mOwner;
224 nsCOMPtr<Element> mTarget;
226 RefPtr<DOMRectReadOnly> mContentRect;
227 RefPtr<ResizeObserverSize> mBorderBoxSize;
228 RefPtr<ResizeObserverSize> mContentBoxSize;
231 class ResizeObserverSize final : public nsISupports, public nsWrapperCache {
232 public:
233 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
234 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObserverSize)
236 // Note: the unit of |aSize| is app unit, and we convert it into css pixel in
237 // the public JS APIs.
238 ResizeObserverSize(nsISupports* aOwner, const nsSize& aSize,
239 const WritingMode aWM)
240 : mOwner(aOwner), mSize(aWM, aSize), mWM(aWM) {
241 MOZ_ASSERT(mOwner, "Need a non-null owner");
244 nsISupports* GetParentObject() const { return mOwner; }
246 JSObject* WrapObject(JSContext* aCx,
247 JS::Handle<JSObject*> aGivenProto) override {
248 return ResizeObserverSize_Binding::Wrap(aCx, this, aGivenProto);
251 double InlineSize() const {
252 return NSAppUnitsToDoublePixels(mSize.ISize(mWM), AppUnitsPerCSSPixel());
255 double BlockSize() const {
256 return NSAppUnitsToDoublePixels(mSize.BSize(mWM), AppUnitsPerCSSPixel());
259 protected:
260 ~ResizeObserverSize() = default;
262 nsCOMPtr<nsISupports> mOwner;
263 const LogicalSize mSize;
264 const WritingMode mWM;
267 } // namespace dom
268 } // namespace mozilla
270 #endif // mozilla_dom_ResizeObserver_h