summaryrefslogtreecommitdiffstats
path: root/dom/performance/LargestContentfulPaint.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /dom/performance/LargestContentfulPaint.h
parentInitial commit. (diff)
downloadfirefox-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.h236
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