nsDOMNavigationTiming.h (8855B)
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/. */ 6 7 #ifndef nsDOMNavigationTiming_h___ 8 #define nsDOMNavigationTiming_h___ 9 10 #include "mozilla/BaseProfilerMarkersPrerequisites.h" 11 #include "mozilla/RelativeTimeline.h" 12 #include "mozilla/TimeStamp.h" 13 #include "mozilla/WeakPtr.h" 14 #include "nsCOMArray.h" 15 #include "nsCOMPtr.h" 16 #include "nsITimer.h" 17 18 class nsDocShell; 19 class nsIURI; 20 21 using DOMTimeMilliSec = unsigned long long; 22 using DOMHighResTimeStamp = double; 23 24 class PickleIterator; 25 namespace IPC { 26 class Message; 27 class MessageReader; 28 class MessageWriter; 29 template <typename> 30 struct ParamTraits; 31 } // namespace IPC 32 33 class nsDOMNavigationTiming final : public mozilla::RelativeTimeline { 34 public: 35 enum Type { 36 TYPE_NAVIGATE = 0, 37 TYPE_RELOAD = 1, 38 TYPE_BACK_FORWARD = 2, 39 TYPE_RESERVED = 255, 40 }; 41 42 explicit nsDOMNavigationTiming(nsDocShell* aDocShell); 43 44 NS_INLINE_DECL_REFCOUNTING(nsDOMNavigationTiming) 45 46 Type GetType() const { return mNavigationType; } 47 48 inline DOMHighResTimeStamp GetNavigationStartHighRes() const { 49 return mNavigationStartHighRes; 50 } 51 52 DOMTimeMilliSec GetNavigationStart() const { 53 return static_cast<int64_t>(GetNavigationStartHighRes()); 54 } 55 56 mozilla::TimeStamp GetNavigationStartTimeStamp() const { 57 return mNavigationStart; 58 } 59 60 mozilla::TimeStamp GetLoadEventStartTimeStamp() const { 61 return mLoadEventStart; 62 } 63 64 mozilla::TimeStamp GetDOMContentLoadedEventStartTimeStamp() const { 65 return mDOMContentLoadedEventStart; 66 } 67 68 mozilla::TimeStamp GetFirstContentfulCompositeTimeStamp() const { 69 return mContentfulComposite; 70 } 71 72 mozilla::TimeStamp GetLargestContentfulRenderTimeStamp() const { 73 return mLargestContentfulRender; 74 } 75 76 DOMTimeMilliSec GetUnloadEventStart() { 77 return TimeStampToDOM(GetUnloadEventStartTimeStamp()); 78 } 79 80 DOMTimeMilliSec GetUnloadEventEnd() { 81 return TimeStampToDOM(GetUnloadEventEndTimeStamp()); 82 } 83 84 DOMTimeMilliSec GetDomLoading() const { return TimeStampToDOM(mDOMLoading); } 85 DOMTimeMilliSec GetDomInteractive() const { 86 return TimeStampToDOM(mDOMInteractive); 87 } 88 DOMTimeMilliSec GetDomContentLoadedEventStart() const { 89 return TimeStampToDOM(mDOMContentLoadedEventStart); 90 } 91 DOMTimeMilliSec GetDomContentLoadedEventEnd() const { 92 return TimeStampToDOM(mDOMContentLoadedEventEnd); 93 } 94 DOMTimeMilliSec GetDomComplete() const { 95 return TimeStampToDOM(mDOMComplete); 96 } 97 DOMTimeMilliSec GetLoadEventStart() const { 98 return TimeStampToDOM(mLoadEventStart); 99 } 100 DOMTimeMilliSec GetLoadEventEnd() const { 101 return TimeStampToDOM(mLoadEventEnd); 102 } 103 DOMTimeMilliSec GetTimeToNonBlankPaint() const { 104 return TimeStampToDOM(mNonBlankPaint); 105 } 106 DOMTimeMilliSec GetTimeToContentfulComposite() const { 107 return TimeStampToDOM(mContentfulComposite); 108 } 109 DOMTimeMilliSec GetTimeToLargestContentfulRender() const { 110 return TimeStampToDOM(mLargestContentfulRender); 111 } 112 DOMTimeMilliSec GetTimeToTTFI() const { return TimeStampToDOM(mTTFI); } 113 114 DOMHighResTimeStamp GetUnloadEventStartHighRes() { 115 mozilla::TimeStamp stamp = GetUnloadEventStartTimeStamp(); 116 if (stamp.IsNull()) { 117 return 0; 118 } 119 return TimeStampToDOMHighRes(stamp); 120 } 121 DOMHighResTimeStamp GetUnloadEventEndHighRes() { 122 mozilla::TimeStamp stamp = GetUnloadEventEndTimeStamp(); 123 if (stamp.IsNull()) { 124 return 0; 125 } 126 return TimeStampToDOMHighRes(stamp); 127 } 128 DOMHighResTimeStamp GetDomInteractiveHighRes() const { 129 return TimeStampToDOMHighRes(mDOMInteractive); 130 } 131 DOMHighResTimeStamp GetDomContentLoadedEventStartHighRes() const { 132 return TimeStampToDOMHighRes(mDOMContentLoadedEventStart); 133 } 134 DOMHighResTimeStamp GetDomContentLoadedEventEndHighRes() const { 135 return TimeStampToDOMHighRes(mDOMContentLoadedEventEnd); 136 } 137 DOMHighResTimeStamp GetDomCompleteHighRes() const { 138 return TimeStampToDOMHighRes(mDOMComplete); 139 } 140 DOMHighResTimeStamp GetLoadEventStartHighRes() const { 141 return TimeStampToDOMHighRes(mLoadEventStart); 142 } 143 DOMHighResTimeStamp GetLoadEventEndHighRes() const { 144 return TimeStampToDOMHighRes(mLoadEventEnd); 145 } 146 147 enum class DocShellState : uint8_t { eActive, eInactive }; 148 149 void NotifyNavigationStart(DocShellState aDocShellState); 150 void NotifyFetchStart(nsIURI* aURI, Type aNavigationType); 151 // A restoration occurs when the document is loaded from the 152 // bfcache. This method sets the appropriate parameters of the 153 // navigation timing object in this case. 154 void NotifyRestoreStart(); 155 void NotifyBeforeUnload(); 156 void NotifyUnloadAccepted(nsIURI* aOldURI); 157 void NotifyUnloadEventStart(); 158 void NotifyUnloadEventEnd(); 159 void NotifyLoadEventStart(); 160 void NotifyLoadEventEnd(); 161 162 // Document changes state to 'loading' before connecting to timing 163 void SetDOMLoadingTimeStamp(nsIURI* aURI, mozilla::TimeStamp aValue); 164 void NotifyDOMLoading(nsIURI* aURI); 165 void NotifyDOMInteractive(nsIURI* aURI); 166 void NotifyDOMComplete(nsIURI* aURI); 167 void NotifyDOMContentLoadedStart(nsIURI* aURI); 168 void NotifyDOMContentLoadedEnd(nsIURI* aURI); 169 170 static void TTITimeoutCallback(nsITimer* aTimer, void* aClosure); 171 void TTITimeout(nsITimer* aTimer); 172 173 void NotifyLongTask(mozilla::TimeStamp aWhen); 174 void NotifyNonBlankPaintForRootContentDocument(); 175 void NotifyContentfulCompositeForRootContentDocument( 176 const mozilla::TimeStamp& aCompositeEndTime); 177 void NotifyLargestContentfulRenderForRootContentDocument( 178 const DOMHighResTimeStamp& aRenderTime); 179 void NotifyDocShellStateChanged(DocShellState aDocShellState); 180 181 void MaybeAddLCPProfilerMarker(mozilla::MarkerInnerWindowId aInnerWindowID); 182 183 DOMTimeMilliSec TimeStampToDOM(mozilla::TimeStamp aStamp) const; 184 185 inline DOMHighResTimeStamp TimeStampToDOMHighRes( 186 mozilla::TimeStamp aStamp) const { 187 if (aStamp.IsNull()) { 188 return 0; 189 } 190 mozilla::TimeDuration duration = aStamp - mNavigationStart; 191 return duration.ToMilliseconds(); 192 } 193 194 // Called by the DocumentLoadListener before sending the timing information 195 // to the new content process. 196 void Anonymize(nsIURI* aFinalURI); 197 198 inline already_AddRefed<nsDOMNavigationTiming> CloneNavigationTime( 199 nsDocShell* aDocShell) const { 200 RefPtr<nsDOMNavigationTiming> timing = new nsDOMNavigationTiming(aDocShell); 201 timing->mNavigationStartHighRes = mNavigationStartHighRes; 202 timing->mNavigationStart = mNavigationStart; 203 return timing.forget(); 204 } 205 206 bool DocShellHasBeenActiveSinceNavigationStart() const { 207 return mDocShellHasBeenActiveSinceNavigationStart; 208 } 209 210 mozilla::TimeStamp LoadEventEnd() { return mLoadEventEnd; } 211 212 private: 213 friend class nsDocShell; 214 nsDOMNavigationTiming(nsDocShell* aDocShell, nsDOMNavigationTiming* aOther); 215 nsDOMNavigationTiming(const nsDOMNavigationTiming&) = delete; 216 ~nsDOMNavigationTiming(); 217 218 void Clear(); 219 220 mozilla::TimeStamp GetUnloadEventStartTimeStamp() const; 221 mozilla::TimeStamp GetUnloadEventEndTimeStamp() const; 222 223 bool IsTopLevelContentDocumentInContentProcess() const; 224 225 // Should those be amended, the IPC serializer should be updated 226 // accordingly. 227 mozilla::WeakPtr<nsDocShell> mDocShell; 228 229 nsCOMPtr<nsIURI> mUnloadedURI; 230 nsCOMPtr<nsIURI> mLoadedURI; 231 nsCOMPtr<nsITimer> mTTITimer; 232 233 Type mNavigationType; 234 DOMHighResTimeStamp mNavigationStartHighRes; 235 mozilla::TimeStamp mNavigationStart; 236 mozilla::TimeStamp mNonBlankPaint; 237 mozilla::TimeStamp mContentfulComposite; 238 mozilla::TimeStamp mLargestContentfulRender; 239 240 mozilla::TimeStamp mBeforeUnloadStart; 241 mozilla::TimeStamp mUnloadStart; 242 mozilla::TimeStamp mUnloadEnd; 243 mozilla::TimeStamp mLoadEventStart; 244 mozilla::TimeStamp mLoadEventEnd; 245 246 mozilla::TimeStamp mDOMLoading; 247 mozilla::TimeStamp mDOMInteractive; 248 mozilla::TimeStamp mDOMContentLoadedEventStart; 249 mozilla::TimeStamp mDOMContentLoadedEventEnd; 250 mozilla::TimeStamp mDOMComplete; 251 252 mozilla::TimeStamp mTTFI; 253 254 bool mDocShellHasBeenActiveSinceNavigationStart; 255 256 friend struct IPC::ParamTraits<nsDOMNavigationTiming*>; 257 }; 258 259 // IPDL serializer. Please be aware of the caveats in sending across 260 // the information and the potential resulting data leakage. 261 // For now, this serializer is to only be used under a very narrowed scope 262 // so that only the starting times are ever set. 263 namespace IPC { 264 265 template <> 266 struct ParamTraits<nsDOMNavigationTiming*> { 267 static void Write(MessageWriter* aWriter, nsDOMNavigationTiming* aParam); 268 static bool Read(MessageReader* aReader, 269 RefPtr<nsDOMNavigationTiming>* aResult); 270 }; 271 272 } // namespace IPC 273 274 #endif /* nsDOMNavigationTiming_h___ */