commit ce82072e19be84ce102516b501e40bc50ddf7b94
parent f9499e10c551c63d115c8088d43f4aecd6a9572f
Author: Sandor Molnar <smolnar@mozilla.com>
Date: Wed, 22 Oct 2025 02:51:35 +0300
Revert "Bug 1995282 - Clean up URLExtraData storage in stylesheets. r=smaug" for causing xpc crashes
This reverts commit c6bdc6abd200b1c812cc814789d1b03d6d4b6a47.
Diffstat:
11 files changed, 215 insertions(+), 123 deletions(-)
diff --git a/dom/security/ReferrerInfo.cpp b/dom/security/ReferrerInfo.cpp
@@ -1254,16 +1254,15 @@ already_AddRefed<nsIReferrerInfo> ReferrerInfo::CreateForFetch(
/* static */
already_AddRefed<nsIReferrerInfo> ReferrerInfo::CreateForExternalCSSResources(
- mozilla::StyleSheet* aExternalSheet, nsIURI* aExternalSheetURI,
- ReferrerPolicyEnum aPolicy) {
- MOZ_ASSERT(aExternalSheet);
- MOZ_ASSERT(aExternalSheetURI);
+ mozilla::StyleSheet* aExternalSheet, ReferrerPolicyEnum aPolicy) {
+ MOZ_ASSERT(aExternalSheet && !aExternalSheet->IsInline());
+ nsCOMPtr<nsIReferrerInfo> referrerInfo;
+
// Step 2
// https://w3c.github.io/webappsec-referrer-policy/#integration-with-css
// Use empty policy at the beginning and update it later from Referrer-Policy
// header.
- nsCOMPtr<nsIReferrerInfo> referrerInfo =
- new ReferrerInfo(aExternalSheetURI, aPolicy);
+ referrerInfo = new ReferrerInfo(aExternalSheet->GetSheetURI(), aPolicy);
return referrerInfo.forget();
}
diff --git a/dom/security/ReferrerInfo.h b/dom/security/ReferrerInfo.h
@@ -110,12 +110,11 @@ class ReferrerInfo : public nsIReferrerInfo {
* stylesheet. The returned nsIReferrerInfo object will be used for any
* requests or resources referenced by the sheet.
*
- * @param aExternalSheet the stylesheet.
- * @param aExternalSheetURI the stylesheet URI.
+ * @param aSheet the stylesheet to init referrerInfo.
* @param aPolicy referrer policy from header if there's any.
*/
static already_AddRefed<nsIReferrerInfo> CreateForExternalCSSResources(
- StyleSheet* aExternalSheet, nsIURI* aExternalSheetURI,
+ StyleSheet* aExternalSheet,
ReferrerPolicyEnum aPolicy = ReferrerPolicy::_empty);
/**
diff --git a/layout/style/GeckoBindings.cpp b/layout/style/GeckoBindings.cpp
@@ -1394,10 +1394,11 @@ static already_AddRefed<StyleSheet> LoadImportSheet(
if (!uri) {
NS_NewURI(getter_AddRefs(uri), "about:invalid"_ns);
}
+ emptySheet->SetURIs(uri, uri, uri);
+ emptySheet->SetPrincipal(aURL.ExtraData().Principal());
nsCOMPtr<nsIReferrerInfo> referrerInfo =
- ReferrerInfo::CreateForExternalCSSResources(emptySheet, uri);
- emptySheet->SetURIs(uri, uri, uri, referrerInfo,
- aURL.ExtraData().Principal());
+ ReferrerInfo::CreateForExternalCSSResources(emptySheet);
+ emptySheet->SetReferrerInfo(referrerInfo);
emptySheet->SetComplete();
aParent->AppendStyleSheet(*emptySheet);
return emptySheet.forget();
diff --git a/layout/style/GlobalStyleSheetCache.cpp b/layout/style/GlobalStyleSheetCache.cpp
@@ -311,10 +311,11 @@ void GlobalStyleSheetCache::LoadSheetFromSharedMemory(
nsCOMPtr<nsIURI> uri;
MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), aURL));
+ sheet->SetPrincipal(nsContentUtils::GetSystemPrincipal());
+ sheet->SetURIs(uri, uri, uri);
nsCOMPtr<nsIReferrerInfo> referrerInfo =
- dom::ReferrerInfo::CreateForExternalCSSResources(sheet, uri);
- sheet->SetURIs(uri, uri, uri, referrerInfo,
- nsContentUtils::GetSystemPrincipal());
+ dom::ReferrerInfo::CreateForExternalCSSResources(sheet);
+ sheet->SetReferrerInfo(referrerInfo);
sheet->SetSharedContents(aHeader->mSheets[i]);
sheet->SetComplete();
URLExtraData::sShared[i] = sheet->URLData();
diff --git a/layout/style/Loader.cpp b/layout/style/Loader.cpp
@@ -280,6 +280,8 @@ SheetLoadData::SheetLoadData(
mMediaMatched(aMediaMatches == MediaMatched::Yes),
mUseSystemPrincipal(false),
mSheetAlreadyComplete(false),
+ mIsCrossOriginNoCORS(false),
+ mBlockResourceTiming(false),
mLoadFailed(false),
mShouldEmulateNotificationsForCachedLoad(false),
mPreloadKind(aPreloadKind),
@@ -323,6 +325,8 @@ SheetLoadData::SheetLoadData(
mMediaMatched(true),
mUseSystemPrincipal(aParentData && aParentData->mUseSystemPrincipal),
mSheetAlreadyComplete(false),
+ mIsCrossOriginNoCORS(false),
+ mBlockResourceTiming(false),
mLoadFailed(false),
mShouldEmulateNotificationsForCachedLoad(false),
mPreloadKind(StylePreloadKind::None),
@@ -369,6 +373,8 @@ SheetLoadData::SheetLoadData(
mMediaMatched(true),
mUseSystemPrincipal(aUseSystemPrincipal == UseSystemPrincipal::Yes),
mSheetAlreadyComplete(false),
+ mIsCrossOriginNoCORS(false),
+ mBlockResourceTiming(false),
mLoadFailed(false),
mShouldEmulateNotificationsForCachedLoad(false),
mPreloadKind(aPreloadKind),
@@ -654,6 +660,8 @@ void SheetLoadData::OnStartRequest(nsIRequest* aRequest) {
NS_GetFinalChannelURI(channel, getter_AddRefs(finalURI));
MOZ_DIAGNOSTIC_ASSERT(finalURI,
"Someone just violated the nsIRequest contract");
+ mSheet->SetURIs(finalURI, originalURI, finalURI);
+
nsCOMPtr<nsIPrincipal> principal;
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
if (mUseSystemPrincipal) {
@@ -662,40 +670,22 @@ void SheetLoadData::OnStartRequest(nsIRequest* aRequest) {
secMan->GetChannelResultPrincipal(channel, getter_AddRefs(principal));
}
MOZ_DIAGNOSTIC_ASSERT(principal);
+ mSheet->SetPrincipal(principal);
nsCOMPtr<nsIReferrerInfo> referrerInfo =
ReferrerInfo::CreateForExternalCSSResources(
- mSheet, finalURI,
- nsContentUtils::GetReferrerPolicyFromChannel(channel));
- mSheet->SetURIs(finalURI, originalURI, finalURI, referrerInfo, principal);
- mSheet->SetOriginClean([&] {
- if (mParentData && !mParentData->mSheet->IsOriginClean()) {
- return false;
- }
- if (mSheet->GetCORSMode() != CORS_NONE) {
- return true;
- }
- if (!mLoader->LoaderPrincipal()->Subsumes(mSheet->Principal())) {
- return false;
- }
- if (nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(channel)) {
- bool allRedirectsSameOrigin = false;
- bool hadCrossOriginRedirects =
- NS_SUCCEEDED(timedChannel->GetAllRedirectsSameOrigin(
- &allRedirectsSameOrigin)) &&
- !allRedirectsSameOrigin;
- if (hadCrossOriginRedirects) {
- return false;
- }
- }
- return true;
- }());
+ mSheet, nsContentUtils::GetReferrerPolicyFromChannel(channel));
+ mSheet->SetReferrerInfo(referrerInfo);
+
if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel)) {
nsCString sourceMapURL;
if (nsContentUtils::GetSourceMapURL(httpChannel, sourceMapURL)) {
mSheet->SetSourceMapURL(std::move(sourceMapURL));
}
}
+
+ mIsCrossOriginNoCORS = mSheet->GetCORSMode() == CORS_NONE &&
+ !mTriggeringPrincipal->Subsumes(mSheet->Principal());
}
/*
@@ -744,11 +734,7 @@ nsresult SheetLoadData::VerifySheetReadyToParse(nsresult aStatus,
contentType.IsEmpty();
if (!validType) {
- // FIXME(emilio, bug 1995647): This should arguably use IsOriginClean(),
- // though test_css_cross_domain_no_orb.html tests precisely this behavior
- // intentionally, and this is quirks-only...
- const bool sameOrigin =
- mLoader->LoaderPrincipal()->Subsumes(mSheet->Principal());
+ const bool sameOrigin = mTriggeringPrincipal->Subsumes(mSheet->Principal());
const auto flag = sameOrigin && mCompatMode == eCompatibility_NavQuirks
? nsIScriptError::warningFlag
: nsIScriptError::errorFlag;
@@ -957,14 +943,16 @@ Loader::CreateSheet(nsIURI* aURI, nsIContent* aLinkingContent,
return {std::move(sheet), sheetState, std::move(networkMetadata)};
}
}
+
+ nsIURI* sheetURI = aURI;
+ nsIURI* baseURI = aURI;
+ nsIURI* originalURI = aURI;
+
auto sheet = MakeRefPtr<StyleSheet>(aParsingMode, aCORSMode, sriMetadata);
+ sheet->SetURIs(sheetURI, originalURI, baseURI);
nsCOMPtr<nsIReferrerInfo> referrerInfo =
- ReferrerInfo::CreateForExternalCSSResources(sheet, aURI);
- // NOTE: If the sheet is loaded, then SetURIs gets called again with the right
- // principal / final uri / etc.
- sheet->SetURIs(aURI, aURI, aURI, referrerInfo, LoaderPrincipal());
- // Load errors should be origin-dirty, even if same-origin.
- sheet->SetOriginClean(false);
+ ReferrerInfo::CreateForExternalCSSResources(sheet);
+ sheet->SetReferrerInfo(referrerInfo);
LOG((" Needs parser"));
return {std::move(sheet), SheetState::NeedsParser, nullptr};
}
@@ -1416,9 +1404,9 @@ nsresult Loader::LoadSheetAsyncInternal(SheetLoadData& aLoadData,
if (nsCOMPtr<nsITimedChannel> timedChannel =
do_QueryInterface(httpChannel)) {
timedChannel->SetInitiatorType(aLoadData.InitiatorTypeString());
- if (aLoadData.mParentData &&
- !aLoadData.mParentData->mSheet->IsOriginClean()) {
- // This is a child sheet load of a cross-origin stylesheet.
+
+ if (aLoadData.mParentData) {
+ // This is a child sheet load.
//
// The resource timing of the sub-resources that a document loads
// should normally be reported to the document. One exception is any
@@ -1430,9 +1418,24 @@ nsresult Loader::LoadSheetAsyncInternal(SheetLoadData& aLoadData,
// timings for any sub-resources that a cross-origin resource may load
// since that obviously leaks information about what the cross-origin
// resource loads, which is bad.
- // Mark the channel so PerformanceMainThread::AddEntry will not
- // report the resource.
- timedChannel->SetReportResourceTiming(false);
+ //
+ // In addition to checking whether we're an immediate child resource of
+ // a cross-origin resource (by checking if mIsCrossOriginNoCORS is set
+ // to true on our parent), we also check our parent to see whether it
+ // itself is a sub-resource of a cross-origin resource by checking
+ // mBlockResourceTiming. If that is set then we too are such a
+ // sub-resource and so we set the flag on ourself too to propagate it
+ // on down.
+ if (aLoadData.mParentData->mIsCrossOriginNoCORS ||
+ aLoadData.mParentData->mBlockResourceTiming) {
+ // Set a flag so any other stylesheet triggered by this one will
+ // not be reported
+ aLoadData.mBlockResourceTiming = true;
+
+ // Mark the channel so PerformanceMainThread::AddEntry will not
+ // report the resource.
+ timedChannel->SetReportResourceTiming(false);
+ }
}
}
}
@@ -1826,10 +1829,12 @@ Result<Loader::LoadSheetResult, nsresult> Loader::LoadInlineStyle(
if (!isSheetFromCache) {
sheet = MakeRefPtr<StyleSheet>(eAuthorSheetFeatures, aInfo.mCORSMode,
SRIMetadata{});
+ sheet->SetURIs(sheetURI, originalURI, baseURI);
nsIReferrerInfo* referrerInfo =
aInfo.mContent->OwnerDoc()->ReferrerInfoForInternalCSSAndSVGResources();
- sheet->SetURIs(sheetURI, originalURI, baseURI, referrerInfo,
- sheetPrincipal);
+ sheet->SetReferrerInfo(referrerInfo);
+ // We never actually load this, so just set its principal directly.
+ sheet->SetPrincipal(sheetPrincipal);
}
auto matched = PrepareSheet(*sheet, aInfo.mTitle, aInfo.mMedia, nullptr,
diff --git a/layout/style/SheetLoadData.h b/layout/style/SheetLoadData.h
@@ -199,6 +199,18 @@ class SheetLoadData final
// async observer notification for an already-complete sheet.
bool mSheetAlreadyComplete : 1;
+ // If true, the sheet is being loaded cross-origin without CORS permissions.
+ // This is completely normal and CORS isn't needed for such loads. This
+ // flag is simply useful in determining whether to set mBlockResourceTiming
+ // for a child sheet.
+ bool mIsCrossOriginNoCORS : 1;
+
+ // If this flag is true, LoadSheet will call SetReportResourceTiming(false)
+ // on the timedChannel. This is to mark resources that are loaded by a
+ // cross-origin stylesheet with a no-cors policy.
+ // https://www.w3.org/TR/resource-timing/#processing-model
+ bool mBlockResourceTiming : 1;
+
// Boolean flag indicating whether the load has failed. This will be set
// to true if this load, or the load of any descendant import, fails.
bool mLoadFailed : 1;
diff --git a/layout/style/StyleSheet.cpp b/layout/style/StyleSheet.cpp
@@ -7,7 +7,6 @@
#include "mozilla/StyleSheet.h"
#include "mozAutoDocUpdate.h"
-#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/Assertions.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/ComputedStyleInlines.h"
@@ -39,7 +38,6 @@ StyleSheet::StyleSheet(css::SheetParsingMode aParsingMode, CORSMode aCORSMode,
: mParentSheet(nullptr),
mConstructorDocument(nullptr),
mDocumentOrShadowRoot(nullptr),
- mURLData{URLExtraData::Dummy()},
mParsingMode(aParsingMode),
mState(static_cast<State>(0)),
mInner(new StyleSheetInfo(aCORSMode, aIntegrity, aParsingMode)) {
@@ -53,9 +51,6 @@ StyleSheet::StyleSheet(const StyleSheet& aCopy, StyleSheet* aParentSheetToUse,
mConstructorDocument(aConstructorDocToUse),
mTitle(aCopy.mTitle),
mDocumentOrShadowRoot(aDocOrShadowRootToUse),
- mURLData(aCopy.mURLData),
- mSheetURI(aCopy.mSheetURI),
- mOriginalSheetURI(aCopy.mOriginalSheetURI),
mParsingMode(aCopy.mParsingMode),
mState(aCopy.mState),
// Shallow copy, but concrete subclasses will fix up.
@@ -333,6 +328,11 @@ void StyleSheet::SetDisabled(bool aDisabled) {
}
}
+void StyleSheet::SetURLExtraData() {
+ Inner().mURLData =
+ new URLExtraData(GetBaseURI(), GetReferrerInfo(), Principal());
+}
+
nsISupports* StyleSheet::GetRelevantGlobal() const {
const StyleSheet& outer = OutermostSheet();
return outer.mRelevantGlobal;
@@ -341,19 +341,31 @@ nsISupports* StyleSheet::GetRelevantGlobal() const {
StyleSheetInfo::StyleSheetInfo(CORSMode aCORSMode,
const SRIMetadata& aIntegrity,
css::SheetParsingMode aParsingMode)
- : mCORSMode(aCORSMode),
+ : mPrincipal(NullPrincipal::CreateWithoutOriginAttributes()),
+ mCORSMode(aCORSMode),
+ mReferrerInfo(new ReferrerInfo(nullptr)),
mIntegrity(aIntegrity),
- mContents(Servo_StyleSheet_Empty(aParsingMode).Consume()) {
+ mContents(Servo_StyleSheet_Empty(aParsingMode).Consume()),
+ mURLData(URLExtraData::Dummy()) {
+ if (!mPrincipal) {
+ MOZ_CRASH("NullPrincipal::Init failed");
+ }
MOZ_COUNT_CTOR(StyleSheetInfo);
}
StyleSheetInfo::StyleSheetInfo(StyleSheetInfo& aCopy, StyleSheet* aPrimarySheet)
- : mCORSMode(aCopy.mCORSMode),
+ : mSheetURI(aCopy.mSheetURI),
+ mOriginalSheetURI(aCopy.mOriginalSheetURI),
+ mBaseURI(aCopy.mBaseURI),
+ mPrincipal(aCopy.mPrincipal),
+ mCORSMode(aCopy.mCORSMode),
+ mReferrerInfo(aCopy.mReferrerInfo),
mIntegrity(aCopy.mIntegrity),
// We don't rebuild the child because we're making a copy without
// children.
mSourceMapURL(aCopy.mSourceMapURL),
- mContents(Servo_StyleSheet_Clone(aCopy.mContents.get()).Consume())
+ mContents(Servo_StyleSheet_Clone(aCopy.mContents.get()).Consume()),
+ mURLData(aCopy.mURLData)
#ifdef DEBUG
,
mPrincipalSet(aCopy.mPrincipalSet)
@@ -412,7 +424,7 @@ void StyleSheetInfo::RemoveSheet(StyleSheet* aSheet) {
void StyleSheet::GetType(nsAString& aType) { aType.AssignLiteral("text/css"); }
void StyleSheet::GetHref(nsAString& aHref, ErrorResult& aRv) {
- if (nsIURI* sheetURI = mOriginalSheetURI) {
+ if (nsIURI* sheetURI = Inner().mOriginalSheetURI) {
nsAutoCString str;
nsresult rv = sheetURI->GetSpec(str);
if (NS_FAILED(rv)) {
@@ -718,7 +730,7 @@ void StyleSheet::ReplaceSync(const nsACString& aText, ErrorResult& aRv) {
RefPtr<const StyleStylesheetContents> rawContent =
Servo_StyleSheet_FromUTF8Bytes(
&mConstructorDocument->EnsureCSSLoader(), this,
- /* load_data = */ nullptr, &aText, mParsingMode, mURLData,
+ /* load_data = */ nullptr, &aText, mParsingMode, URLData(),
mConstructorDocument->GetCompatibilityMode(),
/* reusable_sheets = */ nullptr, StyleAllowImportRules::No,
StyleSanitizationKind::None,
@@ -863,7 +875,9 @@ void StyleSheet::RemoveFromParent() {
void StyleSheet::SubjectSubsumesInnerPrincipal(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv) {
- if (aSubjectPrincipal.Subsumes(Principal())) {
+ StyleSheetInfo& info = Inner();
+
+ if (aSubjectPrincipal.Subsumes(info.mPrincipal)) {
return;
}
@@ -874,12 +888,26 @@ void StyleSheet::SubjectSubsumesInnerPrincipal(nsIPrincipal& aSubjectPrincipal,
return;
}
- // Make sure we're complete.
+ // Now make sure we set the principal of our inner to the subjectPrincipal.
+ // We do this because we're in a situation where the caller would not normally
+ // be able to access the sheet, but the sheet has opted in to being read.
+ // Unfortunately, that means it's also opted in to being _edited_, and if the
+ // caller now makes edits to the sheet we want the resulting resource loads,
+ // if any, to look as if they are coming from the caller's principal, not the
+ // original sheet principal.
+ //
+ // That means we need a unique inner, of course. But we don't want to do that
+ // if we're not complete yet. Luckily, all the callers of this method throw
+ // anyway if not complete, so we can just do that here too.
if (!IsComplete()) {
aRv.ThrowInvalidAccessError(
"Not allowed to access still-loading stylesheet");
return;
}
+
+ WillDirty();
+
+ info.mPrincipal = &aSubjectPrincipal;
}
bool StyleSheet::IsDirectlyAssociatedTo(
@@ -913,13 +941,10 @@ bool StyleSheet::AreRulesAvailable(nsIPrincipal& aSubjectPrincipal,
"Can't access rules of still-loading style sheet");
return false;
}
- if (aSubjectPrincipal.IsSystemPrincipal()) {
- // System principal should always allow access to rules. Devtools needs this
- // for example.
- return true;
- }
- if (!Inner().mOriginClean && !nsContentUtils::BypassCSSOMOriginCheck()) {
- aRv.ThrowSecurityError("Not allowed to access cross-origin stylesheet");
+ //-- Security check: Only scripts whose principal subsumes that of the
+ // style sheet can access rule collections.
+ SubjectSubsumesInnerPrincipal(aSubjectPrincipal, aRv);
+ if (NS_WARN_IF(aRv.Failed())) {
return false;
}
return true;
@@ -1151,11 +1176,13 @@ already_AddRefed<StyleSheet> StyleSheet::CreateConstructedSheet(
}
}
- auto referrerInfo = MakeRefPtr<ReferrerInfo>(aConstructorDocument);
nsIURI* sheetURI = aConstructorDocument.GetDocumentURI();
nsIURI* originalURI = nullptr;
- sheet->SetURIs(sheetURI, originalURI, baseURI, referrerInfo,
- aConstructorDocument.NodePrincipal());
+ sheet->SetURIs(sheetURI, originalURI, baseURI);
+
+ sheet->SetPrincipal(aConstructorDocument.NodePrincipal());
+ auto referrerInfo = MakeRefPtr<ReferrerInfo>(aConstructorDocument);
+ sheet->SetReferrerInfo(referrerInfo);
sheet->mConstructorDocument = &aConstructorDocument;
// 2. Set the sheet's media according to aOptions.
@@ -1167,6 +1194,7 @@ already_AddRefed<StyleSheet> StyleSheet::CreateConstructedSheet(
// 3. Set the sheet's disabled flag according to aOptions.
sheet->SetDisabled(aOptions.mDisabled);
+ sheet->SetURLExtraData();
sheet->SetComplete();
sheet->ReplaceSync(""_ns, aRv);
@@ -1197,17 +1225,19 @@ RefPtr<StyleSheetParsePromise> StyleSheet::ParseSheet(
__func__);
}
BlockParsePromise();
+ SetURLExtraData();
// @import rules are disallowed due to this decision:
// https://github.com/WICG/construct-stylesheets/issues/119#issuecomment-588352418
// We may allow @import rules again in the future.
auto allowImportRules = SelfOrAncestorIsConstructed()
? StyleAllowImportRules::No
: StyleAllowImportRules::Yes;
+ URLExtraData* urlData = URLData();
if (aLoadData->get()->mRecordErrors) {
MOZ_ASSERT(NS_IsMainThread());
RefPtr<StyleStylesheetContents> contents =
Servo_StyleSheet_FromUTF8Bytes(
- &aLoader, this, aLoadData->get(), &aBytes, mParsingMode, mURLData,
+ &aLoader, this, aLoadData->get(), &aBytes, mParsingMode, urlData,
aLoadData->get()->mCompatMode,
/* reusable_sheets = */ nullptr, allowImportRules,
StyleSanitizationKind::None,
@@ -1216,7 +1246,7 @@ RefPtr<StyleSheetParsePromise> StyleSheet::ParseSheet(
FinishAsyncParse(contents.forget());
} else {
Servo_StyleSheet_FromUTF8BytesAsync(
- aLoadData, mURLData, &aBytes, mParsingMode,
+ aLoadData, urlData, &aBytes, mParsingMode,
aLoadData->get()->mCompatMode, allowImportRules);
}
@@ -1253,31 +1283,11 @@ const StyleUseCounters* StyleSheet::UseCounters() const {
return Servo_StyleSheet_UseCounters(RawContents());
}
-void StyleSheet::SetURIs(nsIURI* aSheetURI, nsIURI* aOriginalSheetURI,
- nsIURI* aBaseURI, nsIReferrerInfo* aReferrerInfo,
- nsIPrincipal* aPrincipal) {
- MOZ_ASSERT(aSheetURI);
- MOZ_ASSERT(aBaseURI);
- MOZ_ASSERT(aPrincipal);
- MOZ_ASSERT(aReferrerInfo);
- mURLData = MakeAndAddRef<URLExtraData>(aBaseURI, aReferrerInfo, aPrincipal);
- mSheetURI = aSheetURI;
- mOriginalSheetURI = aOriginalSheetURI;
-}
-
-nsIURI* StyleSheet::GetBaseURI() const { return URLData()->BaseURI(); }
-
-nsIReferrerInfo* StyleSheet::GetReferrerInfo() const {
- return URLData()->ReferrerInfo();
-}
-
-nsIPrincipal* StyleSheet::Principal() const { return URLData()->Principal(); }
-
void StyleSheet::PropagateUseCountersTo(Document* aDoc) const {
if (!aDoc || URLData()->ChromeRulesEnabled()) {
return;
}
- if (const auto* counters = aDoc->GetStyleUseCounters()) {
+ if (auto* counters = aDoc->GetStyleUseCounters()) {
Servo_UseCounters_Merge(counters, UseCounters());
}
}
@@ -1296,13 +1306,16 @@ void StyleSheet::ParseSheetSync(
return eCompatibility_FullStandards;
}();
+ SetURLExtraData();
+
+ URLExtraData* urlData = URLData();
auto allowImportRules = SelfOrAncestorIsConstructed()
? StyleAllowImportRules::No
: StyleAllowImportRules::Yes;
Inner().mContents =
Servo_StyleSheet_FromUTF8Bytes(
- aLoader, this, aLoadData, &aBytes, mParsingMode, mURLData, compatMode,
+ aLoader, this, aLoadData, &aBytes, mParsingMode, urlData, compatMode,
aReusableSheets, allowImportRules, StyleSanitizationKind::None,
/* sanitized_output = */ nullptr)
.Consume();
@@ -1494,8 +1507,10 @@ StyleOrigin StyleSheet::GetOrigin() const {
void StyleSheet::SetSharedContents(const StyleLockedCssRules* aSharedRules) {
MOZ_ASSERT(!IsComplete());
+ SetURLExtraData();
+
Inner().mContents =
- Servo_StyleSheet_FromSharedData(mURLData, aSharedRules).Consume();
+ Servo_StyleSheet_FromSharedData(URLData(), aSharedRules).Consume();
}
const StyleLockedCssRules* StyleSheet::ToShared(
diff --git a/layout/style/StyleSheet.h b/layout/style/StyleSheet.h
@@ -167,7 +167,7 @@ class StyleSheet final : public nsICSSLoaderObserver, public nsWrapperCache {
// Whether our original contents may be using relative URIs.
StyleNonLocalUriDependency OriginalContentsUriDependency() const;
- URLExtraData* URLData() const { return mURLData.get(); }
+ URLExtraData* URLData() const { return Inner().mURLData; }
// nsICSSLoaderObserver interface
NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet, bool aWasDeferred,
@@ -197,18 +197,24 @@ class StyleSheet final : public nsICSSLoaderObserver, public nsWrapperCache {
// Whether the sheet is for an inline <style> element.
bool IsInline() const { return !GetOriginalURI(); }
- nsIURI* GetSheetURI() const { return mSheetURI; }
+ nsIURI* GetSheetURI() const { return Inner().mSheetURI; }
+
/**
* Get the URI this sheet was originally loaded from, if any. Can return null.
*/
- nsIURI* GetOriginalURI() const { return mOriginalSheetURI; }
- nsIURI* GetBaseURI() const;
+ nsIURI* GetOriginalURI() const { return Inner().mOriginalSheetURI; }
- void SetURIs(nsIURI* aSheetURI, nsIURI* aOriginalSheetURI, nsIURI* aBaseURI,
- nsIReferrerInfo* aReferrerInfo, nsIPrincipal* aPrincipal);
+ nsIURI* GetBaseURI() const { return Inner().mBaseURI; }
- void SetOriginClean(bool aValue) { Inner().mOriginClean = aValue; }
- bool IsOriginClean() const { return Inner().mOriginClean; }
+ /**
+ * SetURIs must be called on all sheets before parsing into them.
+ * SetURIs may only be called while the sheet is 1) incomplete and 2)
+ * has no rules in it.
+ *
+ * FIXME(emilio): Can we pass this down when constructing the sheet instead?
+ */
+ inline void SetURIs(nsIURI* aSheetURI, nsIURI* aOriginalSheetURI,
+ nsIURI* aBaseURI);
/**
* Whether the sheet is applicable. A sheet that is not applicable
@@ -308,7 +314,27 @@ class StyleSheet final : public nsICSSLoaderObserver, public nsWrapperCache {
}
// Principal() never returns a null pointer.
- nsIPrincipal* Principal() const;
+ nsIPrincipal* Principal() const { return Inner().mPrincipal; }
+
+ /**
+ * SetPrincipal should be called on all sheets before parsing into them.
+ * This can only be called once with a non-null principal.
+ *
+ * Calling this with a null pointer is allowed and is treated as a no-op.
+ *
+ * FIXME(emilio): Can we get this at construction time instead?
+ */
+ void SetPrincipal(nsIPrincipal* aPrincipal) {
+ StyleSheetInfo& info = Inner();
+ MOZ_ASSERT_IF(info.mPrincipalSet, info.mPrincipal == aPrincipal);
+ if (aPrincipal) {
+ info.mPrincipal = aPrincipal;
+#ifdef DEBUG
+ info.mPrincipalSet = true;
+#endif
+ }
+ }
+
void SetTitle(const nsAString& aTitle) { mTitle = aTitle; }
void SetMedia(already_AddRefed<dom::MediaList> aMedia);
@@ -316,7 +342,12 @@ class StyleSheet final : public nsICSSLoaderObserver, public nsWrapperCache {
CORSMode GetCORSMode() const { return Inner().mCORSMode; }
// Get this style sheet's ReferrerInfo
- nsIReferrerInfo* GetReferrerInfo() const;
+ nsIReferrerInfo* GetReferrerInfo() const { return Inner().mReferrerInfo; }
+
+ // Set this style sheet's ReferrerInfo
+ void SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
+ Inner().mReferrerInfo = aReferrerInfo;
+ }
// Get this style sheet's integrity metadata
void GetIntegrity(dom::SRIMetadata& aResult) const {
@@ -518,6 +549,8 @@ class StyleSheet final : public nsICSSLoaderObserver, public nsWrapperCache {
// returns false.
bool AreRulesAvailable(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
+ void SetURLExtraData();
+
protected:
// Internal methods which do not have security check and completeness check.
uint32_t InsertRuleInternal(const nsACString& aRule, uint32_t aIndex,
@@ -596,10 +629,6 @@ class StyleSheet final : public nsICSSLoaderObserver, public nsWrapperCache {
RefPtr<dom::MediaList> mMedia;
- RefPtr<URLExtraData> mURLData;
- RefPtr<nsIURI> mSheetURI;
- RefPtr<nsIURI> mOriginalSheetURI;
-
// mParsingMode controls access to nonstandard style constructs that
// are not safe for use on the public Web but necessary in UA sheets
// and/or useful in user sheets.
diff --git a/layout/style/StyleSheetInfo.h b/layout/style/StyleSheetInfo.h
@@ -41,10 +41,17 @@ struct StyleSheetInfo final {
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
+ // FIXME(emilio): most of this struct should be const, then we can remove the
+ // duplication with the UrlExtraData member and such.
+ nsCOMPtr<nsIURI> mSheetURI; // for error reports, etc.
+ nsCOMPtr<nsIURI> mOriginalSheetURI; // for GetHref. Can be null.
+ nsCOMPtr<nsIURI> mBaseURI; // for resolving relative URIs
+ nsCOMPtr<nsIPrincipal> mPrincipal;
const CORSMode mCORSMode;
+ // The ReferrerInfo of a stylesheet is used for its child sheets and loads
+ // come from this stylesheet, so it is stored here.
+ nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
dom::SRIMetadata mIntegrity;
- // https://drafts.csswg.org/cssom/#concept-css-style-sheet-origin-clean-flag
- bool mOriginClean = true;
// Pointer to the list of child sheets. This is all fundamentally broken,
// because each of the child sheets has a unique parent... We can only hope
@@ -60,6 +67,15 @@ struct StyleSheetInfo final {
RefPtr<const StyleStylesheetContents> mContents;
+ // XXX We already have mSheetURI, mBaseURI, and mPrincipal.
+ //
+ // Can we somehow replace them with URLExtraData directly? The issue
+ // is currently URLExtraData is immutable, but URIs in StyleSheetInfo
+ // seems to be mutable, so we probably cannot set them altogether.
+ // Also, this is mostly a duplicate reference of the same url data
+ // inside RawServoStyleSheet. We may want to just use that instead.
+ RefPtr<URLExtraData> mURLData;
+
// HACK: This must be the after any member rust accesses in order to not cause
// issues on i686-android. Bindgen generates an opaque blob of [u64; N] for
// types it doesn't understand like AutoTArray, but turns out u64 is not
diff --git a/layout/style/StyleSheetInlines.h b/layout/style/StyleSheetInlines.h
@@ -14,6 +14,16 @@
namespace mozilla {
+void StyleSheet::SetURIs(nsIURI* aSheetURI, nsIURI* aOriginalSheetURI,
+ nsIURI* aBaseURI) {
+ MOZ_ASSERT(aSheetURI && aBaseURI, "null ptr");
+ MOZ_ASSERT(!HasRules() && !IsComplete());
+ StyleSheetInfo& info = Inner();
+ info.mSheetURI = aSheetURI;
+ info.mOriginalSheetURI = aOriginalSheetURI;
+ info.mBaseURI = aBaseURI;
+}
+
dom::ParentObject StyleSheet::GetParentObject() const {
if (mRelevantGlobal) {
return dom::ParentObject(mRelevantGlobal);
diff --git a/testing/web-platform/meta/css/cssom/stylesheet-same-origin.sub.html.ini b/testing/web-platform/meta/css/cssom/stylesheet-same-origin.sub.html.ini
@@ -1,3 +1,8 @@
[stylesheet-same-origin.sub.html]
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Origin-clean check in cross-origin CSSOM Stylesheets (redirect from cross-origin to same-origin)]
+ expected: FAIL
+
[Origin-clean check in loading error CSSOM Stylesheets]
expected: FAIL