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;
};