Bug 1064706 - Save timing info in nsPerformanceTiming to avoid keeping a ref to the channel r=bz

This commit is contained in:
Valentin Gosu 2014-10-21 15:49:40 +03:00
Родитель 6e415f1825
Коммит 79c0bcd432
2 изменённых файлов: 75 добавлений и 63 удалений

Просмотреть файл

@ -33,10 +33,12 @@ nsPerformanceTiming::nsPerformanceTiming(nsPerformance* aPerformance,
nsIHttpChannel* aHttpChannel, nsIHttpChannel* aHttpChannel,
DOMHighResTimeStamp aZeroTime) DOMHighResTimeStamp aZeroTime)
: mPerformance(aPerformance), : mPerformance(aPerformance),
mChannel(aChannel),
mFetchStart(0.0), mFetchStart(0.0),
mZeroTime(aZeroTime), mZeroTime(aZeroTime),
mRedirectCount(0),
mTimingAllowed(true), mTimingAllowed(true),
mAllRedirectsSameOrigin(true),
mInitialized(!!aChannel),
mReportCrossOriginRedirect(true) mReportCrossOriginRedirect(true)
{ {
MOZ_ASSERT(aPerformance, "Parent performance object should be provided"); MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
@ -49,11 +51,36 @@ nsPerformanceTiming::nsPerformanceTiming(nsPerformance* aPerformance,
// is being used for the navigation timing (document) and has a non-null // is being used for the navigation timing (document) and has a non-null
// value for the resource timing (any resources within the page). // value for the resource timing (any resources within the page).
if (aHttpChannel) { if (aHttpChannel) {
mTimingAllowed = CheckAllowedOrigin(aHttpChannel); mTimingAllowed = CheckAllowedOrigin(aHttpChannel, aChannel);
bool redirectsPassCheck = false; bool redirectsPassCheck = false;
mChannel->GetAllRedirectsPassTimingAllowCheck(&redirectsPassCheck); aChannel->GetAllRedirectsPassTimingAllowCheck(&redirectsPassCheck);
mReportCrossOriginRedirect = mTimingAllowed && redirectsPassCheck; mReportCrossOriginRedirect = mTimingAllowed && redirectsPassCheck;
} }
InitializeTimingInfo(aChannel);
}
// Copy the timing info from the channel so we don't need to keep the channel
// alive just to get the timestamps.
void
nsPerformanceTiming::InitializeTimingInfo(nsITimedChannel* aChannel)
{
if (aChannel) {
aChannel->GetAsyncOpen(&mAsyncOpen);
aChannel->GetAllRedirectsSameOrigin(&mAllRedirectsSameOrigin);
aChannel->GetRedirectCount(&mRedirectCount);
aChannel->GetRedirectStart(&mRedirectStart);
aChannel->GetRedirectEnd(&mRedirectEnd);
aChannel->GetDomainLookupStart(&mDomainLookupStart);
aChannel->GetDomainLookupEnd(&mDomainLookupEnd);
aChannel->GetConnectStart(&mConnectStart);
aChannel->GetConnectEnd(&mConnectEnd);
aChannel->GetRequestStart(&mRequestStart);
aChannel->GetResponseStart(&mResponseStart);
aChannel->GetCacheReadStart(&mCacheReadStart);
aChannel->GetResponseEnd(&mResponseEnd);
aChannel->GetCacheReadEnd(&mCacheReadEnd);
}
} }
nsPerformanceTiming::~nsPerformanceTiming() nsPerformanceTiming::~nsPerformanceTiming()
@ -67,12 +94,10 @@ nsPerformanceTiming::FetchStartHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime; return mZeroTime;
} }
TimeStamp stamp; MOZ_ASSERT(!mAsyncOpen.IsNull(), "The fetch start time stamp should always be "
mChannel->GetAsyncOpen(&stamp);
MOZ_ASSERT(!stamp.IsNull(), "The fetch start time stamp should always be "
"valid if the performance timing is enabled"); "valid if the performance timing is enabled");
mFetchStart = (!stamp.IsNull()) mFetchStart = (!mAsyncOpen.IsNull())
? TimeStampToDOMHighRes(stamp) ? TimeStampToDOMHighRes(mAsyncOpen)
: 0.0; : 0.0;
} }
return mFetchStart; return mFetchStart;
@ -85,7 +110,8 @@ nsPerformanceTiming::FetchStart()
} }
bool bool
nsPerformanceTiming::CheckAllowedOrigin(nsIHttpChannel* aResourceChannel) nsPerformanceTiming::CheckAllowedOrigin(nsIHttpChannel* aResourceChannel,
nsITimedChannel* aChannel)
{ {
if (!IsInitialized()) { if (!IsInitialized()) {
return false; return false;
@ -102,7 +128,7 @@ nsPerformanceTiming::CheckAllowedOrigin(nsIHttpChannel* aResourceChannel)
// Check if the resource is either same origin as the page that started // Check if the resource is either same origin as the page that started
// the load, or if the response contains the proper Timing-Allow-Origin // the load, or if the response contains the proper Timing-Allow-Origin
// header with the domain of the page that started the load. // header with the domain of the page that started the load.
return mChannel->TimingAllowCheck(principal); return aChannel->TimingAllowCheck(principal);
} }
bool bool
@ -117,14 +143,10 @@ nsPerformanceTiming::GetRedirectCount() const
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return 0; return 0;
} }
bool sameOrigin; if (!mAllRedirectsSameOrigin) {
mChannel->GetAllRedirectsSameOrigin(&sameOrigin);
if (!sameOrigin) {
return 0; return 0;
} }
uint16_t redirectCount; return mRedirectCount;
mChannel->GetRedirectCount(&redirectCount);
return redirectCount;
} }
bool bool
@ -137,9 +159,7 @@ nsPerformanceTiming::ShouldReportCrossOriginRedirect() const
// If the redirect count is 0, or if one of the cross-origin // If the redirect count is 0, or if one of the cross-origin
// redirects doesn't have the proper Timing-Allow-Origin header, // redirects doesn't have the proper Timing-Allow-Origin header,
// then RedirectStart and RedirectEnd will be set to zero // then RedirectStart and RedirectEnd will be set to zero
uint16_t redirectCount; return (mRedirectCount != 0) && mReportCrossOriginRedirect;
mChannel->GetRedirectCount(&redirectCount);
return (redirectCount != 0) && mReportCrossOriginRedirect;
} }
/** /**
@ -158,9 +178,7 @@ nsPerformanceTiming::RedirectStartHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime; return mZeroTime;
} }
mozilla::TimeStamp stamp; return TimeStampToDOMHighResOrFetchStart(mRedirectStart);
mChannel->GetRedirectStart(&stamp);
return TimeStampToDOMHighResOrFetchStart(stamp);
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -171,9 +189,7 @@ nsPerformanceTiming::RedirectStart()
} }
// We have to check if all the redirect URIs had the same origin (since there // We have to check if all the redirect URIs had the same origin (since there
// is no check in RedirectStartHighRes()) // is no check in RedirectStartHighRes())
bool sameOrigin; if (mAllRedirectsSameOrigin) {
mChannel->GetAllRedirectsSameOrigin(&sameOrigin);
if (sameOrigin) {
return static_cast<int64_t>(RedirectStartHighRes()); return static_cast<int64_t>(RedirectStartHighRes());
} }
return 0; return 0;
@ -195,9 +211,7 @@ nsPerformanceTiming::RedirectEndHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime; return mZeroTime;
} }
mozilla::TimeStamp stamp; return TimeStampToDOMHighResOrFetchStart(mRedirectEnd);
mChannel->GetRedirectEnd(&stamp);
return TimeStampToDOMHighResOrFetchStart(stamp);
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -208,9 +222,7 @@ nsPerformanceTiming::RedirectEnd()
} }
// We have to check if all the redirect URIs had the same origin (since there // We have to check if all the redirect URIs had the same origin (since there
// is no check in RedirectEndHighRes()) // is no check in RedirectEndHighRes())
bool sameOrigin; if (mAllRedirectsSameOrigin) {
mChannel->GetAllRedirectsSameOrigin(&sameOrigin);
if (sameOrigin) {
return static_cast<int64_t>(RedirectEndHighRes()); return static_cast<int64_t>(RedirectEndHighRes());
} }
return 0; return 0;
@ -222,9 +234,7 @@ nsPerformanceTiming::DomainLookupStartHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime; return mZeroTime;
} }
mozilla::TimeStamp stamp; return TimeStampToDOMHighResOrFetchStart(mDomainLookupStart);
mChannel->GetDomainLookupStart(&stamp);
return TimeStampToDOMHighResOrFetchStart(stamp);
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -239,9 +249,7 @@ nsPerformanceTiming::DomainLookupEndHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime; return mZeroTime;
} }
mozilla::TimeStamp stamp; return TimeStampToDOMHighResOrFetchStart(mDomainLookupEnd);
mChannel->GetDomainLookupEnd(&stamp);
return TimeStampToDOMHighResOrFetchStart(stamp);
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -256,9 +264,7 @@ nsPerformanceTiming::ConnectStartHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime; return mZeroTime;
} }
mozilla::TimeStamp stamp; return TimeStampToDOMHighResOrFetchStart(mConnectStart);
mChannel->GetConnectStart(&stamp);
return TimeStampToDOMHighResOrFetchStart(stamp);
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -273,9 +279,7 @@ nsPerformanceTiming::ConnectEndHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime; return mZeroTime;
} }
mozilla::TimeStamp stamp; return TimeStampToDOMHighResOrFetchStart(mConnectEnd);
mChannel->GetConnectEnd(&stamp);
return TimeStampToDOMHighResOrFetchStart(stamp);
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -290,9 +294,7 @@ nsPerformanceTiming::RequestStartHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime; return mZeroTime;
} }
mozilla::TimeStamp stamp; return TimeStampToDOMHighResOrFetchStart(mRequestStart);
mChannel->GetRequestStart(&stamp);
return TimeStampToDOMHighResOrFetchStart(stamp);
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -307,14 +309,11 @@ nsPerformanceTiming::ResponseStartHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime; return mZeroTime;
} }
mozilla::TimeStamp stamp; if (mResponseStart.IsNull() ||
mChannel->GetResponseStart(&stamp); (!mCacheReadStart.IsNull() && mCacheReadStart < mResponseStart)) {
mozilla::TimeStamp cacheStamp; mResponseStart = mCacheReadStart;
mChannel->GetCacheReadStart(&cacheStamp);
if (stamp.IsNull() || (!cacheStamp.IsNull() && cacheStamp < stamp)) {
stamp = cacheStamp;
} }
return TimeStampToDOMHighResOrFetchStart(stamp); return TimeStampToDOMHighResOrFetchStart(mResponseStart);
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -329,14 +328,11 @@ nsPerformanceTiming::ResponseEndHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime; return mZeroTime;
} }
mozilla::TimeStamp stamp; if (mResponseEnd.IsNull() ||
mChannel->GetResponseEnd(&stamp); (!mCacheReadEnd.IsNull() && mCacheReadEnd < mResponseEnd)) {
mozilla::TimeStamp cacheStamp; mResponseEnd = mCacheReadEnd;
mChannel->GetCacheReadEnd(&cacheStamp);
if (stamp.IsNull() || (!cacheStamp.IsNull() && cacheStamp < stamp)) {
stamp = cacheStamp;
} }
return TimeStampToDOMHighResOrFetchStart(stamp); return TimeStampToDOMHighResOrFetchStart(mResponseEnd);
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -348,7 +344,7 @@ nsPerformanceTiming::ResponseEnd()
bool bool
nsPerformanceTiming::IsInitialized() const nsPerformanceTiming::IsInitialized() const
{ {
return !!mChannel; return mInitialized;
} }
JSObject* JSObject*

Просмотреть файл

@ -142,7 +142,7 @@ public:
// Checks if the resource is either same origin as the page that started // 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 // the load, or if the response contains the Timing-Allow-Origin header
// with a value of * or matching the domain of the loading Principal // with a value of * or matching the domain of the loading Principal
bool CheckAllowedOrigin(nsIHttpChannel* aResourceChannel); bool CheckAllowedOrigin(nsIHttpChannel* aResourceChannel, nsITimedChannel* aChannel);
// Cached result of CheckAllowedOrigin. If false, security sensitive // Cached result of CheckAllowedOrigin. If false, security sensitive
// attributes of the resourceTiming object will be set to 0 // attributes of the resourceTiming object will be set to 0
bool TimingAllowed() const; bool TimingAllowed() const;
@ -222,15 +222,31 @@ public:
private: private:
~nsPerformanceTiming(); ~nsPerformanceTiming();
bool IsInitialized() const; bool IsInitialized() const;
void InitializeTimingInfo(nsITimedChannel* aChannel);
nsRefPtr<nsPerformance> mPerformance; nsRefPtr<nsPerformance> mPerformance;
nsCOMPtr<nsITimedChannel> mChannel;
DOMHighResTimeStamp mFetchStart; DOMHighResTimeStamp mFetchStart;
// This is an offset that will be added to each timing ([ms] resolution). // This is an offset that will be added to each timing ([ms] resolution).
// There are only 2 possible values: (1) logicaly equal to navigationStart // There are only 2 possible values: (1) logicaly equal to navigationStart
// TimeStamp (results are absolute timstamps - wallclock); (2) "0" (results // TimeStamp (results are absolute timstamps - wallclock); (2) "0" (results
// are relative to the navigation start). // are relative to the navigation start).
DOMHighResTimeStamp mZeroTime; DOMHighResTimeStamp mZeroTime;
TimeStamp mAsyncOpen;
TimeStamp mRedirectStart;
TimeStamp mRedirectEnd;
TimeStamp mDomainLookupStart;
TimeStamp mDomainLookupEnd;
TimeStamp mConnectStart;
TimeStamp mConnectEnd;
TimeStamp mRequestStart;
TimeStamp mResponseStart;
TimeStamp mCacheReadStart;
TimeStamp mResponseEnd;
TimeStamp mCacheReadEnd;
uint16_t mRedirectCount;
bool mTimingAllowed; bool mTimingAllowed;
bool mAllRedirectsSameOrigin;
bool mInitialized;
// If the resourceTiming object should have non-zero redirectStart and // If the resourceTiming object should have non-zero redirectStart and
// redirectEnd attributes. It is false if there were no redirects, or if // redirectEnd attributes. It is false if there were no redirects, or if