summaryrefslogtreecommitdiffstats
path: root/dom/base/nsDOMNavigationTiming.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/base/nsDOMNavigationTiming.h282
1 files changed, 282 insertions, 0 deletions
diff --git a/dom/base/nsDOMNavigationTiming.h b/dom/base/nsDOMNavigationTiming.h
new file mode 100644
index 0000000000..dc6785000f
--- /dev/null
+++ b/dom/base/nsDOMNavigationTiming.h
@@ -0,0 +1,282 @@
+/* -*- 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 nsDOMNavigationTiming_h___
+#define nsDOMNavigationTiming_h___
+
+#include "nsCOMPtr.h"
+#include "nsCOMArray.h"
+#include "mozilla/WeakPtr.h"
+#include "mozilla/RelativeTimeline.h"
+#include "mozilla/TimeStamp.h"
+#include "mozilla/BaseProfilerMarkersPrerequisites.h"
+#include "nsITimer.h"
+
+class nsDocShell;
+class nsIURI;
+
+using DOMTimeMilliSec = unsigned long long;
+using DOMHighResTimeStamp = double;
+
+class PickleIterator;
+namespace IPC {
+class Message;
+class MessageReader;
+class MessageWriter;
+} // namespace IPC
+namespace mozilla::ipc {
+class IProtocol;
+template <typename>
+struct IPDLParamTraits;
+} // namespace mozilla::ipc
+
+class nsDOMNavigationTiming final : public mozilla::RelativeTimeline {
+ public:
+ enum Type {
+ TYPE_NAVIGATE = 0,
+ TYPE_RELOAD = 1,
+ TYPE_BACK_FORWARD = 2,
+ TYPE_RESERVED = 255,
+ };
+
+ explicit nsDOMNavigationTiming(nsDocShell* aDocShell);
+
+ NS_INLINE_DECL_REFCOUNTING(nsDOMNavigationTiming)
+
+ Type GetType() const { return mNavigationType; }
+
+ inline DOMHighResTimeStamp GetNavigationStartHighRes() const {
+ return mNavigationStartHighRes;
+ }
+
+ DOMTimeMilliSec GetNavigationStart() const {
+ return static_cast<int64_t>(GetNavigationStartHighRes());
+ }
+
+ mozilla::TimeStamp GetNavigationStartTimeStamp() const {
+ return mNavigationStart;
+ }
+
+ mozilla::TimeStamp GetLoadEventStartTimeStamp() const {
+ return mLoadEventStart;
+ }
+
+ mozilla::TimeStamp GetDOMContentLoadedEventStartTimeStamp() const {
+ return mDOMContentLoadedEventStart;
+ }
+
+ mozilla::TimeStamp GetFirstContentfulCompositeTimeStamp() const {
+ return mContentfulComposite;
+ }
+
+ mozilla::TimeStamp GetLargestContentfulRenderTimeStamp() const {
+ return mLargestContentfulRender;
+ }
+
+ DOMTimeMilliSec GetUnloadEventStart() {
+ return TimeStampToDOM(GetUnloadEventStartTimeStamp());
+ }
+
+ DOMTimeMilliSec GetUnloadEventEnd() {
+ return TimeStampToDOM(GetUnloadEventEndTimeStamp());
+ }
+
+ DOMTimeMilliSec GetDomLoading() const { return TimeStampToDOM(mDOMLoading); }
+ DOMTimeMilliSec GetDomInteractive() const {
+ return TimeStampToDOM(mDOMInteractive);
+ }
+ DOMTimeMilliSec GetDomContentLoadedEventStart() const {
+ return TimeStampToDOM(mDOMContentLoadedEventStart);
+ }
+ DOMTimeMilliSec GetDomContentLoadedEventEnd() const {
+ return TimeStampToDOM(mDOMContentLoadedEventEnd);
+ }
+ DOMTimeMilliSec GetDomComplete() const {
+ return TimeStampToDOM(mDOMComplete);
+ }
+ DOMTimeMilliSec GetLoadEventStart() const {
+ return TimeStampToDOM(mLoadEventStart);
+ }
+ DOMTimeMilliSec GetLoadEventEnd() const {
+ return TimeStampToDOM(mLoadEventEnd);
+ }
+ DOMTimeMilliSec GetTimeToNonBlankPaint() const {
+ return TimeStampToDOM(mNonBlankPaint);
+ }
+ DOMTimeMilliSec GetTimeToContentfulComposite() const {
+ return TimeStampToDOM(mContentfulComposite);
+ }
+ DOMTimeMilliSec GetTimeToLargestContentfulRender() const {
+ return TimeStampToDOM(mLargestContentfulRender);
+ }
+ DOMTimeMilliSec GetTimeToTTFI() const { return TimeStampToDOM(mTTFI); }
+ DOMTimeMilliSec GetTimeToDOMContentFlushed() const {
+ return TimeStampToDOM(mDOMContentFlushed);
+ }
+
+ DOMHighResTimeStamp GetUnloadEventStartHighRes() {
+ mozilla::TimeStamp stamp = GetUnloadEventStartTimeStamp();
+ if (stamp.IsNull()) {
+ return 0;
+ }
+ return TimeStampToDOMHighRes(stamp);
+ }
+ DOMHighResTimeStamp GetUnloadEventEndHighRes() {
+ mozilla::TimeStamp stamp = GetUnloadEventEndTimeStamp();
+ if (stamp.IsNull()) {
+ return 0;
+ }
+ return TimeStampToDOMHighRes(stamp);
+ }
+ DOMHighResTimeStamp GetDomInteractiveHighRes() const {
+ return TimeStampToDOMHighRes(mDOMInteractive);
+ }
+ DOMHighResTimeStamp GetDomContentLoadedEventStartHighRes() const {
+ return TimeStampToDOMHighRes(mDOMContentLoadedEventStart);
+ }
+ DOMHighResTimeStamp GetDomContentLoadedEventEndHighRes() const {
+ return TimeStampToDOMHighRes(mDOMContentLoadedEventEnd);
+ }
+ DOMHighResTimeStamp GetDomCompleteHighRes() const {
+ return TimeStampToDOMHighRes(mDOMComplete);
+ }
+ DOMHighResTimeStamp GetLoadEventStartHighRes() const {
+ return TimeStampToDOMHighRes(mLoadEventStart);
+ }
+ DOMHighResTimeStamp GetLoadEventEndHighRes() const {
+ return TimeStampToDOMHighRes(mLoadEventEnd);
+ }
+
+ enum class DocShellState : uint8_t { eActive, eInactive };
+
+ void NotifyNavigationStart(DocShellState aDocShellState);
+ void NotifyFetchStart(nsIURI* aURI, Type aNavigationType);
+ // A restoration occurs when the document is loaded from the
+ // bfcache. This method sets the appropriate parameters of the
+ // navigation timing object in this case.
+ void NotifyRestoreStart();
+ void NotifyBeforeUnload();
+ void NotifyUnloadAccepted(nsIURI* aOldURI);
+ void NotifyUnloadEventStart();
+ void NotifyUnloadEventEnd();
+ void NotifyLoadEventStart();
+ void NotifyLoadEventEnd();
+
+ // Document changes state to 'loading' before connecting to timing
+ void SetDOMLoadingTimeStamp(nsIURI* aURI, mozilla::TimeStamp aValue);
+ void NotifyDOMLoading(nsIURI* aURI);
+ void NotifyDOMInteractive(nsIURI* aURI);
+ void NotifyDOMComplete(nsIURI* aURI);
+ void NotifyDOMContentLoadedStart(nsIURI* aURI);
+ void NotifyDOMContentLoadedEnd(nsIURI* aURI);
+
+ static void TTITimeoutCallback(nsITimer* aTimer, void* aClosure);
+ void TTITimeout(nsITimer* aTimer);
+
+ void NotifyLongTask(mozilla::TimeStamp aWhen);
+ void NotifyNonBlankPaintForRootContentDocument();
+ void NotifyContentfulCompositeForRootContentDocument(
+ const mozilla::TimeStamp& aCompositeEndTime);
+ void NotifyLargestContentfulRenderForRootContentDocument(
+ const DOMHighResTimeStamp& aRenderTime);
+ void NotifyDOMContentFlushedForRootContentDocument();
+ void NotifyDocShellStateChanged(DocShellState aDocShellState);
+
+ void MaybeAddLCPProfilerMarker(mozilla::MarkerInnerWindowId aInnerWindowID);
+
+ DOMTimeMilliSec TimeStampToDOM(mozilla::TimeStamp aStamp) const;
+
+ inline DOMHighResTimeStamp TimeStampToDOMHighRes(
+ mozilla::TimeStamp aStamp) const {
+ if (aStamp.IsNull()) {
+ return 0;
+ }
+ mozilla::TimeDuration duration = aStamp - mNavigationStart;
+ return duration.ToMilliseconds();
+ }
+
+ // Called by the DocumentLoadListener before sending the timing information
+ // to the new content process.
+ void Anonymize(nsIURI* aFinalURI);
+
+ inline already_AddRefed<nsDOMNavigationTiming> CloneNavigationTime(
+ nsDocShell* aDocShell) const {
+ RefPtr<nsDOMNavigationTiming> timing = new nsDOMNavigationTiming(aDocShell);
+ timing->mNavigationStartHighRes = mNavigationStartHighRes;
+ timing->mNavigationStart = mNavigationStart;
+ return timing.forget();
+ }
+
+ bool DocShellHasBeenActiveSinceNavigationStart() {
+ return mDocShellHasBeenActiveSinceNavigationStart;
+ }
+
+ mozilla::TimeStamp LoadEventEnd() { return mLoadEventEnd; }
+
+ private:
+ friend class nsDocShell;
+ nsDOMNavigationTiming(nsDocShell* aDocShell, nsDOMNavigationTiming* aOther);
+ nsDOMNavigationTiming(const nsDOMNavigationTiming&) = delete;
+ ~nsDOMNavigationTiming();
+
+ void Clear();
+
+ mozilla::TimeStamp GetUnloadEventStartTimeStamp() const;
+ mozilla::TimeStamp GetUnloadEventEndTimeStamp() const;
+
+ bool IsTopLevelContentDocumentInContentProcess() const;
+
+ // Should those be amended, the IPC serializer should be updated
+ // accordingly.
+ mozilla::WeakPtr<nsDocShell> mDocShell;
+
+ nsCOMPtr<nsIURI> mUnloadedURI;
+ nsCOMPtr<nsIURI> mLoadedURI;
+ nsCOMPtr<nsITimer> mTTITimer;
+
+ Type mNavigationType;
+ DOMHighResTimeStamp mNavigationStartHighRes;
+ mozilla::TimeStamp mNavigationStart;
+ mozilla::TimeStamp mNonBlankPaint;
+ mozilla::TimeStamp mContentfulComposite;
+ mozilla::TimeStamp mLargestContentfulRender;
+ mozilla::TimeStamp mDOMContentFlushed;
+
+ mozilla::TimeStamp mBeforeUnloadStart;
+ mozilla::TimeStamp mUnloadStart;
+ mozilla::TimeStamp mUnloadEnd;
+ mozilla::TimeStamp mLoadEventStart;
+ mozilla::TimeStamp mLoadEventEnd;
+
+ mozilla::TimeStamp mDOMLoading;
+ mozilla::TimeStamp mDOMInteractive;
+ mozilla::TimeStamp mDOMContentLoadedEventStart;
+ mozilla::TimeStamp mDOMContentLoadedEventEnd;
+ mozilla::TimeStamp mDOMComplete;
+
+ mozilla::TimeStamp mTTFI;
+
+ bool mDocShellHasBeenActiveSinceNavigationStart;
+
+ friend struct mozilla::ipc::IPDLParamTraits<nsDOMNavigationTiming*>;
+};
+
+// IPDL serializer. Please be aware of the caveats in sending across
+// the information and the potential resulting data leakage.
+// For now, this serializer is to only be used under a very narrowed scope
+// so that only the starting times are ever set.
+namespace mozilla::ipc {
+template <>
+struct IPDLParamTraits<nsDOMNavigationTiming*> {
+ static void Write(IPC::MessageWriter* aWriter, IProtocol* aActor,
+ nsDOMNavigationTiming* aParam);
+ static bool Read(IPC::MessageReader* aReader, IProtocol* aActor,
+ RefPtr<nsDOMNavigationTiming>* aResult);
+};
+
+} // namespace mozilla::ipc
+
+#endif /* nsDOMNavigationTiming_h___ */