зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1539159 - Prevent modification of UA style sheets. r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D25661 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
2ca1c8c765
Коммит
e95797966a
|
@ -6,6 +6,9 @@
|
|||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
<script type="application/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
function sheetText(sheet) {
|
||||
return [...sheet.cssRules].map(r => r.cssText).join();
|
||||
}
|
||||
function run() {
|
||||
const sss = Cc["@mozilla.org/content/style-sheet-service;1"]
|
||||
.getService(Ci.nsIStyleSheetService);
|
||||
|
@ -42,11 +45,14 @@
|
|||
|
||||
// Check that re-parsing preserves the mode.
|
||||
let mode = sheet.parsingMode;
|
||||
try {
|
||||
InspectorUtils.parseStyleSheet(sheet, "body { color: chartreuse; }");
|
||||
isnot(sheet.parsingMode, "agent", "Agent sheets cannot be reparsed");
|
||||
} catch (ex) {
|
||||
is(sheet.parsingMode, "agent", "Agent sheets cannot be reparsed");
|
||||
let text = sheetText(sheet);
|
||||
InspectorUtils.parseStyleSheet(sheet, "body { color: chartreuse; }");
|
||||
if (mode == "agent") {
|
||||
is(sheetText(sheet), text,
|
||||
"Reparsing should not have changed a UA sheet");
|
||||
} else {
|
||||
isnot(sheetText(sheet), text,
|
||||
"Reparsing should have changed a non-UA sheet");
|
||||
}
|
||||
is(sheet.parsingMode, mode,
|
||||
"check that re-parsing preserved mode " + mode);
|
||||
|
|
|
@ -29,4 +29,5 @@ skip-if = ((os == 'win' && bits!=64) || (os=='linux' && bits==32) || os == 'mac'
|
|||
support-files =
|
||||
test_fontVariationsAPI.css
|
||||
[test_fontFaceGeneric.xul]
|
||||
[test_ua_rule_modification.html]
|
||||
[test_ua_sheet_disable.html]
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Test for bug 1539159</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
<p></p>
|
||||
<script>
|
||||
function start() {
|
||||
let rules = InspectorUtils.getCSSStyleRules(document.querySelector("p"));
|
||||
ok(rules.length > 0, "Should have found some rules");
|
||||
is(rules[0].type, CSSRule.STYLE_RULE, "Should have found a style rule");
|
||||
|
||||
let selector = rules[0].selectorText;
|
||||
isnot(selector, ".xxxxx", "Rule selector should not be something strange");
|
||||
|
||||
try {
|
||||
rules[0].selectorText = "img";
|
||||
} catch (ex) {
|
||||
}
|
||||
is(rules[0].selectorText, selector, "Selector text should be unchanged");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
document.addEventListener('DOMContentLoaded', start)
|
||||
</script>
|
|
@ -43,6 +43,9 @@ void CSSCounterStyleRule::GetName(nsAString& aName) {
|
|||
}
|
||||
|
||||
void CSSCounterStyleRule::SetName(const nsAString& aName) {
|
||||
if (IsReadOnly()) {
|
||||
return;
|
||||
}
|
||||
NS_ConvertUTF16toUTF8 name(aName);
|
||||
if (Servo_CounterStyleRule_SetName(mRawRule, &name)) {
|
||||
if (StyleSheet* sheet = GetStyleSheet()) {
|
||||
|
@ -58,6 +61,9 @@ void CSSCounterStyleRule::SetName(const nsAString& aName) {
|
|||
mRawRule, eCSSCounterDesc_##method_, &aValue); \
|
||||
} \
|
||||
void CSSCounterStyleRule::Set##method_(const nsAString& aValue) { \
|
||||
if (IsReadOnly()) { \
|
||||
return; \
|
||||
} \
|
||||
NS_ConvertUTF16toUTF8 value(aValue); \
|
||||
if (Servo_CounterStyleRule_SetDescriptor( \
|
||||
mRawRule, eCSSCounterDesc_##method_, &value)) { \
|
||||
|
|
|
@ -49,6 +49,9 @@ void CSSFontFaceRuleDecl::GetCssText(nsAString& aCssText) {
|
|||
void CSSFontFaceRuleDecl::SetCssText(const nsAString& aCssText,
|
||||
nsIPrincipal* aSubjectPrincipal,
|
||||
ErrorResult& aRv) {
|
||||
if (ContainingRule()->IsReadOnly()) {
|
||||
return;
|
||||
}
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); // bug 443978
|
||||
}
|
||||
|
||||
|
@ -70,6 +73,10 @@ CSSFontFaceRuleDecl::RemoveProperty(const nsAString& aPropName,
|
|||
NS_ASSERTION(descID >= eCSSFontDesc_UNKNOWN && descID < eCSSFontDesc_COUNT,
|
||||
"LookupFontDesc returned value out of range");
|
||||
|
||||
if (ContainingRule()->IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
aResult.Truncate();
|
||||
if (descID != eCSSFontDesc_UNKNOWN) {
|
||||
GetPropertyValue(descID, aResult);
|
||||
|
@ -92,6 +99,10 @@ CSSFontFaceRuleDecl::SetProperty(const nsAString& aPropName,
|
|||
// FIXME(heycam): If we are changing unicode-range, then a FontFace object
|
||||
// representing this rule must have its mUnicodeRange value invalidated.
|
||||
|
||||
if (ContainingRule()->IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
|
||||
}
|
||||
|
||||
|
|
|
@ -46,11 +46,19 @@ void CSSFontFeatureValuesRule::GetValueText(nsAString& aValueText) {
|
|||
|
||||
void CSSFontFeatureValuesRule::SetFontFamily(const nsAString& aFontFamily,
|
||||
ErrorResult& aRv) {
|
||||
if (IsReadOnly()) {
|
||||
return;
|
||||
}
|
||||
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
void CSSFontFeatureValuesRule::SetValueText(const nsAString& aValueText,
|
||||
ErrorResult& aRv) {
|
||||
if (IsReadOnly()) {
|
||||
return;
|
||||
}
|
||||
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
|
|
@ -140,6 +140,10 @@ void CSSKeyframeRule::List(FILE* out, int32_t aIndent) const {
|
|||
|
||||
template <typename Func>
|
||||
void CSSKeyframeRule::UpdateRule(Func aCallback) {
|
||||
if (IsReadOnly()) {
|
||||
return;
|
||||
}
|
||||
|
||||
aCallback();
|
||||
|
||||
if (StyleSheet* sheet = GetStyleSheet()) {
|
||||
|
|
|
@ -67,9 +67,14 @@ class CSSKeyframeList : public dom::CSSRuleList {
|
|||
return GetRule(aIndex);
|
||||
}
|
||||
|
||||
void AppendRule() { mRules.AppendObject(nullptr); }
|
||||
void AppendRule() {
|
||||
MOZ_ASSERT(!mParentRule->IsReadOnly());
|
||||
mRules.AppendObject(nullptr);
|
||||
}
|
||||
|
||||
void RemoveRule(uint32_t aIndex) {
|
||||
MOZ_ASSERT(!mParentRule->IsReadOnly());
|
||||
|
||||
if (aIndex >= mRules.Length()) {
|
||||
return;
|
||||
}
|
||||
|
@ -214,11 +219,17 @@ uint32_t CSSKeyframesRule::FindRuleIndexForKey(const nsAString& aKey) {
|
|||
}
|
||||
|
||||
template <typename Func>
|
||||
void CSSKeyframesRule::UpdateRule(Func aCallback) {
|
||||
nsresult CSSKeyframesRule::UpdateRule(Func aCallback) {
|
||||
if (IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
aCallback();
|
||||
if (StyleSheet* sheet = GetStyleSheet()) {
|
||||
sheet->RuleChanged(this);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void CSSKeyframesRule::GetName(nsAString& aName) const {
|
||||
|
|
|
@ -49,7 +49,7 @@ class CSSKeyframesRule final : public css::Rule {
|
|||
uint32_t FindRuleIndexForKey(const nsAString& aKey);
|
||||
|
||||
template <typename Func>
|
||||
void UpdateRule(Func aCallback);
|
||||
nsresult UpdateRule(Func aCallback);
|
||||
|
||||
virtual ~CSSKeyframesRule();
|
||||
|
||||
|
|
|
@ -74,6 +74,9 @@ void CSSMediaRule::GetConditionText(nsAString& aConditionText) {
|
|||
|
||||
void CSSMediaRule::SetConditionText(const nsAString& aConditionText,
|
||||
ErrorResult& aRv) {
|
||||
if (IsReadOnly()) {
|
||||
return;
|
||||
}
|
||||
Media()->SetMediaText(aConditionText);
|
||||
}
|
||||
|
||||
|
|
|
@ -104,6 +104,10 @@ void CSSMozDocumentRule::GetConditionText(nsAString& aConditionText) {
|
|||
|
||||
void CSSMozDocumentRule::SetConditionText(const nsAString& aConditionText,
|
||||
ErrorResult& aRv) {
|
||||
if (IsReadOnly()) {
|
||||
return;
|
||||
}
|
||||
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,10 @@ nsresult CSSPageRuleDeclaration::SetCSSDeclaration(
|
|||
MOZ_ASSERT(aDecl, "must be non-null");
|
||||
CSSPageRule* rule = Rule();
|
||||
|
||||
if (rule->IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aDecl != mDecls) {
|
||||
mDecls->SetOwningRule(nullptr);
|
||||
RefPtr<DeclarationBlock> decls = aDecl;
|
||||
|
|
|
@ -57,6 +57,11 @@ DeclarationBlock* CSSStyleRuleDeclaration::GetOrCreateCSSDeclaration(
|
|||
nsresult CSSStyleRuleDeclaration::SetCSSDeclaration(
|
||||
DeclarationBlock* aDecl, MutationClosureData* aClosureData) {
|
||||
CSSStyleRule* rule = Rule();
|
||||
|
||||
if (rule->IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (RefPtr<StyleSheet> sheet = rule->GetStyleSheet()) {
|
||||
if (aDecl != mDecls) {
|
||||
mDecls->SetOwningRule(nullptr);
|
||||
|
@ -158,6 +163,10 @@ void CSSStyleRule::GetSelectorText(nsAString& aSelectorText) {
|
|||
}
|
||||
|
||||
void CSSStyleRule::SetSelectorText(const nsAString& aSelectorText) {
|
||||
if (IsReadOnly()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (RefPtr<StyleSheet> sheet = GetStyleSheet()) {
|
||||
// StyleRule lives inside of the Inner, it is unsafe to call WillDirty
|
||||
// if sheet does not already have a unique Inner.
|
||||
|
|
|
@ -47,6 +47,10 @@ void CSSSupportsRule::GetConditionText(nsAString& aConditionText) {
|
|||
|
||||
void CSSSupportsRule::SetConditionText(const nsAString& aConditionText,
|
||||
ErrorResult& aRv) {
|
||||
if (IsReadOnly()) {
|
||||
return;
|
||||
}
|
||||
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "mozilla/DeclarationBlock.h"
|
||||
|
||||
#include "mozilla/css/Rule.h"
|
||||
#include "mozilla/ServoBindings.h"
|
||||
|
||||
#include "nsCSSProps.h"
|
||||
|
@ -23,4 +24,9 @@ already_AddRefed<DeclarationBlock> DeclarationBlock::FromCssText(
|
|||
return decl.forget();
|
||||
}
|
||||
|
||||
bool DeclarationBlock::OwnerIsReadOnly() const {
|
||||
css::Rule* rule = GetOwningRule();
|
||||
return rule && rule->IsReadOnly();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -59,6 +59,7 @@ class DeclarationBlock final {
|
|||
*/
|
||||
void AssertMutable() const {
|
||||
MOZ_ASSERT(IsMutable(), "someone forgot to call EnsureMutable");
|
||||
MOZ_ASSERT(!OwnerIsReadOnly(), "User Agent sheets shouldn't be modified");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,6 +86,8 @@ class DeclarationBlock final {
|
|||
* Copy |this|, if necessary to ensure that it can be modified.
|
||||
*/
|
||||
already_AddRefed<DeclarationBlock> EnsureMutable() {
|
||||
MOZ_ASSERT(!OwnerIsReadOnly());
|
||||
|
||||
if (!IsDirty()) {
|
||||
// In stylo, the old DeclarationBlock is stored in element's rule node
|
||||
// tree directly, to avoid new values replacing the DeclarationBlock in
|
||||
|
@ -136,6 +139,8 @@ class DeclarationBlock final {
|
|||
return c.mHTMLCSSStyleSheet;
|
||||
}
|
||||
|
||||
bool IsReadOnly() const;
|
||||
|
||||
static already_AddRefed<DeclarationBlock> FromCssText(
|
||||
const nsAString& aCssText, URLExtraData* aExtraData,
|
||||
nsCompatibility aMode, css::Loader* aLoader);
|
||||
|
@ -202,6 +207,9 @@ class DeclarationBlock final {
|
|||
|
||||
private:
|
||||
~DeclarationBlock() = default;
|
||||
|
||||
bool OwnerIsReadOnly() const;
|
||||
|
||||
union {
|
||||
// We only ever have one of these since we have an
|
||||
// nsHTMLCSSStyleSheet only for style attributes, and style
|
||||
|
|
|
@ -456,6 +456,9 @@ bool FontFace::SetDescriptor(nsCSSFontDesc aFontDesc, const nsAString& aValue,
|
|||
return false;
|
||||
}
|
||||
|
||||
// FIXME(heycam): Should not allow modification of FontFaces that are
|
||||
// CSS-connected and whose rule is read only.
|
||||
|
||||
NS_ConvertUTF16toUTF8 value(aValue);
|
||||
RefPtr<URLExtraData> url = GetURLExtraData();
|
||||
if (!Servo_FontFaceRule_SetDescriptor(GetData(), aFontDesc, &value, url)) {
|
||||
|
|
|
@ -74,6 +74,10 @@ void GroupRule::DropSheetReference() {
|
|||
|
||||
uint32_t GroupRule::InsertRule(const nsAString& aRule, uint32_t aIndex,
|
||||
ErrorResult& aRv) {
|
||||
if (IsReadOnly()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
StyleSheet* sheet = GetStyleSheet();
|
||||
if (NS_WARN_IF(!sheet)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
|
@ -97,6 +101,10 @@ uint32_t GroupRule::InsertRule(const nsAString& aRule, uint32_t aIndex,
|
|||
}
|
||||
|
||||
void GroupRule::DeleteRule(uint32_t aIndex, ErrorResult& aRv) {
|
||||
if (IsReadOnly()) {
|
||||
return;
|
||||
}
|
||||
|
||||
StyleSheet* sheet = GetStyleSheet();
|
||||
if (NS_WARN_IF(!sheet)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
|
|
|
@ -41,6 +41,10 @@ void MediaList::SetStyleSheet(StyleSheet* aSheet) {
|
|||
|
||||
template <typename Func>
|
||||
nsresult MediaList::DoMediaChange(Func aCallback) {
|
||||
if (IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mStyleSheet) {
|
||||
mStyleSheet->WillDirty();
|
||||
}
|
||||
|
@ -85,6 +89,10 @@ already_AddRefed<MediaList> MediaList::Create(const nsAString& aMedia,
|
|||
}
|
||||
|
||||
void MediaList::SetText(const nsAString& aMediaText) {
|
||||
if (IsReadOnly()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetTextInternal(aMediaText, CallerType::NonSystem);
|
||||
}
|
||||
|
||||
|
@ -107,6 +115,7 @@ void MediaList::IndexedGetter(uint32_t aIndex, bool& aFound,
|
|||
}
|
||||
|
||||
nsresult MediaList::Delete(const nsAString& aOldMedium) {
|
||||
MOZ_ASSERT(!IsReadOnly());
|
||||
NS_ConvertUTF16toUTF8 oldMedium(aOldMedium);
|
||||
if (Servo_MediaList_DeleteMedium(mRawList, &oldMedium)) {
|
||||
return NS_OK;
|
||||
|
@ -122,6 +131,7 @@ bool MediaList::Matches(const Document& aDocument) const {
|
|||
}
|
||||
|
||||
nsresult MediaList::Append(const nsAString& aNewMedium) {
|
||||
MOZ_ASSERT(!IsReadOnly());
|
||||
if (aNewMedium.IsEmpty()) {
|
||||
return NS_ERROR_DOM_NOT_FOUND_ERR;
|
||||
}
|
||||
|
@ -161,5 +171,9 @@ size_t MediaList::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
|
|||
return n;
|
||||
}
|
||||
|
||||
bool MediaList::IsReadOnly() const {
|
||||
return mStyleSheet && mStyleSheet->IsReadOnly();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -77,6 +77,8 @@ class MediaList final : public nsISupports, public nsWrapperCache {
|
|||
MOZ_ASSERT(!mStyleSheet, "Backpointer should have been cleared");
|
||||
}
|
||||
|
||||
bool IsReadOnly() const;
|
||||
|
||||
// not refcounted; sheet will let us know when it goes away
|
||||
// mStyleSheet is the sheet that needs to be dirtied when this
|
||||
// medialist changes
|
||||
|
|
|
@ -75,5 +75,13 @@ void Rule::SetCssText(const nsAString& aCssText) {
|
|||
|
||||
Rule* Rule::GetParentRule() const { return mParentRule; }
|
||||
|
||||
bool Rule::IsReadOnly() const {
|
||||
MOZ_ASSERT(!mSheet || !mParentRule ||
|
||||
mSheet->IsReadOnly() == mParentRule->IsReadOnly(),
|
||||
"a parent rule should be read only iff the owning sheet is "
|
||||
"read only");
|
||||
return mSheet && mSheet->IsReadOnly();
|
||||
}
|
||||
|
||||
} // namespace css
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -89,6 +89,9 @@ class Rule : public nsISupports, public nsWrapperCache {
|
|||
uint32_t GetLineNumber() const { return mLineNumber; }
|
||||
uint32_t GetColumnNumber() const { return mColumnNumber; }
|
||||
|
||||
// Whether this a rule in a read only style sheet.
|
||||
bool IsReadOnly() const;
|
||||
|
||||
// This is pure virtual because all of Rule's data members are non-owning and
|
||||
// thus measured elsewhere.
|
||||
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
|
|
|
@ -154,6 +154,11 @@ nsresult ServoCSSRuleList::InsertRule(const nsAString& aRule, uint32_t aIndex) {
|
|||
MOZ_ASSERT(mStyleSheet,
|
||||
"Caller must ensure that "
|
||||
"the list is not unlinked from stylesheet");
|
||||
|
||||
if (IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 rule(aRule);
|
||||
bool nested = !!mParentRule;
|
||||
css::Loader* loader = nullptr;
|
||||
|
@ -178,6 +183,10 @@ nsresult ServoCSSRuleList::InsertRule(const nsAString& aRule, uint32_t aIndex) {
|
|||
}
|
||||
|
||||
nsresult ServoCSSRuleList::DeleteRule(uint32_t aIndex) {
|
||||
if (IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = Servo_CssRules_DeleteRule(mRawRules, aIndex);
|
||||
if (!NS_FAILED(rv)) {
|
||||
uintptr_t rule = mRules[aIndex];
|
||||
|
@ -203,4 +212,12 @@ ServoCSSRuleList::~ServoCSSRuleList() {
|
|||
DropAllRules();
|
||||
}
|
||||
|
||||
bool ServoCSSRuleList::IsReadOnly() const {
|
||||
MOZ_ASSERT(!mStyleSheet || !mParentRule ||
|
||||
mStyleSheet->IsReadOnly() == mParentRule->IsReadOnly(),
|
||||
"a parent rule should be read only iff the owning sheet is "
|
||||
"read only");
|
||||
return mStyleSheet && mStyleSheet->IsReadOnly();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -71,6 +71,8 @@ class ServoCSSRuleList final : public dom::CSSRuleList {
|
|||
|
||||
void DropAllRules();
|
||||
|
||||
bool IsReadOnly() const;
|
||||
|
||||
// mStyleSheet may be nullptr when it drops the reference to us.
|
||||
StyleSheet* mStyleSheet = nullptr;
|
||||
// mParentRule is nullptr if it isn't a nested rule list.
|
||||
|
|
|
@ -242,8 +242,7 @@ void StyleSheet::ApplicableStateChanged(bool aApplicable) {
|
|||
}
|
||||
|
||||
void StyleSheet::SetDisabled(bool aDisabled) {
|
||||
// Only allow disabling author sheets.
|
||||
if (mParsingMode != css::eAuthorSheetFeatures) {
|
||||
if (IsReadOnly()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -296,9 +295,8 @@ StyleSheetInfo::StyleSheetInfo(StyleSheetInfo& aCopy, StyleSheet* aPrimarySheet)
|
|||
mCORSMode(aCopy.mCORSMode),
|
||||
mReferrerPolicy(aCopy.mReferrerPolicy),
|
||||
mIntegrity(aCopy.mIntegrity),
|
||||
mFirstChild() // We don't rebuild the child because we're making a copy
|
||||
// without children.
|
||||
,
|
||||
mFirstChild(), // We don't rebuild the child because we're making a copy
|
||||
// without children.
|
||||
mSourceMapURL(aCopy.mSourceMapURL),
|
||||
mSourceMapURLFromComment(aCopy.mSourceMapURLFromComment),
|
||||
mSourceURL(aCopy.mSourceURL),
|
||||
|
@ -412,6 +410,8 @@ void StyleSheet::GetTitle(nsAString& aTitle) {
|
|||
}
|
||||
|
||||
void StyleSheet::WillDirty() {
|
||||
MOZ_ASSERT(!IsReadOnly());
|
||||
|
||||
if (IsComplete()) {
|
||||
EnsureUniqueInner();
|
||||
}
|
||||
|
@ -433,6 +433,12 @@ void StyleSheet::DropStyleSet(ServoStyleSet* aStyleSet) {
|
|||
|
||||
void StyleSheet::EnsureUniqueInner() {
|
||||
MOZ_ASSERT(mInner->mSheets.Length() != 0, "unexpected number of outers");
|
||||
|
||||
if (IsReadOnly()) {
|
||||
// Sheets that can't be modified don't need a unique inner.
|
||||
return;
|
||||
}
|
||||
|
||||
mState |= State::ForcedUniqueInner;
|
||||
|
||||
if (HasUniqueInner()) {
|
||||
|
@ -504,6 +510,9 @@ css::Rule* StyleSheet::GetDOMOwnerRule() const { return mOwnerRule; }
|
|||
uint32_t StyleSheet::InsertRule(const nsAString& aRule, uint32_t aIndex,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aRv) {
|
||||
if (IsReadOnly()) {
|
||||
return 0;
|
||||
}
|
||||
if (!AreRulesAvailable(aSubjectPrincipal, aRv)) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -512,6 +521,9 @@ uint32_t StyleSheet::InsertRule(const nsAString& aRule, uint32_t aIndex,
|
|||
|
||||
void StyleSheet::DeleteRule(uint32_t aIndex, nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aRv) {
|
||||
if (IsReadOnly()) {
|
||||
return;
|
||||
}
|
||||
if (!AreRulesAvailable(aSubjectPrincipal, aRv)) {
|
||||
return;
|
||||
}
|
||||
|
@ -530,6 +542,10 @@ nsresult StyleSheet::DeleteRuleFromGroup(css::GroupRule* aGroup,
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
WillDirty();
|
||||
|
||||
nsresult result = aGroup->DeleteStyleRuleAt(aIndex);
|
||||
|
@ -601,6 +617,10 @@ nsresult StyleSheet::InsertRuleIntoGroup(const nsAString& aRule,
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
WillDirty();
|
||||
|
||||
nsresult result = InsertRuleIntoGroupInternal(aRule, aGroup, aIndex);
|
||||
|
@ -729,6 +749,7 @@ void StyleSheet::PrependStyleSheet(StyleSheet* aSheet) {
|
|||
|
||||
void StyleSheet::PrependStyleSheetSilently(StyleSheet* aSheet) {
|
||||
MOZ_ASSERT(aSheet);
|
||||
MOZ_ASSERT(!IsReadOnly());
|
||||
|
||||
aSheet->mNext = Inner().mFirstChild;
|
||||
Inner().mFirstChild = aSheet;
|
||||
|
@ -995,8 +1016,8 @@ nsresult StyleSheet::ReparseSheet(const nsAString& aInput) {
|
|||
// Allowing to modify UA sheets is dangerous (in the sense that C++ code
|
||||
// relies on rules in those sheets), plus they're probably going to be shared
|
||||
// across processes in which case this is directly a no-go.
|
||||
if (GetOrigin() == StyleOrigin::UserAgent) {
|
||||
return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
|
||||
if (IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Hold strong ref to the CSSLoader in case the document update
|
||||
|
@ -1133,6 +1154,8 @@ ServoCSSRuleList* StyleSheet::GetCssRulesInternal() {
|
|||
|
||||
uint32_t StyleSheet::InsertRuleInternal(const nsAString& aRule, uint32_t aIndex,
|
||||
ErrorResult& aRv) {
|
||||
MOZ_ASSERT(!IsReadOnly());
|
||||
|
||||
// Ensure mRuleList is constructed.
|
||||
GetCssRulesInternal();
|
||||
|
||||
|
@ -1153,6 +1176,8 @@ uint32_t StyleSheet::InsertRuleInternal(const nsAString& aRule, uint32_t aIndex,
|
|||
}
|
||||
|
||||
void StyleSheet::DeleteRuleInternal(uint32_t aIndex, ErrorResult& aRv) {
|
||||
MOZ_ASSERT(!IsReadOnly());
|
||||
|
||||
// Ensure mRuleList is constructed.
|
||||
GetCssRulesInternal();
|
||||
if (aIndex >= mRuleList->Length()) {
|
||||
|
@ -1175,6 +1200,8 @@ void StyleSheet::DeleteRuleInternal(uint32_t aIndex, ErrorResult& aRv) {
|
|||
nsresult StyleSheet::InsertRuleIntoGroupInternal(const nsAString& aRule,
|
||||
css::GroupRule* aGroup,
|
||||
uint32_t aIndex) {
|
||||
MOZ_ASSERT(!IsReadOnly());
|
||||
|
||||
auto rules = static_cast<ServoCSSRuleList*>(aGroup->CssRules());
|
||||
MOZ_ASSERT(rules->GetParentRule() == aGroup);
|
||||
return rules->InsertRule(aRule, aIndex);
|
||||
|
@ -1215,4 +1242,8 @@ const ServoCssRules* StyleSheet::ToShared(
|
|||
return Servo_SharedMemoryBuilder_AddStylesheet(aBuilder, Inner().mContents);
|
||||
}
|
||||
|
||||
bool StyleSheet::IsReadOnly() const {
|
||||
return IsComplete() && GetOrigin() == StyleOrigin::UserAgent;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -32,7 +32,6 @@ namespace mozilla {
|
|||
|
||||
class ServoCSSRuleList;
|
||||
class ServoStyleSet;
|
||||
enum class OriginFlags : uint8_t;
|
||||
|
||||
typedef MozPromise</* Dummy */ bool,
|
||||
/* Dummy */ bool,
|
||||
|
@ -140,7 +139,7 @@ class StyleSheet final : public nsICSSLoaderObserver, public nsWrapperCache {
|
|||
// completeness check.
|
||||
ServoCSSRuleList* GetCssRulesInternal();
|
||||
|
||||
// Returns the stylesheet's Servo origin as an OriginFlags value.
|
||||
// Returns the stylesheet's Servo origin as a StyleOrigin value.
|
||||
mozilla::StyleOrigin GetOrigin() const;
|
||||
|
||||
/**
|
||||
|
@ -389,6 +388,11 @@ class StyleSheet final : public nsICSSLoaderObserver, public nsWrapperCache {
|
|||
void SetSharedContents(nsLayoutStylesheetCacheShm* aSharedMemory,
|
||||
const ServoCssRules* aSharedRules);
|
||||
|
||||
// Whether this style sheet should not allow any modifications.
|
||||
//
|
||||
// This is true for any User Agent sheets once they are complete.
|
||||
bool IsReadOnly() const;
|
||||
|
||||
private:
|
||||
dom::ShadowRoot* GetContainingShadow() const;
|
||||
|
||||
|
|
|
@ -50,6 +50,10 @@ nsresult nsDOMCSSDeclaration::GetPropertyValue(const nsCSSPropertyID aPropID,
|
|||
nsresult nsDOMCSSDeclaration::SetPropertyValue(
|
||||
const nsCSSPropertyID aPropID, const nsAString& aValue,
|
||||
nsIPrincipal* aSubjectPrincipal) {
|
||||
if (IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
switch (aPropID) {
|
||||
case eCSSProperty_background_position:
|
||||
case eCSSProperty_background_position_x:
|
||||
|
@ -98,6 +102,10 @@ void nsDOMCSSDeclaration::GetCssText(nsAString& aCssText) {
|
|||
void nsDOMCSSDeclaration::SetCssText(const nsAString& aCssText,
|
||||
nsIPrincipal* aSubjectPrincipal,
|
||||
ErrorResult& aRv) {
|
||||
if (IsReadOnly()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't need to *do* anything with the old declaration, but we need
|
||||
// to ensure that it exists, or else SetCSSDeclaration may crash.
|
||||
RefPtr<DeclarationBlock> created;
|
||||
|
@ -179,6 +187,10 @@ nsDOMCSSDeclaration::SetProperty(const nsAString& aPropertyName,
|
|||
const nsAString& aValue,
|
||||
const nsAString& aPriority,
|
||||
nsIPrincipal* aSubjectPrincipal) {
|
||||
if (IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aValue.IsEmpty()) {
|
||||
// If the new value of the property is an empty string we remove the
|
||||
// property.
|
||||
|
@ -212,6 +224,10 @@ nsDOMCSSDeclaration::SetProperty(const nsAString& aPropertyName,
|
|||
NS_IMETHODIMP
|
||||
nsDOMCSSDeclaration::RemoveProperty(const nsAString& aPropertyName,
|
||||
nsAString& aReturn) {
|
||||
if (IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = GetPropertyValue(aPropertyName, aReturn);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return RemovePropertyInternal(aPropertyName);
|
||||
|
@ -279,6 +295,10 @@ nsresult nsDOMCSSDeclaration::ParsePropertyValue(
|
|||
bool aIsImportant, nsIPrincipal* aSubjectPrincipal) {
|
||||
AUTO_PROFILER_LABEL_CATEGORY_PAIR(LAYOUT_CSSParsing);
|
||||
|
||||
if (IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DeclarationBlockMutationClosure closure = {};
|
||||
MutationClosureData closureData;
|
||||
GetPropertyChangeClosure(&closure, &closureData);
|
||||
|
@ -298,6 +318,10 @@ nsresult nsDOMCSSDeclaration::ParseCustomPropertyValue(
|
|||
bool aIsImportant, nsIPrincipal* aSubjectPrincipal) {
|
||||
MOZ_ASSERT(nsCSSProps::IsCustomPropertyName(aPropertyName));
|
||||
|
||||
if (IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DeclarationBlockMutationClosure closure = {};
|
||||
MutationClosureData closureData;
|
||||
GetPropertyChangeClosure(&closure, &closureData);
|
||||
|
@ -316,6 +340,10 @@ nsresult nsDOMCSSDeclaration::ParseCustomPropertyValue(
|
|||
nsresult nsDOMCSSDeclaration::RemovePropertyInternal(nsCSSPropertyID aPropID) {
|
||||
DeclarationBlock* olddecl =
|
||||
GetOrCreateCSSDeclaration(eOperation_RemoveProperty, nullptr);
|
||||
if (IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!olddecl) {
|
||||
return NS_OK; // no decl, so nothing to remove
|
||||
}
|
||||
|
@ -340,6 +368,10 @@ nsresult nsDOMCSSDeclaration::RemovePropertyInternal(nsCSSPropertyID aPropID) {
|
|||
|
||||
nsresult nsDOMCSSDeclaration::RemovePropertyInternal(
|
||||
const nsAString& aPropertyName) {
|
||||
if (IsReadOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DeclarationBlock* olddecl =
|
||||
GetOrCreateCSSDeclaration(eOperation_RemoveProperty, nullptr);
|
||||
if (!olddecl) {
|
||||
|
|
|
@ -20,3 +20,8 @@ DocGroup* nsICSSDeclaration::GetDocGroup() {
|
|||
|
||||
return parentNode->GetDocGroup();
|
||||
}
|
||||
|
||||
bool nsICSSDeclaration::IsReadOnly() {
|
||||
mozilla::css::Rule* rule = GetParentRule();
|
||||
return rule && rule->IsReadOnly();
|
||||
}
|
||||
|
|
|
@ -100,6 +100,9 @@ class nsICSSDeclaration : public nsISupports, public nsWrapperCache {
|
|||
rv = RemoveProperty(aPropName, aRetval);
|
||||
}
|
||||
virtual mozilla::css::Rule* GetParentRule() = 0;
|
||||
|
||||
protected:
|
||||
bool IsReadOnly();
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsICSSDeclaration, NS_ICSSDECLARATION_IID)
|
||||
|
|
Загрузка…
Ссылка в новой задаче