[Bug 901656] nsIRadioGroupContainer can use HTMLInputElement r=Ms2ger
authorDavid Zbarsky <dzbarsky@gmail.com>
Fri, 09 Aug 2013 21:17:51 -0400
changeset 142154 803d0a3d53072291cedea96ae7eecdd15143faee
parent 142153 cb152e57f23b30944a940f6381a7192df73153a6
child 142155 08a81efba1ec0a462567d8137413d58492ad7a7b
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersMs2ger
bugs901656
milestone26.0a1
[Bug 901656] nsIRadioGroupContainer can use HTMLInputElement r=Ms2ger
content/base/src/nsDocument.cpp
content/base/src/nsDocument.h
content/html/content/public/nsIRadioGroupContainer.h
content/html/content/src/HTMLFormElement.cpp
content/html/content/src/HTMLFormElement.h
content/html/content/src/HTMLInputElement.cpp
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -493,17 +493,17 @@ struct nsRadioGroupStruct
   nsRadioGroupStruct()
     : mRequiredRadioCount(0)
     , mGroupSuffersFromValueMissing(false)
   {}
 
   /**
    * A strong pointer to the currently selected radio button.
    */
-  nsCOMPtr<nsIDOMHTMLInputElement> mSelectedRadioButton;
+  nsRefPtr<HTMLInputElement> mSelectedRadioButton;
   nsCOMArray<nsIFormControl> mRadioButtons;
   uint32_t mRequiredRadioCount;
   bool mGroupSuffersFromValueMissing;
 };
 
 
 nsDOMStyleSheetList::nsDOMStyleSheetList(nsIDocument *aDocument)
 {
@@ -1665,17 +1665,17 @@ static PLDHashOperator
 RadioGroupsTraverser(const nsAString& aKey, nsRadioGroupStruct* aData,
                      void* aClosure)
 {
   nsCycleCollectionTraversalCallback *cb =
     static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
 
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
                                    "mRadioGroups entry->mSelectedRadioButton");
-  cb->NoteXPCOMChild(aData->mSelectedRadioButton);
+  cb->NoteXPCOMChild(ToSupports(aData->mSelectedRadioButton));
 
   uint32_t i, count = aData->mRadioButtons.Count();
   for (i = 0; i < count; ++i) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
                                        "mRadioGroups entry->mRadioButtons[i]");
     cb->NoteXPCOMChild(aData->mRadioButtons[i]);
   }
 
@@ -7267,78 +7267,76 @@ nsDocument::GetOrCreateRadioGroup(const 
   nsAutoPtr<nsRadioGroupStruct> newRadioGroup(new nsRadioGroupStruct());
   mRadioGroups.Put(tmKey, newRadioGroup);
 
   return newRadioGroup.forget();
 }
 
 void
 nsDocument::SetCurrentRadioButton(const nsAString& aName,
-                                  nsIDOMHTMLInputElement* aRadio)
+                                  HTMLInputElement* aRadio)
 {
   nsRadioGroupStruct* radioGroup = GetOrCreateRadioGroup(aName);
   radioGroup->mSelectedRadioButton = aRadio;
 }
 
-nsIDOMHTMLInputElement*
+HTMLInputElement*
 nsDocument::GetCurrentRadioButton(const nsAString& aName)
 {
   return GetOrCreateRadioGroup(aName)->mSelectedRadioButton;
 }
 
 NS_IMETHODIMP
 nsDocument::GetNextRadioButton(const nsAString& aName,
                                const bool aPrevious,
-                               nsIDOMHTMLInputElement*  aFocusedRadio,
-                               nsIDOMHTMLInputElement** aRadioOut)
+                               HTMLInputElement* aFocusedRadio,
+                               HTMLInputElement** aRadioOut)
 {
   // XXX Can we combine the HTML radio button method impls of
   //     nsDocument and nsHTMLFormControl?
   // XXX Why is HTML radio button stuff in nsDocument, as
   //     opposed to nsHTMLDocument?
   *aRadioOut = nullptr;
 
   nsRadioGroupStruct* radioGroup = GetOrCreateRadioGroup(aName);
 
   // Return the radio button relative to the focused radio button.
   // If no radio is focused, get the radio relative to the selected one.
-  nsCOMPtr<nsIDOMHTMLInputElement> currentRadio;
+  nsRefPtr<HTMLInputElement> currentRadio;
   if (aFocusedRadio) {
     currentRadio = aFocusedRadio;
   }
   else {
     currentRadio = radioGroup->mSelectedRadioButton;
     if (!currentRadio) {
       return NS_ERROR_FAILURE;
     }
   }
-  nsCOMPtr<nsIFormControl> radioControl(do_QueryInterface(currentRadio));
-  int32_t index = radioGroup->mRadioButtons.IndexOf(radioControl);
+  int32_t index = radioGroup->mRadioButtons.IndexOf(currentRadio);
   if (index < 0) {
     return NS_ERROR_FAILURE;
   }
 
   int32_t numRadios = radioGroup->mRadioButtons.Count();
-  bool disabled;
-  nsCOMPtr<nsIDOMHTMLInputElement> radio;
+  nsRefPtr<HTMLInputElement> radio;
   do {
     if (aPrevious) {
       if (--index < 0) {
         index = numRadios -1;
       }
     }
     else if (++index >= numRadios) {
       index = 0;
     }
-    radio = do_QueryInterface(radioGroup->mRadioButtons[index]);
-    NS_ASSERTION(radio, "mRadioButtons holding a non-radio button");
-    radio->GetDisabled(&disabled);
-  } while (disabled && radio != currentRadio);
-
-  NS_IF_ADDREF(*aRadioOut = radio);
+    NS_ASSERTION(static_cast<nsGenericHTMLFormElement*>(radioGroup->mRadioButtons[index])->IsHTML(nsGkAtoms::input),
+                 "mRadioButtons holding a non-radio button");
+    radio = static_cast<HTMLInputElement*>(radioGroup->mRadioButtons[index]);
+  } while (radio->Disabled() && radio != currentRadio);
+
+  radio.forget(aRadioOut);
   return NS_OK;
 }
 
 void
 nsDocument::AddToRadioGroup(const nsAString& aName,
                             nsIFormControl* aRadio)
 {
   nsRadioGroupStruct* radioGroup = GetOrCreateRadioGroup(aName);
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -721,23 +721,26 @@ public:
   {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   // nsIRadioGroupContainer
   NS_IMETHOD WalkRadioGroup(const nsAString& aName,
                             nsIRadioVisitor* aVisitor,
                             bool aFlushContent) MOZ_OVERRIDE;
-  virtual void SetCurrentRadioButton(const nsAString& aName,
-                                     nsIDOMHTMLInputElement* aRadio) MOZ_OVERRIDE;
-  virtual nsIDOMHTMLInputElement* GetCurrentRadioButton(const nsAString& aName) MOZ_OVERRIDE;
-  NS_IMETHOD GetNextRadioButton(const nsAString& aName,
-                                const bool aPrevious,
-                                nsIDOMHTMLInputElement*  aFocusedRadio,
-                                nsIDOMHTMLInputElement** aRadioOut) MOZ_OVERRIDE;
+  virtual void
+    SetCurrentRadioButton(const nsAString& aName,
+                          mozilla::dom::HTMLInputElement* aRadio) MOZ_OVERRIDE;
+  virtual mozilla::dom::HTMLInputElement*
+    GetCurrentRadioButton(const nsAString& aName) MOZ_OVERRIDE;
+  NS_IMETHOD
+    GetNextRadioButton(const nsAString& aName,
+                       const bool aPrevious,
+                       mozilla::dom::HTMLInputElement*  aFocusedRadio,
+                       mozilla::dom::HTMLInputElement** aRadioOut) MOZ_OVERRIDE;
   virtual void AddToRadioGroup(const nsAString& aName,
                                nsIFormControl* aRadio) MOZ_OVERRIDE;
   virtual void RemoveFromRadioGroup(const nsAString& aName,
                                     nsIFormControl* aRadio) MOZ_OVERRIDE;
   virtual uint32_t GetRequiredRadioCount(const nsAString& aName) const MOZ_OVERRIDE;
   virtual void RadioRequiredChanged(const nsAString& aName,
                                     nsIFormControl* aRadio) MOZ_OVERRIDE;
   virtual bool GetValueMissingState(const nsAString& aName) const MOZ_OVERRIDE;
--- a/content/html/content/public/nsIRadioGroupContainer.h
+++ b/content/html/content/public/nsIRadioGroupContainer.h
@@ -2,21 +2,26 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef nsIRadioGroupContainer_h___
 #define nsIRadioGroupContainer_h___
 
 #include "nsISupports.h"
 
-class nsIDOMHTMLInputElement;
 class nsString;
 class nsIRadioVisitor;
 class nsIFormControl;
 
+namespace mozilla {
+namespace dom {
+class HTMLInputElement;
+}
+}
+
 #define NS_IRADIOGROUPCONTAINER_IID   \
 { 0x22924a01, 0x4360, 0x401b, \
   { 0xb1, 0xd1, 0x56, 0x8d, 0xf5, 0xa3, 0xda, 0x71 } }
 
 /**
  * A container that has multiple radio groups in it, defined by name.
  */
 class nsIRadioGroupContainer : public nsISupports
@@ -36,37 +41,37 @@ public:
                             nsIRadioVisitor* aVisitor,
                             bool aFlushContent) = 0;
 
   /**
    * Set the current radio button in a group
    * @param aName the group name
    * @param aRadio the currently selected radio button
    */
-  virtual void SetCurrentRadioButton(const nsAString& aName, 
-                                     nsIDOMHTMLInputElement* aRadio) = 0;
+  virtual void SetCurrentRadioButton(const nsAString& aName,
+                                     mozilla::dom::HTMLInputElement* aRadio) = 0;
 
   /**
    * Get the current radio button in a group
    * @param aName the group name
    * @return the currently selected radio button
    */
-  virtual nsIDOMHTMLInputElement* GetCurrentRadioButton(const nsAString& aName) = 0;
+  virtual mozilla::dom::HTMLInputElement* GetCurrentRadioButton(const nsAString& aName) = 0;
 
   /**
    * Get the next/prev radio button in a group
    * @param aName the group name
    * @param aPrevious, true gets previous radio button, false gets next
    * @param aFocusedRadio the currently focused radio button
    * @param aRadio the currently selected radio button [OUT]
    */
   NS_IMETHOD GetNextRadioButton(const nsAString& aName,
                                 const bool aPrevious,
-                                nsIDOMHTMLInputElement*  aFocusedRadio,
-                                nsIDOMHTMLInputElement** aRadio) = 0;
+                                mozilla::dom::HTMLInputElement*  aFocusedRadio,
+                                mozilla::dom::HTMLInputElement** aRadio) = 0;
 
   /**
    * Add radio button to radio group
    *
    * Note that forms do not do anything for this method since they already
    * store radio groups on their own.
    *
    * @param aName radio group's name
--- a/content/html/content/src/HTMLFormElement.cpp
+++ b/content/html/content/src/HTMLFormElement.cpp
@@ -33,17 +33,16 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsNetUtil.h"
 #include "nsIWebProgress.h"
 #include "nsIDocShell.h"
 #include "nsFormData.h"
 #include "nsFormSubmissionConstants.h"
 
 // radio buttons
-#include "nsIDOMHTMLInputElement.h"
 #include "mozilla/dom/HTMLInputElement.h"
 #include "nsIRadioVisitor.h"
 
 #include "nsLayoutUtils.h"
 
 #include "nsEventDispatcher.h"
 
 #include "mozAutoDocUpdate.h"
@@ -281,23 +280,23 @@ HTMLFormElement::Init()
 
   return NS_OK;
 }
 
 
 // nsISupports
 
 static PLDHashOperator
-ElementTraverser(const nsAString& key, nsIDOMHTMLInputElement* element,
+ElementTraverser(const nsAString& key, HTMLInputElement* element,
                  void* userArg)
 {
-  nsCycleCollectionTraversalCallback *cb = 
+  nsCycleCollectionTraversalCallback *cb =
     static_cast<nsCycleCollectionTraversalCallback*>(userArg);
- 
-  cb->NoteXPCOMChild(element);
+
+  cb->NoteXPCOMChild(ToSupports(element));
   return PL_DHASH_NEXT;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLFormElement)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLFormElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControls)
@@ -2114,85 +2113,78 @@ NS_IMETHODIMP_(int32_t)
 HTMLFormElement::IndexOfControl(nsIFormControl* aControl)
 {
   int32_t index = 0;
   return mControls->IndexOfControl(aControl, &index) == NS_OK ? index : 0;
 }
 
 void
 HTMLFormElement::SetCurrentRadioButton(const nsAString& aName,
-                                       nsIDOMHTMLInputElement* aRadio)
+                                       HTMLInputElement* aRadio)
 {
   mSelectedRadioButtons.Put(aName, aRadio);
 }
 
-nsIDOMHTMLInputElement*
+HTMLInputElement*
 HTMLFormElement::GetCurrentRadioButton(const nsAString& aName)
 {
   return mSelectedRadioButtons.GetWeak(aName);
 }
 
 NS_IMETHODIMP
 HTMLFormElement::GetNextRadioButton(const nsAString& aName,
                                     const bool aPrevious,
-                                    nsIDOMHTMLInputElement*  aFocusedRadio,
-                                    nsIDOMHTMLInputElement** aRadioOut)
+                                    HTMLInputElement* aFocusedRadio,
+                                    HTMLInputElement** aRadioOut)
 {
   // Return the radio button relative to the focused radio button.
   // If no radio is focused, get the radio relative to the selected one.
   *aRadioOut = nullptr;
 
-  nsCOMPtr<nsIDOMHTMLInputElement> currentRadio;
+  nsRefPtr<HTMLInputElement> currentRadio;
   if (aFocusedRadio) {
     currentRadio = aFocusedRadio;
   }
   else {
     mSelectedRadioButtons.Get(aName, getter_AddRefs(currentRadio));
   }
 
   nsCOMPtr<nsISupports> itemWithName = DoResolveName(aName, true);
   nsCOMPtr<nsINodeList> radioGroup(do_QueryInterface(itemWithName));
 
   if (!radioGroup) {
     return NS_ERROR_FAILURE;
   }
 
-  nsCOMPtr<nsIContent> currentRadioNode(do_QueryInterface(currentRadio));
-  NS_ASSERTION(currentRadioNode, "No nsIContent for current radio button");
-  int32_t index = radioGroup->IndexOf(currentRadioNode);
+  int32_t index = radioGroup->IndexOf(currentRadio);
   if (index < 0) {
     return NS_ERROR_FAILURE;
   }
 
   uint32_t numRadios;
   radioGroup->GetLength(&numRadios);
-  bool disabled = true;
-  nsCOMPtr<nsIDOMHTMLInputElement> radio;
-  nsCOMPtr<nsIFormControl> formControl;
+  nsRefPtr<HTMLInputElement> radio;
 
   do {
     if (aPrevious) {
       if (--index < 0) {
         index = numRadios -1;
       }
     }
     else if (++index >= (int32_t)numRadios) {
       index = 0;
     }
-    radio = do_QueryInterface(radioGroup->Item(index));
+    radio = HTMLInputElement::FromContentOrNull(radioGroup->Item(index));
     if (!radio)
       continue;
 
-    // XXXbz why is this formControl check needed, exactly?
-    formControl = do_QueryInterface(radio);
-    if (!formControl || formControl->GetType() != NS_FORM_INPUT_RADIO)
+    if (radio->GetType() != NS_FORM_INPUT_RADIO)
       continue;
 
-    radio->GetDisabled(&disabled);
-  } while (disabled && radio != currentRadio);
+  } while (radio->Disabled() && radio != currentRadio);
 
   NS_IF_ADDREF(*aRadioOut = radio);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLFormElement::WalkRadioGroup(const nsAString& aName,
                                 nsIRadioVisitor* aVisitor,
--- a/content/html/content/src/HTMLFormElement.h
+++ b/content/html/content/src/HTMLFormElement.h
@@ -13,16 +13,17 @@
 #include "nsFormSubmission.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIWebProgressListener.h"
 #include "nsIRadioGroupContainer.h"
 #include "nsIWeakReferenceUtils.h"
 #include "nsThreadUtils.h"
 #include "nsInterfaceHashtable.h"
+#include "nsRefPtrHashtable.h"
 #include "nsDataHashtable.h"
 #include "nsAsyncDOMEvent.h"
 
 class nsIMutableArray;
 class nsIURI;
 
 namespace mozilla {
 namespace dom {
@@ -61,22 +62,22 @@ public:
   // nsIForm
   NS_IMETHOD_(nsIFormControl*) GetElementAt(int32_t aIndex) const;
   NS_IMETHOD_(uint32_t) GetElementCount() const MOZ_OVERRIDE;
   NS_IMETHOD_(int32_t) IndexOfControl(nsIFormControl* aControl) MOZ_OVERRIDE;
   NS_IMETHOD_(nsIFormControl*) GetDefaultSubmitElement() const MOZ_OVERRIDE;
 
   // nsIRadioGroupContainer
   void SetCurrentRadioButton(const nsAString& aName,
-                             nsIDOMHTMLInputElement* aRadio) MOZ_OVERRIDE;
-  nsIDOMHTMLInputElement* GetCurrentRadioButton(const nsAString& aName) MOZ_OVERRIDE;
+                             HTMLInputElement* aRadio) MOZ_OVERRIDE;
+  HTMLInputElement* GetCurrentRadioButton(const nsAString& aName) MOZ_OVERRIDE;
   NS_IMETHOD GetNextRadioButton(const nsAString& aName,
                                 const bool aPrevious,
-                                nsIDOMHTMLInputElement*  aFocusedRadio,
-                                nsIDOMHTMLInputElement** aRadioOut) MOZ_OVERRIDE;
+                                HTMLInputElement* aFocusedRadio,
+                                HTMLInputElement** aRadioOut) MOZ_OVERRIDE;
   NS_IMETHOD WalkRadioGroup(const nsAString& aName, nsIRadioVisitor* aVisitor,
                             bool aFlushContent) MOZ_OVERRIDE;
   void AddToRadioGroup(const nsAString& aName, nsIFormControl* aRadio) MOZ_OVERRIDE;
   void RemoveFromRadioGroup(const nsAString& aName, nsIFormControl* aRadio) MOZ_OVERRIDE;
   virtual uint32_t GetRequiredRadioCount(const nsAString& aName) const MOZ_OVERRIDE;
   virtual void RadioRequiredChanged(const nsAString& aName,
                                     nsIFormControl* aRadio) MOZ_OVERRIDE;
   virtual bool GetValueMissingState(const nsAString& aName) const MOZ_OVERRIDE;
@@ -533,17 +534,17 @@ public:
 protected:
 
   //
   // Data members
   //
   /** The list of controls (form.elements as well as stuff not in elements) */
   nsRefPtr<nsFormControlList> mControls;
   /** The currently selected radio button of each group */
-  nsInterfaceHashtable<nsStringCaseInsensitiveHashKey,nsIDOMHTMLInputElement> mSelectedRadioButtons;
+  nsRefPtrHashtable<nsStringCaseInsensitiveHashKey, HTMLInputElement> mSelectedRadioButtons;
   /** The number of required radio button of each group */
   nsDataHashtable<nsStringCaseInsensitiveHashKey,uint32_t> mRequiredRadioButtonCounts;
   /** The value missing state of each group */
   nsDataHashtable<nsStringCaseInsensitiveHashKey,bool> mValueMissingRadioGroups;
   /** Whether we are currently processing a submit event or not */
   bool mGeneratingSubmit;
   /** Whether we are currently processing a reset event or not */
   bool mGeneratingReset;
--- a/content/html/content/src/HTMLInputElement.cpp
+++ b/content/html/content/src/HTMLInputElement.cpp
@@ -3106,31 +3106,28 @@ HTMLInputElement::PostHandleEvent(nsEven
                 // FALLTHROUGH
               case NS_VK_DOWN:
               case NS_VK_RIGHT:
               // Arrow key pressed, focus+select prev/next radio button
               nsIRadioGroupContainer* container = GetRadioGroupContainer();
               if (container) {
                 nsAutoString name;
                 GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
-                nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton;
+                nsRefPtr<HTMLInputElement> selectedRadioButton;
                 container->GetNextRadioButton(name, isMovingBack, this,
                                               getter_AddRefs(selectedRadioButton));
-                nsCOMPtr<nsIContent> radioContent =
-                  do_QueryInterface(selectedRadioButton);
-                if (radioContent) {
-                  nsCOMPtr<nsIDOMHTMLElement> elem = do_QueryInterface(selectedRadioButton);
-                  rv = elem->Focus();
+                if (selectedRadioButton) {
+                  rv = selectedRadioButton->Focus();
                   if (NS_SUCCEEDED(rv)) {
                     nsEventStatus status = nsEventStatus_eIgnore;
                     nsMouseEvent event(aVisitor.mEvent->mFlags.mIsTrusted,
                                        NS_MOUSE_CLICK, nullptr,
                                        nsMouseEvent::eReal);
                     event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD;
-                    rv = nsEventDispatcher::Dispatch(radioContent,
+                    rv = nsEventDispatcher::Dispatch(ToSupports(selectedRadioButton),
                                                      aVisitor.mPresContext,
                                                      &event, nullptr, &status);
                     if (NS_SUCCEEDED(rv)) {
                       aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
                     }
                   }
                 }
               }
@@ -4970,18 +4967,17 @@ HTMLInputElement::IsHTMLFocusable(bool a
   if (!container) {
     *aIsFocusable = defaultFocusable;
     return false;
   }
 
   nsAutoString name;
   GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
 
-  nsCOMPtr<nsIDOMHTMLInputElement> currentRadio = container->GetCurrentRadioButton(name);
-  if (currentRadio) {
+  if (container->GetCurrentRadioButton(name)) {
     *aTabIndex = -1;
   }
   *aIsFocusable = defaultFocusable;
   return false;
 }
 
 nsresult
 HTMLInputElement::VisitGroup(nsIRadioVisitor* aVisitor, bool aFlushContent)