From e040ed925030f899f845d458c226f7e439f4ec8b Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 29 Apr 2018 11:49:50 +0200 Subject: moebius#158: The Performance Resource Timing (added support for "workerStart") https://github.com/MoonchildProductions/moebius/pull/158 --- dom/performance/PerformanceResourceTiming.cpp | 18 ++++++- dom/performance/PerformanceResourceTiming.h | 6 +++ dom/performance/PerformanceTiming.cpp | 71 ++++++++++++++++++++------- dom/performance/PerformanceTiming.h | 10 +++- 4 files changed, 82 insertions(+), 23 deletions(-) (limited to 'dom/performance') diff --git a/dom/performance/PerformanceResourceTiming.cpp b/dom/performance/PerformanceResourceTiming.cpp index 60a20ca28..94df27408 100644 --- a/dom/performance/PerformanceResourceTiming.cpp +++ b/dom/performance/PerformanceResourceTiming.cpp @@ -42,8 +42,22 @@ PerformanceResourceTiming::~PerformanceResourceTiming() DOMHighResTimeStamp PerformanceResourceTiming::StartTime() const { - DOMHighResTimeStamp startTime = mTiming->RedirectStartHighRes(); - return startTime ? startTime : mTiming->FetchStartHighRes(); + // Force the start time to be the earliest of: + // - RedirectStart + // - WorkerStart + // - AsyncOpen + // Ignore zero values. The RedirectStart and WorkerStart values + // can come from earlier redirected channels prior to the AsyncOpen + // time being recorded. + DOMHighResTimeStamp redirect = mTiming->RedirectStartHighRes(); + redirect = redirect ? redirect : DBL_MAX; + + DOMHighResTimeStamp worker = mTiming->WorkerStartHighRes(); + worker = worker ? worker : DBL_MAX; + + DOMHighResTimeStamp asyncOpen = mTiming->AsyncOpenHighRes(); + + return std::min(asyncOpen, std::min(redirect, worker)); } JSObject* diff --git a/dom/performance/PerformanceResourceTiming.h b/dom/performance/PerformanceResourceTiming.h index 2dd6b4a06..c2e6c0972 100644 --- a/dom/performance/PerformanceResourceTiming.h +++ b/dom/performance/PerformanceResourceTiming.h @@ -62,6 +62,12 @@ public: mNextHopProtocol = aNextHopProtocol; } + DOMHighResTimeStamp WorkerStart() const { + return mTiming && mTiming->TimingAllowed() + ? mTiming->WorkerStartHighRes() + : 0; + } + DOMHighResTimeStamp FetchStart() const { return mTiming ? mTiming->FetchStartHighRes() diff --git a/dom/performance/PerformanceTiming.cpp b/dom/performance/PerformanceTiming.cpp index e2f76a21f..887a23938 100755 --- a/dom/performance/PerformanceTiming.cpp +++ b/dom/performance/PerformanceTiming.cpp @@ -73,6 +73,7 @@ PerformanceTiming::InitializeTimingInfo(nsITimedChannel* aChannel) { if (aChannel) { aChannel->GetAsyncOpen(&mAsyncOpen); + aChannel->GetDispatchFetchEventStart(&mWorkerStart); aChannel->GetAllRedirectsSameOrigin(&mAllRedirectsSameOrigin); aChannel->GetRedirectCount(&mRedirectCount); aChannel->GetRedirectStart(&mRedirectStart); @@ -88,31 +89,39 @@ PerformanceTiming::InitializeTimingInfo(nsITimedChannel* aChannel) aChannel->GetResponseEnd(&mResponseEnd); aChannel->GetCacheReadEnd(&mCacheReadEnd); - // the performance timing api essentially requires that the event timestamps - // are >= asyncOpen().. but in truth the browser engages in a number of - // speculative activities that sometimes mean connections and lookups begin - // earlier. Workaround that here by just using asyncOpen as the minimum - // timestamp for dns and connection info. + // The performance timing api essentially requires that the event timestamps + // have a strict relation with each other. The truth, however, is the browser + // engages in a number of speculative activities that sometimes mean connections + // and lookups begin at different times. Workaround that here by clamping + // these values to what we expect FetchStart to be. This means the later of + // AsyncOpen or WorkerStart times. if (!mAsyncOpen.IsNull()) { - if (!mDomainLookupStart.IsNull() && mDomainLookupStart < mAsyncOpen) { - mDomainLookupStart = mAsyncOpen; + // We want to clamp to the expected FetchStart value. This is later of + // the AsyncOpen and WorkerStart values. + const TimeStamp* clampTime = &mAsyncOpen; + if (!mWorkerStart.IsNull() && mWorkerStart > mAsyncOpen) { + clampTime = &mWorkerStart; } - if (!mDomainLookupEnd.IsNull() && mDomainLookupEnd < mAsyncOpen) { - mDomainLookupEnd = mAsyncOpen; + if (!mDomainLookupStart.IsNull() && mDomainLookupStart < *clampTime) { + mDomainLookupStart = *clampTime; } - if (!mConnectStart.IsNull() && mConnectStart < mAsyncOpen) { - mConnectStart = mAsyncOpen; + if (!mDomainLookupEnd.IsNull() && mDomainLookupEnd < *clampTime) { + mDomainLookupEnd = *clampTime; + } + + if (!mConnectStart.IsNull() && mConnectStart < *clampTime) { + mConnectStart = *clampTime; } if (mSecureConnection && !mSecureConnectionStart.IsNull() && - mSecureConnectionStart < mAsyncOpen) { - mSecureConnectionStart = mAsyncOpen; + mSecureConnectionStart < *clampTime) { + mSecureConnectionStart = *clampTime; } - if (!mConnectEnd.IsNull() && mConnectEnd < mAsyncOpen) { - mConnectEnd = mAsyncOpen; + if (!mConnectEnd.IsNull() && mConnectEnd < *clampTime) { + mConnectEnd = *clampTime; } } } @@ -131,9 +140,13 @@ PerformanceTiming::FetchStartHighRes() } MOZ_ASSERT(!mAsyncOpen.IsNull(), "The fetch start time stamp should always be " "valid if the performance timing is enabled"); - mFetchStart = (!mAsyncOpen.IsNull()) - ? TimeStampToDOMHighRes(mAsyncOpen) - : 0.0; + if (!mAsyncOpen.IsNull()) { + if (!mWorkerStart.IsNull() && mWorkerStart > mAsyncOpen) { + mFetchStart = TimeStampToDOMHighRes(mWorkerStart); + } else { + mFetchStart = TimeStampToDOMHighRes(mAsyncOpen); + } + } } return TimerClamping::ReduceMsTimeValue(mFetchStart); } @@ -180,7 +193,7 @@ PerformanceTiming::TimingAllowed() const return mTimingAllowed; } -uint16_t +uint8_t PerformanceTiming::GetRedirectCount() const { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { @@ -205,6 +218,26 @@ PerformanceTiming::ShouldReportCrossOriginRedirect() const return (mRedirectCount != 0) && mReportCrossOriginRedirect; } +DOMHighResTimeStamp +PerformanceTiming::AsyncOpenHighRes() +{ + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() || + mAsyncOpen.IsNull()) { + return mZeroTime; + } + return TimeStampToReducedDOMHighResOrFetchStart(mAsyncOpen); +} + +DOMHighResTimeStamp +PerformanceTiming::WorkerStartHighRes() +{ + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() || + mWorkerStart.IsNull()) { + return mZeroTime; + } + return TimeStampToReducedDOMHighResOrFetchStart(mWorkerStart); +} + /** * RedirectStartHighRes() is used by both the navigation timing and the * resource timing. Since, navigation timing and resource timing check and diff --git a/dom/performance/PerformanceTiming.h b/dom/performance/PerformanceTiming.h index fc7e7d5bd..584ae0816 100755 --- a/dom/performance/PerformanceTiming.h +++ b/dom/performance/PerformanceTiming.h @@ -139,7 +139,7 @@ public: return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetUnloadEventEnd()); } - uint16_t GetRedirectCount() const; + 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 @@ -155,7 +155,12 @@ public: // the timing-allow-origin check in HttpBaseChannel::TimingAllowCheck bool ShouldReportCrossOriginRedirect() const; + // The last channel's AsyncOpen time. This may occur before the FetchStart + // in some cases. + DOMHighResTimeStamp AsyncOpenHighRes(); + // High resolution (used by resource timing) + DOMHighResTimeStamp WorkerStartHighRes(); DOMHighResTimeStamp FetchStartHighRes(); DOMHighResTimeStamp RedirectStartHighRes(); DOMHighResTimeStamp RedirectEndHighRes(); @@ -253,6 +258,7 @@ private: DOMHighResTimeStamp mZeroTime; TimeStamp mAsyncOpen; + TimeStamp mWorkerStart; TimeStamp mRedirectStart; TimeStamp mRedirectEnd; TimeStamp mDomainLookupStart; @@ -265,7 +271,7 @@ private: TimeStamp mCacheReadStart; TimeStamp mResponseEnd; TimeStamp mCacheReadEnd; - uint16_t mRedirectCount; + uint8_t mRedirectCount; bool mTimingAllowed; bool mAllRedirectsSameOrigin; bool mInitialized; -- cgit v1.2.3