Bug 783162: Make mapped attributes hold the image alive. r=bz

The nsCSSValue in nsGenericHTMLElement::MapBackgroundInto is a temporary.  This causes a problem after Bug 697230 landed, because the nsCSSValue::Image we put into that value is destroyed once we're done doing style stuff.  Previously the nsImageLoader would grab the request off the nsCSSValue::Image and hold it alive.  Bug 697230 changed the behavior here; now when the nsCSSValue::Image is destroyed it tells the image loader to drop the request.  The result is that all the references to the request are dropped and the frame is never told it has a background.

The solution is to keep the nsCSSValue::Image alive longer.  This patch adds two new types of nsAttrValue.  The first is an nsCSSValue::URL.  A ParseBackgroundAttribute method is added on nsGenericHTMLElement that the relevant elements (body/td/th/table/tr/tbody/thead/tfoot) call that parses background into an nsCSSValue::URL.  The second is an nsCSSValue::Image.  nsGenericHTMLElement::MapBackgroundInto attempts to convert the nsCSSValue::URL into an nsCSSValue::Image by kicking off the image load.  The result is that image loads are only started when the element is actually visible.  This also mirrors the way background-image works.  This also allows us to fix two longstanding bugs in this code.  Since MapBackgroundInto doesn't have a pointer to the actual element, it relied on grabbing the principal of the document.  Now we can grab the principal of the node in ParseBackgroundAttribute.  MapBackgroundInto also has no way to get at the element's base URI (to honor xml:base), which is now possible in ParseBackgroundAttribute.

nsCSSValue::[Image|URL] have also been moved to be mozilla::css::[Image|URL]Value.  nsAttrValue.h is included in external linkage code, so it can't include nsCSSValue.h to get the declarations of nsCSSValue::[Image|URL], and nested classes can't be forward declared.  Moving the classes to a namespace solves the problem.

Finally some old inoperative quirks mode code was removed.  This code has done nothing since Bug 273078 was landed in 2004.
This commit is contained in:
Kyle Huey 2012-08-24 10:50:49 -07:00
parent 583084b3a2
commit 1a68eab98d
26 changed files with 429 additions and 201 deletions

View File

@ -210,6 +210,16 @@ nsAttrValue::SetTo(const nsAttrValue& aOther)
NS_ADDREF(cont->mCSSStyleRule = otherCont->mCSSStyleRule);
break;
}
case eURL:
{
NS_ADDREF(cont->mURL = otherCont->mURL);
break;
}
case eImage:
{
NS_ADDREF(cont->mImage = otherCont->mImage);
break;
}
case eAtomArray:
{
if (!EnsureEmptyAtomArray() ||
@ -314,6 +324,17 @@ nsAttrValue::SetTo(css::StyleRule* aValue, const nsAString* aSerialized)
}
}
void
nsAttrValue::SetTo(css::URLValue* aValue, const nsAString* aSerialized)
{
if (EnsureEmptyMiscContainer()) {
MiscContainer* cont = GetMiscContainer();
NS_ADDREF(cont->mURL = aValue);
cont->mType = eURL;
SetMiscAtomOrString(aSerialized);
}
}
void
nsAttrValue::SetTo(const nsIntMargin& aValue)
{
@ -774,6 +795,15 @@ nsAttrValue::HashValue() const
{
return NS_PTR_TO_INT32(cont->mCSSStyleRule);
}
// Intentionally identical, so that loading the image does not change the
// hash code.
case eURL:
case eImage:
{
nsString str;
ToString(str);
return HashString(str);
}
case eAtomArray:
{
uint32_t hash = 0;
@ -870,6 +900,14 @@ nsAttrValue::Equals(const nsAttrValue& aOther) const
{
return thisCont->mCSSStyleRule == otherCont->mCSSStyleRule;
}
case eURL:
{
return thisCont->mURL == otherCont->mURL;
}
case eImage:
{
return thisCont->mImage == otherCont->mImage;
}
case eAtomArray:
{
// For classlists we could be insensitive to order, however
@ -1500,6 +1538,31 @@ nsAttrValue::ParseIntMarginValue(const nsAString& aString)
return false;
}
bool
nsAttrValue::LoadImage(nsIDocument* aDocument)
{
NS_ASSERTION(Type() == eURL, "wrong type");
nsString val;
ToString(val);
if (val.IsEmpty()) {
return false;
}
MiscContainer* cont = GetMiscContainer();
mozilla::css::URLValue* url = cont->mURL;
mozilla::css::ImageValue* image =
new css::ImageValue(url->GetURI(), url->mString, url->mReferrer,
url->mOriginPrincipal, aDocument);
NS_ADDREF(image);
cont->mImage = image;
NS_RELEASE(url);
cont->mType = eImage;
return true;
}
void
nsAttrValue::SetMiscAtomOrString(const nsAString* aValue)
{
@ -1576,6 +1639,16 @@ nsAttrValue::EnsureEmptyMiscContainer()
NS_RELEASE(cont->mCSSStyleRule);
break;
}
case eURL:
{
NS_RELEASE(cont->mURL);
break;
}
case eImage:
{
NS_RELEASE(cont->mImage);
break;
}
case eAtomArray:
{
delete cont->mAtomArray;

View File

@ -23,12 +23,15 @@
typedef PRUptrdiff PtrBits;
class nsAString;
class nsIAtom;
class nsIDocument;
template<class E, class A> class nsTArray;
struct nsTArrayDefaultAllocator;
namespace mozilla {
namespace css {
class StyleRule;
struct URLValue;
struct ImageValue;
}
}
@ -91,22 +94,24 @@ public:
// Values below here won't matter, they'll be always stored in the 'misc'
// struct.
eCSSStyleRule = 0x10
,eAtomArray = 0x11
,eDoubleValue = 0x12
,eIntMarginValue = 0x13
,eSVGTypesBegin = 0x14
,eURL = 0x11
,eImage = 0x12
,eAtomArray = 0x13
,eDoubleValue = 0x14
,eIntMarginValue = 0x15
,eSVGTypesBegin = 0x16
,eSVGAngle = eSVGTypesBegin
,eSVGIntegerPair = 0x15
,eSVGLength = 0x16
,eSVGLengthList = 0x17
,eSVGNumberList = 0x18
,eSVGNumberPair = 0x19
,eSVGPathData = 0x20
,eSVGPointList = 0x21
,eSVGPreserveAspectRatio = 0x22
,eSVGStringList = 0x23
,eSVGTransformList = 0x24
,eSVGViewBox = 0x25
,eSVGIntegerPair = 0x17
,eSVGLength = 0x18
,eSVGLengthList = 0x19
,eSVGNumberList = 0x20
,eSVGNumberPair = 0x21
,eSVGPathData = 0x22
,eSVGPointList = 0x23
,eSVGPreserveAspectRatio = 0x24
,eSVGStringList = 0x25
,eSVGTransformList = 0x26
,eSVGViewBox = 0x27
,eSVGTypesEnd = 0x34
};
@ -121,6 +126,7 @@ public:
void SetTo(int32_t aInt, const nsAString* aSerialized);
void SetTo(double aValue, const nsAString* aSerialized);
void SetTo(mozilla::css::StyleRule* aValue, const nsAString* aSerialized);
void SetTo(mozilla::css::URLValue* aValue, const nsAString* aSerialized);
void SetTo(const nsIntMargin& aValue);
void SetTo(const nsSVGAngle& aValue, const nsAString* aSerialized);
void SetTo(const nsSVGIntegerPair& aValue, const nsAString* aSerialized);
@ -169,6 +175,8 @@ public:
inline float GetPercentValue() const;
inline AtomArray* GetAtomArrayValue() const;
inline mozilla::css::StyleRule* GetCSSStyleRuleValue() const;
inline mozilla::css::URLValue* GetURLValue() const;
inline mozilla::css::ImageValue* GetImageValue() const;
inline double GetDoubleValue() const;
bool GetIntMarginValue(nsIntMargin& aMargin) const;
@ -342,6 +350,14 @@ public:
*/
bool ParseIntMarginValue(const nsAString& aString);
/**
* Convert a URL nsAttrValue to an Image nsAttrValue.
*
* @param aDocument the document this nsAttrValue belongs to.
* @return whether an image load was attempted
*/
bool LoadImage(nsIDocument* aDocument);
size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
private:
@ -367,6 +383,8 @@ private:
uint32_t mEnumValue;
int32_t mPercent;
mozilla::css::StyleRule* mCSSStyleRule;
mozilla::css::URLValue* mURL;
mozilla::css::ImageValue* mImage;
AtomArray* mAtomArray;
double mDoubleValue;
nsIntMargin* mIntMargin;
@ -495,6 +513,20 @@ nsAttrValue::GetCSSStyleRuleValue() const
return GetMiscContainer()->mCSSStyleRule;
}
inline mozilla::css::URLValue*
nsAttrValue::GetURLValue() const
{
NS_PRECONDITION(Type() == eURL, "wrong type");
return GetMiscContainer()->mURL;
}
inline mozilla::css::ImageValue*
nsAttrValue::GetImageValue() const
{
NS_PRECONDITION(Type() == eImage, "wrong type");
return GetMiscContainer()->mImage;
}
inline double
nsAttrValue::GetDoubleValue() const
{

View File

@ -2134,6 +2134,39 @@ nsGenericHTMLElement::ParseAttribute(int32_t aNamespaceID,
aValue, aResult);
}
bool
nsGenericHTMLElement::ParseBackgroundAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aNamespaceID == kNameSpaceID_None &&
aAttribute == nsGkAtoms::background) {
// Resolve url to an absolute url
nsIDocument* doc = OwnerDoc();
nsCOMPtr<nsIURI> baseURI = GetBaseURI();
nsCOMPtr<nsIURI> uri;
nsresult rv = nsContentUtils::NewURIWithDocumentCharset(
getter_AddRefs(uri), aValue, doc, baseURI);
if (NS_FAILED(rv)) {
return false;
}
nsString value(aValue);
nsRefPtr<nsStringBuffer> buffer = nsCSSValue::BufferFromString(value);
if (NS_UNLIKELY(!buffer)) {
return false;
}
mozilla::css::URLValue *url =
new mozilla::css::URLValue(buffer, baseURI, uri, NodePrincipal());
aResult.SetTo(url, &aValue);
return true;
}
return false;
}
bool
nsGenericHTMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const
{
@ -2739,45 +2772,16 @@ nsGenericHTMLElement::MapBackgroundInto(const nsMappedAttributes* aAttributes,
if (backImage->GetUnit() == eCSSUnit_Null &&
presContext->UseDocumentColors()) {
// background
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::background);
if (value && value->Type() == nsAttrValue::eString) {
const nsString& spec = value->GetStringValue();
if (!spec.IsEmpty()) {
// Resolve url to an absolute url
// XXX this breaks if the HTML element has an xml:base
// attribute (the xml:base will not be taken into account)
// as well as elements with _baseHref set. We need to be able
// to get to the element somehow, or store the base URI in the
// attributes.
nsIDocument* doc = presContext->Document();
nsCOMPtr<nsIURI> uri;
nsresult rv = nsContentUtils::NewURIWithDocumentCharset(
getter_AddRefs(uri), spec, doc, doc->GetDocBaseURI());
if (NS_SUCCEEDED(rv)) {
// Note that this should generally succeed here, due to the way
// |spec| is created. Maybe we should just add an nsStringBuffer
// accessor on nsAttrValue?
nsRefPtr<nsStringBuffer> buffer = nsCSSValue::BufferFromString(spec);
if (NS_LIKELY(buffer)) {
// XXXbz it would be nice to assert that doc->NodePrincipal() is
// the same as the principal of the node (which we'd need to store
// in the mapped attrs or something?)
nsCSSValue::Image *img =
new nsCSSValue::Image(uri, buffer, doc->GetDocumentURI(),
doc->NodePrincipal(), doc);
if (NS_LIKELY(img)) {
nsCSSValueList* list = backImage->SetListValue();
list->mValue.SetImageValue(img);
}
}
}
}
else if (presContext->CompatibilityMode() == eCompatibility_NavQuirks) {
// in NavQuirks mode, allow the empty string to set the
// background to empty
nsCSSValueList* list = backImage->SetListValue();
list->mValue.SetNoneValue();
}
nsAttrValue* value =
const_cast<nsAttrValue*>(aAttributes->GetAttr(nsGkAtoms::background));
// If the value is an image, or it is a URL and we attempted a load,
// put it in the style tree.
if (value &&
(value->Type() == nsAttrValue::eImage ||
(value->Type() == nsAttrValue::eURL &&
value->LoadImage(presContext->Document())))) {
nsCSSValueList* list = backImage->SetListValue();
list->mValue.SetImageValue(value->GetImageValue());
}
}
}

View File

@ -213,6 +213,11 @@ public:
}
virtual bool ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
bool ParseBackgroundAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);

View File

@ -83,9 +83,9 @@ public:
#undef EVENT
virtual bool ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
virtual void UnbindFromTree(bool aDeep = true,
bool aNullParent = true);
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
@ -324,7 +324,10 @@ nsHTMLBodyElement::ParseAttribute(int32_t aNamespaceID,
}
}
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
aAttribute, aValue,
aResult) ||
nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
aResult);
}

View File

@ -44,9 +44,9 @@ public:
NS_DECL_NSIDOMHTMLTABLECELLELEMENT
virtual bool ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
@ -285,7 +285,10 @@ nsHTMLTableCellElement::ParseAttribute(int32_t aNamespaceID,
}
}
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
aAttribute, aValue,
aResult) ||
nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
aResult);
}

View File

@ -910,7 +910,10 @@ nsHTMLTableElement::ParseAttribute(int32_t aNamespaceID,
}
}
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
aAttribute, aValue,
aResult) ||
nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
aResult);
}

View File

@ -352,7 +352,10 @@ nsHTMLTableRowElement::ParseAttribute(int32_t aNamespaceID,
}
}
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
aAttribute, aValue,
aResult) ||
nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
aResult);
}

View File

@ -43,9 +43,9 @@ public:
NS_DECL_NSIDOMHTMLTABLESECTIONELEMENT
virtual bool ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
@ -238,7 +238,10 @@ nsHTMLTableSectionElement::ParseAttribute(int32_t aNamespaceID,
}
}
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
aAttribute, aValue,
aResult) ||
nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
aResult);
}

View File

@ -7960,7 +7960,7 @@ IDBEventTargetSH::PreCreate(nsISupports *aNativeObj, JSContext *aCx,
static bool
GetBindingURL(Element *aElement, nsIDocument *aDocument,
nsCSSValue::URL **aResult)
mozilla::css::URLValue **aResult)
{
// If we have a frame the frame has already loaded the binding. And
// otherwise, don't do anything else here unless we're dealing with
@ -8024,7 +8024,7 @@ nsElementSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
return rv == NS_SUCCESS_ALLOW_SLIM_WRAPPERS ? NS_OK : rv;
}
nsCSSValue::URL *bindingURL;
mozilla::css::URLValue *bindingURL;
bool ok = GetBindingURL(element, doc, &bindingURL);
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
@ -8089,7 +8089,7 @@ nsElementSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// Make sure the style context goes away _before_ we load the binding
// since that can destroy the relevant presshell.
nsCSSValue::URL *bindingURL;
mozilla::css::URLValue *bindingURL;
bool ok = GetBindingURL(element, doc, &bindingURL);
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);

View File

@ -0,0 +1,2 @@
<body style="background-image: url('aqua-yellow-32x32.png')">
</body>

View File

@ -0,0 +1,2 @@
<body background="aqua-yellow-32x32.png">
</body>

View File

@ -0,0 +1,3 @@
<div style="background-image: url('aqua-yellow-32x32.png')">
Ohai
</div>

View File

@ -0,0 +1,3 @@
<div background="aqua-yellow-32x32.png">
Ohai
</div>

View File

@ -128,5 +128,8 @@ random-if(bug685516) HTTP == root-background-1.html root-background-ref.html
random-if(bug685516) HTTP != root-background-1.html about:blank
random-if(bug685516) == really-big-background.html really-big-background-ref.html
random-if(bug685516) == body-background.html body-background-ref.html
random-if(bug685516) == table-background.html table-background-ref.html
random-if(bug685516) != div-background.html div-background-ref.html
random-if(bug685516) == background-repeat-1-ref.html background-repeat-1.html

View File

@ -0,0 +1,39 @@
<body>
<table style="background-image: url('aqua-yellow-32x32.png')">
<thead style="background-image: url('blue-16x20-green-16x20.png')">
<tr>
<td>
Foo
</td>
<td style="background-image: url('yellow-32x32.png')">
Bar
</td>
</tr>
</thead>
<tbody style="background-image: url('red-32x32.png')">
<tr>
<th style="background-image: url('fuchsia-32x32.png')">
Foo
</th>
<th>
Bar
</th>
</tr>
<tr style="background-image: url('fuchsia-32x32.png')">
<td>
Foo
</td>
<td style="background-image: url('yellow-32x32.png')">
Bar
</td>
</tr>
</tbody>
<tfoot style="background-image: url('yellow-32x32.png')">
<tr>
<td>
Baz
</td>
</tr>
</tfoot>
</table>
</body>

View File

@ -0,0 +1,39 @@
<body>
<table background="aqua-yellow-32x32.png">
<thead background="blue-16x20-green-16x20.png">
<tr>
<td>
Foo
</td>
<td background="yellow-32x32.png">
Bar
</td>
</tr>
</thead>
<tbody background="red-32x32.png">
<tr>
<th background="fuchsia-32x32.png">
Foo
</th>
<th>
Bar
</th>
</tr>
<tr background="fuchsia-32x32.png">
<td>
Foo
</td>
<td background="yellow-32x32.png">
Bar
</td>
</tr>
</tbody>
<tfoot background="yellow-32x32.png">
<tr>
<td>
Baz
</td>
</tr>
</tfoot>
</table>
</body>

View File

@ -108,7 +108,7 @@ ImageLoader::AssociateRequestToFrame(imgIRequest* aRequest,
}
void
ImageLoader::MaybeRegisterCSSImage(nsCSSValue::Image* aImage)
ImageLoader::MaybeRegisterCSSImage(ImageLoader::Image* aImage)
{
NS_ASSERTION(aImage, "This should never be null!");
@ -139,7 +139,7 @@ ImageLoader::MaybeRegisterCSSImage(nsCSSValue::Image* aImage)
}
void
ImageLoader::DeregisterCSSImage(nsCSSValue::Image* aImage)
ImageLoader::DeregisterCSSImage(ImageLoader::Image* aImage)
{
RemoveImage(aImage);
}
@ -219,10 +219,10 @@ ImageLoader::SetAnimationMode(uint16_t aMode)
}
static PLDHashOperator
ClearImageHashSet(nsPtrHashKey<nsCSSValue::Image>* aKey, void* aClosure)
ClearImageHashSet(nsPtrHashKey<ImageLoader::Image>* aKey, void* aClosure)
{
nsIDocument* doc = static_cast<nsIDocument*>(aClosure);
nsCSSValue::Image* image = aKey->GetKey();
ImageLoader::Image* image = aKey->GetKey();
imgIRequest* request = image->mRequests.GetWeak(doc);
if (request) {
@ -244,7 +244,7 @@ ImageLoader::ClearAll()
void
ImageLoader::LoadImage(nsIURI* aURI, nsIPrincipal* aOriginPrincipal,
nsIURI* aReferrer, nsCSSValue::Image* aImage)
nsIURI* aReferrer, ImageLoader::Image* aImage)
{
NS_ASSERTION(aImage->mRequests.Count() == 0, "Huh?");
@ -284,7 +284,7 @@ ImageLoader::LoadImage(nsIURI* aURI, nsIPrincipal* aOriginPrincipal,
}
void
ImageLoader::AddImage(nsCSSValue::Image* aImage)
ImageLoader::AddImage(ImageLoader::Image* aImage)
{
NS_ASSERTION(!mImages.Contains(aImage), "Huh?");
if (!mImages.PutEntry(aImage)) {
@ -293,7 +293,7 @@ ImageLoader::AddImage(nsCSSValue::Image* aImage)
}
void
ImageLoader::RemoveImage(nsCSSValue::Image* aImage)
ImageLoader::RemoveImage(ImageLoader::Image* aImage)
{
NS_ASSERTION(mImages.Contains(aImage), "Huh?");
mImages.RemoveEntry(aImage);

View File

@ -26,6 +26,8 @@ namespace css {
class ImageLoader : public nsStubImageDecoderObserver,
public imgIOnloadBlocker {
public:
typedef mozilla::css::ImageValue Image;
ImageLoader(nsIDocument* aDocument)
: mDocument(aDocument),
mInClone(false)
@ -55,8 +57,8 @@ public:
void DropDocumentReference();
void MaybeRegisterCSSImage(nsCSSValue::Image* aImage);
void DeregisterCSSImage(nsCSSValue::Image* aImage);
void MaybeRegisterCSSImage(Image* aImage);
void DeregisterCSSImage(Image* aImage);
void AssociateRequestToFrame(imgIRequest* aRequest,
nsIFrame* aFrame);
@ -71,7 +73,7 @@ public:
void ClearAll();
void LoadImage(nsIURI* aURI, nsIPrincipal* aPrincipal, nsIURI* aReferrer,
nsCSSValue::Image* aCSSValue);
Image* aCSSValue);
void DestroyRequest(imgIRequest* aRequest);
@ -83,14 +85,14 @@ private:
typedef nsTArray<nsIFrame*> FrameSet;
typedef nsTArray<nsCOMPtr<imgIRequest> > RequestSet;
typedef nsTHashtable<nsPtrHashKey<nsCSSValue::Image> > ImageHashSet;
typedef nsTHashtable<nsPtrHashKey<Image> > ImageHashSet;
typedef nsClassHashtable<nsISupportsHashKey,
FrameSet> RequestToFrameMap;
typedef nsClassHashtable<nsPtrHashKey<nsIFrame>,
RequestSet> FrameToRequestMap;
void AddImage(nsCSSValue::Image* aCSSImage);
void RemoveImage(nsCSSValue::Image* aCSSImage);
void AddImage(Image* aCSSImage);
void RemoveImage(Image* aCSSImage);
nsPresContext* GetPresContext();

View File

@ -5041,8 +5041,8 @@ CSSParserImpl::SetValueToURL(nsCSSValue& aValue, const nsString& aURL)
nsRefPtr<nsStringBuffer> buffer(nsCSSValue::BufferFromString(aURL));
// Note: urlVal retains its own reference to |buffer|.
nsCSSValue::URL *urlVal =
new nsCSSValue::URL(buffer, mBaseURI, mSheetURI, mSheetPrincipal);
mozilla::css::URLValue *urlVal =
new mozilla::css::URLValue(buffer, mBaseURI, mSheetURI, mSheetPrincipal);
aValue.SetURLValue(urlVal);
return true;
}

View File

@ -73,14 +73,14 @@ nsCSSValue::nsCSSValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit)
mValue.mArray->AddRef();
}
nsCSSValue::nsCSSValue(nsCSSValue::URL* aValue)
nsCSSValue::nsCSSValue(mozilla::css::URLValue* aValue)
: mUnit(eCSSUnit_URL)
{
mValue.mURL = aValue;
mValue.mURL->AddRef();
}
nsCSSValue::nsCSSValue(nsCSSValue::Image* aValue)
nsCSSValue::nsCSSValue(mozilla::css::ImageValue* aValue)
: mUnit(eCSSUnit_Image)
{
mValue.mImage = aValue;
@ -364,7 +364,7 @@ void nsCSSValue::SetArrayValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit)
mValue.mArray->AddRef();
}
void nsCSSValue::SetURLValue(nsCSSValue::URL* aValue)
void nsCSSValue::SetURLValue(mozilla::css::URLValue* aValue)
{
Reset();
mUnit = eCSSUnit_URL;
@ -372,7 +372,7 @@ void nsCSSValue::SetURLValue(nsCSSValue::URL* aValue)
mValue.mURL->AddRef();
}
void nsCSSValue::SetImageValue(nsCSSValue::Image* aValue)
void nsCSSValue::SetImageValue(mozilla::css::ImageValue* aValue)
{
Reset();
mUnit = eCSSUnit_Image;
@ -563,12 +563,12 @@ void nsCSSValue::SetDummyInheritValue()
void nsCSSValue::StartImageLoad(nsIDocument* aDocument) const
{
NS_ABORT_IF_FALSE(eCSSUnit_URL == mUnit, "Not a URL value!");
nsCSSValue::Image* image =
new nsCSSValue::Image(mValue.mURL->GetURI(),
mValue.mURL->mString,
mValue.mURL->mReferrer,
mValue.mURL->mOriginPrincipal,
aDocument);
mozilla::css::ImageValue* image =
new mozilla::css::ImageValue(mValue.mURL->GetURI(),
mValue.mURL->mString,
mValue.mURL->mReferrer,
mValue.mURL->mOriginPrincipal,
aDocument);
if (image) {
nsCSSValue* writable = const_cast<nsCSSValue*>(this);
writable->SetImageValue(image);
@ -1600,8 +1600,8 @@ nsCSSValue::Array::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
return n;
}
nsCSSValue::URL::URL(nsIURI* aURI, nsStringBuffer* aString,
nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal)
css::URLValue::URLValue(nsIURI* aURI, nsStringBuffer* aString,
nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal)
: mURI(aURI),
mString(aString),
mReferrer(aReferrer),
@ -1612,8 +1612,8 @@ nsCSSValue::URL::URL(nsIURI* aURI, nsStringBuffer* aString,
mString->AddRef();
}
nsCSSValue::URL::URL(nsStringBuffer* aString, nsIURI* aBaseURI,
nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal)
css::URLValue::URLValue(nsStringBuffer* aString, nsIURI* aBaseURI,
nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal)
: mURI(aBaseURI),
mString(aString),
mReferrer(aReferrer),
@ -1624,17 +1624,17 @@ nsCSSValue::URL::URL(nsStringBuffer* aString, nsIURI* aBaseURI,
mString->AddRef();
}
nsCSSValue::URL::~URL()
css::URLValue::~URLValue()
{
mString->Release();
}
bool
nsCSSValue::URL::operator==(const URL& aOther) const
css::URLValue::operator==(const URLValue& aOther) const
{
bool eq;
return NS_strcmp(GetBufferValue(mString),
GetBufferValue(aOther.mString)) == 0 &&
return NS_strcmp(nsCSSValue::GetBufferValue(mString),
nsCSSValue::GetBufferValue(aOther.mString)) == 0 &&
(GetURI() == aOther.GetURI() || // handles null == null
(mURI && aOther.mURI &&
NS_SUCCEEDED(mURI->Equals(aOther.mURI, &eq)) &&
@ -1645,7 +1645,7 @@ nsCSSValue::URL::operator==(const URL& aOther) const
}
bool
nsCSSValue::URL::URIEquals(const URL& aOther) const
css::URLValue::URIEquals(const URLValue& aOther) const
{
NS_ABORT_IF_FALSE(mURIResolved && aOther.mURIResolved,
"How do you know the URIs aren't null?");
@ -1662,14 +1662,15 @@ nsCSSValue::URL::URIEquals(const URL& aOther) const
}
nsIURI*
nsCSSValue::URL::GetURI() const
css::URLValue::GetURI() const
{
if (!mURIResolved) {
mURIResolved = true;
// Be careful to not null out mURI before we've passed it as the base URI
nsCOMPtr<nsIURI> newURI;
NS_NewURI(getter_AddRefs(newURI),
NS_ConvertUTF16toUTF8(GetBufferValue(mString)), nullptr, mURI);
NS_ConvertUTF16toUTF8(nsCSSValue::GetBufferValue(mString)),
nullptr, mURI);
newURI.swap(mURI);
}
@ -1677,7 +1678,7 @@ nsCSSValue::URL::GetURI() const
}
size_t
nsCSSValue::URL::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
css::URLValue::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
{
size_t n = aMallocSizeOf(this);
@ -1694,10 +1695,10 @@ nsCSSValue::URL::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
}
nsCSSValue::Image::Image(nsIURI* aURI, nsStringBuffer* aString,
nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal,
nsIDocument* aDocument)
: URL(aURI, aString, aReferrer, aOriginPrincipal)
css::ImageValue::ImageValue(nsIURI* aURI, nsStringBuffer* aString,
nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal,
nsIDocument* aDocument)
: URLValue(aURI, aString, aReferrer, aOriginPrincipal)
{
if (aDocument->GetOriginalDocument()) {
aDocument = aDocument->GetOriginalDocument();
@ -1713,7 +1714,8 @@ static PLDHashOperator
ClearRequestHashtable(nsISupports* aKey, nsCOMPtr<imgIRequest>& aValue,
void* aClosure)
{
nsCSSValue::Image* image = static_cast<nsCSSValue::Image*>(aClosure);
mozilla::css::ImageValue* image =
static_cast<mozilla::css::ImageValue*>(aClosure);
nsIDocument* doc = static_cast<nsIDocument*>(aKey);
#ifdef DEBUG
@ -1734,7 +1736,7 @@ ClearRequestHashtable(nsISupports* aKey, nsCOMPtr<imgIRequest>& aValue,
return PL_DHASH_REMOVE;
}
nsCSSValue::Image::~Image()
css::ImageValue::~ImageValue()
{
mRequests.Enumerate(&ClearRequestHashtable, this);
}

View File

@ -61,6 +61,79 @@ class nsPtrHashKey;
} \
}
namespace mozilla {
namespace css {
struct URLValue {
// Methods are not inline because using an nsIPrincipal means requiring
// caps, which leads to REQUIRES hell, since this header is included all
// over.
// For both constructors aString must not be null.
// For both constructors aOriginPrincipal must not be null.
// Construct with a base URI; this will create the actual URI lazily from
// aString and aBaseURI.
URLValue(nsStringBuffer* aString, nsIURI* aBaseURI, nsIURI* aReferrer,
nsIPrincipal* aOriginPrincipal);
// Construct with the actual URI.
URLValue(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aReferrer,
nsIPrincipal* aOriginPrincipal);
~URLValue();
bool operator==(const URLValue& aOther) const;
// URIEquals only compares URIs and principals (unlike operator==, which
// also compares the original strings). URIEquals also assumes that the
// mURI member of both URL objects is non-null. Do NOT call this method
// unless you're sure this is the case.
bool URIEquals(const URLValue& aOther) const;
nsIURI* GetURI() const;
size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
private:
// If mURIResolved is false, mURI stores the base URI.
// If mURIResolved is true, mURI stores the URI we resolve to; this may be
// null if the URI is invalid.
mutable nsCOMPtr<nsIURI> mURI;
public:
nsStringBuffer* mString; // Could use nsRefPtr, but it'd add useless
// null-checks; this is never null.
nsCOMPtr<nsIURI> mReferrer;
nsCOMPtr<nsIPrincipal> mOriginPrincipal;
NS_INLINE_DECL_REFCOUNTING(URLValue)
private:
mutable bool mURIResolved;
URLValue(const URLValue& aOther) MOZ_DELETE;
URLValue& operator=(const URLValue& aOther) MOZ_DELETE;
};
struct ImageValue : public URLValue {
// Not making the constructor and destructor inline because that would
// force us to include imgIRequest.h, which leads to REQUIRES hell, since
// this header is included all over.
// aString must not be null.
ImageValue(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aReferrer,
nsIPrincipal* aOriginPrincipal, nsIDocument* aDocument);
~ImageValue();
// Inherit operator== from URLValue
nsInterfaceHashtable<nsISupportsHashKey, imgIRequest> mRequests;
// Override AddRef and Release to not only log ourselves correctly, but
// also so that we delete correctly without a virtual destructor
NS_INLINE_DECL_REFCOUNTING(ImageValue)
};
}
}
enum nsCSSUnit {
eCSSUnit_Null = 0, // (n/a) null unit, value is not specified
eCSSUnit_Auto = 1, // (n/a) value is algorithmic
@ -182,11 +255,9 @@ public:
struct Array;
friend struct Array;
struct URL;
friend struct URL;
friend struct mozilla::css::URLValue;
struct Image;
friend struct Image;
friend struct mozilla::css::ImageValue;
// for valueless units only (null, auto, inherit, none, all, normal)
explicit nsCSSValue(nsCSSUnit aUnit = eCSSUnit_Null)
@ -199,8 +270,8 @@ public:
nsCSSValue(float aValue, nsCSSUnit aUnit);
nsCSSValue(const nsString& aValue, nsCSSUnit aUnit);
nsCSSValue(Array* aArray, nsCSSUnit aUnit);
explicit nsCSSValue(URL* aValue);
explicit nsCSSValue(Image* aValue);
explicit nsCSSValue(mozilla::css::URLValue* aValue);
explicit nsCSSValue(mozilla::css::ImageValue* aValue);
explicit nsCSSValue(nsCSSValueGradient* aValue);
nsCSSValue(const nsCSSValue& aCopy);
~nsCSSValue() { Reset(); }
@ -349,7 +420,7 @@ public:
inline nsCSSValueTriplet& GetTripletValue();
inline const nsCSSValueTriplet& GetTripletValue() const;
URL* GetURLStructValue() const
mozilla::css::URLValue* GetURLStructValue() const
{
// Not allowing this for Image values, because if the caller takes
// a ref to them they won't be able to delete them properly.
@ -357,7 +428,7 @@ public:
return mValue.mURL;
}
Image* GetImageStructValue() const
mozilla::css::ImageValue* GetImageStructValue() const
{
NS_ABORT_IF_FALSE(mUnit == eCSSUnit_Image, "not an Image value");
return mValue.mImage;
@ -395,8 +466,8 @@ public:
void SetStringValue(const nsString& aValue, nsCSSUnit aUnit);
void SetColorValue(nscolor aValue);
void SetArrayValue(nsCSSValue::Array* aArray, nsCSSUnit aUnit);
void SetURLValue(nsCSSValue::URL* aURI);
void SetImageValue(nsCSSValue::Image* aImage);
void SetURLValue(mozilla::css::URLValue* aURI);
void SetImageValue(mozilla::css::ImageValue* aImage);
void SetGradientValue(nsCSSValueGradient* aGradient);
void SetPairValue(const nsCSSValuePair* aPair);
void SetPairValue(const nsCSSValue& xValue, const nsCSSValue& yValue);
@ -434,73 +505,6 @@ public:
size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
struct URL {
// Methods are not inline because using an nsIPrincipal means requiring
// caps, which leads to REQUIRES hell, since this header is included all
// over.
// For both constructors aString must not be null.
// For both constructors aOriginPrincipal must not be null.
// Construct with a base URI; this will create the actual URI lazily from
// aString and aBaseURI.
URL(nsStringBuffer* aString, nsIURI* aBaseURI, nsIURI* aReferrer,
nsIPrincipal* aOriginPrincipal);
// Construct with the actual URI.
URL(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aReferrer,
nsIPrincipal* aOriginPrincipal);
~URL();
bool operator==(const URL& aOther) const;
// URIEquals only compares URIs and principals (unlike operator==, which
// also compares the original strings). URIEquals also assumes that the
// mURI member of both URL objects is non-null. Do NOT call this method
// unless you're sure this is the case.
bool URIEquals(const URL& aOther) const;
nsIURI* GetURI() const;
size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
private:
// If mURIResolved is false, mURI stores the base URI.
// If mURIResolved is true, mURI stores the URI we resolve to; this may be
// null if the URI is invalid.
mutable nsCOMPtr<nsIURI> mURI;
public:
nsStringBuffer* mString; // Could use nsRefPtr, but it'd add useless
// null-checks; this is never null.
nsCOMPtr<nsIURI> mReferrer;
nsCOMPtr<nsIPrincipal> mOriginPrincipal;
NS_INLINE_DECL_REFCOUNTING(nsCSSValue::URL)
private:
mutable bool mURIResolved;
URL(const URL& aOther) MOZ_DELETE;
URL& operator=(const URL& aOther) MOZ_DELETE;
};
struct Image : public URL {
// Not making the constructor and destructor inline because that would
// force us to include imgIRequest.h, which leads to REQUIRES hell, since
// this header is included all over.
// aString must not be null.
Image(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aReferrer,
nsIPrincipal* aOriginPrincipal, nsIDocument* aDocument);
~Image();
// Inherit operator== from nsCSSValue::URL
nsInterfaceHashtable<nsISupportsHashKey, imgIRequest> mRequests;
// Override AddRef and Release to not only log ourselves correctly, but
// also so that we delete correctly without a virtual destructor
NS_INLINE_DECL_REFCOUNTING(nsCSSValue::Image)
};
private:
static const PRUnichar* GetBufferValue(nsStringBuffer* aBuffer) {
return static_cast<PRUnichar*>(aBuffer->Data());
@ -516,8 +520,8 @@ protected:
nsStringBuffer* mString;
nscolor mColor;
Array* mArray;
URL* mURL;
Image* mImage;
mozilla::css::URLValue* mURL;
mozilla::css::ImageValue* mImage;
nsCSSValueGradient* mGradient;
nsCSSValuePair_heap* mPair;
nsCSSRect_heap* mRect;

View File

@ -4658,7 +4658,7 @@ nsRuleNode::ComputeDisplayData(void* aStartStruct,
// binding: url, none, inherit
const nsCSSValue* bindingValue = aRuleData->ValueForBinding();
if (eCSSUnit_URL == bindingValue->GetUnit()) {
nsCSSValue::URL* url = bindingValue->GetURLStructValue();
mozilla::css::URLValue* url = bindingValue->GetURLStructValue();
NS_ASSERTION(url, "What's going on here?");
if (NS_LIKELY(url->GetURI())) {

View File

@ -3124,11 +3124,11 @@ nsStyleAnimation::ExtractComputedValue(nsCSSProperty aProperty,
GetURIAsUtf16StringBuffer(paint.mPaint.mPaintServer);
NS_ENSURE_TRUE(!!uriAsStringBuffer, false);
nsIDocument* doc = aStyleContext->PresContext()->Document();
nsRefPtr<nsCSSValue::URL> url =
new nsCSSValue::URL(paint.mPaint.mPaintServer,
uriAsStringBuffer,
doc->GetDocumentURI(),
doc->NodePrincipal());
nsRefPtr<mozilla::css::URLValue> url =
new mozilla::css::URLValue(paint.mPaint.mPaintServer,
uriAsStringBuffer,
doc->GetDocumentURI(),
doc->NodePrincipal());
pair->mXValue.SetURLValue(url);
pair->mYValue.SetColorValue(paint.mFallbackColor);
aComputedValue.SetAndAdoptCSSValuePairValue(pair.forget(),

View File

@ -51,7 +51,7 @@ static bool EqualURIs(nsIURI *aURI1, nsIURI *aURI2)
eq);
}
static bool EqualURIs(nsCSSValue::URL *aURI1, nsCSSValue::URL *aURI2)
static bool EqualURIs(mozilla::css::URLValue *aURI1, mozilla::css::URLValue *aURI2)
{
return aURI1 == aURI2 || // handle null==null, and optimize
(aURI1 && aURI2 && aURI1->URIEquals(*aURI2));

View File

@ -1556,7 +1556,7 @@ struct nsStyleDisplay {
// We guarantee that if mBinding is non-null, so are mBinding->GetURI() and
// mBinding->mOriginPrincipal.
nsRefPtr<nsCSSValue::URL> mBinding; // [reset]
nsRefPtr<mozilla::css::URLValue> mBinding; // [reset]
nsRect mClip; // [reset] offsets from upper-left border edge
float mOpacity; // [reset]
uint8_t mDisplay; // [reset] see nsStyleConsts.h NS_STYLE_DISPLAY_*