diff options
Diffstat (limited to '')
-rw-r--r-- | dom/base/nsDOMNavigationTiming.h | 282 |
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___ */ |