Bug 1665252 - remove allowpaymentrequest attribute from HTMLIFrameElement r=dom-worke...
[gecko.git] / dom / base / nsDOMNavigationTiming.cpp
blobba839e7416e71272a8816adfec699053c7626835
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"
19 #include "nsCOMPtr.h"
20 #include "nsContentUtils.h"
21 #include "nsDocShell.h"
22 #include "nsHttp.h"
23 #include "nsIScriptSecurityManager.h"
24 #include "nsIURI.h"
25 #include "nsPrintfCString.h"
26 #include "prtime.h"
27 #ifdef MOZ_GECKO_PROFILER
28 # include "ProfilerMarkerPayload.h"
29 #endif
31 using namespace mozilla;
32 using namespace mozilla::dom;
34 namespace mozilla {
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) {
43 Clear();
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()) {
80 return 0;
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.
101 mLoadedURI = aURI;
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()) {
131 return;
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,
142 mNavigationStart,
143 mLoadEventStartForTelemetry);
145 if (mDocShellHasBeenActiveSinceNavigationStart) {
146 if (net::nsHttp::IsBeforeLastActiveTabLoadOptimization(
147 mNavigationStart)) {
148 Telemetry::AccumulateTimeDelta(
149 Telemetry::TIME_TO_LOAD_EVENT_START_ACTIVE_NETOPT_MS,
150 mNavigationStart, mLoadEventStartForTelemetry);
151 } else {
152 Telemetry::AccumulateTimeDelta(
153 Telemetry::TIME_TO_LOAD_EVENT_START_ACTIVE_MS, mNavigationStart,
154 mLoadEventStartForTelemetry);
160 void nsDOMNavigationTiming::NotifyLoadEventEnd() {
161 if (!mLoadEventEnd.IsNull()) {
162 return;
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;
174 nsAutoCString spec;
175 if (mLoadedURI) {
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)));
187 #endif
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,
198 TimeStamp aValue) {
199 if (!mDOMLoading.IsNull()) {
200 return;
202 mLoadedURI = aURI;
203 mDOMLoading = aValue;
206 void nsDOMNavigationTiming::NotifyDOMLoading(nsIURI* aURI) {
207 if (!mDOMLoading.IsNull()) {
208 return;
210 mLoadedURI = aURI;
211 mDOMLoading = TimeStamp::Now();
213 PROFILER_MARKER_UNTYPED("Navigation::DOMLoading", DOM);
216 void nsDOMNavigationTiming::NotifyDOMInteractive(nsIURI* aURI) {
217 if (!mDOMInteractive.IsNull()) {
218 return;
220 mLoadedURI = aURI;
221 mDOMInteractive = TimeStamp::Now();
223 PROFILER_MARKER_UNTYPED("Navigation::DOMInteractive", DOM);
226 void nsDOMNavigationTiming::NotifyDOMComplete(nsIURI* aURI) {
227 if (!mDOMComplete.IsNull()) {
228 return;
230 mLoadedURI = aURI;
231 mDOMComplete = TimeStamp::Now();
233 PROFILER_MARKER_UNTYPED("Navigation::DOMComplete", DOM);
236 void nsDOMNavigationTiming::NotifyDOMContentLoadedStart(nsIURI* aURI) {
237 if (!mDOMContentLoadedEventStart.IsNull()) {
238 return;
241 mLoadedURI = aURI;
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(
255 mNavigationStart)) {
256 Telemetry::AccumulateTimeDelta(
257 Telemetry::TIME_TO_DOM_CONTENT_LOADED_START_ACTIVE_NETOPT_MS,
258 mNavigationStart, now);
259 } else {
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()) {
270 return;
273 mLoadedURI = aURI;
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,
281 mNavigationStart);
285 // static
286 void nsDOMNavigationTiming::TTITimeoutCallback(nsITimer* aTimer,
287 void* aClosure) {
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) {
305 PAGELOAD_LOG(
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");
325 return;
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
336 // handle it)
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
341 // is >= FCP here.
343 if (mTTFI.IsNull()) {
344 // lastLongTaskEnded is >= mContentfulPaint
345 mTTFI = (mDOMContentLoadedEventEnd.IsNull() ||
346 lastLongTaskEnded > mDOMContentLoadedEventEnd)
347 ? lastLongTaskEnded
348 : mDOMContentLoadedEventEnd;
349 PAGELOAD_LOG(
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)
364 mTTITimer = nullptr;
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;
372 nsAutoCString spec;
373 if (mLoadedURI) {
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)));
385 #endif
388 void nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument() {
389 MOZ_ASSERT(NS_IsMainThread());
390 MOZ_ASSERT(!mNavigationStart.IsNull());
392 if (!mNonBlankPaint.IsNull()) {
393 return;
396 mNonBlankPaint = TimeStamp::Now();
398 #ifdef MOZ_GECKO_PROFILER
399 if (profiler_thread_is_being_profiled() || PAGELOAD_LOG_ENABLED()) {
400 TimeDuration elapsed = mNonBlankPaint - mNavigationStart;
401 nsAutoCString spec;
402 if (mLoadedURI) {
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
409 ? "foreground tab"
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)));
418 #endif
420 if (mDocShellHasBeenActiveSinceNavigationStart) {
421 if (net::nsHttp::IsBeforeLastActiveTabLoadOptimization(mNavigationStart)) {
422 Telemetry::AccumulateTimeDelta(
423 Telemetry::TIME_TO_NON_BLANK_PAINT_NETOPT_MS, mNavigationStart,
424 mNonBlankPaint);
425 } else {
426 Telemetry::AccumulateTimeDelta(
427 Telemetry::TIME_TO_NON_BLANK_PAINT_NO_NETOPT_MS, mNavigationStart,
428 mNonBlankPaint);
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()) {
442 return;
445 mContentfulPaint = aCompositeEndTime;
447 #ifdef MOZ_GECKO_PROFILER
448 if (profiler_can_accept_markers() || PAGELOAD_LOG_ENABLED()) {
449 TimeDuration elapsed = mContentfulPaint - mNavigationStart;
450 nsAutoCString spec;
451 if (mLoadedURI) {
452 mLoadedURI->GetSpec(spec);
454 nsPrintfCString marker(
455 "Contentful paint after %dms for URL %s, %s",
456 int(elapsed.ToMilliseconds()), spec.get(),
457 mDocShellHasBeenActiveSinceNavigationStart
458 ? "foreground tab"
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)));
467 #endif
469 if (!mTTITimer) {
470 mTTITimer = NS_NewTimer();
473 // TTI is first checked 5 seconds after the FCP (non-blank-paint is very close
474 // to FCP).
475 mTTITimer->InitWithNamedFuncCallback(TTITimeoutCallback, this,
476 TTI_WINDOW_SIZE_MS,
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()) {
491 return;
494 mDOMContentFlushed = TimeStamp::Now();
496 #ifdef MOZ_GECKO_PROFILER
497 if (profiler_thread_is_being_profiled() || PAGELOAD_LOG_ENABLED()) {
498 TimeDuration elapsed = mDOMContentFlushed - mNavigationStart;
499 nsAutoCString spec;
500 if (mLoadedURI) {
501 mLoadedURI->GetSpec(spec);
503 nsPrintfCString marker(
504 "DOMContentFlushed after %dms for URL %s, %s",
505 int(elapsed.ToMilliseconds()), spec.get(),
506 mDocShellHasBeenActiveSinceNavigationStart
507 ? "foreground tab"
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)));
516 #endif
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)) {
531 return mUnloadStart;
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)) {
542 return mUnloadEnd;
544 return mozilla::TimeStamp();
547 bool nsDOMNavigationTiming::IsTopLevelContentDocumentInContentProcess() const {
548 if (!mDocShell) {
549 return false;
551 if (!XRE_IsContentProcess()) {
552 return false;
554 return mDocShell->GetBrowsingContext()->IsTopContent();
557 void nsDOMNavigationTiming::MaybeSubmitTimeToLoadEventPreloadTelemetry(
558 mozilla::TimeStamp aLoadEventEnd) const {
559 if (!mDocShell) {
560 return;
563 if (const ContentChild* cc = ContentChild::GetSingleton();
564 cc && !(IsWebRemoteType(cc->GetRemoteType()) ||
565 IsPriviligedMozillaRemoteType(cc->GetRemoteType()))) {
566 return;
569 Document* doc = mDocShell->GetExtantDocument();
570 if (!doc ||
571 !doc->ShouldIncludeInTelemetry(/* aAllowExtensionURIs = */ false)) {
572 return;
575 WindowGlobalChild* wgc = doc->GetWindowGlobalChild();
576 if (!wgc) {
577 return;
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) {}
609 /* static */
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);
637 /* static */
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);
642 uint32_t type;
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)) {
667 return false;
669 timing->mNavigationType = nsDOMNavigationTiming::Type(type);
670 if (unloadedURI) {
671 timing->mUnloadedURI = std::move(*unloadedURI);
673 if (loadedURI) {
674 timing->mLoadedURI = std::move(*loadedURI);
676 *aResult = std::move(timing);
677 return true;