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 "mozilla/Telemetry.h"
11 #include "mozilla/TimeStamp.h"
12 #include "mozilla/Unused.h"
13 #include "mozilla/dom/ContentChild.h"
14 #include "mozilla/dom/ContentParent.h"
15 #include "mozilla/dom/PerformanceNavigation.h"
16 #include "mozilla/dom/WindowGlobalChild.h"
17 #include "mozilla/ipc/IPDLParamTraits.h"
18 #include "mozilla/ipc/URIUtils.h"
20 #include "nsContentUtils.h"
21 #include "nsDocShell.h"
23 #include "nsIScriptSecurityManager.h"
25 #include "nsPrintfCString.h"
27 #ifdef MOZ_GECKO_PROFILER
28 # include "ProfilerMarkerPayload.h"
31 using namespace mozilla
;
32 using namespace mozilla::dom
;
36 LazyLogModule
gPageLoadLog("PageLoad");
37 #define PAGELOAD_LOG(args) MOZ_LOG(gPageLoadLog, LogLevel::Debug, args)
38 #define PAGELOAD_LOG_ENABLED() MOZ_LOG_TEST(gPageLoadLog, LogLevel::Error)
40 } // namespace mozilla
42 nsDOMNavigationTiming::nsDOMNavigationTiming(nsDocShell
* aDocShell
) {
45 mDocShell
= aDocShell
;
48 nsDOMNavigationTiming::~nsDOMNavigationTiming() = default;
50 void nsDOMNavigationTiming::Clear() {
51 mNavigationType
= TYPE_RESERVED
;
52 mNavigationStartHighRes
= 0;
54 mBeforeUnloadStart
= TimeStamp();
55 mUnloadStart
= TimeStamp();
56 mUnloadEnd
= TimeStamp();
57 mLoadEventStart
= TimeStamp();
58 mLoadEventEnd
= TimeStamp();
59 mDOMLoading
= TimeStamp();
60 mDOMInteractive
= TimeStamp();
61 mDOMContentLoadedEventStart
= TimeStamp();
62 mDOMContentLoadedEventEnd
= TimeStamp();
63 mDOMComplete
= TimeStamp();
64 mContentfulPaint
= TimeStamp();
65 mNonBlankPaint
= TimeStamp();
67 mDocShellHasBeenActiveSinceNavigationStart
= false;
70 void nsDOMNavigationTiming::Anonymize(nsIURI
* aFinalURI
) {
71 mLoadedURI
= aFinalURI
;
72 mUnloadedURI
= nullptr;
73 mBeforeUnloadStart
= TimeStamp();
74 mUnloadStart
= TimeStamp();
75 mUnloadEnd
= TimeStamp();
78 DOMTimeMilliSec
nsDOMNavigationTiming::TimeStampToDOM(TimeStamp aStamp
) const {
79 if (aStamp
.IsNull()) {
83 TimeDuration duration
= aStamp
- mNavigationStart
;
84 return GetNavigationStart() + static_cast<int64_t>(duration
.ToMilliseconds());
87 void nsDOMNavigationTiming::NotifyNavigationStart(
88 DocShellState aDocShellState
) {
89 mNavigationStartHighRes
= (double)PR_Now() / PR_USEC_PER_MSEC
;
90 mNavigationStart
= TimeStamp::Now();
91 mDocShellHasBeenActiveSinceNavigationStart
=
92 (aDocShellState
== DocShellState::eActive
);
93 PROFILER_MARKER_UNTYPED("Navigation::Start", DOM
);
96 void nsDOMNavigationTiming::NotifyFetchStart(nsIURI
* aURI
,
97 Type aNavigationType
) {
98 mNavigationType
= aNavigationType
;
99 // At the unload event time we don't really know the loading uri.
100 // Need it for later check for unload timing access.
104 void nsDOMNavigationTiming::NotifyRestoreStart() {
105 mNavigationType
= TYPE_BACK_FORWARD
;
108 void nsDOMNavigationTiming::NotifyBeforeUnload() {
109 mBeforeUnloadStart
= TimeStamp::Now();
112 void nsDOMNavigationTiming::NotifyUnloadAccepted(nsIURI
* aOldURI
) {
113 mUnloadStart
= mBeforeUnloadStart
;
114 mUnloadedURI
= aOldURI
;
117 void nsDOMNavigationTiming::NotifyUnloadEventStart() {
118 mUnloadStart
= TimeStamp::Now();
119 PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "Unload", NETWORK
,
120 TRACING_INTERVAL_START
, mDocShell
);
123 void nsDOMNavigationTiming::NotifyUnloadEventEnd() {
124 mUnloadEnd
= TimeStamp::Now();
125 PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "Unload", NETWORK
,
126 TRACING_INTERVAL_END
, mDocShell
);
129 void nsDOMNavigationTiming::NotifyLoadEventStart() {
130 if (!mLoadEventStart
.IsNull()) {
133 mLoadEventStart
= TimeStamp::Now();
135 PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "Load", NETWORK
,
136 TRACING_INTERVAL_START
, mDocShell
);
138 if (IsTopLevelContentDocumentInContentProcess()) {
139 mLoadEventStartForTelemetry
= TimeStamp::Now();
141 Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_LOAD_EVENT_START_MS
,
143 mLoadEventStartForTelemetry
);
145 if (mDocShellHasBeenActiveSinceNavigationStart
) {
146 if (net::nsHttp::IsBeforeLastActiveTabLoadOptimization(
148 Telemetry::AccumulateTimeDelta(
149 Telemetry::TIME_TO_LOAD_EVENT_START_ACTIVE_NETOPT_MS
,
150 mNavigationStart
, mLoadEventStartForTelemetry
);
152 Telemetry::AccumulateTimeDelta(
153 Telemetry::TIME_TO_LOAD_EVENT_START_ACTIVE_MS
, mNavigationStart
,
154 mLoadEventStartForTelemetry
);
160 void nsDOMNavigationTiming::NotifyLoadEventEnd() {
161 if (!mLoadEventEnd
.IsNull()) {
164 mLoadEventEnd
= TimeStamp::Now();
166 PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "Load", NETWORK
,
167 TRACING_INTERVAL_END
, mDocShell
);
169 if (IsTopLevelContentDocumentInContentProcess()) {
170 #ifdef MOZ_GECKO_PROFILER
171 if (profiler_can_accept_markers() || PAGELOAD_LOG_ENABLED()) {
172 TimeDuration elapsed
= mLoadEventEnd
- mNavigationStart
;
173 TimeDuration duration
= mLoadEventEnd
- mLoadEventStart
;
176 mLoadedURI
->GetSpec(spec
);
178 nsPrintfCString
marker(
179 "Document %s loaded after %dms, load event duration %dms", spec
.get(),
180 int(elapsed
.ToMilliseconds()), int(duration
.ToMilliseconds()));
181 PAGELOAD_LOG(("%s", marker
.get()));
182 PROFILER_ADD_MARKER_WITH_PAYLOAD(
183 "DocumentLoad", DOM
, TextMarkerPayload
,
184 (marker
, mNavigationStart
, mLoadEventEnd
,
185 profiler_get_inner_window_id_from_docshell(mDocShell
)));
188 TimeStamp loadEventEnd
= TimeStamp::Now();
190 Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_LOAD_EVENT_END_MS
,
191 mNavigationStart
, loadEventEnd
);
193 MaybeSubmitTimeToLoadEventPreloadTelemetry(loadEventEnd
);
197 void nsDOMNavigationTiming::SetDOMLoadingTimeStamp(nsIURI
* aURI
,
199 if (!mDOMLoading
.IsNull()) {
203 mDOMLoading
= aValue
;
206 void nsDOMNavigationTiming::NotifyDOMLoading(nsIURI
* aURI
) {
207 if (!mDOMLoading
.IsNull()) {
211 mDOMLoading
= TimeStamp::Now();
213 PROFILER_MARKER_UNTYPED("Navigation::DOMLoading", DOM
);
216 void nsDOMNavigationTiming::NotifyDOMInteractive(nsIURI
* aURI
) {
217 if (!mDOMInteractive
.IsNull()) {
221 mDOMInteractive
= TimeStamp::Now();
223 PROFILER_MARKER_UNTYPED("Navigation::DOMInteractive", DOM
);
226 void nsDOMNavigationTiming::NotifyDOMComplete(nsIURI
* aURI
) {
227 if (!mDOMComplete
.IsNull()) {
231 mDOMComplete
= TimeStamp::Now();
233 PROFILER_MARKER_UNTYPED("Navigation::DOMComplete", DOM
);
236 void nsDOMNavigationTiming::NotifyDOMContentLoadedStart(nsIURI
* aURI
) {
237 if (!mDOMContentLoadedEventStart
.IsNull()) {
242 mDOMContentLoadedEventStart
= TimeStamp::Now();
244 PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "DOMContentLoaded", NETWORK
,
245 TRACING_INTERVAL_START
, mDocShell
);
247 if (IsTopLevelContentDocumentInContentProcess()) {
248 TimeStamp now
= TimeStamp::Now();
250 Telemetry::AccumulateTimeDelta(
251 Telemetry::TIME_TO_DOM_CONTENT_LOADED_START_MS
, mNavigationStart
, now
);
253 if (mDocShellHasBeenActiveSinceNavigationStart
) {
254 if (net::nsHttp::IsBeforeLastActiveTabLoadOptimization(
256 Telemetry::AccumulateTimeDelta(
257 Telemetry::TIME_TO_DOM_CONTENT_LOADED_START_ACTIVE_NETOPT_MS
,
258 mNavigationStart
, now
);
260 Telemetry::AccumulateTimeDelta(
261 Telemetry::TIME_TO_DOM_CONTENT_LOADED_START_ACTIVE_MS
,
262 mNavigationStart
, now
);
268 void nsDOMNavigationTiming::NotifyDOMContentLoadedEnd(nsIURI
* aURI
) {
269 if (!mDOMContentLoadedEventEnd
.IsNull()) {
274 mDOMContentLoadedEventEnd
= TimeStamp::Now();
276 PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "DOMContentLoaded", NETWORK
,
277 TRACING_INTERVAL_END
, mDocShell
);
279 if (IsTopLevelContentDocumentInContentProcess()) {
280 Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_DOM_CONTENT_LOADED_END_MS
,
286 void nsDOMNavigationTiming::TTITimeoutCallback(nsITimer
* aTimer
,
288 nsDOMNavigationTiming
* self
= static_cast<nsDOMNavigationTiming
*>(aClosure
);
289 self
->TTITimeout(aTimer
);
292 #define TTI_WINDOW_SIZE_MS (5 * 1000)
294 void nsDOMNavigationTiming::TTITimeout(nsITimer
* aTimer
) {
295 // Check TTI: see if it's been 5 seconds since the last Long Task
296 TimeStamp now
= TimeStamp::Now();
297 MOZ_RELEASE_ASSERT(!mContentfulPaint
.IsNull(),
298 "TTI timeout with no contentful-paint?");
300 nsCOMPtr
<nsIThread
> mainThread
= do_GetMainThread();
301 TimeStamp lastLongTaskEnded
;
302 mainThread
->GetLastLongNonIdleTaskEnd(&lastLongTaskEnded
);
303 // Window starts at mContentfulPaint; any long task before that is ignored
304 if (lastLongTaskEnded
.IsNull() || lastLongTaskEnded
< mContentfulPaint
) {
306 ("no longtask (last was %g ms before ContentfulPaint)",
307 lastLongTaskEnded
.IsNull()
309 : (mContentfulPaint
- lastLongTaskEnded
).ToMilliseconds()));
310 lastLongTaskEnded
= mContentfulPaint
;
312 TimeDuration delta
= now
- lastLongTaskEnded
;
313 PAGELOAD_LOG(("TTI delta: %g ms", delta
.ToMilliseconds()));
314 if (delta
.ToMilliseconds() < TTI_WINDOW_SIZE_MS
) {
315 // Less than 5 seconds since the last long task or start of the window.
316 // Schedule another check.
317 PAGELOAD_LOG(("TTI: waiting additional %g ms",
318 (TTI_WINDOW_SIZE_MS
+ 100) - delta
.ToMilliseconds()));
319 aTimer
->InitWithNamedFuncCallback(
320 TTITimeoutCallback
, this,
321 (TTI_WINDOW_SIZE_MS
+ 100) -
322 delta
.ToMilliseconds(), // slightly after the window ends
323 nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY
,
324 "nsDOMNavigationTiming::TTITimeout");
328 // To correctly implement TTI/TTFI as proposed, we'd need to not
329 // fire it until there are no more than 2 network loads. By the
330 // proposed definition, without that we're closer to
331 // TimeToFirstInteractive. There are also arguments about what sort
332 // of loads should qualify.
334 // XXX check number of network loads, and if > 2 mark to check if loads
335 // decreases to 2 (or record that point and let the normal timer here
338 // TTI has occurred! TTI is either FCP (if there are no longtasks and no
339 // DCLEnd in the window that starts at FCP), or at the end of the last
340 // Long Task or DOMContentLoadedEnd (whichever is later). lastLongTaskEnded
343 if (mTTFI
.IsNull()) {
344 // lastLongTaskEnded is >= mContentfulPaint
345 mTTFI
= (mDOMContentLoadedEventEnd
.IsNull() ||
346 lastLongTaskEnded
> mDOMContentLoadedEventEnd
)
348 : mDOMContentLoadedEventEnd
;
350 ("TTFI after %dms (LongTask was at %dms, DCL was %dms)",
351 int((mTTFI
- mNavigationStart
).ToMilliseconds()),
352 lastLongTaskEnded
.IsNull()
354 : int((lastLongTaskEnded
- mNavigationStart
).ToMilliseconds()),
355 mDOMContentLoadedEventEnd
.IsNull()
357 : int((mDOMContentLoadedEventEnd
- mNavigationStart
)
358 .ToMilliseconds())));
360 // XXX Implement TTI via check number of network loads, and if > 2 mark
361 // to check if loads decreases to 2 (or record that point and let the
362 // normal timer here handle it)
366 #ifdef MOZ_GECKO_PROFILER
367 if (profiler_can_accept_markers() || PAGELOAD_LOG_ENABLED()) {
368 TimeDuration elapsed
= mTTFI
- mNavigationStart
;
369 MOZ_ASSERT(elapsed
.ToMilliseconds() > 0);
370 TimeDuration elapsedLongTask
=
371 lastLongTaskEnded
.IsNull() ? 0 : lastLongTaskEnded
- mNavigationStart
;
374 mLoadedURI
->GetSpec(spec
);
376 nsPrintfCString
marker("TTFI after %dms (LongTask was at %dms) for URL %s",
377 int(elapsed
.ToMilliseconds()),
378 int(elapsedLongTask
.ToMilliseconds()), spec
.get());
380 PROFILER_ADD_MARKER_WITH_PAYLOAD(
381 "TimeToFirstInteractive (TTFI)", DOM
, TextMarkerPayload
,
382 (marker
, mNavigationStart
, mTTFI
,
383 profiler_get_inner_window_id_from_docshell(mDocShell
)));
388 void nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument() {
389 MOZ_ASSERT(NS_IsMainThread());
390 MOZ_ASSERT(!mNavigationStart
.IsNull());
392 if (!mNonBlankPaint
.IsNull()) {
396 mNonBlankPaint
= TimeStamp::Now();
398 #ifdef MOZ_GECKO_PROFILER
399 if (profiler_thread_is_being_profiled() || PAGELOAD_LOG_ENABLED()) {
400 TimeDuration elapsed
= mNonBlankPaint
- mNavigationStart
;
403 mLoadedURI
->GetSpec(spec
);
405 nsPrintfCString
marker(
406 "Non-blank paint after %dms for URL %s, %s",
407 int(elapsed
.ToMilliseconds()), spec
.get(),
408 mDocShellHasBeenActiveSinceNavigationStart
410 : "this tab was inactive some of the time between navigation start "
411 "and first non-blank paint");
412 PAGELOAD_LOG(("%s", marker
.get()));
413 PROFILER_ADD_MARKER_WITH_PAYLOAD(
414 "FirstNonBlankPaint", DOM
, TextMarkerPayload
,
415 (marker
, mNavigationStart
, mNonBlankPaint
,
416 profiler_get_inner_window_id_from_docshell(mDocShell
)));
420 if (mDocShellHasBeenActiveSinceNavigationStart
) {
421 if (net::nsHttp::IsBeforeLastActiveTabLoadOptimization(mNavigationStart
)) {
422 Telemetry::AccumulateTimeDelta(
423 Telemetry::TIME_TO_NON_BLANK_PAINT_NETOPT_MS
, mNavigationStart
,
426 Telemetry::AccumulateTimeDelta(
427 Telemetry::TIME_TO_NON_BLANK_PAINT_NO_NETOPT_MS
, mNavigationStart
,
431 Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_NON_BLANK_PAINT_MS
,
432 mNavigationStart
, mNonBlankPaint
);
436 void nsDOMNavigationTiming::NotifyContentfulPaintForRootContentDocument(
437 const mozilla::TimeStamp
& aCompositeEndTime
) {
438 MOZ_ASSERT(NS_IsMainThread());
439 MOZ_ASSERT(!mNavigationStart
.IsNull());
441 if (!mContentfulPaint
.IsNull()) {
445 mContentfulPaint
= aCompositeEndTime
;
447 #ifdef MOZ_GECKO_PROFILER
448 if (profiler_can_accept_markers() || PAGELOAD_LOG_ENABLED()) {
449 TimeDuration elapsed
= mContentfulPaint
- mNavigationStart
;
452 mLoadedURI
->GetSpec(spec
);
454 nsPrintfCString
marker(
455 "Contentful paint after %dms for URL %s, %s",
456 int(elapsed
.ToMilliseconds()), spec
.get(),
457 mDocShellHasBeenActiveSinceNavigationStart
459 : "this tab was inactive some of the time between navigation start "
460 "and first non-blank paint");
461 PAGELOAD_LOG(("%s", marker
.get()));
462 PROFILER_ADD_MARKER_WITH_PAYLOAD(
463 "FirstContentfulPaint", DOM
, TextMarkerPayload
,
464 (marker
, mNavigationStart
, mContentfulPaint
,
465 profiler_get_inner_window_id_from_docshell(mDocShell
)));
470 mTTITimer
= NS_NewTimer();
473 // TTI is first checked 5 seconds after the FCP (non-blank-paint is very close
475 mTTITimer
->InitWithNamedFuncCallback(TTITimeoutCallback
, this,
477 nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY
,
478 "nsDOMNavigationTiming::TTITimeout");
480 if (mDocShellHasBeenActiveSinceNavigationStart
) {
481 Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_FIRST_CONTENTFUL_PAINT_MS
,
482 mNavigationStart
, mContentfulPaint
);
486 void nsDOMNavigationTiming::NotifyDOMContentFlushedForRootContentDocument() {
487 MOZ_ASSERT(NS_IsMainThread());
488 MOZ_ASSERT(!mNavigationStart
.IsNull());
490 if (!mDOMContentFlushed
.IsNull()) {
494 mDOMContentFlushed
= TimeStamp::Now();
496 #ifdef MOZ_GECKO_PROFILER
497 if (profiler_thread_is_being_profiled() || PAGELOAD_LOG_ENABLED()) {
498 TimeDuration elapsed
= mDOMContentFlushed
- mNavigationStart
;
501 mLoadedURI
->GetSpec(spec
);
503 nsPrintfCString
marker(
504 "DOMContentFlushed after %dms for URL %s, %s",
505 int(elapsed
.ToMilliseconds()), spec
.get(),
506 mDocShellHasBeenActiveSinceNavigationStart
508 : "this tab was inactive some of the time between navigation start "
509 "and DOMContentFlushed");
510 PAGELOAD_LOG(("%s", marker
.get()));
511 PROFILER_ADD_MARKER_WITH_PAYLOAD(
512 "DOMContentFlushed", DOM
, TextMarkerPayload
,
513 (marker
, mNavigationStart
, mDOMContentFlushed
,
514 profiler_get_inner_window_id_from_docshell(mDocShell
)));
519 void nsDOMNavigationTiming::NotifyDocShellStateChanged(
520 DocShellState aDocShellState
) {
521 mDocShellHasBeenActiveSinceNavigationStart
&=
522 (aDocShellState
== DocShellState::eActive
);
525 mozilla::TimeStamp
nsDOMNavigationTiming::GetUnloadEventStartTimeStamp() const {
526 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
527 // todo: if you intend to update CheckSameOriginURI to log the error to the
528 // console you also need to update the 'aFromPrivateWindow' argument.
529 nsresult rv
= ssm
->CheckSameOriginURI(mLoadedURI
, mUnloadedURI
, false, false);
530 if (NS_SUCCEEDED(rv
)) {
533 return mozilla::TimeStamp();
536 mozilla::TimeStamp
nsDOMNavigationTiming::GetUnloadEventEndTimeStamp() const {
537 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
538 // todo: if you intend to update CheckSameOriginURI to log the error to the
539 // console you also need to update the 'aFromPrivateWindow' argument.
540 nsresult rv
= ssm
->CheckSameOriginURI(mLoadedURI
, mUnloadedURI
, false, false);
541 if (NS_SUCCEEDED(rv
)) {
544 return mozilla::TimeStamp();
547 bool nsDOMNavigationTiming::IsTopLevelContentDocumentInContentProcess() const {
551 if (!XRE_IsContentProcess()) {
554 return mDocShell
->GetBrowsingContext()->IsTopContent();
557 void nsDOMNavigationTiming::MaybeSubmitTimeToLoadEventPreloadTelemetry(
558 mozilla::TimeStamp aLoadEventEnd
) const {
563 if (const ContentChild
* cc
= ContentChild::GetSingleton();
564 cc
&& !(IsWebRemoteType(cc
->GetRemoteType()) ||
565 IsPriviligedMozillaRemoteType(cc
->GetRemoteType()))) {
569 Document
* doc
= mDocShell
->GetExtantDocument();
571 !doc
->ShouldIncludeInTelemetry(/* aAllowExtensionURIs = */ false)) {
575 WindowGlobalChild
* wgc
= doc
->GetWindowGlobalChild();
580 wgc
->SendSubmitLoadEventPreloadTelemetry(
581 mNavigationStart
, mLoadEventStartForTelemetry
, aLoadEventEnd
);
584 nsDOMNavigationTiming::nsDOMNavigationTiming(nsDocShell
* aDocShell
,
585 nsDOMNavigationTiming
* aOther
)
586 : mDocShell(aDocShell
),
587 mUnloadedURI(aOther
->mUnloadedURI
),
588 mLoadedURI(aOther
->mLoadedURI
),
589 mNavigationType(aOther
->mNavigationType
),
590 mNavigationStartHighRes(aOther
->mNavigationStartHighRes
),
591 mNavigationStart(aOther
->mNavigationStart
),
592 mNonBlankPaint(aOther
->mNonBlankPaint
),
593 mContentfulPaint(aOther
->mContentfulPaint
),
594 mDOMContentFlushed(aOther
->mDOMContentFlushed
),
595 mBeforeUnloadStart(aOther
->mBeforeUnloadStart
),
596 mUnloadStart(aOther
->mUnloadStart
),
597 mUnloadEnd(aOther
->mUnloadEnd
),
598 mLoadEventStart(aOther
->mLoadEventStart
),
599 mLoadEventEnd(aOther
->mLoadEventEnd
),
600 mDOMLoading(aOther
->mDOMLoading
),
601 mDOMInteractive(aOther
->mDOMInteractive
),
602 mDOMContentLoadedEventStart(aOther
->mDOMContentLoadedEventStart
),
603 mDOMContentLoadedEventEnd(aOther
->mDOMContentLoadedEventEnd
),
604 mDOMComplete(aOther
->mDOMComplete
),
605 mTTFI(aOther
->mTTFI
),
606 mDocShellHasBeenActiveSinceNavigationStart(
607 aOther
->mDocShellHasBeenActiveSinceNavigationStart
) {}
610 void mozilla::ipc::IPDLParamTraits
<nsDOMNavigationTiming
*>::Write(
611 IPC::Message
* aMsg
, IProtocol
* aActor
, nsDOMNavigationTiming
* aParam
) {
612 RefPtr
<nsIURI
> unloadedURI
= aParam
->mUnloadedURI
.get();
613 RefPtr
<nsIURI
> loadedURI
= aParam
->mLoadedURI
.get();
614 WriteIPDLParam(aMsg
, aActor
, unloadedURI
? Some(unloadedURI
) : Nothing());
615 WriteIPDLParam(aMsg
, aActor
, loadedURI
? Some(loadedURI
) : Nothing());
616 WriteIPDLParam(aMsg
, aActor
, uint32_t(aParam
->mNavigationType
));
617 WriteIPDLParam(aMsg
, aActor
, aParam
->mNavigationStartHighRes
);
618 WriteIPDLParam(aMsg
, aActor
, aParam
->mNavigationStart
);
619 WriteIPDLParam(aMsg
, aActor
, aParam
->mNonBlankPaint
);
620 WriteIPDLParam(aMsg
, aActor
, aParam
->mContentfulPaint
);
621 WriteIPDLParam(aMsg
, aActor
, aParam
->mDOMContentFlushed
);
622 WriteIPDLParam(aMsg
, aActor
, aParam
->mBeforeUnloadStart
);
623 WriteIPDLParam(aMsg
, aActor
, aParam
->mUnloadStart
);
624 WriteIPDLParam(aMsg
, aActor
, aParam
->mUnloadEnd
);
625 WriteIPDLParam(aMsg
, aActor
, aParam
->mLoadEventStart
);
626 WriteIPDLParam(aMsg
, aActor
, aParam
->mLoadEventEnd
);
627 WriteIPDLParam(aMsg
, aActor
, aParam
->mDOMLoading
);
628 WriteIPDLParam(aMsg
, aActor
, aParam
->mDOMInteractive
);
629 WriteIPDLParam(aMsg
, aActor
, aParam
->mDOMContentLoadedEventStart
);
630 WriteIPDLParam(aMsg
, aActor
, aParam
->mDOMContentLoadedEventEnd
);
631 WriteIPDLParam(aMsg
, aActor
, aParam
->mDOMComplete
);
632 WriteIPDLParam(aMsg
, aActor
, aParam
->mTTFI
);
633 WriteIPDLParam(aMsg
, aActor
,
634 aParam
->mDocShellHasBeenActiveSinceNavigationStart
);
638 bool mozilla::ipc::IPDLParamTraits
<nsDOMNavigationTiming
*>::Read(
639 const IPC::Message
* aMsg
, PickleIterator
* aIter
, IProtocol
* aActor
,
640 RefPtr
<nsDOMNavigationTiming
>* aResult
) {
641 auto timing
= MakeRefPtr
<nsDOMNavigationTiming
>(nullptr);
643 Maybe
<RefPtr
<nsIURI
>> unloadedURI
;
644 Maybe
<RefPtr
<nsIURI
>> loadedURI
;
645 if (!ReadIPDLParam(aMsg
, aIter
, aActor
, &unloadedURI
) ||
646 !ReadIPDLParam(aMsg
, aIter
, aActor
, &loadedURI
) ||
647 !ReadIPDLParam(aMsg
, aIter
, aActor
, &type
) ||
648 !ReadIPDLParam(aMsg
, aIter
, aActor
, &timing
->mNavigationStartHighRes
) ||
649 !ReadIPDLParam(aMsg
, aIter
, aActor
, &timing
->mNavigationStart
) ||
650 !ReadIPDLParam(aMsg
, aIter
, aActor
, &timing
->mNonBlankPaint
) ||
651 !ReadIPDLParam(aMsg
, aIter
, aActor
, &timing
->mContentfulPaint
) ||
652 !ReadIPDLParam(aMsg
, aIter
, aActor
, &timing
->mDOMContentFlushed
) ||
653 !ReadIPDLParam(aMsg
, aIter
, aActor
, &timing
->mBeforeUnloadStart
) ||
654 !ReadIPDLParam(aMsg
, aIter
, aActor
, &timing
->mUnloadStart
) ||
655 !ReadIPDLParam(aMsg
, aIter
, aActor
, &timing
->mUnloadEnd
) ||
656 !ReadIPDLParam(aMsg
, aIter
, aActor
, &timing
->mLoadEventStart
) ||
657 !ReadIPDLParam(aMsg
, aIter
, aActor
, &timing
->mLoadEventEnd
) ||
658 !ReadIPDLParam(aMsg
, aIter
, aActor
, &timing
->mDOMLoading
) ||
659 !ReadIPDLParam(aMsg
, aIter
, aActor
, &timing
->mDOMInteractive
) ||
660 !ReadIPDLParam(aMsg
, aIter
, aActor
,
661 &timing
->mDOMContentLoadedEventStart
) ||
662 !ReadIPDLParam(aMsg
, aIter
, aActor
, &timing
->mDOMContentLoadedEventEnd
) ||
663 !ReadIPDLParam(aMsg
, aIter
, aActor
, &timing
->mDOMComplete
) ||
664 !ReadIPDLParam(aMsg
, aIter
, aActor
, &timing
->mTTFI
) ||
665 !ReadIPDLParam(aMsg
, aIter
, aActor
,
666 &timing
->mDocShellHasBeenActiveSinceNavigationStart
)) {
669 timing
->mNavigationType
= nsDOMNavigationTiming::Type(type
);
671 timing
->mUnloadedURI
= std::move(*unloadedURI
);
674 timing
->mLoadedURI
= std::move(*loadedURI
);
676 *aResult
= std::move(timing
);