tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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:
Mdom/security/ReferrerInfo.cpp | 11+++++------
Mdom/security/ReferrerInfo.h | 5++---
Mlayout/style/GeckoBindings.cpp | 7++++---
Mlayout/style/GlobalStyleSheetCache.cpp | 7++++---
Mlayout/style/Loader.cpp | 93++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Mlayout/style/SheetLoadData.h | 12++++++++++++
Mlayout/style/StyleSheet.cpp | 111+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Mlayout/style/StyleSheet.h | 57+++++++++++++++++++++++++++++++++++++++++++--------------
Mlayout/style/StyleSheetInfo.h | 20++++++++++++++++++--
Mlayout/style/StyleSheetInlines.h | 10++++++++++
Mtesting/web-platform/meta/css/cssom/stylesheet-same-origin.sub.html.ini | 5+++++
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