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
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_LargestContentfulPaint_h___
8 #define mozilla_dom_LargestContentfulPaint_h___
10 #include "nsCycleCollectionParticipant.h"
11 #include "mozilla/dom/Element.h"
12 #include "mozilla/dom/PerformanceEntry.h"
13 #include "mozilla/dom/PerformanceLargestContentfulPaintBinding.h"
15 #include "imgRequestProxy.h"
18 namespace mozilla::dom
{
20 static constexpr nsLiteralString kLargestContentfulPaintName
=
21 u
"largest-contentful-paint"_ns
;
24 class PerformanceMainThread
;
26 struct LCPImageEntryKey
{
27 LCPImageEntryKey(Element
* aElement
, imgRequestProxy
* aImgRequestProxy
)
28 : mElement(do_GetWeakReference(aElement
)),
29 mImageRequestProxy(aImgRequestProxy
) {
31 MOZ_ASSERT(aImgRequestProxy
);
33 mHash
= mozilla::HashGeneric(reinterpret_cast<uintptr_t>(aElement
),
34 reinterpret_cast<uintptr_t>(aImgRequestProxy
));
37 LCPImageEntryKey(const LCPImageEntryKey
& aLCPImageEntryKey
) {
38 mElement
= aLCPImageEntryKey
.mElement
;
39 mImageRequestProxy
= aLCPImageEntryKey
.mImageRequestProxy
;
40 mHash
= aLCPImageEntryKey
.mHash
;
43 Element
* GetElement() const {
44 nsCOMPtr
<Element
> element
= do_QueryReferent(mElement
);
48 imgRequestProxy
* GetImgRequestProxy() const {
49 return static_cast<imgRequestProxy
*>(mImageRequestProxy
.get());
52 bool operator==(const LCPImageEntryKey
& aOther
) const {
53 imgRequestProxy
* imgRequest
= GetImgRequestProxy();
58 imgRequestProxy
* otherImgRequest
= aOther
.GetImgRequestProxy();
59 if (!otherImgRequest
) {
63 Element
* element
= GetElement();
68 Element
* otherElement
= aOther
.GetElement();
73 return element
== otherElement
&& imgRequest
== otherImgRequest
;
78 WeakPtr
<PreloaderBase
> mImageRequestProxy
;
80 PLDHashNumber mHash
= 0;
82 ~LCPImageEntryKey() = default;
85 struct LCPTextFrameHelper final
{
86 static void MaybeUnionTextFrame(nsTextFrame
* aTextFrame
,
87 const nsRect
& aRelativeToSelfRect
);
90 class ImagePendingRendering final
{
92 ImagePendingRendering(const LCPImageEntryKey
& aLCPImageEntryKey
,
93 const TimeStamp
& aLoadTime
);
95 Element
* GetElement() const { return mLCPImageEntryKey
.GetElement(); }
97 imgRequestProxy
* GetImgRequestProxy() const {
98 return mLCPImageEntryKey
.GetImgRequestProxy();
101 LCPImageEntryKey mLCPImageEntryKey
;
105 class LCPEntryHashEntry
: public PLDHashEntryHdr
{
107 typedef const LCPImageEntryKey
& KeyType
;
108 typedef const LCPImageEntryKey
* KeyTypePointer
;
110 explicit LCPEntryHashEntry(KeyTypePointer aKey
) : mKey(*aKey
) {}
111 LCPEntryHashEntry(LCPEntryHashEntry
&&) = default;
113 ~LCPEntryHashEntry() = default;
115 bool KeyEquals(KeyTypePointer aKey
) const { return mKey
== *aKey
; }
117 KeyType
GetKey() const { return mKey
; }
119 static KeyTypePointer
KeyToPointer(KeyType
& aKey
) { return &aKey
; }
121 static PLDHashNumber
HashKey(KeyTypePointer aKey
) { return aKey
->mHash
; }
122 enum { ALLOW_MEMMOVE
= true };
124 LCPImageEntryKey mKey
;
127 class LCPHelpers final
{
129 // Creates the LCP Entry for images with all information except the size of
130 // the element. The size of the image is unknown at the moment. The entry is
131 // not going to be queued in this function.
132 static void CreateLCPEntryForImage(
133 PerformanceMainThread
* aPerformance
, Element
* aElement
,
134 imgRequestProxy
* aRequestProxy
, const TimeStamp
& aLoadTime
,
135 const TimeStamp
& aRenderTime
, const LCPImageEntryKey
& aContentIdentifier
);
137 // Called when the size of the image is known.
138 static void FinalizeLCPEntryForImage(Element
* aContainingBlock
,
139 imgRequestProxy
* aImgRequestProxy
,
140 const nsRect
& aTargetRectRelativeToSelf
);
142 static void FinalizeLCPEntryForText(PerformanceMainThread
* aPerformance
,
143 const TimeStamp
& aRenderTime
,
144 Element
* aContainingBlock
,
145 const nsRect
& aTargetRectRelativeToSelf
,
146 const nsPresContext
* aPresContext
);
148 static bool IsQualifiedImageRequest(imgRequest
* aRequest
,
149 Element
* aContainingElement
);
152 static bool CanFinalizeLCPEntry(const nsIFrame
* aFrame
);
155 // https://w3c.github.io/largest-contentful-paint/
156 class LargestContentfulPaint final
: public PerformanceEntry
{
158 NS_DECL_ISUPPORTS_INHERITED
160 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(LargestContentfulPaint
,
163 LargestContentfulPaint(PerformanceMainThread
* aPerformance
,
164 const TimeStamp
& aRenderTime
,
165 const Maybe
<TimeStamp
>& aLoadTime
,
166 const unsigned long aSize
, nsIURI
* aURI
,
168 const Maybe
<const LCPImageEntryKey
>& aLCPImageEntryKey
,
169 bool aShouldExposeRenderTime
);
171 JSObject
* WrapObject(JSContext
* aCx
,
172 JS::Handle
<JSObject
*> aGivenProto
) override
;
174 DOMHighResTimeStamp
RenderTime() const;
175 DOMHighResTimeStamp
LoadTime() const;
176 DOMHighResTimeStamp
StartTime() const override
;
178 unsigned long Size() const { return mSize
; }
179 void GetId(nsAString
& aId
) const {
184 void GetUrl(nsAString
& aUrl
);
186 Element
* GetElement() const;
188 static Element
* GetContainingBlockForTextFrame(const nsTextFrame
* aTextFrame
);
190 void UpdateSize(const Element
* aContainingBlock
,
191 const nsRect
& aTargetRectRelativeToSelf
,
192 const PerformanceMainThread
* aPerformance
, bool aIsImage
);
194 void BufferEntryIfNeeded() override
;
196 static void MaybeProcessImageForElementTiming(imgRequestProxy
* aRequest
,
201 Maybe
<LCPImageEntryKey
>& GetLCPImageEntryKey() { return mLCPImageEntryKey
; }
204 ~LargestContentfulPaint() = default;
206 void ReportLCPToNavigationTimings();
208 RefPtr
<PerformanceMainThread
> mPerformance
;
210 // This is always set but only exposed to web content if
211 // mShouldExposeRenderTime is true.
212 const TimeStamp mRenderTime
;
213 const Maybe
<TimeStamp
> mLoadTime
;
214 // This is set to false when for security reasons web content it not allowed
215 // to see the RenderTime.
216 const bool mShouldExposeRenderTime
;
218 nsCOMPtr
<nsIURI
> mURI
;
223 Maybe
<LCPImageEntryKey
> mLCPImageEntryKey
;
225 } // namespace mozilla::dom