Bug 1425462 Pass in a time origin for the Performance APIs. At least I think I got them all...
MozReview-Commit-ID: 7em25TgqUrD
--- a/dom/performance/PerformanceTiming.cpp
+++ b/dom/performance/PerformanceTiming.cpp
@@ -22,16 +22,17 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(P
PerformanceTiming::PerformanceTiming(Performance* aPerformance,
nsITimedChannel* aChannel,
nsIHttpChannel* aHttpChannel,
DOMHighResTimeStamp aZeroTime)
: mPerformance(aPerformance),
mFetchStart(0.0),
mZeroTime(nsRFPService::ReduceTimePrecisionAsMSecs(aZeroTime)),
+ mPerformanceTimingType(aZeroTime == 0 ? RESOURCE_TIMING : NAVIGATION_TIMING),
mRedirectCount(0),
mTimingAllowed(true),
mAllRedirectsSameOrigin(true),
mInitialized(!!aChannel),
mReportCrossOriginRedirect(true)
{
MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
@@ -152,29 +153,30 @@ PerformanceTiming::~PerformanceTiming()
}
DOMHighResTimeStamp
PerformanceTiming::FetchStartHighRes()
{
if (!mFetchStart) {
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
nsContentUtils::ShouldResistFingerprinting()) {
- return mZeroTime;
+ return nsRFPService::ReduceTimePrecisionAsMSecs(mZeroTime, 0, false);
}
MOZ_ASSERT(!mAsyncOpen.IsNull(), "The fetch start time stamp should always be "
"valid if the performance timing is enabled");
if (!mAsyncOpen.IsNull()) {
if (!mWorkerRequestStart.IsNull() && mWorkerRequestStart > mAsyncOpen) {
mFetchStart = TimeStampToDOMHighRes(mWorkerRequestStart);
} else {
mFetchStart = TimeStampToDOMHighRes(mAsyncOpen);
}
}
}
- return nsRFPService::ReduceTimePrecisionAsMSecs(mFetchStart);
+ return nsRFPService::ReduceTimePrecisionAsMSecs(mFetchStart,
+ GetAbsoluteTimeReferencePoint(), false);
}
DOMTimeMilliSec
PerformanceTiming::FetchStart()
{
return static_cast<int64_t>(FetchStartHighRes());
}
@@ -243,27 +245,29 @@ PerformanceTiming::ShouldReportCrossOrig
DOMHighResTimeStamp
PerformanceTiming::AsyncOpenHighRes()
{
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
nsContentUtils::ShouldResistFingerprinting() || mAsyncOpen.IsNull()) {
return mZeroTime;
}
- return nsRFPService::ReduceTimePrecisionAsMSecs(TimeStampToDOMHighRes(mAsyncOpen));
+ return nsRFPService::ReduceTimePrecisionAsMSecs(
+ TimeStampToDOMHighRes(mAsyncOpen), GetAbsoluteTimeReferencePoint(), false);
}
DOMHighResTimeStamp
PerformanceTiming::WorkerStartHighRes()
{
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
nsContentUtils::ShouldResistFingerprinting() || mWorkerStart.IsNull()) {
return mZeroTime;
}
- return nsRFPService::ReduceTimePrecisionAsMSecs(TimeStampToDOMHighRes(mWorkerStart));
+ return nsRFPService::ReduceTimePrecisionAsMSecs(
+ TimeStampToDOMHighRes(mWorkerStart), GetAbsoluteTimeReferencePoint(), false);
}
/**
* RedirectStartHighRes() is used by both the navigation timing and the
* resource timing. Since, navigation timing and resource timing check and
* interpret cross-domain redirects in a different manner,
* RedirectStartHighRes() will make no checks for cross-domain redirect.
* It's up to the consumers of this method (PerformanceTiming::RedirectStart()
@@ -350,17 +354,18 @@ PerformanceTiming::DomainLookupEndHighRe
{
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
nsContentUtils::ShouldResistFingerprinting()) {
return mZeroTime;
}
// Bug 1155008 - nsHttpTransaction is racy. Return DomainLookupStart when null
return mDomainLookupEnd.IsNull() ? DomainLookupStartHighRes()
: nsRFPService::ReduceTimePrecisionAsMSecs(
- TimeStampToDOMHighRes(mDomainLookupEnd));
+ TimeStampToDOMHighRes(mDomainLookupEnd),
+ GetAbsoluteTimeReferencePoint(), false);
}
DOMTimeMilliSec
PerformanceTiming::DomainLookupEnd()
{
return static_cast<int64_t>(DomainLookupEndHighRes());
}
@@ -368,17 +373,18 @@ DOMHighResTimeStamp
PerformanceTiming::ConnectStartHighRes()
{
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
nsContentUtils::ShouldResistFingerprinting()) {
return mZeroTime;
}
return mConnectStart.IsNull() ? DomainLookupEndHighRes()
: nsRFPService::ReduceTimePrecisionAsMSecs(
- TimeStampToDOMHighRes(mConnectStart));
+ TimeStampToDOMHighRes(mConnectStart),
+ GetAbsoluteTimeReferencePoint(), false);
}
DOMTimeMilliSec
PerformanceTiming::ConnectStart()
{
return static_cast<int64_t>(ConnectStartHighRes());
}
@@ -389,17 +395,18 @@ PerformanceTiming::SecureConnectionStart
nsContentUtils::ShouldResistFingerprinting()) {
return mZeroTime;
}
return !mSecureConnection
? 0 // We use 0 here, because mZeroTime is sometimes set to the navigation
// start time.
: (mSecureConnectionStart.IsNull() ? mZeroTime
: nsRFPService::ReduceTimePrecisionAsMSecs(
- TimeStampToDOMHighRes(mSecureConnectionStart)));
+ TimeStampToDOMHighRes(mSecureConnectionStart),
+ GetAbsoluteTimeReferencePoint(), false));
}
DOMTimeMilliSec
PerformanceTiming::SecureConnectionStart()
{
return static_cast<int64_t>(SecureConnectionStartHighRes());
}
@@ -408,17 +415,18 @@ PerformanceTiming::ConnectEndHighRes()
{
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
nsContentUtils::ShouldResistFingerprinting()) {
return mZeroTime;
}
// Bug 1155008 - nsHttpTransaction is racy. Return ConnectStart when null
return mConnectEnd.IsNull() ? ConnectStartHighRes()
: nsRFPService::ReduceTimePrecisionAsMSecs(
- TimeStampToDOMHighRes(mConnectEnd));
+ TimeStampToDOMHighRes(mConnectEnd),
+ GetAbsoluteTimeReferencePoint(), false);
}
DOMTimeMilliSec
PerformanceTiming::ConnectEnd()
{
return static_cast<int64_t>(ConnectEndHighRes());
}
@@ -480,17 +488,18 @@ PerformanceTiming::ResponseEndHighRes()
mResponseEnd = mCacheReadEnd;
}
if (mResponseEnd.IsNull()) {
mResponseEnd = mWorkerResponseEnd;
}
// Bug 1155008 - nsHttpTransaction is racy. Return ResponseStart when null
return mResponseEnd.IsNull() ? ResponseStartHighRes()
: nsRFPService::ReduceTimePrecisionAsMSecs(
- TimeStampToDOMHighRes(mResponseEnd));
+ TimeStampToDOMHighRes(mResponseEnd),
+ GetAbsoluteTimeReferencePoint(), false);
}
DOMTimeMilliSec
PerformanceTiming::ResponseEnd()
{
return static_cast<int64_t>(ResponseEndHighRes());
}
--- a/dom/performance/PerformanceTiming.h
+++ b/dom/performance/PerformanceTiming.h
@@ -67,17 +67,18 @@ public:
* @return the duration of an event with a given TimeStamp, relative to the
* navigationStart TimeStamp (the moment the user landed on the
* page), if the given TimeStamp is valid. Otherwise, it will return
* the FetchStart timing value.
*/
inline DOMHighResTimeStamp TimeStampToReducedDOMHighResOrFetchStart(TimeStamp aStamp)
{
return (!aStamp.IsNull())
- ? nsRFPService::ReduceTimePrecisionAsMSecs(TimeStampToDOMHighRes(aStamp))
+ ? nsRFPService::ReduceTimePrecisionAsMSecs(TimeStampToDOMHighRes(aStamp),
+ GetAbsoluteTimeReferencePoint(), false)
: FetchStartHighRes();
}
/**
* The nsITimedChannel records an absolute timestamp for each event.
* The nsDOMNavigationTiming will record the moment when the user landed on
* the page. This is a window.performance unique timestamp, so it can be used
* for all the events (navigation timing and resource timing events).
@@ -117,37 +118,40 @@ public:
// PerformanceNavigation WebIDL methods
DOMTimeMilliSec NavigationStart() const
{
if (!nsContentUtils::IsPerformanceTimingEnabled() ||
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
- GetDOMTiming()->GetNavigationStart(), 0, false);
+ GetDOMTiming()->GetNavigationStart(),
+ GetAbsoluteTimeReferencePoint(), false);
}
DOMTimeMilliSec UnloadEventStart()
{
if (!nsContentUtils::IsPerformanceTimingEnabled() ||
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
- GetDOMTiming()->GetUnloadEventStart());
+ GetDOMTiming()->GetUnloadEventStart(),
+ GetAbsoluteTimeReferencePoint(), false);
}
DOMTimeMilliSec UnloadEventEnd()
{
if (!nsContentUtils::IsPerformanceTimingEnabled() ||
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
- GetDOMTiming()->GetUnloadEventEnd());
+ GetDOMTiming()->GetUnloadEventEnd(),
+ GetAbsoluteTimeReferencePoint(), false);
}
uint8_t GetRedirectCount() const;
// Checks if the resource is either same origin as the page that started
// the load, or if the response contains the Timing-Allow-Origin header
// with a value of * or matching the domain of the loading Principal
bool CheckAllowedOrigin(nsIHttpChannel* aResourceChannel, nsITimedChannel* aChannel);
@@ -194,106 +198,134 @@ public:
DOMTimeMilliSec DomLoading()
{
if (!nsContentUtils::IsPerformanceTimingEnabled() ||
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
- GetDOMTiming()->GetDomLoading());
+ GetDOMTiming()->GetDomLoading(),
+ GetAbsoluteTimeReferencePoint(), false);
}
DOMTimeMilliSec DomInteractive() const
{
if (!nsContentUtils::IsPerformanceTimingEnabled() ||
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
- GetDOMTiming()->GetDomInteractive());
+ GetDOMTiming()->GetDomInteractive(), 0, false);
}
DOMTimeMilliSec DomContentLoadedEventStart() const
{
if (!nsContentUtils::IsPerformanceTimingEnabled() ||
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
- GetDOMTiming()->GetDomContentLoadedEventStart());
+ GetDOMTiming()->GetDomContentLoadedEventStart(),
+ GetAbsoluteTimeReferencePoint(), false);
}
DOMTimeMilliSec DomContentLoadedEventEnd() const
{
if (!nsContentUtils::IsPerformanceTimingEnabled() ||
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
- GetDOMTiming()->GetDomContentLoadedEventEnd());
+ GetDOMTiming()->GetDomContentLoadedEventEnd(),
+ GetAbsoluteTimeReferencePoint(), false);
}
DOMTimeMilliSec DomComplete() const
{
if (!nsContentUtils::IsPerformanceTimingEnabled() ||
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
- GetDOMTiming()->GetDomComplete());
+ GetDOMTiming()->GetDomComplete(),
+ GetAbsoluteTimeReferencePoint(), false);
}
DOMTimeMilliSec LoadEventStart() const
{
if (!nsContentUtils::IsPerformanceTimingEnabled() ||
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
- GetDOMTiming()->GetLoadEventStart());
+ GetDOMTiming()->GetLoadEventStart(),
+ GetAbsoluteTimeReferencePoint(), false);
}
DOMTimeMilliSec LoadEventEnd() const
{
if (!nsContentUtils::IsPerformanceTimingEnabled() ||
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
- GetDOMTiming()->GetLoadEventEnd());
+ GetDOMTiming()->GetLoadEventEnd(),
+ GetAbsoluteTimeReferencePoint(), false);
}
DOMTimeMilliSec TimeToNonBlankPaint() const
{
if (!nsContentUtils::IsPerformanceTimingEnabled() ||
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
- GetDOMTiming()->GetTimeToNonBlankPaint());
+ GetDOMTiming()->GetTimeToNonBlankPaint(),
+ GetAbsoluteTimeReferencePoint(), false);
}
private:
~PerformanceTiming();
bool IsInitialized() const;
void InitializeTimingInfo(nsITimedChannel* aChannel);
bool IsTopLevelContentDocument() const;
+ // Returns a value that should be added to the various timestamps
+ // to convert to milliseconds since the epoch
+ inline DOMTimeMilliSec GetAbsoluteTimeReferencePoint() const
+ {
+ return mPerformanceTimingType == RESOURCE_TIMING ?
+ this->GetDOMTiming()->GetNavigationStartHighRes() : 0;
+ }
+
RefPtr<Performance> mPerformance;
DOMHighResTimeStamp mFetchStart;
// This is an offset that will be added to each timing ([ms] resolution).
// There are only 2 possible values: (1) logicaly equal to navigationStart
// TimeStamp (results are absolute timstamps - wallclock); (2) "0" (results
// are relative to the navigation start).
DOMHighResTimeStamp mZeroTime;
+ enum PerformanceTimingType {
+ // Resource timing entries have relative timestamps and a zero mZeroTime
+ // They are access as part of performance.getEntriesByType("resource")
+ // or equivalent
+ RESOURCE_TIMING,
+ // Navigation timing entries are exposed by performance.timing.XXX, have
+ // a non-zero mZeroTime but have absolute timestamps. One should not
+ // add mZeroTime to the TimeStamp value; but one may subtract mZeroTime
+ // to get a duration.
+ NAVIGATION_TIMING
+ };
+ PerformanceTimingType mPerformanceTimingType;
+
TimeStamp mAsyncOpen;
TimeStamp mRedirectStart;
TimeStamp mRedirectEnd;
TimeStamp mDomainLookupStart;
TimeStamp mDomainLookupEnd;
TimeStamp mConnectStart;
TimeStamp mSecureConnectionStart;
TimeStamp mConnectEnd;