зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1599160 - Add a performance resource entry when hitting the cache for the first time in a document. r=mayhemer,valentin
This matches other browsers, our current behavior, and the test expectations from various WPTs. Differential Revision: https://phabricator.services.mozilla.com/D77842
This commit is contained in:
Родитель
208b60eed2
Коммит
d999791a43
|
@ -147,15 +147,18 @@ void PerformanceMainThread::AddEntry(nsIHttpChannel* channel,
|
|||
if (!performanceTimingData) {
|
||||
return;
|
||||
}
|
||||
AddRawEntry(std::move(performanceTimingData), initiatorType, entryName);
|
||||
}
|
||||
|
||||
void PerformanceMainThread::AddRawEntry(UniquePtr<PerformanceTimingData> aData,
|
||||
const nsAString& aInitiatorType,
|
||||
const nsAString& aEntryName) {
|
||||
// The PerformanceResourceTiming object will use the PerformanceTimingData
|
||||
// object to get all the required timings.
|
||||
RefPtr<PerformanceResourceTiming> performanceEntry =
|
||||
new PerformanceResourceTiming(std::move(performanceTimingData), this,
|
||||
entryName);
|
||||
|
||||
performanceEntry->SetInitiatorType(initiatorType);
|
||||
InsertResourceEntry(performanceEntry);
|
||||
auto entry =
|
||||
MakeRefPtr<PerformanceResourceTiming>(std::move(aData), this, aEntryName);
|
||||
entry->SetInitiatorType(aInitiatorType);
|
||||
InsertResourceEntry(entry);
|
||||
}
|
||||
|
||||
// To be removed once bug 1124165 lands
|
||||
|
|
|
@ -35,6 +35,10 @@ class PerformanceMainThread final : public Performance,
|
|||
virtual void AddEntry(nsIHttpChannel* channel,
|
||||
nsITimedChannel* timedChannel) override;
|
||||
|
||||
void AddRawEntry(UniquePtr<PerformanceTimingData>,
|
||||
const nsAString& aInitiatorType,
|
||||
const nsAString& aEntryName);
|
||||
|
||||
TimeStamp CreationTimeStamp() const override;
|
||||
|
||||
DOMHighResTimeStamp CreationTime() const override;
|
||||
|
|
|
@ -205,6 +205,14 @@ PerformanceTimingData::PerformanceTimingData(nsITimedChannel* aChannel,
|
|||
}
|
||||
}
|
||||
|
||||
void PerformanceTimingData::InitializeForMemoryCacheHit() {
|
||||
auto now = TimeStamp::Now();
|
||||
mInitialized = true;
|
||||
mAsyncOpen = mRequestStart = mResponseStart = mResponseEnd =
|
||||
mDomainLookupStart = mDomainLookupEnd = mConnectStart = mConnectEnd =
|
||||
mCacheReadStart = mCacheReadEnd = now;
|
||||
}
|
||||
|
||||
void PerformanceTimingData::SetPropertiesFromHttpChannel(
|
||||
nsIHttpChannel* aHttpChannel, nsITimedChannel* aChannel) {
|
||||
MOZ_ASSERT(aHttpChannel);
|
||||
|
|
|
@ -112,6 +112,18 @@ class PerformanceTimingData final {
|
|||
return duration.ToMilliseconds() + mZeroTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the timestamps to represent a synchronous cache hit in an
|
||||
* in-memory cache.
|
||||
*
|
||||
* This is used right now for the shared stylesheet cache, which doesn't
|
||||
* always go through necko and thus there isn't an HTTP channel, etc.
|
||||
*
|
||||
* We fill the values with the current timestamp to represent an "instant"
|
||||
* resource fetch.
|
||||
*/
|
||||
void InitializeForMemoryCacheHit();
|
||||
|
||||
// The last channel's AsyncOpen time. This may occur before the FetchStart
|
||||
// in some cases.
|
||||
DOMHighResTimeStamp AsyncOpenHighRes(Performance* aPerformance);
|
||||
|
|
|
@ -10,6 +10,7 @@ with Files("**"):
|
|||
EXPORTS.mozilla.dom += [
|
||||
'Performance.h',
|
||||
'PerformanceEntry.h',
|
||||
'PerformanceMainThread.h',
|
||||
'PerformanceMark.h',
|
||||
'PerformanceMeasure.h',
|
||||
'PerformanceNavigation.h',
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include "nsIContent.h"
|
||||
#include "nsIContentInlines.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/PerformanceTiming.h"
|
||||
#include "mozilla/dom/PerformanceMainThread.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
@ -263,10 +265,6 @@ SheetLoadData::SheetLoadData(Loader* aLoader, nsIURI* aURI, StyleSheet* aSheet,
|
|||
mCompatMode(aLoader->mCompatMode) {
|
||||
MOZ_ASSERT(mLoader, "Must have a loader!");
|
||||
MOZ_ASSERT(mTriggeringPrincipal);
|
||||
if (mParentData) {
|
||||
++mParentData->mPendingChildren;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mUseSystemPrincipal || mSyncLoad,
|
||||
"Shouldn't use system principal for async loads");
|
||||
}
|
||||
|
@ -648,18 +646,14 @@ nsresult SheetLoadData::VerifySheetReadyToParse(nsresult aStatus,
|
|||
|
||||
mSheet->SetPrincipal(principal);
|
||||
|
||||
if (mSheet->GetCORSMode() == CORS_NONE) {
|
||||
bool subsumed;
|
||||
result = mTriggeringPrincipal->Subsumes(principal, &subsumed);
|
||||
if (NS_FAILED(result) || !subsumed) {
|
||||
mIsCrossOriginNoCORS = true;
|
||||
}
|
||||
if (mSheet->GetCORSMode() == CORS_NONE &&
|
||||
!mTriggeringPrincipal->Subsumes(principal)) {
|
||||
mIsCrossOriginNoCORS = true;
|
||||
}
|
||||
|
||||
// If it's an HTTP channel, we want to make sure this is not an
|
||||
// error document we got.
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
|
||||
if (httpChannel) {
|
||||
if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel)) {
|
||||
bool requestSucceeded;
|
||||
result = httpChannel->GetRequestSucceeded(&requestSucceeded);
|
||||
if (NS_SUCCEEDED(result) && !requestSucceeded) {
|
||||
|
@ -829,6 +823,48 @@ nsresult Loader::CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void Loader::MaybeNotifyOfResourceTiming(SheetLoadData& aData) {
|
||||
SheetLoadDataHashKey key(aData);
|
||||
if (!mLoadsPerformed.EnsureInserted(key)) {
|
||||
// We've already reported this subresource load.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mDocument) {
|
||||
// No document means no performance object to report to.
|
||||
return;
|
||||
}
|
||||
|
||||
nsPIDOMWindowInner* win = mDocument->GetInnerWindow();
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* perf = static_cast<dom::PerformanceMainThread*>(win->GetPerformance());
|
||||
if (!perf) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If any ancestor is cross-origin, then we don't report it, see
|
||||
// mIsCrossOriginNoCORS and so.
|
||||
for (auto* parent = aData.mSheet->GetParentSheet(); parent;
|
||||
parent = parent->GetParentSheet()) {
|
||||
if (parent->GetCORSMode() == CORS_NONE &&
|
||||
!aData.mTriggeringPrincipal->Subsumes(parent->Principal())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nsLiteralString initiatorType = aData.mSheet->GetParentSheet()
|
||||
? NS_LITERAL_STRING("css")
|
||||
: NS_LITERAL_STRING("link");
|
||||
nsAutoCString entryName;
|
||||
aData.mSheet->GetOriginalURI()->GetSpec(entryName);
|
||||
auto data = MakeUnique<dom::PerformanceTimingData>(nullptr, nullptr, 0);
|
||||
data->InitializeForMemoryCacheHit();
|
||||
perf->AddRawEntry(std::move(data), initiatorType,
|
||||
NS_ConvertUTF8toUTF16(entryName));
|
||||
}
|
||||
/**
|
||||
* CreateSheet() creates a StyleSheet object for the given URI.
|
||||
*
|
||||
|
@ -1048,6 +1084,9 @@ nsresult Loader::LoadSheet(SheetLoadData& aLoadData, SheetState aSheetState) {
|
|||
LOG_URI(" Load from: '%s'", aLoadData.mURI);
|
||||
|
||||
++mOngoingLoadCount;
|
||||
if (aLoadData.mParentData) {
|
||||
++aLoadData.mParentData->mPendingChildren;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
@ -1306,6 +1345,8 @@ nsresult Loader::LoadSheet(SheetLoadData& aLoadData, SheetState aSheetState) {
|
|||
// sub-resource and so we set the flag on ourself too to propagate it
|
||||
// on down.
|
||||
//
|
||||
// If you add more conditions here make sure to add them to
|
||||
// MaybeNotifyResourceTiming too.
|
||||
if (aLoadData.mParentData->mIsCrossOriginNoCORS ||
|
||||
aLoadData.mParentData->mBlockResourceTiming) {
|
||||
// Set a flag so any other stylesheet triggered by this one will
|
||||
|
@ -1684,6 +1725,7 @@ Result<Loader::LoadSheetResult, nsresult> Loader::LoadStyleLink(
|
|||
aInfo.mReferrerInfo, context);
|
||||
if (state == SheetState::Complete) {
|
||||
LOG((" Sheet already complete: 0x%p", sheet.get()));
|
||||
MaybeNotifyOfResourceTiming(*data);
|
||||
if (aObserver || !mObservers.IsEmpty() || aInfo.mContent) {
|
||||
rv = PostLoadEvent(std::move(data));
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -1833,18 +1875,22 @@ nsresult Loader::LoadChildSheet(StyleSheet& aParentSheet,
|
|||
MOZ_ASSERT(sheet);
|
||||
InsertChildSheet(*sheet, aParentSheet);
|
||||
|
||||
if (state == SheetState::Complete) {
|
||||
LOG((" Sheet already complete"));
|
||||
// We're completely done. No need to notify, even, since the
|
||||
// @import rule addition/modification will trigger the right style
|
||||
// changes automatically.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
auto data = MakeRefPtr<SheetLoadData>(
|
||||
this, aURL, sheet, aParentData, observer, principal,
|
||||
aParentSheet.GetReferrerInfo(), context);
|
||||
|
||||
if (state == SheetState::Complete) {
|
||||
LOG((" Sheet already complete"));
|
||||
MaybeNotifyOfResourceTiming(*data);
|
||||
// We're completely done. No need to notify, even, since the
|
||||
// @import rule addition/modification will trigger the right style
|
||||
// changes automatically.
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
data->mIntentionallyDropped = true;
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool syncLoad = data->mSyncLoad;
|
||||
|
||||
// Load completion will release the data
|
||||
|
@ -1925,6 +1971,7 @@ Result<RefPtr<StyleSheet>, nsresult> Loader::InternalLoadNonDocumentSheet(
|
|||
mDocument);
|
||||
if (state == SheetState::Complete) {
|
||||
LOG((" Sheet already complete"));
|
||||
MaybeNotifyOfResourceTiming(*data);
|
||||
if (aObserver || !mObservers.IsEmpty()) {
|
||||
rv = PostLoadEvent(std::move(data));
|
||||
if (NS_FAILED(rv)) {
|
||||
|
|
|
@ -358,6 +358,11 @@ class Loader final {
|
|||
nsIURI* aURL, dom::MediaList* aMedia,
|
||||
LoaderReusableStyleSheets* aSavedSheets);
|
||||
|
||||
// If we hit the shared cache and this is the first load for a given resource,
|
||||
// we still post a resource timing entry, because tests expect this, and other
|
||||
// browsers behave like this too.
|
||||
void MaybeNotifyOfResourceTiming(SheetLoadData&);
|
||||
|
||||
enum class UseSystemPrincipal { No, Yes };
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче