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/. */
7 #include "nsDOMNavigationTiming.h"
9 #include "GeckoProfiler.h"
10 #include "ipc/IPCMessageUtilsSpecializations.h"
11 #include "mozilla/ProfilerMarkers.h"
12 #include "mozilla/Telemetry.h"
13 #include "mozilla/TimeStamp.h"
14 #include "mozilla/dom/Document.h"
15 #include "mozilla/dom/PerformanceNavigation.h"
16 #include "mozilla/ipc/IPDLParamTraits.h"
17 #include "mozilla/ipc/URIUtils.h"
19 #include "nsContentUtils.h"
20 #include "nsDocShell.h"
22 #include "nsIScriptSecurityManager.h"
24 #include "nsPrintfCString.h"
27 using namespace mozilla
;
31 LazyLogModule
gPageLoadLog("PageLoad");
32 #define PAGELOAD_LOG(args) MOZ_LOG(gPageLoadLog, LogLevel::Debug, args)
33 #define PAGELOAD_LOG_ENABLED() MOZ_LOG_TEST(gPageLoadLog, LogLevel::Error)
35 } // namespace mozilla
37 nsDOMNavigationTiming::nsDOMNavigationTiming(nsDocShell
* aDocShell
) {
40 mDocShell
= aDocShell
;
43 nsDOMNavigationTiming::~nsDOMNavigationTiming() = default;
45 void nsDOMNavigationTiming::Clear() {
46 mNavigationType
= TYPE_RESERVED
;
47 mNavigationStartHighRes
= 0;
49 mBeforeUnloadStart
= TimeStamp();
50 mUnloadStart
= TimeStamp();
51 mUnloadEnd
= TimeStamp();
52 mLoadEventStart
= TimeStamp();
53 mLoadEventEnd
= TimeStamp();
54 mDOMLoading
= TimeStamp();
55 mDOMInteractive
= TimeStamp();
56 mDOMContentLoadedEventStart
= TimeStamp();
57 mDOMContentLoadedEventEnd
= TimeStamp();
58 mDOMComplete
= TimeStamp();
59 mContentfulComposite
= TimeStamp();
60 mNonBlankPaint
= TimeStamp();
62 mDocShellHasBeenActiveSinceNavigationStart
= false;
65 void nsDOMNavigationTiming::Anonymize(nsIURI
* aFinalURI
) {
66 mLoadedURI
= aFinalURI
;
67 mUnloadedURI
= nullptr;
68 mBeforeUnloadStart
= TimeStamp();
69 mUnloadStart
= TimeStamp();
70 mUnloadEnd
= TimeStamp();
73 DOMTimeMilliSec
nsDOMNavigationTiming::TimeStampToDOM(TimeStamp aStamp
) const {
74 if (aStamp
.IsNull()) {
78 TimeDuration duration
= aStamp
- mNavigationStart
;
79 return GetNavigationStart() + static_cast<int64_t>(duration
.ToMilliseconds());
82 void nsDOMNavigationTiming::NotifyNavigationStart(
83 DocShellState aDocShellState
) {
84 mNavigationStartHighRes
= (double)PR_Now() / PR_USEC_PER_MSEC
;
85 mNavigationStart
= TimeStamp::Now();
86 mDocShellHasBeenActiveSinceNavigationStart
=
87 (aDocShellState
== DocShellState::eActive
);
88 PROFILER_MARKER_UNTYPED("Navigation::Start", DOM
,
89 MarkerInnerWindowIdFromDocShell(mDocShell
));
92 void nsDOMNavigationTiming::NotifyFetchStart(nsIURI
* aURI
,
93 Type aNavigationType
) {
94 mNavigationType
= aNavigationType
;
95 // At the unload event time we don't really know the loading uri.
96 // Need it for later check for unload timing access.
100 void nsDOMNavigationTiming::NotifyRestoreStart() {
101 mNavigationType
= TYPE_BACK_FORWARD
;
104 void nsDOMNavigationTiming::NotifyBeforeUnload() {
105 mBeforeUnloadStart
= TimeStamp::Now();
108 void nsDOMNavigationTiming::NotifyUnloadAccepted(nsIURI
* aOldURI
) {
109 mUnloadStart
= mBeforeUnloadStart
;
110 mUnloadedURI
= aOldURI
;
113 void nsDOMNavigationTiming::NotifyUnloadEventStart() {
114 mUnloadStart
= TimeStamp::Now();
115 PROFILER_MARKER("Unload", NETWORK
,
116 MarkerOptions(MarkerTiming::IntervalStart(),
117 MarkerInnerWindowIdFromDocShell(mDocShell
)),
118 Tracing
, "Navigation");
121 void nsDOMNavigationTiming::NotifyUnloadEventEnd() {
122 mUnloadEnd
= TimeStamp::Now();
123 PROFILER_MARKER("Unload", NETWORK
,
124 MarkerOptions(MarkerTiming::IntervalEnd(),
125 MarkerInnerWindowIdFromDocShell(mDocShell
)),
126 Tracing
, "Navigation");
129 void nsDOMNavigationTiming::NotifyLoadEventStart() {
130 if (!mLoadEventStart
.IsNull()) {
133 mLoadEventStart
= TimeStamp::Now();
135 PROFILER_MARKER("Load", NETWORK
,
136 MarkerOptions(MarkerTiming::IntervalStart(),
137 MarkerInnerWindowIdFromDocShell(mDocShell
)),
138 Tracing
, "Navigation");
140 if (IsTopLevelContentDocumentInContentProcess()) {
141 TimeStamp now
= TimeStamp::Now();
143 Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_LOAD_EVENT_START_MS
,
144 mNavigationStart
, now
);
146 if (mDocShellHasBeenActiveSinceNavigationStart
) {
147 if (net::nsHttp::IsBeforeLastActiveTabLoadOptimization(
149 Telemetry::AccumulateTimeDelta(
150 Telemetry::TIME_TO_LOAD_EVENT_START_ACTIVE_NETOPT_MS
,
151 mNavigationStart
, now
);
153 Telemetry::AccumulateTimeDelta(
154 Telemetry::TIME_TO_LOAD_EVENT_START_ACTIVE_MS
, mNavigationStart
,
161 void nsDOMNavigationTiming::NotifyLoadEventEnd() {
162 if (!mLoadEventEnd
.IsNull()) {
165 mLoadEventEnd
= TimeStamp::Now();
167 PROFILER_MARKER("Load", NETWORK
,
168 MarkerOptions(MarkerTiming::IntervalEnd(),
169 MarkerInnerWindowIdFromDocShell(mDocShell
)),
170 Tracing
, "Navigation");
172 if (IsTopLevelContentDocumentInContentProcess()) {
173 if (profiler_thread_is_being_profiled_for_markers() ||
174 PAGELOAD_LOG_ENABLED()) {
175 TimeDuration elapsed
= mLoadEventEnd
- mNavigationStart
;
176 TimeDuration duration
= mLoadEventEnd
- mLoadEventStart
;
177 nsPrintfCString
marker(
178 "Document %s loaded after %dms, load event duration %dms",
179 nsContentUtils::TruncatedURLForDisplay(mLoadedURI
).get(),
180 int(elapsed
.ToMilliseconds()), int(duration
.ToMilliseconds()));
181 PAGELOAD_LOG(("%s", marker
.get()));
182 PROFILER_MARKER_TEXT(
184 MarkerOptions(MarkerTiming::Interval(mNavigationStart
, mLoadEventEnd
),
185 MarkerInnerWindowIdFromDocShell(mDocShell
)),
188 Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_LOAD_EVENT_END_MS
,
193 void nsDOMNavigationTiming::SetDOMLoadingTimeStamp(nsIURI
* aURI
,
195 if (!mDOMLoading
.IsNull()) {
199 mDOMLoading
= aValue
;
202 void nsDOMNavigationTiming::NotifyDOMLoading(nsIURI
* aURI
) {
203 if (!mDOMLoading
.IsNull()) {
207 mDOMLoading
= TimeStamp::Now();
209 PROFILER_MARKER_UNTYPED("Navigation::DOMLoading", DOM
,
210 MarkerInnerWindowIdFromDocShell(mDocShell
));
213 void nsDOMNavigationTiming::NotifyDOMInteractive(nsIURI
* aURI
) {
214 if (!mDOMInteractive
.IsNull()) {
218 mDOMInteractive
= TimeStamp::Now();
220 PROFILER_MARKER_UNTYPED("Navigation::DOMInteractive", DOM
,
221 MarkerInnerWindowIdFromDocShell(mDocShell
));
224 void nsDOMNavigationTiming::NotifyDOMComplete(nsIURI
* aURI
) {
225 if (!mDOMComplete
.IsNull()) {
229 mDOMComplete
= TimeStamp::Now();
231 PROFILER_MARKER_UNTYPED("Navigation::DOMComplete", DOM
,
232 MarkerInnerWindowIdFromDocShell(mDocShell
));
235 void nsDOMNavigationTiming::NotifyDOMContentLoadedStart(nsIURI
* aURI
) {
236 if (!mDOMContentLoadedEventStart
.IsNull()) {
241 mDOMContentLoadedEventStart
= TimeStamp::Now();
243 PROFILER_MARKER("DOMContentLoaded", NETWORK
,
244 MarkerOptions(MarkerTiming::IntervalStart(),
245 MarkerInnerWindowIdFromDocShell(mDocShell
)),
246 Tracing
, "Navigation");
248 if (IsTopLevelContentDocumentInContentProcess()) {
249 TimeStamp now
= TimeStamp::Now();
251 Telemetry::AccumulateTimeDelta(
252 Telemetry::TIME_TO_DOM_CONTENT_LOADED_START_MS
, mNavigationStart
, now
);
254 if (mDocShellHasBeenActiveSinceNavigationStart
) {
255 if (net::nsHttp::IsBeforeLastActiveTabLoadOptimization(
257 Telemetry::AccumulateTimeDelta(
258 Telemetry::TIME_TO_DOM_CONTENT_LOADED_START_ACTIVE_NETOPT_MS
,
259 mNavigationStart
, now
);
261 Telemetry::AccumulateTimeDelta(
262 Telemetry::TIME_TO_DOM_CONTENT_LOADED_START_ACTIVE_MS
,
263 mNavigationStart
, now
);
269 void nsDOMNavigationTiming::NotifyDOMContentLoadedEnd(nsIURI
* aURI
) {
270 if (!mDOMContentLoadedEventEnd
.IsNull()) {
275 mDOMContentLoadedEventEnd
= TimeStamp::Now();
277 PROFILER_MARKER("DOMContentLoaded", NETWORK
,
278 MarkerOptions(MarkerTiming::IntervalEnd(),
279 MarkerInnerWindowIdFromDocShell(mDocShell
)),
280 Tracing
, "Navigation");
282 if (IsTopLevelContentDocumentInContentProcess()) {
283 Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_DOM_CONTENT_LOADED_END_MS
,
289 void nsDOMNavigationTiming::TTITimeoutCallback(nsITimer
* aTimer
,
291 nsDOMNavigationTiming
* self
= static_cast<nsDOMNavigationTiming
*>(aClosure
);
292 self
->TTITimeout(aTimer
);
295 #define TTI_WINDOW_SIZE_MS (5 * 1000)
297 void nsDOMNavigationTiming::TTITimeout(nsITimer
* aTimer
) {
298 // Check TTI: see if it's been 5 seconds since the last Long Task
299 TimeStamp now
= TimeStamp::Now();
300 MOZ_RELEASE_ASSERT(!mContentfulComposite
.IsNull(),
301 "TTI timeout with no contentful-composite?");
303 nsCOMPtr
<nsIThread
> mainThread
= do_GetMainThread();
304 TimeStamp lastLongTaskEnded
;
305 mainThread
->GetLastLongNonIdleTaskEnd(&lastLongTaskEnded
);
306 // Window starts at mContentfulComposite; any long task before that is ignored
307 if (lastLongTaskEnded
.IsNull() || lastLongTaskEnded
< mContentfulComposite
) {
309 ("no longtask (last was %g ms before ContentfulComposite)",
310 lastLongTaskEnded
.IsNull()
312 : (mContentfulComposite
- lastLongTaskEnded
).ToMilliseconds()));
313 lastLongTaskEnded
= mContentfulComposite
;
315 TimeDuration delta
= now
- lastLongTaskEnded
;
316 PAGELOAD_LOG(("TTI delta: %g ms", delta
.ToMilliseconds()));
317 if (delta
.ToMilliseconds() < TTI_WINDOW_SIZE_MS
) {
318 // Less than 5 seconds since the last long task or start of the window.
319 // Schedule another check.
320 PAGELOAD_LOG(("TTI: waiting additional %g ms",
321 (TTI_WINDOW_SIZE_MS
+ 100) - delta
.ToMilliseconds()));
322 aTimer
->InitWithNamedFuncCallback(
323 TTITimeoutCallback
, this,
324 (TTI_WINDOW_SIZE_MS
+ 100) -
325 delta
.ToMilliseconds(), // slightly after the window ends
326 nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY
,
327 "nsDOMNavigationTiming::TTITimeout");
331 // To correctly implement TTI/TTFI as proposed, we'd need to not
332 // fire it until there are no more than 2 network loads. By the
333 // proposed definition, without that we're closer to
334 // TimeToFirstInteractive. There are also arguments about what sort
335 // of loads should qualify.
337 // XXX check number of network loads, and if > 2 mark to check if loads
338 // decreases to 2 (or record that point and let the normal timer here
341 // TTI has occurred! TTI is either FCP (if there are no longtasks and no
342 // DCLEnd in the window that starts at FCP), or at the end of the last
343 // Long Task or DOMContentLoadedEnd (whichever is later). lastLongTaskEnded
346 if (mTTFI
.IsNull()) {
347 // lastLongTaskEnded is >= mContentfulComposite
348 mTTFI
= (mDOMContentLoadedEventEnd
.IsNull() ||
349 lastLongTaskEnded
> mDOMContentLoadedEventEnd
)
351 : mDOMContentLoadedEventEnd
;
353 ("TTFI after %dms (LongTask was at %dms, DCL was %dms)",
354 int((mTTFI
- mNavigationStart
).ToMilliseconds()),
355 lastLongTaskEnded
.IsNull()
357 : int((lastLongTaskEnded
- mNavigationStart
).ToMilliseconds()),
358 mDOMContentLoadedEventEnd
.IsNull()
360 : int((mDOMContentLoadedEventEnd
- mNavigationStart
)
361 .ToMilliseconds())));
363 // XXX Implement TTI via check number of network loads, and if > 2 mark
364 // to check if loads decreases to 2 (or record that point and let the
365 // normal timer here handle it)
369 if (profiler_thread_is_being_profiled_for_markers() ||
370 PAGELOAD_LOG_ENABLED()) {
371 TimeDuration elapsed
= mTTFI
- mNavigationStart
;
372 MOZ_ASSERT(elapsed
.ToMilliseconds() > 0);
373 TimeDuration elapsedLongTask
=
374 lastLongTaskEnded
.IsNull() ? 0 : lastLongTaskEnded
- mNavigationStart
;
375 nsPrintfCString
marker(
376 "TTFI after %dms (LongTask was at %dms) for URL %s",
377 int(elapsed
.ToMilliseconds()), int(elapsedLongTask
.ToMilliseconds()),
378 nsContentUtils::TruncatedURLForDisplay(mLoadedURI
).get());
380 PROFILER_MARKER_TEXT(
381 "TimeToFirstInteractive (TTFI)", DOM
,
382 MarkerOptions(MarkerTiming::Interval(mNavigationStart
, mTTFI
),
383 MarkerInnerWindowIdFromDocShell(mDocShell
)),
388 void nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument() {
389 MOZ_ASSERT(NS_IsMainThread());
390 MOZ_ASSERT(!mNavigationStart
.IsNull());
392 if (!mNonBlankPaint
.IsNull()) {
396 mNonBlankPaint
= TimeStamp::Now();
398 if (profiler_thread_is_being_profiled_for_markers() ||
399 PAGELOAD_LOG_ENABLED()) {
400 TimeDuration elapsed
= mNonBlankPaint
- mNavigationStart
;
401 nsPrintfCString
marker(
402 "Non-blank paint after %dms for URL %s, %s",
403 int(elapsed
.ToMilliseconds()),
404 nsContentUtils::TruncatedURLForDisplay(mLoadedURI
).get(),
405 mDocShellHasBeenActiveSinceNavigationStart
407 : "this tab was inactive some of the time between navigation start "
408 "and first non-blank paint");
409 PAGELOAD_LOG(("%s", marker
.get()));
410 PROFILER_MARKER_TEXT(
411 "FirstNonBlankPaint", DOM
,
412 MarkerOptions(MarkerTiming::Interval(mNavigationStart
, mNonBlankPaint
),
413 MarkerInnerWindowIdFromDocShell(mDocShell
)),
417 if (mDocShellHasBeenActiveSinceNavigationStart
) {
418 if (net::nsHttp::IsBeforeLastActiveTabLoadOptimization(mNavigationStart
)) {
419 Telemetry::AccumulateTimeDelta(
420 Telemetry::TIME_TO_NON_BLANK_PAINT_NETOPT_MS
, mNavigationStart
,
423 Telemetry::AccumulateTimeDelta(
424 Telemetry::TIME_TO_NON_BLANK_PAINT_NO_NETOPT_MS
, mNavigationStart
,
428 Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_NON_BLANK_PAINT_MS
,
429 mNavigationStart
, mNonBlankPaint
);
433 void nsDOMNavigationTiming::NotifyContentfulCompositeForRootContentDocument(
434 const mozilla::TimeStamp
& aCompositeEndTime
) {
435 MOZ_ASSERT(NS_IsMainThread());
436 MOZ_ASSERT(!mNavigationStart
.IsNull());
438 if (!mContentfulComposite
.IsNull()) {
442 mContentfulComposite
= aCompositeEndTime
;
444 if (profiler_thread_is_being_profiled_for_markers() ||
445 PAGELOAD_LOG_ENABLED()) {
446 TimeDuration elapsed
= mContentfulComposite
- mNavigationStart
;
447 nsPrintfCString
marker(
448 "Contentful composite after %dms for URL %s, %s",
449 int(elapsed
.ToMilliseconds()),
450 nsContentUtils::TruncatedURLForDisplay(mLoadedURI
).get(),
451 mDocShellHasBeenActiveSinceNavigationStart
453 : "this tab was inactive some of the time between navigation start "
454 "and first non-blank paint");
455 PAGELOAD_LOG(("%s", marker
.get()));
456 PROFILER_MARKER_TEXT(
457 "FirstContentfulComposite", DOM
,
459 MarkerTiming::Interval(mNavigationStart
, mContentfulComposite
),
460 MarkerInnerWindowIdFromDocShell(mDocShell
)),
465 mTTITimer
= NS_NewTimer();
468 // TTI is first checked 5 seconds after the FCP (non-blank-paint is very close
470 mTTITimer
->InitWithNamedFuncCallback(TTITimeoutCallback
, this,
472 nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY
,
473 "nsDOMNavigationTiming::TTITimeout");
475 if (mDocShellHasBeenActiveSinceNavigationStart
) {
476 Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_FIRST_CONTENTFUL_PAINT_MS
,
477 mNavigationStart
, mContentfulComposite
);
481 void nsDOMNavigationTiming::NotifyDOMContentFlushedForRootContentDocument() {
482 MOZ_ASSERT(NS_IsMainThread());
483 MOZ_ASSERT(!mNavigationStart
.IsNull());
485 if (!mDOMContentFlushed
.IsNull()) {
489 mDOMContentFlushed
= TimeStamp::Now();
491 if (profiler_thread_is_being_profiled_for_markers() ||
492 PAGELOAD_LOG_ENABLED()) {
493 TimeDuration elapsed
= mDOMContentFlushed
- mNavigationStart
;
494 nsPrintfCString
marker(
495 "DOMContentFlushed after %dms for URL %s, %s",
496 int(elapsed
.ToMilliseconds()),
497 nsContentUtils::TruncatedURLForDisplay(mLoadedURI
).get(),
498 mDocShellHasBeenActiveSinceNavigationStart
500 : "this tab was inactive some of the time between navigation start "
501 "and DOMContentFlushed");
502 PAGELOAD_LOG(("%s", marker
.get()));
503 PROFILER_MARKER_TEXT(
504 "DOMContentFlushed", DOM
,
506 MarkerTiming::Interval(mNavigationStart
, mDOMContentFlushed
),
507 MarkerInnerWindowIdFromDocShell(mDocShell
)),
512 void nsDOMNavigationTiming::NotifyDocShellStateChanged(
513 DocShellState aDocShellState
) {
514 mDocShellHasBeenActiveSinceNavigationStart
&=
515 (aDocShellState
== DocShellState::eActive
);
518 mozilla::TimeStamp
nsDOMNavigationTiming::GetUnloadEventStartTimeStamp() const {
519 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
520 // todo: if you intend to update CheckSameOriginURI to log the error to the
521 // console you also need to update the 'aFromPrivateWindow' argument.
522 nsresult rv
= ssm
->CheckSameOriginURI(mLoadedURI
, mUnloadedURI
, false, false);
523 if (NS_SUCCEEDED(rv
)) {
526 return mozilla::TimeStamp();
529 mozilla::TimeStamp
nsDOMNavigationTiming::GetUnloadEventEndTimeStamp() const {
530 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
531 // todo: if you intend to update CheckSameOriginURI to log the error to the
532 // console you also need to update the 'aFromPrivateWindow' argument.
533 nsresult rv
= ssm
->CheckSameOriginURI(mLoadedURI
, mUnloadedURI
, false, false);
534 if (NS_SUCCEEDED(rv
)) {
537 return mozilla::TimeStamp();
540 bool nsDOMNavigationTiming::IsTopLevelContentDocumentInContentProcess() const {
544 if (!XRE_IsContentProcess()) {
547 return mDocShell
->GetBrowsingContext()->IsTopContent();
550 nsDOMNavigationTiming::nsDOMNavigationTiming(nsDocShell
* aDocShell
,
551 nsDOMNavigationTiming
* aOther
)
552 : mDocShell(aDocShell
),
553 mUnloadedURI(aOther
->mUnloadedURI
),
554 mLoadedURI(aOther
->mLoadedURI
),
555 mNavigationType(aOther
->mNavigationType
),
556 mNavigationStartHighRes(aOther
->mNavigationStartHighRes
),
557 mNavigationStart(aOther
->mNavigationStart
),
558 mNonBlankPaint(aOther
->mNonBlankPaint
),
559 mContentfulComposite(aOther
->mContentfulComposite
),
560 mDOMContentFlushed(aOther
->mDOMContentFlushed
),
561 mBeforeUnloadStart(aOther
->mBeforeUnloadStart
),
562 mUnloadStart(aOther
->mUnloadStart
),
563 mUnloadEnd(aOther
->mUnloadEnd
),
564 mLoadEventStart(aOther
->mLoadEventStart
),
565 mLoadEventEnd(aOther
->mLoadEventEnd
),
566 mDOMLoading(aOther
->mDOMLoading
),
567 mDOMInteractive(aOther
->mDOMInteractive
),
568 mDOMContentLoadedEventStart(aOther
->mDOMContentLoadedEventStart
),
569 mDOMContentLoadedEventEnd(aOther
->mDOMContentLoadedEventEnd
),
570 mDOMComplete(aOther
->mDOMComplete
),
571 mTTFI(aOther
->mTTFI
),
572 mDocShellHasBeenActiveSinceNavigationStart(
573 aOther
->mDocShellHasBeenActiveSinceNavigationStart
) {}
576 void mozilla::ipc::IPDLParamTraits
<nsDOMNavigationTiming
*>::Write(
577 IPC::MessageWriter
* aWriter
, IProtocol
* aActor
,
578 nsDOMNavigationTiming
* aParam
) {
579 bool isNull
= !aParam
;
580 WriteIPDLParam(aWriter
, aActor
, isNull
);
585 RefPtr
<nsIURI
> unloadedURI
= aParam
->mUnloadedURI
.get();
586 RefPtr
<nsIURI
> loadedURI
= aParam
->mLoadedURI
.get();
587 WriteIPDLParam(aWriter
, aActor
, unloadedURI
? Some(unloadedURI
) : Nothing());
588 WriteIPDLParam(aWriter
, aActor
, loadedURI
? Some(loadedURI
) : Nothing());
589 WriteIPDLParam(aWriter
, aActor
, uint32_t(aParam
->mNavigationType
));
590 WriteIPDLParam(aWriter
, aActor
, aParam
->mNavigationStartHighRes
);
591 WriteIPDLParam(aWriter
, aActor
, aParam
->mNavigationStart
);
592 WriteIPDLParam(aWriter
, aActor
, aParam
->mNonBlankPaint
);
593 WriteIPDLParam(aWriter
, aActor
, aParam
->mContentfulComposite
);
594 WriteIPDLParam(aWriter
, aActor
, aParam
->mDOMContentFlushed
);
595 WriteIPDLParam(aWriter
, aActor
, aParam
->mBeforeUnloadStart
);
596 WriteIPDLParam(aWriter
, aActor
, aParam
->mUnloadStart
);
597 WriteIPDLParam(aWriter
, aActor
, aParam
->mUnloadEnd
);
598 WriteIPDLParam(aWriter
, aActor
, aParam
->mLoadEventStart
);
599 WriteIPDLParam(aWriter
, aActor
, aParam
->mLoadEventEnd
);
600 WriteIPDLParam(aWriter
, aActor
, aParam
->mDOMLoading
);
601 WriteIPDLParam(aWriter
, aActor
, aParam
->mDOMInteractive
);
602 WriteIPDLParam(aWriter
, aActor
, aParam
->mDOMContentLoadedEventStart
);
603 WriteIPDLParam(aWriter
, aActor
, aParam
->mDOMContentLoadedEventEnd
);
604 WriteIPDLParam(aWriter
, aActor
, aParam
->mDOMComplete
);
605 WriteIPDLParam(aWriter
, aActor
, aParam
->mTTFI
);
606 WriteIPDLParam(aWriter
, aActor
,
607 aParam
->mDocShellHasBeenActiveSinceNavigationStart
);
611 bool mozilla::ipc::IPDLParamTraits
<nsDOMNavigationTiming
*>::Read(
612 IPC::MessageReader
* aReader
, IProtocol
* aActor
,
613 RefPtr
<nsDOMNavigationTiming
>* aResult
) {
615 if (!ReadIPDLParam(aReader
, aActor
, &isNull
)) {
623 auto timing
= MakeRefPtr
<nsDOMNavigationTiming
>(nullptr);
625 Maybe
<RefPtr
<nsIURI
>> unloadedURI
;
626 Maybe
<RefPtr
<nsIURI
>> loadedURI
;
627 if (!ReadIPDLParam(aReader
, aActor
, &unloadedURI
) ||
628 !ReadIPDLParam(aReader
, aActor
, &loadedURI
) ||
629 !ReadIPDLParam(aReader
, aActor
, &type
) ||
630 !ReadIPDLParam(aReader
, aActor
, &timing
->mNavigationStartHighRes
) ||
631 !ReadIPDLParam(aReader
, aActor
, &timing
->mNavigationStart
) ||
632 !ReadIPDLParam(aReader
, aActor
, &timing
->mNonBlankPaint
) ||
633 !ReadIPDLParam(aReader
, aActor
, &timing
->mContentfulComposite
) ||
634 !ReadIPDLParam(aReader
, aActor
, &timing
->mDOMContentFlushed
) ||
635 !ReadIPDLParam(aReader
, aActor
, &timing
->mBeforeUnloadStart
) ||
636 !ReadIPDLParam(aReader
, aActor
, &timing
->mUnloadStart
) ||
637 !ReadIPDLParam(aReader
, aActor
, &timing
->mUnloadEnd
) ||
638 !ReadIPDLParam(aReader
, aActor
, &timing
->mLoadEventStart
) ||
639 !ReadIPDLParam(aReader
, aActor
, &timing
->mLoadEventEnd
) ||
640 !ReadIPDLParam(aReader
, aActor
, &timing
->mDOMLoading
) ||
641 !ReadIPDLParam(aReader
, aActor
, &timing
->mDOMInteractive
) ||
642 !ReadIPDLParam(aReader
, aActor
, &timing
->mDOMContentLoadedEventStart
) ||
643 !ReadIPDLParam(aReader
, aActor
, &timing
->mDOMContentLoadedEventEnd
) ||
644 !ReadIPDLParam(aReader
, aActor
, &timing
->mDOMComplete
) ||
645 !ReadIPDLParam(aReader
, aActor
, &timing
->mTTFI
) ||
646 !ReadIPDLParam(aReader
, aActor
,
647 &timing
->mDocShellHasBeenActiveSinceNavigationStart
)) {
650 timing
->mNavigationType
= nsDOMNavigationTiming::Type(type
);
652 timing
->mUnloadedURI
= std::move(*unloadedURI
);
655 timing
->mLoadedURI
= std::move(*loadedURI
);
657 *aResult
= std::move(timing
);