diff --git a/mozilla/content/base/public/nsIStyleRuleProcessor.h b/mozilla/content/base/public/nsIStyleRuleProcessor.h index 81e321cbf4a..4e229c7437d 100644 --- a/mozilla/content/base/public/nsIStyleRuleProcessor.h +++ b/mozilla/content/base/public/nsIStyleRuleProcessor.h @@ -179,11 +179,9 @@ public: // populate rule node tree with nsIStyleRule* // rules are ordered, those with higher precedence are farthest from the root of the tree - NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData, - nsIAtom* aMedium) = 0; + NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData) = 0; - NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData, - nsIAtom* aMedium) = 0; + NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData) = 0; /** * Test whether style is dependent on content state. This test is @@ -193,7 +191,6 @@ public: * Event states are defined in nsIEventStateManager.h. */ NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult) = 0; /** @@ -202,7 +199,6 @@ public: * the side of reporting more dependencies than really exist. */ NS_IMETHOD HasAttributeDependentStyle(AttributeRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult) = 0; }; diff --git a/mozilla/content/base/src/nsStyleSet.cpp b/mozilla/content/base/src/nsStyleSet.cpp index 9996055333e..cb87d487f43 100644 --- a/mozilla/content/base/src/nsStyleSet.cpp +++ b/mozilla/content/base/src/nsStyleSet.cpp @@ -329,23 +329,13 @@ nsStyleSet::EnableQuirkStyleSheet(PRBool aEnable) } } -struct RulesMatchingData : public ElementRuleProcessorData { - RulesMatchingData(nsPresContext* aPresContext, - nsIContent* aContent, - nsRuleWalker* aRuleWalker) - : ElementRuleProcessorData(aPresContext, aContent, aRuleWalker), - mMedium(aPresContext->Medium()) - { - } - nsIAtom* mMedium; -}; - static PRBool EnumRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData) { - RulesMatchingData* data = (RulesMatchingData*)aData; + ElementRuleProcessorData* data = + NS_STATIC_CAST(ElementRuleProcessorData*, aData); - aProcessor->RulesMatching(data, data->mMedium); + aProcessor->RulesMatching(data); return PR_TRUE; } @@ -588,7 +578,7 @@ nsStyleSet::ResolveStyleFor(nsIContent* aContent, mRuleProcessors[eDocSheet] || mRuleProcessors[eStyleAttrSheet] || mRuleProcessors[eOverrideSheet]) { - RulesMatchingData data(presContext, aContent, mRuleWalker); + ElementRuleProcessorData data(presContext, aContent, mRuleWalker); FileRules(EnumRulesMatching, &data); result = GetContext(presContext, aParentContext, nsnull).get(); @@ -624,26 +614,13 @@ nsStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext) } -struct PseudoRulesMatchingData : public PseudoRuleProcessorData { - PseudoRulesMatchingData(nsPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsICSSPseudoComparator* aComparator, - nsRuleWalker* aRuleWalker) - : PseudoRuleProcessorData(aPresContext, aParentContent, aPseudoTag, - aComparator, aRuleWalker), - mMedium(aPresContext->Medium()) - { - } - nsIAtom* mMedium; -}; - static PRBool EnumPseudoRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData) { - PseudoRulesMatchingData* data = (PseudoRulesMatchingData*)aData; + PseudoRuleProcessorData* data = + NS_STATIC_CAST(PseudoRuleProcessorData*, aData); - aProcessor->RulesMatching(data, data->mMedium); + aProcessor->RulesMatching(data); return PR_TRUE; } @@ -669,7 +646,7 @@ nsStyleSet::ResolvePseudoStyleFor(nsIContent* aParentContent, mRuleProcessors[eDocSheet] || mRuleProcessors[eStyleAttrSheet] || mRuleProcessors[eOverrideSheet]) { - PseudoRulesMatchingData data(presContext, aParentContent, aPseudoTag, + PseudoRuleProcessorData data(presContext, aParentContent, aPseudoTag, aComparator, mRuleWalker); FileRules(EnumPseudoRulesMatching, &data); @@ -704,7 +681,7 @@ nsStyleSet::ProbePseudoStyleFor(nsIContent* aParentContent, mRuleProcessors[eDocSheet] || mRuleProcessors[eStyleAttrSheet] || mRuleProcessors[eOverrideSheet]) { - PseudoRulesMatchingData data(presContext, aParentContent, aPseudoTag, + PseudoRuleProcessorData data(presContext, aParentContent, aPseudoTag, nsnull, mRuleWalker); FileRules(EnumPseudoRulesMatching, &data); @@ -831,10 +808,8 @@ struct StatefulData : public StateRuleProcessorData { StatefulData(nsPresContext* aPresContext, nsIContent* aContent, PRInt32 aStateMask) : StateRuleProcessorData(aPresContext, aContent, aStateMask), - mMedium(aPresContext->Medium()), mHint(nsReStyleHint(0)) {} - nsIAtom* mMedium; nsReStyleHint mHint; }; @@ -843,7 +818,7 @@ static PRBool SheetHasStatefulStyle(nsIStyleRuleProcessor* aProcessor, { StatefulData* data = (StatefulData*)aData; nsReStyleHint hint; - aProcessor->HasStateDependentStyle(data, data->mMedium, &hint); + aProcessor->HasStateDependentStyle(data, &hint); data->mHint = nsReStyleHint(data->mHint | hint); return PR_TRUE; // continue } @@ -876,10 +851,8 @@ struct AttributeData : public AttributeRuleProcessorData { AttributeData(nsPresContext* aPresContext, nsIContent* aContent, nsIAtom* aAttribute, PRInt32 aModType) : AttributeRuleProcessorData(aPresContext, aContent, aAttribute, aModType), - mMedium(aPresContext->Medium()), mHint(nsReStyleHint(0)) {} - nsIAtom* mMedium; nsReStyleHint mHint; }; @@ -888,7 +861,7 @@ SheetHasAttributeStyle(nsIStyleRuleProcessor* aProcessor, void *aData) { AttributeData* data = (AttributeData*)aData; nsReStyleHint hint; - aProcessor->HasAttributeDependentStyle(data, data->mMedium, &hint); + aProcessor->HasAttributeDependentStyle(data, &hint); data->mHint = nsReStyleHint(data->mHint | hint); return PR_TRUE; // continue } diff --git a/mozilla/content/html/style/src/Makefile.in b/mozilla/content/html/style/src/Makefile.in index afe1593461b..3ffd7e067f6 100644 --- a/mozilla/content/html/style/src/Makefile.in +++ b/mozilla/content/html/style/src/Makefile.in @@ -101,7 +101,6 @@ EXPORTS = \ nsICSSStyleRule.h \ nsICSSStyleRuleDOMWrapper.h \ nsICSSImportRule.h \ - nsICSSMediaRule.h \ nsICSSNameSpaceRule.h \ nsCSSStruct.h \ nsICSSOMFactory.h \ diff --git a/mozilla/content/html/style/src/nsCSSParser.cpp b/mozilla/content/html/style/src/nsCSSParser.cpp index 0bf45141ed3..e029905f956 100644 --- a/mozilla/content/html/style/src/nsCSSParser.cpp +++ b/mozilla/content/html/style/src/nsCSSParser.cpp @@ -45,7 +45,7 @@ #include "nsICSSLoader.h" #include "nsICSSStyleRule.h" #include "nsICSSImportRule.h" -#include "nsICSSMediaRule.h" +#include "nsCSSRules.h" #include "nsICSSNameSpaceRule.h" #include "nsIUnicharInputStream.h" #include "nsICSSStyleSheet.h" @@ -151,13 +151,16 @@ protected: PRBool ParseAtRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData); PRBool ParseCharsetRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData); PRBool ParseImportRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData); + PRBool GatherURL(nsresult& aErrorCode, nsString& aURL); PRBool GatherMedia(nsresult& aErrorCode, nsISupportsArray* aMediaAtoms); PRBool ProcessImport(nsresult& aErrorCode, const nsString& aURLSpec, nsISupportsArray* aMedia, RuleAppendFunc aAppendFunc, void* aProcessData); + PRBool ParseGroupRule(nsresult& aErrorCode, nsICSSGroupRule* aRule, RuleAppendFunc aAppendFunc, void* aProcessData); PRBool ParseMediaRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData); + PRBool ParseMozDocumentRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData); PRBool ParseNameSpaceRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData); PRBool ProcessNameSpace(nsresult& aErrorCode, const nsString& aPrefix, const nsString& aURLSpec, RuleAppendFunc aAppendFunc, @@ -979,6 +982,12 @@ PRBool CSSParserImpl::ParseAtRule(nsresult& aErrorCode, RuleAppendFunc aAppendFu return PR_TRUE; } } + if (mToken.mIdent.LowerCaseEqualsLiteral("-moz-document")) { + if (ParseMozDocumentRule(aErrorCode, aAppendFunc, aData)) { + mSection = eCSSSection_General; + return PR_TRUE; + } + } if (mToken.mIdent.LowerCaseEqualsLiteral("font-face")) { if (ParseFontFaceRule(aErrorCode, aAppendFunc, aData)) { mSection = eCSSSection_General; @@ -1029,6 +1038,29 @@ PRBool CSSParserImpl::ParseCharsetRule(nsresult& aErrorCode, RuleAppendFunc aApp return PR_TRUE; } +PRBool CSSParserImpl::GatherURL(nsresult& aErrorCode, nsString& aURL) +{ + if (!GetToken(aErrorCode, PR_TRUE)) { + return PR_FALSE; + } + if (eCSSToken_String == mToken.mType) { + aURL = mToken.mIdent; + return PR_TRUE; + } + else if (eCSSToken_Function == mToken.mType && + mToken.mIdent.LowerCaseEqualsLiteral("url") && + ExpectSymbol(aErrorCode, '(', PR_FALSE) && + GetURLToken(aErrorCode, PR_TRUE) && + (eCSSToken_String == mToken.mType || + eCSSToken_URL == mToken.mType)) { + aURL = mToken.mIdent; + if (ExpectSymbol(aErrorCode, ')', PR_TRUE)) { + return PR_TRUE; + } + } + return PR_FALSE; +} + PRBool CSSParserImpl::GatherMedia(nsresult& aErrorCode, nsISupportsArray* aMediaAtoms) { @@ -1089,10 +1121,6 @@ PRBool CSSParserImpl::GatherMedia(nsresult& aErrorCode, // Parse a CSS2 import rule: "@import STRING | URL [medium [, mdeium]]" PRBool CSSParserImpl::ParseImportRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aData) { - if (!GetToken(aErrorCode, PR_TRUE)) { - REPORT_UNEXPECTED_EOF(NS_LITERAL_STRING("URI in @import rule")); - return PR_FALSE; - } nsAutoString url; nsCOMPtr media; aErrorCode = NS_NewISupportsArray(getter_AddRefs(media)); @@ -1100,38 +1128,23 @@ PRBool CSSParserImpl::ParseImportRule(nsresult& aErrorCode, RuleAppendFunc aAppe // Out of memory return PR_FALSE; } + + if (!GatherURL(aErrorCode, url)) { + REPORT_UNEXPECTED_TOKEN( + NS_LITERAL_STRING("Expected URI in @import rule but found")); + return PR_FALSE; + } - if (eCSSToken_String == mToken.mType) { - url = mToken.mIdent; - if (GatherMedia(aErrorCode, media)) { - if (ExpectSymbol(aErrorCode, ';', PR_TRUE)) { - ProcessImport(aErrorCode, url, media, aAppendFunc, aData); - return PR_TRUE; - } - } + if (!GatherMedia(aErrorCode, media) || + !ExpectSymbol(aErrorCode, ';', PR_TRUE)) { + REPORT_UNEXPECTED_TOKEN( + NS_LITERAL_STRING("Unexpected token within @import:")); + // don't advance section, simply ignore invalid @import + return PR_FALSE; } - else if ((eCSSToken_Function == mToken.mType) && - (mToken.mIdent.LowerCaseEqualsLiteral("url"))) { - if (ExpectSymbol(aErrorCode, '(', PR_FALSE)) { - if (GetURLToken(aErrorCode, PR_TRUE)) { - if ((eCSSToken_String == mToken.mType) || (eCSSToken_URL == mToken.mType)) { - url = mToken.mIdent; - if (ExpectSymbol(aErrorCode, ')', PR_TRUE)) { - if (GatherMedia(aErrorCode, media)) { - if (ExpectSymbol(aErrorCode, ';', PR_TRUE)) { - ProcessImport(aErrorCode, url, media, aAppendFunc, aData); - return PR_TRUE; - } - } - } - } - } - } - } - REPORT_UNEXPECTED_TOKEN( - NS_LITERAL_STRING("Unexpected token within @import:")); - // don't advance section, simply ignore invalid @import - return PR_FALSE; + + ProcessImport(aErrorCode, url, media, aAppendFunc, aData); + return PR_TRUE; } @@ -1165,8 +1178,55 @@ PRBool CSSParserImpl::ProcessImport(nsresult& aErrorCode, return PR_TRUE; } +// Parse the {} part of an @media or @-moz-document rule. +PRBool CSSParserImpl::ParseGroupRule(nsresult& aErrorCode, + nsICSSGroupRule* aRule, + RuleAppendFunc aAppendFunc, + void* aData) +{ + // XXXbz this could use better error reporting throughout the method + if (!ExpectSymbol(aErrorCode, '{', PR_TRUE)) { + return PR_FALSE; + } + + // push rule on stack, loop over children + if (!PushGroup(aRule)) { + aErrorCode = NS_ERROR_OUT_OF_MEMORY; + return PR_FALSE; + } + nsCSSSection holdSection = mSection; + mSection = eCSSSection_General; + + for (;;) { + // Get next non-whitespace token + if (! GetToken(aErrorCode, PR_TRUE)) { + REPORT_UNEXPECTED_EOF(NS_LITERAL_STRING("end of @media or @-moz-document rule")); + break; + } + if (mToken.IsSymbol('}')) { // done! + UngetToken(); + break; + } + if (eCSSToken_AtKeyword == mToken.mType) { + SkipAtRule(aErrorCode); // group rules cannot contain @rules + continue; + } + UngetToken(); + ParseRuleSet(aErrorCode, AppendRuleToSheet, this); + } + PopGroup(); + + if (!ExpectSymbol(aErrorCode, '}', PR_TRUE)) { + mSection = holdSection; + return PR_FALSE; + } + (*aAppendFunc)(aRule, aData); + return PR_TRUE; +} + // Parse a CSS2 media rule: "@media medium [, medium] { ... }" -PRBool CSSParserImpl::ParseMediaRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, +PRBool CSSParserImpl::ParseMediaRule(nsresult& aErrorCode, + RuleAppendFunc aAppendFunc, void* aData) { nsCOMPtr media; @@ -1176,48 +1236,13 @@ PRBool CSSParserImpl::ParseMediaRule(nsresult& aErrorCode, RuleAppendFunc aAppen // XXXbz this could use better error reporting throughout the method PRUint32 count; media->Count(&count); - if (count > 0 && - ExpectSymbol(aErrorCode, '{', PR_TRUE)) { - // push media rule on stack, loop over children - nsCOMPtr rule; - NS_NewCSSMediaRule(getter_AddRefs(rule)); - if (rule) { - if (PushGroup(rule)) { - - nsCSSSection holdSection = mSection; - mSection = eCSSSection_General; - - for (;;) { - // Get next non-whitespace token - if (! GetToken(aErrorCode, PR_TRUE)) { - REPORT_UNEXPECTED_EOF(NS_LITERAL_STRING("end of @media rule")); - break; - } - if (mToken.IsSymbol('}')) { // done! - UngetToken(); - break; - } - if (eCSSToken_AtKeyword == mToken.mType) { - SkipAtRule(aErrorCode); // @media cannot contain @rules - continue; - } - UngetToken(); - ParseRuleSet(aErrorCode, AppendRuleToSheet, this); - } - PopGroup(); - - if (ExpectSymbol(aErrorCode, '}', PR_TRUE)) { - // Append first, so when we do SetMedia() the rule - // knows what its stylesheet is. - (*aAppendFunc)(rule, aData); - rule->SetMedia(media); - return PR_TRUE; - } - mSection = holdSection; - } - } - else { // failed to create rule, backup and skip block - UngetToken(); + if (count > 0) { + nsRefPtr rule(new nsCSSMediaRule()); + // Append first, so when we do SetMedia() the rule + // knows what its stylesheet is. + if (rule && ParseGroupRule(aErrorCode, rule, aAppendFunc, aData)) { + rule->SetMedia(media); + return PR_TRUE; } } } @@ -1226,6 +1251,72 @@ PRBool CSSParserImpl::ParseMediaRule(nsresult& aErrorCode, RuleAppendFunc aAppen return PR_FALSE; } +// Parse a @-moz-document rule. This is like an @media rule, but instead +// of a medium it has a nonempty list of items where each item is either +// url(), url-prefix(), or domain(). +PRBool CSSParserImpl::ParseMozDocumentRule(nsresult& aErrorCode, + RuleAppendFunc aAppendFunc, + void* aData) +{ + nsCSSDocumentRule::URL *urls = nsnull; + nsCSSDocumentRule::URL **next = &urls; + do { + if (!GetToken(aErrorCode, PR_TRUE) || + eCSSToken_Function != mToken.mType || + !(mToken.mIdent.LowerCaseEqualsLiteral("url") || + mToken.mIdent.LowerCaseEqualsLiteral("url-prefix") || + mToken.mIdent.LowerCaseEqualsLiteral("domain"))) { + REPORT_UNEXPECTED_TOKEN( + NS_LITERAL_STRING("Expected url(), url-prefix(), or domain() in @-moz-document rule but found")); + delete urls; + return PR_FALSE; + } + nsCSSDocumentRule::URL *cur = *next = new nsCSSDocumentRule::URL; + if (!cur) { + aErrorCode = NS_ERROR_OUT_OF_MEMORY; + delete urls; + return PR_FALSE; + } + next = &cur->next; + if (mToken.mIdent.LowerCaseEqualsLiteral("url")) { + cur->func = nsCSSDocumentRule::eURL; + } else if (mToken.mIdent.LowerCaseEqualsLiteral("url-prefix")) { + cur->func = nsCSSDocumentRule::eURLPrefix; + } else if (mToken.mIdent.LowerCaseEqualsLiteral("domain")) { + cur->func = nsCSSDocumentRule::eDomain; + } + + if (!ExpectSymbol(aErrorCode, '(', PR_FALSE) || + !GetURLToken(aErrorCode, PR_TRUE) || + (eCSSToken_String != mToken.mType && + eCSSToken_URL != mToken.mType)) { + REPORT_UNEXPECTED_TOKEN( + NS_LITERAL_STRING("Expected URI in @-moz-document rule but found")); + delete urls; + return PR_FALSE; + } + if (!ExpectSymbol(aErrorCode, ')', PR_TRUE)) { + delete urls; + return PR_FALSE; + } + + // We could try to make the URL (as long as it's not domain()) + // canonical and absolute with NS_NewURI and GetSpec, but I'm + // inclined to think we shouldn't. + CopyUTF16toUTF8(mToken.mIdent, cur->url); + } while (ExpectSymbol(aErrorCode, ',', PR_TRUE)); + + nsRefPtr rule(new nsCSSDocumentRule()); + if (!rule) { + aErrorCode = NS_ERROR_OUT_OF_MEMORY; + delete urls; + return PR_FALSE; + } + rule->SetURLs(urls); + + return ParseGroupRule(aErrorCode, rule, aAppendFunc, aData); +} + // Parse a CSS3 namespace rule: "@namespace [prefix] STRING | URL;" PRBool CSSParserImpl::ParseNameSpaceRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, diff --git a/mozilla/content/html/style/src/nsCSSRule.cpp b/mozilla/content/html/style/src/nsCSSRule.cpp index 2253057ed8b..4e5eaadb807 100644 --- a/mozilla/content/html/style/src/nsCSSRule.cpp +++ b/mozilla/content/html/style/src/nsCSSRule.cpp @@ -60,13 +60,6 @@ nsCSSRule::~nsCSSRule(void) NS_IMPL_ADDREF(nsCSSRule) NS_IMPL_RELEASE(nsCSSRule) -NS_IMETHODIMP -nsCSSRule::QueryInterface(REFNSIID aIID, void** aInstancePtr) -{ - NS_NOTREACHED("nsCSSRule::QueryInterface"); - return NS_NOINTERFACE; -} - NS_IMETHODIMP nsCSSRule::GetStyleSheet(nsIStyleSheet*& aSheet) const { diff --git a/mozilla/content/html/style/src/nsCSSRule.h b/mozilla/content/html/style/src/nsCSSRule.h index 575987534b8..67142e00b6a 100644 --- a/mozilla/content/html/style/src/nsCSSRule.h +++ b/mozilla/content/html/style/src/nsCSSRule.h @@ -51,7 +51,13 @@ public: nsCSSRule(const nsCSSRule& aCopy); virtual ~nsCSSRule(void); - NS_DECL_ISUPPORTS + // for implementing nsISupports + nsrefcnt AddRef(); + nsrefcnt Release(); +protected: + nsAutoRefCnt mRefCnt; + NS_DECL_OWNINGTHREAD +public: NS_IMETHOD GetStyleSheet(nsIStyleSheet*& aSheet) const; NS_IMETHOD SetStyleSheet(nsICSSStyleSheet* aSheet); diff --git a/mozilla/content/html/style/src/nsCSSRuleProcessor.h b/mozilla/content/html/style/src/nsCSSRuleProcessor.h index 5e6c88ca1b3..c8cddf61e75 100644 --- a/mozilla/content/html/style/src/nsCSSRuleProcessor.h +++ b/mozilla/content/html/style/src/nsCSSRuleProcessor.h @@ -67,26 +67,22 @@ public: nsresult ClearRuleCascades(); // nsIStyleRuleProcessor - NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData, - nsIAtom* aMedium); + NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); - NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData, - nsIAtom* aMedium); + NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult); NS_IMETHOD HasAttributeDependentStyle(AttributeRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult); protected: - RuleCascadeData* GetRuleCascade(nsPresContext* aPresContext, nsIAtom* aMedium); + RuleCascadeData* GetRuleCascade(nsPresContext* aPresContext); nsCOMArray mSheets; - RuleCascadeData* mRuleCascades; + RuleCascadeData* mRuleCascades; }; #endif /* nsCSSRuleProcessor_h_ */ diff --git a/mozilla/content/html/style/src/nsCSSRules.cpp b/mozilla/content/html/style/src/nsCSSRules.cpp index d8375e310d1..6e03090eb70 100644 --- a/mozilla/content/html/style/src/nsCSSRules.cpp +++ b/mozilla/content/html/style/src/nsCSSRules.cpp @@ -35,8 +35,8 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ +#include "nsCSSRules.h" #include "nsICSSImportRule.h" -#include "nsICSSMediaRule.h" #include "nsICSSNameSpaceRule.h" #include "nsString.h" @@ -53,24 +53,19 @@ #include "nsIDOMCSSRule.h" #include "nsIDOMCSSImportRule.h" #include "nsIDOMCSSMediaRule.h" +#include "nsIDOMCSSMozDocumentRule.h" #include "nsIDOMCSSCharsetRule.h" #include "nsIMediaList.h" #include "nsIDOMMediaList.h" #include "nsIDOMCSSRuleList.h" #include "nsIDOMStyleSheet.h" #include "nsIDocument.h" +#include "nsPresContext.h" #include "nsContentUtils.h" #include "nsStyleConsts.h" #include "nsDOMError.h" -#define DECL_STYLE_RULE_INHERIT \ -NS_IMETHOD GetStyleSheet(nsIStyleSheet*& aSheet) const; \ -NS_IMETHOD SetStyleSheet(nsICSSStyleSheet* aSheet); \ -NS_IMETHOD SetParentRule(nsICSSGroupRule* aRule); \ -NS_IMETHOD GetDOMRule(nsIDOMCSSRule** aDOMRule); \ -NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData); - #define IMPL_STYLE_RULE_INHERIT(_class, super) \ NS_IMETHODIMP _class::GetStyleSheet(nsIStyleSheet*& aSheet) const { return super::GetStyleSheet(aSheet); } \ NS_IMETHODIMP _class::SetStyleSheet(nsICSSStyleSheet* aSheet) { return super::SetStyleSheet(aSheet); } \ @@ -625,61 +620,9 @@ CSSImportRuleImpl::GetStyleSheet(nsIDOMCSSStyleSheet * *aStyleSheet) return CallQueryInterface(mChildSheet, aStyleSheet); } -// ------------------------------------------- -// nsICSSMediaRule -// -class CSSMediaRuleImpl : public nsCSSRule, - public nsICSSMediaRule, - public nsIDOMCSSMediaRule -{ -public: - CSSMediaRuleImpl(void); - CSSMediaRuleImpl(const CSSMediaRuleImpl& aCopy); - virtual ~CSSMediaRuleImpl(void); - - NS_DECL_ISUPPORTS_INHERITED - - DECL_STYLE_RULE_INHERIT - - // nsIStyleRule methods -#ifdef DEBUG - NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const; -#endif - - // nsICSSRule methods - NS_IMETHOD GetType(PRInt32& aType) const; - NS_IMETHOD Clone(nsICSSRule*& aClone) const; - - // nsICSSMediaRule methods - NS_IMETHOD SetMedia(nsISupportsArray* aMedia); - NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const; - - // nsICSSGroupRule methods - NS_IMETHOD AppendStyleRule(nsICSSRule* aRule); - NS_IMETHOD StyleRuleCount(PRInt32& aCount) const; - NS_IMETHOD GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const; - NS_IMETHOD EnumerateRulesForwards(nsISupportsArrayEnumFunc aFunc, void * aData) const; - NS_IMETHOD DeleteStyleRuleAt(PRUint32 aIndex); - NS_IMETHOD InsertStyleRulesAt(PRUint32 aIndex, nsISupportsArray* aRules); - NS_IMETHOD ReplaceStyleRule(nsICSSRule *aOld, nsICSSRule *aNew); - - // nsIDOMCSSRule interface - NS_DECL_NSIDOMCSSRULE - - // nsIDOMCSSMediaRule interface - NS_DECL_NSIDOMCSSMEDIARULE - -protected: - nsCOMPtr mMedia; - nsCOMPtr mRules; - CSSGroupRuleRuleListImpl* mRuleCollection; -}; - -CSSMediaRuleImpl::CSSMediaRuleImpl(void) - : nsCSSRule(), - mMedia(nsnull), - mRules(nsnull), - mRuleCollection(nsnull) +nsCSSGroupRule::nsCSSGroupRule() + : nsCSSRule() + , mRuleCollection(nsnull) { } @@ -700,37 +643,27 @@ CloneRuleInto(nsISupports* aRule, void* aArray) static PRBool SetParentRuleReference(nsISupports* aRule, void* aParentRule) { - nsICSSRule* rule = (nsICSSRule*)aRule; - nsICSSGroupRule* parentRule = (nsICSSGroupRule*)aParentRule; + nsICSSRule* rule = NS_STATIC_CAST(nsICSSRule*, aRule); + nsCSSGroupRule* parentRule = NS_STATIC_CAST(nsCSSGroupRule*, aParentRule); rule->SetParentRule(parentRule); return PR_TRUE; } -CSSMediaRuleImpl::CSSMediaRuleImpl(const CSSMediaRuleImpl& aCopy) - : nsCSSRule(aCopy), - mMedia(nsnull), - mRules(nsnull), - mRuleCollection(nsnull) +nsCSSGroupRule::nsCSSGroupRule(const nsCSSGroupRule& aCopy) + : nsCSSRule(aCopy) + , mRuleCollection(nsnull) // lazily constructed { - if (aCopy.mMedia) { - NS_NewMediaList(aCopy.mMedia, aCopy.mSheet, getter_AddRefs(mMedia)); - } - if (aCopy.mRules) { NS_NewISupportsArray(getter_AddRefs(mRules)); if (mRules) { aCopy.mRules->EnumerateForwards(CloneRuleInto, mRules); - mRules->EnumerateForwards(SetParentRuleReference, - NS_STATIC_CAST(nsICSSGroupRule*, this)); + mRules->EnumerateForwards(SetParentRuleReference, this); } } } -CSSMediaRuleImpl::~CSSMediaRuleImpl(void) +nsCSSGroupRule::~nsCSSGroupRule() { - if (mMedia) { - mMedia->DropReference(); - } if (mRules) { mRules->EnumerateForwards(SetParentRuleReference, nsnull); } @@ -740,21 +673,7 @@ CSSMediaRuleImpl::~CSSMediaRuleImpl(void) } } -NS_IMPL_ADDREF_INHERITED(CSSMediaRuleImpl, nsCSSRule) -NS_IMPL_RELEASE_INHERITED(CSSMediaRuleImpl, nsCSSRule) - -// QueryInterface implementation for CSSMediaRuleImpl -NS_INTERFACE_MAP_BEGIN(CSSMediaRuleImpl) - NS_INTERFACE_MAP_ENTRY(nsICSSMediaRule) - NS_INTERFACE_MAP_ENTRY(nsICSSRule) - NS_INTERFACE_MAP_ENTRY(nsIStyleRule) - NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) - NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMediaRule) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICSSMediaRule) - NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSMediaRule) -NS_INTERFACE_MAP_END - -IMPL_STYLE_RULE_INHERIT2(CSSMediaRuleImpl, nsCSSRule) +IMPL_STYLE_RULE_INHERIT2(nsCSSGroupRule, nsCSSRule) static PRBool SetStyleSheetReference(nsISupports* aRule, void* aSheet) @@ -766,11 +685,279 @@ SetStyleSheetReference(nsISupports* aRule, void* aSheet) } NS_IMETHODIMP -CSSMediaRuleImpl::SetStyleSheet(nsICSSStyleSheet* aSheet) +nsCSSGroupRule::SetStyleSheet(nsICSSStyleSheet* aSheet) { if (mRules) { mRules->EnumerateForwards(SetStyleSheetReference, aSheet); } + + return nsCSSRule::SetStyleSheet(aSheet); +} + +#ifdef DEBUG +nsresult +nsCSSGroupRule::List(FILE* out, PRInt32 aIndent) const +{ + fputs(" {\n", out); + + if (mRules) { + PRUint32 index = 0; + PRUint32 count; + mRules->Count(&count); + while (index < count) { + nsCOMPtr rule = dont_AddRef((nsICSSRule*)mRules->ElementAt(index++)); + rule->List(out, aIndent + 1); + } + } + fputs("}\n", out); + return NS_OK; +} +#endif + +NS_IMETHODIMP +nsCSSGroupRule::AppendStyleRule(nsICSSRule* aRule) +{ + nsresult result = NS_OK; + if (!mRules) { + result = NS_NewISupportsArray(getter_AddRefs(mRules)); + } + if (NS_SUCCEEDED(result) && mRules) { + mRules->AppendElement(aRule); + aRule->SetStyleSheet(mSheet); + aRule->SetParentRule(this); + if (mSheet) { + // XXXldb Shouldn't we be using |WillDirty| and |DidDirty| (and + // shouldn't |SetModified| be removed? + mSheet->SetModified(PR_TRUE); + } + } + return result; +} + +NS_IMETHODIMP +nsCSSGroupRule::StyleRuleCount(PRInt32& aCount) const +{ + if (mRules) { + PRUint32 count; + mRules->Count(&count); + aCount = (PRInt32)count; + } + else { + aCount = 0; + } + return NS_OK; +} + +NS_IMETHODIMP +nsCSSGroupRule::GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const +{ + if (mRules) { + PRInt32 count = 0; + nsresult rv = StyleRuleCount(count); + NS_ENSURE_SUCCESS(rv, rv); + if (aIndex >= count) { + aRule = nsnull; + return NS_ERROR_ILLEGAL_VALUE; + } + aRule = (nsICSSRule*)mRules->ElementAt(aIndex); + return NS_OK; + } + return NS_ERROR_ILLEGAL_VALUE; +} + +NS_IMETHODIMP +nsCSSGroupRule::EnumerateRulesForwards(nsISupportsArrayEnumFunc aFunc, void * aData) const +{ + if (mRules) { + return ((mRules->EnumerateForwards(aFunc, aData)) ? NS_OK : NS_ENUMERATOR_FALSE); + } + return NS_OK; +} + +/* + * The next two methods (DeleteStyleRuleAt and InsertStyleRulesAt) + * should never be called unless you have first called WillDirty() on + * the parents tylesheet. After they are called, DidDirty() needs to + * be called on the sheet + */ +NS_IMETHODIMP +nsCSSGroupRule::DeleteStyleRuleAt(PRUint32 aIndex) +{ + NS_ENSURE_TRUE(mRules, NS_ERROR_FAILURE); + + nsCOMPtr rule = dont_AddRef((nsICSSRule*)mRules->ElementAt(aIndex)); + if (rule) { + rule->SetStyleSheet(nsnull); + rule->SetParentRule(nsnull); + } + return mRules->DeleteElementAt(aIndex); +} + +NS_IMETHODIMP +nsCSSGroupRule::InsertStyleRulesAt(PRUint32 aIndex, nsISupportsArray* aRules) +{ + NS_ENSURE_TRUE(mRules, NS_ERROR_FAILURE); + + aRules->EnumerateForwards(SetStyleSheetReference, mSheet); + aRules->EnumerateForwards(SetParentRuleReference, this); + // There is no xpcom-compatible version of InsertElementsAt.... :( + if (! mRules->InsertElementsAt(aRules, aIndex)) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +NS_IMETHODIMP +nsCSSGroupRule::ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew) +{ + PRInt32 index = mRules->IndexOf(aOld); + NS_ENSURE_TRUE(index != -1, NS_ERROR_UNEXPECTED); + mRules->ReplaceElementAt(aNew, index); + aNew->SetStyleSheet(mSheet); + aNew->SetParentRule(this); + aOld->SetStyleSheet(nsnull); + aOld->SetParentRule(nsnull); + return NS_OK; +} + +nsresult +nsCSSGroupRule::AppendRulesToCssText(nsAString& aCssText) +{ + aCssText.AppendLiteral(" {\n"); + + // get all the rules + if (mRules) { + PRUint32 count; + mRules->Count(&count); + for (PRUint32 index = 0; index < count; index++) { + nsCOMPtr rule; + mRules->GetElementAt(index, getter_AddRefs(rule)); + nsCOMPtr domRule; + rule->GetDOMRule(getter_AddRefs(domRule)); + if (domRule) { + nsAutoString cssText; + domRule->GetCssText(cssText); + aCssText.Append(NS_LITERAL_STRING(" ") + + cssText + + NS_LITERAL_STRING("\n")); + } + } + } + + aCssText.AppendLiteral("}"); + + return NS_OK; +} + +nsresult +nsCSSGroupRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) +{ + if (mSheet) { + return CallQueryInterface(mSheet, aSheet); + } + *aSheet = nsnull; + return NS_OK; +} + +nsresult +nsCSSGroupRule::GetParentRule(nsIDOMCSSRule** aParentRule) +{ + if (mParentRule) { + return mParentRule->GetDOMRule(aParentRule); + } + *aParentRule = nsnull; + return NS_OK; +} + +// nsIDOMCSSMediaRule or nsIDOMCSSMozDocumentRule methods +nsresult +nsCSSGroupRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList) +{ + if (!mRuleCollection) { + mRuleCollection = new CSSGroupRuleRuleListImpl(this); + if (!mRuleCollection) { + return NS_ERROR_OUT_OF_MEMORY; + } + NS_ADDREF(mRuleCollection); + } + + return CallQueryInterface(mRuleCollection, aRuleList); +} + +nsresult +nsCSSGroupRule::InsertRule(const nsAString & aRule, PRUint32 aIndex, PRUint32* _retval) +{ + NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE); + + if (!mRules) { + nsresult rv = NS_NewISupportsArray(getter_AddRefs(mRules)); + if (NS_FAILED(rv)) + return rv; + } + + PRUint32 count; + mRules->Count(&count); + if (aIndex > count) + return NS_ERROR_DOM_INDEX_SIZE_ERR; + + return mSheet->InsertRuleIntoGroup(aRule, this, aIndex, _retval); +} + +nsresult +nsCSSGroupRule::DeleteRule(PRUint32 aIndex) +{ + NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE); + if (!mRules) { + return NS_ERROR_DOM_INDEX_SIZE_ERR; + } + + PRUint32 count; + mRules->Count(&count); + if (aIndex >= count) + return NS_ERROR_DOM_INDEX_SIZE_ERR; + + return mSheet->DeleteRuleFromGroup(this, aIndex); +} + +// ------------------------------------------- +// nsICSSMediaRule +// +nsCSSMediaRule::nsCSSMediaRule() +{ +} + +nsCSSMediaRule::nsCSSMediaRule(const nsCSSMediaRule& aCopy) + : nsCSSGroupRule(aCopy) +{ + if (aCopy.mMedia) { + NS_NewMediaList(aCopy.mMedia, aCopy.mSheet, getter_AddRefs(mMedia)); + } +} + +nsCSSMediaRule::~nsCSSMediaRule() +{ + if (mMedia) { + mMedia->DropReference(); + } +} + +NS_IMPL_ADDREF_INHERITED(nsCSSMediaRule, nsCSSRule) +NS_IMPL_RELEASE_INHERITED(nsCSSMediaRule, nsCSSRule) + +// QueryInterface implementation for nsCSSMediaRule +NS_INTERFACE_MAP_BEGIN(nsCSSMediaRule) + NS_INTERFACE_MAP_ENTRY(nsICSSGroupRule) + NS_INTERFACE_MAP_ENTRY(nsICSSRule) + NS_INTERFACE_MAP_ENTRY(nsIStyleRule) + NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) + NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMediaRule) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsCSSGroupRule) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSMediaRule) +NS_INTERFACE_MAP_END + +NS_IMETHODIMP +nsCSSMediaRule::SetStyleSheet(nsICSSStyleSheet* aSheet) +{ if (mMedia) { nsresult rv; nsCOMPtr oldMedia(do_QueryInterface(mMedia, &rv)); @@ -782,12 +969,12 @@ CSSMediaRuleImpl::SetStyleSheet(nsICSSStyleSheet* aSheet) return rv; } - return nsCSSRule::SetStyleSheet(aSheet); + return nsCSSGroupRule::SetStyleSheet(aSheet); } #ifdef DEBUG NS_IMETHODIMP -CSSMediaRuleImpl::List(FILE* out, PRInt32 aIndent) const +nsCSSMediaRule::List(FILE* out, PRInt32 aIndent) const { for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out); @@ -808,33 +995,22 @@ CSSMediaRuleImpl::List(FILE* out, PRInt32 aIndent) const } } } - fputs(" {\n", out); - if (mRules) { - PRUint32 index = 0; - PRUint32 count; - mRules->Count(&count); - while (index < count) { - nsCOMPtr rule = dont_AddRef((nsICSSRule*)mRules->ElementAt(index++)); - rule->List(out, aIndent + 1); - } - } - fputs("}\n", out); - return NS_OK; + return nsCSSGroupRule::List(out, aIndent); } #endif NS_IMETHODIMP -CSSMediaRuleImpl::GetType(PRInt32& aType) const +nsCSSMediaRule::GetType(PRInt32& aType) const { aType = nsICSSRule::MEDIA_RULE; return NS_OK; } NS_IMETHODIMP -CSSMediaRuleImpl::Clone(nsICSSRule*& aClone) const +nsCSSMediaRule::Clone(nsICSSRule*& aClone) const { - CSSMediaRuleImpl* clone = new CSSMediaRuleImpl(*this); + nsCSSMediaRule* clone = new nsCSSMediaRule(*this); if (clone) { return CallQueryInterface(clone, &aClone); } @@ -842,157 +1018,22 @@ CSSMediaRuleImpl::Clone(nsICSSRule*& aClone) const return NS_ERROR_OUT_OF_MEMORY; } -// nsICSSMediaRule methods -NS_IMETHODIMP -CSSMediaRuleImpl::SetMedia(nsISupportsArray* aMedia) +nsresult +nsCSSMediaRule::SetMedia(nsISupportsArray* aMedia) { return NS_NewMediaList(aMedia, mSheet, getter_AddRefs(mMedia)); } -NS_IMETHODIMP_(PRBool) -CSSMediaRuleImpl::UseForMedium(nsIAtom* aMedium) const -{ - if (mMedia) { - PRBool matches = PR_FALSE; - mMedia->MatchesMedium(aMedium, &matches); - return matches; - } - return PR_TRUE; -} - -NS_IMETHODIMP -CSSMediaRuleImpl::AppendStyleRule(nsICSSRule* aRule) -{ - nsresult result = NS_OK; - if (!mRules) { - result = NS_NewISupportsArray(getter_AddRefs(mRules)); - } - if (NS_SUCCEEDED(result) && mRules) { - mRules->AppendElement(aRule); - aRule->SetStyleSheet(mSheet); - aRule->SetParentRule(this); - if (mSheet) { - // XXXldb Shouldn't we be using |WillDirty| and |DidDirty| (and - // shouldn't |SetModified| be removed? - mSheet->SetModified(PR_TRUE); - } - } - return result; -} - -NS_IMETHODIMP -CSSMediaRuleImpl::StyleRuleCount(PRInt32& aCount) const -{ - if (mRules) { - PRUint32 count; - mRules->Count(&count); - aCount = (PRInt32)count; - } - else { - aCount = 0; - } - return NS_OK; -} - -NS_IMETHODIMP -CSSMediaRuleImpl::GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const -{ - if (mRules) { - PRInt32 count = 0; - nsresult rv = StyleRuleCount(count); - NS_ENSURE_SUCCESS(rv, rv); - if (aIndex >= count) { - aRule = nsnull; - return NS_ERROR_ILLEGAL_VALUE; - } - aRule = (nsICSSRule*)mRules->ElementAt(aIndex); - return NS_OK; - } - return NS_ERROR_ILLEGAL_VALUE; -} - -NS_IMETHODIMP -CSSMediaRuleImpl::EnumerateRulesForwards(nsISupportsArrayEnumFunc aFunc, void * aData) const -{ - if (mRules) { - return ((mRules->EnumerateForwards(aFunc, aData)) ? NS_OK : NS_ENUMERATOR_FALSE); - } - return NS_OK; -} - -/* - * The next two methods (DeleteStyleRuleAt and InsertStyleRulesAt) - * should never be called unless you have first called WillDirty() on - * the parents tylesheet. After they are called, DidDirty() needs to - * be called on the sheet - */ -NS_IMETHODIMP -CSSMediaRuleImpl::DeleteStyleRuleAt(PRUint32 aIndex) -{ - NS_ENSURE_TRUE(mRules, NS_ERROR_FAILURE); - - nsCOMPtr rule = dont_AddRef((nsICSSRule*)mRules->ElementAt(aIndex)); - if (rule) { - rule->SetStyleSheet(nsnull); - rule->SetParentRule(nsnull); - } - return mRules->DeleteElementAt(aIndex); -} - -NS_IMETHODIMP -CSSMediaRuleImpl::InsertStyleRulesAt(PRUint32 aIndex, nsISupportsArray* aRules) -{ - NS_ENSURE_TRUE(mRules, NS_ERROR_FAILURE); - - aRules->EnumerateForwards(SetStyleSheetReference, mSheet); - aRules->EnumerateForwards(SetParentRuleReference, - NS_STATIC_CAST(nsICSSGroupRule*, this)); - // There is no xpcom-compatible version of InsertElementsAt.... :( - if (! mRules->InsertElementsAt(aRules, aIndex)) { - return NS_ERROR_FAILURE; - } - return NS_OK; -} - -NS_IMETHODIMP -CSSMediaRuleImpl::ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew) -{ - PRInt32 index = mRules->IndexOf(aOld); - NS_ENSURE_TRUE(index != -1, NS_ERROR_UNEXPECTED); - mRules->ReplaceElementAt(aNew, index); - aNew->SetStyleSheet(mSheet); - aNew->SetParentRule(this); - aOld->SetStyleSheet(nsnull); - aOld->SetParentRule(nsnull); - return NS_OK; -} - -nsresult -NS_NewCSSMediaRule(nsICSSMediaRule** aInstancePtrResult) -{ - if (! aInstancePtrResult) { - return NS_ERROR_NULL_POINTER; - } - - CSSMediaRuleImpl* it = new CSSMediaRuleImpl(); - - if (! it) { - return NS_ERROR_OUT_OF_MEMORY; - } - - return CallQueryInterface(it, aInstancePtrResult); -} - // nsIDOMCSSRule methods NS_IMETHODIMP -CSSMediaRuleImpl::GetType(PRUint16* aType) +nsCSSMediaRule::GetType(PRUint16* aType) { *aType = nsIDOMCSSRule::MEDIA_RULE; return NS_OK; } NS_IMETHODIMP -CSSMediaRuleImpl::GetCssText(nsAString& aCssText) +nsCSSMediaRule::GetCssText(nsAString& aCssText) { PRUint32 index; PRUint32 count; @@ -1012,60 +1053,30 @@ CSSMediaRuleImpl::GetCssText(nsAString& aCssText) } } - aCssText.AppendLiteral(" {\n"); - - // get all the rules - if (mRules) { - mRules->Count(&count); - for (index = 0; index < count; index++) { - nsCOMPtr rule; - mRules->GetElementAt(index, getter_AddRefs(rule)); - nsCOMPtr domRule; - rule->GetDOMRule(getter_AddRefs(domRule)); - if (domRule) { - nsAutoString cssText; - domRule->GetCssText(cssText); - aCssText.Append(NS_LITERAL_STRING(" ") + - cssText + - NS_LITERAL_STRING("\n")); - } - } - } - - aCssText.AppendLiteral("}"); - - return NS_OK; + return nsCSSGroupRule::AppendRulesToCssText(aCssText); } NS_IMETHODIMP -CSSMediaRuleImpl::SetCssText(const nsAString& aCssText) +nsCSSMediaRule::SetCssText(const nsAString& aCssText) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -CSSMediaRuleImpl::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) +nsCSSMediaRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) { - if (mSheet) { - return CallQueryInterface(mSheet, aSheet); - } - *aSheet = nsnull; - return NS_OK; + return nsCSSGroupRule::GetParentStyleSheet(aSheet); } NS_IMETHODIMP -CSSMediaRuleImpl::GetParentRule(nsIDOMCSSRule** aParentRule) +nsCSSMediaRule::GetParentRule(nsIDOMCSSRule** aParentRule) { - if (mParentRule) { - return mParentRule->GetDOMRule(aParentRule); - } - *aParentRule = nsnull; - return NS_OK; + return nsCSSGroupRule::GetParentRule(aParentRule); } // nsIDOMCSSMediaRule methods NS_IMETHODIMP -CSSMediaRuleImpl::GetMedia(nsIDOMMediaList* *aMedia) +nsCSSMediaRule::GetMedia(nsIDOMMediaList* *aMedia) { NS_ENSURE_ARG_POINTER(aMedia); if (!mMedia) { @@ -1077,54 +1088,225 @@ CSSMediaRuleImpl::GetMedia(nsIDOMMediaList* *aMedia) } NS_IMETHODIMP -CSSMediaRuleImpl::GetCssRules(nsIDOMCSSRuleList* *aRuleList) +nsCSSMediaRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList) { - if (!mRuleCollection) { - mRuleCollection = new CSSGroupRuleRuleListImpl(this); - if (!mRuleCollection) { - return NS_ERROR_OUT_OF_MEMORY; + return nsCSSGroupRule::GetCssRules(aRuleList); +} + +NS_IMETHODIMP +nsCSSMediaRule::InsertRule(const nsAString & aRule, PRUint32 aIndex, PRUint32* _retval) +{ + return nsCSSGroupRule::InsertRule(aRule, aIndex, _retval); +} + +NS_IMETHODIMP +nsCSSMediaRule::DeleteRule(PRUint32 aIndex) +{ + return nsCSSGroupRule::DeleteRule(aIndex); +} + +// nsICSSGroupRule interface +NS_IMETHODIMP_(PRBool) +nsCSSMediaRule::UseForPresentation(nsPresContext* aPresContext) +{ + if (mMedia) { + PRBool matches = PR_FALSE; + mMedia->MatchesMedium(aPresContext->Medium(), &matches); + return matches; + } + return PR_TRUE; +} + + +nsCSSDocumentRule::nsCSSDocumentRule(void) +{ +} + +nsCSSDocumentRule::nsCSSDocumentRule(const nsCSSDocumentRule& aCopy) + : nsCSSGroupRule(aCopy) + , mURLs(new URL(*aCopy.mURLs)) +{ +} + +nsCSSDocumentRule::~nsCSSDocumentRule(void) +{ +} + +NS_IMPL_ADDREF_INHERITED(nsCSSDocumentRule, nsCSSRule) +NS_IMPL_RELEASE_INHERITED(nsCSSDocumentRule, nsCSSRule) + +// QueryInterface implementation for nsCSSDocumentRule +NS_INTERFACE_MAP_BEGIN(nsCSSDocumentRule) + NS_INTERFACE_MAP_ENTRY(nsICSSGroupRule) + NS_INTERFACE_MAP_ENTRY(nsICSSRule) + NS_INTERFACE_MAP_ENTRY(nsIStyleRule) + NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) + NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMozDocumentRule) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsCSSGroupRule) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSMozDocumentRule) +NS_INTERFACE_MAP_END + +#ifdef DEBUG +NS_IMETHODIMP +nsCSSDocumentRule::List(FILE* out, PRInt32 aIndent) const +{ + for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out); + + nsCAutoString str; + str.AssignLiteral("@-moz-document "); + for (URL *url = mURLs; url; url = url->next) { + switch (url->func) { + case eURL: + str.AppendLiteral("url(\""); + break; + case eURLPrefix: + str.AppendLiteral("url-prefix(\""); + break; + case eDomain: + str.AppendLiteral("domain(\""); + break; } - NS_ADDREF(mRuleCollection); + nsCAutoString escapedURL(url->url); + escapedURL.ReplaceSubstring("\"", "\\\""); // escape quotes + str.Append(escapedURL); + str.AppendLiteral("\"), "); } + str.Cut(str.Length() - 2, 1); // remove last , + fputs(str.get(), out); - return CallQueryInterface(mRuleCollection, aRuleList); + return nsCSSGroupRule::List(out, aIndent); +} +#endif + +NS_IMETHODIMP +nsCSSDocumentRule::GetType(PRInt32& aType) const +{ + aType = nsICSSRule::DOCUMENT_RULE; + return NS_OK; } NS_IMETHODIMP -CSSMediaRuleImpl::InsertRule(const nsAString & aRule, PRUint32 aIndex, PRUint32* _retval) +nsCSSDocumentRule::Clone(nsICSSRule*& aClone) const { - NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE); - - if (!mRules) { - nsresult rv = NS_NewISupportsArray(getter_AddRefs(mRules)); - if (NS_FAILED(rv)) - return rv; + nsCSSDocumentRule* clone = new nsCSSDocumentRule(*this); + if (clone) { + return CallQueryInterface(clone, &aClone); } + aClone = nsnull; + return NS_ERROR_OUT_OF_MEMORY; +} - PRUint32 count; - mRules->Count(&count); - if (aIndex > count) - return NS_ERROR_DOM_INDEX_SIZE_ERR; - - return mSheet->InsertRuleIntoGroup(aRule, this, aIndex, _retval); +// nsIDOMCSSRule methods +NS_IMETHODIMP +nsCSSDocumentRule::GetType(PRUint16* aType) +{ + // XXX What should really happen here? + *aType = nsIDOMCSSRule::UNKNOWN_RULE; + return NS_OK; } NS_IMETHODIMP -CSSMediaRuleImpl::DeleteRule(PRUint32 aIndex) +nsCSSDocumentRule::GetCssText(nsAString& aCssText) { - NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE); - if (!mRules) { - return NS_ERROR_DOM_INDEX_SIZE_ERR; + aCssText.AssignLiteral("@-moz-document "); + for (URL *url = mURLs; url; url = url->next) { + switch (url->func) { + case eURL: + aCssText.AppendLiteral("url(\""); + break; + case eURLPrefix: + aCssText.AppendLiteral("url-prefix(\""); + break; + case eDomain: + aCssText.AppendLiteral("domain(\""); + break; + } + nsCAutoString escapedURL(url->url); + escapedURL.ReplaceSubstring("\"", "\\\""); // escape quotes + AppendUTF8toUTF16(escapedURL, aCssText); + aCssText.AppendLiteral("\"), "); } - - PRUint32 count; - mRules->Count(&count); - if (aIndex >= count) - return NS_ERROR_DOM_INDEX_SIZE_ERR; + aCssText.Cut(aCssText.Length() - 2, 1); // remove last , - return mSheet->DeleteRuleFromGroup(this, aIndex); + return nsCSSGroupRule::AppendRulesToCssText(aCssText); } +NS_IMETHODIMP +nsCSSDocumentRule::SetCssText(const nsAString& aCssText) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsCSSDocumentRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) +{ + return nsCSSGroupRule::GetParentStyleSheet(aSheet); +} + +NS_IMETHODIMP +nsCSSDocumentRule::GetParentRule(nsIDOMCSSRule** aParentRule) +{ + return nsCSSGroupRule::GetParentRule(aParentRule); +} + +NS_IMETHODIMP +nsCSSDocumentRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList) +{ + return nsCSSGroupRule::GetCssRules(aRuleList); +} + +NS_IMETHODIMP +nsCSSDocumentRule::InsertRule(const nsAString & aRule, PRUint32 aIndex, PRUint32* _retval) +{ + return nsCSSGroupRule::InsertRule(aRule, aIndex, _retval); +} + +NS_IMETHODIMP +nsCSSDocumentRule::DeleteRule(PRUint32 aIndex) +{ + return nsCSSGroupRule::DeleteRule(aIndex); +} + +// nsICSSGroupRule interface +NS_IMETHODIMP_(PRBool) +nsCSSDocumentRule::UseForPresentation(nsPresContext* aPresContext) +{ + nsIURI *docURI = aPresContext->GetDocument()->GetDocumentURI(); + nsCAutoString docURISpec; + if (docURI) + docURI->GetSpec(docURISpec); + + for (URL *url = mURLs; url; url = url->next) { + switch (url->func) { + case eURL: { + if (docURISpec == url->url) + return PR_TRUE; + } break; + case eURLPrefix: { + if (StringBeginsWith(docURISpec, url->url)) + return PR_TRUE; + } break; + case eDomain: { + nsCAutoString host; + if (docURI) + docURI->GetHost(host); + PRInt32 lenDiff = host.Length() - url->url.Length(); + if (lenDiff == 0) { + if (host == url->url) + return PR_TRUE; + } else { + if (StringEndsWith(host, url->url) && + host.CharAt(lenDiff - 1) == '.') + return PR_TRUE; + } + } break; + } + } + + return PR_FALSE; +} + + // ------------------------------------------- // nsICSSNameSpaceRule // @@ -1294,6 +1476,7 @@ NS_NewCSSNameSpaceRule(nsICSSNameSpaceRule** aInstancePtrResult, NS_IMETHODIMP CSSNameSpaceRuleImpl::GetType(PRUint16* aType) { + // XXX What should really happen here? *aType = nsIDOMCSSRule::UNKNOWN_RULE; return NS_OK; } diff --git a/mozilla/content/html/style/src/nsCSSRules.h b/mozilla/content/html/style/src/nsCSSRules.h new file mode 100644 index 00000000000..994686e9146 --- /dev/null +++ b/mozilla/content/html/style/src/nsCSSRules.h @@ -0,0 +1,199 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +// vim:cindent:ts=2:et:sw=2: +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * L. David Baron + * Boris Zbarsky + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsCSSRules_h_ +#define nsCSSRules_h_ + +#include "nsCSSRule.h" +#include "nsICSSGroupRule.h" +#include "nsCOMPtr.h" +#include "nsAutoPtr.h" +#include "nsISupportsArray.h" +#include "nsIDOMCSSMediaRule.h" +#include "nsIDOMCSSMozDocumentRule.h" +#include "nsString.h" + +class CSSGroupRuleRuleListImpl; +class nsIMediaList; + +#define DECL_STYLE_RULE_INHERIT \ +NS_IMETHOD GetStyleSheet(nsIStyleSheet*& aSheet) const; \ +NS_IMETHOD SetStyleSheet(nsICSSStyleSheet* aSheet); \ +NS_IMETHOD SetParentRule(nsICSSGroupRule* aRule); \ +NS_IMETHOD GetDOMRule(nsIDOMCSSRule** aDOMRule); \ +NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData); + +// inherits from nsCSSRule and also implements methods on nsICSSGroupRule +// so they can be shared between nsCSSMediaRule and nsCSSDocumentRule +class nsCSSGroupRule : public nsCSSRule, public nsICSSGroupRule +{ +protected: + nsCSSGroupRule(); + nsCSSGroupRule(const nsCSSGroupRule& aCopy); + ~nsCSSGroupRule(); + + // implement part of nsIStyleRule and nsICSSRule + DECL_STYLE_RULE_INHERIT + + // to help implement nsIStyleRule +#ifdef DEBUG + nsresult List(FILE* out = stdout, PRInt32 aIndent = 0) const; +#endif + +public: + // implement nsICSSGroupRule + NS_IMETHOD AppendStyleRule(nsICSSRule* aRule); + NS_IMETHOD StyleRuleCount(PRInt32& aCount) const; + NS_IMETHOD GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const; + NS_IMETHOD EnumerateRulesForwards(nsISupportsArrayEnumFunc aFunc, void * aData) const; + NS_IMETHOD DeleteStyleRuleAt(PRUint32 aIndex); + NS_IMETHOD InsertStyleRulesAt(PRUint32 aIndex, nsISupportsArray* aRules); + NS_IMETHOD ReplaceStyleRule(nsICSSRule *aOld, nsICSSRule *aNew); + +protected: + // to help implement nsIDOMCSSRule + nsresult AppendRulesToCssText(nsAString& aCssText); + // to implement methods on nsIDOMCSSRule + nsresult GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet); + nsresult GetParentRule(nsIDOMCSSRule** aParentRule); + + // to implement common methods on nsIDOMCSSMediaRule and + // nsIDOMCSSMozDocumentRule + nsresult GetCssRules(nsIDOMCSSRuleList* *aRuleList); + nsresult InsertRule(const nsAString & aRule, PRUint32 aIndex, + PRUint32* _retval); + nsresult DeleteRule(PRUint32 aIndex); + + nsCOMPtr mRules; + CSSGroupRuleRuleListImpl* mRuleCollection; +}; + +class nsCSSMediaRule : public nsCSSGroupRule, + public nsIDOMCSSMediaRule +{ +public: + nsCSSMediaRule(); + nsCSSMediaRule(const nsCSSMediaRule& aCopy); + virtual ~nsCSSMediaRule(); + + NS_DECL_ISUPPORTS_INHERITED + + // nsIStyleRule methods +#ifdef DEBUG + NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const; +#endif + + // nsICSSRule methods + NS_IMETHOD SetStyleSheet(nsICSSStyleSheet* aSheet); //override nsCSSGroupRule + NS_IMETHOD GetType(PRInt32& aType) const; + NS_IMETHOD Clone(nsICSSRule*& aClone) const; + + // nsIDOMCSSRule interface + NS_DECL_NSIDOMCSSRULE + + // nsIDOMCSSMediaRule interface + NS_DECL_NSIDOMCSSMEDIARULE + + // rest of nsICSSGroupRule interface + NS_IMETHOD_(PRBool) UseForPresentation(nsPresContext* aPresContext); + + // @media rule methods + nsresult SetMedia(nsISupportsArray* aMedia); + +protected: + nsCOMPtr mMedia; +}; + +class nsCSSDocumentRule : public nsCSSGroupRule, + public nsIDOMCSSMozDocumentRule +{ +public: + nsCSSDocumentRule(void); + nsCSSDocumentRule(const nsCSSDocumentRule& aCopy); + virtual ~nsCSSDocumentRule(void); + + NS_DECL_ISUPPORTS_INHERITED + + // nsIStyleRule methods +#ifdef DEBUG + NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const; +#endif + + // nsICSSRule methods + NS_IMETHOD GetType(PRInt32& aType) const; + NS_IMETHOD Clone(nsICSSRule*& aClone) const; + + // nsIDOMCSSRule interface + NS_DECL_NSIDOMCSSRULE + + // nsIDOMCSSMozDocumentRule interface + NS_DECL_NSIDOMCSSMOZDOCUMENTRULE + + // rest of nsICSSGroupRule interface + NS_IMETHOD_(PRBool) UseForPresentation(nsPresContext* aPresContext); + + enum Function { + eURL, + eURLPrefix, + eDomain + }; + + struct URL { + nsCSSDocumentRule::Function func; + nsCString url; + URL *next; + + URL() : next(nsnull) {} + URL(const URL& aOther) + : func(aOther.func) + , url(aOther.url) + , next(new URL(*aOther.next)) + { + } + ~URL() { delete next; } + }; + + void SetURLs(URL *aURLs) { mURLs = aURLs; } + +protected: + nsAutoPtr mURLs; // linked list of |struct URL| above. +}; + + +#endif /* !defined(nsCSSRules_h_) */ diff --git a/mozilla/content/html/style/src/nsCSSStyleSheet.cpp b/mozilla/content/html/style/src/nsCSSStyleSheet.cpp index f80e0e417de..b8cc796498f 100644 --- a/mozilla/content/html/style/src/nsCSSStyleSheet.cpp +++ b/mozilla/content/html/style/src/nsCSSStyleSheet.cpp @@ -55,7 +55,7 @@ #include "nsCSSRuleProcessor.h" #include "nsICSSStyleRule.h" #include "nsICSSNameSpaceRule.h" -#include "nsICSSMediaRule.h" +#include "nsICSSGroupRule.h" #include "nsIMediaList.h" #include "nsIStyledContent.h" #include "nsIDocument.h" @@ -3589,13 +3589,12 @@ static void ContentEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector, } NS_IMETHODIMP -nsCSSRuleProcessor::RulesMatching(ElementRuleProcessorData *aData, - nsIAtom* aMedium) +nsCSSRuleProcessor::RulesMatching(ElementRuleProcessorData *aData) { NS_PRECONDITION(aData->mContent->IsContentOfType(nsIContent::eELEMENT), "content must be element"); - RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext, aMedium); + RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext); if (cascade) { nsIStyledContent* styledContent = aData->mStyledContent; @@ -3659,14 +3658,13 @@ static void PseudoEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector, } NS_IMETHODIMP -nsCSSRuleProcessor::RulesMatching(PseudoRuleProcessorData* aData, - nsIAtom* aMedium) +nsCSSRuleProcessor::RulesMatching(PseudoRuleProcessorData* aData) { NS_PRECONDITION(!aData->mContent || aData->mContent->IsContentOfType(nsIContent::eELEMENT), "content (if present) must be element"); - RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext, aMedium); + RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext); if (cascade) { cascade->mRuleHash.EnumerateTagRules(aData->mPseudoTag, @@ -3708,13 +3706,12 @@ PR_STATIC_CALLBACK(PRBool) StateEnumFunc(void* aSelector, void* aData) NS_IMETHODIMP nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult) { NS_PRECONDITION(aData->mContent->IsContentOfType(nsIContent::eELEMENT), "content must be element"); - RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext, aMedium); + RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext); // Look up the content node in the state rule list, which points to // any (CSS2 definition) simple selector (whether or not it is the @@ -3759,7 +3756,6 @@ PR_STATIC_CALLBACK(PRBool) AttributeEnumFunc(void* aSelector, void* aData) NS_IMETHODIMP nsCSSRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult) { NS_PRECONDITION(aData->mContent->IsContentOfType(nsIContent::eELEMENT), @@ -3779,7 +3775,7 @@ nsCSSRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData } // XXX What about XLinks? - RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext, aMedium); + RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext); // We do the same thing for attributes that we do for state selectors // (see HasStateDependentStyle), except that instead of one big list @@ -3900,14 +3896,14 @@ RuleArraysDestroy(nsHashKey *aKey, void *aData, void *aClosure) } struct CascadeEnumData { - CascadeEnumData(nsIAtom* aMedium, PLArenaPool& aArena) - : mMedium(aMedium), + CascadeEnumData(nsPresContext* aPresContext, PLArenaPool& aArena) + : mPresContext(aPresContext), mRuleArrays(nsnull, nsnull, RuleArraysDestroy, nsnull, 64), mArena(aArena) { } - nsIAtom* mMedium; + nsPresContext* mPresContext; nsObjectHashtable mRuleArrays; // of nsAutoVoidArray PLArenaPool& mArena; }; @@ -3939,11 +3935,11 @@ InsertRuleByWeight(nsISupports* aRule, void* aData) rules->AppendElement(info); } } - else if (nsICSSRule::MEDIA_RULE == type) { - nsICSSMediaRule* mediaRule = (nsICSSMediaRule*)rule; - if (mediaRule->UseForMedium(data->mMedium)) { - mediaRule->EnumerateRulesForwards(InsertRuleByWeight, aData); - } + else if (nsICSSRule::MEDIA_RULE == type || + nsICSSRule::DOCUMENT_RULE == type) { + nsICSSGroupRule* groupRule = (nsICSSGroupRule*)rule; + if (groupRule->UseForPresentation(data->mPresContext)) + groupRule->EnumerateRulesForwards(InsertRuleByWeight, aData); } return PR_TRUE; } @@ -3957,7 +3953,7 @@ CascadeSheetRulesInto(nsICSSStyleSheet* aSheet, void* aData) PRBool bSheetApplicable = PR_TRUE; sheet->GetApplicable(bSheetApplicable); - if (bSheetApplicable && sheet->UseForMedium(data->mMedium)) { + if (bSheetApplicable && sheet->UseForMedium(data->mPresContext->Medium())) { nsCSSStyleSheet* child = sheet->mFirstChild; while (child) { CascadeSheetRulesInto(child, data); @@ -4030,22 +4026,28 @@ static void PutRulesInList(nsObjectHashtable* aRuleArrays, } RuleCascadeData* -nsCSSRuleProcessor::GetRuleCascade(nsPresContext* aPresContext, - nsIAtom* aMedium) +nsCSSRuleProcessor::GetRuleCascade(nsPresContext* aPresContext) { + // Having RuleCascadeData objects be per-medium works for now since + // nsCSSRuleProcessor objects are per-document. (For a given set + // of stylesheets they can vary based on medium (@media) or document + // (@-moz-document).) Things will get a little more complicated if + // we implement media queries, though. + RuleCascadeData **cascadep = &mRuleCascades; RuleCascadeData *cascade; + nsIAtom *medium = aPresContext->Medium(); while ((cascade = *cascadep)) { - if (cascade->mMedium == aMedium) + if (cascade->mMedium == medium) return cascade; cascadep = &cascade->mNext; } if (mSheets.Count() != 0) { - cascade = new RuleCascadeData(aMedium, + cascade = new RuleCascadeData(medium, eCompatibility_NavQuirks == aPresContext->CompatibilityMode()); if (cascade) { - CascadeEnumData data(aMedium, cascade->mRuleHash.Arena()); + CascadeEnumData data(aPresContext, cascade->mRuleHash.Arena()); mSheets.EnumerateForwards(CascadeSheetRulesInto, &data); nsVoidArray weightedRules; PutRulesInList(&data.mRuleArrays, &weightedRules); diff --git a/mozilla/content/html/style/src/nsHTMLCSSStyleSheet.cpp b/mozilla/content/html/style/src/nsHTMLCSSStyleSheet.cpp index b9d4ee0b2fb..cf65efc5a68 100644 --- a/mozilla/content/html/style/src/nsHTMLCSSStyleSheet.cpp +++ b/mozilla/content/html/style/src/nsHTMLCSSStyleSheet.cpp @@ -368,18 +368,14 @@ public: NS_IMETHOD SetOwningDocument(nsIDocument* aDocument); // nsIStyleRuleProcessor api - NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData, - nsIAtom* aMedium); + NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); - NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData, - nsIAtom* aMedium); + NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult); NS_IMETHOD HasAttributeDependentStyle(AttributeRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult); #ifdef DEBUG @@ -432,8 +428,7 @@ NS_IMPL_ISUPPORTS3(HTMLCSSStyleSheetImpl, nsIStyleRuleProcessor) NS_IMETHODIMP -HTMLCSSStyleSheetImpl::RulesMatching(ElementRuleProcessorData* aData, - nsIAtom* aMedium) +HTMLCSSStyleSheetImpl::RulesMatching(ElementRuleProcessorData* aData) { nsIStyledContent *styledContent = aData->mStyledContent; @@ -449,8 +444,7 @@ HTMLCSSStyleSheetImpl::RulesMatching(ElementRuleProcessorData* aData, } NS_IMETHODIMP -HTMLCSSStyleSheetImpl::RulesMatching(PseudoRuleProcessorData* aData, - nsIAtom* aMedium) +HTMLCSSStyleSheetImpl::RulesMatching(PseudoRuleProcessorData* aData) { // We only want to add these rules if there are real :first-letter or // :first-line rules that cause a pseudo-element frame to be created. @@ -500,7 +494,6 @@ HTMLCSSStyleSheetImpl::Init(nsIURI* aURL, nsIDocument* aDocument) // Test if style is dependent on content state NS_IMETHODIMP HTMLCSSStyleSheetImpl::HasStateDependentStyle(StateRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult) { *aResult = nsReStyleHint(0); @@ -510,7 +503,6 @@ HTMLCSSStyleSheetImpl::HasStateDependentStyle(StateRuleProcessorData* aData, // Test if style is dependent on attribute NS_IMETHODIMP HTMLCSSStyleSheetImpl::HasAttributeDependentStyle(AttributeRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult) { *aResult = nsReStyleHint(0); diff --git a/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp b/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp index 51d4e329922..2ffa87386f4 100644 --- a/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp +++ b/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp @@ -516,8 +516,7 @@ static nsresult GetBodyColor(nsPresContext* aPresContext, nscolor* aColor) } NS_IMETHODIMP -nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData, - nsIAtom* aMedium) +nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData) { nsIStyledContent *styledContent = aData->mStyledContent; @@ -599,7 +598,6 @@ nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData, // Test if style is dependent on content state NS_IMETHODIMP nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult) { if (mActiveRule && @@ -617,7 +615,6 @@ nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData, NS_IMETHODIMP nsHTMLStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult) { // Result is true for |href| changes on HTML links if we have link rules. @@ -646,8 +643,7 @@ nsHTMLStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData, NS_IMETHODIMP -nsHTMLStyleSheet::RulesMatching(PseudoRuleProcessorData* aData, - nsIAtom* aMedium) +nsHTMLStyleSheet::RulesMatching(PseudoRuleProcessorData* aData) { nsIAtom* pseudoTag = aData->mPseudoTag; if (pseudoTag == nsCSSAnonBoxes::tableCol) { diff --git a/mozilla/content/html/style/src/nsHTMLStyleSheet.h b/mozilla/content/html/style/src/nsHTMLStyleSheet.h index 4ab5d18d3e0..bb25a89484c 100644 --- a/mozilla/content/html/style/src/nsHTMLStyleSheet.h +++ b/mozilla/content/html/style/src/nsHTMLStyleSheet.h @@ -73,15 +73,11 @@ public: #endif // nsIStyleRuleProcessor API - NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData, - nsIAtom* aMedium); - NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData, - nsIAtom* aMedium); + NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); + NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult); NS_IMETHOD HasAttributeDependentStyle(AttributeRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult); nsresult Init(nsIURI* aURL, nsIDocument* aDocument); diff --git a/mozilla/content/html/style/src/nsICSSGroupRule.h b/mozilla/content/html/style/src/nsICSSGroupRule.h index 48b1434f3fa..6d9166e5356 100644 --- a/mozilla/content/html/style/src/nsICSSGroupRule.h +++ b/mozilla/content/html/style/src/nsICSSGroupRule.h @@ -41,6 +41,7 @@ #include "nsISupportsArray.h" class nsIAtom; +class nsPresContext; // IID for the nsICSSGroupRule interface {5af048aa-1af0-11d3-9d83-0060088f9ff7} #define NS_ICSS_GROUP_RULE_IID \ @@ -65,6 +66,8 @@ public: NS_IMETHOD DeleteStyleRuleAt(PRUint32 aIndex) = 0; NS_IMETHOD InsertStyleRulesAt(PRUint32 aIndex, nsISupportsArray* aRules) = 0; NS_IMETHOD ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew) = 0; + + NS_IMETHOD_(PRBool) UseForPresentation(nsPresContext* aPresContext) = 0; }; diff --git a/mozilla/content/html/style/src/nsICSSRule.h b/mozilla/content/html/style/src/nsICSSRule.h index 0c9502d8685..260bac340e4 100644 --- a/mozilla/content/html/style/src/nsICSSRule.h +++ b/mozilla/content/html/style/src/nsICSSRule.h @@ -60,7 +60,8 @@ public: FONT_FACE_RULE = 4, PAGE_RULE = 5, CHARSET_RULE = 6, - NAMESPACE_RULE = 7 + NAMESPACE_RULE = 7, + DOCUMENT_RULE = 8 }; NS_IMETHOD GetType(PRInt32& aType) const = 0; diff --git a/mozilla/dom/public/idl/css/Makefile.in b/mozilla/dom/public/idl/css/Makefile.in index 2093a6f0d5d..2fb8eee4ae3 100644 --- a/mozilla/dom/public/idl/css/Makefile.in +++ b/mozilla/dom/public/idl/css/Makefile.in @@ -62,6 +62,7 @@ XPIDLSRCS = \ nsIDOMCSSFontFaceRule.idl \ nsIDOMCSSImportRule.idl \ nsIDOMCSSMediaRule.idl \ + nsIDOMCSSMozDocumentRule.idl \ nsIDOMCSSPageRule.idl \ nsIDOMCSSStyleRule.idl \ nsIDOMCSSUnknownRule.idl \ diff --git a/mozilla/content/html/style/src/nsICSSMediaRule.h b/mozilla/dom/public/idl/css/nsIDOMCSSMozDocumentRule.idl similarity index 56% rename from mozilla/content/html/style/src/nsICSSMediaRule.h rename to mozilla/dom/public/idl/css/nsIDOMCSSMozDocumentRule.idl index 589fb1aae26..524533ebf6c 100644 --- a/mozilla/content/html/style/src/nsICSSMediaRule.h +++ b/mozilla/dom/public/idl/css/nsIDOMCSSMozDocumentRule.idl @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -12,18 +12,18 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is mozilla.org code. + * The Original Code is nsIDOMCSSMozDocumentRule. * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1999 + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2004 * the Initial Developer. All Rights Reserved. * * Contributor(s): + * L. David Baron (original author) * * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to @@ -34,27 +34,22 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#ifndef nsICSSMediaRule_h___ -#define nsICSSMediaRule_h___ -#include "nsICSSGroupRule.h" -//#include "nsString.h" +#include "nsIDOMCSSRule.idl" -class nsIAtom; +/** + * Modified version of nsIDOMCSSMediaRule for @-moz-document rules. + */ +[scriptable, uuid(4eb9adac-afaf-4b8a-8640-7340863c1587)] +interface nsIDOMCSSMozDocumentRule : nsIDOMCSSRule +{ + readonly attribute nsIDOMCSSRuleList cssRules; -// IID for the nsICSSMediaRule interface {2c1d0110-1a09-11d3-805a-006008159b5a} -#define NS_ICSS_MEDIA_RULE_IID \ -{0x2c1d0110, 0x1a09, 0x11d3, {0x80, 0x5a, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x5a}} + unsigned long insertRule(in DOMString rule, + in unsigned long index) + raises(DOMException); + void deleteRule(in unsigned long index) + raises(DOMException); -class nsICSSMediaRule : public nsICSSGroupRule { -public: - NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICSS_MEDIA_RULE_IID) - - NS_IMETHOD SetMedia(nsISupportsArray* aMedia) = 0; - NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const = 0; + // XXX Add access to the URL list. }; - -nsresult -NS_NewCSSMediaRule(nsICSSMediaRule** aInstancePtrResult); - -#endif /* nsICSSMediaRule_h___ */ diff --git a/mozilla/dom/public/nsIDOMClassInfo.h b/mozilla/dom/public/nsIDOMClassInfo.h index 9a0cf0eb7ae..82ecdecac77 100644 --- a/mozilla/dom/public/nsIDOMClassInfo.h +++ b/mozilla/dom/public/nsIDOMClassInfo.h @@ -194,7 +194,8 @@ enum nsDOMClassInfoID { // We are now trying to preserve binary compat in classinfo. No // more putting things in those categories up there. New entries - // are to be added right before eDOMClassInfoIDCount + // are to be added right before eDOMClassInfoIDCount (or, for now, + // before the MOZ_SVG ifdefs, since they're off by default). // Rect object used by getComputedStyle eDOMClassInfo_CSSRect_id, @@ -234,6 +235,8 @@ enum nsDOMClassInfoID { eDOMClassInfo_TreeColumns_id, #endif + eDOMClassInfo_CSSMozDocumentRule_id, + #ifdef MOZ_SVG // The SVG document eDOMClassInfo_SVGDocument_id, diff --git a/mozilla/dom/src/base/nsDOMClassInfo.cpp b/mozilla/dom/src/base/nsDOMClassInfo.cpp index 2d602a8cde3..4df482bcec8 100644 --- a/mozilla/dom/src/base/nsDOMClassInfo.cpp +++ b/mozilla/dom/src/base/nsDOMClassInfo.cpp @@ -274,6 +274,7 @@ #include "nsIDOMCSSCharsetRule.h" #include "nsIDOMCSSImportRule.h" #include "nsIDOMCSSMediaRule.h" +#include "nsIDOMCSSMozDocumentRule.h" #include "nsIDOMCSSPrimitiveValue.h" #include "nsIDOMCSSStyleRule.h" #include "nsIDOMCSSStyleSheet.h" @@ -789,6 +790,9 @@ static nsDOMClassInfoData sClassInfoData[] = { ARRAY_SCRIPTABLE_FLAGS) #endif + NS_DEFINE_CLASSINFO_DATA(CSSMozDocumentRule, nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) + #ifdef MOZ_SVG // SVG document NS_DEFINE_CLASSINFO_DATA(SVGDocument, nsDocumentSH, @@ -2137,6 +2141,10 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_END #endif + DOM_CLASSINFO_MAP_BEGIN(CSSMozDocumentRule, nsIDOMCSSMozDocumentRule) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSMozDocumentRule) + DOM_CLASSINFO_MAP_END + #ifdef MOZ_SVG #define DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES \ DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGElement) \ diff --git a/mozilla/layout/style/nsCSSParser.cpp b/mozilla/layout/style/nsCSSParser.cpp index 0bf45141ed3..e029905f956 100644 --- a/mozilla/layout/style/nsCSSParser.cpp +++ b/mozilla/layout/style/nsCSSParser.cpp @@ -45,7 +45,7 @@ #include "nsICSSLoader.h" #include "nsICSSStyleRule.h" #include "nsICSSImportRule.h" -#include "nsICSSMediaRule.h" +#include "nsCSSRules.h" #include "nsICSSNameSpaceRule.h" #include "nsIUnicharInputStream.h" #include "nsICSSStyleSheet.h" @@ -151,13 +151,16 @@ protected: PRBool ParseAtRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData); PRBool ParseCharsetRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData); PRBool ParseImportRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData); + PRBool GatherURL(nsresult& aErrorCode, nsString& aURL); PRBool GatherMedia(nsresult& aErrorCode, nsISupportsArray* aMediaAtoms); PRBool ProcessImport(nsresult& aErrorCode, const nsString& aURLSpec, nsISupportsArray* aMedia, RuleAppendFunc aAppendFunc, void* aProcessData); + PRBool ParseGroupRule(nsresult& aErrorCode, nsICSSGroupRule* aRule, RuleAppendFunc aAppendFunc, void* aProcessData); PRBool ParseMediaRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData); + PRBool ParseMozDocumentRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData); PRBool ParseNameSpaceRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData); PRBool ProcessNameSpace(nsresult& aErrorCode, const nsString& aPrefix, const nsString& aURLSpec, RuleAppendFunc aAppendFunc, @@ -979,6 +982,12 @@ PRBool CSSParserImpl::ParseAtRule(nsresult& aErrorCode, RuleAppendFunc aAppendFu return PR_TRUE; } } + if (mToken.mIdent.LowerCaseEqualsLiteral("-moz-document")) { + if (ParseMozDocumentRule(aErrorCode, aAppendFunc, aData)) { + mSection = eCSSSection_General; + return PR_TRUE; + } + } if (mToken.mIdent.LowerCaseEqualsLiteral("font-face")) { if (ParseFontFaceRule(aErrorCode, aAppendFunc, aData)) { mSection = eCSSSection_General; @@ -1029,6 +1038,29 @@ PRBool CSSParserImpl::ParseCharsetRule(nsresult& aErrorCode, RuleAppendFunc aApp return PR_TRUE; } +PRBool CSSParserImpl::GatherURL(nsresult& aErrorCode, nsString& aURL) +{ + if (!GetToken(aErrorCode, PR_TRUE)) { + return PR_FALSE; + } + if (eCSSToken_String == mToken.mType) { + aURL = mToken.mIdent; + return PR_TRUE; + } + else if (eCSSToken_Function == mToken.mType && + mToken.mIdent.LowerCaseEqualsLiteral("url") && + ExpectSymbol(aErrorCode, '(', PR_FALSE) && + GetURLToken(aErrorCode, PR_TRUE) && + (eCSSToken_String == mToken.mType || + eCSSToken_URL == mToken.mType)) { + aURL = mToken.mIdent; + if (ExpectSymbol(aErrorCode, ')', PR_TRUE)) { + return PR_TRUE; + } + } + return PR_FALSE; +} + PRBool CSSParserImpl::GatherMedia(nsresult& aErrorCode, nsISupportsArray* aMediaAtoms) { @@ -1089,10 +1121,6 @@ PRBool CSSParserImpl::GatherMedia(nsresult& aErrorCode, // Parse a CSS2 import rule: "@import STRING | URL [medium [, mdeium]]" PRBool CSSParserImpl::ParseImportRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aData) { - if (!GetToken(aErrorCode, PR_TRUE)) { - REPORT_UNEXPECTED_EOF(NS_LITERAL_STRING("URI in @import rule")); - return PR_FALSE; - } nsAutoString url; nsCOMPtr media; aErrorCode = NS_NewISupportsArray(getter_AddRefs(media)); @@ -1100,38 +1128,23 @@ PRBool CSSParserImpl::ParseImportRule(nsresult& aErrorCode, RuleAppendFunc aAppe // Out of memory return PR_FALSE; } + + if (!GatherURL(aErrorCode, url)) { + REPORT_UNEXPECTED_TOKEN( + NS_LITERAL_STRING("Expected URI in @import rule but found")); + return PR_FALSE; + } - if (eCSSToken_String == mToken.mType) { - url = mToken.mIdent; - if (GatherMedia(aErrorCode, media)) { - if (ExpectSymbol(aErrorCode, ';', PR_TRUE)) { - ProcessImport(aErrorCode, url, media, aAppendFunc, aData); - return PR_TRUE; - } - } + if (!GatherMedia(aErrorCode, media) || + !ExpectSymbol(aErrorCode, ';', PR_TRUE)) { + REPORT_UNEXPECTED_TOKEN( + NS_LITERAL_STRING("Unexpected token within @import:")); + // don't advance section, simply ignore invalid @import + return PR_FALSE; } - else if ((eCSSToken_Function == mToken.mType) && - (mToken.mIdent.LowerCaseEqualsLiteral("url"))) { - if (ExpectSymbol(aErrorCode, '(', PR_FALSE)) { - if (GetURLToken(aErrorCode, PR_TRUE)) { - if ((eCSSToken_String == mToken.mType) || (eCSSToken_URL == mToken.mType)) { - url = mToken.mIdent; - if (ExpectSymbol(aErrorCode, ')', PR_TRUE)) { - if (GatherMedia(aErrorCode, media)) { - if (ExpectSymbol(aErrorCode, ';', PR_TRUE)) { - ProcessImport(aErrorCode, url, media, aAppendFunc, aData); - return PR_TRUE; - } - } - } - } - } - } - } - REPORT_UNEXPECTED_TOKEN( - NS_LITERAL_STRING("Unexpected token within @import:")); - // don't advance section, simply ignore invalid @import - return PR_FALSE; + + ProcessImport(aErrorCode, url, media, aAppendFunc, aData); + return PR_TRUE; } @@ -1165,8 +1178,55 @@ PRBool CSSParserImpl::ProcessImport(nsresult& aErrorCode, return PR_TRUE; } +// Parse the {} part of an @media or @-moz-document rule. +PRBool CSSParserImpl::ParseGroupRule(nsresult& aErrorCode, + nsICSSGroupRule* aRule, + RuleAppendFunc aAppendFunc, + void* aData) +{ + // XXXbz this could use better error reporting throughout the method + if (!ExpectSymbol(aErrorCode, '{', PR_TRUE)) { + return PR_FALSE; + } + + // push rule on stack, loop over children + if (!PushGroup(aRule)) { + aErrorCode = NS_ERROR_OUT_OF_MEMORY; + return PR_FALSE; + } + nsCSSSection holdSection = mSection; + mSection = eCSSSection_General; + + for (;;) { + // Get next non-whitespace token + if (! GetToken(aErrorCode, PR_TRUE)) { + REPORT_UNEXPECTED_EOF(NS_LITERAL_STRING("end of @media or @-moz-document rule")); + break; + } + if (mToken.IsSymbol('}')) { // done! + UngetToken(); + break; + } + if (eCSSToken_AtKeyword == mToken.mType) { + SkipAtRule(aErrorCode); // group rules cannot contain @rules + continue; + } + UngetToken(); + ParseRuleSet(aErrorCode, AppendRuleToSheet, this); + } + PopGroup(); + + if (!ExpectSymbol(aErrorCode, '}', PR_TRUE)) { + mSection = holdSection; + return PR_FALSE; + } + (*aAppendFunc)(aRule, aData); + return PR_TRUE; +} + // Parse a CSS2 media rule: "@media medium [, medium] { ... }" -PRBool CSSParserImpl::ParseMediaRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, +PRBool CSSParserImpl::ParseMediaRule(nsresult& aErrorCode, + RuleAppendFunc aAppendFunc, void* aData) { nsCOMPtr media; @@ -1176,48 +1236,13 @@ PRBool CSSParserImpl::ParseMediaRule(nsresult& aErrorCode, RuleAppendFunc aAppen // XXXbz this could use better error reporting throughout the method PRUint32 count; media->Count(&count); - if (count > 0 && - ExpectSymbol(aErrorCode, '{', PR_TRUE)) { - // push media rule on stack, loop over children - nsCOMPtr rule; - NS_NewCSSMediaRule(getter_AddRefs(rule)); - if (rule) { - if (PushGroup(rule)) { - - nsCSSSection holdSection = mSection; - mSection = eCSSSection_General; - - for (;;) { - // Get next non-whitespace token - if (! GetToken(aErrorCode, PR_TRUE)) { - REPORT_UNEXPECTED_EOF(NS_LITERAL_STRING("end of @media rule")); - break; - } - if (mToken.IsSymbol('}')) { // done! - UngetToken(); - break; - } - if (eCSSToken_AtKeyword == mToken.mType) { - SkipAtRule(aErrorCode); // @media cannot contain @rules - continue; - } - UngetToken(); - ParseRuleSet(aErrorCode, AppendRuleToSheet, this); - } - PopGroup(); - - if (ExpectSymbol(aErrorCode, '}', PR_TRUE)) { - // Append first, so when we do SetMedia() the rule - // knows what its stylesheet is. - (*aAppendFunc)(rule, aData); - rule->SetMedia(media); - return PR_TRUE; - } - mSection = holdSection; - } - } - else { // failed to create rule, backup and skip block - UngetToken(); + if (count > 0) { + nsRefPtr rule(new nsCSSMediaRule()); + // Append first, so when we do SetMedia() the rule + // knows what its stylesheet is. + if (rule && ParseGroupRule(aErrorCode, rule, aAppendFunc, aData)) { + rule->SetMedia(media); + return PR_TRUE; } } } @@ -1226,6 +1251,72 @@ PRBool CSSParserImpl::ParseMediaRule(nsresult& aErrorCode, RuleAppendFunc aAppen return PR_FALSE; } +// Parse a @-moz-document rule. This is like an @media rule, but instead +// of a medium it has a nonempty list of items where each item is either +// url(), url-prefix(), or domain(). +PRBool CSSParserImpl::ParseMozDocumentRule(nsresult& aErrorCode, + RuleAppendFunc aAppendFunc, + void* aData) +{ + nsCSSDocumentRule::URL *urls = nsnull; + nsCSSDocumentRule::URL **next = &urls; + do { + if (!GetToken(aErrorCode, PR_TRUE) || + eCSSToken_Function != mToken.mType || + !(mToken.mIdent.LowerCaseEqualsLiteral("url") || + mToken.mIdent.LowerCaseEqualsLiteral("url-prefix") || + mToken.mIdent.LowerCaseEqualsLiteral("domain"))) { + REPORT_UNEXPECTED_TOKEN( + NS_LITERAL_STRING("Expected url(), url-prefix(), or domain() in @-moz-document rule but found")); + delete urls; + return PR_FALSE; + } + nsCSSDocumentRule::URL *cur = *next = new nsCSSDocumentRule::URL; + if (!cur) { + aErrorCode = NS_ERROR_OUT_OF_MEMORY; + delete urls; + return PR_FALSE; + } + next = &cur->next; + if (mToken.mIdent.LowerCaseEqualsLiteral("url")) { + cur->func = nsCSSDocumentRule::eURL; + } else if (mToken.mIdent.LowerCaseEqualsLiteral("url-prefix")) { + cur->func = nsCSSDocumentRule::eURLPrefix; + } else if (mToken.mIdent.LowerCaseEqualsLiteral("domain")) { + cur->func = nsCSSDocumentRule::eDomain; + } + + if (!ExpectSymbol(aErrorCode, '(', PR_FALSE) || + !GetURLToken(aErrorCode, PR_TRUE) || + (eCSSToken_String != mToken.mType && + eCSSToken_URL != mToken.mType)) { + REPORT_UNEXPECTED_TOKEN( + NS_LITERAL_STRING("Expected URI in @-moz-document rule but found")); + delete urls; + return PR_FALSE; + } + if (!ExpectSymbol(aErrorCode, ')', PR_TRUE)) { + delete urls; + return PR_FALSE; + } + + // We could try to make the URL (as long as it's not domain()) + // canonical and absolute with NS_NewURI and GetSpec, but I'm + // inclined to think we shouldn't. + CopyUTF16toUTF8(mToken.mIdent, cur->url); + } while (ExpectSymbol(aErrorCode, ',', PR_TRUE)); + + nsRefPtr rule(new nsCSSDocumentRule()); + if (!rule) { + aErrorCode = NS_ERROR_OUT_OF_MEMORY; + delete urls; + return PR_FALSE; + } + rule->SetURLs(urls); + + return ParseGroupRule(aErrorCode, rule, aAppendFunc, aData); +} + // Parse a CSS3 namespace rule: "@namespace [prefix] STRING | URL;" PRBool CSSParserImpl::ParseNameSpaceRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, diff --git a/mozilla/layout/style/nsCSSRule.cpp b/mozilla/layout/style/nsCSSRule.cpp index 2253057ed8b..4e5eaadb807 100644 --- a/mozilla/layout/style/nsCSSRule.cpp +++ b/mozilla/layout/style/nsCSSRule.cpp @@ -60,13 +60,6 @@ nsCSSRule::~nsCSSRule(void) NS_IMPL_ADDREF(nsCSSRule) NS_IMPL_RELEASE(nsCSSRule) -NS_IMETHODIMP -nsCSSRule::QueryInterface(REFNSIID aIID, void** aInstancePtr) -{ - NS_NOTREACHED("nsCSSRule::QueryInterface"); - return NS_NOINTERFACE; -} - NS_IMETHODIMP nsCSSRule::GetStyleSheet(nsIStyleSheet*& aSheet) const { diff --git a/mozilla/layout/style/nsCSSRule.h b/mozilla/layout/style/nsCSSRule.h index 575987534b8..67142e00b6a 100644 --- a/mozilla/layout/style/nsCSSRule.h +++ b/mozilla/layout/style/nsCSSRule.h @@ -51,7 +51,13 @@ public: nsCSSRule(const nsCSSRule& aCopy); virtual ~nsCSSRule(void); - NS_DECL_ISUPPORTS + // for implementing nsISupports + nsrefcnt AddRef(); + nsrefcnt Release(); +protected: + nsAutoRefCnt mRefCnt; + NS_DECL_OWNINGTHREAD +public: NS_IMETHOD GetStyleSheet(nsIStyleSheet*& aSheet) const; NS_IMETHOD SetStyleSheet(nsICSSStyleSheet* aSheet); diff --git a/mozilla/layout/style/nsCSSRuleProcessor.h b/mozilla/layout/style/nsCSSRuleProcessor.h index 5e6c88ca1b3..c8cddf61e75 100644 --- a/mozilla/layout/style/nsCSSRuleProcessor.h +++ b/mozilla/layout/style/nsCSSRuleProcessor.h @@ -67,26 +67,22 @@ public: nsresult ClearRuleCascades(); // nsIStyleRuleProcessor - NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData, - nsIAtom* aMedium); + NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); - NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData, - nsIAtom* aMedium); + NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult); NS_IMETHOD HasAttributeDependentStyle(AttributeRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult); protected: - RuleCascadeData* GetRuleCascade(nsPresContext* aPresContext, nsIAtom* aMedium); + RuleCascadeData* GetRuleCascade(nsPresContext* aPresContext); nsCOMArray mSheets; - RuleCascadeData* mRuleCascades; + RuleCascadeData* mRuleCascades; }; #endif /* nsCSSRuleProcessor_h_ */ diff --git a/mozilla/layout/style/nsCSSRules.cpp b/mozilla/layout/style/nsCSSRules.cpp index d8375e310d1..6e03090eb70 100644 --- a/mozilla/layout/style/nsCSSRules.cpp +++ b/mozilla/layout/style/nsCSSRules.cpp @@ -35,8 +35,8 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ +#include "nsCSSRules.h" #include "nsICSSImportRule.h" -#include "nsICSSMediaRule.h" #include "nsICSSNameSpaceRule.h" #include "nsString.h" @@ -53,24 +53,19 @@ #include "nsIDOMCSSRule.h" #include "nsIDOMCSSImportRule.h" #include "nsIDOMCSSMediaRule.h" +#include "nsIDOMCSSMozDocumentRule.h" #include "nsIDOMCSSCharsetRule.h" #include "nsIMediaList.h" #include "nsIDOMMediaList.h" #include "nsIDOMCSSRuleList.h" #include "nsIDOMStyleSheet.h" #include "nsIDocument.h" +#include "nsPresContext.h" #include "nsContentUtils.h" #include "nsStyleConsts.h" #include "nsDOMError.h" -#define DECL_STYLE_RULE_INHERIT \ -NS_IMETHOD GetStyleSheet(nsIStyleSheet*& aSheet) const; \ -NS_IMETHOD SetStyleSheet(nsICSSStyleSheet* aSheet); \ -NS_IMETHOD SetParentRule(nsICSSGroupRule* aRule); \ -NS_IMETHOD GetDOMRule(nsIDOMCSSRule** aDOMRule); \ -NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData); - #define IMPL_STYLE_RULE_INHERIT(_class, super) \ NS_IMETHODIMP _class::GetStyleSheet(nsIStyleSheet*& aSheet) const { return super::GetStyleSheet(aSheet); } \ NS_IMETHODIMP _class::SetStyleSheet(nsICSSStyleSheet* aSheet) { return super::SetStyleSheet(aSheet); } \ @@ -625,61 +620,9 @@ CSSImportRuleImpl::GetStyleSheet(nsIDOMCSSStyleSheet * *aStyleSheet) return CallQueryInterface(mChildSheet, aStyleSheet); } -// ------------------------------------------- -// nsICSSMediaRule -// -class CSSMediaRuleImpl : public nsCSSRule, - public nsICSSMediaRule, - public nsIDOMCSSMediaRule -{ -public: - CSSMediaRuleImpl(void); - CSSMediaRuleImpl(const CSSMediaRuleImpl& aCopy); - virtual ~CSSMediaRuleImpl(void); - - NS_DECL_ISUPPORTS_INHERITED - - DECL_STYLE_RULE_INHERIT - - // nsIStyleRule methods -#ifdef DEBUG - NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const; -#endif - - // nsICSSRule methods - NS_IMETHOD GetType(PRInt32& aType) const; - NS_IMETHOD Clone(nsICSSRule*& aClone) const; - - // nsICSSMediaRule methods - NS_IMETHOD SetMedia(nsISupportsArray* aMedia); - NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const; - - // nsICSSGroupRule methods - NS_IMETHOD AppendStyleRule(nsICSSRule* aRule); - NS_IMETHOD StyleRuleCount(PRInt32& aCount) const; - NS_IMETHOD GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const; - NS_IMETHOD EnumerateRulesForwards(nsISupportsArrayEnumFunc aFunc, void * aData) const; - NS_IMETHOD DeleteStyleRuleAt(PRUint32 aIndex); - NS_IMETHOD InsertStyleRulesAt(PRUint32 aIndex, nsISupportsArray* aRules); - NS_IMETHOD ReplaceStyleRule(nsICSSRule *aOld, nsICSSRule *aNew); - - // nsIDOMCSSRule interface - NS_DECL_NSIDOMCSSRULE - - // nsIDOMCSSMediaRule interface - NS_DECL_NSIDOMCSSMEDIARULE - -protected: - nsCOMPtr mMedia; - nsCOMPtr mRules; - CSSGroupRuleRuleListImpl* mRuleCollection; -}; - -CSSMediaRuleImpl::CSSMediaRuleImpl(void) - : nsCSSRule(), - mMedia(nsnull), - mRules(nsnull), - mRuleCollection(nsnull) +nsCSSGroupRule::nsCSSGroupRule() + : nsCSSRule() + , mRuleCollection(nsnull) { } @@ -700,37 +643,27 @@ CloneRuleInto(nsISupports* aRule, void* aArray) static PRBool SetParentRuleReference(nsISupports* aRule, void* aParentRule) { - nsICSSRule* rule = (nsICSSRule*)aRule; - nsICSSGroupRule* parentRule = (nsICSSGroupRule*)aParentRule; + nsICSSRule* rule = NS_STATIC_CAST(nsICSSRule*, aRule); + nsCSSGroupRule* parentRule = NS_STATIC_CAST(nsCSSGroupRule*, aParentRule); rule->SetParentRule(parentRule); return PR_TRUE; } -CSSMediaRuleImpl::CSSMediaRuleImpl(const CSSMediaRuleImpl& aCopy) - : nsCSSRule(aCopy), - mMedia(nsnull), - mRules(nsnull), - mRuleCollection(nsnull) +nsCSSGroupRule::nsCSSGroupRule(const nsCSSGroupRule& aCopy) + : nsCSSRule(aCopy) + , mRuleCollection(nsnull) // lazily constructed { - if (aCopy.mMedia) { - NS_NewMediaList(aCopy.mMedia, aCopy.mSheet, getter_AddRefs(mMedia)); - } - if (aCopy.mRules) { NS_NewISupportsArray(getter_AddRefs(mRules)); if (mRules) { aCopy.mRules->EnumerateForwards(CloneRuleInto, mRules); - mRules->EnumerateForwards(SetParentRuleReference, - NS_STATIC_CAST(nsICSSGroupRule*, this)); + mRules->EnumerateForwards(SetParentRuleReference, this); } } } -CSSMediaRuleImpl::~CSSMediaRuleImpl(void) +nsCSSGroupRule::~nsCSSGroupRule() { - if (mMedia) { - mMedia->DropReference(); - } if (mRules) { mRules->EnumerateForwards(SetParentRuleReference, nsnull); } @@ -740,21 +673,7 @@ CSSMediaRuleImpl::~CSSMediaRuleImpl(void) } } -NS_IMPL_ADDREF_INHERITED(CSSMediaRuleImpl, nsCSSRule) -NS_IMPL_RELEASE_INHERITED(CSSMediaRuleImpl, nsCSSRule) - -// QueryInterface implementation for CSSMediaRuleImpl -NS_INTERFACE_MAP_BEGIN(CSSMediaRuleImpl) - NS_INTERFACE_MAP_ENTRY(nsICSSMediaRule) - NS_INTERFACE_MAP_ENTRY(nsICSSRule) - NS_INTERFACE_MAP_ENTRY(nsIStyleRule) - NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) - NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMediaRule) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICSSMediaRule) - NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSMediaRule) -NS_INTERFACE_MAP_END - -IMPL_STYLE_RULE_INHERIT2(CSSMediaRuleImpl, nsCSSRule) +IMPL_STYLE_RULE_INHERIT2(nsCSSGroupRule, nsCSSRule) static PRBool SetStyleSheetReference(nsISupports* aRule, void* aSheet) @@ -766,11 +685,279 @@ SetStyleSheetReference(nsISupports* aRule, void* aSheet) } NS_IMETHODIMP -CSSMediaRuleImpl::SetStyleSheet(nsICSSStyleSheet* aSheet) +nsCSSGroupRule::SetStyleSheet(nsICSSStyleSheet* aSheet) { if (mRules) { mRules->EnumerateForwards(SetStyleSheetReference, aSheet); } + + return nsCSSRule::SetStyleSheet(aSheet); +} + +#ifdef DEBUG +nsresult +nsCSSGroupRule::List(FILE* out, PRInt32 aIndent) const +{ + fputs(" {\n", out); + + if (mRules) { + PRUint32 index = 0; + PRUint32 count; + mRules->Count(&count); + while (index < count) { + nsCOMPtr rule = dont_AddRef((nsICSSRule*)mRules->ElementAt(index++)); + rule->List(out, aIndent + 1); + } + } + fputs("}\n", out); + return NS_OK; +} +#endif + +NS_IMETHODIMP +nsCSSGroupRule::AppendStyleRule(nsICSSRule* aRule) +{ + nsresult result = NS_OK; + if (!mRules) { + result = NS_NewISupportsArray(getter_AddRefs(mRules)); + } + if (NS_SUCCEEDED(result) && mRules) { + mRules->AppendElement(aRule); + aRule->SetStyleSheet(mSheet); + aRule->SetParentRule(this); + if (mSheet) { + // XXXldb Shouldn't we be using |WillDirty| and |DidDirty| (and + // shouldn't |SetModified| be removed? + mSheet->SetModified(PR_TRUE); + } + } + return result; +} + +NS_IMETHODIMP +nsCSSGroupRule::StyleRuleCount(PRInt32& aCount) const +{ + if (mRules) { + PRUint32 count; + mRules->Count(&count); + aCount = (PRInt32)count; + } + else { + aCount = 0; + } + return NS_OK; +} + +NS_IMETHODIMP +nsCSSGroupRule::GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const +{ + if (mRules) { + PRInt32 count = 0; + nsresult rv = StyleRuleCount(count); + NS_ENSURE_SUCCESS(rv, rv); + if (aIndex >= count) { + aRule = nsnull; + return NS_ERROR_ILLEGAL_VALUE; + } + aRule = (nsICSSRule*)mRules->ElementAt(aIndex); + return NS_OK; + } + return NS_ERROR_ILLEGAL_VALUE; +} + +NS_IMETHODIMP +nsCSSGroupRule::EnumerateRulesForwards(nsISupportsArrayEnumFunc aFunc, void * aData) const +{ + if (mRules) { + return ((mRules->EnumerateForwards(aFunc, aData)) ? NS_OK : NS_ENUMERATOR_FALSE); + } + return NS_OK; +} + +/* + * The next two methods (DeleteStyleRuleAt and InsertStyleRulesAt) + * should never be called unless you have first called WillDirty() on + * the parents tylesheet. After they are called, DidDirty() needs to + * be called on the sheet + */ +NS_IMETHODIMP +nsCSSGroupRule::DeleteStyleRuleAt(PRUint32 aIndex) +{ + NS_ENSURE_TRUE(mRules, NS_ERROR_FAILURE); + + nsCOMPtr rule = dont_AddRef((nsICSSRule*)mRules->ElementAt(aIndex)); + if (rule) { + rule->SetStyleSheet(nsnull); + rule->SetParentRule(nsnull); + } + return mRules->DeleteElementAt(aIndex); +} + +NS_IMETHODIMP +nsCSSGroupRule::InsertStyleRulesAt(PRUint32 aIndex, nsISupportsArray* aRules) +{ + NS_ENSURE_TRUE(mRules, NS_ERROR_FAILURE); + + aRules->EnumerateForwards(SetStyleSheetReference, mSheet); + aRules->EnumerateForwards(SetParentRuleReference, this); + // There is no xpcom-compatible version of InsertElementsAt.... :( + if (! mRules->InsertElementsAt(aRules, aIndex)) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +NS_IMETHODIMP +nsCSSGroupRule::ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew) +{ + PRInt32 index = mRules->IndexOf(aOld); + NS_ENSURE_TRUE(index != -1, NS_ERROR_UNEXPECTED); + mRules->ReplaceElementAt(aNew, index); + aNew->SetStyleSheet(mSheet); + aNew->SetParentRule(this); + aOld->SetStyleSheet(nsnull); + aOld->SetParentRule(nsnull); + return NS_OK; +} + +nsresult +nsCSSGroupRule::AppendRulesToCssText(nsAString& aCssText) +{ + aCssText.AppendLiteral(" {\n"); + + // get all the rules + if (mRules) { + PRUint32 count; + mRules->Count(&count); + for (PRUint32 index = 0; index < count; index++) { + nsCOMPtr rule; + mRules->GetElementAt(index, getter_AddRefs(rule)); + nsCOMPtr domRule; + rule->GetDOMRule(getter_AddRefs(domRule)); + if (domRule) { + nsAutoString cssText; + domRule->GetCssText(cssText); + aCssText.Append(NS_LITERAL_STRING(" ") + + cssText + + NS_LITERAL_STRING("\n")); + } + } + } + + aCssText.AppendLiteral("}"); + + return NS_OK; +} + +nsresult +nsCSSGroupRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) +{ + if (mSheet) { + return CallQueryInterface(mSheet, aSheet); + } + *aSheet = nsnull; + return NS_OK; +} + +nsresult +nsCSSGroupRule::GetParentRule(nsIDOMCSSRule** aParentRule) +{ + if (mParentRule) { + return mParentRule->GetDOMRule(aParentRule); + } + *aParentRule = nsnull; + return NS_OK; +} + +// nsIDOMCSSMediaRule or nsIDOMCSSMozDocumentRule methods +nsresult +nsCSSGroupRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList) +{ + if (!mRuleCollection) { + mRuleCollection = new CSSGroupRuleRuleListImpl(this); + if (!mRuleCollection) { + return NS_ERROR_OUT_OF_MEMORY; + } + NS_ADDREF(mRuleCollection); + } + + return CallQueryInterface(mRuleCollection, aRuleList); +} + +nsresult +nsCSSGroupRule::InsertRule(const nsAString & aRule, PRUint32 aIndex, PRUint32* _retval) +{ + NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE); + + if (!mRules) { + nsresult rv = NS_NewISupportsArray(getter_AddRefs(mRules)); + if (NS_FAILED(rv)) + return rv; + } + + PRUint32 count; + mRules->Count(&count); + if (aIndex > count) + return NS_ERROR_DOM_INDEX_SIZE_ERR; + + return mSheet->InsertRuleIntoGroup(aRule, this, aIndex, _retval); +} + +nsresult +nsCSSGroupRule::DeleteRule(PRUint32 aIndex) +{ + NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE); + if (!mRules) { + return NS_ERROR_DOM_INDEX_SIZE_ERR; + } + + PRUint32 count; + mRules->Count(&count); + if (aIndex >= count) + return NS_ERROR_DOM_INDEX_SIZE_ERR; + + return mSheet->DeleteRuleFromGroup(this, aIndex); +} + +// ------------------------------------------- +// nsICSSMediaRule +// +nsCSSMediaRule::nsCSSMediaRule() +{ +} + +nsCSSMediaRule::nsCSSMediaRule(const nsCSSMediaRule& aCopy) + : nsCSSGroupRule(aCopy) +{ + if (aCopy.mMedia) { + NS_NewMediaList(aCopy.mMedia, aCopy.mSheet, getter_AddRefs(mMedia)); + } +} + +nsCSSMediaRule::~nsCSSMediaRule() +{ + if (mMedia) { + mMedia->DropReference(); + } +} + +NS_IMPL_ADDREF_INHERITED(nsCSSMediaRule, nsCSSRule) +NS_IMPL_RELEASE_INHERITED(nsCSSMediaRule, nsCSSRule) + +// QueryInterface implementation for nsCSSMediaRule +NS_INTERFACE_MAP_BEGIN(nsCSSMediaRule) + NS_INTERFACE_MAP_ENTRY(nsICSSGroupRule) + NS_INTERFACE_MAP_ENTRY(nsICSSRule) + NS_INTERFACE_MAP_ENTRY(nsIStyleRule) + NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) + NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMediaRule) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsCSSGroupRule) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSMediaRule) +NS_INTERFACE_MAP_END + +NS_IMETHODIMP +nsCSSMediaRule::SetStyleSheet(nsICSSStyleSheet* aSheet) +{ if (mMedia) { nsresult rv; nsCOMPtr oldMedia(do_QueryInterface(mMedia, &rv)); @@ -782,12 +969,12 @@ CSSMediaRuleImpl::SetStyleSheet(nsICSSStyleSheet* aSheet) return rv; } - return nsCSSRule::SetStyleSheet(aSheet); + return nsCSSGroupRule::SetStyleSheet(aSheet); } #ifdef DEBUG NS_IMETHODIMP -CSSMediaRuleImpl::List(FILE* out, PRInt32 aIndent) const +nsCSSMediaRule::List(FILE* out, PRInt32 aIndent) const { for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out); @@ -808,33 +995,22 @@ CSSMediaRuleImpl::List(FILE* out, PRInt32 aIndent) const } } } - fputs(" {\n", out); - if (mRules) { - PRUint32 index = 0; - PRUint32 count; - mRules->Count(&count); - while (index < count) { - nsCOMPtr rule = dont_AddRef((nsICSSRule*)mRules->ElementAt(index++)); - rule->List(out, aIndent + 1); - } - } - fputs("}\n", out); - return NS_OK; + return nsCSSGroupRule::List(out, aIndent); } #endif NS_IMETHODIMP -CSSMediaRuleImpl::GetType(PRInt32& aType) const +nsCSSMediaRule::GetType(PRInt32& aType) const { aType = nsICSSRule::MEDIA_RULE; return NS_OK; } NS_IMETHODIMP -CSSMediaRuleImpl::Clone(nsICSSRule*& aClone) const +nsCSSMediaRule::Clone(nsICSSRule*& aClone) const { - CSSMediaRuleImpl* clone = new CSSMediaRuleImpl(*this); + nsCSSMediaRule* clone = new nsCSSMediaRule(*this); if (clone) { return CallQueryInterface(clone, &aClone); } @@ -842,157 +1018,22 @@ CSSMediaRuleImpl::Clone(nsICSSRule*& aClone) const return NS_ERROR_OUT_OF_MEMORY; } -// nsICSSMediaRule methods -NS_IMETHODIMP -CSSMediaRuleImpl::SetMedia(nsISupportsArray* aMedia) +nsresult +nsCSSMediaRule::SetMedia(nsISupportsArray* aMedia) { return NS_NewMediaList(aMedia, mSheet, getter_AddRefs(mMedia)); } -NS_IMETHODIMP_(PRBool) -CSSMediaRuleImpl::UseForMedium(nsIAtom* aMedium) const -{ - if (mMedia) { - PRBool matches = PR_FALSE; - mMedia->MatchesMedium(aMedium, &matches); - return matches; - } - return PR_TRUE; -} - -NS_IMETHODIMP -CSSMediaRuleImpl::AppendStyleRule(nsICSSRule* aRule) -{ - nsresult result = NS_OK; - if (!mRules) { - result = NS_NewISupportsArray(getter_AddRefs(mRules)); - } - if (NS_SUCCEEDED(result) && mRules) { - mRules->AppendElement(aRule); - aRule->SetStyleSheet(mSheet); - aRule->SetParentRule(this); - if (mSheet) { - // XXXldb Shouldn't we be using |WillDirty| and |DidDirty| (and - // shouldn't |SetModified| be removed? - mSheet->SetModified(PR_TRUE); - } - } - return result; -} - -NS_IMETHODIMP -CSSMediaRuleImpl::StyleRuleCount(PRInt32& aCount) const -{ - if (mRules) { - PRUint32 count; - mRules->Count(&count); - aCount = (PRInt32)count; - } - else { - aCount = 0; - } - return NS_OK; -} - -NS_IMETHODIMP -CSSMediaRuleImpl::GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const -{ - if (mRules) { - PRInt32 count = 0; - nsresult rv = StyleRuleCount(count); - NS_ENSURE_SUCCESS(rv, rv); - if (aIndex >= count) { - aRule = nsnull; - return NS_ERROR_ILLEGAL_VALUE; - } - aRule = (nsICSSRule*)mRules->ElementAt(aIndex); - return NS_OK; - } - return NS_ERROR_ILLEGAL_VALUE; -} - -NS_IMETHODIMP -CSSMediaRuleImpl::EnumerateRulesForwards(nsISupportsArrayEnumFunc aFunc, void * aData) const -{ - if (mRules) { - return ((mRules->EnumerateForwards(aFunc, aData)) ? NS_OK : NS_ENUMERATOR_FALSE); - } - return NS_OK; -} - -/* - * The next two methods (DeleteStyleRuleAt and InsertStyleRulesAt) - * should never be called unless you have first called WillDirty() on - * the parents tylesheet. After they are called, DidDirty() needs to - * be called on the sheet - */ -NS_IMETHODIMP -CSSMediaRuleImpl::DeleteStyleRuleAt(PRUint32 aIndex) -{ - NS_ENSURE_TRUE(mRules, NS_ERROR_FAILURE); - - nsCOMPtr rule = dont_AddRef((nsICSSRule*)mRules->ElementAt(aIndex)); - if (rule) { - rule->SetStyleSheet(nsnull); - rule->SetParentRule(nsnull); - } - return mRules->DeleteElementAt(aIndex); -} - -NS_IMETHODIMP -CSSMediaRuleImpl::InsertStyleRulesAt(PRUint32 aIndex, nsISupportsArray* aRules) -{ - NS_ENSURE_TRUE(mRules, NS_ERROR_FAILURE); - - aRules->EnumerateForwards(SetStyleSheetReference, mSheet); - aRules->EnumerateForwards(SetParentRuleReference, - NS_STATIC_CAST(nsICSSGroupRule*, this)); - // There is no xpcom-compatible version of InsertElementsAt.... :( - if (! mRules->InsertElementsAt(aRules, aIndex)) { - return NS_ERROR_FAILURE; - } - return NS_OK; -} - -NS_IMETHODIMP -CSSMediaRuleImpl::ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew) -{ - PRInt32 index = mRules->IndexOf(aOld); - NS_ENSURE_TRUE(index != -1, NS_ERROR_UNEXPECTED); - mRules->ReplaceElementAt(aNew, index); - aNew->SetStyleSheet(mSheet); - aNew->SetParentRule(this); - aOld->SetStyleSheet(nsnull); - aOld->SetParentRule(nsnull); - return NS_OK; -} - -nsresult -NS_NewCSSMediaRule(nsICSSMediaRule** aInstancePtrResult) -{ - if (! aInstancePtrResult) { - return NS_ERROR_NULL_POINTER; - } - - CSSMediaRuleImpl* it = new CSSMediaRuleImpl(); - - if (! it) { - return NS_ERROR_OUT_OF_MEMORY; - } - - return CallQueryInterface(it, aInstancePtrResult); -} - // nsIDOMCSSRule methods NS_IMETHODIMP -CSSMediaRuleImpl::GetType(PRUint16* aType) +nsCSSMediaRule::GetType(PRUint16* aType) { *aType = nsIDOMCSSRule::MEDIA_RULE; return NS_OK; } NS_IMETHODIMP -CSSMediaRuleImpl::GetCssText(nsAString& aCssText) +nsCSSMediaRule::GetCssText(nsAString& aCssText) { PRUint32 index; PRUint32 count; @@ -1012,60 +1053,30 @@ CSSMediaRuleImpl::GetCssText(nsAString& aCssText) } } - aCssText.AppendLiteral(" {\n"); - - // get all the rules - if (mRules) { - mRules->Count(&count); - for (index = 0; index < count; index++) { - nsCOMPtr rule; - mRules->GetElementAt(index, getter_AddRefs(rule)); - nsCOMPtr domRule; - rule->GetDOMRule(getter_AddRefs(domRule)); - if (domRule) { - nsAutoString cssText; - domRule->GetCssText(cssText); - aCssText.Append(NS_LITERAL_STRING(" ") + - cssText + - NS_LITERAL_STRING("\n")); - } - } - } - - aCssText.AppendLiteral("}"); - - return NS_OK; + return nsCSSGroupRule::AppendRulesToCssText(aCssText); } NS_IMETHODIMP -CSSMediaRuleImpl::SetCssText(const nsAString& aCssText) +nsCSSMediaRule::SetCssText(const nsAString& aCssText) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -CSSMediaRuleImpl::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) +nsCSSMediaRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) { - if (mSheet) { - return CallQueryInterface(mSheet, aSheet); - } - *aSheet = nsnull; - return NS_OK; + return nsCSSGroupRule::GetParentStyleSheet(aSheet); } NS_IMETHODIMP -CSSMediaRuleImpl::GetParentRule(nsIDOMCSSRule** aParentRule) +nsCSSMediaRule::GetParentRule(nsIDOMCSSRule** aParentRule) { - if (mParentRule) { - return mParentRule->GetDOMRule(aParentRule); - } - *aParentRule = nsnull; - return NS_OK; + return nsCSSGroupRule::GetParentRule(aParentRule); } // nsIDOMCSSMediaRule methods NS_IMETHODIMP -CSSMediaRuleImpl::GetMedia(nsIDOMMediaList* *aMedia) +nsCSSMediaRule::GetMedia(nsIDOMMediaList* *aMedia) { NS_ENSURE_ARG_POINTER(aMedia); if (!mMedia) { @@ -1077,54 +1088,225 @@ CSSMediaRuleImpl::GetMedia(nsIDOMMediaList* *aMedia) } NS_IMETHODIMP -CSSMediaRuleImpl::GetCssRules(nsIDOMCSSRuleList* *aRuleList) +nsCSSMediaRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList) { - if (!mRuleCollection) { - mRuleCollection = new CSSGroupRuleRuleListImpl(this); - if (!mRuleCollection) { - return NS_ERROR_OUT_OF_MEMORY; + return nsCSSGroupRule::GetCssRules(aRuleList); +} + +NS_IMETHODIMP +nsCSSMediaRule::InsertRule(const nsAString & aRule, PRUint32 aIndex, PRUint32* _retval) +{ + return nsCSSGroupRule::InsertRule(aRule, aIndex, _retval); +} + +NS_IMETHODIMP +nsCSSMediaRule::DeleteRule(PRUint32 aIndex) +{ + return nsCSSGroupRule::DeleteRule(aIndex); +} + +// nsICSSGroupRule interface +NS_IMETHODIMP_(PRBool) +nsCSSMediaRule::UseForPresentation(nsPresContext* aPresContext) +{ + if (mMedia) { + PRBool matches = PR_FALSE; + mMedia->MatchesMedium(aPresContext->Medium(), &matches); + return matches; + } + return PR_TRUE; +} + + +nsCSSDocumentRule::nsCSSDocumentRule(void) +{ +} + +nsCSSDocumentRule::nsCSSDocumentRule(const nsCSSDocumentRule& aCopy) + : nsCSSGroupRule(aCopy) + , mURLs(new URL(*aCopy.mURLs)) +{ +} + +nsCSSDocumentRule::~nsCSSDocumentRule(void) +{ +} + +NS_IMPL_ADDREF_INHERITED(nsCSSDocumentRule, nsCSSRule) +NS_IMPL_RELEASE_INHERITED(nsCSSDocumentRule, nsCSSRule) + +// QueryInterface implementation for nsCSSDocumentRule +NS_INTERFACE_MAP_BEGIN(nsCSSDocumentRule) + NS_INTERFACE_MAP_ENTRY(nsICSSGroupRule) + NS_INTERFACE_MAP_ENTRY(nsICSSRule) + NS_INTERFACE_MAP_ENTRY(nsIStyleRule) + NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) + NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMozDocumentRule) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsCSSGroupRule) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSMozDocumentRule) +NS_INTERFACE_MAP_END + +#ifdef DEBUG +NS_IMETHODIMP +nsCSSDocumentRule::List(FILE* out, PRInt32 aIndent) const +{ + for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out); + + nsCAutoString str; + str.AssignLiteral("@-moz-document "); + for (URL *url = mURLs; url; url = url->next) { + switch (url->func) { + case eURL: + str.AppendLiteral("url(\""); + break; + case eURLPrefix: + str.AppendLiteral("url-prefix(\""); + break; + case eDomain: + str.AppendLiteral("domain(\""); + break; } - NS_ADDREF(mRuleCollection); + nsCAutoString escapedURL(url->url); + escapedURL.ReplaceSubstring("\"", "\\\""); // escape quotes + str.Append(escapedURL); + str.AppendLiteral("\"), "); } + str.Cut(str.Length() - 2, 1); // remove last , + fputs(str.get(), out); - return CallQueryInterface(mRuleCollection, aRuleList); + return nsCSSGroupRule::List(out, aIndent); +} +#endif + +NS_IMETHODIMP +nsCSSDocumentRule::GetType(PRInt32& aType) const +{ + aType = nsICSSRule::DOCUMENT_RULE; + return NS_OK; } NS_IMETHODIMP -CSSMediaRuleImpl::InsertRule(const nsAString & aRule, PRUint32 aIndex, PRUint32* _retval) +nsCSSDocumentRule::Clone(nsICSSRule*& aClone) const { - NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE); - - if (!mRules) { - nsresult rv = NS_NewISupportsArray(getter_AddRefs(mRules)); - if (NS_FAILED(rv)) - return rv; + nsCSSDocumentRule* clone = new nsCSSDocumentRule(*this); + if (clone) { + return CallQueryInterface(clone, &aClone); } + aClone = nsnull; + return NS_ERROR_OUT_OF_MEMORY; +} - PRUint32 count; - mRules->Count(&count); - if (aIndex > count) - return NS_ERROR_DOM_INDEX_SIZE_ERR; - - return mSheet->InsertRuleIntoGroup(aRule, this, aIndex, _retval); +// nsIDOMCSSRule methods +NS_IMETHODIMP +nsCSSDocumentRule::GetType(PRUint16* aType) +{ + // XXX What should really happen here? + *aType = nsIDOMCSSRule::UNKNOWN_RULE; + return NS_OK; } NS_IMETHODIMP -CSSMediaRuleImpl::DeleteRule(PRUint32 aIndex) +nsCSSDocumentRule::GetCssText(nsAString& aCssText) { - NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE); - if (!mRules) { - return NS_ERROR_DOM_INDEX_SIZE_ERR; + aCssText.AssignLiteral("@-moz-document "); + for (URL *url = mURLs; url; url = url->next) { + switch (url->func) { + case eURL: + aCssText.AppendLiteral("url(\""); + break; + case eURLPrefix: + aCssText.AppendLiteral("url-prefix(\""); + break; + case eDomain: + aCssText.AppendLiteral("domain(\""); + break; + } + nsCAutoString escapedURL(url->url); + escapedURL.ReplaceSubstring("\"", "\\\""); // escape quotes + AppendUTF8toUTF16(escapedURL, aCssText); + aCssText.AppendLiteral("\"), "); } - - PRUint32 count; - mRules->Count(&count); - if (aIndex >= count) - return NS_ERROR_DOM_INDEX_SIZE_ERR; + aCssText.Cut(aCssText.Length() - 2, 1); // remove last , - return mSheet->DeleteRuleFromGroup(this, aIndex); + return nsCSSGroupRule::AppendRulesToCssText(aCssText); } +NS_IMETHODIMP +nsCSSDocumentRule::SetCssText(const nsAString& aCssText) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsCSSDocumentRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) +{ + return nsCSSGroupRule::GetParentStyleSheet(aSheet); +} + +NS_IMETHODIMP +nsCSSDocumentRule::GetParentRule(nsIDOMCSSRule** aParentRule) +{ + return nsCSSGroupRule::GetParentRule(aParentRule); +} + +NS_IMETHODIMP +nsCSSDocumentRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList) +{ + return nsCSSGroupRule::GetCssRules(aRuleList); +} + +NS_IMETHODIMP +nsCSSDocumentRule::InsertRule(const nsAString & aRule, PRUint32 aIndex, PRUint32* _retval) +{ + return nsCSSGroupRule::InsertRule(aRule, aIndex, _retval); +} + +NS_IMETHODIMP +nsCSSDocumentRule::DeleteRule(PRUint32 aIndex) +{ + return nsCSSGroupRule::DeleteRule(aIndex); +} + +// nsICSSGroupRule interface +NS_IMETHODIMP_(PRBool) +nsCSSDocumentRule::UseForPresentation(nsPresContext* aPresContext) +{ + nsIURI *docURI = aPresContext->GetDocument()->GetDocumentURI(); + nsCAutoString docURISpec; + if (docURI) + docURI->GetSpec(docURISpec); + + for (URL *url = mURLs; url; url = url->next) { + switch (url->func) { + case eURL: { + if (docURISpec == url->url) + return PR_TRUE; + } break; + case eURLPrefix: { + if (StringBeginsWith(docURISpec, url->url)) + return PR_TRUE; + } break; + case eDomain: { + nsCAutoString host; + if (docURI) + docURI->GetHost(host); + PRInt32 lenDiff = host.Length() - url->url.Length(); + if (lenDiff == 0) { + if (host == url->url) + return PR_TRUE; + } else { + if (StringEndsWith(host, url->url) && + host.CharAt(lenDiff - 1) == '.') + return PR_TRUE; + } + } break; + } + } + + return PR_FALSE; +} + + // ------------------------------------------- // nsICSSNameSpaceRule // @@ -1294,6 +1476,7 @@ NS_NewCSSNameSpaceRule(nsICSSNameSpaceRule** aInstancePtrResult, NS_IMETHODIMP CSSNameSpaceRuleImpl::GetType(PRUint16* aType) { + // XXX What should really happen here? *aType = nsIDOMCSSRule::UNKNOWN_RULE; return NS_OK; } diff --git a/mozilla/layout/style/nsCSSRules.h b/mozilla/layout/style/nsCSSRules.h new file mode 100644 index 00000000000..994686e9146 --- /dev/null +++ b/mozilla/layout/style/nsCSSRules.h @@ -0,0 +1,199 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +// vim:cindent:ts=2:et:sw=2: +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * L. David Baron + * Boris Zbarsky + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsCSSRules_h_ +#define nsCSSRules_h_ + +#include "nsCSSRule.h" +#include "nsICSSGroupRule.h" +#include "nsCOMPtr.h" +#include "nsAutoPtr.h" +#include "nsISupportsArray.h" +#include "nsIDOMCSSMediaRule.h" +#include "nsIDOMCSSMozDocumentRule.h" +#include "nsString.h" + +class CSSGroupRuleRuleListImpl; +class nsIMediaList; + +#define DECL_STYLE_RULE_INHERIT \ +NS_IMETHOD GetStyleSheet(nsIStyleSheet*& aSheet) const; \ +NS_IMETHOD SetStyleSheet(nsICSSStyleSheet* aSheet); \ +NS_IMETHOD SetParentRule(nsICSSGroupRule* aRule); \ +NS_IMETHOD GetDOMRule(nsIDOMCSSRule** aDOMRule); \ +NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData); + +// inherits from nsCSSRule and also implements methods on nsICSSGroupRule +// so they can be shared between nsCSSMediaRule and nsCSSDocumentRule +class nsCSSGroupRule : public nsCSSRule, public nsICSSGroupRule +{ +protected: + nsCSSGroupRule(); + nsCSSGroupRule(const nsCSSGroupRule& aCopy); + ~nsCSSGroupRule(); + + // implement part of nsIStyleRule and nsICSSRule + DECL_STYLE_RULE_INHERIT + + // to help implement nsIStyleRule +#ifdef DEBUG + nsresult List(FILE* out = stdout, PRInt32 aIndent = 0) const; +#endif + +public: + // implement nsICSSGroupRule + NS_IMETHOD AppendStyleRule(nsICSSRule* aRule); + NS_IMETHOD StyleRuleCount(PRInt32& aCount) const; + NS_IMETHOD GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const; + NS_IMETHOD EnumerateRulesForwards(nsISupportsArrayEnumFunc aFunc, void * aData) const; + NS_IMETHOD DeleteStyleRuleAt(PRUint32 aIndex); + NS_IMETHOD InsertStyleRulesAt(PRUint32 aIndex, nsISupportsArray* aRules); + NS_IMETHOD ReplaceStyleRule(nsICSSRule *aOld, nsICSSRule *aNew); + +protected: + // to help implement nsIDOMCSSRule + nsresult AppendRulesToCssText(nsAString& aCssText); + // to implement methods on nsIDOMCSSRule + nsresult GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet); + nsresult GetParentRule(nsIDOMCSSRule** aParentRule); + + // to implement common methods on nsIDOMCSSMediaRule and + // nsIDOMCSSMozDocumentRule + nsresult GetCssRules(nsIDOMCSSRuleList* *aRuleList); + nsresult InsertRule(const nsAString & aRule, PRUint32 aIndex, + PRUint32* _retval); + nsresult DeleteRule(PRUint32 aIndex); + + nsCOMPtr mRules; + CSSGroupRuleRuleListImpl* mRuleCollection; +}; + +class nsCSSMediaRule : public nsCSSGroupRule, + public nsIDOMCSSMediaRule +{ +public: + nsCSSMediaRule(); + nsCSSMediaRule(const nsCSSMediaRule& aCopy); + virtual ~nsCSSMediaRule(); + + NS_DECL_ISUPPORTS_INHERITED + + // nsIStyleRule methods +#ifdef DEBUG + NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const; +#endif + + // nsICSSRule methods + NS_IMETHOD SetStyleSheet(nsICSSStyleSheet* aSheet); //override nsCSSGroupRule + NS_IMETHOD GetType(PRInt32& aType) const; + NS_IMETHOD Clone(nsICSSRule*& aClone) const; + + // nsIDOMCSSRule interface + NS_DECL_NSIDOMCSSRULE + + // nsIDOMCSSMediaRule interface + NS_DECL_NSIDOMCSSMEDIARULE + + // rest of nsICSSGroupRule interface + NS_IMETHOD_(PRBool) UseForPresentation(nsPresContext* aPresContext); + + // @media rule methods + nsresult SetMedia(nsISupportsArray* aMedia); + +protected: + nsCOMPtr mMedia; +}; + +class nsCSSDocumentRule : public nsCSSGroupRule, + public nsIDOMCSSMozDocumentRule +{ +public: + nsCSSDocumentRule(void); + nsCSSDocumentRule(const nsCSSDocumentRule& aCopy); + virtual ~nsCSSDocumentRule(void); + + NS_DECL_ISUPPORTS_INHERITED + + // nsIStyleRule methods +#ifdef DEBUG + NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const; +#endif + + // nsICSSRule methods + NS_IMETHOD GetType(PRInt32& aType) const; + NS_IMETHOD Clone(nsICSSRule*& aClone) const; + + // nsIDOMCSSRule interface + NS_DECL_NSIDOMCSSRULE + + // nsIDOMCSSMozDocumentRule interface + NS_DECL_NSIDOMCSSMOZDOCUMENTRULE + + // rest of nsICSSGroupRule interface + NS_IMETHOD_(PRBool) UseForPresentation(nsPresContext* aPresContext); + + enum Function { + eURL, + eURLPrefix, + eDomain + }; + + struct URL { + nsCSSDocumentRule::Function func; + nsCString url; + URL *next; + + URL() : next(nsnull) {} + URL(const URL& aOther) + : func(aOther.func) + , url(aOther.url) + , next(new URL(*aOther.next)) + { + } + ~URL() { delete next; } + }; + + void SetURLs(URL *aURLs) { mURLs = aURLs; } + +protected: + nsAutoPtr mURLs; // linked list of |struct URL| above. +}; + + +#endif /* !defined(nsCSSRules_h_) */ diff --git a/mozilla/layout/style/nsCSSStyleSheet.cpp b/mozilla/layout/style/nsCSSStyleSheet.cpp index f80e0e417de..b8cc796498f 100644 --- a/mozilla/layout/style/nsCSSStyleSheet.cpp +++ b/mozilla/layout/style/nsCSSStyleSheet.cpp @@ -55,7 +55,7 @@ #include "nsCSSRuleProcessor.h" #include "nsICSSStyleRule.h" #include "nsICSSNameSpaceRule.h" -#include "nsICSSMediaRule.h" +#include "nsICSSGroupRule.h" #include "nsIMediaList.h" #include "nsIStyledContent.h" #include "nsIDocument.h" @@ -3589,13 +3589,12 @@ static void ContentEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector, } NS_IMETHODIMP -nsCSSRuleProcessor::RulesMatching(ElementRuleProcessorData *aData, - nsIAtom* aMedium) +nsCSSRuleProcessor::RulesMatching(ElementRuleProcessorData *aData) { NS_PRECONDITION(aData->mContent->IsContentOfType(nsIContent::eELEMENT), "content must be element"); - RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext, aMedium); + RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext); if (cascade) { nsIStyledContent* styledContent = aData->mStyledContent; @@ -3659,14 +3658,13 @@ static void PseudoEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector, } NS_IMETHODIMP -nsCSSRuleProcessor::RulesMatching(PseudoRuleProcessorData* aData, - nsIAtom* aMedium) +nsCSSRuleProcessor::RulesMatching(PseudoRuleProcessorData* aData) { NS_PRECONDITION(!aData->mContent || aData->mContent->IsContentOfType(nsIContent::eELEMENT), "content (if present) must be element"); - RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext, aMedium); + RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext); if (cascade) { cascade->mRuleHash.EnumerateTagRules(aData->mPseudoTag, @@ -3708,13 +3706,12 @@ PR_STATIC_CALLBACK(PRBool) StateEnumFunc(void* aSelector, void* aData) NS_IMETHODIMP nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult) { NS_PRECONDITION(aData->mContent->IsContentOfType(nsIContent::eELEMENT), "content must be element"); - RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext, aMedium); + RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext); // Look up the content node in the state rule list, which points to // any (CSS2 definition) simple selector (whether or not it is the @@ -3759,7 +3756,6 @@ PR_STATIC_CALLBACK(PRBool) AttributeEnumFunc(void* aSelector, void* aData) NS_IMETHODIMP nsCSSRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult) { NS_PRECONDITION(aData->mContent->IsContentOfType(nsIContent::eELEMENT), @@ -3779,7 +3775,7 @@ nsCSSRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData } // XXX What about XLinks? - RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext, aMedium); + RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext); // We do the same thing for attributes that we do for state selectors // (see HasStateDependentStyle), except that instead of one big list @@ -3900,14 +3896,14 @@ RuleArraysDestroy(nsHashKey *aKey, void *aData, void *aClosure) } struct CascadeEnumData { - CascadeEnumData(nsIAtom* aMedium, PLArenaPool& aArena) - : mMedium(aMedium), + CascadeEnumData(nsPresContext* aPresContext, PLArenaPool& aArena) + : mPresContext(aPresContext), mRuleArrays(nsnull, nsnull, RuleArraysDestroy, nsnull, 64), mArena(aArena) { } - nsIAtom* mMedium; + nsPresContext* mPresContext; nsObjectHashtable mRuleArrays; // of nsAutoVoidArray PLArenaPool& mArena; }; @@ -3939,11 +3935,11 @@ InsertRuleByWeight(nsISupports* aRule, void* aData) rules->AppendElement(info); } } - else if (nsICSSRule::MEDIA_RULE == type) { - nsICSSMediaRule* mediaRule = (nsICSSMediaRule*)rule; - if (mediaRule->UseForMedium(data->mMedium)) { - mediaRule->EnumerateRulesForwards(InsertRuleByWeight, aData); - } + else if (nsICSSRule::MEDIA_RULE == type || + nsICSSRule::DOCUMENT_RULE == type) { + nsICSSGroupRule* groupRule = (nsICSSGroupRule*)rule; + if (groupRule->UseForPresentation(data->mPresContext)) + groupRule->EnumerateRulesForwards(InsertRuleByWeight, aData); } return PR_TRUE; } @@ -3957,7 +3953,7 @@ CascadeSheetRulesInto(nsICSSStyleSheet* aSheet, void* aData) PRBool bSheetApplicable = PR_TRUE; sheet->GetApplicable(bSheetApplicable); - if (bSheetApplicable && sheet->UseForMedium(data->mMedium)) { + if (bSheetApplicable && sheet->UseForMedium(data->mPresContext->Medium())) { nsCSSStyleSheet* child = sheet->mFirstChild; while (child) { CascadeSheetRulesInto(child, data); @@ -4030,22 +4026,28 @@ static void PutRulesInList(nsObjectHashtable* aRuleArrays, } RuleCascadeData* -nsCSSRuleProcessor::GetRuleCascade(nsPresContext* aPresContext, - nsIAtom* aMedium) +nsCSSRuleProcessor::GetRuleCascade(nsPresContext* aPresContext) { + // Having RuleCascadeData objects be per-medium works for now since + // nsCSSRuleProcessor objects are per-document. (For a given set + // of stylesheets they can vary based on medium (@media) or document + // (@-moz-document).) Things will get a little more complicated if + // we implement media queries, though. + RuleCascadeData **cascadep = &mRuleCascades; RuleCascadeData *cascade; + nsIAtom *medium = aPresContext->Medium(); while ((cascade = *cascadep)) { - if (cascade->mMedium == aMedium) + if (cascade->mMedium == medium) return cascade; cascadep = &cascade->mNext; } if (mSheets.Count() != 0) { - cascade = new RuleCascadeData(aMedium, + cascade = new RuleCascadeData(medium, eCompatibility_NavQuirks == aPresContext->CompatibilityMode()); if (cascade) { - CascadeEnumData data(aMedium, cascade->mRuleHash.Arena()); + CascadeEnumData data(aPresContext, cascade->mRuleHash.Arena()); mSheets.EnumerateForwards(CascadeSheetRulesInto, &data); nsVoidArray weightedRules; PutRulesInList(&data.mRuleArrays, &weightedRules); diff --git a/mozilla/layout/style/nsHTMLCSSStyleSheet.cpp b/mozilla/layout/style/nsHTMLCSSStyleSheet.cpp index b9d4ee0b2fb..cf65efc5a68 100644 --- a/mozilla/layout/style/nsHTMLCSSStyleSheet.cpp +++ b/mozilla/layout/style/nsHTMLCSSStyleSheet.cpp @@ -368,18 +368,14 @@ public: NS_IMETHOD SetOwningDocument(nsIDocument* aDocument); // nsIStyleRuleProcessor api - NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData, - nsIAtom* aMedium); + NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); - NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData, - nsIAtom* aMedium); + NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult); NS_IMETHOD HasAttributeDependentStyle(AttributeRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult); #ifdef DEBUG @@ -432,8 +428,7 @@ NS_IMPL_ISUPPORTS3(HTMLCSSStyleSheetImpl, nsIStyleRuleProcessor) NS_IMETHODIMP -HTMLCSSStyleSheetImpl::RulesMatching(ElementRuleProcessorData* aData, - nsIAtom* aMedium) +HTMLCSSStyleSheetImpl::RulesMatching(ElementRuleProcessorData* aData) { nsIStyledContent *styledContent = aData->mStyledContent; @@ -449,8 +444,7 @@ HTMLCSSStyleSheetImpl::RulesMatching(ElementRuleProcessorData* aData, } NS_IMETHODIMP -HTMLCSSStyleSheetImpl::RulesMatching(PseudoRuleProcessorData* aData, - nsIAtom* aMedium) +HTMLCSSStyleSheetImpl::RulesMatching(PseudoRuleProcessorData* aData) { // We only want to add these rules if there are real :first-letter or // :first-line rules that cause a pseudo-element frame to be created. @@ -500,7 +494,6 @@ HTMLCSSStyleSheetImpl::Init(nsIURI* aURL, nsIDocument* aDocument) // Test if style is dependent on content state NS_IMETHODIMP HTMLCSSStyleSheetImpl::HasStateDependentStyle(StateRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult) { *aResult = nsReStyleHint(0); @@ -510,7 +503,6 @@ HTMLCSSStyleSheetImpl::HasStateDependentStyle(StateRuleProcessorData* aData, // Test if style is dependent on attribute NS_IMETHODIMP HTMLCSSStyleSheetImpl::HasAttributeDependentStyle(AttributeRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult) { *aResult = nsReStyleHint(0); diff --git a/mozilla/layout/style/nsHTMLStyleSheet.cpp b/mozilla/layout/style/nsHTMLStyleSheet.cpp index 51d4e329922..2ffa87386f4 100644 --- a/mozilla/layout/style/nsHTMLStyleSheet.cpp +++ b/mozilla/layout/style/nsHTMLStyleSheet.cpp @@ -516,8 +516,7 @@ static nsresult GetBodyColor(nsPresContext* aPresContext, nscolor* aColor) } NS_IMETHODIMP -nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData, - nsIAtom* aMedium) +nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData) { nsIStyledContent *styledContent = aData->mStyledContent; @@ -599,7 +598,6 @@ nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData, // Test if style is dependent on content state NS_IMETHODIMP nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult) { if (mActiveRule && @@ -617,7 +615,6 @@ nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData, NS_IMETHODIMP nsHTMLStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult) { // Result is true for |href| changes on HTML links if we have link rules. @@ -646,8 +643,7 @@ nsHTMLStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData, NS_IMETHODIMP -nsHTMLStyleSheet::RulesMatching(PseudoRuleProcessorData* aData, - nsIAtom* aMedium) +nsHTMLStyleSheet::RulesMatching(PseudoRuleProcessorData* aData) { nsIAtom* pseudoTag = aData->mPseudoTag; if (pseudoTag == nsCSSAnonBoxes::tableCol) { diff --git a/mozilla/layout/style/nsHTMLStyleSheet.h b/mozilla/layout/style/nsHTMLStyleSheet.h index 4ab5d18d3e0..bb25a89484c 100644 --- a/mozilla/layout/style/nsHTMLStyleSheet.h +++ b/mozilla/layout/style/nsHTMLStyleSheet.h @@ -73,15 +73,11 @@ public: #endif // nsIStyleRuleProcessor API - NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData, - nsIAtom* aMedium); - NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData, - nsIAtom* aMedium); + NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); + NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult); NS_IMETHOD HasAttributeDependentStyle(AttributeRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult); nsresult Init(nsIURI* aURL, nsIDocument* aDocument); diff --git a/mozilla/layout/style/nsICSSGroupRule.h b/mozilla/layout/style/nsICSSGroupRule.h index 48b1434f3fa..6d9166e5356 100644 --- a/mozilla/layout/style/nsICSSGroupRule.h +++ b/mozilla/layout/style/nsICSSGroupRule.h @@ -41,6 +41,7 @@ #include "nsISupportsArray.h" class nsIAtom; +class nsPresContext; // IID for the nsICSSGroupRule interface {5af048aa-1af0-11d3-9d83-0060088f9ff7} #define NS_ICSS_GROUP_RULE_IID \ @@ -65,6 +66,8 @@ public: NS_IMETHOD DeleteStyleRuleAt(PRUint32 aIndex) = 0; NS_IMETHOD InsertStyleRulesAt(PRUint32 aIndex, nsISupportsArray* aRules) = 0; NS_IMETHOD ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew) = 0; + + NS_IMETHOD_(PRBool) UseForPresentation(nsPresContext* aPresContext) = 0; }; diff --git a/mozilla/layout/style/nsICSSRule.h b/mozilla/layout/style/nsICSSRule.h index 0c9502d8685..260bac340e4 100644 --- a/mozilla/layout/style/nsICSSRule.h +++ b/mozilla/layout/style/nsICSSRule.h @@ -60,7 +60,8 @@ public: FONT_FACE_RULE = 4, PAGE_RULE = 5, CHARSET_RULE = 6, - NAMESPACE_RULE = 7 + NAMESPACE_RULE = 7, + DOCUMENT_RULE = 8 }; NS_IMETHOD GetType(PRInt32& aType) const = 0; diff --git a/mozilla/layout/style/nsIStyleRuleProcessor.h b/mozilla/layout/style/nsIStyleRuleProcessor.h index 81e321cbf4a..4e229c7437d 100644 --- a/mozilla/layout/style/nsIStyleRuleProcessor.h +++ b/mozilla/layout/style/nsIStyleRuleProcessor.h @@ -179,11 +179,9 @@ public: // populate rule node tree with nsIStyleRule* // rules are ordered, those with higher precedence are farthest from the root of the tree - NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData, - nsIAtom* aMedium) = 0; + NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData) = 0; - NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData, - nsIAtom* aMedium) = 0; + NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData) = 0; /** * Test whether style is dependent on content state. This test is @@ -193,7 +191,6 @@ public: * Event states are defined in nsIEventStateManager.h. */ NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult) = 0; /** @@ -202,7 +199,6 @@ public: * the side of reporting more dependencies than really exist. */ NS_IMETHOD HasAttributeDependentStyle(AttributeRuleProcessorData* aData, - nsIAtom* aMedium, nsReStyleHint* aResult) = 0; }; diff --git a/mozilla/layout/style/nsStyleSet.cpp b/mozilla/layout/style/nsStyleSet.cpp index 9996055333e..cb87d487f43 100644 --- a/mozilla/layout/style/nsStyleSet.cpp +++ b/mozilla/layout/style/nsStyleSet.cpp @@ -329,23 +329,13 @@ nsStyleSet::EnableQuirkStyleSheet(PRBool aEnable) } } -struct RulesMatchingData : public ElementRuleProcessorData { - RulesMatchingData(nsPresContext* aPresContext, - nsIContent* aContent, - nsRuleWalker* aRuleWalker) - : ElementRuleProcessorData(aPresContext, aContent, aRuleWalker), - mMedium(aPresContext->Medium()) - { - } - nsIAtom* mMedium; -}; - static PRBool EnumRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData) { - RulesMatchingData* data = (RulesMatchingData*)aData; + ElementRuleProcessorData* data = + NS_STATIC_CAST(ElementRuleProcessorData*, aData); - aProcessor->RulesMatching(data, data->mMedium); + aProcessor->RulesMatching(data); return PR_TRUE; } @@ -588,7 +578,7 @@ nsStyleSet::ResolveStyleFor(nsIContent* aContent, mRuleProcessors[eDocSheet] || mRuleProcessors[eStyleAttrSheet] || mRuleProcessors[eOverrideSheet]) { - RulesMatchingData data(presContext, aContent, mRuleWalker); + ElementRuleProcessorData data(presContext, aContent, mRuleWalker); FileRules(EnumRulesMatching, &data); result = GetContext(presContext, aParentContext, nsnull).get(); @@ -624,26 +614,13 @@ nsStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext) } -struct PseudoRulesMatchingData : public PseudoRuleProcessorData { - PseudoRulesMatchingData(nsPresContext* aPresContext, - nsIContent* aParentContent, - nsIAtom* aPseudoTag, - nsICSSPseudoComparator* aComparator, - nsRuleWalker* aRuleWalker) - : PseudoRuleProcessorData(aPresContext, aParentContent, aPseudoTag, - aComparator, aRuleWalker), - mMedium(aPresContext->Medium()) - { - } - nsIAtom* mMedium; -}; - static PRBool EnumPseudoRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData) { - PseudoRulesMatchingData* data = (PseudoRulesMatchingData*)aData; + PseudoRuleProcessorData* data = + NS_STATIC_CAST(PseudoRuleProcessorData*, aData); - aProcessor->RulesMatching(data, data->mMedium); + aProcessor->RulesMatching(data); return PR_TRUE; } @@ -669,7 +646,7 @@ nsStyleSet::ResolvePseudoStyleFor(nsIContent* aParentContent, mRuleProcessors[eDocSheet] || mRuleProcessors[eStyleAttrSheet] || mRuleProcessors[eOverrideSheet]) { - PseudoRulesMatchingData data(presContext, aParentContent, aPseudoTag, + PseudoRuleProcessorData data(presContext, aParentContent, aPseudoTag, aComparator, mRuleWalker); FileRules(EnumPseudoRulesMatching, &data); @@ -704,7 +681,7 @@ nsStyleSet::ProbePseudoStyleFor(nsIContent* aParentContent, mRuleProcessors[eDocSheet] || mRuleProcessors[eStyleAttrSheet] || mRuleProcessors[eOverrideSheet]) { - PseudoRulesMatchingData data(presContext, aParentContent, aPseudoTag, + PseudoRuleProcessorData data(presContext, aParentContent, aPseudoTag, nsnull, mRuleWalker); FileRules(EnumPseudoRulesMatching, &data); @@ -831,10 +808,8 @@ struct StatefulData : public StateRuleProcessorData { StatefulData(nsPresContext* aPresContext, nsIContent* aContent, PRInt32 aStateMask) : StateRuleProcessorData(aPresContext, aContent, aStateMask), - mMedium(aPresContext->Medium()), mHint(nsReStyleHint(0)) {} - nsIAtom* mMedium; nsReStyleHint mHint; }; @@ -843,7 +818,7 @@ static PRBool SheetHasStatefulStyle(nsIStyleRuleProcessor* aProcessor, { StatefulData* data = (StatefulData*)aData; nsReStyleHint hint; - aProcessor->HasStateDependentStyle(data, data->mMedium, &hint); + aProcessor->HasStateDependentStyle(data, &hint); data->mHint = nsReStyleHint(data->mHint | hint); return PR_TRUE; // continue } @@ -876,10 +851,8 @@ struct AttributeData : public AttributeRuleProcessorData { AttributeData(nsPresContext* aPresContext, nsIContent* aContent, nsIAtom* aAttribute, PRInt32 aModType) : AttributeRuleProcessorData(aPresContext, aContent, aAttribute, aModType), - mMedium(aPresContext->Medium()), mHint(nsReStyleHint(0)) {} - nsIAtom* mMedium; nsReStyleHint mHint; }; @@ -888,7 +861,7 @@ SheetHasAttributeStyle(nsIStyleRuleProcessor* aProcessor, void *aData) { AttributeData* data = (AttributeData*)aData; nsReStyleHint hint; - aProcessor->HasAttributeDependentStyle(data, data->mMedium, &hint); + aProcessor->HasAttributeDependentStyle(data, &hint); data->mHint = nsReStyleHint(data->mHint | hint); return PR_TRUE; // continue } diff --git a/mozilla/profile/defaults/chrome/userContent-example.css b/mozilla/profile/defaults/chrome/userContent-example.css index bd796919f9e..59cca32f08b 100644 --- a/mozilla/profile/defaults/chrome/userContent-example.css +++ b/mozilla/profile/defaults/chrome/userContent-example.css @@ -28,6 +28,14 @@ * marquee { -moz-binding: none; } * */ + +/* + * example: make search fields on www.mozilla.org white-on-black + * + * @-moz-document url-prefix(http://www.mozilla.org/) { + * #q { background: white ! important; color: black ! important; } + * } + */ /* * For more examples see http://www.mozilla.org/unix/customizing.html