--- a/layout/style/StyleSheet.cpp
+++ b/layout/style/StyleSheet.cpp
@@ -2,25 +2,27 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/StyleSheet.h"
#include "mozilla/ComputedStyleInlines.h"
+#include "mozilla/css/ErrorReporter.h"
#include "mozilla/css/GroupRule.h"
#include "mozilla/dom/CSSImportRule.h"
#include "mozilla/dom/CSSRuleList.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/MediaList.h"
#include "mozilla/dom/ShadowRoot.h"
#include "mozilla/dom/ShadowRootBinding.h"
#include "mozilla/ServoCSSRuleList.h"
#include "mozilla/ServoStyleSet.h"
+#include "mozilla/StaticPrefs.h"
#include "mozilla/StyleSheetInlines.h"
#include "mozAutoDocUpdate.h"
#include "NullPrincipal.h"
namespace mozilla {
StyleSheet::StyleSheet(css::SheetParsingMode aParsingMode,
@@ -78,17 +80,17 @@ StyleSheet::StyleSheet(const StyleSheet&
StyleSheet::~StyleSheet()
{
MOZ_ASSERT(!mInner, "Inner should have been dropped in LastRelease");
}
bool
StyleSheet::HasRules() const
{
- return Servo_StyleSheet_HasRules(Inner()->mContents);
+ return Servo_StyleSheet_HasRules(Inner().mContents);
}
void
StyleSheet::LastRelease()
{
MOZ_ASSERT(mInner, "Should have an mInner at time of destruction.");
MOZ_ASSERT(mInner->mSheets.Contains(this), "Our mInner should include us.");
@@ -112,17 +114,17 @@ StyleSheet::UnlinkInner()
// Have to be a bit careful with child sheets, because we want to
// drop their mNext pointers and null out their mParent and
// mDocument, but don't want to work with deleted objects. And we
// don't want to do any addrefing in the process, just to make sure
// we don't confuse the cycle collector (though on the face of it,
// addref/release pairs during unlink should probably be ok).
RefPtr<StyleSheet> child;
- child.swap(SheetInfo().mFirstChild);
+ child.swap(Inner().mFirstChild);
while (child) {
MOZ_ASSERT(child->mParent == this, "We have a unique inner!");
child->mParent = nullptr;
// We (and child) might still think we're owned by a document, because
// unlink order is non-deterministic, so the document's unlink, which would
// tell us it does't own us anymore, may not have happened yet. But if
// we're being unlinked, clearly we're not owned by a document anymore
// conceptually!
@@ -201,26 +203,26 @@ StyleSheet::ParsingModeDOM()
#undef CHECK
return static_cast<mozilla::dom::CSSStyleSheetParsingMode>(mParsingMode);
}
bool
StyleSheet::IsComplete() const
{
- return SheetInfo().mComplete;
+ return Inner().mComplete;
}
void
StyleSheet::SetComplete()
{
NS_ASSERTION(!HasForcedUniqueInner(),
"Can't complete a sheet that's already been forced "
"unique.");
- SheetInfo().mComplete = true;
+ Inner().mComplete = true;
if (!mDisabled) {
ApplicableStateChanged(true);
}
}
void
StyleSheet::ApplicableStateChanged(bool aApplicable)
{
@@ -372,17 +374,17 @@ StyleSheet::SetDisabled(bool aDisabled)
// DOM method, so handle BeginUpdate/EndUpdate
MOZ_AUTO_DOC_UPDATE(mDocument, UPDATE_STYLE, true);
SetEnabled(!aDisabled);
}
void
StyleSheet::GetHref(nsAString& aHref, ErrorResult& aRv)
{
- if (nsIURI* sheetURI = SheetInfo().mOriginalSheetURI) {
+ if (nsIURI* sheetURI = Inner().mOriginalSheetURI) {
nsAutoCString str;
nsresult rv = sheetURI->GetSpec(str);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return;
}
CopyUTF8toUTF16(str, aHref);
} else {
@@ -681,17 +683,17 @@ StyleSheet::UnparentChildren()
}
}
}
void
StyleSheet::SubjectSubsumesInnerPrincipal(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
- StyleSheetInfo& info = SheetInfo();
+ StyleSheetInfo& info = Inner();
if (aSubjectPrincipal.Subsumes(info.mPrincipal)) {
return;
}
// Allow access only if CORS mode is not NONE and the security flag
// is not turned off.
if (GetCORSMode() == CORS_NONE &&
@@ -721,33 +723,33 @@ StyleSheet::SubjectSubsumesInnerPrincipa
info.mPrincipal = &aSubjectPrincipal;
}
bool
StyleSheet::AreRulesAvailable(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
// Rules are not available on incomplete sheets.
- if (!SheetInfo().mComplete) {
+ if (!Inner().mComplete) {
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
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())) {
return false;
}
return true;
}
StyleSheet*
StyleSheet::GetFirstChild() const
{
- return SheetInfo().mFirstChild;
+ return Inner().mFirstChild;
}
void
StyleSheet::SetAssociatedDocument(nsIDocument* aDocument,
DocumentAssociationMode aAssociationMode)
{
MOZ_ASSERT(aDocument || aAssociationMode == NotOwnedByDocument);
@@ -779,18 +781,18 @@ StyleSheet::PrependStyleSheet(StyleSheet
PrependStyleSheetSilently(aSheet);
}
void
StyleSheet::PrependStyleSheetSilently(StyleSheet* aSheet)
{
MOZ_ASSERT(aSheet);
- aSheet->mNext = SheetInfo().mFirstChild;
- SheetInfo().mFirstChild = aSheet;
+ aSheet->mNext = Inner().mFirstChild;
+ Inner().mFirstChild = aSheet;
// This is not reference counted. Our parent tells us when
// it's going away.
aSheet->mParent = this;
aSheet->SetAssociatedDocument(mDocument, mDocumentAssociationMode);
}
size_t
@@ -800,18 +802,18 @@ StyleSheet::SizeOfIncludingThis(MallocSi
const StyleSheet* s = this;
while (s) {
n += aMallocSizeOf(s);
// See the comment in CSSStyleSheet::SizeOfIncludingThis() for an
// explanation of this.
//
// FIXME(emilio): This comment is gone, someone should go find it.
- if (s->Inner()->mSheets.LastElement() == s) {
- n += s->Inner()->SizeOfIncludingThis(aMallocSizeOf);
+ if (s->Inner().mSheets.LastElement() == s) {
+ n += s->Inner().SizeOfIncludingThis(aMallocSizeOf);
}
// Measurement of the following members may be added later if DMD finds it
// is worthwhile:
// - s->mTitle
// - s->mMedia
// - s->mStyleSets
// - s->mRuleList
@@ -903,21 +905,21 @@ StyleSheet::RuleHasPendingChildSheet(css
return !childSheet->IsComplete();
}
return false;
}
void
StyleSheet::BuildChildListAfterInnerClone()
{
- MOZ_ASSERT(Inner()->mSheets.Length() == 1, "Should've just cloned");
- MOZ_ASSERT(Inner()->mSheets[0] == this);
- MOZ_ASSERT(!Inner()->mFirstChild);
+ MOZ_ASSERT(Inner().mSheets.Length() == 1, "Should've just cloned");
+ MOZ_ASSERT(Inner().mSheets[0] == this);
+ MOZ_ASSERT(!Inner().mFirstChild);
- auto* contents = Inner()->mContents.get();
+ auto* contents = Inner().mContents.get();
RefPtr<ServoCssRules> rules =
Servo_StyleSheet_GetRules(contents).Consume();
uint32_t index = 0;
while (true) {
uint32_t line, column; // Actually unused.
RefPtr<RawServoImportRule> import =
Servo_CssRules_GetImportRuleAt(rules, index, &line, &column).Consume();
@@ -989,91 +991,91 @@ RefPtr<StyleSheetParsePromise>
StyleSheet::ParseSheet(css::Loader* aLoader,
const nsACString& aBytes,
css::SheetLoadData* aLoadData)
{
MOZ_ASSERT(aLoader);
MOZ_ASSERT(aLoadData);
MOZ_ASSERT(mParsePromise.IsEmpty());
RefPtr<StyleSheetParsePromise> p = mParsePromise.Ensure(__func__);
- Inner()->mURLData =
+ Inner().mURLData =
new URLExtraData(GetBaseURI(), GetSheetURI(), Principal()); // RefPtr
if (!AllowParallelParse(aLoader, GetSheetURI())) {
RefPtr<RawServoStyleSheetContents> contents =
Servo_StyleSheet_FromUTF8Bytes(aLoader,
this,
aLoadData,
&aBytes,
mParsingMode,
- Inner()->mURLData,
+ Inner().mURLData,
aLoadData->mLineNumber,
aLoader->GetCompatibilityMode(),
/* reusable_sheets = */ nullptr)
.Consume();
FinishAsyncParse(contents.forget());
} else {
RefPtr<css::SheetLoadDataHolder> loadDataHolder =
new css::SheetLoadDataHolder(__func__, aLoadData);
Servo_StyleSheet_FromUTF8BytesAsync(loadDataHolder,
- Inner()->mURLData,
+ Inner().mURLData,
&aBytes,
mParsingMode,
aLoadData->mLineNumber,
aLoader->GetCompatibilityMode());
}
return Move(p);
}
void
StyleSheet::FinishAsyncParse(already_AddRefed<RawServoStyleSheetContents> aSheetContents)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mParsePromise.IsEmpty());
- Inner()->mContents = aSheetContents;
+ Inner().mContents = aSheetContents;
FinishParse();
mParsePromise.Resolve(true, __func__);
}
void
StyleSheet::ParseSheetSync(css::Loader* aLoader,
const nsACString& aBytes,
css::SheetLoadData* aLoadData,
uint32_t aLineNumber,
css::LoaderReusableStyleSheets* aReusableSheets)
{
nsCompatibility compatMode =
aLoader ? aLoader->GetCompatibilityMode() : eCompatibility_FullStandards;
- Inner()->mURLData = new URLExtraData(GetBaseURI(), GetSheetURI(), Principal()); // RefPtr
- Inner()->mContents = Servo_StyleSheet_FromUTF8Bytes(aLoader,
- this,
- aLoadData,
- &aBytes,
- mParsingMode,
- Inner()->mURLData,
- aLineNumber,
- compatMode,
- aReusableSheets)
+ Inner().mURLData = new URLExtraData(GetBaseURI(), GetSheetURI(), Principal()); // RefPtr
+ Inner().mContents = Servo_StyleSheet_FromUTF8Bytes(aLoader,
+ this,
+ aLoadData,
+ &aBytes,
+ mParsingMode,
+ Inner().mURLData,
+ aLineNumber,
+ compatMode,
+ aReusableSheets)
.Consume();
FinishParse();
}
void
StyleSheet::FinishParse()
{
nsString sourceMapURL;
- Servo_StyleSheet_GetSourceMapURL(Inner()->mContents, &sourceMapURL);
+ Servo_StyleSheet_GetSourceMapURL(Inner().mContents, &sourceMapURL);
SetSourceMapURLFromComment(sourceMapURL);
nsString sourceURL;
- Servo_StyleSheet_GetSourceURL(Inner()->mContents, &sourceURL);
+ Servo_StyleSheet_GetSourceURL(Inner().mContents, &sourceURL);
SetSourceURL(sourceURL);
}
nsresult
StyleSheet::ReparseSheet(const nsAString& aInput)
{
if (!mInner->mComplete) {
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
@@ -1104,17 +1106,17 @@ StyleSheet::ReparseSheet(const nsAString
// clean up child sheets list
for (StyleSheet* child = GetFirstChild(); child; ) {
StyleSheet* next = child->mNext;
child->mParent = nullptr;
child->SetAssociatedDocument(nullptr, NotOwnedByDocument);
child->mNext = nullptr;
child = next;
}
- Inner()->mFirstChild = nullptr;
+ Inner().mFirstChild = nullptr;
uint32_t lineNumber = 1;
if (mOwningNode) {
nsCOMPtr<nsIStyleSheetLinkingElement> link = do_QueryInterface(mOwningNode);
if (link) {
lineNumber = link->GetLineNumber();
}
}
@@ -1123,17 +1125,17 @@ StyleSheet::ReparseSheet(const nsAString
{
ServoCSSRuleList* ruleList = GetCssRulesInternal();
MOZ_ASSERT(ruleList);
uint32_t ruleCount = ruleList->Length();
for (uint32_t i = 0; i < ruleCount; ++i) {
css::Rule* rule = ruleList->GetRule(i);
MOZ_ASSERT(rule);
- if (rule->Type() == CSSRuleBinding::IMPORT_RULE &&
+ if (rule->Type() == dom::CSSRuleBinding::IMPORT_RULE &&
RuleHasPendingChildSheet(rule)) {
continue; // notify when loaded (see StyleSheetLoaded)
}
RuleRemoved(*rule);
}
}
DropRuleList();
@@ -1215,17 +1217,17 @@ StyleSheet::Clone(StyleSheet* aClonePare
ServoCSSRuleList*
StyleSheet::GetCssRulesInternal()
{
if (!mRuleList) {
EnsureUniqueInner();
RefPtr<ServoCssRules> rawRules =
- Servo_StyleSheet_GetRules(Inner()->mContents).Consume();
+ Servo_StyleSheet_GetRules(Inner().mContents).Consume();
MOZ_ASSERT(rawRules);
mRuleList = new ServoCSSRuleList(rawRules.forget(), this);
}
return mRuleList;
}
uint32_t
StyleSheet::InsertRuleInternal(const nsAString& aRule,
@@ -1284,12 +1286,12 @@ StyleSheet::InsertRuleIntoGroupInternal(
MOZ_ASSERT(rules->GetParentRule() == aGroup);
return rules->InsertRule(aRule, aIndex);
}
OriginFlags
StyleSheet::GetOrigin()
{
return static_cast<OriginFlags>(
- Servo_StyleSheet_GetOrigin(Inner()->mContents));
+ Servo_StyleSheet_GetOrigin(Inner().mContents));
}
} // namespace mozilla
--- a/layout/style/StyleSheet.h
+++ b/layout/style/StyleSheet.h
@@ -94,26 +94,27 @@ public:
ParseSheetSync(css::Loader* aLoader,
const nsACString& aBytes,
css::SheetLoadData* aLoadData,
uint32_t aLineNumber,
css::LoaderReusableStyleSheets* aReusableSheets = nullptr);
nsresult ReparseSheet(const nsAString& aInput);
- const RawServoStyleSheetContents* RawContents() const {
- return Inner()->mContents;
+ const RawServoStyleSheetContents* RawContents() const
+ {
+ return Inner().mContents;
}
void SetContentsForImport(const RawServoStyleSheetContents* aContents) {
- MOZ_ASSERT(!Inner()->mContents);
- Inner()->mContents = aContents;
+ MOZ_ASSERT(!Inner().mContents);
+ Inner().mContents = aContents;
}
- URLExtraData* URLData() const { return Inner()->mURLData; }
+ URLExtraData* URLData() const { return Inner().mURLData; }
// nsICSSLoaderObserver interface
NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet, bool aWasAlternate,
nsresult aStatus) final;
// Internal GetCssRules methods which do not have security check and
// completeness check.
ServoCSSRuleList* GetCssRulesInternal();
@@ -157,38 +158,60 @@ public:
* BeginUpdate() or EndUpdate() on the document -- calling those is
* the caller's responsibility. This allows use of SetEnabled when
* batched updates are desired. If you want updates handled for
* you, see SetDisabled().
*/
void SetEnabled(bool aEnabled);
// Whether the sheet is for an inline <style> element.
- inline bool IsInline() const;
+ bool IsInline() const
+ {
+ return !GetOriginalURI();
+ }
+
+ nsIURI* GetSheetURI() const
+ {
+ return Inner().mSheetURI;
+ }
- inline nsIURI* GetSheetURI() const;
- /* Get the URI this sheet was originally loaded from, if any. Can
- return null */
- inline nsIURI* GetOriginalURI() const;
- inline nsIURI* GetBaseURI() const;
+ /**
+ * Get the URI this sheet was originally loaded from, if any. Can return null.
+ */
+ nsIURI* GetOriginalURI() const
+ {
+ return Inner().mOriginalSheetURI;
+ }
+
+ nsIURI* GetBaseURI() const
+ {
+ return Inner().mBaseURI;
+ }
+
/**
* 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
+ * has no rules in it.
+ *
+ * FIXME(emilio): Can we pass this down when constructing the sheet instead?
*/
- inline void SetURIs(nsIURI* aSheetURI, nsIURI* aOriginalSheetURI,
+ inline void SetURIs(nsIURI* aSheetURI,
+ nsIURI* aOriginalSheetURI,
nsIURI* aBaseURI);
/**
* Whether the sheet is applicable. A sheet that is not applicable
* should never be inserted into a style set. A sheet may not be
* applicable for a variety of reasons including being disabled and
* being incomplete.
*/
- inline bool IsApplicable() const;
+ bool IsApplicable() const
+ {
+ return !mDisabled && Inner().mComplete;
+ }
already_AddRefed<StyleSheet> Clone(StyleSheet* aCloneParent,
dom::CSSImportRule* aCloneOwnerRule,
nsIDocument* aCloneDocument,
nsINode* aCloneOwningNode) const;
bool HasForcedUniqueInner() const
{
@@ -200,19 +223,27 @@ public:
return mDirtyFlags & MODIFIED_RULES;
}
void ClearModifiedRules()
{
mDirtyFlags &= ~MODIFIED_RULES;
}
- inline bool HasUniqueInner() const;
+ bool HasUniqueInner() const
+ {
+ return Inner().mSheets.Length() == 1;
+ }
+
+ void AssertHasUniqueInner() const
+ {
+ MOZ_ASSERT(HasUniqueInner());
+ }
+
void EnsureUniqueInner();
- inline void AssertHasUniqueInner() const;
// Append all of this sheet's child sheets to aArray.
void AppendAllChildSheets(nsTArray<StyleSheet*>& aArray);
// style sheet owner info
enum DocumentAssociationMode : uint8_t {
// OwnedByDocument means mDocument owns us (possibly via a chain of other
// stylesheets).
@@ -221,21 +252,28 @@ public:
// different lifetime than mDocument.
NotOwnedByDocument
};
nsIDocument* GetAssociatedDocument() const { return mDocument; }
bool IsOwnedByDocument() const {
return mDocumentAssociationMode == OwnedByDocument;
}
// aDocument must not be null.
- void SetAssociatedDocument(nsIDocument* aDocument,
- DocumentAssociationMode aMode);
+ void SetAssociatedDocument(nsIDocument* aDocument, DocumentAssociationMode);
void ClearAssociatedDocument();
- nsINode* GetOwnerNode() const { return mOwningNode; }
- inline StyleSheet* GetParentSheet() const { return mParent; }
+
+ nsINode* GetOwnerNode() const
+ {
+ return mOwningNode;
+ }
+
+ StyleSheet* GetParentSheet() const
+ {
+ return mParent;
+ }
void SetOwnerRule(dom::CSSImportRule* aOwnerRule) {
mOwnerRule = aOwnerRule; /* Not ref counted */
}
dom::CSSImportRule* GetOwnerRule() const { return mOwnerRule; }
void PrependStyleSheet(StyleSheet* aSheet);
@@ -245,44 +283,74 @@ public:
StyleSheet* GetFirstChild() const;
StyleSheet* GetMostRecentlyAddedChildSheet() const {
// New child sheet can only be prepended into the linked list of
// child sheets, so the most recently added one is always the first.
return GetFirstChild();
}
// Principal() never returns a null pointer.
- inline 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.
+ * 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?
*/
- inline void SetPrincipal(nsIPrincipal* aPrincipal);
+ void SetPrincipal(nsIPrincipal* aPrincipal)
+ {
+ StyleSheetInfo& info = Inner();
+ MOZ_ASSERT(!info.mPrincipalSet, "Should only set principal once");
+ if (aPrincipal) {
+ info.mPrincipal = aPrincipal;
+#ifdef DEBUG
+ info.mPrincipalSet = true;
+#endif
+ }
+ }
void SetTitle(const nsAString& aTitle) { mTitle = aTitle; }
void SetMedia(dom::MediaList* aMedia);
// Get this style sheet's CORS mode
- inline CORSMode GetCORSMode() const;
+ CORSMode GetCORSMode() const
+ {
+ return Inner().mCORSMode;
+ }
+
// Get this style sheet's Referrer Policy
- inline net::ReferrerPolicy GetReferrerPolicy() const;
+ net::ReferrerPolicy GetReferrerPolicy() const
+ {
+ return Inner().mReferrerPolicy;
+ }
// Get this style sheet's integrity metadata
- inline void GetIntegrity(dom::SRIMetadata& aResult) const;
+ void GetIntegrity(dom::SRIMetadata& aResult) const
+ {
+ aResult = Inner().mIntegrity;
+ }
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
#ifdef DEBUG
void List(FILE* aOut = stdout, int32_t aIndex = 0) const;
#endif
// WebIDL StyleSheet API
void GetType(nsAString& aType);
void GetHref(nsAString& aHref, ErrorResult& aRv);
// GetOwnerNode is defined above.
- inline StyleSheet* GetParentStyleSheet() const;
+ StyleSheet* GetParentStyleSheet() const
+ {
+ return GetParentSheet();
+ }
void GetTitle(nsAString& aTitle);
dom::MediaList* Media();
bool Disabled() const { return mDisabled; }
void SetDisabled(bool aDisabled);
void GetSourceMapURL(nsAString& aTitle);
void SetSourceMapURL(const nsAString& aSourceMapURL);
void SetSourceMapURLFromComment(const nsAString& aSourceMapURLFromComment);
void GetSourceURL(nsAString& aSourceURL);
@@ -329,23 +397,27 @@ public:
for (StyleSheet* child = GetFirstChild(); child; child = child->mNext) {
aCallback(child);
}
}
private:
dom::ShadowRoot* GetContainingShadow() const;
- StyleSheetInfo* Inner() { return mInner; }
- const StyleSheetInfo* Inner() const { return mInner; }
+ StyleSheetInfo& Inner()
+ {
+ MOZ_ASSERT(mInner);
+ return *mInner;
+ }
- // Get a handle to the various stylesheet bits which live on the 'inner' for
- // gecko stylesheets and live on the StyleSheet for Servo stylesheets.
- inline StyleSheetInfo& SheetInfo();
- inline const StyleSheetInfo& SheetInfo() const;
+ const StyleSheetInfo& Inner() const
+ {
+ MOZ_ASSERT(mInner);
+ return *mInner;
+ }
// Check if the rules are available for read and write.
// It does the security check as well as whether the rules have been
// completely loaded. aRv will have an exception set if this function
// returns false.
bool AreRulesAvailable(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
protected: