Bug 1245751 - Part 1: Allow href without xlink on SVG <a> elements.
MozReview-Commit-ID: 6HwWv2Uxx5j
--- a/dom/base/Link.cpp
+++ b/dom/base/Link.cpp
@@ -40,20 +40,19 @@ Link::Link(Element *aElement)
Link::~Link()
{
UnregisterFromHistory();
}
bool
Link::ElementHasHref() const
{
- return ((!mElement->IsSVGElement() &&
- mElement->HasAttr(kNameSpaceID_None, nsGkAtoms::href))
- || (!mElement->IsHTMLElement() &&
- mElement->HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)));
+ return mElement->HasAttr(kNameSpaceID_None, nsGkAtoms::href) ||
+ (!mElement->IsHTMLElement() &&
+ mElement->HasAttr(kNameSpaceID_XLink, nsGkAtoms::href));
}
void
Link::TryDNSPrefetch()
{
MOZ_ASSERT(mElement->IsInComposedDoc());
if (ElementHasHref() && nsHTMLDNSPrefetch::IsAllowed(mElement->OwnerDoc())) {
nsHTMLDNSPrefetch::PrefetchLow(this);
--- a/dom/svg/SVGAElement.cpp
+++ b/dom/svg/SVGAElement.cpp
@@ -22,18 +22,19 @@ namespace mozilla {
namespace dom {
JSObject*
SVGAElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
{
return SVGAElementBinding::Wrap(aCx, this, aGivenProto);
}
-nsSVGElement::StringInfo SVGAElement::sStringInfo[2] =
+nsSVGElement::StringInfo SVGAElement::sStringInfo[3] =
{
+ { &nsGkAtoms::href, kNameSpaceID_None, true },
{ &nsGkAtoms::href, kNameSpaceID_XLink, true },
{ &nsGkAtoms::target, kNameSpaceID_None, true }
};
//----------------------------------------------------------------------
// nsISupports methods
@@ -69,17 +70,19 @@ SVGAElement::SVGAElement(already_AddRefe
SVGAElement::~SVGAElement()
{
}
already_AddRefed<SVGAnimatedString>
SVGAElement::Href()
{
- return mStringAttributes[HREF].ToDOMAnimatedString(this);
+ return mStringAttributes[HREF].IsExplicitlySet()
+ ? mStringAttributes[HREF].ToDOMAnimatedString(this)
+ : mStringAttributes[XLINK_HREF].ToDOMAnimatedString(this);
}
//----------------------------------------------------------------------
// nsINode methods
nsresult
SVGAElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
{
@@ -223,34 +226,38 @@ SVGAElement::IsLink(nsIURI** aURI) const
static nsIContent::AttrValuesArray sShowVals[] =
{ &nsGkAtoms::_empty, &nsGkAtoms::_new, &nsGkAtoms::replace, nullptr };
static nsIContent::AttrValuesArray sActuateVals[] =
{ &nsGkAtoms::_empty, &nsGkAtoms::onRequest, nullptr };
// Optimization: check for href first for early return
- const nsAttrValue* href = mAttrsAndChildren.GetAttr(nsGkAtoms::href,
- kNameSpaceID_XLink);
+ bool useXLink = !HasAttr(kNameSpaceID_None, nsGkAtoms::href);
+ const nsAttrValue* href =
+ useXLink
+ ? mAttrsAndChildren.GetAttr(nsGkAtoms::href, kNameSpaceID_XLink)
+ : mAttrsAndChildren.GetAttr(nsGkAtoms::href, kNameSpaceID_None);
+
if (href &&
FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::type,
sTypeVals, eCaseMatters) !=
nsIContent::ATTR_VALUE_NO_MATCH &&
FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::show,
sShowVals, eCaseMatters) !=
nsIContent::ATTR_VALUE_NO_MATCH &&
FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::actuate,
sActuateVals, eCaseMatters) !=
nsIContent::ATTR_VALUE_NO_MATCH) {
nsCOMPtr<nsIURI> baseURI = GetBaseURI();
// Get absolute URI
nsAutoString str;
- mStringAttributes[HREF].GetAnimValue(str, this);
- nsContentUtils::NewURIWithDocumentCharset(aURI, str,
- OwnerDoc(), baseURI);
+ const uint8_t idx = useXLink ? XLINK_HREF : HREF;
+ mStringAttributes[idx].GetAnimValue(str, this);
+ nsContentUtils::NewURIWithDocumentCharset(aURI, str, OwnerDoc(), baseURI);
// must promise out param is non-null if we return true
return !!*aURI;
}
*aURI = nullptr;
return false;
}
@@ -292,17 +299,19 @@ SVGAElement::SetAttr(int32_t aNameSpaceI
nsresult rv = SVGAElementBase::SetAttr(aNameSpaceID, aName, aPrefix,
aValue, aNotify);
// The ordering of the parent class's SetAttr call and Link::ResetLinkState
// is important here! The attribute is not set until SetAttr returns, and
// we will need the updated attribute value because notifying the document
// that content states have changed will call IntrinsicState, which will try
// to get updated information about the visitedness from Link.
- if (aName == nsGkAtoms::href && aNameSpaceID == kNameSpaceID_XLink) {
+ if (aName == nsGkAtoms::href &&
+ (aNameSpaceID == kNameSpaceID_XLink ||
+ aNameSpaceID == kNameSpaceID_None)) {
Link::ResetLinkState(!!aNotify, true);
}
return rv;
}
nsresult
SVGAElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttr,
@@ -310,18 +319,22 @@ SVGAElement::UnsetAttr(int32_t aNameSpac
{
nsresult rv = nsSVGElement::UnsetAttr(aNameSpaceID, aAttr, aNotify);
// The ordering of the parent class's UnsetAttr call and Link::ResetLinkState
// is important here! The attribute is not unset until UnsetAttr returns, and
// we will need the updated attribute value because notifying the document
// that content states have changed will call IntrinsicState, which will try
// to get updated information about the visitedness from Link.
- if (aAttr == nsGkAtoms::href && aNameSpaceID == kNameSpaceID_XLink) {
- Link::ResetLinkState(!!aNotify, false);
+ if (aAttr == nsGkAtoms::href &&
+ (aNameSpaceID == kNameSpaceID_XLink ||
+ aNameSpaceID == kNameSpaceID_None)) {
+ bool hasHref = HasAttr(kNameSpaceID_None, nsGkAtoms::href) ||
+ HasAttr(kNameSpaceID_XLink, nsGkAtoms::href);
+ Link::ResetLinkState(!!aNotify, hasHref);
}
return rv;
}
//----------------------------------------------------------------------
// nsSVGElement methods
--- a/dom/svg/SVGAElement.h
+++ b/dom/svg/SVGAElement.h
@@ -71,17 +71,17 @@ public:
void GetDownload(nsAString & aDownload);
void SetDownload(const nsAString & aDownload, ErrorResult& rv);
protected:
virtual ~SVGAElement();
virtual StringAttributesInfo GetStringInfo() override;
- enum { HREF, TARGET };
- nsSVGString mStringAttributes[2];
- static StringInfo sStringInfo[2];
+ enum { HREF, XLINK_HREF, TARGET };
+ nsSVGString mStringAttributes[3];
+ static StringInfo sStringInfo[3];
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_SVGAElement_h