Bug 2070130 - Check final URI in CSS loader mime type quirk. r=dshin

This fixes the Firefox failures in web-platform-tests/wpt#62516.

Implement it behind a pref just-in case. Also, unfortunately we need to
do the same-origin check up-front, because the mime type check can
happen off the main thread.

Pull request: https://github.com/mozilla-firefox/firefox/pull/364
This commit is contained in:
Emilio Cobos Álvarez
2026-09-10 15:30:14 +00:00
committed by ealvarez@mozilla.com
parent 75438996a6
commit 6d5a2bbbcc
6 changed files with 49 additions and 40 deletions
+29 -22
View File
@@ -278,6 +278,9 @@ SheetLoadData::SheetLoadData(
mSheetAlreadyComplete(false),
mLoadFailed(false),
mShouldEmulateNotificationsForCachedLoad(false),
mRecordErrors(
aLoader->GetDocument() &&
css::ErrorReporter::ShouldReportErrors(*aLoader->GetDocument())),
mPreloadKind(aPreloadKind),
mObserver(aObserver),
mTriggeringPrincipal(aTriggeringPrincipal),
@@ -286,9 +289,6 @@ SheetLoadData::SheetLoadData(
mFetchPriority{aFetchPriority},
mGuessedEncoding(GetFallbackEncoding(*aLoader, aOwningNode, nullptr)),
mCompatMode(aLoader->CompatMode(aPreloadKind)),
mRecordErrors(
aLoader && aLoader->GetDocument() &&
css::ErrorReporter::ShouldReportErrors(*aLoader->GetDocument())),
mNetworkMetadata(std::move(aNetworkMetadata)) {
MOZ_ASSERT(!aOwningNode || dom::LinkStyle::FromNode(*aOwningNode),
"Must implement LinkStyle");
@@ -321,6 +321,9 @@ SheetLoadData::SheetLoadData(
mSheetAlreadyComplete(false),
mLoadFailed(false),
mShouldEmulateNotificationsForCachedLoad(false),
mRecordErrors(
aLoader->GetDocument() &&
css::ErrorReporter::ShouldReportErrors(*aLoader->GetDocument())),
mPreloadKind(StylePreloadKind::None),
mObserver(aObserver),
mTriggeringPrincipal(aTriggeringPrincipal),
@@ -330,9 +333,6 @@ SheetLoadData::SheetLoadData(
mGuessedEncoding(GetFallbackEncoding(
*aLoader, nullptr, aParentData ? aParentData->mEncoding : nullptr)),
mCompatMode(aLoader->CompatMode(mPreloadKind)),
mRecordErrors(
aLoader && aLoader->GetDocument() &&
css::ErrorReporter::ShouldReportErrors(*aLoader->GetDocument())),
mNetworkMetadata(std::move(aNetworkMetadata)) {
MOZ_ASSERT(mLoader, "Must have a loader!");
MOZ_ASSERT(mTriggeringPrincipal);
@@ -367,6 +367,9 @@ SheetLoadData::SheetLoadData(
mSheetAlreadyComplete(false),
mLoadFailed(false),
mShouldEmulateNotificationsForCachedLoad(false),
mRecordErrors(
aLoader->GetDocument() &&
css::ErrorReporter::ShouldReportErrors(*aLoader->GetDocument())),
mPreloadKind(aPreloadKind),
mObserver(aObserver),
mTriggeringPrincipal(aTriggeringPrincipal),
@@ -376,9 +379,6 @@ SheetLoadData::SheetLoadData(
mGuessedEncoding(
GetFallbackEncoding(*aLoader, nullptr, aPreloadEncoding)),
mCompatMode(aLoader->CompatMode(aPreloadKind)),
mRecordErrors(
aLoader && aLoader->GetDocument() &&
css::ErrorReporter::ShouldReportErrors(*aLoader->GetDocument())),
mNetworkMetadata(std::move(aNetworkMetadata)) {
MOZ_ASSERT(mTriggeringPrincipal);
MOZ_ASSERT(mLoader, "Must have a loader!");
@@ -689,6 +689,7 @@ void SheetLoadData::OnStartRequest(nsIRequest* aRequest) {
}
return true;
}());
mFinalURISameOrigin = mLoader->LoaderPrincipal()->IsSameOrigin(finalURI);
if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel)) {
nsCString sourceMapURL;
if (nsContentUtils::GetSourceMapURL(httpChannel, sourceMapURL)) {
@@ -741,24 +742,30 @@ nsresult SheetLoadData::VerifySheetReadyToParse(nsresult aStatus,
contentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE) ||
contentType.IsEmpty();
if (!validType) {
const bool sameOrigin = mSheet->IsOriginClean();
const auto flag = sameOrigin && mCompatMode == eCompatibility_NavQuirks
? nsIScriptError::warningFlag
: nsIScriptError::errorFlag;
const auto errorMessage = flag == nsIScriptError::errorFlag
? "MimeNotCss"_ns
: "MimeNotCssWarn"_ns;
NS_ConvertUTF8toUTF16 sheetUri(mURI->GetSpecOrDefault());
NS_ConvertUTF8toUTF16 contentType16(contentType);
const bool shouldAllow = [&] {
if (mCompatMode != eCompatibility_NavQuirks) {
return false;
}
if (!mSheet->IsOriginClean()) {
return false;
}
if (StaticPrefs::layout_css_quirks_final_uri_check() &&
!mFinalURISameOrigin) {
return false;
}
return true;
}();
nsAutoCString referrerSpec;
if (nsCOMPtr<nsIURI> referrer = ReferrerInfo()->GetOriginalReferrer()) {
referrer->GetSpec(referrerSpec);
}
mLoader->mReporter->AddConsoleReport(
flag, "CSS Loader"_ns, PropertiesFile::CSS_PROPERTIES, referrerSpec, 0,
0, errorMessage, {std::move(sheetUri), std::move(contentType16)});
if (flag == nsIScriptError::errorFlag) {
shouldAllow ? nsIScriptError::warningFlag : nsIScriptError::errorFlag,
"CSS Loader"_ns, PropertiesFile::CSS_PROPERTIES, referrerSpec, 0, 0,
shouldAllow ? "MimeNotCssWarn"_ns : "MimeNotCss"_ns,
{NS_ConvertUTF8toUTF16(mURI->GetSpecOrDefault()),
NS_ConvertUTF8toUTF16(contentType)});
if (!shouldAllow) {
LOG_WARN(
(" Ignoring sheet with improper MIME type %s", contentType.get()));
return NS_ERROR_NOT_AVAILABLE;
+13 -9
View File
@@ -206,6 +206,19 @@ class SheetLoadData final
// * This load uses a complete cache and no necko activity happens
bool mShouldEmulateNotificationsForCachedLoad : 1;
// Whether SheetComplete was called.
bool mSheetCompleteCalled : 1 = false;
// Whether we intentionally are not calling SheetComplete because nobody is
// listening for the load.
bool mIntentionallyDropped : 1 = false;
const bool mRecordErrors : 1;
// Whether our final URI is same-origin with the document that's loading us.
// Only relevant for non-inline sheets.
bool mFinalURISameOrigin : 1 = false;
// Whether this is a preload, and which kind of preload it is.
//
// TODO(emilio): This can become a bitfield once we build with a GCC version
@@ -235,19 +248,10 @@ class SheetLoadData final
// The quirks mode of the loader at the time the load was triggered.
const nsCompatibility mCompatMode;
// Whether SheetComplete was called.
bool mSheetCompleteCalled = false;
// Whether we intentionally are not calling SheetComplete because nobody is
// listening for the load.
bool mIntentionallyDropped = false;
// The start timestamp for the load, or the timestamp where this load is
// coalesced into an existing load.
TimeStamp mLoadStart;
const bool mRecordErrors;
RefPtr<SubResourceNetworkMetadataHolder> mNetworkMetadata;
bool ShouldDefer() const { return mWasAlternate || !mMediaMatched; }
+7
View File
@@ -10809,6 +10809,13 @@
mirror: always
rust: true
# Whether quirks mode check the same-originness of the final uri,
# see https://github.com/whatwg/html/pull/12468
- name: layout.css.quirks.final-uri-check
type: RelaxedAtomicBool
value: true
mirror: always
# Should we look for counter ancestor scopes first?
- name: layout.css.counter-ancestor-scope.enabled
type: bool
@@ -1,3 +0,0 @@
[quirk-origin-check-recursive-import.html]
[Origin check for stylesheet with non-CSS MIME type quirk: recursive @import]
expected: FAIL
@@ -1,3 +0,0 @@
[quirk-origin-check.html]
[Origin check for stylesheet with non-CSS MIME type quirk]
expected: FAIL
@@ -1,3 +0,0 @@
[link-style-data-url-quirks.html]
[data: URL stylesheet with text/plain is blocked in quirks mode]
expected: FAIL