LCOV - code coverage report
Current view: top level - dom/base - nsDOMNavigationTiming.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 138 174 79.3 %
Date: 2017-07-14 16:53:18 Functions: 19 24 79.2 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "nsDOMNavigationTiming.h"
       8             : 
       9             : #include "GeckoProfiler.h"
      10             : #include "nsCOMPtr.h"
      11             : #include "nsContentUtils.h"
      12             : #include "nsDocShell.h"
      13             : #include "nsIDocShellTreeItem.h"
      14             : #include "nsIScriptSecurityManager.h"
      15             : #include "prtime.h"
      16             : #include "nsIURI.h"
      17             : #include "nsPrintfCString.h"
      18             : #include "mozilla/dom/PerformanceNavigation.h"
      19             : #include "mozilla/TimeStamp.h"
      20             : #include "mozilla/Telemetry.h"
      21             : 
      22             : using namespace mozilla;
      23             : 
      24          27 : nsDOMNavigationTiming::nsDOMNavigationTiming(nsDocShell* aDocShell)
      25             : {
      26          27 :   Clear();
      27             : 
      28          27 :   mDocShell = aDocShell;
      29          27 : }
      30             : 
      31           0 : nsDOMNavigationTiming::~nsDOMNavigationTiming()
      32             : {
      33           0 : }
      34             : 
      35             : void
      36          27 : nsDOMNavigationTiming::Clear()
      37             : {
      38          27 :   mNavigationType = TYPE_RESERVED;
      39          27 :   mNavigationStartHighRes = 0;
      40          27 :   mBeforeUnloadStart = 0;
      41          27 :   mUnloadStart = 0;
      42          27 :   mUnloadEnd = 0;
      43          27 :   mLoadEventStart = 0;
      44          27 :   mLoadEventEnd = 0;
      45          27 :   mDOMLoading = 0;
      46          27 :   mDOMInteractive = 0;
      47          27 :   mDOMContentLoadedEventStart = 0;
      48          27 :   mDOMContentLoadedEventEnd = 0;
      49          27 :   mDOMComplete = 0;
      50             : 
      51          27 :   mLoadEventStartSet = false;
      52          27 :   mLoadEventEndSet = false;
      53          27 :   mDOMLoadingSet = false;
      54          27 :   mDOMInteractiveSet = false;
      55          27 :   mDOMContentLoadedEventStartSet = false;
      56          27 :   mDOMContentLoadedEventEndSet = false;
      57          27 :   mDOMCompleteSet = false;
      58          27 :   mDocShellHasBeenActiveSinceNavigationStart = false;
      59          27 : }
      60             : 
      61             : DOMTimeMilliSec
      62         124 : nsDOMNavigationTiming::TimeStampToDOM(TimeStamp aStamp) const
      63             : {
      64         124 :   if (aStamp.IsNull()) {
      65           0 :     return 0;
      66             :   }
      67             : 
      68         124 :   TimeDuration duration = aStamp - mNavigationStartTimeStamp;
      69         124 :   return GetNavigationStart() + static_cast<int64_t>(duration.ToMilliseconds());
      70             : }
      71             : 
      72         100 : DOMTimeMilliSec nsDOMNavigationTiming::DurationFromStart()
      73             : {
      74         100 :   return TimeStampToDOM(TimeStamp::Now());
      75             : }
      76             : 
      77             : void
      78          31 : nsDOMNavigationTiming::NotifyNavigationStart(DocShellState aDocShellState)
      79             : {
      80          31 :   mNavigationStartHighRes = (double)PR_Now() / PR_USEC_PER_MSEC;
      81          31 :   mNavigationStartTimeStamp = TimeStamp::Now();
      82          31 :   mDocShellHasBeenActiveSinceNavigationStart = (aDocShellState == DocShellState::eActive);
      83          31 :   profiler_add_marker("Navigation::Start");
      84          31 : }
      85             : 
      86             : void
      87           6 : nsDOMNavigationTiming::NotifyFetchStart(nsIURI* aURI, Type aNavigationType)
      88             : {
      89           6 :   mNavigationType = aNavigationType;
      90             :   // At the unload event time we don't really know the loading uri.
      91             :   // Need it for later check for unload timing access.
      92           6 :   mLoadedURI = aURI;
      93           6 : }
      94             : 
      95             : void
      96           6 : nsDOMNavigationTiming::NotifyBeforeUnload()
      97             : {
      98           6 :   mBeforeUnloadStart = DurationFromStart();
      99           6 : }
     100             : 
     101             : void
     102           6 : nsDOMNavigationTiming::NotifyUnloadAccepted(nsIURI* aOldURI)
     103             : {
     104           6 :   mUnloadStart = mBeforeUnloadStart;
     105           6 :   mUnloadedURI = aOldURI;
     106           6 : }
     107             : 
     108             : void
     109           4 : nsDOMNavigationTiming::NotifyUnloadEventStart()
     110             : {
     111           4 :   mUnloadStart = DurationFromStart();
     112           4 :   profiler_tracing("Navigation", "Unload", TRACING_INTERVAL_START);
     113           4 : }
     114             : 
     115             : void
     116           4 : nsDOMNavigationTiming::NotifyUnloadEventEnd()
     117             : {
     118           4 :   mUnloadEnd = DurationFromStart();
     119           4 :   profiler_tracing("Navigation", "Unload", TRACING_INTERVAL_END);
     120           4 : }
     121             : 
     122             : void
     123           4 : nsDOMNavigationTiming::NotifyLoadEventStart()
     124             : {
     125           4 :   if (!mLoadEventStartSet) {
     126           4 :     mLoadEventStart = DurationFromStart();
     127           4 :     mLoadEventStartSet = true;
     128             : 
     129           4 :     profiler_tracing("Navigation", "Load", TRACING_INTERVAL_START);
     130             : 
     131           4 :     if (IsTopLevelContentDocument()) {
     132           1 :       Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_LOAD_EVENT_START_MS,
     133           1 :                                      mNavigationStartTimeStamp);
     134             :     }
     135             :   }
     136           4 : }
     137             : 
     138             : void
     139           4 : nsDOMNavigationTiming::NotifyLoadEventEnd()
     140             : {
     141           4 :   if (!mLoadEventEndSet) {
     142           4 :     mLoadEventEnd = DurationFromStart();
     143           4 :     mLoadEventEndSet = true;
     144             : 
     145           4 :     profiler_tracing("Navigation", "Load", TRACING_INTERVAL_END);
     146             : 
     147           4 :     if (IsTopLevelContentDocument()) {
     148           1 :       Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_LOAD_EVENT_END_MS,
     149           1 :                                      mNavigationStartTimeStamp);
     150             :     }
     151             :   }
     152           4 : }
     153             : 
     154             : void
     155          24 : nsDOMNavigationTiming::SetDOMLoadingTimeStamp(nsIURI* aURI, TimeStamp aValue)
     156             : {
     157          24 :   if (!mDOMLoadingSet) {
     158          24 :     mLoadedURI = aURI;
     159          24 :     mDOMLoading = TimeStampToDOM(aValue);
     160          24 :     mDOMLoadingSet = true;
     161             :   }
     162          24 : }
     163             : 
     164             : void
     165           0 : nsDOMNavigationTiming::NotifyDOMLoading(nsIURI* aURI)
     166             : {
     167           0 :   if (!mDOMLoadingSet) {
     168           0 :     mLoadedURI = aURI;
     169           0 :     mDOMLoading = DurationFromStart();
     170           0 :     mDOMLoadingSet = true;
     171             : 
     172           0 :     profiler_add_marker("Navigation::DOMLoading");
     173             : 
     174           0 :     if (IsTopLevelContentDocument()) {
     175           0 :       Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_DOM_LOADING_MS,
     176           0 :                                      mNavigationStartTimeStamp);
     177             :     }
     178             :   }
     179           0 : }
     180             : 
     181             : void
     182          24 : nsDOMNavigationTiming::NotifyDOMInteractive(nsIURI* aURI)
     183             : {
     184          24 :   if (!mDOMInteractiveSet) {
     185          24 :     mLoadedURI = aURI;
     186          24 :     mDOMInteractive = DurationFromStart();
     187          24 :     mDOMInteractiveSet = true;
     188             : 
     189          24 :     profiler_add_marker("Navigation::DOMInteractive");
     190             : 
     191          24 :     if (IsTopLevelContentDocument()) {
     192           1 :       Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_DOM_INTERACTIVE_MS,
     193           1 :                                      mNavigationStartTimeStamp);
     194             :     }
     195             :   }
     196          24 : }
     197             : 
     198             : void
     199           4 : nsDOMNavigationTiming::NotifyDOMComplete(nsIURI* aURI)
     200             : {
     201           4 :   if (!mDOMCompleteSet) {
     202           4 :     mLoadedURI = aURI;
     203           4 :     mDOMComplete = DurationFromStart();
     204           4 :     mDOMCompleteSet = true;
     205             : 
     206           4 :     profiler_add_marker("Navigation::DOMComplete");
     207             : 
     208           4 :     if (IsTopLevelContentDocument()) {
     209           1 :       Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_DOM_COMPLETE_MS,
     210           1 :                                      mNavigationStartTimeStamp);
     211             :     }
     212             :   }
     213           4 : }
     214             : 
     215             : void
     216          25 : nsDOMNavigationTiming::NotifyDOMContentLoadedStart(nsIURI* aURI)
     217             : {
     218          25 :   if (!mDOMContentLoadedEventStartSet) {
     219          25 :     mLoadedURI = aURI;
     220          25 :     mDOMContentLoadedEventStart = DurationFromStart();
     221          25 :     mDOMContentLoadedEventStartSet = true;
     222             : 
     223          25 :     profiler_tracing("Navigation", "DOMContentLoaded", TRACING_INTERVAL_START);
     224             : 
     225          25 :     if (IsTopLevelContentDocument()) {
     226           1 :       Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_DOM_CONTENT_LOADED_START_MS,
     227           1 :                                      mNavigationStartTimeStamp);
     228             :     }
     229             :   }
     230          25 : }
     231             : 
     232             : void
     233          25 : nsDOMNavigationTiming::NotifyDOMContentLoadedEnd(nsIURI* aURI)
     234             : {
     235          25 :   if (!mDOMContentLoadedEventEndSet) {
     236          25 :     mLoadedURI = aURI;
     237          25 :     mDOMContentLoadedEventEnd = DurationFromStart();
     238          25 :     mDOMContentLoadedEventEndSet = true;
     239             : 
     240          25 :     profiler_tracing("Navigation", "DOMContentLoaded", TRACING_INTERVAL_END);
     241             : 
     242          25 :     if (IsTopLevelContentDocument()) {
     243           1 :       Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_DOM_CONTENT_LOADED_END_MS,
     244           1 :                                      mNavigationStartTimeStamp);
     245             :     }
     246             :   }
     247          25 : }
     248             : 
     249             : void
     250           1 : nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument()
     251             : {
     252           1 :   MOZ_ASSERT(NS_IsMainThread());
     253           1 :   MOZ_ASSERT(!mNavigationStartTimeStamp.IsNull());
     254             : 
     255           1 :   if (!mNonBlankPaintTimeStamp.IsNull()) {
     256           0 :     return;
     257             :   }
     258             : 
     259           1 :   mNonBlankPaintTimeStamp = TimeStamp::Now();
     260           1 :   TimeDuration elapsed = mNonBlankPaintTimeStamp - mNavigationStartTimeStamp;
     261             : 
     262           1 :   if (profiler_is_active()) {
     263           0 :     nsAutoCString spec;
     264           0 :     if (mLoadedURI) {
     265           0 :       mLoadedURI->GetSpec(spec);
     266             :     }
     267             :     nsPrintfCString marker("Non-blank paint after %dms for URL %s, %s",
     268           0 :                            int(elapsed.ToMilliseconds()), spec.get(),
     269           0 :                            mDocShellHasBeenActiveSinceNavigationStart ? "foreground tab" : "this tab was inactive some of the time between navigation start and first non-blank paint");
     270           0 :     profiler_add_marker(marker.get());
     271             :   }
     272             : 
     273           1 :   if (mDocShellHasBeenActiveSinceNavigationStart) {
     274             :     Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_NON_BLANK_PAINT_MS,
     275             :                                    mNavigationStartTimeStamp,
     276           1 :                                    mNonBlankPaintTimeStamp);
     277             :   }
     278             : }
     279             : 
     280             : void
     281           0 : nsDOMNavigationTiming::NotifyDocShellStateChanged(DocShellState aDocShellState)
     282             : {
     283           0 :   mDocShellHasBeenActiveSinceNavigationStart &=
     284           0 :     (aDocShellState == DocShellState::eActive);
     285           0 : }
     286             : 
     287             : DOMTimeMilliSec
     288           0 : nsDOMNavigationTiming::GetUnloadEventStart()
     289             : {
     290           0 :   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
     291           0 :   nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false);
     292           0 :   if (NS_SUCCEEDED(rv)) {
     293           0 :     return mUnloadStart;
     294             :   }
     295           0 :   return 0;
     296             : }
     297             : 
     298             : DOMTimeMilliSec
     299           0 : nsDOMNavigationTiming::GetUnloadEventEnd()
     300             : {
     301           0 :   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
     302           0 :   nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false);
     303           0 :   if (NS_SUCCEEDED(rv)) {
     304           0 :     return mUnloadEnd;
     305             :   }
     306           0 :   return 0;
     307             : }
     308             : 
     309             : bool
     310          86 : nsDOMNavigationTiming::IsTopLevelContentDocument() const
     311             : {
     312          86 :   if (!mDocShell) {
     313          63 :     return false;
     314             :   }
     315          46 :   nsCOMPtr<nsIDocShellTreeItem> rootItem;
     316          23 :   Unused << mDocShell->GetSameTypeRootTreeItem(getter_AddRefs(rootItem));
     317          23 :   if (rootItem.get() != static_cast<nsIDocShellTreeItem*>(mDocShell.get())) {
     318           6 :     return false;
     319             :   }
     320          17 :   return rootItem->ItemType() == nsIDocShellTreeItem::typeContent;
     321             : }

Generated by: LCOV version 1.13