2015-05-03 22:32:37 +03:00
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
2012-05-21 15:12:37 +04:00
/* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2.0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/. */
2011-06-23 14:39:48 +04:00
# include "nsDOMNavigationTiming.h"
2016-11-11 00:00:45 +03:00
# include "GeckoProfiler.h"
2011-06-23 14:39:48 +04:00
# include "nsCOMPtr.h"
2013-07-02 22:15:39 +04:00
# include "nsContentUtils.h"
2017-04-19 09:00:00 +03:00
# include "nsDocShell.h"
# include "nsIDocShellTreeItem.h"
2013-07-02 22:15:39 +04:00
# include "nsIScriptSecurityManager.h"
2013-07-03 19:56:26 +04:00
# include "prtime.h"
2013-08-15 22:17:48 +04:00
# include "nsIURI.h"
2016-11-11 00:00:45 +03:00
# include "nsPrintfCString.h"
2016-06-09 13:44:54 +03:00
# include "mozilla/dom/PerformanceNavigation.h"
2013-08-24 10:12:51 +04:00
# include "mozilla/TimeStamp.h"
2016-12-01 17:12:42 +03:00
# include "mozilla/Telemetry.h"
using namespace mozilla ;
2011-06-23 14:39:48 +04:00
2017-04-19 09:00:00 +03:00
nsDOMNavigationTiming : : nsDOMNavigationTiming ( nsDocShell * aDocShell )
2011-06-23 14:39:48 +04:00
{
Clear ( ) ;
2017-04-19 09:00:00 +03:00
mDocShell = aDocShell ;
2011-06-23 14:39:48 +04:00
}
nsDOMNavigationTiming : : ~ nsDOMNavigationTiming ( )
{
}
void
nsDOMNavigationTiming : : Clear ( )
{
2016-06-10 17:29:46 +03:00
mNavigationType = TYPE_RESERVED ;
2013-10-16 05:35:44 +04:00
mNavigationStartHighRes = 0 ;
2011-06-23 14:39:48 +04:00
mBeforeUnloadStart = 0 ;
mUnloadStart = 0 ;
mUnloadEnd = 0 ;
mLoadEventStart = 0 ;
mLoadEventEnd = 0 ;
mDOMLoading = 0 ;
mDOMInteractive = 0 ;
mDOMContentLoadedEventStart = 0 ;
mDOMContentLoadedEventEnd = 0 ;
mDOMComplete = 0 ;
2012-08-09 07:47:04 +04:00
mLoadEventStartSet = false ;
mLoadEventEndSet = false ;
mDOMLoadingSet = false ;
mDOMInteractiveSet = false ;
mDOMContentLoadedEventStartSet = false ;
mDOMContentLoadedEventEndSet = false ;
mDOMCompleteSet = false ;
2016-11-10 22:26:54 +03:00
mDocShellHasBeenActiveSinceNavigationStart = false ;
2011-06-23 14:39:48 +04:00
}
2012-07-17 05:42:18 +04:00
DOMTimeMilliSec
2016-12-01 17:12:42 +03:00
nsDOMNavigationTiming : : TimeStampToDOM ( TimeStamp aStamp ) const
2011-07-04 20:44:00 +04:00
{
if ( aStamp . IsNull ( ) ) {
2012-07-17 05:42:18 +04:00
return 0 ;
2011-07-04 20:44:00 +04:00
}
2016-12-01 17:12:42 +03:00
TimeDuration duration = aStamp - mNavigationStartTimeStamp ;
2013-10-16 05:35:44 +04:00
return GetNavigationStart ( ) + static_cast < int64_t > ( duration . ToMilliseconds ( ) ) ;
2011-08-08 16:20:03 +04:00
}
2015-05-25 19:53:07 +03:00
DOMTimeMilliSec nsDOMNavigationTiming : : DurationFromStart ( )
{
2016-12-01 17:12:42 +03:00
return TimeStampToDOM ( TimeStamp : : Now ( ) ) ;
2011-06-23 14:39:48 +04:00
}
void
2016-11-10 22:26:54 +03:00
nsDOMNavigationTiming : : NotifyNavigationStart ( DocShellState aDocShellState )
2011-06-23 14:39:48 +04:00
{
2013-10-16 05:35:44 +04:00
mNavigationStartHighRes = ( double ) PR_Now ( ) / PR_USEC_PER_MSEC ;
2016-12-01 17:12:42 +03:00
mNavigationStartTimeStamp = TimeStamp : : Now ( ) ;
2016-11-10 22:26:54 +03:00
mDocShellHasBeenActiveSinceNavigationStart = ( aDocShellState = = DocShellState : : eActive ) ;
2017-06-22 06:40:21 +03:00
profiler_add_marker ( " Navigation::Start " ) ;
2011-06-23 14:39:48 +04:00
}
void
2016-06-10 17:29:46 +03:00
nsDOMNavigationTiming : : NotifyFetchStart ( nsIURI * aURI , Type aNavigationType )
2011-06-23 14:39:48 +04:00
{
mNavigationType = aNavigationType ;
// At the unload event time we don't really know the loading uri.
// Need it for later check for unload timing access.
mLoadedURI = aURI ;
}
void
nsDOMNavigationTiming : : NotifyBeforeUnload ( )
{
mBeforeUnloadStart = DurationFromStart ( ) ;
}
void
nsDOMNavigationTiming : : NotifyUnloadAccepted ( nsIURI * aOldURI )
{
mUnloadStart = mBeforeUnloadStart ;
mUnloadedURI = aOldURI ;
}
void
nsDOMNavigationTiming : : NotifyUnloadEventStart ( )
{
mUnloadStart = DurationFromStart ( ) ;
2017-04-27 05:11:00 +03:00
profiler_tracing ( " Navigation " , " Unload " , TRACING_INTERVAL_START ) ;
2011-06-23 14:39:48 +04:00
}
void
nsDOMNavigationTiming : : NotifyUnloadEventEnd ( )
{
mUnloadEnd = DurationFromStart ( ) ;
2017-04-27 05:11:00 +03:00
profiler_tracing ( " Navigation " , " Unload " , TRACING_INTERVAL_END ) ;
2011-06-23 14:39:48 +04:00
}
void
nsDOMNavigationTiming : : NotifyLoadEventStart ( )
{
2012-08-09 07:47:04 +04:00
if ( ! mLoadEventStartSet ) {
mLoadEventStart = DurationFromStart ( ) ;
mLoadEventStartSet = true ;
2017-04-19 09:00:00 +03:00
2017-04-27 05:11:00 +03:00
profiler_tracing ( " Navigation " , " Load " , TRACING_INTERVAL_START ) ;
2017-04-19 09:00:00 +03:00
if ( IsTopLevelContentDocument ( ) ) {
Telemetry : : AccumulateTimeDelta ( Telemetry : : TIME_TO_LOAD_EVENT_START_MS ,
mNavigationStartTimeStamp ) ;
}
2012-08-09 07:47:04 +04:00
}
2011-06-23 14:39:48 +04:00
}
void
nsDOMNavigationTiming : : NotifyLoadEventEnd ( )
{
2012-08-09 07:47:04 +04:00
if ( ! mLoadEventEndSet ) {
mLoadEventEnd = DurationFromStart ( ) ;
mLoadEventEndSet = true ;
2017-04-19 09:00:00 +03:00
2017-04-27 05:11:00 +03:00
profiler_tracing ( " Navigation " , " Load " , TRACING_INTERVAL_END ) ;
2017-04-19 09:00:00 +03:00
if ( IsTopLevelContentDocument ( ) ) {
Telemetry : : AccumulateTimeDelta ( Telemetry : : TIME_TO_LOAD_EVENT_END_MS ,
mNavigationStartTimeStamp ) ;
}
2012-08-09 07:47:04 +04:00
}
2011-06-23 14:39:48 +04:00
}
void
2016-12-01 17:12:42 +03:00
nsDOMNavigationTiming : : SetDOMLoadingTimeStamp ( nsIURI * aURI , TimeStamp aValue )
2011-06-23 14:39:48 +04:00
{
2012-08-09 07:47:04 +04:00
if ( ! mDOMLoadingSet ) {
mLoadedURI = aURI ;
mDOMLoading = TimeStampToDOM ( aValue ) ;
mDOMLoadingSet = true ;
}
2011-06-23 14:39:48 +04:00
}
void
nsDOMNavigationTiming : : NotifyDOMLoading ( nsIURI * aURI )
{
2012-08-09 07:47:04 +04:00
if ( ! mDOMLoadingSet ) {
mLoadedURI = aURI ;
mDOMLoading = DurationFromStart ( ) ;
mDOMLoadingSet = true ;
2017-04-19 09:00:00 +03:00
2017-06-22 06:40:21 +03:00
profiler_add_marker ( " Navigation::DOMLoading " ) ;
2017-04-27 05:11:00 +03:00
2017-04-19 09:00:00 +03:00
if ( IsTopLevelContentDocument ( ) ) {
Telemetry : : AccumulateTimeDelta ( Telemetry : : TIME_TO_DOM_LOADING_MS ,
mNavigationStartTimeStamp ) ;
}
2012-08-09 07:47:04 +04:00
}
2011-06-23 14:39:48 +04:00
}
void
nsDOMNavigationTiming : : NotifyDOMInteractive ( nsIURI * aURI )
{
2012-08-09 07:47:04 +04:00
if ( ! mDOMInteractiveSet ) {
mLoadedURI = aURI ;
mDOMInteractive = DurationFromStart ( ) ;
mDOMInteractiveSet = true ;
2017-04-19 09:00:00 +03:00
2017-06-22 06:40:21 +03:00
profiler_add_marker ( " Navigation::DOMInteractive " ) ;
2017-04-27 05:11:00 +03:00
2017-04-19 09:00:00 +03:00
if ( IsTopLevelContentDocument ( ) ) {
Telemetry : : AccumulateTimeDelta ( Telemetry : : TIME_TO_DOM_INTERACTIVE_MS ,
mNavigationStartTimeStamp ) ;
}
2012-08-09 07:47:04 +04:00
}
2011-06-23 14:39:48 +04:00
}
void
nsDOMNavigationTiming : : NotifyDOMComplete ( nsIURI * aURI )
{
2012-08-09 07:47:04 +04:00
if ( ! mDOMCompleteSet ) {
mLoadedURI = aURI ;
mDOMComplete = DurationFromStart ( ) ;
mDOMCompleteSet = true ;
2017-04-19 09:00:00 +03:00
2017-06-22 06:40:21 +03:00
profiler_add_marker ( " Navigation::DOMComplete " ) ;
2017-04-27 05:11:00 +03:00
2017-04-19 09:00:00 +03:00
if ( IsTopLevelContentDocument ( ) ) {
Telemetry : : AccumulateTimeDelta ( Telemetry : : TIME_TO_DOM_COMPLETE_MS ,
mNavigationStartTimeStamp ) ;
}
2012-08-09 07:47:04 +04:00
}
2011-06-23 14:39:48 +04:00
}
void
nsDOMNavigationTiming : : NotifyDOMContentLoadedStart ( nsIURI * aURI )
{
2012-08-09 07:47:04 +04:00
if ( ! mDOMContentLoadedEventStartSet ) {
mLoadedURI = aURI ;
mDOMContentLoadedEventStart = DurationFromStart ( ) ;
mDOMContentLoadedEventStartSet = true ;
2017-04-19 09:00:00 +03:00
2017-04-27 05:11:00 +03:00
profiler_tracing ( " Navigation " , " DOMContentLoaded " , TRACING_INTERVAL_START ) ;
2017-04-19 09:00:00 +03:00
if ( IsTopLevelContentDocument ( ) ) {
Telemetry : : AccumulateTimeDelta ( Telemetry : : TIME_TO_DOM_CONTENT_LOADED_START_MS ,
mNavigationStartTimeStamp ) ;
}
2012-08-09 07:47:04 +04:00
}
2011-06-23 14:39:48 +04:00
}
void
nsDOMNavigationTiming : : NotifyDOMContentLoadedEnd ( nsIURI * aURI )
{
2012-08-09 07:47:04 +04:00
if ( ! mDOMContentLoadedEventEndSet ) {
mLoadedURI = aURI ;
mDOMContentLoadedEventEnd = DurationFromStart ( ) ;
mDOMContentLoadedEventEndSet = true ;
2017-04-19 09:00:00 +03:00
2017-04-27 05:11:00 +03:00
profiler_tracing ( " Navigation " , " DOMContentLoaded " , TRACING_INTERVAL_END ) ;
2017-04-19 09:00:00 +03:00
if ( IsTopLevelContentDocument ( ) ) {
Telemetry : : AccumulateTimeDelta ( Telemetry : : TIME_TO_DOM_CONTENT_LOADED_END_MS ,
mNavigationStartTimeStamp ) ;
}
2012-08-09 07:47:04 +04:00
}
2011-06-23 14:39:48 +04:00
}
2016-11-11 00:00:45 +03:00
void
2016-11-10 22:26:54 +03:00
nsDOMNavigationTiming : : NotifyNonBlankPaintForRootContentDocument ( )
2016-11-11 00:00:45 +03:00
{
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
MOZ_ASSERT ( ! mNavigationStartTimeStamp . IsNull ( ) ) ;
if ( ! mNonBlankPaintTimeStamp . IsNull ( ) ) {
return ;
}
mNonBlankPaintTimeStamp = TimeStamp : : Now ( ) ;
TimeDuration elapsed = mNonBlankPaintTimeStamp - mNavigationStartTimeStamp ;
if ( profiler_is_active ( ) ) {
nsAutoCString spec ;
if ( mLoadedURI ) {
mLoadedURI - > GetSpec ( spec ) ;
}
2016-11-10 22:26:54 +03:00
nsPrintfCString marker ( " Non-blank paint after %dms for URL %s, %s " ,
int ( elapsed . ToMilliseconds ( ) ) , spec . get ( ) ,
mDocShellHasBeenActiveSinceNavigationStart ? " foreground tab " : " this tab was inactive some of the time between navigation start and first non-blank paint " ) ;
2017-06-22 06:40:21 +03:00
profiler_add_marker ( marker . get ( ) ) ;
2016-11-11 00:00:45 +03:00
}
2016-11-10 22:26:54 +03:00
if ( mDocShellHasBeenActiveSinceNavigationStart ) {
Telemetry : : AccumulateTimeDelta ( Telemetry : : TIME_TO_NON_BLANK_PAINT_MS ,
mNavigationStartTimeStamp ,
mNonBlankPaintTimeStamp ) ;
}
}
void
nsDOMNavigationTiming : : NotifyDocShellStateChanged ( DocShellState aDocShellState )
{
mDocShellHasBeenActiveSinceNavigationStart & =
( aDocShellState = = DocShellState : : eActive ) ;
2016-11-11 00:00:45 +03:00
}
2012-07-17 05:42:18 +04:00
DOMTimeMilliSec
nsDOMNavigationTiming : : GetUnloadEventStart ( )
2011-06-23 14:39:48 +04:00
{
nsIScriptSecurityManager * ssm = nsContentUtils : : GetSecurityManager ( ) ;
2011-10-17 18:59:28 +04:00
nsresult rv = ssm - > CheckSameOriginURI ( mLoadedURI , mUnloadedURI , false ) ;
2011-06-23 14:39:48 +04:00
if ( NS_SUCCEEDED ( rv ) ) {
2012-07-17 05:42:18 +04:00
return mUnloadStart ;
2011-06-23 14:39:48 +04:00
}
2012-07-17 05:42:18 +04:00
return 0 ;
2011-06-23 14:39:48 +04:00
}
2012-07-17 05:42:18 +04:00
DOMTimeMilliSec
nsDOMNavigationTiming : : GetUnloadEventEnd ( )
2011-06-23 14:39:48 +04:00
{
nsIScriptSecurityManager * ssm = nsContentUtils : : GetSecurityManager ( ) ;
2011-10-17 18:59:28 +04:00
nsresult rv = ssm - > CheckSameOriginURI ( mLoadedURI , mUnloadedURI , false ) ;
2011-06-23 14:39:48 +04:00
if ( NS_SUCCEEDED ( rv ) ) {
2012-07-17 05:42:18 +04:00
return mUnloadEnd ;
2011-06-23 14:39:48 +04:00
}
2012-07-17 05:42:18 +04:00
return 0 ;
2011-06-23 14:39:48 +04:00
}
2017-04-19 09:00:00 +03:00
bool
nsDOMNavigationTiming : : IsTopLevelContentDocument ( ) const
{
if ( ! mDocShell ) {
return false ;
}
nsCOMPtr < nsIDocShellTreeItem > rootItem ;
Unused < < mDocShell - > GetSameTypeRootTreeItem ( getter_AddRefs ( rootItem ) ) ;
if ( rootItem . get ( ) ! = static_cast < nsIDocShellTreeItem * > ( mDocShell . get ( ) ) ) {
return false ;
}
return rootItem - > ItemType ( ) = = nsIDocShellTreeItem : : typeContent ;
}