Bug 461199 (Part 10) - Ensure that Link::ResetLinkState is always called when an element is bound or unbound from the DOM tree.
authorShawn Wilsher <sdwilsh@shawnwilsher.com>
Mon, 23 Nov 2009 10:48:52 -0800
changeset 38469 8e4fb9ef39c787a23225ff1a1ef4cd7ecb4217db
parent 38468 74f08c7a58cc172d46589267226796b00bb9be40
child 38470 d013cef514a14d1893e83913cf9ce9e15c43773d
push idunknown
push userunknown
push dateunknown
bugs461199
milestone1.9.3a2pre
Bug 461199 (Part 10) - Ensure that Link::ResetLinkState is always called when an element is bound or unbound from the DOM tree. We would not be notified about base URI changes during this time, so we need to make sure we are not registered and have no cached state. r=bz r=jwatt
content/html/content/src/nsHTMLAnchorElement.cpp
content/html/content/src/nsHTMLAreaElement.cpp
content/html/content/src/nsHTMLLinkElement.cpp
content/svg/content/src/nsSVGAElement.cpp
content/svg/content/src/nsSVGAElement.h
--- a/content/html/content/src/nsHTMLAnchorElement.cpp
+++ b/content/html/content/src/nsHTMLAnchorElement.cpp
@@ -193,16 +193,18 @@ nsHTMLAnchorElement::GetDraggable(PRBool
   return nsGenericHTMLElement::GetDraggable(aDraggable);
 }
 
 nsresult
 nsHTMLAnchorElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                                 nsIContent* aBindingParent,
                                 PRBool aCompileEventHandlers)
 {
+  Link::ResetLinkState();
+
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
                                                  aBindingParent,
                                                  aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDocument) {
     RegUnRegAccessKey(PR_TRUE);
   }
@@ -212,19 +214,22 @@ nsHTMLAnchorElement::BindToTree(nsIDocum
     nsHTMLDNSPrefetch::PrefetchLow(this);
   }
   return rv;
 }
 
 void
 nsHTMLAnchorElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
 {
+  // If this link is ever reinserted into a document, it might
+  // be under a different xml:base, so forget the cached state now.
+  Link::ResetLinkState();
+
   if (IsInDoc()) {
     RegUnRegAccessKey(PR_FALSE);
-    Link::ResetLinkState();
   }
 
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
 }
 
 NS_IMETHODIMP
 nsHTMLAnchorElement::Blur()
 {
--- a/content/html/content/src/nsHTMLAreaElement.cpp
+++ b/content/html/content/src/nsHTMLAreaElement.cpp
@@ -199,36 +199,39 @@ nsHTMLAreaElement::GetLinkTarget(nsAStri
   }
 }
 
 nsresult
 nsHTMLAreaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers)
 {
+  Link::ResetLinkState();
+
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
                                                  aBindingParent,
                                                  aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDocument) {
     RegUnRegAccessKey(PR_TRUE);
   }
 
   return rv;
 }
 
 void
 nsHTMLAreaElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
 {
+  // If this link is ever reinserted into a document, it might
+  // be under a different xml:base, so forget the cached state now.
+  Link::ResetLinkState();
+
   if (IsInDoc()) {
     RegUnRegAccessKey(PR_FALSE);
-    // If this link is ever reinserted into a document, it might
-    // be under a different xml:base, so forget the cached state now
-    Link::ResetLinkState();
   }
 
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
 }
 
 nsresult
 nsHTMLAreaElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
--- a/content/html/content/src/nsHTMLLinkElement.cpp
+++ b/content/html/content/src/nsHTMLLinkElement.cpp
@@ -198,28 +198,30 @@ NS_IMPL_STRING_ATTR(nsHTMLLinkElement, R
 NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Target, target)
 NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Type, type)
 
 nsresult
 nsHTMLLinkElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers)
 {
+  Link::ResetLinkState();
+
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
                                                  aBindingParent,
                                                  aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsContentUtils::AddScriptRunner(
     new nsRunnableMethod<nsHTMLLinkElement>(this,
                                             &nsHTMLLinkElement::UpdateStyleSheetInternal));
 
   CreateAndDispatchEvent(aDocument, NS_LITERAL_STRING("DOMLinkAdded"));
 
-  return rv;  
+  return rv;
 }
 
 NS_IMETHODIMP
 nsHTMLLinkElement::LinkAdded()
 {
   CreateAndDispatchEvent(GetOwnerDoc(), NS_LITERAL_STRING("DOMLinkAdded"));
   return NS_OK;
 }
@@ -229,16 +231,18 @@ nsHTMLLinkElement::LinkRemoved()
 {
   CreateAndDispatchEvent(GetOwnerDoc(), NS_LITERAL_STRING("DOMLinkRemoved"));
   return NS_OK;
 }
 
 void
 nsHTMLLinkElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
 {
+  // If this link is ever reinserted into a document, it might
+  // be under a different xml:base, so forget the cached state now.
   Link::ResetLinkState();
 
   // Once we have XPCOMGC we shouldn't need to call UnbindFromTree during Unlink
   // and so this messy event dispatch can go away.
   nsCOMPtr<nsIDocument> oldDoc = GetCurrentDoc();
   CreateAndDispatchEvent(oldDoc, NS_LITERAL_STRING("DOMLinkRemoved"));
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
   UpdateStyleSheetInternal(oldDoc);
--- a/content/svg/content/src/nsSVGAElement.cpp
+++ b/content/svg/content/src/nsSVGAElement.cpp
@@ -116,16 +116,41 @@ nsSVGAElement::GetTarget(nsIDOMSVGAnimat
 {
   return mStringAttributes[TARGET].ToDOMAnimatedString(aTarget, this);
 }
 
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
+nsresult
+nsSVGAElement::BindToTree(nsIDocument *aDocument, nsIContent *aParent,
+                          nsIContent *aBindingParent,
+                          PRBool aCompileEventHandlers)
+{
+  Link::ResetLinkState();
+
+  nsresult rv = nsSVGAElementBase::BindToTree(aDocument, aParent,
+                                              aBindingParent,
+                                              aCompileEventHandlers);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
+void
+nsSVGAElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
+{
+  // If this link is ever reinserted into a document, it might
+  // be under a different xml:base, so forget the cached state now.
+  Link::ResetLinkState();
+
+  nsSVGAElementBase::UnbindFromTree(aDeep, aNullParent);
+}
+
 nsLinkState
 nsSVGAElement::GetLinkState() const
 {
   return Link::GetLinkState();
 }
 
 void
 nsSVGAElement::SetLinkState(nsLinkState aState)
--- a/content/svg/content/src/nsSVGAElement.h
+++ b/content/svg/content/src/nsSVGAElement.h
@@ -73,16 +73,21 @@ public:
   virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   // nsILink
   NS_IMETHOD LinkAdded() { return NS_OK; }
   NS_IMETHOD LinkRemoved() { return NS_OK; }
 
   // nsIContent
+  virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
+                              nsIContent *aBindingParent,
+                              PRBool aCompileEventHandlers);
+  virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
+                              PRBool aNullParent = PR_TRUE);
   virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
   virtual PRBool IsLink(nsIURI** aURI) const;
   virtual void GetLinkTarget(nsAString& aTarget);
   virtual nsLinkState GetLinkState() const;
   virtual void SetLinkState(nsLinkState aState);
   virtual already_AddRefed<nsIURI> GetHrefURI() const;
 
 protected: