From 168fa487a7375e4eb12b19a04dc11ad904495b62 Mon Sep 17 00:00:00 2001 From: "bzbarsky%mit.edu" Date: Wed, 5 Sep 2001 00:00:18 +0000 Subject: [PATCH] Fix the nsIDOMMediaList interface to have the right properties. Make media rules implement nsIDOMCSSMediaRule. Fix insertRule() to be able to insert into the middle of a rule list. Fix issues with stylesheets not getting dirtied when media lists are modified. bug 93977, r=pierre, sr=jst --- content/base/public/nsIStyleSheet.h | 2 +- content/html/style/public/nsICSSParser.h | 4 + content/html/style/public/nsICSSStyleSheet.h | 5 + content/html/style/public/nsIMediaList.h | 18 +- content/html/style/src/nsCSSParser.cpp | 170 +++-- content/html/style/src/nsCSSRules.cpp | 279 +++++++-- content/html/style/src/nsCSSStyleSheet.cpp | 582 ++++++++++++++---- .../html/style/src/nsHTMLCSSStyleSheet.cpp | 6 +- content/html/style/src/nsHTMLStyleSheet.cpp | 6 +- content/html/style/src/nsICSSGroupRule.h | 11 + content/html/style/src/nsICSSMediaRule.h | 2 +- .../idl/stylesheets/nsIDOMMediaList.idl | 4 +- dom/public/nsIDOMClassInfo.h | 1 + dom/src/base/nsDOMClassInfo.cpp | 8 +- layout/style/nsCSSParser.cpp | 170 +++-- layout/style/nsCSSRules.cpp | 279 +++++++-- layout/style/nsCSSStyleSheet.cpp | 582 ++++++++++++++---- layout/style/nsHTMLCSSStyleSheet.cpp | 6 +- layout/style/nsHTMLStyleSheet.cpp | 6 +- layout/style/nsICSSGroupRule.h | 11 + layout/style/nsICSSParser.h | 4 + layout/style/nsICSSStyleSheet.h | 5 + layout/style/nsIMediaList.h | 18 +- layout/style/nsIStyleSheet.h | 2 +- 24 files changed, 1751 insertions(+), 430 deletions(-) diff --git a/content/base/public/nsIStyleSheet.h b/content/base/public/nsIStyleSheet.h index a69e99ccd68..87c1ccf1806 100644 --- a/content/base/public/nsIStyleSheet.h +++ b/content/base/public/nsIStyleSheet.h @@ -52,7 +52,7 @@ public: NS_IMETHOD GetType(nsString& aType) const = 0; NS_IMETHOD GetMediumCount(PRInt32& aCount) const = 0; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const = 0; - NS_IMETHOD UseForMedium(nsIAtom* aMedium) const = 0; + NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const = 0; NS_IMETHOD GetEnabled(PRBool& aEnabled) const = 0; NS_IMETHOD SetEnabled(PRBool aEnabled) = 0; diff --git a/content/html/style/public/nsICSSParser.h b/content/html/style/public/nsICSSParser.h index e7ff6cc1541..6839164714a 100644 --- a/content/html/style/public/nsICSSParser.h +++ b/content/html/style/public/nsICSSParser.h @@ -75,6 +75,10 @@ public: PRBool aParseOnlyOneDecl, PRInt32* aHint) = 0; + NS_IMETHOD ParseRule(nsAReadableString& aRule, + nsIURI* aBaseURL, + nsIStyleRule** aResult) = 0; + // Charset management method: // Set the charset before calling any of the Parse emthods if you want the // charset to be anything other than the default diff --git a/content/html/style/public/nsICSSStyleSheet.h b/content/html/style/public/nsICSSStyleSheet.h index 475b9b6aa8e..bc919bc196a 100644 --- a/content/html/style/public/nsICSSStyleSheet.h +++ b/content/html/style/public/nsICSSStyleSheet.h @@ -24,12 +24,14 @@ #include "nslayout.h" #include "nsIStyleSheet.h" +#include "nsString.h" class nsICSSRule; class nsIDOMNode; class nsINameSpace; class nsICSSStyleRuleProcessor; class nsIMediaList; +class nsICSSGroupRule; // IID for the nsICSSStyleSheet interface {8f83b0f0-b21a-11d1-8031-006008159b5a} #define NS_ICSS_STYLE_SHEET_IID \ @@ -50,6 +52,9 @@ public: NS_IMETHOD StyleRuleCount(PRInt32& aCount) const = 0; NS_IMETHOD GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const = 0; + NS_IMETHOD DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex) = 0; + NS_IMETHOD InsertRuleIntoGroup(nsAReadableString & aRule, nsICSSGroupRule* aGroup, PRUint32 aIndex, PRUint32* _retval) = 0; + NS_IMETHOD StyleSheetCount(PRInt32& aCount) const = 0; NS_IMETHOD GetStyleSheetAt(PRInt32 aIndex, nsICSSStyleSheet*& aSheet) const = 0; diff --git a/content/html/style/public/nsIMediaList.h b/content/html/style/public/nsIMediaList.h index 95076e732df..695c737beed 100644 --- a/content/html/style/public/nsIMediaList.h +++ b/content/html/style/public/nsIMediaList.h @@ -31,15 +31,25 @@ class nsIMediaList : public nsISupportsArray { public: static const nsIID& GetIID() { static nsIID iid = NS_IMEDIA_LIST_IID; return iid; } - NS_IMETHOD GetMediaText(nsAWritableString& aMediaText) = 0; - NS_IMETHOD SetMediaText(nsAReadableString& aMediaText) = 0; - + NS_IMETHOD GetText(nsAWritableString& aMediaText) = 0; + NS_IMETHOD SetText(nsAReadableString& aMediaText) = 0; + NS_IMETHOD MatchesMedium(nsIAtom* aMedium, PRBool* aMatch) = 0; + NS_IMETHOD DropReference(void) = 0; }; +/* Use this macro when declaring classes that implement this interface. */ +#define NS_DECL_NSIMEDIALIST \ + NS_IMETHOD GetText(nsAWritableString& aMediaText); \ + NS_IMETHOD SetText(nsAReadableString& aMediaText); \ + NS_IMETHOD MatchesMedium(nsIAtom* aMedium, PRBool* aMatch); \ + NS_IMETHOD DropReference(void); + extern NS_HTML nsresult -NS_NewMediaList(nsIMediaList** aInstancePtrResult, const nsAReadableString& aMediaText); +NS_NewMediaList(const nsAReadableString& aMediaText, nsIMediaList** aInstancePtrResult); extern NS_HTML nsresult NS_NewMediaList(nsIMediaList** aInstancePtrResult); +extern NS_HTML nsresult +NS_NewMediaList(nsISupportsArray* aArray, nsICSSStyleSheet* aSheet, nsIMediaList** aInstancePtrResult); #endif /* nsICSSLoader_h___ */ diff --git a/content/html/style/src/nsCSSParser.cpp b/content/html/style/src/nsCSSParser.cpp index 0b7c810b1b3..d66334a548e 100644 --- a/content/html/style/src/nsCSSParser.cpp +++ b/content/html/style/src/nsCSSParser.cpp @@ -154,6 +154,10 @@ public: PRBool aParseOnlyOneDecl, PRInt32* aHint); + NS_IMETHOD ParseRule(nsAReadableString& aRule, + nsIURI* aBaseURL, + nsIStyleRule** aResult); + NS_IMETHOD GetCharset(/*out*/nsAWritableString &aCharsetDest) const; // sets the out-param to the current charset, as set by SetCharset NS_IMETHOD SetCharset(/*in*/ const nsAReadableString &aCharsetSrc); @@ -180,18 +184,18 @@ protected: void PopGroup(void); void AppendRule(nsICSSRule* aRule); - PRBool ParseRuleSet(PRInt32& aErrorCode); - PRBool ParseAtRule(PRInt32& aErrorCode); - PRBool ParseCharsetRule(PRInt32& aErrorCode); - PRBool ParseImportRule(PRInt32& aErrorCode); + PRBool ParseRuleSet(PRInt32& aErrorCode, nsIStyleRule** aResult = nsnull); + PRBool ParseAtRule(PRInt32& aErrorCode, nsIStyleRule** aResult = nsnull); + PRBool ParseCharsetRule(PRInt32& aErrorCode, nsIStyleRule** aResult); + PRBool ParseImportRule(PRInt32& aErrorCode, nsIStyleRule** aResult); PRBool GatherMedia(PRInt32& aErrorCode, nsString& aMedia, nsISupportsArray* aMediaAtoms); - PRBool ProcessImport(PRInt32& aErrorCode, const nsString& aURLSpec, const nsString& aMedia); - PRBool ParseMediaRule(PRInt32& aErrorCode); - PRBool ParseNameSpaceRule(PRInt32& aErrorCode); + PRBool ProcessImport(PRInt32& aErrorCode, const nsString& aURLSpec, const nsString& aMedia, nsIStyleRule** aResult); + PRBool ParseMediaRule(PRInt32& aErrorCode, nsIStyleRule** aResult); + PRBool ParseNameSpaceRule(PRInt32& aErrorCode, nsIStyleRule** aResult); PRBool ProcessNameSpace(PRInt32& aErrorCode, const nsString& aPrefix, - const nsString& aURLSpec); - PRBool ParseFontFaceRule(PRInt32& aErrorCode); - PRBool ParsePageRule(PRInt32& aErrorCode); + const nsString& aURLSpec, nsIStyleRule** aResult); + PRBool ParseFontFaceRule(PRInt32& aErrorCode, nsIStyleRule** aResult); + PRBool ParsePageRule(PRInt32& aErrorCode, nsIStyleRule** aResult); void ParseIDSelector(PRInt32& aDataMask, nsCSSSelector& aSelector, PRInt32& aParsingStatus, PRInt32& aErrorCode); @@ -677,6 +681,49 @@ CSSParserImpl::ParseAndAppendDeclaration(const nsAReadableString& aBuffer, return rv; } +NS_IMETHODIMP +CSSParserImpl::ParseRule(nsAReadableString& aRule, + nsIURI* aBaseURL, + nsIStyleRule** aResult) +{ + NS_ASSERTION(nsnull != aBaseURL, "need base URL"); + NS_ENSURE_ARG_POINTER(aResult); + *aResult = nsnull; + + nsString* str = new nsString(aRule); + if (nsnull == str) { + return NS_ERROR_OUT_OF_MEMORY; + } + nsCOMPtr input = nsnull; + nsresult rv = NS_NewStringUnicharInputStream(getter_AddRefs(input), str); + if (NS_OK != rv) { + delete str; + return rv; + } + + rv = InitScanner(input, aBaseURL); + if (! NS_SUCCEEDED(rv)) { + return rv; + } + + mSection = eCSSSection_Charset; // callers are responsible for rejecting invalid rules. Maybe pass in the previous rule to this method? + PRInt32 errorCode = NS_OK; + + nsCSSToken* tk = &mToken; + // Get first non-whitespace token + if (!GetToken(errorCode, PR_TRUE)) { + OUTPUT_ERROR(); + } else if (eCSSToken_AtKeyword == tk->mType) { + ParseAtRule(errorCode, aResult); + } + else { + UngetToken(); + ParseRuleSet(errorCode, aResult); + } + ReleaseScanner(); + return NS_OK; +} + //---------------------------------------------------------------------- PRBool CSSParserImpl::GetToken(PRInt32& aErrorCode, PRBool aSkipWS) @@ -790,43 +837,43 @@ PRBool CSSParserImpl::SkipAtRule(PRInt32& aErrorCode) return PR_TRUE; } -PRBool CSSParserImpl::ParseAtRule(PRInt32& aErrorCode) +PRBool CSSParserImpl::ParseAtRule(PRInt32& aErrorCode, nsIStyleRule** aResult) { if ((mSection <= eCSSSection_Charset) && (mToken.mIdent.EqualsIgnoreCase("charset"))) { - if (ParseCharsetRule(aErrorCode)) { + if (ParseCharsetRule(aErrorCode, aResult)) { mSection = eCSSSection_Import; // only one charset allowed return PR_TRUE; } } if ((mSection <= eCSSSection_Import) && mToken.mIdent.EqualsIgnoreCase("import")) { - if (ParseImportRule(aErrorCode)) { + if (ParseImportRule(aErrorCode, aResult)) { mSection = eCSSSection_Import; return PR_TRUE; } } if ((mSection <= eCSSSection_NameSpace) && mToken.mIdent.EqualsIgnoreCase("namespace")) { - if (ParseNameSpaceRule(aErrorCode)) { + if (ParseNameSpaceRule(aErrorCode, aResult)) { mSection = eCSSSection_NameSpace; return PR_TRUE; } } if (mToken.mIdent.EqualsIgnoreCase("media")) { - if (ParseMediaRule(aErrorCode)) { + if (ParseMediaRule(aErrorCode, aResult)) { mSection = eCSSSection_General; return PR_TRUE; } } if (mToken.mIdent.EqualsIgnoreCase("font-face")) { - if (ParseFontFaceRule(aErrorCode)) { + if (ParseFontFaceRule(aErrorCode, aResult)) { mSection = eCSSSection_General; return PR_TRUE; } } if (mToken.mIdent.EqualsIgnoreCase("page")) { - if (ParsePageRule(aErrorCode)) { + if (ParsePageRule(aErrorCode, aResult)) { mSection = eCSSSection_General; return PR_TRUE; } @@ -839,7 +886,7 @@ PRBool CSSParserImpl::ParseAtRule(PRInt32& aErrorCode) return SkipAtRule(aErrorCode); } -PRBool CSSParserImpl::ParseCharsetRule(PRInt32& aErrorCode) +PRBool CSSParserImpl::ParseCharsetRule(PRInt32& aErrorCode, nsIStyleRule** aResult) { // XXX not yet implemented return PR_FALSE; @@ -914,7 +961,7 @@ PRBool CSSParserImpl::GatherMedia(PRInt32& aErrorCode, nsString& aMedia, } // Parse a CSS2 import rule: "@import STRING | URL [medium [, mdeium]]" -PRBool CSSParserImpl::ParseImportRule(PRInt32& aErrorCode) +PRBool CSSParserImpl::ParseImportRule(PRInt32& aErrorCode, nsIStyleRule** aResult) { if (!GetToken(aErrorCode, PR_TRUE)) { REPORT_UNEXPECTED_EOF(); @@ -927,7 +974,7 @@ PRBool CSSParserImpl::ParseImportRule(PRInt32& aErrorCode) url = mToken.mIdent; if (GatherMedia(aErrorCode, media, nsnull)) { if (ExpectSymbol(aErrorCode, ';', PR_TRUE)) { - ProcessImport(aErrorCode, url, media); + ProcessImport(aErrorCode, url, media, aResult); return PR_TRUE; } } @@ -941,7 +988,7 @@ PRBool CSSParserImpl::ParseImportRule(PRInt32& aErrorCode) if (ExpectSymbol(aErrorCode, ')', PR_TRUE)) { if (GatherMedia(aErrorCode, media, nsnull)) { if (ExpectSymbol(aErrorCode, ';', PR_TRUE)) { - ProcessImport(aErrorCode, url, media); + ProcessImport(aErrorCode, url, media, aResult); return PR_TRUE; } } @@ -957,12 +1004,18 @@ PRBool CSSParserImpl::ParseImportRule(PRInt32& aErrorCode) } -PRBool CSSParserImpl::ProcessImport(PRInt32& aErrorCode, const nsString& aURLSpec, const nsString& aMedia) +PRBool CSSParserImpl::ProcessImport(PRInt32& aErrorCode, const nsString& aURLSpec, const nsString& aMedia, nsIStyleRule** aResult) { nsCOMPtr rule; NS_NewCSSImportRule(getter_AddRefs(rule), aURLSpec, aMedia); if (rule) { - AppendRule(rule); + if (aResult) { // someone wants this rule + *aResult = rule; + NS_ADDREF(*aResult); + } + else { + AppendRule(rule); + } } if (mChildLoader) { @@ -989,18 +1042,18 @@ PRBool CSSParserImpl::ProcessImport(PRInt32& aErrorCode, const nsString& aURLSpe } // Parse a CSS2 media rule: "@media medium [, medium] { ... }" -PRBool CSSParserImpl::ParseMediaRule(PRInt32& aErrorCode) +PRBool CSSParserImpl::ParseMediaRule(PRInt32& aErrorCode, nsIStyleRule** aResult) { nsAutoString mediaStr; - nsISupportsArray* media = nsnull; - NS_NewISupportsArray(&media); + nsCOMPtr media; + NS_NewISupportsArray(getter_AddRefs(media)); if (media) { if (GatherMedia(aErrorCode, mediaStr, media)) { if ((0 < mediaStr.Length()) && ExpectSymbol(aErrorCode, '{', PR_TRUE)) { // push media rule on stack, loop over children - nsICSSMediaRule* rule = nsnull; - NS_NewCSSMediaRule(&rule); + nsCOMPtr rule; + NS_NewCSSMediaRule(getter_AddRefs(rule)); if (rule) { if (PushGroup(rule)) { @@ -1027,29 +1080,34 @@ PRBool CSSParserImpl::ParseMediaRule(PRInt32& aErrorCode) PopGroup(); if (ExpectSymbol(aErrorCode, '}', PR_TRUE)) { - rule->SetMedia(media); - AppendRule(rule); - NS_RELEASE(rule); - NS_RELEASE(media); + if (aResult) { // someone wants this rule + rule->SetMedia(media); + *aResult = rule; + NS_ADDREF(*aResult); + } + else { + // Append first, so when we do SetMedia() the rule + // knows what its stylesheet is. + AppendRule(rule); + rule->SetMedia(media); + } return PR_TRUE; } mSection = holdSection; } - NS_RELEASE(rule); } else { // failed to create rule, backup and skip block UngetToken(); } } } - NS_RELEASE(media); } return PR_FALSE; } // Parse a CSS3 namespace rule: "@namespace [prefix] STRING | URL;" -PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode) +PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode, nsIStyleRule** aResult) { if (!GetToken(aErrorCode, PR_TRUE)) { REPORT_UNEXPECTED_EOF(); @@ -1071,7 +1129,7 @@ PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode) if (eCSSToken_String == mToken.mType) { url = mToken.mIdent; if (ExpectSymbol(aErrorCode, ';', PR_TRUE)) { - ProcessNameSpace(aErrorCode, prefix, url); + ProcessNameSpace(aErrorCode, prefix, url, aResult); return PR_TRUE; } } @@ -1083,7 +1141,7 @@ PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode) url = mToken.mIdent; if (ExpectSymbol(aErrorCode, ')', PR_TRUE)) { if (ExpectSymbol(aErrorCode, ';', PR_TRUE)) { - ProcessNameSpace(aErrorCode, prefix, url); + ProcessNameSpace(aErrorCode, prefix, url, aResult); return PR_TRUE; } } @@ -1098,36 +1156,40 @@ PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode) } PRBool CSSParserImpl::ProcessNameSpace(PRInt32& aErrorCode, const nsString& aPrefix, - const nsString& aURLSpec) + const nsString& aURLSpec, nsIStyleRule** aResult) { PRBool result = PR_FALSE; - nsICSSNameSpaceRule* rule = nsnull; - nsIAtom* prefix = nsnull; + nsCOMPtr rule; + nsCOMPtr prefix; if (0 < aPrefix.Length()) { - prefix = NS_NewAtom(aPrefix); + prefix = dont_AddRef(NS_NewAtom(aPrefix)); } - NS_NewCSSNameSpaceRule(&rule, prefix, aURLSpec); + NS_NewCSSNameSpaceRule(getter_AddRefs(rule), prefix, aURLSpec); if (rule) { - AppendRule(rule); - NS_RELEASE(rule); - NS_IF_RELEASE(mNameSpace); - mSheet->GetNameSpace(mNameSpace); + if (aResult) { // someone wants this rule + *aResult = rule; + NS_ADDREF(*aResult); + } + else { + AppendRule(rule); + NS_IF_RELEASE(mNameSpace); + mSheet->GetNameSpace(mNameSpace); + } } - NS_IF_RELEASE(prefix); return result; } -PRBool CSSParserImpl::ParseFontFaceRule(PRInt32& aErrorCode) +PRBool CSSParserImpl::ParseFontFaceRule(PRInt32& aErrorCode, nsIStyleRule** aResult) { // XXX not yet implemented return PR_FALSE; } -PRBool CSSParserImpl::ParsePageRule(PRInt32& aErrorCode) +PRBool CSSParserImpl::ParsePageRule(PRInt32& aErrorCode, nsIStyleRule** aResult) { // XXX not yet implemented return PR_FALSE; @@ -1251,7 +1313,7 @@ void CSSParserImpl::AppendRule(nsICSSRule* aRule) } } -PRBool CSSParserImpl::ParseRuleSet(PRInt32& aErrorCode) +PRBool CSSParserImpl::ParseRuleSet(PRInt32& aErrorCode, nsIStyleRule** aResult) { // First get the list of selectors for the rule SelectorList* slist = nsnull; @@ -1299,7 +1361,13 @@ PRBool CSSParserImpl::ParseRuleSet(PRInt32& aErrorCode) rule->SetDeclaration(declaration); rule->SetWeight(list->mWeight); // rule->List(); - AppendRule(rule); + if (aResult) { // someone wants this rule back; don't append it + *aResult = rule; + NS_ADDREF(*aResult); + } + else { + AppendRule(rule); + } NS_RELEASE(rule); } diff --git a/content/html/style/src/nsCSSRules.cpp b/content/html/style/src/nsCSSRules.cpp index 1ada56e6884..637cadf6ffd 100644 --- a/content/html/style/src/nsCSSRules.cpp +++ b/content/html/style/src/nsCSSRules.cpp @@ -18,6 +18,8 @@ * Rights Reserved. * * Contributor(s): + * Boris Zbarsky + * */ #include "nsICSSCharsetRule.h" #include "nsICSSImportRule.h" @@ -39,11 +41,16 @@ #include "nsIDOMCSSStyleSheet.h" #include "nsIDOMCSSRule.h" #include "nsIDOMCSSImportRule.h" +#include "nsIDOMCSSMediaRule.h" #include "nsIMediaList.h" #include "nsIDOMMediaList.h" +#include "nsIDOMCSSRuleList.h" #include "nsIDOMStyleSheet.h" +#include "nsIDocument.h" #include "nsContentUtils.h" +#include "nsStyleConsts.h" +#include "nsDOMError.h" static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); @@ -64,6 +71,84 @@ NS_IMETHODIMP _class::GetStyleSheet(nsIStyleSheet*& aSheet) const { return super NS_IMETHODIMP _class::GetStrength(PRInt32& aStrength) const { return super::GetStrength(aStrength); } \ NS_IMETHODIMP _class::MapRuleInfoInto(nsRuleData* aRuleData) { return NS_OK; } +// ------------------------------- +// Style Rule List for group rules +// +class CSSGroupRuleRuleListImpl : public nsIDOMCSSRuleList +{ +public: + CSSGroupRuleRuleListImpl(nsICSSGroupRule *aGroupRule); + + NS_DECL_ISUPPORTS + + NS_DECL_NSIDOMCSSRULELIST + + void DropReference() { mGroupRule = nsnull; } + +protected: + virtual ~CSSGroupRuleRuleListImpl(void); + +private: + nsICSSGroupRule* mGroupRule; +}; + +CSSGroupRuleRuleListImpl::CSSGroupRuleRuleListImpl(nsICSSGroupRule *aGroupRule) +{ + NS_INIT_REFCNT(); + // Not reference counted to avoid circular references. + // The rule will tell us when its going away. + mGroupRule = aGroupRule; +} + +CSSGroupRuleRuleListImpl::~CSSGroupRuleRuleListImpl() +{ +} + +// QueryInterface implementation for CSSGroupRuleRuleList +NS_INTERFACE_MAP_BEGIN(CSSGroupRuleRuleListImpl) + NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRuleList) + NS_INTERFACE_MAP_ENTRY(nsISupports) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSGroupRuleRuleList) +NS_INTERFACE_MAP_END + + +NS_IMPL_ADDREF(CSSGroupRuleRuleListImpl); +NS_IMPL_RELEASE(CSSGroupRuleRuleListImpl); + +NS_IMETHODIMP +CSSGroupRuleRuleListImpl::GetLength(PRUint32* aLength) +{ + if (mGroupRule) { + PRInt32 count; + mGroupRule->StyleRuleCount(count); + *aLength = (PRUint32)count; + } else { + *aLength = 0; + } + + return NS_OK; +} + +NS_IMETHODIMP +CSSGroupRuleRuleListImpl::Item(PRUint32 aIndex, nsIDOMCSSRule** aReturn) +{ + nsresult result = NS_OK; + + *aReturn = nsnull; + if (mGroupRule) { + nsCOMPtr rule; + + result = mGroupRule->GetStyleRuleAt(aIndex, *getter_AddRefs(rule)); + if (rule) { + result = CallQueryInterface(rule, aReturn); + } else if (result == NS_ERROR_ILLEGAL_VALUE) { + result = NS_OK; // per spec: "Return Value ... null if ... not a valid index." + } + } + + return result; +} + // ------------------------------------------- // nsICSSCharsetRule // @@ -374,7 +459,7 @@ CSSImportRuleImpl::List(FILE* out, PRInt32 aIndent) const fputs("\" ", out); nsAutoString mediaText; - mMedia->GetMediaText(mediaText); + mMedia->GetText(mediaText); fputs(mediaText, out); fputs("\n", out); @@ -456,7 +541,7 @@ NS_IMETHODIMP CSSImportRuleImpl::SetMedia(const nsString& aMedia) { if (mMedia) { - return mMedia->SetMediaText(aMedia); + return mMedia->SetText(aMedia); } else { return NS_OK; } @@ -466,7 +551,7 @@ NS_IMETHODIMP CSSImportRuleImpl::GetMedia(nsString& aMedia) const { if (mMedia) { - return mMedia->GetMediaText(aMedia); + return mMedia->GetText(aMedia); } else { aMedia.Truncate(); return NS_OK; @@ -527,7 +612,7 @@ CSSImportRuleImpl::GetCssText(nsAWritableString& aCssText) aCssText.Append(NS_LITERAL_STRING(")")); if (mMedia) { nsAutoString mediaText; - mMedia->GetMediaText(mediaText); + mMedia->GetText(mediaText); if (!mediaText.IsEmpty()) { aCssText.Append(NS_LITERAL_STRING(" ")); aCssText.Append(mediaText); @@ -596,7 +681,7 @@ CSSImportRuleImpl::GetStyleSheet(nsIDOMCSSStyleSheet * *aStyleSheet) // class CSSMediaRuleImpl : public nsCSSRule, public nsICSSMediaRule, - public nsIDOMCSSRule + public nsIDOMCSSMediaRule { public: CSSMediaRuleImpl(void); @@ -618,27 +703,33 @@ public: // nsICSSMediaRule methods NS_IMETHOD SetMedia(nsISupportsArray* aMedia); - NS_IMETHOD UseForMedium(nsIAtom* aMedium) const; + 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 InsertStyleRuleAt(PRUint32 aIndex, nsICSSRule* aRule); + // nsIDOMCSSRule interface NS_DECL_NSIDOMCSSRULE + // nsIDOMCSSMediaRule interface + NS_DECL_NSIDOMCSSMEDIARULE + protected: - nsISupportsArray* mMedia; + nsCOMPtr mMedia; nsISupportsArray* mRules; + CSSGroupRuleRuleListImpl* mRuleCollection; }; CSSMediaRuleImpl::CSSMediaRuleImpl(void) : nsCSSRule(), mMedia(nsnull), - mRules(nsnull) + mRules(nsnull), + mRuleCollection(nsnull) { } @@ -659,13 +750,11 @@ CloneRuleInto(nsISupports* aRule, void* aArray) CSSMediaRuleImpl::CSSMediaRuleImpl(const CSSMediaRuleImpl& aCopy) : nsCSSRule(aCopy), mMedia(nsnull), - mRules(nsnull) + mRules(nsnull), + mRuleCollection(nsnull) { if (aCopy.mMedia) { - NS_NewISupportsArray(&mMedia); - if (mMedia) { - mMedia->AppendElements(aCopy.mMedia); - } + NS_NewMediaList(aCopy.mMedia, aCopy.mSheet, getter_AddRefs(mMedia)); } if (aCopy.mRules) { @@ -678,8 +767,14 @@ CSSMediaRuleImpl::CSSMediaRuleImpl(const CSSMediaRuleImpl& aCopy) CSSMediaRuleImpl::~CSSMediaRuleImpl(void) { - NS_IF_RELEASE(mMedia); NS_IF_RELEASE(mRules); + if (mMedia) { + mMedia->DropReference(); + } + if (mRuleCollection) { + mRuleCollection->DropReference(); + NS_RELEASE(mRuleCollection); + } } NS_IMPL_ADDREF_INHERITED(CSSMediaRuleImpl, nsCSSRule); @@ -691,6 +786,7 @@ NS_INTERFACE_MAP_BEGIN(CSSMediaRuleImpl) 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 @@ -712,6 +808,17 @@ CSSMediaRuleImpl::SetStyleSheet(nsICSSStyleSheet* aSheet) if (mRules) { mRules->EnumerateForwards(SetStyleSheetReference, aSheet); } + if (mMedia) { + nsresult rv; + nsCOMPtr oldMedia(do_QueryInterface(mMedia, &rv)); + if (NS_FAILED(rv)) + return rv; + mMedia->DropReference(); + rv = NS_NewMediaList(oldMedia, aSheet, getter_AddRefs(mMedia)); + if (NS_FAILED(rv)) + return rv; + } + return nsCSSRule::SetStyleSheet(aSheet); } @@ -729,13 +836,13 @@ CSSMediaRuleImpl::List(FILE* out, PRInt32 aIndent) const PRUint32 count; mMedia->Count(&count); while (index < count) { - nsIAtom* medium = (nsIAtom*)mMedia->ElementAt(index++); + nsCOMPtr medium; + mMedia->QueryElementAt(index++, NS_GET_IID(nsIAtom), getter_AddRefs(medium)); medium->ToString(buffer); fputs(buffer, out); if (index < count) { fputs(", ", out); } - NS_RELEASE(medium); } } fputs(" {\n", out); @@ -745,9 +852,9 @@ CSSMediaRuleImpl::List(FILE* out, PRInt32 aIndent) const PRUint32 count; mRules->Count(&count); while (index < count) { - nsICSSRule* rule = (nsICSSRule*)mRules->ElementAt(index++); + nsCOMPtr rule; + mRules->QueryElementAt(index++, NS_GET_IID(nsICSSRule), getter_AddRefs(rule)); rule->List(out, aIndent + 1); - NS_RELEASE(rule); } } fputs("}\n", out); @@ -791,12 +898,12 @@ void CSSMediaRuleImpl::SizeOf(nsISizeOfHandler *aSizeOfHandler, PRUint32 &aSize) PRUint32 count; mMedia->Count(&count); while (index < count) { - nsIAtom* medium = (nsIAtom*)mMedia->ElementAt(index++); + nsCOMPtr medium; + mMedia->QueryElementAt(index++, NS_GET_IID(nsIAtom), getter_AddRefs(medium)); if(medium && uniqueItems->AddItem(medium)){ medium->SizeOf(aSizeOfHandler, &localSize); aSize += localSize; } - NS_IF_RELEASE(medium); } } // we are done with the size we report for ourself @@ -808,9 +915,9 @@ void CSSMediaRuleImpl::SizeOf(nsISizeOfHandler *aSizeOfHandler, PRUint32 &aSize) PRUint32 count; mRules->Count(&count); while (index < count) { - nsICSSRule* rule = (nsICSSRule*)mRules->ElementAt(index++); + nsCOMPtr rule; + mRules->QueryElementAt(index++, NS_GET_IID(nsICSSRule), getter_AddRefs(rule)); rule->SizeOf(aSizeOfHandler, localSize); - NS_RELEASE(rule); } } } @@ -837,26 +944,18 @@ CSSMediaRuleImpl::Clone(nsICSSRule*& aClone) const NS_IMETHODIMP CSSMediaRuleImpl::SetMedia(nsISupportsArray* aMedia) { - nsresult result = NS_OK; - NS_IF_RELEASE(mMedia); - mMedia = aMedia; - NS_IF_ADDREF(mMedia); - return result; + return NS_NewMediaList(aMedia, mSheet, getter_AddRefs(mMedia)); } -NS_IMETHODIMP +NS_IMETHODIMP_(PRBool) CSSMediaRuleImpl::UseForMedium(nsIAtom* aMedium) const { if (mMedia) { - if (-1 != mMedia->IndexOf(aMedium)) { - return NS_OK; - } - if (-1 != mMedia->IndexOf(nsLayoutAtoms::all)) { - return NS_OK; - } - return NS_COMFALSE; + PRBool matches = PR_FALSE; + mMedia->MatchesMedium(aMedium, &matches); + return matches; } - return NS_OK; + return PR_TRUE; } NS_IMETHODIMP @@ -894,10 +993,17 @@ 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_INVALID_ARG; + return NS_ERROR_ILLEGAL_VALUE; } NS_IMETHODIMP @@ -909,6 +1015,37 @@ CSSMediaRuleImpl::EnumerateRulesForwards(nsISupportsArrayEnumFunc aFunc, void * return NS_OK; } +/* + * The next two methods (DeleteStyleRuleAt and InsertStyleRuleAt) + * 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; + nsresult rv = mRules->QueryElementAt(aIndex, NS_GET_IID(nsICSSRule), getter_AddRefs(rule)); + NS_ENSURE_SUCCESS(rv, rv); + rule->SetStyleSheet(nsnull); + return mRules->DeleteElementAt(aIndex); +} + +NS_IMETHODIMP +CSSMediaRuleImpl::InsertStyleRuleAt(PRUint32 aIndex, nsICSSRule* aRule) +{ + NS_ENSURE_TRUE(mRules, NS_ERROR_FAILURE); + + // There is no xpcom-compatible version of InsertElementAt.... :( + if (! mRules->InsertElementAt(aRule, aIndex)) { + return NS_ERROR_FAILURE; + } + aRule->SetStyleSheet(mSheet); + return NS_OK; +} + nsresult NS_NewCSSMediaRule(nsICSSMediaRule** aInstancePtrResult) @@ -926,6 +1063,7 @@ NS_NewCSSMediaRule(nsICSSMediaRule** aInstancePtrResult) return it->QueryInterface(NS_GET_IID(nsICSSMediaRule), (void **) aInstancePtrResult); } +// nsIDOMCSSRule methods NS_IMETHODIMP CSSMediaRuleImpl::GetType(PRUint16* aType) { @@ -943,7 +1081,8 @@ CSSMediaRuleImpl::GetCssText(nsAWritableString& aCssText) if (mMedia) { mMedia->Count(&count); for (index = 0; index < count; index++) { - nsCOMPtr medium (do_QueryInterface(mMedia->ElementAt(index))); + nsCOMPtr medium; + mMedia->QueryElementAt(index, NS_GET_IID(nsIAtom), getter_AddRefs(medium)); if (medium) { nsAutoString tempString; if (index > 0) @@ -960,7 +1099,8 @@ CSSMediaRuleImpl::GetCssText(nsAWritableString& aCssText) if (mRules) { mRules->Count(&count); for (index = 0; index < count; index++) { - nsCOMPtr rule (do_QueryInterface(mRules->ElementAt(index))); + nsCOMPtr rule; + mRules->QueryElementAt(index, NS_GET_IID(nsIDOMCSSRule), getter_AddRefs(rule)); if (rule) { nsAutoString tempString; rule->GetCssText(tempString); @@ -998,6 +1138,60 @@ CSSMediaRuleImpl::GetParentRule(nsIDOMCSSRule** aParentRule) return NS_ERROR_NOT_IMPLEMENTED; } +// nsIDOMCSSMediaRule methods +NS_IMETHODIMP +CSSMediaRuleImpl::GetMedia(nsIDOMMediaList* *aMedia) +{ + NS_ENSURE_ARG_POINTER(aMedia); + if (!mMedia) { + *aMedia = nsnull; + return NS_OK; + } + + return CallQueryInterface(mMedia, aMedia); +} + +NS_IMETHODIMP +CSSMediaRuleImpl::GetCssRules(nsIDOMCSSRuleList* *aRuleList) +{ + if (!mRuleCollection) { + mRuleCollection = new CSSGroupRuleRuleListImpl(this); + if (!mRuleCollection) { + return NS_ERROR_OUT_OF_MEMORY; + } + NS_ADDREF(mRuleCollection); + } + + return CallQueryInterface(mRuleCollection, aRuleList); +} + +NS_IMETHODIMP +CSSMediaRuleImpl::InsertRule(nsAReadableString & aRule, PRUint32 aIndex, PRUint32* _retval) +{ + NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE); + NS_ENSURE_TRUE(mRules, NS_ERROR_FAILURE); + + PRUint32 count; + mRules->Count(&count); + if (aIndex > count) + return NS_ERROR_DOM_INDEX_SIZE_ERR; + + return mSheet->InsertRuleIntoGroup(aRule, this, aIndex, _retval); +} + +NS_IMETHODIMP +CSSMediaRuleImpl::DeleteRule(PRUint32 aIndex) +{ + NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE); + NS_ENSURE_TRUE(mRules, NS_ERROR_FAILURE); + + PRUint32 count; + mRules->Count(&count); + if (aIndex >= count) + return NS_ERROR_DOM_INDEX_SIZE_ERR; + + return mSheet->DeleteRuleFromGroup(this, aIndex); +} // ------------------------------------------- // nsICSSNameSpaceRule @@ -1251,3 +1445,4 @@ CSSNameSpaceRuleImpl::GetParentRule(nsIDOMCSSRule** aParentRule) { return NS_ERROR_NOT_IMPLEMENTED; } + diff --git a/content/html/style/src/nsCSSStyleSheet.cpp b/content/html/style/src/nsCSSStyleSheet.cpp index 025a1eec4eb..6d7bafee8e8 100644 --- a/content/html/style/src/nsCSSStyleSheet.cpp +++ b/content/html/style/src/nsCSSStyleSheet.cpp @@ -40,6 +40,7 @@ #include "nsIMediaList.h" #include "nsIHTMLContent.h" #include "nsIDocument.h" +#include "nsIHTMLContentContainer.h" #include "nsIPresContext.h" #include "nsIEventStateManager.h" #include "nsHTMLAtoms.h" @@ -61,6 +62,7 @@ #include "nsDOMError.h" #include "nsIPresShell.h" #include "nsICSSParser.h" +#include "nsICSSLoader.h" #include "nsIRuleWalker.h" #include "nsCSSAtoms.h" #include "nsINameSpaceManager.h" @@ -679,7 +681,7 @@ public: nsISupportsArray* mOrderedRules; - nsINameSpace* mNameSpace; + nsCOMPtr mNameSpace; PRInt32 mDefaultNameSpaceID; nsHashtable mRelevantAttributes; }; @@ -715,10 +717,12 @@ public: NS_IMETHOD GetType(nsString& aType) const; NS_IMETHOD GetMediumCount(PRInt32& aCount) const; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const; - NS_IMETHOD UseForMedium(nsIAtom* aMedium) const; + NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const; NS_IMETHOD AppendMedium(nsIAtom* aMedium); NS_IMETHOD ClearMedia(void); - + NS_IMETHOD DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex); + NS_IMETHOD InsertRuleIntoGroup(nsAReadableString& aRule, nsICSSGroupRule* aGroup, PRUint32 aIndex, PRUint32* _retval); + NS_IMETHOD GetEnabled(PRBool& aEnabled) const; NS_IMETHOD SetEnabled(PRBool aEnabled); @@ -812,7 +816,8 @@ protected: nsVoidArray* mRuleProcessors; -friend class CSSRuleProcessor; + friend class CSSRuleProcessor; + friend class DOMMediaListImpl; }; @@ -923,13 +928,22 @@ class DOMMediaListImpl : public nsIDOMMediaList, return mArray->ElementAt(aIndex); } + // nsIMediaList methods + NS_DECL_NSIMEDIALIST + DOMMediaListImpl(nsISupportsArray *aArray, CSSStyleSheetImpl *aStyleSheet); virtual ~DOMMediaListImpl(); - void DropReference() { mStyleSheet = nsnull; } - private: + nsresult BeginMediaChange(void); + nsresult EndMediaChange(void); + nsresult Delete(nsAReadableString & aOldMedium); + nsresult Append(nsAReadableString & aOldMedium); + nsCOMPtr mArray; + // not refcounted; sheet will let us know when it goes away + // mStyleSheet is the sheet that needs to be dirtied when this medialist + // changes CSSStyleSheetImpl* mStyleSheet; }; @@ -937,6 +951,7 @@ private: NS_INTERFACE_MAP_BEGIN(DOMMediaListImpl) NS_INTERFACE_MAP_ENTRY(nsIDOMMediaList) NS_INTERFACE_MAP_ENTRY(nsIMediaList) + NS_INTERFACE_MAP_ENTRY(nsISupportsArray) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMediaList) NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(MediaList) NS_INTERFACE_MAP_ENTRY(nsISerializable) @@ -962,13 +977,13 @@ DOMMediaListImpl::~DOMMediaListImpl() nsresult NS_NewMediaList(nsIMediaList** aInstancePtrResult) { - return NS_NewMediaList(aInstancePtrResult, NS_LITERAL_STRING("")); + return NS_NewMediaList(NS_LITERAL_STRING(""), aInstancePtrResult); } nsresult -NS_NewMediaList(nsIMediaList** aInstancePtrResult, const nsAReadableString& aMediaText) { +NS_NewMediaList(const nsAReadableString& aMediaText, nsIMediaList** aInstancePtrResult) { nsresult rv; - NS_ENSURE_ARG_POINTER(aInstancePtrResult); + NS_ASSERTION(aInstancePtrResult, "Null out param."); nsCOMPtr array; rv = NS_NewISupportsArray(getter_AddRefs(array)); @@ -976,15 +991,29 @@ NS_NewMediaList(nsIMediaList** aInstancePtrResult, const nsAReadableString& aMed return NS_ERROR_OUT_OF_MEMORY; } DOMMediaListImpl* medialist = new DOMMediaListImpl(array, nsnull); - NS_ENSURE_TRUE(medialist, NS_ERROR_OUT_OF_MEMORY); - rv = medialist->SetMediaText(aMediaText); - NS_ENSURE_SUCCESS(rv, rv); *aInstancePtrResult = medialist; + NS_ENSURE_TRUE(medialist, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(*aInstancePtrResult); + rv = medialist->SetMediaText(aMediaText); + if (NS_FAILED(rv)) { + NS_RELEASE(*aInstancePtrResult); + *aInstancePtrResult = nsnull; + } + return rv; +} + +nsresult NS_NewMediaList(nsISupportsArray* aArray, nsICSSStyleSheet* aSheet, nsIMediaList** aInstancePtrResult) +{ + NS_ASSERTION(aInstancePtrResult, "Null out param."); + DOMMediaListImpl* medialist = new DOMMediaListImpl(aArray, NS_STATIC_CAST(CSSStyleSheetImpl*, aSheet)); + *aInstancePtrResult = medialist; + NS_ENSURE_TRUE(medialist, NS_ERROR_OUT_OF_MEMORY); + NS_ADDREF(*aInstancePtrResult); + return NS_OK; } NS_IMETHODIMP -DOMMediaListImpl::GetMediaText(nsAWritableString& aMediaText) +DOMMediaListImpl::GetText(nsAWritableString& aMediaText) { aMediaText.Truncate(); @@ -995,10 +1024,8 @@ DOMMediaListImpl::GetMediaText(nsAWritableString& aMediaText) PRInt32 count = cnt, index = 0; while (index < count) { - nsCOMPtr tmp(dont_AddRef(ElementAt(index++))); - NS_ENSURE_TRUE(tmp, NS_ERROR_FAILURE); - - nsCOMPtr medium(do_QueryInterface(tmp)); + nsCOMPtr medium; + QueryElementAt(index++, NS_GET_IID(nsIAtom), getter_AddRefs(medium)); NS_ENSURE_TRUE(medium, NS_ERROR_FAILURE); const PRUnichar *buffer; @@ -1013,7 +1040,7 @@ DOMMediaListImpl::GetMediaText(nsAWritableString& aMediaText) } NS_IMETHODIMP -DOMMediaListImpl::SetMediaText(const nsAReadableString& aMediaText) +DOMMediaListImpl::SetText(const nsAReadableString& aMediaText) { nsresult rv = Clear(); NS_ENSURE_SUCCESS(rv, rv); @@ -1044,6 +1071,57 @@ DOMMediaListImpl::SetMediaText(const nsAReadableString& aMediaText) return rv; } +/* + * aMatch is true when we contain the desired medium or contain the + * "all" medium or contain no media at all, which is the same as + * containing "all" + */ +NS_IMETHODIMP +DOMMediaListImpl::MatchesMedium(nsIAtom* aMedium, PRBool* aMatch) +{ + NS_ENSURE_ARG_POINTER(aMatch); + *aMatch = PR_FALSE; + *aMatch = (-1 != IndexOf(aMedium)) || + (-1 != IndexOf(nsLayoutAtoms::all)); + if (*aMatch) + return NS_OK; + PRUint32 count; + nsresult rv = Count(&count); + if(NS_FAILED(rv)) + return rv; + *aMatch = (count == 0); + return NS_OK; +} + +NS_IMETHODIMP +DOMMediaListImpl::DropReference(void) +{ + mStyleSheet = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +DOMMediaListImpl::GetMediaText(nsAWritableString& aMediaText) +{ + return GetText(aMediaText); +} + +NS_IMETHODIMP +DOMMediaListImpl::SetMediaText(nsAReadableString& aMediaText) +{ + nsresult rv; + rv = BeginMediaChange(); + if (NS_FAILED(rv)) + return rv; + + rv = SetText(aMediaText); + if (NS_FAILED(rv)) + return rv; + + rv = EndMediaChange(); + return rv; +} + NS_IMETHODIMP DOMMediaListImpl::GetLength(PRUint32* aLength) { @@ -1079,6 +1157,38 @@ DOMMediaListImpl::Item(PRUint32 aIndex, nsAWritableString& aReturn) } NS_IMETHODIMP +DOMMediaListImpl::DeleteMedium(const nsAReadableString& aOldMedium) +{ + nsresult rv; + rv = BeginMediaChange(); + if (NS_FAILED(rv)) + return rv; + + rv = Delete(aOldMedium); + if (NS_FAILED(rv)) + return rv; + + rv = EndMediaChange(); + return rv; +} + +NS_IMETHODIMP +DOMMediaListImpl::AppendMedium(const nsAReadableString& aNewMedium) +{ + nsresult rv; + rv = BeginMediaChange(); + if (NS_FAILED(rv)) + return rv; + + rv = Append(aNewMedium); + if (NS_FAILED(rv)) + return rv; + + rv = EndMediaChange(); + return rv; +} + +nsresult DOMMediaListImpl::Delete(const nsAReadableString& aOldMedium) { if (!aOldMedium.Length()) @@ -1098,7 +1208,7 @@ DOMMediaListImpl::Delete(const nsAReadableString& aOldMedium) return NS_OK; } -NS_IMETHODIMP +nsresult DOMMediaListImpl::Append(const nsAReadableString& aNewMedium) { if (!aNewMedium.Length()) @@ -1118,6 +1228,39 @@ DOMMediaListImpl::Append(const nsAReadableString& aNewMedium) return NS_OK; } +nsresult +DOMMediaListImpl::BeginMediaChange(void) +{ + nsresult rv; + nsCOMPtr doc; + + if (mStyleSheet) { + rv = mStyleSheet->GetOwningDocument(*getter_AddRefs(doc)); + NS_ENSURE_SUCCESS(rv, rv); + rv = doc->BeginUpdate(); + NS_ENSURE_SUCCESS(rv, rv); + rv = mStyleSheet->WillDirty(); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; +} + +nsresult +DOMMediaListImpl::EndMediaChange(void) +{ + nsresult rv; + nsCOMPtr doc; + if (mStyleSheet) { + mStyleSheet->DidDirty(); + rv = mStyleSheet->GetOwningDocument(*getter_AddRefs(doc)); + NS_ENSURE_SUCCESS(rv, rv); + rv = doc->StyleRuleChanged(mStyleSheet, nsnull, NS_STYLE_HINT_RECONSTRUCT_ALL); + NS_ENSURE_SUCCESS(rv, rv); + rv = doc->EndUpdate(); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; +} // ------------------------------- // Imports Collection for the DOM @@ -1286,7 +1429,6 @@ CSSStyleSheetInner::~CSSStyleSheetInner(void) mOrderedRules->EnumerateForwards(SetStyleSheetReference, nsnull); NS_RELEASE(mOrderedRules); } - NS_IF_RELEASE(mNameSpace); } CSSStyleSheetInner* @@ -1326,7 +1468,7 @@ static PRBool CreateNameSpace(nsISupports* aRule, void* aNameSpacePtr) { nsICSSRule* rule = (nsICSSRule*)aRule; - PRInt32 type; + PRInt32 type = nsICSSRule::UNKNOWN_RULE; rule->GetType(type); if (nsICSSRule::NAMESPACE_RULE == type) { nsICSSNameSpaceRule* nameSpaceRule = (nsICSSNameSpaceRule*)rule; @@ -1355,27 +1497,26 @@ CreateNameSpace(nsISupports* aRule, void* aNameSpacePtr) void CSSStyleSheetInner::RebuildNameSpaces(void) { - nsINameSpaceManager* nameSpaceMgr; + nsCOMPtr nameSpaceMgr; if (mNameSpace) { - mNameSpace->GetNameSpaceManager(nameSpaceMgr); - NS_RELEASE(mNameSpace); + mNameSpace->GetNameSpaceManager(*getter_AddRefs(nameSpaceMgr)); } else { - NS_NewNameSpaceManager(&nameSpaceMgr); + NS_NewNameSpaceManager(getter_AddRefs(nameSpaceMgr)); } if (nameSpaceMgr) { - nameSpaceMgr->CreateRootNameSpace(mNameSpace); + nameSpaceMgr->CreateRootNameSpace(*getter_AddRefs(mNameSpace)); if (kNameSpaceID_Unknown != mDefaultNameSpaceID) { - nsINameSpace* defaultNameSpace; - mNameSpace->CreateChildNameSpace(nsnull, mDefaultNameSpaceID, defaultNameSpace); + nsCOMPtr defaultNameSpace; + mNameSpace->CreateChildNameSpace(nsnull, mDefaultNameSpaceID, + *getter_AddRefs(defaultNameSpace)); if (defaultNameSpace) { - NS_RELEASE(mNameSpace); mNameSpace = defaultNameSpace; } } - NS_RELEASE(nameSpaceMgr); if (mOrderedRules) { - mOrderedRules->EnumerateForwards(CreateNameSpace, &mNameSpace); + nsINameSpace* nameSpace = mNameSpace; + mOrderedRules->EnumerateForwards(CreateNameSpace, &nameSpace); } } } @@ -1745,24 +1886,15 @@ CSSStyleSheetImpl::GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const return NS_ERROR_INVALID_ARG; } -NS_IMETHODIMP +NS_IMETHODIMP_(PRBool) CSSStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const { if (mMedia) { - if (-1 != mMedia->IndexOf(aMedium)) { - return NS_OK; - } - if (-1 != mMedia->IndexOf(nsLayoutAtoms::all)) { - return NS_OK; - } - PRUint32 count; - mMedia->Count(&count); - if (count == 0) { // equivalent to having a medium of "all" - return NS_OK; - } - return NS_COMFALSE; + PRBool matches = PR_FALSE; + mMedia->MatchesMedium(aMedium, &matches); + return matches; } - return NS_OK; + return PR_TRUE; } @@ -1976,7 +2108,7 @@ CSSStyleSheetImpl::PrependStyleRule(nsICSSRule* aRule) aRule->SetStyleSheet(this); DidDirty(); - PRInt32 type; + PRInt32 type = nsICSSRule::UNKNOWN_RULE; aRule->GetType(type); if (nsICSSRule::NAMESPACE_RULE == type) { // no api to prepend a namespace (ugh), release old ones and re-create them all @@ -2003,31 +2135,29 @@ CSSStyleSheetImpl::AppendStyleRule(nsICSSRule* aRule) aRule->SetStyleSheet(this); DidDirty(); - PRInt32 type; + PRInt32 type = nsICSSRule::UNKNOWN_RULE; aRule->GetType(type); if (nsICSSRule::NAMESPACE_RULE == type) { if (! mInner->mNameSpace) { - nsINameSpaceManager* nameSpaceMgr; - NS_NewNameSpaceManager(&nameSpaceMgr); + nsCOMPtr nameSpaceMgr; + NS_NewNameSpaceManager(getter_AddRefs(nameSpaceMgr)); if (nameSpaceMgr) { - nameSpaceMgr->CreateRootNameSpace(mInner->mNameSpace); - NS_RELEASE(nameSpaceMgr); + nameSpaceMgr->CreateRootNameSpace(*getter_AddRefs(mInner->mNameSpace)); } } if (mInner->mNameSpace) { - nsICSSNameSpaceRule* nameSpaceRule = (nsICSSNameSpaceRule*)aRule; - nsINameSpace* newNameSpace = nsnull; + nsCOMPtr nameSpaceRule(do_QueryInterface(aRule)); + nsCOMPtr newNameSpace; - nsIAtom* prefix = nsnull; + nsCOMPtr prefix; nsAutoString urlSpec; - nameSpaceRule->GetPrefix(prefix); + nameSpaceRule->GetPrefix(*getter_AddRefs(prefix)); nameSpaceRule->GetURLSpec(urlSpec); - mInner->mNameSpace->CreateChildNameSpace(prefix, urlSpec, newNameSpace); - NS_IF_RELEASE(prefix); + mInner->mNameSpace->CreateChildNameSpace(prefix, urlSpec, + *getter_AddRefs(newNameSpace)); if (newNameSpace) { - NS_RELEASE(mInner->mNameSpace); - mInner->mNameSpace = newNameSpace; // takes ref + mInner->mNameSpace = newNameSpace; } } } else { @@ -2050,7 +2180,7 @@ CheckRuleForAttributesEnum(nsISupports *aRule, void *aData) NS_IMETHODIMP CSSStyleSheetImpl::CheckRuleForAttributes(nsICSSRule *aRule) { - PRInt32 ruleType; + PRInt32 ruleType = nsICSSRule::UNKNOWN_RULE; aRule->GetType(ruleType); switch (ruleType) { case nsICSSRule::MEDIA_RULE: { @@ -2124,8 +2254,13 @@ CSSStyleSheetImpl::GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const NS_IMETHODIMP CSSStyleSheetImpl::GetNameSpace(nsINameSpace*& aNameSpace) const { - aNameSpace = ((mInner) ? mInner->mNameSpace : nsnull); - NS_IF_ADDREF(aNameSpace); + if (mInner) { + aNameSpace = mInner->mNameSpace; + NS_IF_ADDREF(aNameSpace); + } + else { + aNameSpace = nsnull; + } return NS_OK; } @@ -2218,9 +2353,9 @@ ListRules(nsISupportsArray* aRules, FILE* aOut, PRInt32 aIndent) if (aRules) { aRules->Count(&count); for (index = 0; index < count; index++) { - nsICSSRule* rule = (nsICSSRule*)aRules->ElementAt(index); + nsCOMPtr rule; + aRules->QueryElementAt(index, NS_GET_IID(nsICSSRule), getter_AddRefs(rule)); rule->List(aOut, aIndent); - NS_RELEASE(rule); } } } @@ -2282,13 +2417,13 @@ void CSSStyleSheetImpl::List(FILE* out, PRInt32 aIndent) const mMedia->Count(&count); nsAutoString buffer; while (index < PRInt32(count)) { - nsIAtom* medium = (nsIAtom*)mMedia->ElementAt(index++); + nsCOMPtr medium; + mMedia->QueryElementAt(index++, NS_GET_IID(nsIAtom), getter_AddRefs(medium)); medium->ToString(buffer); fputs(buffer, out); if (index < PRInt32(count)) { fputs(", ", out); } - NS_RELEASE(medium); } } fputs("\n", out); @@ -2543,62 +2678,173 @@ CSSStyleSheetImpl::InsertRule(const nsAReadableString& aRule, PRUint32 aIndex, PRUint32* aReturn) { - nsICSSParser* css; - // XXX should get parser from CSS loader - nsresult result = NS_NewCSSParser(&css); - if (NS_OK == result) { - nsString* str = new nsString(aRule); // will be deleted by the input stream - nsIUnicharInputStream* input = nsnull; - result = NS_NewStringUnicharInputStream(&input, str); - if (NS_OK == result) { - nsICSSStyleSheet* tmp; - css->SetStyleSheet(this); - // XXX Currently, the parser will append the rule to the - // style sheet. We shouldn't ignore the index. - result = css->Parse(input, mInner->mURL, tmp); - NS_ASSERTION(tmp == this, "parser incorrectly created a new stylesheet"); - NS_RELEASE(tmp); - NS_RELEASE(input); - PRUint32 cnt; - if (mInner && mInner->mOrderedRules) { - result = mInner->mOrderedRules->Count(&cnt); - if (NS_SUCCEEDED(result)) { - *aReturn = cnt; - if (nsnull != mDocument) { - nsICSSRule* rule; + NS_ENSURE_TRUE(mInner, NS_ERROR_FAILURE); + nsresult result; + if (! mInner->mOrderedRules) { + result = NS_NewISupportsArray(&(mInner->mOrderedRules)); + } + if (NS_FAILED(result)) + return result; - rule = (nsICSSRule*)(mInner->mOrderedRules->ElementAt(aIndex)); - mDocument->StyleRuleAdded(this, rule); - NS_IF_RELEASE(rule); - } - } - } - } + PRUint32 count; + mInner->mOrderedRules->Count(&count); + if (aIndex > count) + return NS_ERROR_DOM_INDEX_SIZE_ERR; + + result = WillDirty(); + if (NS_FAILED(result)) + return result; - NS_RELEASE(css); + nsCOMPtr loader; + nsCOMPtr css; + nsCOMPtr htmlContainer(do_QueryInterface(mDocument)); + if (htmlContainer) { + htmlContainer->GetCSSLoader(*getter_AddRefs(loader)); + } + if (loader) { + result = loader->GetParserFor(this, getter_AddRefs(css)); + } + else { + result = NS_NewCSSParser(getter_AddRefs(css)); + css->SetStyleSheet(this); + } + if (NS_FAILED(result)) + return result; + + if (mDocument) { + result = mDocument->BeginUpdate(); + if (NS_FAILED(result)) + return result; } - return result; + nsCOMPtr rule; + result = css->ParseRule(aRule, mInner->mURL, getter_AddRefs(rule)); + if (NS_FAILED(result)) + return result; + if (! rule) // parsed successfully, but no rule resulted + return NS_ERROR_DOM_SYNTAX_ERR; + + nsCOMPtr cssRule(do_QueryInterface(rule, &result)); + NS_ENSURE_SUCCESS(result, result); + + PRInt32 type = nsICSSRule::UNKNOWN_RULE; + cssRule->GetType(type); + if (aIndex != 0) { + if (type == nsICSSRule::CHARSET_RULE) { // no inserting charset at nonzero position + return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; + } + + nsCOMPtr prevRule; + result = mInner->mOrderedRules->QueryElementAt(aIndex-1, NS_GET_IID(nsICSSRule), getter_AddRefs(prevRule)); + NS_ENSURE_SUCCESS(result, result); + PRInt32 prevType = nsICSSRule::UNKNOWN_RULE; + prevRule->GetType(prevType); + + if (type == nsICSSRule::IMPORT_RULE && + prevType != nsICSSRule::CHARSET_RULE && + prevType != nsICSSRule::IMPORT_RULE) { + return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; + } + + if (type == nsICSSRule::NAMESPACE_RULE && + prevType != nsICSSRule::CHARSET_RULE && + prevType != nsICSSRule::IMPORT_RULE && + prevType != nsICSSRule::NAMESPACE_RULE) { + return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; + } + } + + if (type == nsICSSRule::CHARSET_RULE) { + // check that we're not inserting before another chatset rule + nsCOMPtr nextRule; + mInner->mOrderedRules->QueryElementAt(aIndex, NS_GET_IID(nsICSSRule), getter_AddRefs(nextRule)); + if (nextRule) { + PRInt32 nextType = nsICSSRule::UNKNOWN_RULE; + nextRule->GetType(nextType); + if (nextType == nsICSSRule::CHARSET_RULE) { + return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; + } + } + } + + result = mInner->mOrderedRules->InsertElementAt(cssRule, aIndex); + NS_ENSURE_SUCCESS(result, result); + cssRule->SetStyleSheet(this); + DidDirty(); + if (type == nsICSSRule::NAMESPACE_RULE) { + if (! mInner->mNameSpace) { + nsCOMPtr nameSpaceMgr; + result = NS_NewNameSpaceManager(getter_AddRefs(nameSpaceMgr)); + if (NS_FAILED(result)) + return result; + nameSpaceMgr->CreateRootNameSpace(*getter_AddRefs(mInner->mNameSpace)); + } + + NS_ENSURE_TRUE(mInner->mNameSpace, NS_ERROR_FAILURE); + + nsCOMPtr nameSpaceRule(do_QueryInterface(cssRule)); + nsCOMPtr newNameSpace; + + nsCOMPtr prefix; + nsAutoString urlSpec; + nameSpaceRule->GetPrefix(*getter_AddRefs(prefix)); + nameSpaceRule->GetURLSpec(urlSpec); + mInner->mNameSpace->CreateChildNameSpace(prefix, urlSpec, + *getter_AddRefs(newNameSpace)); + if (newNameSpace) { + mInner->mNameSpace = newNameSpace; + } + } + else { + CheckRuleForAttributes(cssRule); + } + if (mDocument) { + result = mDocument->StyleRuleAdded(this, cssRule); + NS_ENSURE_SUCCESS(result, result); + + result = mDocument->EndUpdate(); + NS_ENSURE_SUCCESS(result, result); + } + + *aReturn = aIndex; + return NS_OK; } NS_IMETHODIMP CSSStyleSheetImpl::DeleteRule(PRUint32 aIndex) { - nsresult result = NS_ERROR_INVALID_ARG; + nsresult result = NS_ERROR_DOM_INDEX_SIZE_ERR; // XXX TBI: handle @rule types if (mInner && mInner->mOrderedRules) { + if (mDocument) { + result = mDocument->BeginUpdate(); + if (NS_FAILED(result)) + return result; + } result = WillDirty(); - - if (NS_SUCCEEDED(result)) { - nsICSSRule *rule; - rule = (nsICSSRule*)(mInner->mOrderedRules->ElementAt(aIndex)); - if (nsnull != rule) { + if (NS_SUCCEEDED(result)) { + PRUint32 count; + mInner->mOrderedRules->Count(&count); + if (aIndex >= count) + return NS_ERROR_DOM_INDEX_SIZE_ERR; + + nsCOMPtr rule; + mInner->mOrderedRules->QueryElementAt(aIndex, NS_GET_IID(nsICSSRule), + getter_AddRefs(rule)); + if (rule) { mInner->mOrderedRules->RemoveElementAt(aIndex); rule->SetStyleSheet(nsnull); DidDirty(); - NS_RELEASE(rule); + + if (mDocument) { + result = mDocument->StyleRuleRemoved(this, rule); + NS_ENSURE_SUCCESS(result, result); + + result = mDocument->EndUpdate(); + NS_ENSURE_SUCCESS(result, result); + } } } } @@ -2606,6 +2852,122 @@ CSSStyleSheetImpl::DeleteRule(PRUint32 aIndex) return result; } +NS_IMETHODIMP +CSSStyleSheetImpl::DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex) +{ + NS_ENSURE_ARG_POINTER(aGroup); + + nsresult result; + nsCOMPtr rule; + result = aGroup->GetStyleRuleAt(aIndex, *getter_AddRefs(rule)); + NS_ENSURE_SUCCESS(result, result); + + // check that the rule actually belongs to this sheet! + nsCOMPtr domRule(do_QueryInterface(rule)); + nsCOMPtr ruleSheet; + result = domRule->GetParentStyleSheet(getter_AddRefs(ruleSheet)); + NS_ENSURE_SUCCESS(result, result); + nsCOMPtr thisSheet; + this->QueryInterface(NS_GET_IID(nsIDOMCSSStyleSheet), getter_AddRefs(thisSheet)); + + if (thisSheet != ruleSheet) { + return NS_ERROR_INVALID_ARG; + } + + result = mDocument->BeginUpdate(); + NS_ENSURE_SUCCESS(result, result); + + result = WillDirty(); + NS_ENSURE_SUCCESS(result, result); + + result = aGroup->DeleteStyleRuleAt(aIndex); + NS_ENSURE_SUCCESS(result, result); + + rule->SetStyleSheet(nsnull); + + DidDirty(); + + result = mDocument->StyleRuleRemoved(this, rule); + NS_ENSURE_SUCCESS(result, result); + + result = mDocument->EndUpdate(); + NS_ENSURE_SUCCESS(result, result); + + return NS_OK; +} + +NS_IMETHODIMP +CSSStyleSheetImpl::InsertRuleIntoGroup(nsAReadableString & aRule, nsICSSGroupRule* aGroup, PRUint32 aIndex, PRUint32* _retval) +{ + nsresult result; + // check that the group actually belongs to this sheet! + nsCOMPtr domGroup(do_QueryInterface(aGroup)); + nsCOMPtr groupSheet; + result = domGroup->GetParentStyleSheet(getter_AddRefs(groupSheet)); + NS_ENSURE_SUCCESS(result, result); + nsCOMPtr thisSheet; + this->QueryInterface(NS_GET_IID(nsIDOMCSSStyleSheet), getter_AddRefs(thisSheet)); + + if (thisSheet != groupSheet) { + return NS_ERROR_INVALID_ARG; + } + + // get the css parser + nsCOMPtr loader; + nsCOMPtr css; + nsCOMPtr htmlContainer(do_QueryInterface(mDocument)); + if (htmlContainer) { + htmlContainer->GetCSSLoader(*getter_AddRefs(loader)); + } + if (loader) { + result = loader->GetParserFor(this, getter_AddRefs(css)); + } + else { + result = NS_NewCSSParser(getter_AddRefs(css)); + css->SetStyleSheet(this); + } + NS_ENSURE_SUCCESS(result, result); + + // parse and grab the rule + result = mDocument->BeginUpdate(); + NS_ENSURE_SUCCESS(result, result); + + result = WillDirty(); + NS_ENSURE_SUCCESS(result, result); + + nsCOMPtr rule; + result = css->ParseRule(aRule, mInner->mURL, getter_AddRefs(rule)); + NS_ENSURE_SUCCESS(result, result); + + if (! rule) { + return NS_ERROR_DOM_SYNTAX_ERR; + } + + nsCOMPtr cssRule(do_QueryInterface(rule, &result)); + NS_ENSURE_SUCCESS(result, result); + + // Only rulesets are allowed in a group as of CSS2 + PRInt32 type = nsICSSRule::UNKNOWN_RULE; + cssRule->GetType(type); + if (type != nsICSSRule::STYLE_RULE) { + return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; + } + + result = aGroup->InsertStyleRuleAt(aIndex, cssRule); + NS_ENSURE_SUCCESS(result, result); + DidDirty(); + CheckRuleForAttributes(cssRule); + + result = mDocument->StyleRuleAdded(this, cssRule); + NS_ENSURE_SUCCESS(result, result); + + result = mDocument->EndUpdate(); + NS_ENSURE_SUCCESS(result, result); + + *_retval = aIndex; + return NS_OK; +} + // XXX for backwards compatibility and convenience NS_HTML nsresult NS_NewCSSStyleSheet(nsICSSStyleSheet** aInstancePtrResult, nsIURI* aURL) @@ -3731,7 +4093,8 @@ void CSSRuleProcessor::SizeOf(nsISizeOfHandler *aSizeOfHandler, PRUint32 &aSize) PRUint32 sheetCount, curSheet, localSize2; mSheets->Count(&sheetCount); for(curSheet=0; curSheet < sheetCount; curSheet++){ - nsICSSStyleSheet *pSheet = (nsICSSStyleSheet *)mSheets->ElementAt(curSheet); + nsCOMPtr pSheet; + mSheets->QueryElementAt(curSheet, NS_GET_IID(nsICSSStyleSheet), getter_AddRefs(pSheet)); if(pSheet && uniqueItems->AddItem((void*)pSheet)){ pSheet->SizeOf(aSizeOfHandler, localSize2); // XXX aSize += localSize2; @@ -3765,6 +4128,7 @@ CSSRuleProcessor::ClearRuleCascades(void) delete data; data = next; } + mRuleCascades = nsnull; return NS_OK; } @@ -3835,7 +4199,7 @@ InsertRuleByWeight(nsISupports* aRule, void* aData) { nsICSSRule* rule = (nsICSSRule*)aRule; CascadeEnumData* data = (CascadeEnumData*)aData; - PRInt32 type; + PRInt32 type = nsICSSRule::UNKNOWN_RULE; rule->GetType(type); if (nsICSSRule::STYLE_RULE == type) { @@ -3854,7 +4218,7 @@ InsertRuleByWeight(nsISupports* aRule, void* aData) } else if (nsICSSRule::MEDIA_RULE == type) { nsICSSMediaRule* mediaRule = (nsICSSMediaRule*)rule; - if (NS_OK == mediaRule->UseForMedium(data->mMedium)) { + if (mediaRule->UseForMedium(data->mMedium)) { mediaRule->EnumerateRulesForwards(InsertRuleByWeight, aData); } } @@ -3871,7 +4235,7 @@ CSSRuleProcessor::CascadeSheetRulesInto(nsISupports* aSheet, void* aData) PRBool bSheetEnabled = PR_TRUE; sheet->GetEnabled(bSheetEnabled); - if ((bSheetEnabled) && (NS_OK == sheet->UseForMedium(data->mMedium))) { + if ((bSheetEnabled) && (sheet->UseForMedium(data->mMedium))) { CSSStyleSheetImpl* child = sheet->mFirstChild; while (child) { CascadeSheetRulesInto((nsICSSStyleSheet*)child, data); diff --git a/content/html/style/src/nsHTMLCSSStyleSheet.cpp b/content/html/style/src/nsHTMLCSSStyleSheet.cpp index 4e0283e6aeb..a7face8a5b7 100644 --- a/content/html/style/src/nsHTMLCSSStyleSheet.cpp +++ b/content/html/style/src/nsHTMLCSSStyleSheet.cpp @@ -210,7 +210,7 @@ public: NS_IMETHOD GetType(nsString& aType) const; NS_IMETHOD GetMediumCount(PRInt32& aCount) const; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const; - NS_IMETHOD UseForMedium(nsIAtom* aMedium) const; + NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const; NS_IMETHOD GetEnabled(PRBool& aEnabled) const; NS_IMETHOD SetEnabled(PRBool aEnabled); @@ -518,10 +518,10 @@ HTMLCSSStyleSheetImpl::GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const return NS_ERROR_INVALID_ARG; } -NS_IMETHODIMP +NS_IMETHODIMP_(PRBool) HTMLCSSStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const { - return NS_OK; // works for all media + return PR_TRUE; // works for all media } NS_IMETHODIMP diff --git a/content/html/style/src/nsHTMLStyleSheet.cpp b/content/html/style/src/nsHTMLStyleSheet.cpp index 7b4296a54c4..0fba8caff67 100644 --- a/content/html/style/src/nsHTMLStyleSheet.cpp +++ b/content/html/style/src/nsHTMLStyleSheet.cpp @@ -536,7 +536,7 @@ public: NS_IMETHOD GetType(nsString& aType) const; NS_IMETHOD GetMediumCount(PRInt32& aCount) const; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const; - NS_IMETHOD UseForMedium(nsIAtom* aMedium) const; + NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const; NS_IMETHOD GetEnabled(PRBool& aEnabled) const; NS_IMETHOD SetEnabled(PRBool aEnabled); @@ -952,10 +952,10 @@ HTMLStyleSheetImpl::GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const return NS_ERROR_INVALID_ARG; } -NS_IMETHODIMP +NS_IMETHODIMP_(PRBool) HTMLStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const { - return NS_OK; // works for all media + return PR_TRUE; // works for all media } diff --git a/content/html/style/src/nsICSSGroupRule.h b/content/html/style/src/nsICSSGroupRule.h index 53118d59b8b..b6d27c53cbb 100644 --- a/content/html/style/src/nsICSSGroupRule.h +++ b/content/html/style/src/nsICSSGroupRule.h @@ -42,6 +42,17 @@ public: NS_IMETHOD GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const = 0; NS_IMETHOD EnumerateRulesForwards(nsISupportsArrayEnumFunc aFunc, void * aData) const = 0; + + /* + * The next two methods (DeleteStyleRuleAt and InsertStyleRuleAt) + * should never be called unless you have first called WillDirty() + * on the parent stylesheet. After they are called, DidDirty() + * needs to be called on the sheet + */ + NS_IMETHOD DeleteStyleRuleAt(PRUint32 aIndex) = 0; + NS_IMETHOD InsertStyleRuleAt(PRUint32 aIndex, nsICSSRule* aRule) = 0; + + }; #endif /* nsICSSGroupRule_h___ */ diff --git a/content/html/style/src/nsICSSMediaRule.h b/content/html/style/src/nsICSSMediaRule.h index b18cde0d35f..f88ed144ef9 100644 --- a/content/html/style/src/nsICSSMediaRule.h +++ b/content/html/style/src/nsICSSMediaRule.h @@ -37,7 +37,7 @@ public: static const nsIID& GetIID() { static nsIID iid = NS_ICSS_MEDIA_RULE_IID; return iid; } NS_IMETHOD SetMedia(nsISupportsArray* aMedia) = 0; - NS_IMETHOD UseForMedium(nsIAtom* aMedium) const = 0; + NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const = 0; }; extern NS_HTML nsresult diff --git a/dom/public/idl/stylesheets/nsIDOMMediaList.idl b/dom/public/idl/stylesheets/nsIDOMMediaList.idl index 3c9bf826440..550a47413cb 100644 --- a/dom/public/idl/stylesheets/nsIDOMMediaList.idl +++ b/dom/public/idl/stylesheets/nsIDOMMediaList.idl @@ -33,8 +33,8 @@ interface nsIDOMMediaList : nsISupports readonly attribute unsigned long length; DOMString item(in unsigned long index); - void delete(in DOMString oldMedium) + void deleteMedium(in DOMString oldMedium) raises(DOMException); - void append(in DOMString newMedium) + void appendMedium(in DOMString newMedium) raises(DOMException); }; diff --git a/dom/public/nsIDOMClassInfo.h b/dom/public/nsIDOMClassInfo.h index e1f735b953c..89ae4e07b5b 100644 --- a/dom/public/nsIDOMClassInfo.h +++ b/dom/public/nsIDOMClassInfo.h @@ -140,6 +140,7 @@ enum nsDOMClassInfoID { eDOMClassInfo_CSSMediaRule_id, eDOMClassInfo_CSSNameSpaceRule_id, eDOMClassInfo_CSSRuleList_id, + eDOMClassInfo_CSSGroupRuleRuleList_id, eDOMClassInfo_MediaList_id, eDOMClassInfo_StyleSheetList_id, eDOMClassInfo_CSSStyleSheet_id, diff --git a/dom/src/base/nsDOMClassInfo.cpp b/dom/src/base/nsDOMClassInfo.cpp index 16bc8854748..36a19966c55 100644 --- a/dom/src/base/nsDOMClassInfo.cpp +++ b/dom/src/base/nsDOMClassInfo.cpp @@ -570,6 +570,8 @@ static nsDOMClassInfoData sClassInfoData[] = { DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(CSSRuleList, nsCSSRuleListSH, ARRAY_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(CSSGroupRuleRuleList, nsCSSRuleListSH, + ARRAY_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(MediaList, nsMediaListSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(StyleSheetList, nsDOMGenericSH, @@ -1409,7 +1411,7 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(CSSMediaRule, nsIDOMCSSMediaRule) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRule) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSMediaRule) DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(CSSNameSpaceRule, nsIDOMCSSRule) @@ -1420,6 +1422,10 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRuleList) DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(CSSGroupRuleRuleList, nsIDOMCSSRuleList) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRuleList) + DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(MediaList, nsIDOMMediaList) DOM_CLASSINFO_MAP_ENTRY(nsIDOMMediaList) DOM_CLASSINFO_MAP_END diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 0b7c810b1b3..d66334a548e 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -154,6 +154,10 @@ public: PRBool aParseOnlyOneDecl, PRInt32* aHint); + NS_IMETHOD ParseRule(nsAReadableString& aRule, + nsIURI* aBaseURL, + nsIStyleRule** aResult); + NS_IMETHOD GetCharset(/*out*/nsAWritableString &aCharsetDest) const; // sets the out-param to the current charset, as set by SetCharset NS_IMETHOD SetCharset(/*in*/ const nsAReadableString &aCharsetSrc); @@ -180,18 +184,18 @@ protected: void PopGroup(void); void AppendRule(nsICSSRule* aRule); - PRBool ParseRuleSet(PRInt32& aErrorCode); - PRBool ParseAtRule(PRInt32& aErrorCode); - PRBool ParseCharsetRule(PRInt32& aErrorCode); - PRBool ParseImportRule(PRInt32& aErrorCode); + PRBool ParseRuleSet(PRInt32& aErrorCode, nsIStyleRule** aResult = nsnull); + PRBool ParseAtRule(PRInt32& aErrorCode, nsIStyleRule** aResult = nsnull); + PRBool ParseCharsetRule(PRInt32& aErrorCode, nsIStyleRule** aResult); + PRBool ParseImportRule(PRInt32& aErrorCode, nsIStyleRule** aResult); PRBool GatherMedia(PRInt32& aErrorCode, nsString& aMedia, nsISupportsArray* aMediaAtoms); - PRBool ProcessImport(PRInt32& aErrorCode, const nsString& aURLSpec, const nsString& aMedia); - PRBool ParseMediaRule(PRInt32& aErrorCode); - PRBool ParseNameSpaceRule(PRInt32& aErrorCode); + PRBool ProcessImport(PRInt32& aErrorCode, const nsString& aURLSpec, const nsString& aMedia, nsIStyleRule** aResult); + PRBool ParseMediaRule(PRInt32& aErrorCode, nsIStyleRule** aResult); + PRBool ParseNameSpaceRule(PRInt32& aErrorCode, nsIStyleRule** aResult); PRBool ProcessNameSpace(PRInt32& aErrorCode, const nsString& aPrefix, - const nsString& aURLSpec); - PRBool ParseFontFaceRule(PRInt32& aErrorCode); - PRBool ParsePageRule(PRInt32& aErrorCode); + const nsString& aURLSpec, nsIStyleRule** aResult); + PRBool ParseFontFaceRule(PRInt32& aErrorCode, nsIStyleRule** aResult); + PRBool ParsePageRule(PRInt32& aErrorCode, nsIStyleRule** aResult); void ParseIDSelector(PRInt32& aDataMask, nsCSSSelector& aSelector, PRInt32& aParsingStatus, PRInt32& aErrorCode); @@ -677,6 +681,49 @@ CSSParserImpl::ParseAndAppendDeclaration(const nsAReadableString& aBuffer, return rv; } +NS_IMETHODIMP +CSSParserImpl::ParseRule(nsAReadableString& aRule, + nsIURI* aBaseURL, + nsIStyleRule** aResult) +{ + NS_ASSERTION(nsnull != aBaseURL, "need base URL"); + NS_ENSURE_ARG_POINTER(aResult); + *aResult = nsnull; + + nsString* str = new nsString(aRule); + if (nsnull == str) { + return NS_ERROR_OUT_OF_MEMORY; + } + nsCOMPtr input = nsnull; + nsresult rv = NS_NewStringUnicharInputStream(getter_AddRefs(input), str); + if (NS_OK != rv) { + delete str; + return rv; + } + + rv = InitScanner(input, aBaseURL); + if (! NS_SUCCEEDED(rv)) { + return rv; + } + + mSection = eCSSSection_Charset; // callers are responsible for rejecting invalid rules. Maybe pass in the previous rule to this method? + PRInt32 errorCode = NS_OK; + + nsCSSToken* tk = &mToken; + // Get first non-whitespace token + if (!GetToken(errorCode, PR_TRUE)) { + OUTPUT_ERROR(); + } else if (eCSSToken_AtKeyword == tk->mType) { + ParseAtRule(errorCode, aResult); + } + else { + UngetToken(); + ParseRuleSet(errorCode, aResult); + } + ReleaseScanner(); + return NS_OK; +} + //---------------------------------------------------------------------- PRBool CSSParserImpl::GetToken(PRInt32& aErrorCode, PRBool aSkipWS) @@ -790,43 +837,43 @@ PRBool CSSParserImpl::SkipAtRule(PRInt32& aErrorCode) return PR_TRUE; } -PRBool CSSParserImpl::ParseAtRule(PRInt32& aErrorCode) +PRBool CSSParserImpl::ParseAtRule(PRInt32& aErrorCode, nsIStyleRule** aResult) { if ((mSection <= eCSSSection_Charset) && (mToken.mIdent.EqualsIgnoreCase("charset"))) { - if (ParseCharsetRule(aErrorCode)) { + if (ParseCharsetRule(aErrorCode, aResult)) { mSection = eCSSSection_Import; // only one charset allowed return PR_TRUE; } } if ((mSection <= eCSSSection_Import) && mToken.mIdent.EqualsIgnoreCase("import")) { - if (ParseImportRule(aErrorCode)) { + if (ParseImportRule(aErrorCode, aResult)) { mSection = eCSSSection_Import; return PR_TRUE; } } if ((mSection <= eCSSSection_NameSpace) && mToken.mIdent.EqualsIgnoreCase("namespace")) { - if (ParseNameSpaceRule(aErrorCode)) { + if (ParseNameSpaceRule(aErrorCode, aResult)) { mSection = eCSSSection_NameSpace; return PR_TRUE; } } if (mToken.mIdent.EqualsIgnoreCase("media")) { - if (ParseMediaRule(aErrorCode)) { + if (ParseMediaRule(aErrorCode, aResult)) { mSection = eCSSSection_General; return PR_TRUE; } } if (mToken.mIdent.EqualsIgnoreCase("font-face")) { - if (ParseFontFaceRule(aErrorCode)) { + if (ParseFontFaceRule(aErrorCode, aResult)) { mSection = eCSSSection_General; return PR_TRUE; } } if (mToken.mIdent.EqualsIgnoreCase("page")) { - if (ParsePageRule(aErrorCode)) { + if (ParsePageRule(aErrorCode, aResult)) { mSection = eCSSSection_General; return PR_TRUE; } @@ -839,7 +886,7 @@ PRBool CSSParserImpl::ParseAtRule(PRInt32& aErrorCode) return SkipAtRule(aErrorCode); } -PRBool CSSParserImpl::ParseCharsetRule(PRInt32& aErrorCode) +PRBool CSSParserImpl::ParseCharsetRule(PRInt32& aErrorCode, nsIStyleRule** aResult) { // XXX not yet implemented return PR_FALSE; @@ -914,7 +961,7 @@ PRBool CSSParserImpl::GatherMedia(PRInt32& aErrorCode, nsString& aMedia, } // Parse a CSS2 import rule: "@import STRING | URL [medium [, mdeium]]" -PRBool CSSParserImpl::ParseImportRule(PRInt32& aErrorCode) +PRBool CSSParserImpl::ParseImportRule(PRInt32& aErrorCode, nsIStyleRule** aResult) { if (!GetToken(aErrorCode, PR_TRUE)) { REPORT_UNEXPECTED_EOF(); @@ -927,7 +974,7 @@ PRBool CSSParserImpl::ParseImportRule(PRInt32& aErrorCode) url = mToken.mIdent; if (GatherMedia(aErrorCode, media, nsnull)) { if (ExpectSymbol(aErrorCode, ';', PR_TRUE)) { - ProcessImport(aErrorCode, url, media); + ProcessImport(aErrorCode, url, media, aResult); return PR_TRUE; } } @@ -941,7 +988,7 @@ PRBool CSSParserImpl::ParseImportRule(PRInt32& aErrorCode) if (ExpectSymbol(aErrorCode, ')', PR_TRUE)) { if (GatherMedia(aErrorCode, media, nsnull)) { if (ExpectSymbol(aErrorCode, ';', PR_TRUE)) { - ProcessImport(aErrorCode, url, media); + ProcessImport(aErrorCode, url, media, aResult); return PR_TRUE; } } @@ -957,12 +1004,18 @@ PRBool CSSParserImpl::ParseImportRule(PRInt32& aErrorCode) } -PRBool CSSParserImpl::ProcessImport(PRInt32& aErrorCode, const nsString& aURLSpec, const nsString& aMedia) +PRBool CSSParserImpl::ProcessImport(PRInt32& aErrorCode, const nsString& aURLSpec, const nsString& aMedia, nsIStyleRule** aResult) { nsCOMPtr rule; NS_NewCSSImportRule(getter_AddRefs(rule), aURLSpec, aMedia); if (rule) { - AppendRule(rule); + if (aResult) { // someone wants this rule + *aResult = rule; + NS_ADDREF(*aResult); + } + else { + AppendRule(rule); + } } if (mChildLoader) { @@ -989,18 +1042,18 @@ PRBool CSSParserImpl::ProcessImport(PRInt32& aErrorCode, const nsString& aURLSpe } // Parse a CSS2 media rule: "@media medium [, medium] { ... }" -PRBool CSSParserImpl::ParseMediaRule(PRInt32& aErrorCode) +PRBool CSSParserImpl::ParseMediaRule(PRInt32& aErrorCode, nsIStyleRule** aResult) { nsAutoString mediaStr; - nsISupportsArray* media = nsnull; - NS_NewISupportsArray(&media); + nsCOMPtr media; + NS_NewISupportsArray(getter_AddRefs(media)); if (media) { if (GatherMedia(aErrorCode, mediaStr, media)) { if ((0 < mediaStr.Length()) && ExpectSymbol(aErrorCode, '{', PR_TRUE)) { // push media rule on stack, loop over children - nsICSSMediaRule* rule = nsnull; - NS_NewCSSMediaRule(&rule); + nsCOMPtr rule; + NS_NewCSSMediaRule(getter_AddRefs(rule)); if (rule) { if (PushGroup(rule)) { @@ -1027,29 +1080,34 @@ PRBool CSSParserImpl::ParseMediaRule(PRInt32& aErrorCode) PopGroup(); if (ExpectSymbol(aErrorCode, '}', PR_TRUE)) { - rule->SetMedia(media); - AppendRule(rule); - NS_RELEASE(rule); - NS_RELEASE(media); + if (aResult) { // someone wants this rule + rule->SetMedia(media); + *aResult = rule; + NS_ADDREF(*aResult); + } + else { + // Append first, so when we do SetMedia() the rule + // knows what its stylesheet is. + AppendRule(rule); + rule->SetMedia(media); + } return PR_TRUE; } mSection = holdSection; } - NS_RELEASE(rule); } else { // failed to create rule, backup and skip block UngetToken(); } } } - NS_RELEASE(media); } return PR_FALSE; } // Parse a CSS3 namespace rule: "@namespace [prefix] STRING | URL;" -PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode) +PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode, nsIStyleRule** aResult) { if (!GetToken(aErrorCode, PR_TRUE)) { REPORT_UNEXPECTED_EOF(); @@ -1071,7 +1129,7 @@ PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode) if (eCSSToken_String == mToken.mType) { url = mToken.mIdent; if (ExpectSymbol(aErrorCode, ';', PR_TRUE)) { - ProcessNameSpace(aErrorCode, prefix, url); + ProcessNameSpace(aErrorCode, prefix, url, aResult); return PR_TRUE; } } @@ -1083,7 +1141,7 @@ PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode) url = mToken.mIdent; if (ExpectSymbol(aErrorCode, ')', PR_TRUE)) { if (ExpectSymbol(aErrorCode, ';', PR_TRUE)) { - ProcessNameSpace(aErrorCode, prefix, url); + ProcessNameSpace(aErrorCode, prefix, url, aResult); return PR_TRUE; } } @@ -1098,36 +1156,40 @@ PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode) } PRBool CSSParserImpl::ProcessNameSpace(PRInt32& aErrorCode, const nsString& aPrefix, - const nsString& aURLSpec) + const nsString& aURLSpec, nsIStyleRule** aResult) { PRBool result = PR_FALSE; - nsICSSNameSpaceRule* rule = nsnull; - nsIAtom* prefix = nsnull; + nsCOMPtr rule; + nsCOMPtr prefix; if (0 < aPrefix.Length()) { - prefix = NS_NewAtom(aPrefix); + prefix = dont_AddRef(NS_NewAtom(aPrefix)); } - NS_NewCSSNameSpaceRule(&rule, prefix, aURLSpec); + NS_NewCSSNameSpaceRule(getter_AddRefs(rule), prefix, aURLSpec); if (rule) { - AppendRule(rule); - NS_RELEASE(rule); - NS_IF_RELEASE(mNameSpace); - mSheet->GetNameSpace(mNameSpace); + if (aResult) { // someone wants this rule + *aResult = rule; + NS_ADDREF(*aResult); + } + else { + AppendRule(rule); + NS_IF_RELEASE(mNameSpace); + mSheet->GetNameSpace(mNameSpace); + } } - NS_IF_RELEASE(prefix); return result; } -PRBool CSSParserImpl::ParseFontFaceRule(PRInt32& aErrorCode) +PRBool CSSParserImpl::ParseFontFaceRule(PRInt32& aErrorCode, nsIStyleRule** aResult) { // XXX not yet implemented return PR_FALSE; } -PRBool CSSParserImpl::ParsePageRule(PRInt32& aErrorCode) +PRBool CSSParserImpl::ParsePageRule(PRInt32& aErrorCode, nsIStyleRule** aResult) { // XXX not yet implemented return PR_FALSE; @@ -1251,7 +1313,7 @@ void CSSParserImpl::AppendRule(nsICSSRule* aRule) } } -PRBool CSSParserImpl::ParseRuleSet(PRInt32& aErrorCode) +PRBool CSSParserImpl::ParseRuleSet(PRInt32& aErrorCode, nsIStyleRule** aResult) { // First get the list of selectors for the rule SelectorList* slist = nsnull; @@ -1299,7 +1361,13 @@ PRBool CSSParserImpl::ParseRuleSet(PRInt32& aErrorCode) rule->SetDeclaration(declaration); rule->SetWeight(list->mWeight); // rule->List(); - AppendRule(rule); + if (aResult) { // someone wants this rule back; don't append it + *aResult = rule; + NS_ADDREF(*aResult); + } + else { + AppendRule(rule); + } NS_RELEASE(rule); } diff --git a/layout/style/nsCSSRules.cpp b/layout/style/nsCSSRules.cpp index 1ada56e6884..637cadf6ffd 100644 --- a/layout/style/nsCSSRules.cpp +++ b/layout/style/nsCSSRules.cpp @@ -18,6 +18,8 @@ * Rights Reserved. * * Contributor(s): + * Boris Zbarsky + * */ #include "nsICSSCharsetRule.h" #include "nsICSSImportRule.h" @@ -39,11 +41,16 @@ #include "nsIDOMCSSStyleSheet.h" #include "nsIDOMCSSRule.h" #include "nsIDOMCSSImportRule.h" +#include "nsIDOMCSSMediaRule.h" #include "nsIMediaList.h" #include "nsIDOMMediaList.h" +#include "nsIDOMCSSRuleList.h" #include "nsIDOMStyleSheet.h" +#include "nsIDocument.h" #include "nsContentUtils.h" +#include "nsStyleConsts.h" +#include "nsDOMError.h" static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); @@ -64,6 +71,84 @@ NS_IMETHODIMP _class::GetStyleSheet(nsIStyleSheet*& aSheet) const { return super NS_IMETHODIMP _class::GetStrength(PRInt32& aStrength) const { return super::GetStrength(aStrength); } \ NS_IMETHODIMP _class::MapRuleInfoInto(nsRuleData* aRuleData) { return NS_OK; } +// ------------------------------- +// Style Rule List for group rules +// +class CSSGroupRuleRuleListImpl : public nsIDOMCSSRuleList +{ +public: + CSSGroupRuleRuleListImpl(nsICSSGroupRule *aGroupRule); + + NS_DECL_ISUPPORTS + + NS_DECL_NSIDOMCSSRULELIST + + void DropReference() { mGroupRule = nsnull; } + +protected: + virtual ~CSSGroupRuleRuleListImpl(void); + +private: + nsICSSGroupRule* mGroupRule; +}; + +CSSGroupRuleRuleListImpl::CSSGroupRuleRuleListImpl(nsICSSGroupRule *aGroupRule) +{ + NS_INIT_REFCNT(); + // Not reference counted to avoid circular references. + // The rule will tell us when its going away. + mGroupRule = aGroupRule; +} + +CSSGroupRuleRuleListImpl::~CSSGroupRuleRuleListImpl() +{ +} + +// QueryInterface implementation for CSSGroupRuleRuleList +NS_INTERFACE_MAP_BEGIN(CSSGroupRuleRuleListImpl) + NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRuleList) + NS_INTERFACE_MAP_ENTRY(nsISupports) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSGroupRuleRuleList) +NS_INTERFACE_MAP_END + + +NS_IMPL_ADDREF(CSSGroupRuleRuleListImpl); +NS_IMPL_RELEASE(CSSGroupRuleRuleListImpl); + +NS_IMETHODIMP +CSSGroupRuleRuleListImpl::GetLength(PRUint32* aLength) +{ + if (mGroupRule) { + PRInt32 count; + mGroupRule->StyleRuleCount(count); + *aLength = (PRUint32)count; + } else { + *aLength = 0; + } + + return NS_OK; +} + +NS_IMETHODIMP +CSSGroupRuleRuleListImpl::Item(PRUint32 aIndex, nsIDOMCSSRule** aReturn) +{ + nsresult result = NS_OK; + + *aReturn = nsnull; + if (mGroupRule) { + nsCOMPtr rule; + + result = mGroupRule->GetStyleRuleAt(aIndex, *getter_AddRefs(rule)); + if (rule) { + result = CallQueryInterface(rule, aReturn); + } else if (result == NS_ERROR_ILLEGAL_VALUE) { + result = NS_OK; // per spec: "Return Value ... null if ... not a valid index." + } + } + + return result; +} + // ------------------------------------------- // nsICSSCharsetRule // @@ -374,7 +459,7 @@ CSSImportRuleImpl::List(FILE* out, PRInt32 aIndent) const fputs("\" ", out); nsAutoString mediaText; - mMedia->GetMediaText(mediaText); + mMedia->GetText(mediaText); fputs(mediaText, out); fputs("\n", out); @@ -456,7 +541,7 @@ NS_IMETHODIMP CSSImportRuleImpl::SetMedia(const nsString& aMedia) { if (mMedia) { - return mMedia->SetMediaText(aMedia); + return mMedia->SetText(aMedia); } else { return NS_OK; } @@ -466,7 +551,7 @@ NS_IMETHODIMP CSSImportRuleImpl::GetMedia(nsString& aMedia) const { if (mMedia) { - return mMedia->GetMediaText(aMedia); + return mMedia->GetText(aMedia); } else { aMedia.Truncate(); return NS_OK; @@ -527,7 +612,7 @@ CSSImportRuleImpl::GetCssText(nsAWritableString& aCssText) aCssText.Append(NS_LITERAL_STRING(")")); if (mMedia) { nsAutoString mediaText; - mMedia->GetMediaText(mediaText); + mMedia->GetText(mediaText); if (!mediaText.IsEmpty()) { aCssText.Append(NS_LITERAL_STRING(" ")); aCssText.Append(mediaText); @@ -596,7 +681,7 @@ CSSImportRuleImpl::GetStyleSheet(nsIDOMCSSStyleSheet * *aStyleSheet) // class CSSMediaRuleImpl : public nsCSSRule, public nsICSSMediaRule, - public nsIDOMCSSRule + public nsIDOMCSSMediaRule { public: CSSMediaRuleImpl(void); @@ -618,27 +703,33 @@ public: // nsICSSMediaRule methods NS_IMETHOD SetMedia(nsISupportsArray* aMedia); - NS_IMETHOD UseForMedium(nsIAtom* aMedium) const; + 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 InsertStyleRuleAt(PRUint32 aIndex, nsICSSRule* aRule); + // nsIDOMCSSRule interface NS_DECL_NSIDOMCSSRULE + // nsIDOMCSSMediaRule interface + NS_DECL_NSIDOMCSSMEDIARULE + protected: - nsISupportsArray* mMedia; + nsCOMPtr mMedia; nsISupportsArray* mRules; + CSSGroupRuleRuleListImpl* mRuleCollection; }; CSSMediaRuleImpl::CSSMediaRuleImpl(void) : nsCSSRule(), mMedia(nsnull), - mRules(nsnull) + mRules(nsnull), + mRuleCollection(nsnull) { } @@ -659,13 +750,11 @@ CloneRuleInto(nsISupports* aRule, void* aArray) CSSMediaRuleImpl::CSSMediaRuleImpl(const CSSMediaRuleImpl& aCopy) : nsCSSRule(aCopy), mMedia(nsnull), - mRules(nsnull) + mRules(nsnull), + mRuleCollection(nsnull) { if (aCopy.mMedia) { - NS_NewISupportsArray(&mMedia); - if (mMedia) { - mMedia->AppendElements(aCopy.mMedia); - } + NS_NewMediaList(aCopy.mMedia, aCopy.mSheet, getter_AddRefs(mMedia)); } if (aCopy.mRules) { @@ -678,8 +767,14 @@ CSSMediaRuleImpl::CSSMediaRuleImpl(const CSSMediaRuleImpl& aCopy) CSSMediaRuleImpl::~CSSMediaRuleImpl(void) { - NS_IF_RELEASE(mMedia); NS_IF_RELEASE(mRules); + if (mMedia) { + mMedia->DropReference(); + } + if (mRuleCollection) { + mRuleCollection->DropReference(); + NS_RELEASE(mRuleCollection); + } } NS_IMPL_ADDREF_INHERITED(CSSMediaRuleImpl, nsCSSRule); @@ -691,6 +786,7 @@ NS_INTERFACE_MAP_BEGIN(CSSMediaRuleImpl) 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 @@ -712,6 +808,17 @@ CSSMediaRuleImpl::SetStyleSheet(nsICSSStyleSheet* aSheet) if (mRules) { mRules->EnumerateForwards(SetStyleSheetReference, aSheet); } + if (mMedia) { + nsresult rv; + nsCOMPtr oldMedia(do_QueryInterface(mMedia, &rv)); + if (NS_FAILED(rv)) + return rv; + mMedia->DropReference(); + rv = NS_NewMediaList(oldMedia, aSheet, getter_AddRefs(mMedia)); + if (NS_FAILED(rv)) + return rv; + } + return nsCSSRule::SetStyleSheet(aSheet); } @@ -729,13 +836,13 @@ CSSMediaRuleImpl::List(FILE* out, PRInt32 aIndent) const PRUint32 count; mMedia->Count(&count); while (index < count) { - nsIAtom* medium = (nsIAtom*)mMedia->ElementAt(index++); + nsCOMPtr medium; + mMedia->QueryElementAt(index++, NS_GET_IID(nsIAtom), getter_AddRefs(medium)); medium->ToString(buffer); fputs(buffer, out); if (index < count) { fputs(", ", out); } - NS_RELEASE(medium); } } fputs(" {\n", out); @@ -745,9 +852,9 @@ CSSMediaRuleImpl::List(FILE* out, PRInt32 aIndent) const PRUint32 count; mRules->Count(&count); while (index < count) { - nsICSSRule* rule = (nsICSSRule*)mRules->ElementAt(index++); + nsCOMPtr rule; + mRules->QueryElementAt(index++, NS_GET_IID(nsICSSRule), getter_AddRefs(rule)); rule->List(out, aIndent + 1); - NS_RELEASE(rule); } } fputs("}\n", out); @@ -791,12 +898,12 @@ void CSSMediaRuleImpl::SizeOf(nsISizeOfHandler *aSizeOfHandler, PRUint32 &aSize) PRUint32 count; mMedia->Count(&count); while (index < count) { - nsIAtom* medium = (nsIAtom*)mMedia->ElementAt(index++); + nsCOMPtr medium; + mMedia->QueryElementAt(index++, NS_GET_IID(nsIAtom), getter_AddRefs(medium)); if(medium && uniqueItems->AddItem(medium)){ medium->SizeOf(aSizeOfHandler, &localSize); aSize += localSize; } - NS_IF_RELEASE(medium); } } // we are done with the size we report for ourself @@ -808,9 +915,9 @@ void CSSMediaRuleImpl::SizeOf(nsISizeOfHandler *aSizeOfHandler, PRUint32 &aSize) PRUint32 count; mRules->Count(&count); while (index < count) { - nsICSSRule* rule = (nsICSSRule*)mRules->ElementAt(index++); + nsCOMPtr rule; + mRules->QueryElementAt(index++, NS_GET_IID(nsICSSRule), getter_AddRefs(rule)); rule->SizeOf(aSizeOfHandler, localSize); - NS_RELEASE(rule); } } } @@ -837,26 +944,18 @@ CSSMediaRuleImpl::Clone(nsICSSRule*& aClone) const NS_IMETHODIMP CSSMediaRuleImpl::SetMedia(nsISupportsArray* aMedia) { - nsresult result = NS_OK; - NS_IF_RELEASE(mMedia); - mMedia = aMedia; - NS_IF_ADDREF(mMedia); - return result; + return NS_NewMediaList(aMedia, mSheet, getter_AddRefs(mMedia)); } -NS_IMETHODIMP +NS_IMETHODIMP_(PRBool) CSSMediaRuleImpl::UseForMedium(nsIAtom* aMedium) const { if (mMedia) { - if (-1 != mMedia->IndexOf(aMedium)) { - return NS_OK; - } - if (-1 != mMedia->IndexOf(nsLayoutAtoms::all)) { - return NS_OK; - } - return NS_COMFALSE; + PRBool matches = PR_FALSE; + mMedia->MatchesMedium(aMedium, &matches); + return matches; } - return NS_OK; + return PR_TRUE; } NS_IMETHODIMP @@ -894,10 +993,17 @@ 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_INVALID_ARG; + return NS_ERROR_ILLEGAL_VALUE; } NS_IMETHODIMP @@ -909,6 +1015,37 @@ CSSMediaRuleImpl::EnumerateRulesForwards(nsISupportsArrayEnumFunc aFunc, void * return NS_OK; } +/* + * The next two methods (DeleteStyleRuleAt and InsertStyleRuleAt) + * 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; + nsresult rv = mRules->QueryElementAt(aIndex, NS_GET_IID(nsICSSRule), getter_AddRefs(rule)); + NS_ENSURE_SUCCESS(rv, rv); + rule->SetStyleSheet(nsnull); + return mRules->DeleteElementAt(aIndex); +} + +NS_IMETHODIMP +CSSMediaRuleImpl::InsertStyleRuleAt(PRUint32 aIndex, nsICSSRule* aRule) +{ + NS_ENSURE_TRUE(mRules, NS_ERROR_FAILURE); + + // There is no xpcom-compatible version of InsertElementAt.... :( + if (! mRules->InsertElementAt(aRule, aIndex)) { + return NS_ERROR_FAILURE; + } + aRule->SetStyleSheet(mSheet); + return NS_OK; +} + nsresult NS_NewCSSMediaRule(nsICSSMediaRule** aInstancePtrResult) @@ -926,6 +1063,7 @@ NS_NewCSSMediaRule(nsICSSMediaRule** aInstancePtrResult) return it->QueryInterface(NS_GET_IID(nsICSSMediaRule), (void **) aInstancePtrResult); } +// nsIDOMCSSRule methods NS_IMETHODIMP CSSMediaRuleImpl::GetType(PRUint16* aType) { @@ -943,7 +1081,8 @@ CSSMediaRuleImpl::GetCssText(nsAWritableString& aCssText) if (mMedia) { mMedia->Count(&count); for (index = 0; index < count; index++) { - nsCOMPtr medium (do_QueryInterface(mMedia->ElementAt(index))); + nsCOMPtr medium; + mMedia->QueryElementAt(index, NS_GET_IID(nsIAtom), getter_AddRefs(medium)); if (medium) { nsAutoString tempString; if (index > 0) @@ -960,7 +1099,8 @@ CSSMediaRuleImpl::GetCssText(nsAWritableString& aCssText) if (mRules) { mRules->Count(&count); for (index = 0; index < count; index++) { - nsCOMPtr rule (do_QueryInterface(mRules->ElementAt(index))); + nsCOMPtr rule; + mRules->QueryElementAt(index, NS_GET_IID(nsIDOMCSSRule), getter_AddRefs(rule)); if (rule) { nsAutoString tempString; rule->GetCssText(tempString); @@ -998,6 +1138,60 @@ CSSMediaRuleImpl::GetParentRule(nsIDOMCSSRule** aParentRule) return NS_ERROR_NOT_IMPLEMENTED; } +// nsIDOMCSSMediaRule methods +NS_IMETHODIMP +CSSMediaRuleImpl::GetMedia(nsIDOMMediaList* *aMedia) +{ + NS_ENSURE_ARG_POINTER(aMedia); + if (!mMedia) { + *aMedia = nsnull; + return NS_OK; + } + + return CallQueryInterface(mMedia, aMedia); +} + +NS_IMETHODIMP +CSSMediaRuleImpl::GetCssRules(nsIDOMCSSRuleList* *aRuleList) +{ + if (!mRuleCollection) { + mRuleCollection = new CSSGroupRuleRuleListImpl(this); + if (!mRuleCollection) { + return NS_ERROR_OUT_OF_MEMORY; + } + NS_ADDREF(mRuleCollection); + } + + return CallQueryInterface(mRuleCollection, aRuleList); +} + +NS_IMETHODIMP +CSSMediaRuleImpl::InsertRule(nsAReadableString & aRule, PRUint32 aIndex, PRUint32* _retval) +{ + NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE); + NS_ENSURE_TRUE(mRules, NS_ERROR_FAILURE); + + PRUint32 count; + mRules->Count(&count); + if (aIndex > count) + return NS_ERROR_DOM_INDEX_SIZE_ERR; + + return mSheet->InsertRuleIntoGroup(aRule, this, aIndex, _retval); +} + +NS_IMETHODIMP +CSSMediaRuleImpl::DeleteRule(PRUint32 aIndex) +{ + NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE); + NS_ENSURE_TRUE(mRules, NS_ERROR_FAILURE); + + PRUint32 count; + mRules->Count(&count); + if (aIndex >= count) + return NS_ERROR_DOM_INDEX_SIZE_ERR; + + return mSheet->DeleteRuleFromGroup(this, aIndex); +} // ------------------------------------------- // nsICSSNameSpaceRule @@ -1251,3 +1445,4 @@ CSSNameSpaceRuleImpl::GetParentRule(nsIDOMCSSRule** aParentRule) { return NS_ERROR_NOT_IMPLEMENTED; } + diff --git a/layout/style/nsCSSStyleSheet.cpp b/layout/style/nsCSSStyleSheet.cpp index 025a1eec4eb..6d7bafee8e8 100644 --- a/layout/style/nsCSSStyleSheet.cpp +++ b/layout/style/nsCSSStyleSheet.cpp @@ -40,6 +40,7 @@ #include "nsIMediaList.h" #include "nsIHTMLContent.h" #include "nsIDocument.h" +#include "nsIHTMLContentContainer.h" #include "nsIPresContext.h" #include "nsIEventStateManager.h" #include "nsHTMLAtoms.h" @@ -61,6 +62,7 @@ #include "nsDOMError.h" #include "nsIPresShell.h" #include "nsICSSParser.h" +#include "nsICSSLoader.h" #include "nsIRuleWalker.h" #include "nsCSSAtoms.h" #include "nsINameSpaceManager.h" @@ -679,7 +681,7 @@ public: nsISupportsArray* mOrderedRules; - nsINameSpace* mNameSpace; + nsCOMPtr mNameSpace; PRInt32 mDefaultNameSpaceID; nsHashtable mRelevantAttributes; }; @@ -715,10 +717,12 @@ public: NS_IMETHOD GetType(nsString& aType) const; NS_IMETHOD GetMediumCount(PRInt32& aCount) const; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const; - NS_IMETHOD UseForMedium(nsIAtom* aMedium) const; + NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const; NS_IMETHOD AppendMedium(nsIAtom* aMedium); NS_IMETHOD ClearMedia(void); - + NS_IMETHOD DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex); + NS_IMETHOD InsertRuleIntoGroup(nsAReadableString& aRule, nsICSSGroupRule* aGroup, PRUint32 aIndex, PRUint32* _retval); + NS_IMETHOD GetEnabled(PRBool& aEnabled) const; NS_IMETHOD SetEnabled(PRBool aEnabled); @@ -812,7 +816,8 @@ protected: nsVoidArray* mRuleProcessors; -friend class CSSRuleProcessor; + friend class CSSRuleProcessor; + friend class DOMMediaListImpl; }; @@ -923,13 +928,22 @@ class DOMMediaListImpl : public nsIDOMMediaList, return mArray->ElementAt(aIndex); } + // nsIMediaList methods + NS_DECL_NSIMEDIALIST + DOMMediaListImpl(nsISupportsArray *aArray, CSSStyleSheetImpl *aStyleSheet); virtual ~DOMMediaListImpl(); - void DropReference() { mStyleSheet = nsnull; } - private: + nsresult BeginMediaChange(void); + nsresult EndMediaChange(void); + nsresult Delete(nsAReadableString & aOldMedium); + nsresult Append(nsAReadableString & aOldMedium); + nsCOMPtr mArray; + // not refcounted; sheet will let us know when it goes away + // mStyleSheet is the sheet that needs to be dirtied when this medialist + // changes CSSStyleSheetImpl* mStyleSheet; }; @@ -937,6 +951,7 @@ private: NS_INTERFACE_MAP_BEGIN(DOMMediaListImpl) NS_INTERFACE_MAP_ENTRY(nsIDOMMediaList) NS_INTERFACE_MAP_ENTRY(nsIMediaList) + NS_INTERFACE_MAP_ENTRY(nsISupportsArray) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMediaList) NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(MediaList) NS_INTERFACE_MAP_ENTRY(nsISerializable) @@ -962,13 +977,13 @@ DOMMediaListImpl::~DOMMediaListImpl() nsresult NS_NewMediaList(nsIMediaList** aInstancePtrResult) { - return NS_NewMediaList(aInstancePtrResult, NS_LITERAL_STRING("")); + return NS_NewMediaList(NS_LITERAL_STRING(""), aInstancePtrResult); } nsresult -NS_NewMediaList(nsIMediaList** aInstancePtrResult, const nsAReadableString& aMediaText) { +NS_NewMediaList(const nsAReadableString& aMediaText, nsIMediaList** aInstancePtrResult) { nsresult rv; - NS_ENSURE_ARG_POINTER(aInstancePtrResult); + NS_ASSERTION(aInstancePtrResult, "Null out param."); nsCOMPtr array; rv = NS_NewISupportsArray(getter_AddRefs(array)); @@ -976,15 +991,29 @@ NS_NewMediaList(nsIMediaList** aInstancePtrResult, const nsAReadableString& aMed return NS_ERROR_OUT_OF_MEMORY; } DOMMediaListImpl* medialist = new DOMMediaListImpl(array, nsnull); - NS_ENSURE_TRUE(medialist, NS_ERROR_OUT_OF_MEMORY); - rv = medialist->SetMediaText(aMediaText); - NS_ENSURE_SUCCESS(rv, rv); *aInstancePtrResult = medialist; + NS_ENSURE_TRUE(medialist, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(*aInstancePtrResult); + rv = medialist->SetMediaText(aMediaText); + if (NS_FAILED(rv)) { + NS_RELEASE(*aInstancePtrResult); + *aInstancePtrResult = nsnull; + } + return rv; +} + +nsresult NS_NewMediaList(nsISupportsArray* aArray, nsICSSStyleSheet* aSheet, nsIMediaList** aInstancePtrResult) +{ + NS_ASSERTION(aInstancePtrResult, "Null out param."); + DOMMediaListImpl* medialist = new DOMMediaListImpl(aArray, NS_STATIC_CAST(CSSStyleSheetImpl*, aSheet)); + *aInstancePtrResult = medialist; + NS_ENSURE_TRUE(medialist, NS_ERROR_OUT_OF_MEMORY); + NS_ADDREF(*aInstancePtrResult); + return NS_OK; } NS_IMETHODIMP -DOMMediaListImpl::GetMediaText(nsAWritableString& aMediaText) +DOMMediaListImpl::GetText(nsAWritableString& aMediaText) { aMediaText.Truncate(); @@ -995,10 +1024,8 @@ DOMMediaListImpl::GetMediaText(nsAWritableString& aMediaText) PRInt32 count = cnt, index = 0; while (index < count) { - nsCOMPtr tmp(dont_AddRef(ElementAt(index++))); - NS_ENSURE_TRUE(tmp, NS_ERROR_FAILURE); - - nsCOMPtr medium(do_QueryInterface(tmp)); + nsCOMPtr medium; + QueryElementAt(index++, NS_GET_IID(nsIAtom), getter_AddRefs(medium)); NS_ENSURE_TRUE(medium, NS_ERROR_FAILURE); const PRUnichar *buffer; @@ -1013,7 +1040,7 @@ DOMMediaListImpl::GetMediaText(nsAWritableString& aMediaText) } NS_IMETHODIMP -DOMMediaListImpl::SetMediaText(const nsAReadableString& aMediaText) +DOMMediaListImpl::SetText(const nsAReadableString& aMediaText) { nsresult rv = Clear(); NS_ENSURE_SUCCESS(rv, rv); @@ -1044,6 +1071,57 @@ DOMMediaListImpl::SetMediaText(const nsAReadableString& aMediaText) return rv; } +/* + * aMatch is true when we contain the desired medium or contain the + * "all" medium or contain no media at all, which is the same as + * containing "all" + */ +NS_IMETHODIMP +DOMMediaListImpl::MatchesMedium(nsIAtom* aMedium, PRBool* aMatch) +{ + NS_ENSURE_ARG_POINTER(aMatch); + *aMatch = PR_FALSE; + *aMatch = (-1 != IndexOf(aMedium)) || + (-1 != IndexOf(nsLayoutAtoms::all)); + if (*aMatch) + return NS_OK; + PRUint32 count; + nsresult rv = Count(&count); + if(NS_FAILED(rv)) + return rv; + *aMatch = (count == 0); + return NS_OK; +} + +NS_IMETHODIMP +DOMMediaListImpl::DropReference(void) +{ + mStyleSheet = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +DOMMediaListImpl::GetMediaText(nsAWritableString& aMediaText) +{ + return GetText(aMediaText); +} + +NS_IMETHODIMP +DOMMediaListImpl::SetMediaText(nsAReadableString& aMediaText) +{ + nsresult rv; + rv = BeginMediaChange(); + if (NS_FAILED(rv)) + return rv; + + rv = SetText(aMediaText); + if (NS_FAILED(rv)) + return rv; + + rv = EndMediaChange(); + return rv; +} + NS_IMETHODIMP DOMMediaListImpl::GetLength(PRUint32* aLength) { @@ -1079,6 +1157,38 @@ DOMMediaListImpl::Item(PRUint32 aIndex, nsAWritableString& aReturn) } NS_IMETHODIMP +DOMMediaListImpl::DeleteMedium(const nsAReadableString& aOldMedium) +{ + nsresult rv; + rv = BeginMediaChange(); + if (NS_FAILED(rv)) + return rv; + + rv = Delete(aOldMedium); + if (NS_FAILED(rv)) + return rv; + + rv = EndMediaChange(); + return rv; +} + +NS_IMETHODIMP +DOMMediaListImpl::AppendMedium(const nsAReadableString& aNewMedium) +{ + nsresult rv; + rv = BeginMediaChange(); + if (NS_FAILED(rv)) + return rv; + + rv = Append(aNewMedium); + if (NS_FAILED(rv)) + return rv; + + rv = EndMediaChange(); + return rv; +} + +nsresult DOMMediaListImpl::Delete(const nsAReadableString& aOldMedium) { if (!aOldMedium.Length()) @@ -1098,7 +1208,7 @@ DOMMediaListImpl::Delete(const nsAReadableString& aOldMedium) return NS_OK; } -NS_IMETHODIMP +nsresult DOMMediaListImpl::Append(const nsAReadableString& aNewMedium) { if (!aNewMedium.Length()) @@ -1118,6 +1228,39 @@ DOMMediaListImpl::Append(const nsAReadableString& aNewMedium) return NS_OK; } +nsresult +DOMMediaListImpl::BeginMediaChange(void) +{ + nsresult rv; + nsCOMPtr doc; + + if (mStyleSheet) { + rv = mStyleSheet->GetOwningDocument(*getter_AddRefs(doc)); + NS_ENSURE_SUCCESS(rv, rv); + rv = doc->BeginUpdate(); + NS_ENSURE_SUCCESS(rv, rv); + rv = mStyleSheet->WillDirty(); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; +} + +nsresult +DOMMediaListImpl::EndMediaChange(void) +{ + nsresult rv; + nsCOMPtr doc; + if (mStyleSheet) { + mStyleSheet->DidDirty(); + rv = mStyleSheet->GetOwningDocument(*getter_AddRefs(doc)); + NS_ENSURE_SUCCESS(rv, rv); + rv = doc->StyleRuleChanged(mStyleSheet, nsnull, NS_STYLE_HINT_RECONSTRUCT_ALL); + NS_ENSURE_SUCCESS(rv, rv); + rv = doc->EndUpdate(); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; +} // ------------------------------- // Imports Collection for the DOM @@ -1286,7 +1429,6 @@ CSSStyleSheetInner::~CSSStyleSheetInner(void) mOrderedRules->EnumerateForwards(SetStyleSheetReference, nsnull); NS_RELEASE(mOrderedRules); } - NS_IF_RELEASE(mNameSpace); } CSSStyleSheetInner* @@ -1326,7 +1468,7 @@ static PRBool CreateNameSpace(nsISupports* aRule, void* aNameSpacePtr) { nsICSSRule* rule = (nsICSSRule*)aRule; - PRInt32 type; + PRInt32 type = nsICSSRule::UNKNOWN_RULE; rule->GetType(type); if (nsICSSRule::NAMESPACE_RULE == type) { nsICSSNameSpaceRule* nameSpaceRule = (nsICSSNameSpaceRule*)rule; @@ -1355,27 +1497,26 @@ CreateNameSpace(nsISupports* aRule, void* aNameSpacePtr) void CSSStyleSheetInner::RebuildNameSpaces(void) { - nsINameSpaceManager* nameSpaceMgr; + nsCOMPtr nameSpaceMgr; if (mNameSpace) { - mNameSpace->GetNameSpaceManager(nameSpaceMgr); - NS_RELEASE(mNameSpace); + mNameSpace->GetNameSpaceManager(*getter_AddRefs(nameSpaceMgr)); } else { - NS_NewNameSpaceManager(&nameSpaceMgr); + NS_NewNameSpaceManager(getter_AddRefs(nameSpaceMgr)); } if (nameSpaceMgr) { - nameSpaceMgr->CreateRootNameSpace(mNameSpace); + nameSpaceMgr->CreateRootNameSpace(*getter_AddRefs(mNameSpace)); if (kNameSpaceID_Unknown != mDefaultNameSpaceID) { - nsINameSpace* defaultNameSpace; - mNameSpace->CreateChildNameSpace(nsnull, mDefaultNameSpaceID, defaultNameSpace); + nsCOMPtr defaultNameSpace; + mNameSpace->CreateChildNameSpace(nsnull, mDefaultNameSpaceID, + *getter_AddRefs(defaultNameSpace)); if (defaultNameSpace) { - NS_RELEASE(mNameSpace); mNameSpace = defaultNameSpace; } } - NS_RELEASE(nameSpaceMgr); if (mOrderedRules) { - mOrderedRules->EnumerateForwards(CreateNameSpace, &mNameSpace); + nsINameSpace* nameSpace = mNameSpace; + mOrderedRules->EnumerateForwards(CreateNameSpace, &nameSpace); } } } @@ -1745,24 +1886,15 @@ CSSStyleSheetImpl::GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const return NS_ERROR_INVALID_ARG; } -NS_IMETHODIMP +NS_IMETHODIMP_(PRBool) CSSStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const { if (mMedia) { - if (-1 != mMedia->IndexOf(aMedium)) { - return NS_OK; - } - if (-1 != mMedia->IndexOf(nsLayoutAtoms::all)) { - return NS_OK; - } - PRUint32 count; - mMedia->Count(&count); - if (count == 0) { // equivalent to having a medium of "all" - return NS_OK; - } - return NS_COMFALSE; + PRBool matches = PR_FALSE; + mMedia->MatchesMedium(aMedium, &matches); + return matches; } - return NS_OK; + return PR_TRUE; } @@ -1976,7 +2108,7 @@ CSSStyleSheetImpl::PrependStyleRule(nsICSSRule* aRule) aRule->SetStyleSheet(this); DidDirty(); - PRInt32 type; + PRInt32 type = nsICSSRule::UNKNOWN_RULE; aRule->GetType(type); if (nsICSSRule::NAMESPACE_RULE == type) { // no api to prepend a namespace (ugh), release old ones and re-create them all @@ -2003,31 +2135,29 @@ CSSStyleSheetImpl::AppendStyleRule(nsICSSRule* aRule) aRule->SetStyleSheet(this); DidDirty(); - PRInt32 type; + PRInt32 type = nsICSSRule::UNKNOWN_RULE; aRule->GetType(type); if (nsICSSRule::NAMESPACE_RULE == type) { if (! mInner->mNameSpace) { - nsINameSpaceManager* nameSpaceMgr; - NS_NewNameSpaceManager(&nameSpaceMgr); + nsCOMPtr nameSpaceMgr; + NS_NewNameSpaceManager(getter_AddRefs(nameSpaceMgr)); if (nameSpaceMgr) { - nameSpaceMgr->CreateRootNameSpace(mInner->mNameSpace); - NS_RELEASE(nameSpaceMgr); + nameSpaceMgr->CreateRootNameSpace(*getter_AddRefs(mInner->mNameSpace)); } } if (mInner->mNameSpace) { - nsICSSNameSpaceRule* nameSpaceRule = (nsICSSNameSpaceRule*)aRule; - nsINameSpace* newNameSpace = nsnull; + nsCOMPtr nameSpaceRule(do_QueryInterface(aRule)); + nsCOMPtr newNameSpace; - nsIAtom* prefix = nsnull; + nsCOMPtr prefix; nsAutoString urlSpec; - nameSpaceRule->GetPrefix(prefix); + nameSpaceRule->GetPrefix(*getter_AddRefs(prefix)); nameSpaceRule->GetURLSpec(urlSpec); - mInner->mNameSpace->CreateChildNameSpace(prefix, urlSpec, newNameSpace); - NS_IF_RELEASE(prefix); + mInner->mNameSpace->CreateChildNameSpace(prefix, urlSpec, + *getter_AddRefs(newNameSpace)); if (newNameSpace) { - NS_RELEASE(mInner->mNameSpace); - mInner->mNameSpace = newNameSpace; // takes ref + mInner->mNameSpace = newNameSpace; } } } else { @@ -2050,7 +2180,7 @@ CheckRuleForAttributesEnum(nsISupports *aRule, void *aData) NS_IMETHODIMP CSSStyleSheetImpl::CheckRuleForAttributes(nsICSSRule *aRule) { - PRInt32 ruleType; + PRInt32 ruleType = nsICSSRule::UNKNOWN_RULE; aRule->GetType(ruleType); switch (ruleType) { case nsICSSRule::MEDIA_RULE: { @@ -2124,8 +2254,13 @@ CSSStyleSheetImpl::GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const NS_IMETHODIMP CSSStyleSheetImpl::GetNameSpace(nsINameSpace*& aNameSpace) const { - aNameSpace = ((mInner) ? mInner->mNameSpace : nsnull); - NS_IF_ADDREF(aNameSpace); + if (mInner) { + aNameSpace = mInner->mNameSpace; + NS_IF_ADDREF(aNameSpace); + } + else { + aNameSpace = nsnull; + } return NS_OK; } @@ -2218,9 +2353,9 @@ ListRules(nsISupportsArray* aRules, FILE* aOut, PRInt32 aIndent) if (aRules) { aRules->Count(&count); for (index = 0; index < count; index++) { - nsICSSRule* rule = (nsICSSRule*)aRules->ElementAt(index); + nsCOMPtr rule; + aRules->QueryElementAt(index, NS_GET_IID(nsICSSRule), getter_AddRefs(rule)); rule->List(aOut, aIndent); - NS_RELEASE(rule); } } } @@ -2282,13 +2417,13 @@ void CSSStyleSheetImpl::List(FILE* out, PRInt32 aIndent) const mMedia->Count(&count); nsAutoString buffer; while (index < PRInt32(count)) { - nsIAtom* medium = (nsIAtom*)mMedia->ElementAt(index++); + nsCOMPtr medium; + mMedia->QueryElementAt(index++, NS_GET_IID(nsIAtom), getter_AddRefs(medium)); medium->ToString(buffer); fputs(buffer, out); if (index < PRInt32(count)) { fputs(", ", out); } - NS_RELEASE(medium); } } fputs("\n", out); @@ -2543,62 +2678,173 @@ CSSStyleSheetImpl::InsertRule(const nsAReadableString& aRule, PRUint32 aIndex, PRUint32* aReturn) { - nsICSSParser* css; - // XXX should get parser from CSS loader - nsresult result = NS_NewCSSParser(&css); - if (NS_OK == result) { - nsString* str = new nsString(aRule); // will be deleted by the input stream - nsIUnicharInputStream* input = nsnull; - result = NS_NewStringUnicharInputStream(&input, str); - if (NS_OK == result) { - nsICSSStyleSheet* tmp; - css->SetStyleSheet(this); - // XXX Currently, the parser will append the rule to the - // style sheet. We shouldn't ignore the index. - result = css->Parse(input, mInner->mURL, tmp); - NS_ASSERTION(tmp == this, "parser incorrectly created a new stylesheet"); - NS_RELEASE(tmp); - NS_RELEASE(input); - PRUint32 cnt; - if (mInner && mInner->mOrderedRules) { - result = mInner->mOrderedRules->Count(&cnt); - if (NS_SUCCEEDED(result)) { - *aReturn = cnt; - if (nsnull != mDocument) { - nsICSSRule* rule; + NS_ENSURE_TRUE(mInner, NS_ERROR_FAILURE); + nsresult result; + if (! mInner->mOrderedRules) { + result = NS_NewISupportsArray(&(mInner->mOrderedRules)); + } + if (NS_FAILED(result)) + return result; - rule = (nsICSSRule*)(mInner->mOrderedRules->ElementAt(aIndex)); - mDocument->StyleRuleAdded(this, rule); - NS_IF_RELEASE(rule); - } - } - } - } + PRUint32 count; + mInner->mOrderedRules->Count(&count); + if (aIndex > count) + return NS_ERROR_DOM_INDEX_SIZE_ERR; + + result = WillDirty(); + if (NS_FAILED(result)) + return result; - NS_RELEASE(css); + nsCOMPtr loader; + nsCOMPtr css; + nsCOMPtr htmlContainer(do_QueryInterface(mDocument)); + if (htmlContainer) { + htmlContainer->GetCSSLoader(*getter_AddRefs(loader)); + } + if (loader) { + result = loader->GetParserFor(this, getter_AddRefs(css)); + } + else { + result = NS_NewCSSParser(getter_AddRefs(css)); + css->SetStyleSheet(this); + } + if (NS_FAILED(result)) + return result; + + if (mDocument) { + result = mDocument->BeginUpdate(); + if (NS_FAILED(result)) + return result; } - return result; + nsCOMPtr rule; + result = css->ParseRule(aRule, mInner->mURL, getter_AddRefs(rule)); + if (NS_FAILED(result)) + return result; + if (! rule) // parsed successfully, but no rule resulted + return NS_ERROR_DOM_SYNTAX_ERR; + + nsCOMPtr cssRule(do_QueryInterface(rule, &result)); + NS_ENSURE_SUCCESS(result, result); + + PRInt32 type = nsICSSRule::UNKNOWN_RULE; + cssRule->GetType(type); + if (aIndex != 0) { + if (type == nsICSSRule::CHARSET_RULE) { // no inserting charset at nonzero position + return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; + } + + nsCOMPtr prevRule; + result = mInner->mOrderedRules->QueryElementAt(aIndex-1, NS_GET_IID(nsICSSRule), getter_AddRefs(prevRule)); + NS_ENSURE_SUCCESS(result, result); + PRInt32 prevType = nsICSSRule::UNKNOWN_RULE; + prevRule->GetType(prevType); + + if (type == nsICSSRule::IMPORT_RULE && + prevType != nsICSSRule::CHARSET_RULE && + prevType != nsICSSRule::IMPORT_RULE) { + return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; + } + + if (type == nsICSSRule::NAMESPACE_RULE && + prevType != nsICSSRule::CHARSET_RULE && + prevType != nsICSSRule::IMPORT_RULE && + prevType != nsICSSRule::NAMESPACE_RULE) { + return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; + } + } + + if (type == nsICSSRule::CHARSET_RULE) { + // check that we're not inserting before another chatset rule + nsCOMPtr nextRule; + mInner->mOrderedRules->QueryElementAt(aIndex, NS_GET_IID(nsICSSRule), getter_AddRefs(nextRule)); + if (nextRule) { + PRInt32 nextType = nsICSSRule::UNKNOWN_RULE; + nextRule->GetType(nextType); + if (nextType == nsICSSRule::CHARSET_RULE) { + return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; + } + } + } + + result = mInner->mOrderedRules->InsertElementAt(cssRule, aIndex); + NS_ENSURE_SUCCESS(result, result); + cssRule->SetStyleSheet(this); + DidDirty(); + if (type == nsICSSRule::NAMESPACE_RULE) { + if (! mInner->mNameSpace) { + nsCOMPtr nameSpaceMgr; + result = NS_NewNameSpaceManager(getter_AddRefs(nameSpaceMgr)); + if (NS_FAILED(result)) + return result; + nameSpaceMgr->CreateRootNameSpace(*getter_AddRefs(mInner->mNameSpace)); + } + + NS_ENSURE_TRUE(mInner->mNameSpace, NS_ERROR_FAILURE); + + nsCOMPtr nameSpaceRule(do_QueryInterface(cssRule)); + nsCOMPtr newNameSpace; + + nsCOMPtr prefix; + nsAutoString urlSpec; + nameSpaceRule->GetPrefix(*getter_AddRefs(prefix)); + nameSpaceRule->GetURLSpec(urlSpec); + mInner->mNameSpace->CreateChildNameSpace(prefix, urlSpec, + *getter_AddRefs(newNameSpace)); + if (newNameSpace) { + mInner->mNameSpace = newNameSpace; + } + } + else { + CheckRuleForAttributes(cssRule); + } + if (mDocument) { + result = mDocument->StyleRuleAdded(this, cssRule); + NS_ENSURE_SUCCESS(result, result); + + result = mDocument->EndUpdate(); + NS_ENSURE_SUCCESS(result, result); + } + + *aReturn = aIndex; + return NS_OK; } NS_IMETHODIMP CSSStyleSheetImpl::DeleteRule(PRUint32 aIndex) { - nsresult result = NS_ERROR_INVALID_ARG; + nsresult result = NS_ERROR_DOM_INDEX_SIZE_ERR; // XXX TBI: handle @rule types if (mInner && mInner->mOrderedRules) { + if (mDocument) { + result = mDocument->BeginUpdate(); + if (NS_FAILED(result)) + return result; + } result = WillDirty(); - - if (NS_SUCCEEDED(result)) { - nsICSSRule *rule; - rule = (nsICSSRule*)(mInner->mOrderedRules->ElementAt(aIndex)); - if (nsnull != rule) { + if (NS_SUCCEEDED(result)) { + PRUint32 count; + mInner->mOrderedRules->Count(&count); + if (aIndex >= count) + return NS_ERROR_DOM_INDEX_SIZE_ERR; + + nsCOMPtr rule; + mInner->mOrderedRules->QueryElementAt(aIndex, NS_GET_IID(nsICSSRule), + getter_AddRefs(rule)); + if (rule) { mInner->mOrderedRules->RemoveElementAt(aIndex); rule->SetStyleSheet(nsnull); DidDirty(); - NS_RELEASE(rule); + + if (mDocument) { + result = mDocument->StyleRuleRemoved(this, rule); + NS_ENSURE_SUCCESS(result, result); + + result = mDocument->EndUpdate(); + NS_ENSURE_SUCCESS(result, result); + } } } } @@ -2606,6 +2852,122 @@ CSSStyleSheetImpl::DeleteRule(PRUint32 aIndex) return result; } +NS_IMETHODIMP +CSSStyleSheetImpl::DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex) +{ + NS_ENSURE_ARG_POINTER(aGroup); + + nsresult result; + nsCOMPtr rule; + result = aGroup->GetStyleRuleAt(aIndex, *getter_AddRefs(rule)); + NS_ENSURE_SUCCESS(result, result); + + // check that the rule actually belongs to this sheet! + nsCOMPtr domRule(do_QueryInterface(rule)); + nsCOMPtr ruleSheet; + result = domRule->GetParentStyleSheet(getter_AddRefs(ruleSheet)); + NS_ENSURE_SUCCESS(result, result); + nsCOMPtr thisSheet; + this->QueryInterface(NS_GET_IID(nsIDOMCSSStyleSheet), getter_AddRefs(thisSheet)); + + if (thisSheet != ruleSheet) { + return NS_ERROR_INVALID_ARG; + } + + result = mDocument->BeginUpdate(); + NS_ENSURE_SUCCESS(result, result); + + result = WillDirty(); + NS_ENSURE_SUCCESS(result, result); + + result = aGroup->DeleteStyleRuleAt(aIndex); + NS_ENSURE_SUCCESS(result, result); + + rule->SetStyleSheet(nsnull); + + DidDirty(); + + result = mDocument->StyleRuleRemoved(this, rule); + NS_ENSURE_SUCCESS(result, result); + + result = mDocument->EndUpdate(); + NS_ENSURE_SUCCESS(result, result); + + return NS_OK; +} + +NS_IMETHODIMP +CSSStyleSheetImpl::InsertRuleIntoGroup(nsAReadableString & aRule, nsICSSGroupRule* aGroup, PRUint32 aIndex, PRUint32* _retval) +{ + nsresult result; + // check that the group actually belongs to this sheet! + nsCOMPtr domGroup(do_QueryInterface(aGroup)); + nsCOMPtr groupSheet; + result = domGroup->GetParentStyleSheet(getter_AddRefs(groupSheet)); + NS_ENSURE_SUCCESS(result, result); + nsCOMPtr thisSheet; + this->QueryInterface(NS_GET_IID(nsIDOMCSSStyleSheet), getter_AddRefs(thisSheet)); + + if (thisSheet != groupSheet) { + return NS_ERROR_INVALID_ARG; + } + + // get the css parser + nsCOMPtr loader; + nsCOMPtr css; + nsCOMPtr htmlContainer(do_QueryInterface(mDocument)); + if (htmlContainer) { + htmlContainer->GetCSSLoader(*getter_AddRefs(loader)); + } + if (loader) { + result = loader->GetParserFor(this, getter_AddRefs(css)); + } + else { + result = NS_NewCSSParser(getter_AddRefs(css)); + css->SetStyleSheet(this); + } + NS_ENSURE_SUCCESS(result, result); + + // parse and grab the rule + result = mDocument->BeginUpdate(); + NS_ENSURE_SUCCESS(result, result); + + result = WillDirty(); + NS_ENSURE_SUCCESS(result, result); + + nsCOMPtr rule; + result = css->ParseRule(aRule, mInner->mURL, getter_AddRefs(rule)); + NS_ENSURE_SUCCESS(result, result); + + if (! rule) { + return NS_ERROR_DOM_SYNTAX_ERR; + } + + nsCOMPtr cssRule(do_QueryInterface(rule, &result)); + NS_ENSURE_SUCCESS(result, result); + + // Only rulesets are allowed in a group as of CSS2 + PRInt32 type = nsICSSRule::UNKNOWN_RULE; + cssRule->GetType(type); + if (type != nsICSSRule::STYLE_RULE) { + return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; + } + + result = aGroup->InsertStyleRuleAt(aIndex, cssRule); + NS_ENSURE_SUCCESS(result, result); + DidDirty(); + CheckRuleForAttributes(cssRule); + + result = mDocument->StyleRuleAdded(this, cssRule); + NS_ENSURE_SUCCESS(result, result); + + result = mDocument->EndUpdate(); + NS_ENSURE_SUCCESS(result, result); + + *_retval = aIndex; + return NS_OK; +} + // XXX for backwards compatibility and convenience NS_HTML nsresult NS_NewCSSStyleSheet(nsICSSStyleSheet** aInstancePtrResult, nsIURI* aURL) @@ -3731,7 +4093,8 @@ void CSSRuleProcessor::SizeOf(nsISizeOfHandler *aSizeOfHandler, PRUint32 &aSize) PRUint32 sheetCount, curSheet, localSize2; mSheets->Count(&sheetCount); for(curSheet=0; curSheet < sheetCount; curSheet++){ - nsICSSStyleSheet *pSheet = (nsICSSStyleSheet *)mSheets->ElementAt(curSheet); + nsCOMPtr pSheet; + mSheets->QueryElementAt(curSheet, NS_GET_IID(nsICSSStyleSheet), getter_AddRefs(pSheet)); if(pSheet && uniqueItems->AddItem((void*)pSheet)){ pSheet->SizeOf(aSizeOfHandler, localSize2); // XXX aSize += localSize2; @@ -3765,6 +4128,7 @@ CSSRuleProcessor::ClearRuleCascades(void) delete data; data = next; } + mRuleCascades = nsnull; return NS_OK; } @@ -3835,7 +4199,7 @@ InsertRuleByWeight(nsISupports* aRule, void* aData) { nsICSSRule* rule = (nsICSSRule*)aRule; CascadeEnumData* data = (CascadeEnumData*)aData; - PRInt32 type; + PRInt32 type = nsICSSRule::UNKNOWN_RULE; rule->GetType(type); if (nsICSSRule::STYLE_RULE == type) { @@ -3854,7 +4218,7 @@ InsertRuleByWeight(nsISupports* aRule, void* aData) } else if (nsICSSRule::MEDIA_RULE == type) { nsICSSMediaRule* mediaRule = (nsICSSMediaRule*)rule; - if (NS_OK == mediaRule->UseForMedium(data->mMedium)) { + if (mediaRule->UseForMedium(data->mMedium)) { mediaRule->EnumerateRulesForwards(InsertRuleByWeight, aData); } } @@ -3871,7 +4235,7 @@ CSSRuleProcessor::CascadeSheetRulesInto(nsISupports* aSheet, void* aData) PRBool bSheetEnabled = PR_TRUE; sheet->GetEnabled(bSheetEnabled); - if ((bSheetEnabled) && (NS_OK == sheet->UseForMedium(data->mMedium))) { + if ((bSheetEnabled) && (sheet->UseForMedium(data->mMedium))) { CSSStyleSheetImpl* child = sheet->mFirstChild; while (child) { CascadeSheetRulesInto((nsICSSStyleSheet*)child, data); diff --git a/layout/style/nsHTMLCSSStyleSheet.cpp b/layout/style/nsHTMLCSSStyleSheet.cpp index 4e0283e6aeb..a7face8a5b7 100644 --- a/layout/style/nsHTMLCSSStyleSheet.cpp +++ b/layout/style/nsHTMLCSSStyleSheet.cpp @@ -210,7 +210,7 @@ public: NS_IMETHOD GetType(nsString& aType) const; NS_IMETHOD GetMediumCount(PRInt32& aCount) const; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const; - NS_IMETHOD UseForMedium(nsIAtom* aMedium) const; + NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const; NS_IMETHOD GetEnabled(PRBool& aEnabled) const; NS_IMETHOD SetEnabled(PRBool aEnabled); @@ -518,10 +518,10 @@ HTMLCSSStyleSheetImpl::GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const return NS_ERROR_INVALID_ARG; } -NS_IMETHODIMP +NS_IMETHODIMP_(PRBool) HTMLCSSStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const { - return NS_OK; // works for all media + return PR_TRUE; // works for all media } NS_IMETHODIMP diff --git a/layout/style/nsHTMLStyleSheet.cpp b/layout/style/nsHTMLStyleSheet.cpp index 7b4296a54c4..0fba8caff67 100644 --- a/layout/style/nsHTMLStyleSheet.cpp +++ b/layout/style/nsHTMLStyleSheet.cpp @@ -536,7 +536,7 @@ public: NS_IMETHOD GetType(nsString& aType) const; NS_IMETHOD GetMediumCount(PRInt32& aCount) const; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const; - NS_IMETHOD UseForMedium(nsIAtom* aMedium) const; + NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const; NS_IMETHOD GetEnabled(PRBool& aEnabled) const; NS_IMETHOD SetEnabled(PRBool aEnabled); @@ -952,10 +952,10 @@ HTMLStyleSheetImpl::GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const return NS_ERROR_INVALID_ARG; } -NS_IMETHODIMP +NS_IMETHODIMP_(PRBool) HTMLStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const { - return NS_OK; // works for all media + return PR_TRUE; // works for all media } diff --git a/layout/style/nsICSSGroupRule.h b/layout/style/nsICSSGroupRule.h index 53118d59b8b..b6d27c53cbb 100644 --- a/layout/style/nsICSSGroupRule.h +++ b/layout/style/nsICSSGroupRule.h @@ -42,6 +42,17 @@ public: NS_IMETHOD GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const = 0; NS_IMETHOD EnumerateRulesForwards(nsISupportsArrayEnumFunc aFunc, void * aData) const = 0; + + /* + * The next two methods (DeleteStyleRuleAt and InsertStyleRuleAt) + * should never be called unless you have first called WillDirty() + * on the parent stylesheet. After they are called, DidDirty() + * needs to be called on the sheet + */ + NS_IMETHOD DeleteStyleRuleAt(PRUint32 aIndex) = 0; + NS_IMETHOD InsertStyleRuleAt(PRUint32 aIndex, nsICSSRule* aRule) = 0; + + }; #endif /* nsICSSGroupRule_h___ */ diff --git a/layout/style/nsICSSParser.h b/layout/style/nsICSSParser.h index e7ff6cc1541..6839164714a 100644 --- a/layout/style/nsICSSParser.h +++ b/layout/style/nsICSSParser.h @@ -75,6 +75,10 @@ public: PRBool aParseOnlyOneDecl, PRInt32* aHint) = 0; + NS_IMETHOD ParseRule(nsAReadableString& aRule, + nsIURI* aBaseURL, + nsIStyleRule** aResult) = 0; + // Charset management method: // Set the charset before calling any of the Parse emthods if you want the // charset to be anything other than the default diff --git a/layout/style/nsICSSStyleSheet.h b/layout/style/nsICSSStyleSheet.h index 475b9b6aa8e..bc919bc196a 100644 --- a/layout/style/nsICSSStyleSheet.h +++ b/layout/style/nsICSSStyleSheet.h @@ -24,12 +24,14 @@ #include "nslayout.h" #include "nsIStyleSheet.h" +#include "nsString.h" class nsICSSRule; class nsIDOMNode; class nsINameSpace; class nsICSSStyleRuleProcessor; class nsIMediaList; +class nsICSSGroupRule; // IID for the nsICSSStyleSheet interface {8f83b0f0-b21a-11d1-8031-006008159b5a} #define NS_ICSS_STYLE_SHEET_IID \ @@ -50,6 +52,9 @@ public: NS_IMETHOD StyleRuleCount(PRInt32& aCount) const = 0; NS_IMETHOD GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const = 0; + NS_IMETHOD DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex) = 0; + NS_IMETHOD InsertRuleIntoGroup(nsAReadableString & aRule, nsICSSGroupRule* aGroup, PRUint32 aIndex, PRUint32* _retval) = 0; + NS_IMETHOD StyleSheetCount(PRInt32& aCount) const = 0; NS_IMETHOD GetStyleSheetAt(PRInt32 aIndex, nsICSSStyleSheet*& aSheet) const = 0; diff --git a/layout/style/nsIMediaList.h b/layout/style/nsIMediaList.h index 95076e732df..695c737beed 100644 --- a/layout/style/nsIMediaList.h +++ b/layout/style/nsIMediaList.h @@ -31,15 +31,25 @@ class nsIMediaList : public nsISupportsArray { public: static const nsIID& GetIID() { static nsIID iid = NS_IMEDIA_LIST_IID; return iid; } - NS_IMETHOD GetMediaText(nsAWritableString& aMediaText) = 0; - NS_IMETHOD SetMediaText(nsAReadableString& aMediaText) = 0; - + NS_IMETHOD GetText(nsAWritableString& aMediaText) = 0; + NS_IMETHOD SetText(nsAReadableString& aMediaText) = 0; + NS_IMETHOD MatchesMedium(nsIAtom* aMedium, PRBool* aMatch) = 0; + NS_IMETHOD DropReference(void) = 0; }; +/* Use this macro when declaring classes that implement this interface. */ +#define NS_DECL_NSIMEDIALIST \ + NS_IMETHOD GetText(nsAWritableString& aMediaText); \ + NS_IMETHOD SetText(nsAReadableString& aMediaText); \ + NS_IMETHOD MatchesMedium(nsIAtom* aMedium, PRBool* aMatch); \ + NS_IMETHOD DropReference(void); + extern NS_HTML nsresult -NS_NewMediaList(nsIMediaList** aInstancePtrResult, const nsAReadableString& aMediaText); +NS_NewMediaList(const nsAReadableString& aMediaText, nsIMediaList** aInstancePtrResult); extern NS_HTML nsresult NS_NewMediaList(nsIMediaList** aInstancePtrResult); +extern NS_HTML nsresult +NS_NewMediaList(nsISupportsArray* aArray, nsICSSStyleSheet* aSheet, nsIMediaList** aInstancePtrResult); #endif /* nsICSSLoader_h___ */ diff --git a/layout/style/nsIStyleSheet.h b/layout/style/nsIStyleSheet.h index a69e99ccd68..87c1ccf1806 100644 --- a/layout/style/nsIStyleSheet.h +++ b/layout/style/nsIStyleSheet.h @@ -52,7 +52,7 @@ public: NS_IMETHOD GetType(nsString& aType) const = 0; NS_IMETHOD GetMediumCount(PRInt32& aCount) const = 0; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const = 0; - NS_IMETHOD UseForMedium(nsIAtom* aMedium) const = 0; + NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const = 0; NS_IMETHOD GetEnabled(PRBool& aEnabled) const = 0; NS_IMETHOD SetEnabled(PRBool aEnabled) = 0;