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:
Cameron McCormack 2019-04-29 05:34:06 +00:00
Родитель 2ca1c8c765
Коммит e95797966a
29 изменённых файлов: 260 добавлений и 17 удалений

Просмотреть файл

@ -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)