tor-browser

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

commit c6bdc6abd200b1c812cc814789d1b03d6d4b6a47
parent 8516b589ff0605c2af6fdb2786ae814290365bc1
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date:   Tue, 21 Oct 2025 22:41:40 +0000

Bug 1995282 - Clean up URLExtraData storage in stylesheets. r=smaug

Make SetURIs be the source of truth for referrer info and principal too.
This allows us to remove redundant members.

Pull the URI and such out of StyleSheetInfo, since we are sharing
StyleSheetInfo across stylesheets with different base URIs and such now
(for inline stylesheets), and we need to keep track of the "right" base
URI for when we eventually clone them.

There's one part of the change here which is a bit scary, which is the
principal shenanigans. However I don't think it's problematic since we
already are using the URLExtraData for CSS parsing and subresource
loads, which doesn't have that mutation. In particular, we only use
StyleSheet::Principal from Loader::LoadChildSheet. So we can implement
what the spec actually says (an origin-clean flag).

Differential Revision: https://phabricator.services.mozilla.com/D269210

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, 123 insertions(+), 215 deletions(-)

diff --git a/dom/security/ReferrerInfo.cpp b/dom/security/ReferrerInfo.cpp @@ -1254,15 +1254,16 @@ already_AddRefed<nsIReferrerInfo> ReferrerInfo::CreateForFetch( /* static */ already_AddRefed<nsIReferrerInfo> ReferrerInfo::CreateForExternalCSSResources( - mozilla::StyleSheet* aExternalSheet, ReferrerPolicyEnum aPolicy) { - MOZ_ASSERT(aExternalSheet && !aExternalSheet->IsInline()); - nsCOMPtr<nsIReferrerInfo> referrerInfo; - + mozilla::StyleSheet* aExternalSheet, nsIURI* aExternalSheetURI, + ReferrerPolicyEnum aPolicy) { + MOZ_ASSERT(aExternalSheet); + MOZ_ASSERT(aExternalSheetURI); // 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. - referrerInfo = new ReferrerInfo(aExternalSheet->GetSheetURI(), aPolicy); + nsCOMPtr<nsIReferrerInfo> referrerInfo = + new ReferrerInfo(aExternalSheetURI, aPolicy); return referrerInfo.forget(); } diff --git a/dom/security/ReferrerInfo.h b/dom/security/ReferrerInfo.h @@ -110,11 +110,12 @@ class ReferrerInfo : public nsIReferrerInfo { * stylesheet. The returned nsIReferrerInfo object will be used for any * requests or resources referenced by the sheet. * - * @param aSheet the stylesheet to init referrerInfo. + * @param aExternalSheet the stylesheet. + * @param aExternalSheetURI the stylesheet URI. * @param aPolicy referrer policy from header if there's any. */ static already_AddRefed<nsIReferrerInfo> CreateForExternalCSSResources( - StyleSheet* aExternalSheet, + StyleSheet* aExternalSheet, nsIURI* aExternalSheetURI, ReferrerPolicyEnum aPolicy = ReferrerPolicy::_empty); /** diff --git a/layout/style/GeckoBindings.cpp b/layout/style/GeckoBindings.cpp @@ -1394,11 +1394,10 @@ 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); - emptySheet->SetReferrerInfo(referrerInfo); + ReferrerInfo::CreateForExternalCSSResources(emptySheet, uri); + emptySheet->SetURIs(uri, uri, uri, referrerInfo, + aURL.ExtraData().Principal()); emptySheet->SetComplete(); aParent->AppendStyleSheet(*emptySheet); return emptySheet.forget(); diff --git a/layout/style/GlobalStyleSheetCache.cpp b/layout/style/GlobalStyleSheetCache.cpp @@ -311,11 +311,10 @@ 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); - sheet->SetReferrerInfo(referrerInfo); + dom::ReferrerInfo::CreateForExternalCSSResources(sheet, uri); + sheet->SetURIs(uri, uri, uri, referrerInfo, + nsContentUtils::GetSystemPrincipal()); 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,8 +280,6 @@ SheetLoadData::SheetLoadData( mMediaMatched(aMediaMatches == MediaMatched::Yes), mUseSystemPrincipal(false), mSheetAlreadyComplete(false), - mIsCrossOriginNoCORS(false), - mBlockResourceTiming(false), mLoadFailed(false), mShouldEmulateNotificationsForCachedLoad(false), mPreloadKind(aPreloadKind), @@ -325,8 +323,6 @@ SheetLoadData::SheetLoadData( mMediaMatched(true), mUseSystemPrincipal(aParentData && aParentData->mUseSystemPrincipal), mSheetAlreadyComplete(false), - mIsCrossOriginNoCORS(false), - mBlockResourceTiming(false), mLoadFailed(false), mShouldEmulateNotificationsForCachedLoad(false), mPreloadKind(StylePreloadKind::None), @@ -373,8 +369,6 @@ SheetLoadData::SheetLoadData( mMediaMatched(true), mUseSystemPrincipal(aUseSystemPrincipal == UseSystemPrincipal::Yes), mSheetAlreadyComplete(false), - mIsCrossOriginNoCORS(false), - mBlockResourceTiming(false), mLoadFailed(false), mShouldEmulateNotificationsForCachedLoad(false), mPreloadKind(aPreloadKind), @@ -660,8 +654,6 @@ 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) { @@ -670,22 +662,40 @@ void SheetLoadData::OnStartRequest(nsIRequest* aRequest) { secMan->GetChannelResultPrincipal(channel, getter_AddRefs(principal)); } MOZ_DIAGNOSTIC_ASSERT(principal); - mSheet->SetPrincipal(principal); nsCOMPtr<nsIReferrerInfo> referrerInfo = ReferrerInfo::CreateForExternalCSSResources( - mSheet, nsContentUtils::GetReferrerPolicyFromChannel(channel)); - mSheet->SetReferrerInfo(referrerInfo); - + 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; + }()); 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()); } /* @@ -734,7 +744,11 @@ nsresult SheetLoadData::VerifySheetReadyToParse(nsresult aStatus, contentType.IsEmpty(); if (!validType) { - const bool sameOrigin = mTriggeringPrincipal->Subsumes(mSheet->Principal()); + // 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 auto flag = sameOrigin && mCompatMode == eCompatibility_NavQuirks ? nsIScriptError::warningFlag : nsIScriptError::errorFlag; @@ -943,16 +957,14 @@ 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); - sheet->SetReferrerInfo(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); LOG((" Needs parser")); return {std::move(sheet), SheetState::NeedsParser, nullptr}; } @@ -1404,9 +1416,9 @@ nsresult Loader::LoadSheetAsyncInternal(SheetLoadData& aLoadData, if (nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(httpChannel)) { timedChannel->SetInitiatorType(aLoadData.InitiatorTypeString()); - - if (aLoadData.mParentData) { - // This is a child sheet load. + if (aLoadData.mParentData && + !aLoadData.mParentData->mSheet->IsOriginClean()) { + // This is a child sheet load of a cross-origin stylesheet. // // The resource timing of the sub-resources that a document loads // should normally be reported to the document. One exception is any @@ -1418,24 +1430,9 @@ 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. - // - // 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); - } + // Mark the channel so PerformanceMainThread::AddEntry will not + // report the resource. + timedChannel->SetReportResourceTiming(false); } } } @@ -1829,12 +1826,10 @@ 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->SetReferrerInfo(referrerInfo); - // We never actually load this, so just set its principal directly. - sheet->SetPrincipal(sheetPrincipal); + sheet->SetURIs(sheetURI, originalURI, baseURI, referrerInfo, + sheetPrincipal); } auto matched = PrepareSheet(*sheet, aInfo.mTitle, aInfo.mMedia, nullptr, diff --git a/layout/style/SheetLoadData.h b/layout/style/SheetLoadData.h @@ -199,18 +199,6 @@ 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,6 +7,7 @@ #include "mozilla/StyleSheet.h" #include "mozAutoDocUpdate.h" +#include "mozilla/AlreadyAddRefed.h" #include "mozilla/Assertions.h" #include "mozilla/BasePrincipal.h" #include "mozilla/ComputedStyleInlines.h" @@ -38,6 +39,7 @@ 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)) { @@ -51,6 +53,9 @@ 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. @@ -328,11 +333,6 @@ 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,31 +341,19 @@ nsISupports* StyleSheet::GetRelevantGlobal() const { StyleSheetInfo::StyleSheetInfo(CORSMode aCORSMode, const SRIMetadata& aIntegrity, css::SheetParsingMode aParsingMode) - : mPrincipal(NullPrincipal::CreateWithoutOriginAttributes()), - mCORSMode(aCORSMode), - mReferrerInfo(new ReferrerInfo(nullptr)), + : mCORSMode(aCORSMode), mIntegrity(aIntegrity), - mContents(Servo_StyleSheet_Empty(aParsingMode).Consume()), - mURLData(URLExtraData::Dummy()) { - if (!mPrincipal) { - MOZ_CRASH("NullPrincipal::Init failed"); - } + mContents(Servo_StyleSheet_Empty(aParsingMode).Consume()) { MOZ_COUNT_CTOR(StyleSheetInfo); } StyleSheetInfo::StyleSheetInfo(StyleSheetInfo& aCopy, StyleSheet* aPrimarySheet) - : mSheetURI(aCopy.mSheetURI), - mOriginalSheetURI(aCopy.mOriginalSheetURI), - mBaseURI(aCopy.mBaseURI), - mPrincipal(aCopy.mPrincipal), - mCORSMode(aCopy.mCORSMode), - mReferrerInfo(aCopy.mReferrerInfo), + : mCORSMode(aCopy.mCORSMode), 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()), - mURLData(aCopy.mURLData) + mContents(Servo_StyleSheet_Clone(aCopy.mContents.get()).Consume()) #ifdef DEBUG , mPrincipalSet(aCopy.mPrincipalSet) @@ -424,7 +412,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 = Inner().mOriginalSheetURI) { + if (nsIURI* sheetURI = mOriginalSheetURI) { nsAutoCString str; nsresult rv = sheetURI->GetSpec(str); if (NS_FAILED(rv)) { @@ -730,7 +718,7 @@ void StyleSheet::ReplaceSync(const nsACString& aText, ErrorResult& aRv) { RefPtr<const StyleStylesheetContents> rawContent = Servo_StyleSheet_FromUTF8Bytes( &mConstructorDocument->EnsureCSSLoader(), this, - /* load_data = */ nullptr, &aText, mParsingMode, URLData(), + /* load_data = */ nullptr, &aText, mParsingMode, mURLData, mConstructorDocument->GetCompatibilityMode(), /* reusable_sheets = */ nullptr, StyleAllowImportRules::No, StyleSanitizationKind::None, @@ -875,9 +863,7 @@ void StyleSheet::RemoveFromParent() { void StyleSheet::SubjectSubsumesInnerPrincipal(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) { - StyleSheetInfo& info = Inner(); - - if (aSubjectPrincipal.Subsumes(info.mPrincipal)) { + if (aSubjectPrincipal.Subsumes(Principal())) { return; } @@ -888,26 +874,12 @@ void StyleSheet::SubjectSubsumesInnerPrincipal(nsIPrincipal& aSubjectPrincipal, return; } - // 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. + // Make sure we're complete. if (!IsComplete()) { aRv.ThrowInvalidAccessError( "Not allowed to access still-loading stylesheet"); return; } - - WillDirty(); - - info.mPrincipal = &aSubjectPrincipal; } bool StyleSheet::IsDirectlyAssociatedTo( @@ -941,10 +913,13 @@ bool StyleSheet::AreRulesAvailable(nsIPrincipal& aSubjectPrincipal, "Can't access rules of still-loading style sheet"); return false; } - //-- 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())) { + 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"); return false; } return true; @@ -1176,13 +1151,11 @@ already_AddRefed<StyleSheet> StyleSheet::CreateConstructedSheet( } } + auto referrerInfo = MakeRefPtr<ReferrerInfo>(aConstructorDocument); nsIURI* sheetURI = aConstructorDocument.GetDocumentURI(); nsIURI* originalURI = nullptr; - sheet->SetURIs(sheetURI, originalURI, baseURI); - - sheet->SetPrincipal(aConstructorDocument.NodePrincipal()); - auto referrerInfo = MakeRefPtr<ReferrerInfo>(aConstructorDocument); - sheet->SetReferrerInfo(referrerInfo); + sheet->SetURIs(sheetURI, originalURI, baseURI, referrerInfo, + aConstructorDocument.NodePrincipal()); sheet->mConstructorDocument = &aConstructorDocument; // 2. Set the sheet's media according to aOptions. @@ -1194,7 +1167,6 @@ 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); @@ -1225,19 +1197,17 @@ 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, urlData, + &aLoader, this, aLoadData->get(), &aBytes, mParsingMode, mURLData, aLoadData->get()->mCompatMode, /* reusable_sheets = */ nullptr, allowImportRules, StyleSanitizationKind::None, @@ -1246,7 +1216,7 @@ RefPtr<StyleSheetParsePromise> StyleSheet::ParseSheet( FinishAsyncParse(contents.forget()); } else { Servo_StyleSheet_FromUTF8BytesAsync( - aLoadData, urlData, &aBytes, mParsingMode, + aLoadData, mURLData, &aBytes, mParsingMode, aLoadData->get()->mCompatMode, allowImportRules); } @@ -1283,11 +1253,31 @@ 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 (auto* counters = aDoc->GetStyleUseCounters()) { + if (const auto* counters = aDoc->GetStyleUseCounters()) { Servo_UseCounters_Merge(counters, UseCounters()); } } @@ -1306,16 +1296,13 @@ 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, urlData, compatMode, + aLoader, this, aLoadData, &aBytes, mParsingMode, mURLData, compatMode, aReusableSheets, allowImportRules, StyleSanitizationKind::None, /* sanitized_output = */ nullptr) .Consume(); @@ -1507,10 +1494,8 @@ StyleOrigin StyleSheet::GetOrigin() const { void StyleSheet::SetSharedContents(const StyleLockedCssRules* aSharedRules) { MOZ_ASSERT(!IsComplete()); - SetURLExtraData(); - Inner().mContents = - Servo_StyleSheet_FromSharedData(URLData(), aSharedRules).Consume(); + Servo_StyleSheet_FromSharedData(mURLData, 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 Inner().mURLData; } + URLExtraData* URLData() const { return mURLData.get(); } // nsICSSLoaderObserver interface NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet, bool aWasDeferred, @@ -197,24 +197,18 @@ 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 Inner().mSheetURI; } - + nsIURI* GetSheetURI() const { return mSheetURI; } /** * Get the URI this sheet was originally loaded from, if any. Can return null. */ - nsIURI* GetOriginalURI() const { return Inner().mOriginalSheetURI; } + nsIURI* GetOriginalURI() const { return mOriginalSheetURI; } + nsIURI* GetBaseURI() const; - nsIURI* GetBaseURI() const { return Inner().mBaseURI; } + void SetURIs(nsIURI* aSheetURI, nsIURI* aOriginalSheetURI, nsIURI* aBaseURI, + nsIReferrerInfo* aReferrerInfo, nsIPrincipal* aPrincipal); - /** - * 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); + void SetOriginClean(bool aValue) { Inner().mOriginClean = aValue; } + bool IsOriginClean() const { return Inner().mOriginClean; } /** * Whether the sheet is applicable. A sheet that is not applicable @@ -314,27 +308,7 @@ class StyleSheet final : public nsICSSLoaderObserver, public nsWrapperCache { } // Principal() never returns a null pointer. - 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 - } - } - + nsIPrincipal* Principal() const; void SetTitle(const nsAString& aTitle) { mTitle = aTitle; } void SetMedia(already_AddRefed<dom::MediaList> aMedia); @@ -342,12 +316,7 @@ class StyleSheet final : public nsICSSLoaderObserver, public nsWrapperCache { CORSMode GetCORSMode() const { return Inner().mCORSMode; } // Get this style sheet's ReferrerInfo - nsIReferrerInfo* GetReferrerInfo() const { return Inner().mReferrerInfo; } - - // Set this style sheet's ReferrerInfo - void SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) { - Inner().mReferrerInfo = aReferrerInfo; - } + nsIReferrerInfo* GetReferrerInfo() const; // Get this style sheet's integrity metadata void GetIntegrity(dom::SRIMetadata& aResult) const { @@ -549,8 +518,6 @@ 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, @@ -629,6 +596,10 @@ 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,17 +41,10 @@ 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 @@ -67,15 +60,6 @@ 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,16 +14,6 @@ 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,8 +1,3 @@ [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