зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1637651 - Assume non-quirks mode for style Link header preloads. r=smaug
This is an issue I found while going through this code and writing/debugging a test for the bug at hand. Without this, the test in the actual fix for this bug will fail to actually reuse the preloaded stylesheet. It seems reasonable to assume that the intersection of quirks mode documents using link preload headers is small (and in that case we'd parse the sheet twice, but oh well). Differential Revision: https://phabricator.services.mozilla.com/D103567
This commit is contained in:
Родитель
6a81495553
Коммит
fe36177806
|
@ -11918,19 +11918,18 @@ NS_IMPL_ISUPPORTS(StubCSSLoaderObserver, nsICSSLoaderObserver)
|
|||
SheetPreloadStatus Document::PreloadStyle(
|
||||
nsIURI* uri, const Encoding* aEncoding, const nsAString& aCrossOriginAttr,
|
||||
const enum ReferrerPolicy aReferrerPolicy, const nsAString& aIntegrity,
|
||||
bool aIsLinkPreload) {
|
||||
css::StylePreloadKind aKind) {
|
||||
MOZ_ASSERT(aKind != css::StylePreloadKind::None);
|
||||
|
||||
// The CSSLoader will retain this object after we return.
|
||||
nsCOMPtr<nsICSSLoaderObserver> obs = new StubCSSLoaderObserver();
|
||||
|
||||
nsCOMPtr<nsIReferrerInfo> referrerInfo =
|
||||
ReferrerInfo::CreateFromDocumentAndPolicyOverride(this, aReferrerPolicy);
|
||||
|
||||
auto preloadType = aIsLinkPreload ? css::Loader::IsPreload::FromLink
|
||||
: css::Loader::IsPreload::FromParser;
|
||||
|
||||
// Charset names are always ASCII.
|
||||
auto result = CSSLoader()->LoadSheet(
|
||||
uri, preloadType, aEncoding, referrerInfo, obs,
|
||||
uri, aKind, aEncoding, referrerInfo, obs,
|
||||
Element::StringToCORSMode(aCrossOriginAttr), aIntegrity);
|
||||
if (result.isErr()) {
|
||||
return SheetPreloadStatus::Errored;
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/UseCounter.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "mozilla/css/StylePreloadKind.h"
|
||||
#include "mozilla/dom/DispatcherTrait.h"
|
||||
#include "mozilla/dom/DocumentOrShadowRoot.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
@ -2951,14 +2952,14 @@ class Document : public nsINode,
|
|||
void ForgetImagePreload(nsIURI* aURI);
|
||||
|
||||
/**
|
||||
* Called by nsParser to preload style sheets. aCrossOriginAttr should be a
|
||||
* void string if the attr is not present.
|
||||
* Called by the parser or the preload service to preload style sheets.
|
||||
* aCrossOriginAttr should be a void string if the attr is not present.
|
||||
*/
|
||||
SheetPreloadStatus PreloadStyle(nsIURI* aURI, const Encoding* aEncoding,
|
||||
const nsAString& aCrossOriginAttr,
|
||||
ReferrerPolicyEnum aReferrerPolicy,
|
||||
const nsAString& aIntegrity,
|
||||
bool aIsLinkPreload);
|
||||
css::StylePreloadKind);
|
||||
|
||||
/**
|
||||
* Called by the chrome registry to load style sheets.
|
||||
|
|
|
@ -144,7 +144,7 @@ SheetLoadDataHashKey::SheetLoadDataHashKey(const css::SheetLoadData& aLoadData)
|
|||
mCORSMode(aLoadData.mSheet->GetCORSMode()),
|
||||
mParsingMode(aLoadData.mSheet->ParsingMode()),
|
||||
mCompatMode(aLoadData.mCompatMode),
|
||||
mIsLinkPreload(aLoadData.IsLinkPreload()) {
|
||||
mIsLinkRelPreload(aLoadData.IsLinkRelPreload()) {
|
||||
MOZ_COUNT_CTOR(SheetLoadDataHashKey);
|
||||
MOZ_ASSERT(mURI);
|
||||
MOZ_ASSERT(mPrincipal);
|
||||
|
@ -209,11 +209,11 @@ bool SheetLoadDataHashKey::KeyEquals(const SheetLoadDataHashKey& aKey) const {
|
|||
// check makes sure that regular loads will never find such a weaker preload
|
||||
// and rather start a new, independent load with new, stronger SRI checker
|
||||
// set up, so that integrity is ensured.
|
||||
if (mIsLinkPreload != aKey.mIsLinkPreload) {
|
||||
if (mIsLinkRelPreload != aKey.mIsLinkRelPreload) {
|
||||
const auto& linkPreloadMetadata =
|
||||
mIsLinkPreload ? mSRIMetadata : aKey.mSRIMetadata;
|
||||
mIsLinkRelPreload ? mSRIMetadata : aKey.mSRIMetadata;
|
||||
const auto& consumerPreloadMetadata =
|
||||
mIsLinkPreload ? aKey.mSRIMetadata : mSRIMetadata;
|
||||
mIsLinkRelPreload ? aKey.mSRIMetadata : mSRIMetadata;
|
||||
|
||||
if (!consumerPreloadMetadata.CanTrustBeDelegatedTo(linkPreloadMetadata)) {
|
||||
LOG((" > Preload SRI metadata mismatch\n"));
|
||||
|
@ -262,7 +262,7 @@ NS_IMPL_ISUPPORTS(SheetLoadData, nsIRunnable, nsIThreadObserver)
|
|||
SheetLoadData::SheetLoadData(Loader* aLoader, const nsAString& aTitle,
|
||||
nsIURI* aURI, StyleSheet* aSheet, bool aSyncLoad,
|
||||
nsINode* aOwningNode, IsAlternate aIsAlternate,
|
||||
MediaMatched aMediaMatches, IsPreload aIsPreload,
|
||||
MediaMatched aMediaMatches, StylePreloadKind aPreloadKind,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
nsIPrincipal* aTriggeringPrincipal,
|
||||
nsIReferrerInfo* aReferrerInfo,
|
||||
|
@ -289,14 +289,14 @@ SheetLoadData::SheetLoadData(Loader* aLoader, const nsAString& aTitle,
|
|||
mIsCrossOriginNoCORS(false),
|
||||
mBlockResourceTiming(false),
|
||||
mLoadFailed(false),
|
||||
mIsPreload(aIsPreload),
|
||||
mPreloadKind(aPreloadKind),
|
||||
mOwningNode(aOwningNode),
|
||||
mObserver(aObserver),
|
||||
mTriggeringPrincipal(aTriggeringPrincipal),
|
||||
mReferrerInfo(aReferrerInfo),
|
||||
mRequestingNode(aRequestingNode),
|
||||
mGuessedEncoding(GetFallbackEncoding(*aLoader, aOwningNode, nullptr)),
|
||||
mCompatMode(aLoader->mCompatMode) {
|
||||
mCompatMode(aLoader->CompatMode(aPreloadKind)) {
|
||||
MOZ_ASSERT(!mOwningNode || dom::LinkStyle::FromNode(*mOwningNode),
|
||||
"Must implement LinkStyle");
|
||||
MOZ_ASSERT(mTriggeringPrincipal);
|
||||
|
@ -331,7 +331,7 @@ SheetLoadData::SheetLoadData(Loader* aLoader, nsIURI* aURI, StyleSheet* aSheet,
|
|||
mIsCrossOriginNoCORS(false),
|
||||
mBlockResourceTiming(false),
|
||||
mLoadFailed(false),
|
||||
mIsPreload(IsPreload::No),
|
||||
mPreloadKind(StylePreloadKind::None),
|
||||
mOwningNode(nullptr),
|
||||
mObserver(aObserver),
|
||||
mTriggeringPrincipal(aTriggeringPrincipal),
|
||||
|
@ -339,7 +339,7 @@ SheetLoadData::SheetLoadData(Loader* aLoader, nsIURI* aURI, StyleSheet* aSheet,
|
|||
mRequestingNode(aRequestingNode),
|
||||
mGuessedEncoding(GetFallbackEncoding(
|
||||
*aLoader, nullptr, aParentData ? aParentData->mEncoding : nullptr)),
|
||||
mCompatMode(aLoader->mCompatMode) {
|
||||
mCompatMode(aLoader->CompatMode(mPreloadKind)) {
|
||||
MOZ_ASSERT(mLoader, "Must have a loader!");
|
||||
MOZ_ASSERT(mTriggeringPrincipal);
|
||||
MOZ_ASSERT(!mUseSystemPrincipal || mSyncLoad,
|
||||
|
@ -349,7 +349,7 @@ SheetLoadData::SheetLoadData(Loader* aLoader, nsIURI* aURI, StyleSheet* aSheet,
|
|||
|
||||
SheetLoadData::SheetLoadData(
|
||||
Loader* aLoader, nsIURI* aURI, StyleSheet* aSheet, bool aSyncLoad,
|
||||
UseSystemPrincipal aUseSystemPrincipal, IsPreload aIsPreload,
|
||||
UseSystemPrincipal aUseSystemPrincipal, StylePreloadKind aPreloadKind,
|
||||
const Encoding* aPreloadEncoding, nsICSSLoaderObserver* aObserver,
|
||||
nsIPrincipal* aTriggeringPrincipal, nsIReferrerInfo* aReferrerInfo,
|
||||
nsINode* aRequestingNode)
|
||||
|
@ -374,7 +374,7 @@ SheetLoadData::SheetLoadData(
|
|||
mIsCrossOriginNoCORS(false),
|
||||
mBlockResourceTiming(false),
|
||||
mLoadFailed(false),
|
||||
mIsPreload(aIsPreload),
|
||||
mPreloadKind(aPreloadKind),
|
||||
mOwningNode(nullptr),
|
||||
mObserver(aObserver),
|
||||
mTriggeringPrincipal(aTriggeringPrincipal),
|
||||
|
@ -382,7 +382,7 @@ SheetLoadData::SheetLoadData(
|
|||
mRequestingNode(aRequestingNode),
|
||||
mGuessedEncoding(
|
||||
GetFallbackEncoding(*aLoader, nullptr, aPreloadEncoding)),
|
||||
mCompatMode(aLoader->mCompatMode) {
|
||||
mCompatMode(aLoader->CompatMode(aPreloadKind)) {
|
||||
MOZ_ASSERT(mTriggeringPrincipal);
|
||||
MOZ_ASSERT(mLoader, "Must have a loader!");
|
||||
MOZ_ASSERT(!mUseSystemPrincipal || mSyncLoad,
|
||||
|
@ -501,7 +501,7 @@ bool LoaderReusableStyleSheets::FindReusableStyleSheet(
|
|||
|
||||
Loader::Loader()
|
||||
: mDocument(nullptr),
|
||||
mCompatMode(eCompatibility_FullStandards),
|
||||
mDocumentCompatMode(eCompatibility_FullStandards),
|
||||
mReporter(new ConsoleReportCollector()) {}
|
||||
|
||||
Loader::Loader(DocGroup* aDocGroup) : Loader() { mDocGroup = aDocGroup; }
|
||||
|
@ -509,7 +509,7 @@ Loader::Loader(DocGroup* aDocGroup) : Loader() { mDocGroup = aDocGroup; }
|
|||
Loader::Loader(Document* aDocument) : Loader() {
|
||||
MOZ_ASSERT(aDocument, "We should get a valid document from the caller!");
|
||||
mDocument = aDocument;
|
||||
mCompatMode = aDocument->GetCompatibilityMode();
|
||||
mDocumentCompatMode = aDocument->GetCompatibilityMode();
|
||||
mSheets = SharedStyleSheetCache::Get();
|
||||
RegisterInSheetCache();
|
||||
}
|
||||
|
@ -783,7 +783,7 @@ nsresult SheetLoadData::VerifySheetReadyToParse(nsresult aStatus,
|
|||
sameOrigin = false;
|
||||
}
|
||||
|
||||
if (sameOrigin && mLoader->mCompatMode == eCompatibility_NavQuirks) {
|
||||
if (sameOrigin && mCompatMode == eCompatibility_NavQuirks) {
|
||||
errorMessage = "MimeNotCssWarn";
|
||||
errorFlag = nsIScriptError::warningFlag;
|
||||
} else {
|
||||
|
@ -884,14 +884,14 @@ nsresult Loader::CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
|
|||
nsIURI* aTargetURI,
|
||||
nsINode* aRequestingNode,
|
||||
const nsAString& aNonce,
|
||||
IsPreload aIsPreload) {
|
||||
StylePreloadKind aPreloadKind) {
|
||||
// When performing a system load don't consult content policies.
|
||||
if (!mDocument) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsContentPolicyType contentPolicyType =
|
||||
aIsPreload == IsPreload::No
|
||||
aPreloadKind == StylePreloadKind::None
|
||||
? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET
|
||||
: nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD;
|
||||
|
||||
|
@ -902,7 +902,7 @@ nsresult Loader::CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
|
|||
// snapshot the nonce at load start time for performing CSP checks
|
||||
if (contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET) {
|
||||
secCheckLoadInfo->SetCspNonce(aNonce);
|
||||
MOZ_ASSERT_IF(aIsPreload != IsPreload::No, aNonce.IsEmpty());
|
||||
MOZ_ASSERT_IF(aPreloadKind != StylePreloadKind::None, aNonce.IsEmpty());
|
||||
}
|
||||
|
||||
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
|
@ -948,7 +948,7 @@ std::tuple<RefPtr<StyleSheet>, Loader::SheetState> Loader::CreateSheet(
|
|||
nsIURI* aURI, nsIContent* aLinkingContent,
|
||||
nsIPrincipal* aTriggeringPrincipal, css::SheetParsingMode aParsingMode,
|
||||
CORSMode aCORSMode, const Encoding* aPreloadOrParentDataEncoding,
|
||||
const nsAString& aIntegrity, bool aSyncLoad, IsPreload aIsPreload) {
|
||||
const nsAString& aIntegrity, bool aSyncLoad, StylePreloadKind aPreloadKind) {
|
||||
MOZ_ASSERT(aURI, "This path is not taken for inline stylesheets");
|
||||
LOG(("css::Loader::CreateSheet(%s)", aURI->GetSpecOrDefault().get()));
|
||||
|
||||
|
@ -965,11 +965,12 @@ std::tuple<RefPtr<StyleSheet>, Loader::SheetState> Loader::CreateSheet(
|
|||
}
|
||||
|
||||
if (mSheets) {
|
||||
SheetLoadDataHashKey key(
|
||||
aURI, aTriggeringPrincipal, LoaderPrincipal(), PartitionedPrincipal(),
|
||||
GetFallbackEncoding(*this, aLinkingContent,
|
||||
aPreloadOrParentDataEncoding),
|
||||
aCORSMode, aParsingMode, mCompatMode, sriMetadata, aIsPreload);
|
||||
SheetLoadDataHashKey key(aURI, aTriggeringPrincipal, LoaderPrincipal(),
|
||||
PartitionedPrincipal(),
|
||||
GetFallbackEncoding(*this, aLinkingContent,
|
||||
aPreloadOrParentDataEncoding),
|
||||
aCORSMode, aParsingMode, CompatMode(aPreloadKind),
|
||||
sriMetadata, aPreloadKind);
|
||||
auto cacheResult = mSheets->Lookup(*this, key, aSyncLoad);
|
||||
if (const auto& [styleSheet, sheetState] = cacheResult; styleSheet) {
|
||||
LOG((" Hit cache with state: %s", gStateStrings[size_t(sheetState)]));
|
||||
|
@ -1196,7 +1197,7 @@ nsresult Loader::LoadSheet(SheetLoadData& aLoadData, SheetState aSheetState,
|
|||
nsILoadInfo::SEC_ALLOW_CHROME;
|
||||
|
||||
nsContentPolicyType contentPolicyType =
|
||||
aLoadData.mIsPreload == IsPreload::No
|
||||
aLoadData.mPreloadKind == StylePreloadKind::None
|
||||
? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET
|
||||
: nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD;
|
||||
|
||||
|
@ -1295,8 +1296,7 @@ nsresult Loader::LoadSheet(SheetLoadData& aLoadData, SheetState aSheetState,
|
|||
}
|
||||
}
|
||||
|
||||
aLoadData.NotifyOpen(preloadKey, mDocument,
|
||||
aLoadData.mIsPreload == IsPreload::FromLink);
|
||||
aLoadData.NotifyOpen(preloadKey, mDocument, aLoadData.IsLinkRelPreload());
|
||||
if (coalescedLoad) {
|
||||
// All done here; once the load completes we'll be marked complete
|
||||
// automatically.
|
||||
|
@ -1336,7 +1336,7 @@ nsresult Loader::LoadSheet(SheetLoadData& aLoadData, SheetState aSheetState,
|
|||
securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;
|
||||
|
||||
nsContentPolicyType contentPolicyType =
|
||||
aLoadData.mIsPreload == IsPreload::No
|
||||
aLoadData.mPreloadKind == StylePreloadKind::None
|
||||
? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET
|
||||
: nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD;
|
||||
|
||||
|
@ -1381,7 +1381,7 @@ nsresult Loader::LoadSheet(SheetLoadData& aLoadData, SheetState aSheetState,
|
|||
if (nsCOMPtr<nsIClassOfService> cos = do_QueryInterface(channel)) {
|
||||
cos->AddClassFlags(nsIClassOfService::Leader);
|
||||
}
|
||||
if (aLoadData.mIsPreload == IsPreload::FromLink) {
|
||||
if (aLoadData.IsLinkRelPreload()) {
|
||||
SheetLoadData::PrioritizeAsPreload(channel);
|
||||
SheetLoadData::AddLoadBackgroundFlag(channel);
|
||||
}
|
||||
|
@ -1713,7 +1713,7 @@ Result<Loader::LoadSheetResult, nsresult> Loader::LoadInlineStyle(
|
|||
} else {
|
||||
auto data = MakeRefPtr<SheetLoadData>(
|
||||
this, aInfo.mTitle, nullptr, sheet, false, aInfo.mContent, isAlternate,
|
||||
matched, IsPreload::No, aObserver, principal, aInfo.mReferrerInfo,
|
||||
matched, StylePreloadKind::None, aObserver, principal, aInfo.mReferrerInfo,
|
||||
aInfo.mContent);
|
||||
data->mLineNumber = aLineNumber;
|
||||
|
||||
|
@ -1773,7 +1773,7 @@ Result<Loader::LoadSheetResult, nsresult> Loader::LoadStyleLink(
|
|||
MOZ_ASSERT_IF(syncLoad, !aObserver);
|
||||
|
||||
nsresult rv = CheckContentPolicy(loadingPrincipal, principal, aInfo.mURI,
|
||||
context, aInfo.mNonce, IsPreload::No);
|
||||
context, aInfo.mNonce, StylePreloadKind::None);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
// Don't fire the error event if our document is loaded as data. We're
|
||||
// supposed to not even try to do loads in that case... Unfortunately, we
|
||||
|
@ -1795,7 +1795,7 @@ Result<Loader::LoadSheetResult, nsresult> Loader::LoadStyleLink(
|
|||
// pending sheets go to the non-pending state.
|
||||
auto isAlternate = IsAlternateSheet(aInfo.mTitle, aInfo.mHasAlternateRel);
|
||||
auto [sheet, state] =
|
||||
CreateSheet(aInfo, eAuthorSheetFeatures, syncLoad, IsPreload::No);
|
||||
CreateSheet(aInfo, eAuthorSheetFeatures, syncLoad, StylePreloadKind::None);
|
||||
|
||||
LOG((" Sheet is alternate: %d", static_cast<int>(isAlternate)));
|
||||
|
||||
|
@ -1814,7 +1814,7 @@ Result<Loader::LoadSheetResult, nsresult> Loader::LoadStyleLink(
|
|||
"If there is any node, it should be a LinkStyle");
|
||||
auto data = MakeRefPtr<SheetLoadData>(
|
||||
this, aInfo.mTitle, aInfo.mURI, sheet, syncLoad, aInfo.mContent,
|
||||
isAlternate, matched, IsPreload::No, aObserver, principal,
|
||||
isAlternate, matched, StylePreloadKind::None, aObserver, principal,
|
||||
aInfo.mReferrerInfo, context);
|
||||
|
||||
MaybeNotifyPreloadUsed(*data);
|
||||
|
@ -1920,7 +1920,7 @@ nsresult Loader::LoadChildSheet(StyleSheet& aParentSheet,
|
|||
|
||||
nsIPrincipal* principal = aParentSheet.Principal();
|
||||
nsresult rv = CheckContentPolicy(LoaderPrincipal(), principal, aURL, context,
|
||||
u""_ns, IsPreload::No);
|
||||
u""_ns, StylePreloadKind::None);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
if (aParentData) {
|
||||
MarkLoadTreeFailed(*aParentData);
|
||||
|
@ -1961,7 +1961,7 @@ nsresult Loader::LoadChildSheet(StyleSheet& aParentSheet,
|
|||
CreateSheet(aURL, nullptr, principal, aParentSheet.ParsingMode(),
|
||||
CORS_NONE, aParentData ? aParentData->mEncoding : nullptr,
|
||||
u""_ns, // integrity is only checked on main sheet
|
||||
aParentData && aParentData->mSyncLoad, IsPreload::No);
|
||||
aParentData && aParentData->mSyncLoad, StylePreloadKind::None);
|
||||
PrepareSheet(*sheet, u""_ns, u""_ns, aMedia, IsAlternate::No,
|
||||
IsExplicitlyEnabled::No);
|
||||
}
|
||||
|
@ -2003,7 +2003,7 @@ Result<RefPtr<StyleSheet>, nsresult> Loader::LoadSheetSync(
|
|||
UseSystemPrincipal aUseSystemPrincipal) {
|
||||
LOG(("css::Loader::LoadSheetSync"));
|
||||
nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo(nullptr);
|
||||
return InternalLoadNonDocumentSheet(aURL, IsPreload::No, aParsingMode,
|
||||
return InternalLoadNonDocumentSheet(aURL, StylePreloadKind::None, aParsingMode,
|
||||
aUseSystemPrincipal, nullptr,
|
||||
referrerInfo, nullptr, CORS_NONE, u""_ns);
|
||||
}
|
||||
|
@ -2013,22 +2013,22 @@ Result<RefPtr<StyleSheet>, nsresult> Loader::LoadSheet(
|
|||
UseSystemPrincipal aUseSystemPrincipal, nsICSSLoaderObserver* aObserver) {
|
||||
nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo(nullptr);
|
||||
return InternalLoadNonDocumentSheet(
|
||||
aURI, IsPreload::No, aParsingMode, aUseSystemPrincipal, nullptr,
|
||||
aURI, StylePreloadKind::None, aParsingMode, aUseSystemPrincipal, nullptr,
|
||||
referrerInfo, aObserver, CORS_NONE, u""_ns);
|
||||
}
|
||||
|
||||
Result<RefPtr<StyleSheet>, nsresult> Loader::LoadSheet(
|
||||
nsIURI* aURL, IsPreload aIsPreload, const Encoding* aPreloadEncoding,
|
||||
nsIURI* aURL, StylePreloadKind aPreloadKind, const Encoding* aPreloadEncoding,
|
||||
nsIReferrerInfo* aReferrerInfo, nsICSSLoaderObserver* aObserver,
|
||||
CORSMode aCORSMode, const nsAString& aIntegrity) {
|
||||
LOG(("css::Loader::LoadSheet(aURL, aObserver) api call"));
|
||||
return InternalLoadNonDocumentSheet(
|
||||
aURL, aIsPreload, eAuthorSheetFeatures, UseSystemPrincipal::No,
|
||||
aURL, aPreloadKind, eAuthorSheetFeatures, UseSystemPrincipal::No,
|
||||
aPreloadEncoding, aReferrerInfo, aObserver, aCORSMode, aIntegrity);
|
||||
}
|
||||
|
||||
Result<RefPtr<StyleSheet>, nsresult> Loader::InternalLoadNonDocumentSheet(
|
||||
nsIURI* aURL, IsPreload aIsPreload, SheetParsingMode aParsingMode,
|
||||
nsIURI* aURL, StylePreloadKind aPreloadKind, SheetParsingMode aParsingMode,
|
||||
UseSystemPrincipal aUseSystemPrincipal, const Encoding* aPreloadEncoding,
|
||||
nsIReferrerInfo* aReferrerInfo, nsICSSLoaderObserver* aObserver,
|
||||
CORSMode aCORSMode, const nsAString& aIntegrity) {
|
||||
|
@ -2047,7 +2047,7 @@ Result<RefPtr<StyleSheet>, nsresult> Loader::InternalLoadNonDocumentSheet(
|
|||
nsIPrincipal* loadingPrincipal = LoaderPrincipal();
|
||||
nsIPrincipal* triggeringPrincipal = loadingPrincipal;
|
||||
nsresult rv = CheckContentPolicy(loadingPrincipal, triggeringPrincipal, aURL,
|
||||
mDocument, u""_ns, aIsPreload);
|
||||
mDocument, u""_ns, aPreloadKind);
|
||||
if (NS_FAILED(rv)) {
|
||||
return Err(rv);
|
||||
}
|
||||
|
@ -2055,13 +2055,13 @@ Result<RefPtr<StyleSheet>, nsresult> Loader::InternalLoadNonDocumentSheet(
|
|||
bool syncLoad = !aObserver;
|
||||
auto [sheet, state] =
|
||||
CreateSheet(aURL, nullptr, triggeringPrincipal, aParsingMode, aCORSMode,
|
||||
aPreloadEncoding, aIntegrity, syncLoad, aIsPreload);
|
||||
aPreloadEncoding, aIntegrity, syncLoad, aPreloadKind);
|
||||
|
||||
PrepareSheet(*sheet, u""_ns, u""_ns, nullptr, IsAlternate::No,
|
||||
IsExplicitlyEnabled::No);
|
||||
|
||||
auto data = MakeRefPtr<SheetLoadData>(
|
||||
this, aURL, sheet, syncLoad, aUseSystemPrincipal, aIsPreload,
|
||||
this, aURL, sheet, syncLoad, aUseSystemPrincipal, aPreloadKind,
|
||||
aPreloadEncoding, aObserver, triggeringPrincipal, aReferrerInfo,
|
||||
mDocument);
|
||||
if (state == SheetState::Complete) {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/CORSMode.h"
|
||||
#include "mozilla/css/StylePreloadKind.h"
|
||||
#include "mozilla/dom/LinkStyle.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
@ -47,16 +48,6 @@ class Element;
|
|||
// This must contain all the state that affects CSS parsing.
|
||||
class SheetLoadDataHashKey : public PLDHashEntryHdr {
|
||||
public:
|
||||
enum class IsPreload : uint8_t {
|
||||
No,
|
||||
// This is a speculative load initiated by a <link rel=stylesheet> tag
|
||||
// scanned by the parser, or @import rules found in a <style> tag.
|
||||
FromParser,
|
||||
// This is a speculative load as well, but initiated by
|
||||
// <link rel="preload" as="style">
|
||||
FromLink,
|
||||
};
|
||||
|
||||
using KeyType = const SheetLoadDataHashKey&;
|
||||
using KeyTypePointer = const SheetLoadDataHashKey*;
|
||||
|
||||
|
@ -70,7 +61,7 @@ class SheetLoadDataHashKey : public PLDHashEntryHdr {
|
|||
mParsingMode(aKey->mParsingMode),
|
||||
mCompatMode(aKey->mCompatMode),
|
||||
mSRIMetadata(aKey->mSRIMetadata),
|
||||
mIsLinkPreload(aKey->mIsLinkPreload) {
|
||||
mIsLinkRelPreload(aKey->mIsLinkRelPreload) {
|
||||
MOZ_COUNT_CTOR(SheetLoadDataHashKey);
|
||||
}
|
||||
|
||||
|
@ -81,7 +72,7 @@ class SheetLoadDataHashKey : public PLDHashEntryHdr {
|
|||
CORSMode aCORSMode, css::SheetParsingMode aParsingMode,
|
||||
nsCompatibility aCompatMode,
|
||||
const dom::SRIMetadata& aSRIMetadata,
|
||||
IsPreload aIsPreload)
|
||||
css::StylePreloadKind aPreloadKind)
|
||||
: mURI(aURI),
|
||||
mPrincipal(aPrincipal),
|
||||
mLoaderPrincipal(aLoaderPrincipal),
|
||||
|
@ -91,7 +82,7 @@ class SheetLoadDataHashKey : public PLDHashEntryHdr {
|
|||
mParsingMode(aParsingMode),
|
||||
mCompatMode(aCompatMode),
|
||||
mSRIMetadata(aSRIMetadata),
|
||||
mIsLinkPreload(aIsPreload == IsPreload::FromLink) {
|
||||
mIsLinkRelPreload(IsLinkRelPreload(aPreloadKind)) {
|
||||
MOZ_ASSERT(aURI);
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
MOZ_ASSERT(aLoaderPrincipal);
|
||||
|
@ -108,7 +99,7 @@ class SheetLoadDataHashKey : public PLDHashEntryHdr {
|
|||
mParsingMode(std::move(toMove.mParsingMode)),
|
||||
mCompatMode(std::move(toMove.mCompatMode)),
|
||||
mSRIMetadata(std::move(toMove.mSRIMetadata)),
|
||||
mIsLinkPreload(std::move(toMove.mIsLinkPreload)) {
|
||||
mIsLinkRelPreload(std::move(toMove.mIsLinkRelPreload)) {
|
||||
MOZ_COUNT_CTOR(SheetLoadDataHashKey);
|
||||
}
|
||||
|
||||
|
@ -156,7 +147,7 @@ class SheetLoadDataHashKey : public PLDHashEntryHdr {
|
|||
const css::SheetParsingMode mParsingMode;
|
||||
const nsCompatibility mCompatMode;
|
||||
dom::SRIMetadata mSRIMetadata;
|
||||
const bool mIsLinkPreload;
|
||||
const bool mIsLinkRelPreload;
|
||||
};
|
||||
|
||||
namespace css {
|
||||
|
@ -237,9 +228,22 @@ class Loader final {
|
|||
void RegisterInSheetCache();
|
||||
|
||||
void SetCompatibilityMode(nsCompatibility aCompatMode) {
|
||||
mCompatMode = aCompatMode;
|
||||
mDocumentCompatMode = aCompatMode;
|
||||
}
|
||||
|
||||
using StylePreloadKind = css::StylePreloadKind;
|
||||
|
||||
nsCompatibility CompatMode(StylePreloadKind aPreloadKind) const {
|
||||
// For Link header preload, we guess non-quirks, because otherwise it is
|
||||
// useless for modern pages.
|
||||
//
|
||||
// Link element preload is generally good because the speculative html
|
||||
// parser deals with quirks mode properly.
|
||||
if (aPreloadKind == StylePreloadKind::FromLinkRelPreloadHeader) {
|
||||
return eCompatibility_FullStandards;
|
||||
}
|
||||
return mDocumentCompatMode;
|
||||
}
|
||||
nsCompatibility GetCompatibilityMode() { return mCompatMode; }
|
||||
|
||||
// TODO(emilio): Is the complexity of this method and carrying the titles
|
||||
// around worth it? The alternate sheets will load anyhow eventually...
|
||||
|
@ -332,8 +336,6 @@ class Loader final {
|
|||
nsIURI*, SheetParsingMode = eAuthorSheetFeatures,
|
||||
UseSystemPrincipal = UseSystemPrincipal::No);
|
||||
|
||||
using IsPreload = SheetLoadDataHashKey::IsPreload;
|
||||
|
||||
/**
|
||||
* Asynchronously load the stylesheet at aURL. If a successful result is
|
||||
* returned, aObserver is guaranteed to be notified asynchronously once the
|
||||
|
@ -356,7 +358,7 @@ class Loader final {
|
|||
* non-UTF8 sheets being treated as UTF-8 by this method.
|
||||
*/
|
||||
Result<RefPtr<StyleSheet>, nsresult> LoadSheet(
|
||||
nsIURI* aURI, IsPreload, const Encoding* aPreloadEncoding,
|
||||
nsIURI* aURI, StylePreloadKind, const Encoding* aPreloadEncoding,
|
||||
nsIReferrerInfo* aReferrerInfo, nsICSSLoaderObserver* aObserver,
|
||||
CORSMode = CORS_NONE, const nsAString& aIntegrity = u""_ns);
|
||||
|
||||
|
@ -483,18 +485,18 @@ class Loader final {
|
|||
nsresult CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
|
||||
nsIPrincipal* aTriggeringPrincipal,
|
||||
nsIURI* aTargetURI, nsINode* aRequestingNode,
|
||||
const nsAString& aNonce, IsPreload);
|
||||
const nsAString& aNonce, StylePreloadKind);
|
||||
|
||||
std::tuple<RefPtr<StyleSheet>, SheetState> CreateSheet(
|
||||
const SheetInfo& aInfo, css::SheetParsingMode aParsingMode,
|
||||
bool aSyncLoad, IsPreload aIsPreload) {
|
||||
bool aSyncLoad, css::StylePreloadKind aPreloadKind) {
|
||||
nsIPrincipal* triggeringPrincipal = aInfo.mTriggeringPrincipal
|
||||
? aInfo.mTriggeringPrincipal.get()
|
||||
: LoaderPrincipal();
|
||||
return CreateSheet(aInfo.mURI, aInfo.mContent, triggeringPrincipal,
|
||||
aParsingMode, aInfo.mCORSMode,
|
||||
/* aPreloadOrParentDataEncoding = */ nullptr,
|
||||
aInfo.mIntegrity, aSyncLoad, aIsPreload);
|
||||
aInfo.mIntegrity, aSyncLoad, aPreloadKind);
|
||||
}
|
||||
|
||||
// For inline style, the aURI param is null, but the aLinkingContent
|
||||
|
@ -504,7 +506,7 @@ class Loader final {
|
|||
nsIURI* aURI, nsIContent* aLinkingContent,
|
||||
nsIPrincipal* aTriggeringPrincipal, css::SheetParsingMode, CORSMode,
|
||||
const Encoding* aPreloadOrParentDataEncoding, const nsAString& aIntegrity,
|
||||
bool aSyncLoad, IsPreload aIsPreload);
|
||||
bool aSyncLoad, StylePreloadKind);
|
||||
|
||||
// Pass in either a media string or the MediaList from the CSSParser. Don't
|
||||
// pass both.
|
||||
|
@ -520,7 +522,7 @@ class Loader final {
|
|||
void InsertChildSheet(StyleSheet& aSheet, StyleSheet& aParentSheet);
|
||||
|
||||
Result<RefPtr<StyleSheet>, nsresult> InternalLoadNonDocumentSheet(
|
||||
nsIURI* aURL, IsPreload, SheetParsingMode aParsingMode,
|
||||
nsIURI* aURL, StylePreloadKind, SheetParsingMode aParsingMode,
|
||||
UseSystemPrincipal, const Encoding* aPreloadEncoding,
|
||||
nsIReferrerInfo* aReferrerInfo, nsICSSLoaderObserver* aObserver,
|
||||
CORSMode aCORSMode, const nsAString& aIntegrity);
|
||||
|
@ -601,7 +603,7 @@ class Loader final {
|
|||
// For dispatching events via DocGroup::Dispatch() when mDocument is nullptr.
|
||||
RefPtr<dom::DocGroup> mDocGroup;
|
||||
|
||||
nsCompatibility mCompatMode;
|
||||
nsCompatibility mDocumentCompatMode;
|
||||
|
||||
nsCOMPtr<nsIConsoleReportCollector> mReporter;
|
||||
|
||||
|
|
|
@ -346,7 +346,7 @@ void SharedStyleSheetCache::LoadCompletedInternal(
|
|||
// Not a document load, nothing to do.
|
||||
return false;
|
||||
}
|
||||
if (data->mIsPreload != css::Loader::IsPreload::No) {
|
||||
if (data->IsPreload()) {
|
||||
// Preloads are not supposed to be observable.
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -26,8 +26,7 @@ class nsIURI;
|
|||
class nsIReferrerInfo;
|
||||
struct StyleUseCounters;
|
||||
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
namespace mozilla::css {
|
||||
|
||||
/*********************************************
|
||||
* Data needed to properly load a stylesheet *
|
||||
|
@ -43,7 +42,6 @@ class SheetLoadData final : public PreloaderBase,
|
|||
public nsIThreadObserver {
|
||||
using MediaMatched = dom::LinkStyle::MediaMatched;
|
||||
using IsAlternate = dom::LinkStyle::IsAlternate;
|
||||
using IsPreload = Loader::IsPreload;
|
||||
using UseSystemPrincipal = Loader::UseSystemPrincipal;
|
||||
|
||||
protected:
|
||||
|
@ -58,7 +56,7 @@ class SheetLoadData final : public PreloaderBase,
|
|||
SheetLoadData(Loader* aLoader, const nsAString& aTitle, nsIURI* aURI,
|
||||
StyleSheet* aSheet, bool aSyncLoad, nsINode* aOwningNode,
|
||||
IsAlternate aIsAlternate, MediaMatched aMediaMatched,
|
||||
IsPreload aIsPreload, nsICSSLoaderObserver* aObserver,
|
||||
StylePreloadKind aPreloadKind, nsICSSLoaderObserver* aObserver,
|
||||
nsIPrincipal* aTriggeringPrincipal,
|
||||
nsIReferrerInfo* aReferrerInfo, nsINode* aRequestingNode);
|
||||
|
||||
|
@ -70,7 +68,7 @@ class SheetLoadData final : public PreloaderBase,
|
|||
|
||||
// Data for loading a non-document sheet
|
||||
SheetLoadData(Loader* aLoader, nsIURI* aURI, StyleSheet* aSheet,
|
||||
bool aSyncLoad, UseSystemPrincipal, IsPreload,
|
||||
bool aSyncLoad, UseSystemPrincipal, StylePreloadKind,
|
||||
const Encoding* aPreloadEncoding,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
nsIPrincipal* aTriggeringPrincipal,
|
||||
|
@ -201,7 +199,7 @@ class SheetLoadData final : public PreloaderBase,
|
|||
// TODO(emilio): This can become a bitfield once we build with a GCC version
|
||||
// that has the fix for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414,
|
||||
// which causes a false positive warning here.
|
||||
const IsPreload mIsPreload;
|
||||
const StylePreloadKind mPreloadKind;
|
||||
|
||||
// This is the node that imported the sheet. Needed to get the charset set on
|
||||
// it, and to fire load/error events. Must implement LinkStyle.
|
||||
|
@ -250,9 +248,10 @@ class SheetLoadData final : public PreloaderBase,
|
|||
}
|
||||
}
|
||||
|
||||
bool IsLinkPreload() const { return mIsPreload == IsPreload::FromLink; }
|
||||
bool IsPreload() const { return mPreloadKind != StylePreloadKind::None; }
|
||||
bool IsLinkRelPreload() const { return css::IsLinkRelPreload(mPreloadKind); }
|
||||
|
||||
bool BlocksLoadEvent() const { return !RootLoadData().IsLinkPreload(); }
|
||||
bool BlocksLoadEvent() const { return !RootLoadData().IsLinkRelPreload(); }
|
||||
|
||||
private:
|
||||
const SheetLoadData& RootLoadData() const {
|
||||
|
@ -268,8 +267,7 @@ class SheetLoadData final : public PreloaderBase,
|
|||
|
||||
using SheetLoadDataHolder = nsMainThreadPtrHolder<SheetLoadData>;
|
||||
|
||||
} // namespace css
|
||||
} // namespace mozilla
|
||||
} // namespace mozilla::css
|
||||
|
||||
/**
|
||||
* Casting SheetLoadData to nsISupports is ambiguous.
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_css_StylePreloadKind_h
|
||||
#define mozilla_css_StylePreloadKind_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace mozilla::css {
|
||||
|
||||
enum class StylePreloadKind : uint8_t {
|
||||
// Not a preload.
|
||||
None,
|
||||
// An speculative load from the parser for a <link rel="stylesheet"> or
|
||||
// @import stylesheet.
|
||||
FromParser,
|
||||
// A preload (speculative or not) for a <link rel="preload" as="style">
|
||||
// element.
|
||||
FromLinkRelPreloadElement,
|
||||
// A preload for a "Link" rel=preload response header.
|
||||
FromLinkRelPreloadHeader,
|
||||
};
|
||||
|
||||
inline bool IsLinkRelPreload(StylePreloadKind aKind) {
|
||||
return aKind == StylePreloadKind::FromLinkRelPreloadElement ||
|
||||
aKind == StylePreloadKind::FromLinkRelPreloadHeader;
|
||||
}
|
||||
|
||||
} // namespace mozilla::css
|
||||
|
||||
#endif // mozilla_css_StylePreloadKind_h
|
|
@ -706,7 +706,7 @@ already_AddRefed<dom::Promise> StyleSheet::Replace(const nsACString& aText,
|
|||
auto* loader = mConstructorDocument->CSSLoader();
|
||||
auto loadData = MakeRefPtr<css::SheetLoadData>(
|
||||
loader, nullptr, this, /* aSyncLoad */ false,
|
||||
css::Loader::UseSystemPrincipal::No, css::Loader::IsPreload::No,
|
||||
css::Loader::UseSystemPrincipal::No, css::StylePreloadKind::None,
|
||||
/* aPreloadEncoding */ nullptr,
|
||||
/* aObserver */ nullptr, mConstructorDocument->NodePrincipal(),
|
||||
GetReferrerInfo(),
|
||||
|
@ -1216,8 +1216,15 @@ void StyleSheet::ParseSheetSync(
|
|||
css::Loader* aLoader, const nsACString& aBytes,
|
||||
css::SheetLoadData* aLoadData, uint32_t aLineNumber,
|
||||
css::LoaderReusableStyleSheets* aReusableSheets) {
|
||||
nsCompatibility compatMode =
|
||||
aLoader ? aLoader->GetCompatibilityMode() : eCompatibility_FullStandards;
|
||||
const nsCompatibility compatMode = [&] {
|
||||
if (aLoadData) {
|
||||
return aLoadData->mCompatMode;
|
||||
}
|
||||
if (aLoader) {
|
||||
return aLoader->CompatMode(css::StylePreloadKind::None);
|
||||
}
|
||||
return eCompatibility_FullStandards;
|
||||
}();
|
||||
|
||||
const StyleUseCounters* useCounters =
|
||||
aLoader && aLoader->GetDocument()
|
||||
|
|
|
@ -153,6 +153,7 @@ EXPORTS.mozilla.css += [
|
|||
"SheetLoadData.h",
|
||||
"SheetParsingMode.h",
|
||||
"StreamLoader.h",
|
||||
"StylePreloadKind.h",
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
|
|
|
@ -1141,7 +1141,9 @@ void nsHtml5TreeOpExecutor::PreloadStyle(const nsAString& aURL,
|
|||
|
||||
mDocument->PreloadStyle(uri, Encoding::ForLabel(aCharset), aCrossOrigin,
|
||||
GetPreloadReferrerPolicy(aReferrerPolicy), aIntegrity,
|
||||
aLinkPreload);
|
||||
aLinkPreload
|
||||
? css::StylePreloadKind::FromLinkRelPreloadElement
|
||||
: css::StylePreloadKind::FromParser);
|
||||
}
|
||||
|
||||
void nsHtml5TreeOpExecutor::PreloadImage(
|
||||
|
|
|
@ -93,9 +93,9 @@ already_AddRefed<PreloaderBase> PreloadService::PreloadLinkElement(
|
|||
aLinkElement->GetReferrerPolicy(referrerPolicy);
|
||||
aLinkElement->GetType(type);
|
||||
|
||||
auto result =
|
||||
PreloadOrCoalesce(uri, url, aPolicyType, as, type, charset, srcset, sizes,
|
||||
integrity, crossOrigin, referrerPolicy);
|
||||
auto result = PreloadOrCoalesce(uri, url, aPolicyType, as, type, charset,
|
||||
srcset, sizes, integrity, crossOrigin,
|
||||
referrerPolicy, /* aFromHeader = */ false);
|
||||
|
||||
if (!result.mPreloader) {
|
||||
NotifyNodeEvent(aLinkElement, result.mAlreadyComplete);
|
||||
|
@ -129,7 +129,8 @@ void PreloadService::PreloadLinkHeader(
|
|||
}
|
||||
|
||||
PreloadOrCoalesce(aURI, aURL, aPolicyType, aAs, aType, u""_ns, aSrcset,
|
||||
aSizes, aIntegrity, aCORS, aReferrerPolicy);
|
||||
aSizes, aIntegrity, aCORS, aReferrerPolicy,
|
||||
/* aFromHeader = */ true);
|
||||
}
|
||||
|
||||
PreloadService::PreloadOrCoalesceResult PreloadService::PreloadOrCoalesce(
|
||||
|
@ -137,7 +138,7 @@ PreloadService::PreloadOrCoalesceResult PreloadService::PreloadOrCoalesce(
|
|||
const nsAString& aAs, const nsAString& aType, const nsAString& aCharset,
|
||||
const nsAString& aSrcset, const nsAString& aSizes,
|
||||
const nsAString& aIntegrity, const nsAString& aCORS,
|
||||
const nsAString& aReferrerPolicy) {
|
||||
const nsAString& aReferrerPolicy, bool aFromHeader) {
|
||||
if (!aURI) {
|
||||
MOZ_ASSERT_UNREACHABLE("Should not pass null nsIURI");
|
||||
return {nullptr, false};
|
||||
|
@ -182,7 +183,9 @@ PreloadService::PreloadOrCoalesceResult PreloadService::PreloadOrCoalesce(
|
|||
} else if (aAs.LowerCaseEqualsASCII("style")) {
|
||||
auto status = mDocument->PreloadStyle(
|
||||
aURI, Encoding::ForLabel(aCharset), aCORS,
|
||||
PreloadReferrerPolicy(aReferrerPolicy), aIntegrity, true);
|
||||
PreloadReferrerPolicy(aReferrerPolicy), aIntegrity,
|
||||
aFromHeader ? css::StylePreloadKind::FromLinkRelPreloadHeader
|
||||
: css::StylePreloadKind::FromLinkRelPreloadElement);
|
||||
switch (status) {
|
||||
case dom::SheetPreloadStatus::AlreadyComplete:
|
||||
return {nullptr, /* already_complete = */ true};
|
||||
|
|
|
@ -103,7 +103,8 @@ class PreloadService {
|
|||
const nsAString& aAs, const nsAString& aType, const nsAString& aCharset,
|
||||
const nsAString& aSrcset, const nsAString& aSizes,
|
||||
const nsAString& aIntegrity, const nsAString& aCORS,
|
||||
const nsAString& aReferrerPolicy);
|
||||
const nsAString& aReferrerPolicy,
|
||||
bool aFromHeader);
|
||||
|
||||
private:
|
||||
nsRefPtrHashtable<PreloadHashKey, PreloaderBase> mPreloads;
|
||||
|
|
Загрузка…
Ссылка в новой задаче