diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index baf238358272..ffaf03d00b6a 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -3445,8 +3445,15 @@ nsGenericHTMLElement::MapBackgroundAttributesInto(const nsIHTMLMappedAttributes* nsCOMPtr uri; rv = nsContentUtils::NewURIWithDocumentCharset( getter_AddRefs(uri), spec, doc, docURL); - if (NS_SUCCEEDED(rv)) - aData->mColorData->mBackImage.SetURLValue(uri); + if (NS_SUCCEEDED(rv)) { + nsCSSValue::URL *url = new nsCSSValue::URL(uri, spec.get()); + if (url) { + if (url->mString) + aData->mColorData->mBackImage.SetURLValue(url); + else + delete url; + } + } } } } diff --git a/content/html/style/src/nsCSSDeclaration.cpp b/content/html/style/src/nsCSSDeclaration.cpp index dd26f79903b5..514de5a009b7 100644 --- a/content/html/style/src/nsCSSDeclaration.cpp +++ b/content/html/style/src/nsCSSDeclaration.cpp @@ -405,10 +405,8 @@ PRBool nsCSSDeclaration::AppendCSSValueToString(nsCSSProperty aProperty, const n aResult.Append(PRUnichar(')')); } else if (eCSSUnit_URL == unit) { - nsCAutoString spec; - aValue.GetURLValue()->GetSpec(spec); aResult.Append(NS_LITERAL_STRING("url(") + - NS_ConvertUTF8toUCS2(spec) + + nsDependentString(aValue.GetOriginalURLValue()) + NS_LITERAL_STRING(")")); } else if (eCSSUnit_Percent == unit) { diff --git a/content/html/style/src/nsCSSParser.cpp b/content/html/style/src/nsCSSParser.cpp index 0bc3cf9cc5cb..5a3814c1e2e1 100644 --- a/content/html/style/src/nsCSSParser.cpp +++ b/content/html/style/src/nsCSSParser.cpp @@ -3612,12 +3612,17 @@ PRBool CSSParserImpl::ParseURL(PRInt32& aErrorCode, nsCSSValue& aValue) if ((eCSSToken_String == tk->mType) || (eCSSToken_URL == tk->mType)) { // Translate url into an absolute url if the url is relative to // the style sheet. - // XXX editors won't like this - too bad for now - nsCOMPtr url; - NS_NewURI(getter_AddRefs(url), tk->mIdent, nsnull, mURL); + nsCOMPtr uri; + NS_NewURI(getter_AddRefs(uri), tk->mIdent, nsnull, mURL); if (ExpectSymbol(aErrorCode, ')', PR_TRUE)) { // Set a null value on failure. Most failure cases should be // NS_ERROR_MALFORMED_URI. + nsCSSValue::URL *url = new nsCSSValue::URL(uri, tk->mIdent.get()); + if (!url || !url->mString) { + aErrorCode = NS_ERROR_OUT_OF_MEMORY; + delete url; + return PR_FALSE; + } aValue.SetURLValue(url); return PR_TRUE; } diff --git a/content/html/style/src/nsCSSValue.cpp b/content/html/style/src/nsCSSValue.cpp index fc2d28c4cf42..e09481fc88d7 100644 --- a/content/html/style/src/nsCSSValue.cpp +++ b/content/html/style/src/nsCSSValue.cpp @@ -90,11 +90,11 @@ nsCSSValue::nsCSSValue(nscolor aValue) mValue.mColor = aValue; } -nsCSSValue::nsCSSValue(nsIURI* aValue) +nsCSSValue::nsCSSValue(nsCSSValue::URL* aValue) : mUnit(eCSSUnit_URL) { mValue.mURL = aValue; - NS_IF_ADDREF(aValue); + mValue.mURL->AddRef(); } nsCSSValue::nsCSSValue(const nsCSSValue& aCopy) @@ -116,7 +116,7 @@ nsCSSValue::nsCSSValue(const nsCSSValue& aCopy) } else if (eCSSUnit_URL == mUnit){ mValue.mURL = aCopy.mValue.mURL; - NS_IF_ADDREF(mValue.mURL); + mValue.mURL->AddRef(); } else { mValue.mFloat = aCopy.mValue.mFloat; @@ -140,7 +140,7 @@ nsCSSValue& nsCSSValue::operator=(const nsCSSValue& aCopy) } else if (eCSSUnit_URL == mUnit){ mValue.mURL = aCopy.mValue.mURL; - NS_IF_ADDREF(mValue.mURL); + mValue.mURL->AddRef(); } else { mValue.mFloat = aCopy.mValue.mFloat; @@ -168,11 +168,7 @@ PRBool nsCSSValue::operator==(const nsCSSValue& aOther) const return mValue.mColor == aOther.mValue.mColor; } else if (eCSSUnit_URL == mUnit) { - PRBool eq; - return (mValue.mURL == aOther.mValue.mURL || // handles null == null - (mValue.mURL && aOther.mValue.mURL && - NS_SUCCEEDED(mValue.mURL->Equals(aOther.mValue.mURL, &eq)) && - eq)); + return *mValue.mURL == *aOther.mValue.mURL; } else { return mValue.mFloat == aOther.mValue.mFloat; @@ -211,12 +207,12 @@ void nsCSSValue::SetColorValue(nscolor aValue) mValue.mColor = aValue; } -void nsCSSValue::SetURLValue(nsIURI* aValue) +void nsCSSValue::SetURLValue(nsCSSValue::URL* aValue) { Reset(); mUnit = eCSSUnit_URL; mValue.mURL = aValue; - NS_IF_ADDREF(mValue.mURL); + mValue.mURL->AddRef(); } void nsCSSValue::SetAutoValue(void) @@ -319,13 +315,7 @@ void nsCSSValue::AppendToString(nsAString& aBuffer, aBuffer.Append(PRUnichar(')')); } else if (eCSSUnit_URL == mUnit) { - if (mValue.mURL) { - nsCAutoString spec; - mValue.mURL->GetSpec(spec); - AppendUTF8toUTF16(spec, aBuffer); - } else { - aBuffer.Append(NS_LITERAL_STRING("url(invalid-url:)")); - } + aBuffer.Append(mValue.mURL->mString); } else if (eCSSUnit_Percent == mUnit) { nsAutoString floatString; diff --git a/content/html/style/src/nsCSSValue.h b/content/html/style/src/nsCSSValue.h index 3f730eab873c..1006ed30dd0a 100644 --- a/content/html/style/src/nsCSSValue.h +++ b/content/html/style/src/nsCSSValue.h @@ -45,6 +45,7 @@ #include "nsCSSProperty.h" #include "nsUnitConversion.h" #include "nsIURI.h" +#include "nsCOMPtr.h" enum nsCSSUnit { eCSSUnit_Null = 0, // (n/a) null unit, value is not specified @@ -57,7 +58,7 @@ enum nsCSSUnit { eCSSUnit_Attr = 11, // (PRUnichar*) a attr(string) value eCSSUnit_Counter = 12, // (PRUnichar*) a counter(string,[string]) value eCSSUnit_Counters = 13, // (PRUnichar*) a counters(string,string[,string]) value - eCSSUnit_URL = 14, // (nsIURI*) a URL value (null == invalid URI) + eCSSUnit_URL = 14, // (nsCSSValue::URL*) value eCSSUnit_Integer = 50, // (int) simple value eCSSUnit_Enumerated = 51, // (int) value has enumerated meaning eCSSUnit_Color = 80, // (color) an RGBA value @@ -114,6 +115,9 @@ enum nsCSSUnit { class nsCSSValue { public: + struct URL; + friend struct URL; + // for valueless units only (null, auto, inherit, none, normal) nsCSSValue(nsCSSUnit aUnit = eCSSUnit_Null) : mUnit(aUnit) @@ -129,7 +133,7 @@ public: nsCSSValue(float aValue, nsCSSUnit aUnit); nsCSSValue(const nsAString& aValue, nsCSSUnit aUnit); nsCSSValue(nscolor aValue); - nsCSSValue(nsIURI* aValue); + nsCSSValue(nsCSSValue::URL* aValue); nsCSSValue(const nsCSSValue& aCopy); ~nsCSSValue(void) { @@ -205,7 +209,13 @@ public: nsIURI* GetURLValue(void) const { NS_ASSERTION(mUnit == eCSSUnit_URL, "not a URL value"); - return mValue.mURL; + return mValue.mURL->mURI; + } + + const PRUnichar* GetOriginalURLValue(void) const + { + NS_ASSERTION(mUnit == eCSSUnit_URL, "not a URL value"); + return mValue.mURL->mString; } @@ -253,7 +263,7 @@ public: (nsnull != mValue.mString)) { nsCRT::free(mValue.mString); } else if (eCSSUnit_URL == mUnit) { - NS_IF_RELEASE(mValue.mURL); + mValue.mURL->Release(); } mUnit = eCSSUnit_Null; mValue.mInt = 0; @@ -279,7 +289,7 @@ public: void SetStringValue(const nsAString& aValue, nsCSSUnit aUnit); void SetColorValue(nscolor aValue); - void SetURLValue(nsIURI* aURI); + void SetURLValue(nsCSSValue::URL* aURI); void SetAutoValue(void); void SetInheritValue(void); void SetInitialValue(void); @@ -291,6 +301,47 @@ public: void AppendToString(nsAString& aBuffer, nsCSSProperty aPropID = eCSSProperty_UNKNOWN) const; void ToString(nsAString& aBuffer, nsCSSProperty aPropID = eCSSProperty_UNKNOWN) const; + MOZ_DECL_CTOR_COUNTER(nsCSSValue::URL) + + struct URL { + // Caller must delete this object immediately if the allocation of + // |mString| fails. + URL(nsIURI* aURI, const PRUnichar* aString) + : mURI(aURI), + mString(nsCRT::strdup(aString)), + mRefCnt(0) + { + MOZ_COUNT_CTOR(nsCSSValue::URL); + } + + ~URL() + { + // null |mString| isn't valid normally, but is checked by callers + // of the constructor + if (mString) + nsCRT::free(mString); + MOZ_COUNT_DTOR(nsCSSValue::URL); + } + + PRBool operator==(const URL& aOther) + { + PRBool eq; + return nsCRT::strcmp(mString, aOther.mString) == 0 && + (mURI == aOther.mURI || // handles null == null + (mURI && aOther.mURI && + NS_SUCCEEDED(mURI->Equals(aOther.mURI, &eq)) && + eq)); + } + + nsCOMPtr mURI; // null == invalid URL + PRUnichar* mString; + + void AddRef() { ++mRefCnt; } + void Release() { if (--mRefCnt == 0) delete this; } + private: + nsrefcnt mRefCnt; + }; + protected: nsCSSUnit mUnit; union { @@ -298,7 +349,7 @@ protected: float mFloat; PRUnichar* mString; nscolor mColor; - nsIURI* mURL; + URL* mURL; } mValue; }; diff --git a/layout/style/nsCSSDeclaration.cpp b/layout/style/nsCSSDeclaration.cpp index dd26f79903b5..514de5a009b7 100644 --- a/layout/style/nsCSSDeclaration.cpp +++ b/layout/style/nsCSSDeclaration.cpp @@ -405,10 +405,8 @@ PRBool nsCSSDeclaration::AppendCSSValueToString(nsCSSProperty aProperty, const n aResult.Append(PRUnichar(')')); } else if (eCSSUnit_URL == unit) { - nsCAutoString spec; - aValue.GetURLValue()->GetSpec(spec); aResult.Append(NS_LITERAL_STRING("url(") + - NS_ConvertUTF8toUCS2(spec) + + nsDependentString(aValue.GetOriginalURLValue()) + NS_LITERAL_STRING(")")); } else if (eCSSUnit_Percent == unit) { diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 0bc3cf9cc5cb..5a3814c1e2e1 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -3612,12 +3612,17 @@ PRBool CSSParserImpl::ParseURL(PRInt32& aErrorCode, nsCSSValue& aValue) if ((eCSSToken_String == tk->mType) || (eCSSToken_URL == tk->mType)) { // Translate url into an absolute url if the url is relative to // the style sheet. - // XXX editors won't like this - too bad for now - nsCOMPtr url; - NS_NewURI(getter_AddRefs(url), tk->mIdent, nsnull, mURL); + nsCOMPtr uri; + NS_NewURI(getter_AddRefs(uri), tk->mIdent, nsnull, mURL); if (ExpectSymbol(aErrorCode, ')', PR_TRUE)) { // Set a null value on failure. Most failure cases should be // NS_ERROR_MALFORMED_URI. + nsCSSValue::URL *url = new nsCSSValue::URL(uri, tk->mIdent.get()); + if (!url || !url->mString) { + aErrorCode = NS_ERROR_OUT_OF_MEMORY; + delete url; + return PR_FALSE; + } aValue.SetURLValue(url); return PR_TRUE; } diff --git a/layout/style/nsCSSValue.cpp b/layout/style/nsCSSValue.cpp index fc2d28c4cf42..e09481fc88d7 100644 --- a/layout/style/nsCSSValue.cpp +++ b/layout/style/nsCSSValue.cpp @@ -90,11 +90,11 @@ nsCSSValue::nsCSSValue(nscolor aValue) mValue.mColor = aValue; } -nsCSSValue::nsCSSValue(nsIURI* aValue) +nsCSSValue::nsCSSValue(nsCSSValue::URL* aValue) : mUnit(eCSSUnit_URL) { mValue.mURL = aValue; - NS_IF_ADDREF(aValue); + mValue.mURL->AddRef(); } nsCSSValue::nsCSSValue(const nsCSSValue& aCopy) @@ -116,7 +116,7 @@ nsCSSValue::nsCSSValue(const nsCSSValue& aCopy) } else if (eCSSUnit_URL == mUnit){ mValue.mURL = aCopy.mValue.mURL; - NS_IF_ADDREF(mValue.mURL); + mValue.mURL->AddRef(); } else { mValue.mFloat = aCopy.mValue.mFloat; @@ -140,7 +140,7 @@ nsCSSValue& nsCSSValue::operator=(const nsCSSValue& aCopy) } else if (eCSSUnit_URL == mUnit){ mValue.mURL = aCopy.mValue.mURL; - NS_IF_ADDREF(mValue.mURL); + mValue.mURL->AddRef(); } else { mValue.mFloat = aCopy.mValue.mFloat; @@ -168,11 +168,7 @@ PRBool nsCSSValue::operator==(const nsCSSValue& aOther) const return mValue.mColor == aOther.mValue.mColor; } else if (eCSSUnit_URL == mUnit) { - PRBool eq; - return (mValue.mURL == aOther.mValue.mURL || // handles null == null - (mValue.mURL && aOther.mValue.mURL && - NS_SUCCEEDED(mValue.mURL->Equals(aOther.mValue.mURL, &eq)) && - eq)); + return *mValue.mURL == *aOther.mValue.mURL; } else { return mValue.mFloat == aOther.mValue.mFloat; @@ -211,12 +207,12 @@ void nsCSSValue::SetColorValue(nscolor aValue) mValue.mColor = aValue; } -void nsCSSValue::SetURLValue(nsIURI* aValue) +void nsCSSValue::SetURLValue(nsCSSValue::URL* aValue) { Reset(); mUnit = eCSSUnit_URL; mValue.mURL = aValue; - NS_IF_ADDREF(mValue.mURL); + mValue.mURL->AddRef(); } void nsCSSValue::SetAutoValue(void) @@ -319,13 +315,7 @@ void nsCSSValue::AppendToString(nsAString& aBuffer, aBuffer.Append(PRUnichar(')')); } else if (eCSSUnit_URL == mUnit) { - if (mValue.mURL) { - nsCAutoString spec; - mValue.mURL->GetSpec(spec); - AppendUTF8toUTF16(spec, aBuffer); - } else { - aBuffer.Append(NS_LITERAL_STRING("url(invalid-url:)")); - } + aBuffer.Append(mValue.mURL->mString); } else if (eCSSUnit_Percent == mUnit) { nsAutoString floatString; diff --git a/layout/style/nsCSSValue.h b/layout/style/nsCSSValue.h index 3f730eab873c..1006ed30dd0a 100644 --- a/layout/style/nsCSSValue.h +++ b/layout/style/nsCSSValue.h @@ -45,6 +45,7 @@ #include "nsCSSProperty.h" #include "nsUnitConversion.h" #include "nsIURI.h" +#include "nsCOMPtr.h" enum nsCSSUnit { eCSSUnit_Null = 0, // (n/a) null unit, value is not specified @@ -57,7 +58,7 @@ enum nsCSSUnit { eCSSUnit_Attr = 11, // (PRUnichar*) a attr(string) value eCSSUnit_Counter = 12, // (PRUnichar*) a counter(string,[string]) value eCSSUnit_Counters = 13, // (PRUnichar*) a counters(string,string[,string]) value - eCSSUnit_URL = 14, // (nsIURI*) a URL value (null == invalid URI) + eCSSUnit_URL = 14, // (nsCSSValue::URL*) value eCSSUnit_Integer = 50, // (int) simple value eCSSUnit_Enumerated = 51, // (int) value has enumerated meaning eCSSUnit_Color = 80, // (color) an RGBA value @@ -114,6 +115,9 @@ enum nsCSSUnit { class nsCSSValue { public: + struct URL; + friend struct URL; + // for valueless units only (null, auto, inherit, none, normal) nsCSSValue(nsCSSUnit aUnit = eCSSUnit_Null) : mUnit(aUnit) @@ -129,7 +133,7 @@ public: nsCSSValue(float aValue, nsCSSUnit aUnit); nsCSSValue(const nsAString& aValue, nsCSSUnit aUnit); nsCSSValue(nscolor aValue); - nsCSSValue(nsIURI* aValue); + nsCSSValue(nsCSSValue::URL* aValue); nsCSSValue(const nsCSSValue& aCopy); ~nsCSSValue(void) { @@ -205,7 +209,13 @@ public: nsIURI* GetURLValue(void) const { NS_ASSERTION(mUnit == eCSSUnit_URL, "not a URL value"); - return mValue.mURL; + return mValue.mURL->mURI; + } + + const PRUnichar* GetOriginalURLValue(void) const + { + NS_ASSERTION(mUnit == eCSSUnit_URL, "not a URL value"); + return mValue.mURL->mString; } @@ -253,7 +263,7 @@ public: (nsnull != mValue.mString)) { nsCRT::free(mValue.mString); } else if (eCSSUnit_URL == mUnit) { - NS_IF_RELEASE(mValue.mURL); + mValue.mURL->Release(); } mUnit = eCSSUnit_Null; mValue.mInt = 0; @@ -279,7 +289,7 @@ public: void SetStringValue(const nsAString& aValue, nsCSSUnit aUnit); void SetColorValue(nscolor aValue); - void SetURLValue(nsIURI* aURI); + void SetURLValue(nsCSSValue::URL* aURI); void SetAutoValue(void); void SetInheritValue(void); void SetInitialValue(void); @@ -291,6 +301,47 @@ public: void AppendToString(nsAString& aBuffer, nsCSSProperty aPropID = eCSSProperty_UNKNOWN) const; void ToString(nsAString& aBuffer, nsCSSProperty aPropID = eCSSProperty_UNKNOWN) const; + MOZ_DECL_CTOR_COUNTER(nsCSSValue::URL) + + struct URL { + // Caller must delete this object immediately if the allocation of + // |mString| fails. + URL(nsIURI* aURI, const PRUnichar* aString) + : mURI(aURI), + mString(nsCRT::strdup(aString)), + mRefCnt(0) + { + MOZ_COUNT_CTOR(nsCSSValue::URL); + } + + ~URL() + { + // null |mString| isn't valid normally, but is checked by callers + // of the constructor + if (mString) + nsCRT::free(mString); + MOZ_COUNT_DTOR(nsCSSValue::URL); + } + + PRBool operator==(const URL& aOther) + { + PRBool eq; + return nsCRT::strcmp(mString, aOther.mString) == 0 && + (mURI == aOther.mURI || // handles null == null + (mURI && aOther.mURI && + NS_SUCCEEDED(mURI->Equals(aOther.mURI, &eq)) && + eq)); + } + + nsCOMPtr mURI; // null == invalid URL + PRUnichar* mString; + + void AddRef() { ++mRefCnt; } + void Release() { if (--mRefCnt == 0) delete this; } + private: + nsrefcnt mRefCnt; + }; + protected: nsCSSUnit mUnit; union { @@ -298,7 +349,7 @@ protected: float mFloat; PRUnichar* mString; nscolor mColor; - nsIURI* mURL; + URL* mURL; } mValue; };