/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */
// If the initiator type had no valid value, then set it to the default // ("other") value. if (aInitiatorType.IsEmpty()) {
aInitiatorType = u"other"_ns;
}
// According to the spec, "The name attribute must return the resolved URL // of the requested resource. This attribute must not change even if the // fetch redirected to a different URL."
nsCOMPtr<nsIURI> originalURI;
aChannel->GetOriginalURI(getter_AddRefs(originalURI));
// The nsITimedChannel argument will be used to gather all the timings. // The nsIHttpChannel argument will be used to check if any cross-origin // redirects occurred. // The last argument is the "zero time" (offset). Since we don't want // any offset for the resource timing, this will be set to "0" - the // resource timing returns a relative timing (no offset). returnnew PerformanceTimingData(aTimedChannel, aChannel, 0);
}
// Non-null aHttpChannel implies that this PerformanceTiming object is being // used for subresources, which is irrelevant to this probe. if (!aHttpChannel && StaticPrefs::dom_enable_performance() &&
IsTopLevelContentDocument()) {
glean::performance_time::response_start.AccumulateRawDuration(
TimeDuration::FromMilliseconds(
mTimingData->ResponseStartHighRes(aPerformance) -
mTimingData->ZeroTime()));
}
}
nsCOMPtr<nsIURI> uri; if (aHttpChannel) {
aHttpChannel->GetURI(getter_AddRefs(uri));
} else {
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel); if (httpChannel) {
httpChannel->GetURI(getter_AddRefs(uri));
}
}
if (uri) {
mSecureConnection = uri->SchemeIs("https");
}
if (aChannel) {
aChannel->GetAllRedirectsSameOrigin(&mAllRedirectsSameOrigin);
aChannel->GetAllRedirectsPassTimingAllowCheck(&mAllRedirectsPassTAO);
aChannel->GetRedirectCount(&mRedirectCount);
}
// The aHttpChannel argument is null if this PerformanceTiming object is // being used for navigation timing (which is only relevant for documents). // It has a non-null value if this PerformanceTiming object is being used // for resource timing, which can include document loads, both toplevel and // in subframes, and resources linked from a document. if (aHttpChannel) {
SetCacheablePropertiesFromHttpChannel(aHttpChannel, aChannel);
}
}
// Copy the timing info from the channel so we don't need to keep the channel // alive just to get the timestamps.
PerformanceTimingData::PerformanceTimingData(nsITimedChannel* aChannel,
nsIHttpChannel* aHttpChannel,
DOMHighResTimeStamp aZeroTime)
: CacheablePerformanceTimingData(aChannel, aHttpChannel),
mZeroTime(0.0),
mFetchStart(0.0),
mTransferSize(0) {
mZeroTime = aZeroTime;
if (!StaticPrefs::dom_enable_performance()) {
mZeroTime = 0;
}
aChannel->GetDispatchFetchEventStart(&mWorkerStart);
aChannel->GetHandleFetchEventStart(&mWorkerRequestStart); // TODO: Track when FetchEvent.respondWith() promise resolves as // ServiceWorker interception responseStart?
aChannel->GetHandleFetchEventEnd(&mWorkerResponseEnd);
// 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()) { // 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 (aHttpChannel) { // NOTE: Other fields are set by SetCacheablePropertiesFromHttpChannel, // called inside CacheablePerformanceTimingData constructor.
SetTransferSizeFromHttpChannel(aHttpChannel);
}
nsITimedChannel::BodyInfoAccess
CacheablePerformanceTimingData::CheckBodyInfoAccessAllowedForOrigin(
nsIHttpChannel* aResourceChannel, nsITimedChannel* aChannel) { // Check if the resource is either same origin as the page that started // the load, or if the response contains an Access-Control-Allow-Origin // header with the domain of the page that started the load.
MOZ_ASSERT(aChannel);
if (!IsInitialized()) { return nsITimedChannel::BodyInfoAccess::DISALLOWED;
}
// Check that the current document passes the check.
nsCOMPtr<nsILoadInfo> loadInfo = aResourceChannel->LoadInfo();
// TYPE_DOCUMENT loads have no loadingPrincipal. if (loadInfo->GetExternalContentPolicyType() ==
ExtContentPolicy::TYPE_DOCUMENT) { return nsITimedChannel::BodyInfoAccess::ALLOW_ALL;
}
nsCOMPtr<nsIPrincipal> principal = loadInfo->GetLoadingPrincipal(); if (!principal) { return nsITimedChannel::BodyInfoAccess::DISALLOWED;
} return aChannel->BodyInfoAccessAllowedCheck(principal);
}
bool CacheablePerformanceTimingData::CheckTimingAllowedForOrigin(
nsIHttpChannel* aResourceChannel, nsITimedChannel* aChannel) { // 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 // header with the domain of the page that started the load.
MOZ_ASSERT(aChannel);
if (!IsInitialized()) { returnfalse;
}
// Check that the current document passes the check.
nsCOMPtr<nsILoadInfo> loadInfo = aResourceChannel->LoadInfo();
// TYPE_DOCUMENT loads have no loadingPrincipal. if (loadInfo->GetExternalContentPolicyType() ==
ExtContentPolicy::TYPE_DOCUMENT) { returntrue;
}
nsCOMPtr<nsIPrincipal> principal = loadInfo->GetLoadingPrincipal(); return principal && aChannel->TimingAllowCheck(principal);
}
if (!mTimingAllowed || mRedirectCount == 0) { returnfalse;
}
// If the redirect count is 0, or if one of the cross-origin // redirects doesn't have the proper Timing-Allow-Origin header, // then RedirectStart and RedirectEnd will be set to zero return aEnsureSameOriginAndIgnoreTAO ? mAllRedirectsSameOrigin
: mAllRedirectsPassTAO;
}
/** * 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() * and PerformanceResourceTiming::RedirectStart() to make such verifications. * * @return a valid timing if the Performance Timing is enabled
*/
DOMHighResTimeStamp PerformanceTimingData::RedirectStartHighRes(
Performance* aPerformance) {
MOZ_ASSERT(aPerformance);
DOMTimeMilliSec PerformanceTiming::RedirectStart() { if (!mTimingData->IsInitialized()) { return 0;
} // We have to check if all the redirect URIs had the same origin (since there // is no check in RedirectStartHighRes()) if (mTimingData->AllRedirectsSameOrigin() &&
mTimingData->RedirectCountReal()) { returnstatic_cast<int64_t>(
mTimingData->RedirectStartHighRes(mPerformance));
} return 0;
}
/** * RedirectEndHighRes() 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, RedirectEndHighRes() will make * no checks for cross-domain redirect. It's up to the consumers of this method * (PerformanceTiming::RedirectEnd() and * PerformanceResourceTiming::RedirectEnd() to make such verifications. * * @return a valid timing if the Performance Timing is enabled
*/
DOMHighResTimeStamp PerformanceTimingData::RedirectEndHighRes(
Performance* aPerformance) {
MOZ_ASSERT(aPerformance);
DOMTimeMilliSec PerformanceTiming::RedirectEnd() { if (!mTimingData->IsInitialized()) { return 0;
} // We have to check if all the redirect URIs had the same origin (since there // is no check in RedirectEndHighRes()) if (mTimingData->AllRedirectsSameOrigin() &&
mTimingData->RedirectCountReal()) { returnstatic_cast<int64_t>(mTimingData->RedirectEndHighRes(mPerformance));
} return 0;
}
if (!StaticPrefs::dom_enable_performance() || !IsInitialized()) { return mZeroTime;
} // Bug 1637985 - DomainLookup information may be useful for fingerprinting. if (aPerformance->ShouldResistFingerprinting()) { return FetchStartHighRes(aPerformance);
} return TimeStampToReducedDOMHighResOrFetchStart(aPerformance,
mDomainLookupStart);
}
if (!StaticPrefs::dom_enable_performance() || !IsInitialized()) { return mZeroTime;
} if (!mSecureConnection) { return 0; // We use 0 here, because mZeroTime is sometimes set to the // navigation start time.
} if (mSecureConnectionStart.IsNull()) { return ConnectStartHighRes(aPerformance);
}
DOMHighResTimeStamp rawValue =
TimeStampToDOMHighRes(aPerformance, mSecureConnectionStart); return nsRFPService::ReduceTimePrecisionAsMSecs(
rawValue, aPerformance->GetRandomTimelineSeed(),
aPerformance->GetRTPCallerType());
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.