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 mozilla_dom_ResizeObserverController_h
8 #define mozilla_dom_ResizeObserverController_h
9 
10 #include "mozilla/dom/Document.h"
11 #include "mozilla/dom/ResizeObserver.h"
12 #include "mozilla/TimeStamp.h"
13 #include "nsRefreshObservers.h"
14 #include "nsTObserverArray.h"
15 
16 class nsRefreshDriver;
17 
18 namespace mozilla {
19 
20 class PresShell;
21 
22 namespace dom {
23 
24 class ResizeObserverController;
25 
26 /**
27  * ResizeObserverNotificationHelper will trigger ResizeObserver notifications
28  * by registering with the Refresh Driver.
29  */
30 class ResizeObserverNotificationHelper final : public nsARefreshObserver {
31  public:
NS_INLINE_DECL_REFCOUNTING(ResizeObserverNotificationHelper,override)32   NS_INLINE_DECL_REFCOUNTING(ResizeObserverNotificationHelper, override)
33 
34   explicit ResizeObserverNotificationHelper(ResizeObserverController* aOwner)
35       : mOwner(aOwner), mRegistered(false) {
36     MOZ_ASSERT(mOwner, "Need a non-null owner");
37   }
38 
39   MOZ_CAN_RUN_SCRIPT void WillRefresh(TimeStamp aTime) override;
40 
41   nsRefreshDriver* GetRefreshDriver() const;
42 
43   void Register();
44 
45   void Unregister();
46 
IsRegistered()47   bool IsRegistered() const { return mRegistered; }
48 
DetachFromOwner()49   void DetachFromOwner() { mOwner = nullptr; }
50 
51  private:
52   virtual ~ResizeObserverNotificationHelper();
53 
54   ResizeObserverController* mOwner;
55   bool mRegistered;
56 };
57 
58 /**
59  * ResizeObserverController contains the list of ResizeObservers and controls
60  * the flow of notification.
61  */
62 class ResizeObserverController final {
63  public:
ResizeObserverController(Document * aDocument)64   explicit ResizeObserverController(Document* aDocument)
65       : mDocument(aDocument),
66         mResizeObserverNotificationHelper(
67             new ResizeObserverNotificationHelper(this)) {
68     MOZ_ASSERT(mDocument, "Need a non-null document");
69   }
70 
71   void AddSizeOfIncludingThis(nsWindowSizes&) const;
72 
73   void ShellDetachedFromDocument();
AddResizeObserver(ResizeObserver & aObserver)74   void AddResizeObserver(ResizeObserver& aObserver) {
75     MOZ_ASSERT(!mResizeObservers.Contains(&aObserver));
76     mResizeObservers.AppendElement(&aObserver);
77   }
78 
RemoveResizeObserver(ResizeObserver & aObserver)79   void RemoveResizeObserver(ResizeObserver& aObserver) {
80     MOZ_ASSERT(mResizeObservers.Contains(&aObserver));
81     mResizeObservers.RemoveElement(&aObserver);
82   }
83 
84   /**
85    * Schedule the notification via ResizeObserverNotificationHelper refresh
86    * observer.
87    */
88   void ScheduleNotification();
89 
90   /**
91    * Notify all ResizeObservers by gathering and broadcasting all active
92    * observations.
93    */
94   MOZ_CAN_RUN_SCRIPT void Notify();
95 
GetPresShell()96   PresShell* GetPresShell() const { return mDocument->GetPresShell(); }
97 
98   ~ResizeObserverController();
99 
100  private:
101   /**
102    * Calls GatherActiveObservations(aDepth) for all ResizeObservers in this
103    * controller. All observations in each ResizeObserver with element's depth
104    * more than aDepth will be gathered.
105    */
106   void GatherAllActiveObservations(uint32_t aDepth);
107 
108   /**
109    * Calls BroadcastActiveObservations() for all ResizeObservers in this
110    * controller. It also returns the shallowest depth of observed target
111    * elements with active observations from all ResizeObservers or
112    * numeric_limits<uint32_t>::max() if there aren't any active observations
113    * at all.
114    */
115   MOZ_CAN_RUN_SCRIPT uint32_t BroadcastAllActiveObservations();
116 
117   /**
118    * Returns whether there is any ResizeObserver that has active observations.
119    */
120   bool HasAnyActiveObservations() const;
121 
122   /**
123    * Returns whether there is any ResizeObserver that has skipped observations.
124    */
125   bool HasAnySkippedObservations() const;
126 
127   // Raw pointer is OK because mDocument strongly owns us & hence must outlive
128   // us.
129   Document* const mDocument;
130 
131   RefPtr<ResizeObserverNotificationHelper> mResizeObserverNotificationHelper;
132   nsTArray<ResizeObserver*> mResizeObservers;
133 };
134 
135 }  // namespace dom
136 }  // namespace mozilla
137 
138 #endif  // mozilla_dom_ResizeObserverController_h
139