diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /dom/performance/LargestContentfulPaint.h | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/performance/LargestContentfulPaint.h')
-rw-r--r-- | dom/performance/LargestContentfulPaint.h | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/dom/performance/LargestContentfulPaint.h b/dom/performance/LargestContentfulPaint.h new file mode 100644 index 0000000000..0193cd858a --- /dev/null +++ b/dom/performance/LargestContentfulPaint.h @@ -0,0 +1,236 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_LargestContentfulPaint_h___ +#define mozilla_dom_LargestContentfulPaint_h___ + +#include "nsCycleCollectionParticipant.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/PerformanceEntry.h" +#include "mozilla/dom/PerformanceLargestContentfulPaintBinding.h" + +#include "imgRequestProxy.h" + +class nsTextFrame; +namespace mozilla::dom { + +static constexpr nsLiteralString kLargestContentfulPaintName = + u"largest-contentful-paint"_ns; + +class Performance; +class PerformanceMainThread; + +struct LCPImageEntryKey { + LCPImageEntryKey(Element* aElement, imgRequestProxy* aImgRequestProxy) + : mElement(do_GetWeakReference(aElement)), + mImageRequestProxy(aImgRequestProxy) { + MOZ_ASSERT(aElement); + MOZ_ASSERT(aImgRequestProxy); + + mHash = mozilla::HashGeneric(reinterpret_cast<uintptr_t>(aElement), + reinterpret_cast<uintptr_t>(aImgRequestProxy)); + } + + LCPImageEntryKey(const LCPImageEntryKey& aLCPImageEntryKey) { + mElement = aLCPImageEntryKey.mElement; + mImageRequestProxy = aLCPImageEntryKey.mImageRequestProxy; + mHash = aLCPImageEntryKey.mHash; + } + + Element* GetElement() const { + nsCOMPtr<Element> element = do_QueryReferent(mElement); + return element; + } + + imgRequestProxy* GetImgRequestProxy() const { + return static_cast<imgRequestProxy*>(mImageRequestProxy.get()); + } + + bool operator==(const LCPImageEntryKey& aOther) const { + imgRequestProxy* imgRequest = GetImgRequestProxy(); + if (!imgRequest) { + return false; + } + + imgRequestProxy* otherImgRequest = aOther.GetImgRequestProxy(); + if (!otherImgRequest) { + return false; + } + + Element* element = GetElement(); + if (!element) { + return false; + } + + Element* otherElement = aOther.GetElement(); + if (!otherElement) { + return false; + } + + return element == otherElement && imgRequest == otherImgRequest; + } + + bool Equals(const Element* aElement, + const imgRequestProxy* aImgRequestProxy) const { + Element* element = GetElement(); + if (!element || !mImageRequestProxy) { + return false; + } + + return element == aElement && mImageRequestProxy == mImageRequestProxy; + } + + nsWeakPtr mElement; + + WeakPtr<PreloaderBase> mImageRequestProxy; + + PLDHashNumber mHash = 0; + + ~LCPImageEntryKey() = default; +}; + +struct LCPTextFrameHelper final { + static void MaybeUnionTextFrame(nsTextFrame* aTextFrame, + const nsRect& aRelativeToSelfRect); +}; + +class ImagePendingRendering final { + public: + ImagePendingRendering(const LCPImageEntryKey& aLCPImageEntryKey, + const TimeStamp& aLoadTime); + + Element* GetElement() const { return mLCPImageEntryKey.GetElement(); } + + imgRequestProxy* GetImgRequestProxy() const { + return mLCPImageEntryKey.GetImgRequestProxy(); + } + + LCPImageEntryKey mLCPImageEntryKey; + TimeStamp mLoadTime; +}; + +class LCPEntryHashEntry : public PLDHashEntryHdr { + public: + typedef const LCPImageEntryKey& KeyType; + typedef const LCPImageEntryKey* KeyTypePointer; + + explicit LCPEntryHashEntry(KeyTypePointer aKey) : mKey(*aKey) {} + LCPEntryHashEntry(LCPEntryHashEntry&&) = default; + + ~LCPEntryHashEntry() = default; + + bool KeyEquals(KeyTypePointer aKey) const { return mKey == *aKey; } + + KeyType GetKey() const { return mKey; } + + static KeyTypePointer KeyToPointer(KeyType& aKey) { return &aKey; } + + static PLDHashNumber HashKey(KeyTypePointer aKey) { return aKey->mHash; } + enum { ALLOW_MEMMOVE = true }; + + LCPImageEntryKey mKey; +}; + +class LCPHelpers final { + public: + // Creates the LCP Entry for images with all information except the size of + // the element. The size of the image is unknown at the moment. The entry is + // not going to be queued in this function. + static void CreateLCPEntryForImage( + PerformanceMainThread* aPerformance, Element* aElement, + imgRequestProxy* aRequestProxy, const TimeStamp& aLoadTime, + const TimeStamp& aRenderTime, const LCPImageEntryKey& aContentIdentifier); + + // Called when the size of the image is known. + static void FinalizeLCPEntryForImage(Element* aContainingBlock, + imgRequestProxy* aImgRequestProxy, + const nsRect& aTargetRectRelativeToSelf); + + static void FinalizeLCPEntryForText(PerformanceMainThread* aPerformance, + const TimeStamp& aRenderTime, + Element* aContainingBlock, + const nsRect& aTargetRectRelativeToSelf, + const nsPresContext* aPresContext); + + static bool IsQualifiedImageRequest(imgRequest* aRequest, + Element* aContainingElement); + + private: + static bool CanFinalizeLCPEntry(const nsIFrame* aFrame); +}; + +// https://w3c.github.io/largest-contentful-paint/ +class LargestContentfulPaint final : public PerformanceEntry { + public: + NS_DECL_ISUPPORTS_INHERITED + + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(LargestContentfulPaint, + PerformanceEntry) + + LargestContentfulPaint(PerformanceMainThread* aPerformance, + const TimeStamp& aRenderTime, + const Maybe<TimeStamp>& aLoadTime, + const unsigned long aSize, nsIURI* aURI, + Element* aElement, + const Maybe<const LCPImageEntryKey>& aLCPImageEntryKey, + bool aShouldExposeRenderTime); + + JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + + DOMHighResTimeStamp RenderTime() const; + DOMHighResTimeStamp LoadTime() const; + DOMHighResTimeStamp StartTime() const override; + + unsigned long Size() const { return mSize; } + void GetId(nsAString& aId) const { + if (mId) { + mId->ToString(aId); + } + } + void GetUrl(nsAString& aUrl); + + Element* GetElement() const; + + static Element* GetContainingBlockForTextFrame(const nsTextFrame* aTextFrame); + + void UpdateSize(const Element* aContainingBlock, + const nsRect& aTargetRectRelativeToSelf, + const PerformanceMainThread* aPerformance, bool aIsImage); + + void BufferEntryIfNeeded() override; + + static void MaybeProcessImageForElementTiming(imgRequestProxy* aRequest, + Element* aElement); + + void QueueEntry(); + + Maybe<LCPImageEntryKey>& GetLCPImageEntryKey() { return mLCPImageEntryKey; } + + private: + ~LargestContentfulPaint() = default; + + void ReportLCPToNavigationTimings(); + + RefPtr<PerformanceMainThread> mPerformance; + + // This is always set but only exposed to web content if + // mShouldExposeRenderTime is true. + const TimeStamp mRenderTime; + const Maybe<TimeStamp> mLoadTime; + // This is set to false when for security reasons web content it not allowed + // to see the RenderTime. + const bool mShouldExposeRenderTime; + unsigned long mSize; + nsCOMPtr<nsIURI> mURI; + + nsWeakPtr mElement; + RefPtr<nsAtom> mId; + + Maybe<LCPImageEntryKey> mLCPImageEntryKey; +}; +} // namespace mozilla::dom +#endif |