diff --git a/content/html/content/public/nsIForm.h b/content/html/content/public/nsIForm.h
index e525219b61f2..6ca7f6c73f90 100644
--- a/content/html/content/public/nsIForm.h
+++ b/content/html/content/public/nsIForm.h
@@ -43,7 +43,6 @@
class nsIFormControl;
class nsISimpleEnumerator;
class nsIURI;
-template class nsTArray;
#define NS_FORM_METHOD_GET 0
#define NS_FORM_METHOD_POST 1
@@ -53,13 +52,12 @@ template class nsTArray;
// IID for the nsIForm interface
#define NS_IFORM_IID \
-{ 0x6e8456c2, 0xcf49, 0x4b6d, \
- { 0xb5, 0xfe, 0x80, 0x0d, 0x03, 0x4f, 0x55, 0x33 } }
+{ 0x27f1ff6c, 0xeb78, 0x405b, \
+ { 0xa6, 0xeb, 0xf0, 0xce, 0xa8, 0x30, 0x85, 0x58 } }
/**
- * This interface provides a complete set of methods dealing with
- * elements which belong to a form element. When nsIDOMHTMLCollection
- * allows write operations
+ * This interface provides some methods that can be used to access the
+ * guts of a form. It's being slowly phased out.
*/
class nsIForm : public nsISupports
@@ -67,27 +65,6 @@ class nsIForm : public nsISupports
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFORM_IID)
- /**
- * Add an element to end of this form's list of elements
- *
- * @param aElement the element to add
- * @param aNotify If true, send nsIDocumentObserver notifications as needed.
- * @return NS_OK if the element was successfully added
- */
- NS_IMETHOD AddElement(nsIFormControl* aElement,
- PRBool aNotify) = 0;
-
- /**
- * Add an element to the lookup table mainted by the form.
- *
- * We can't fold this method into AddElement() because when
- * AddElement() is called, the form control has no
- * attributes. The name or id attributes of the form control
- * are used as a key into the table.
- */
- NS_IMETHOD AddElementToTable(nsIFormControl* aElement,
- const nsAString& aName) = 0;
-
/**
* Get the element at a specified index position in form.elements
*
@@ -95,7 +72,7 @@ public:
* @param aElement the element at that index
* @return NS_OK if there was an element at that position, -1 otherwise
*/
- NS_IMETHOD GetElementAt(PRInt32 aIndex, nsIFormControl** aElement) const = 0;
+ NS_IMETHOD_(nsIFormControl*) GetElementAt(PRInt32 aIndex) const = 0;
/**
* Get the number of elements in form.elements
@@ -105,30 +82,6 @@ public:
*/
NS_IMETHOD_(PRUint32) GetElementCount() const = 0;
- /**
- * Remove an element from this form's list of elements
- *
- * @param aElement the element to remove
- * @param aNotify If true, send nsIDocumentObserver notifications as needed.
- * @return NS_OK if the element was successfully removed.
- */
- NS_IMETHOD RemoveElement(nsIFormControl* aElement,
- PRBool aNotify) = 0;
-
- /**
- * Remove an element from the lookup table mainted by the form.
- * We can't fold this method into RemoveElement() because when
- * RemoveElement() is called it doesn't know if the element is
- * removed because the id attribute has changed, or bacause the
- * name attribute has changed.
- *
- * @param aElement the element to remove
- * @param aName the name or id of the element to remove
- * @return NS_OK if the element was successfully removed.
- */
- NS_IMETHOD RemoveElementFromTable(nsIFormControl* aElement,
- const nsAString& aName) = 0;
-
/**
* Resolve a name in the scope of the form object, this means find
* form controls in this form with the correct value in the name
@@ -147,68 +100,11 @@ public:
*/
NS_IMETHOD_(PRInt32) IndexOfControl(nsIFormControl* aControl) = 0;
- /**
- * Flag the form to know that a button or image triggered scripted form
- * submission. In that case the form will defer the submission until the
- * script handler returns and the return value is known.
- */
- NS_IMETHOD OnSubmitClickBegin() = 0;
- NS_IMETHOD OnSubmitClickEnd() = 0;
-
- /**
- * Flush a possible pending submission. If there was a scripted submission
- * triggered by a button or image, the submission was defered. This method
- * forces the pending submission to be submitted. (happens when the handler
- * returns false or there is an action/target change in the script)
- */
- NS_IMETHOD FlushPendingSubmission() = 0;
- /**
- * Forget a possible pending submission. Same as above but this time we
- * get rid of the pending submission cause the handler returned true
- * so we will rebuild the submission with the name/value of the triggering
- * element
- */
- NS_IMETHOD ForgetPendingSubmission() = 0;
-
- /**
- * Get the full URL to submit to. Do not submit if the returned URL is null.
- *
- * @param aActionURL the full, unadulterated URL you'll be submitting to [OUT]
- */
- NS_IMETHOD GetActionURL(nsIURI** aActionURL) = 0;
-
- /**
- * Get the list of all the form's controls in document order.
- * This list contains all form control elements, not just those
- * returned by form.elements in JS. The controls in this list do
- * not have additional references added.
- *
- * @param aControls Sorted list of form controls [out].
- * @return NS_OK if the list was successfully created.
- */
- NS_IMETHOD GetSortedControls(nsTArray& aControls) const = 0;
-
/**
* Get the default submit element. If there's no default submit element,
* return null.
*/
NS_IMETHOD_(nsIFormControl*) GetDefaultSubmitElement() const = 0;
-
- /**
- * Check whether a given nsIFormControl is the default submit
- * element. This is different from just comparing to
- * GetDefaultSubmitElement() in certain situations inside an update
- * when GetDefaultSubmitElement() might not be up to date. aControl
- * is expected to not be null.
- */
- NS_IMETHOD_(PRBool) IsDefaultSubmitElement(const nsIFormControl* aControl) const = 0;
-
- /**
- * Return whether there is one and only one input text control.
- *
- * @return Whether there is exactly one input text control.
- */
- NS_IMETHOD_(PRBool) HasSingleTextControl() const = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIForm, NS_IFORM_IID)
diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp
index e38efb375136..5ebcee1958f4 100644
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -98,6 +98,7 @@
#include "nsIForm.h"
#include "nsIFormControl.h"
#include "nsIDOMHTMLFormElement.h"
+#include "nsHTMLFormElement.h"
#include "nsFocusManager.h"
#include "nsMutationEvent.h"
@@ -897,8 +898,8 @@ nsGenericHTMLElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
nsGenericElement::UnbindFromTree(aDeep, aNullParent);
}
-already_AddRefed
-nsGenericHTMLElement::FindForm(nsIForm* aCurrentForm)
+nsHTMLFormElement*
+nsGenericHTMLElement::FindForm(nsHTMLFormElement* aCurrentForm)
{
// Make sure we don't end up finding a form that's anonymous from
// our point of view.
@@ -921,10 +922,7 @@ nsGenericHTMLElement::FindForm(nsIForm* aCurrentForm)
}
}
#endif
- nsIDOMHTMLFormElement* form;
- CallQueryInterface(content, &form);
-
- return form;
+ return static_cast(content);
}
nsIContent *prevContent = content;
@@ -938,19 +936,9 @@ nsGenericHTMLElement::FindForm(nsIForm* aCurrentForm)
// we're one of those inputs-in-a-table that have a hacked mForm pointer
// and a subtree containing both us and the form got removed from the
// DOM.
- nsCOMPtr formCOMPtr = do_QueryInterface(aCurrentForm);
- NS_ASSERTION(formCOMPtr, "aCurrentForm isn't an nsIContent?");
- // Use an nsIContent temporary to reduce addref/releasing as we go up the
- // tree
- nsINode* iter = formCOMPtr;
- do {
- iter = iter->GetNodeParent();
- if (iter == prevContent) {
- nsIDOMHTMLFormElement* form;
- CallQueryInterface(aCurrentForm, &form);
- return form;
- }
- } while (iter);
+ if (nsContentUtils::ContentIsDescendantOf(aCurrentForm, prevContent)) {
+ return aCurrentForm;
+ }
}
}
@@ -2265,9 +2253,9 @@ nsGenericHTMLElement::SetContentEditable(const nsAString& aContentEditable)
NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsGenericHTMLFrameElement, TabIndex, tabindex, 0)
nsGenericHTMLFormElement::nsGenericHTMLFormElement(nsINodeInfo *aNodeInfo)
- : nsGenericHTMLElement(aNodeInfo)
+ : nsGenericHTMLElement(aNodeInfo),
+ mForm(nsnull)
{
- mForm = nsnull;
}
nsGenericHTMLFormElement::~nsGenericHTMLFormElement()
@@ -2302,8 +2290,7 @@ nsGenericHTMLFormElement::SetForm(nsIDOMHTMLFormElement* aForm)
"We don't support switching from one non-null form to another.");
// keep a *weak* ref to the form here
- CallQueryInterface(aForm, &mForm);
- mForm->Release();
+ mForm = static_cast(aForm);
}
void
@@ -2341,12 +2328,7 @@ NS_IMETHODIMP
nsGenericHTMLFormElement::GetForm(nsIDOMHTMLFormElement** aForm)
{
NS_ENSURE_ARG_POINTER(aForm);
- *aForm = nsnull;
-
- if (mForm) {
- CallQueryInterface(mForm, aForm);
- }
-
+ NS_IF_ADDREF(*aForm = mForm);
return NS_OK;
}
@@ -2434,10 +2416,7 @@ nsGenericHTMLFormElement::BindToTree(nsIDocument* aDocument,
// it to the right value. Also note that even if being bound here didn't
// change our parent, we still need to search, since our parent chain
// probably changed _somewhere_.
- nsCOMPtr form = FindForm();
- if (form) {
- SetForm(form);
- }
+ mForm = FindForm();
}
if (mForm && !HasFlag(ADDED_TO_FORM)) {
@@ -2476,8 +2455,7 @@ nsGenericHTMLFormElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
ClearForm(PR_TRUE, PR_TRUE);
} else {
// Recheck whether we should still have an mForm.
- nsCOMPtr form = FindForm(mForm);
- if (!form) {
+ if (!FindForm(mForm)) {
ClearForm(PR_TRUE, PR_TRUE);
} else {
UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h
index a28da2c2048a..e200415a372c 100644
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -62,6 +62,7 @@ class nsILayoutHistoryState;
class nsIEditor;
struct nsRect;
struct nsSize;
+class nsHTMLFormElement;
typedef nsMappedAttributeElement nsGenericHTMLElementBase;
@@ -506,7 +507,7 @@ public:
* returned. This is needed to handle cases when HTML elements have a
* current form that they're not descendants of.
*/
- already_AddRefed FindForm(nsIForm* aCurrentForm = nsnull);
+ nsHTMLFormElement* FindForm(nsHTMLFormElement* aCurrentForm = nsnull);
virtual void RecompileScriptEventListeners();
@@ -855,7 +856,7 @@ protected:
FocusTristate FocusState();
/** The form that contains this control */
- nsIForm* mForm;
+ nsHTMLFormElement* mForm;
};
// If this flag is set on an nsGenericHTMLFormElement, that means that we have
diff --git a/content/html/content/src/nsHTMLButtonElement.cpp b/content/html/content/src/nsHTMLButtonElement.cpp
index 7df47786deb8..dd6bfd379069 100644
--- a/content/html/content/src/nsHTMLButtonElement.cpp
+++ b/content/html/content/src/nsHTMLButtonElement.cpp
@@ -61,6 +61,7 @@
#include "nsPresState.h"
#include "nsLayoutErrors.h"
#include "nsFocusManager.h"
+#include "nsHTMLFormElement.h"
#define NS_IN_SUBMIT_CLICK (1 << 0)
#define NS_OUTER_ACTIVATE_EVENT (1 << 1)
@@ -464,8 +465,9 @@ nsHTMLButtonElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
// Using presShell to dispatch the event. It makes sure that
// event is not handled if the window is being destroyed.
if (presShell) {
- nsCOMPtr form(do_QueryInterface(mForm));
- presShell->HandleDOMEventWithTarget(form, &event, &status);
+ // Hold a strong ref while dispatching
+ nsRefPtr form(mForm);
+ presShell->HandleDOMEventWithTarget(mForm, &event, &status);
}
}
}
diff --git a/content/html/content/src/nsHTMLFormElement.cpp b/content/html/content/src/nsHTMLFormElement.cpp
index f81c4d609c07..61314d4c0d79 100644
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -34,16 +34,10 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-#include "nsCOMPtr.h"
-#include "nsIForm.h"
-#include "nsIFormControl.h"
-#include "nsIFormSubmission.h"
-#include "nsIDOMHTMLFormElement.h"
-#include "nsIDOMNSHTMLFormElement.h"
+#include "nsHTMLFormElement.h"
#include "nsIHTMLDocument.h"
#include "nsIDOMNSHTMLFormControlList.h"
#include "nsIDOMEventTarget.h"
-#include "nsGenericHTMLElement.h"
#include "nsEventStateManager.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
@@ -63,28 +57,23 @@
// form submission
#include "nsIFormSubmitObserver.h"
-#include "nsIURI.h"
#include "nsIObserverService.h"
#include "nsICategoryManager.h"
#include "nsCategoryManagerUtils.h"
#include "nsISimpleEnumerator.h"
-#include "nsPIDOMWindow.h"
#include "nsRange.h"
#include "nsIScriptSecurityManager.h"
#include "nsNetUtil.h"
#include "nsIWebProgress.h"
#include "nsIDocShell.h"
-#include "nsIWebProgressListener.h"
// radio buttons
#include "nsIDOMHTMLInputElement.h"
#include "nsIRadioControlElement.h"
#include "nsIRadioVisitor.h"
-#include "nsIRadioGroupContainer.h"
#include "nsLayoutUtils.h"
-#include "nsUnicharUtils.h"
#include "nsEventDispatcher.h"
#include "mozAutoDocUpdate.h"
@@ -92,280 +81,8 @@
static const int NS_FORM_CONTROL_LIST_HASHTABLE_SIZE = 16;
-class nsFormControlList;
-
-/**
- * hashkey wrapper using nsAString KeyType
- *
- * @see nsTHashtable::EntryType for specification
- */
-class nsStringCaseInsensitiveHashKey : public PLDHashEntryHdr
-{
-public:
- typedef const nsAString& KeyType;
- typedef const nsAString* KeyTypePointer;
- nsStringCaseInsensitiveHashKey(KeyTypePointer aStr) : mStr(*aStr) { } //take it easy just deal HashKey
- nsStringCaseInsensitiveHashKey(const nsStringCaseInsensitiveHashKey& toCopy) : mStr(toCopy.mStr) { }
- ~nsStringCaseInsensitiveHashKey() { }
-
- KeyType GetKey() const { return mStr; }
- PRBool KeyEquals(const KeyTypePointer aKey) const
- {
- return mStr.Equals(*aKey,nsCaseInsensitiveStringComparator());
- }
-
- static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
- static PLDHashNumber HashKey(const KeyTypePointer aKey)
- {
- nsAutoString tmKey(*aKey);
- ToLowerCase(tmKey);
- return HashString(tmKey);
- }
- enum { ALLOW_MEMMOVE = PR_TRUE };
-
-private:
- const nsString mStr;
-};
-
-
// nsHTMLFormElement
-class nsHTMLFormElement : public nsGenericHTMLElement,
- public nsIDOMHTMLFormElement,
- public nsIDOMNSHTMLFormElement,
- public nsIWebProgressListener,
- public nsIForm,
- public nsIRadioGroupContainer
-{
-public:
- nsHTMLFormElement(nsINodeInfo *aNodeInfo);
- virtual ~nsHTMLFormElement();
-
- nsresult Init();
-
- // nsISupports
- NS_DECL_ISUPPORTS_INHERITED
-
- // nsIDOMNode
- NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
-
- // nsIDOMElement
- NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
-
- // nsIDOMHTMLElement
- NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
-
- // nsIDOMHTMLFormElement
- NS_DECL_NSIDOMHTMLFORMELEMENT
-
- // nsIDOMNSHTMLFormElement
- NS_DECL_NSIDOMNSHTMLFORMELEMENT
-
- // nsIWebProgressListener
- NS_DECL_NSIWEBPROGRESSLISTENER
-
- // nsIForm
- NS_IMETHOD AddElement(nsIFormControl* aElement,
- PRBool aNotify);
- NS_IMETHOD AddElementToTable(nsIFormControl* aChild,
- const nsAString& aName);
- NS_IMETHOD GetElementAt(PRInt32 aIndex, nsIFormControl** aElement) const;
- NS_IMETHOD_(PRUint32) GetElementCount() const;
- NS_IMETHOD RemoveElement(nsIFormControl* aElement,
- PRBool aNotify);
- NS_IMETHOD RemoveElementFromTable(nsIFormControl* aElement,
- const nsAString& aName);
- NS_IMETHOD_(already_AddRefed) ResolveName(const nsAString& aName);
- NS_IMETHOD_(PRInt32) IndexOfControl(nsIFormControl* aControl);
- NS_IMETHOD OnSubmitClickBegin();
- NS_IMETHOD OnSubmitClickEnd();
- NS_IMETHOD FlushPendingSubmission();
- NS_IMETHOD ForgetPendingSubmission();
- NS_IMETHOD GetActionURL(nsIURI** aActionURL);
- NS_IMETHOD GetSortedControls(nsTArray& aControls) const;
- NS_IMETHOD_(nsIFormControl*) GetDefaultSubmitElement() const;
- NS_IMETHOD_(PRBool) IsDefaultSubmitElement(const nsIFormControl* aControl) const;
- NS_IMETHOD_(PRBool) HasSingleTextControl() const;
-
- // nsIRadioGroupContainer
- NS_IMETHOD SetCurrentRadioButton(const nsAString& aName,
- nsIDOMHTMLInputElement* aRadio);
- NS_IMETHOD GetCurrentRadioButton(const nsAString& aName,
- nsIDOMHTMLInputElement** aRadio);
- NS_IMETHOD GetPositionInGroup(nsIDOMHTMLInputElement *aRadio,
- PRInt32 *aPositionIndex,
- PRInt32 *aItemsInGroup);
- NS_IMETHOD GetNextRadioButton(const nsAString& aName,
- const PRBool aPrevious,
- nsIDOMHTMLInputElement* aFocusedRadio,
- nsIDOMHTMLInputElement** aRadioOut);
- NS_IMETHOD WalkRadioGroup(const nsAString& aName, nsIRadioVisitor* aVisitor,
- PRBool aFlushContent);
- NS_IMETHOD AddToRadioGroup(const nsAString& aName,
- nsIFormControl* aRadio);
- NS_IMETHOD RemoveFromRadioGroup(const nsAString& aName,
- nsIFormControl* aRadio);
-
- // nsIContent
- virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
- nsIAtom* aAttribute,
- const nsAString& aValue,
- nsAttrValue& aResult);
- virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
- virtual nsresult WillHandleEvent(nsEventChainPostVisitor& aVisitor);
- virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
-
- virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
- nsIContent* aBindingParent,
- PRBool aCompileEventHandlers);
- virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
- PRBool aNullParent = PR_TRUE);
- nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
- const nsAString& aValue, PRBool aNotify)
- {
- return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
- }
- virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
- nsIAtom* aPrefix, const nsAString& aValue,
- PRBool aNotify);
-
- /**
- * Forget all information about the current submission (and the fact that we
- * are currently submitting at all).
- */
- void ForgetCurrentSubmission();
-
- virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
-
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLFormElement,
- nsGenericHTMLElement)
-
-protected:
- class RemoveElementRunnable;
- friend class RemoveElementRunnable;
-
- class RemoveElementRunnable : public nsRunnable {
- public:
- RemoveElementRunnable(nsHTMLFormElement* aForm, PRBool aNotify):
- mForm(aForm), mNotify(aNotify)
- {}
-
- NS_IMETHOD Run() {
- mForm->HandleDefaultSubmitRemoval(mNotify);
- return NS_OK;
- }
-
- private:
- nsRefPtr mForm;
- PRBool mNotify;
- };
-
- nsresult DoSubmitOrReset(nsEvent* aEvent,
- PRInt32 aMessage);
- nsresult DoReset();
-
- // Async callback to handle removal of our default submit
- void HandleDefaultSubmitRemoval(PRBool aNotify);
-
- //
- // Submit Helpers
- //
- //
- /**
- * Attempt to submit (submission might be deferred)
- * (called by DoSubmitOrReset)
- *
- * @param aPresContext the presentation context
- * @param aEvent the DOM event that was passed to us for the submit
- */
- nsresult DoSubmit(nsEvent* aEvent);
-
- /**
- * Prepare the submission object (called by DoSubmit)
- *
- * @param aFormSubmission the submission object
- * @param aEvent the DOM event that was passed to us for the submit
- */
- nsresult BuildSubmission(nsCOMPtr& aFormSubmission,
- nsEvent* aEvent);
- /**
- * Perform the submission (called by DoSubmit and FlushPendingSubmission)
- *
- * @param aFormSubmission the submission object
- */
- nsresult SubmitSubmission(nsIFormSubmission* aFormSubmission);
- /**
- * Walk over the form elements and call SubmitNamesValues() on them to get
- * their data pumped into the FormSubmitter.
- *
- * @param aFormSubmission the form submission object
- * @param aSubmitElement the element that was clicked on (nsnull if none)
- */
- nsresult WalkFormElements(nsIFormSubmission* aFormSubmission,
- nsIContent* aSubmitElement);
-
- /**
- * Notify any submit observers of the submit.
- *
- * @param aActionURL the URL being submitted to
- * @param aCancelSubmit out param where submit observers can specify that the
- * submit should be cancelled.
- */
- nsresult NotifySubmitObservers(nsIURI* aActionURL, PRBool* aCancelSubmit,
- PRBool aEarlyNotify);
-
- /**
- * Just like ResolveName(), but takes an arg for whether to flush
- */
- already_AddRefed DoResolveName(const nsAString& aName, PRBool aFlushContent);
-
- //
- // Data members
- //
- /** The list of controls (form.elements as well as stuff not in elements) */
- nsRefPtr mControls;
- /** The currently selected radio button of each group */
- nsInterfaceHashtable mSelectedRadioButtons;
- /** Whether we are currently processing a submit event or not */
- PRPackedBool mGeneratingSubmit;
- /** Whether we are currently processing a reset event or not */
- PRPackedBool mGeneratingReset;
- /** Whether we are submitting currently */
- PRPackedBool mIsSubmitting;
- /** Whether the submission is to be deferred in case a script triggers it */
- PRPackedBool mDeferSubmission;
- /** Whether we notified NS_FORMSUBMIT_SUBJECT listeners already */
- PRPackedBool mNotifiedObservers;
- /** If we notified the listeners early, what was the result? */
- PRPackedBool mNotifiedObserversResult;
- /** Keep track of what the popup state was when the submit was initiated */
- PopupControlState mSubmitPopupState;
- /** Keep track of whether a submission was user-initiated or not */
- PRBool mSubmitInitiatedFromUserInput;
-
- /** The pending submission object */
- nsCOMPtr mPendingSubmission;
- /** The request currently being submitted */
- nsCOMPtr mSubmittingRequest;
- /** The web progress object we are currently listening to */
- nsWeakPtr mWebProgress;
-
- /** The default submit element -- WEAK */
- nsIFormControl* mDefaultSubmitElement;
-
- /** The first submit element in mElements -- WEAK */
- nsIFormControl* mFirstSubmitInElements;
-
- /** The first submit element in mNotInElements -- WEAK */
- nsIFormControl* mFirstSubmitNotInElements;
-
-protected:
- /** Detection of first form to notify observers */
- static PRBool gFirstFormSubmitted;
- /** Detection of first password input to initialize the password manager */
- static PRBool gPasswordManagerInitialized;
-};
-
PRBool nsHTMLFormElement::gFirstFormSubmitted = PR_FALSE;
PRBool nsHTMLFormElement::gPasswordManagerInitialized = PR_FALSE;
@@ -396,7 +113,8 @@ public:
*aResult = NS_OK;
- return mElements.SafeElementAt(aIndex, nsnull);
+ // XXXbz this should start returning nsINode* or something!
+ return static_cast(mElements.SafeElementAt(aIndex, nsnull));
}
virtual nsISupports* GetNamedItem(const nsAString& aName, nsresult* aResult)
{
@@ -405,9 +123,9 @@ public:
return NamedItemInternal(aName, PR_TRUE);
}
- nsresult AddElementToTable(nsIFormControl* aChild,
+ nsresult AddElementToTable(nsGenericHTMLFormElement* aChild,
const nsAString& aName);
- nsresult RemoveElementFromTable(nsIFormControl* aChild,
+ nsresult RemoveElementFromTable(nsGenericHTMLFormElement* aChild,
const nsAString& aName);
nsresult IndexOfControl(nsIFormControl* aControl,
PRInt32* aIndex);
@@ -423,18 +141,18 @@ public:
* @param aControls The list of sorted controls[out].
* @return NS_OK or NS_ERROR_OUT_OF_MEMORY.
*/
- nsresult GetSortedControls(nsTArray& aControls) const;
+ nsresult GetSortedControls(nsTArray& aControls) const;
nsHTMLFormElement* mForm; // WEAK - the form owns me
- nsTArray mElements; // Holds WEAK references - bug 36639
+ nsTArray mElements; // Holds WEAK references - bug 36639
// This array holds on to all form controls that are not contained
// in mElements (form.elements in JS, see ShouldBeInFormControl()).
// This is needed to properly clean up the bi-directional references
// (both weak and strong) between the form and its form controls.
- nsTArray mNotInElements; // Holds WEAK references
+ nsTArray mNotInElements; // Holds WEAK references
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFormControlList, nsIHTMLCollection)
@@ -751,18 +469,16 @@ nsHTMLFormElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
}
static void
-MarkOrphans(const nsTArray aArray)
+MarkOrphans(const nsTArray aArray)
{
PRUint32 length = aArray.Length();
for (PRUint32 i = 0; i < length; ++i) {
- nsCOMPtr node = do_QueryInterface(aArray[i]);
- NS_ASSERTION(node, "Form control must be nsINode");
- node->SetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
+ aArray[i]->SetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
}
}
static void
-CollectOrphans(nsINode* aRemovalRoot, nsTArray aArray
+CollectOrphans(nsINode* aRemovalRoot, nsTArray aArray
#ifdef DEBUG
, nsIDOMHTMLFormElement* aThisForm
#endif
@@ -771,9 +487,7 @@ CollectOrphans(nsINode* aRemovalRoot, nsTArray aArray
// Walk backwards so that if we remove elements we can just keep iterating
PRUint32 length = aArray.Length();
for (PRUint32 i = length; i > 0; --i) {
- nsIFormControl* control = aArray[i-1];
- nsCOMPtr node = do_QueryInterface(control);
- NS_ASSERTION(node, "Form control must be nsINode");
+ nsGenericHTMLFormElement* node = aArray[i-1];
// Now if MAYBE_ORPHAN_FORM_ELEMENT is not set, that would mean that the
// node is in fact a descendant of the form and hence should stay in the
@@ -786,7 +500,7 @@ CollectOrphans(nsINode* aRemovalRoot, nsTArray aArray
if (node->HasFlag(MAYBE_ORPHAN_FORM_ELEMENT)) {
node->UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
if (!nsContentUtils::ContentIsDescendantOf(node, aRemovalRoot)) {
- control->ClearForm(PR_TRUE, PR_TRUE);
+ node->ClearForm(PR_TRUE, PR_TRUE);
#ifdef DEBUG
removed = PR_TRUE;
#endif
@@ -796,7 +510,7 @@ CollectOrphans(nsINode* aRemovalRoot, nsTArray aArray
#ifdef DEBUG
if (!removed) {
nsCOMPtr form;
- control->GetForm(getter_AddRefs(form));
+ node->GetForm(getter_AddRefs(form));
NS_ASSERTION(form == aThisForm, "How did that happen?");
}
#endif /* DEBUG */
@@ -964,8 +678,8 @@ nsHTMLFormElement::DoReset()
// JBK walk the elements[] array instead of form frame controls - bug 34297
PRUint32 numElements = GetElementCount();
for (PRUint32 elementX = 0; (elementX < numElements); elementX++) {
- nsCOMPtr controlNode;
- GetElementAt(elementX, getter_AddRefs(controlNode));
+ // Hold strong ref in case the reset does something weird
+ nsCOMPtr controlNode = GetElementAt(elementX);
if (controlNode) {
controlNode->Reset();
}
@@ -1236,7 +950,7 @@ nsresult
nsHTMLFormElement::WalkFormElements(nsIFormSubmission* aFormSubmission,
nsIContent* aSubmitElement)
{
- nsTArray sortedControls;
+ nsTArray sortedControls;
nsresult rv = mControls->GetSortedControls(sortedControls);
NS_ENSURE_SUCCESS(rv, rv);
@@ -1262,19 +976,10 @@ nsHTMLFormElement::GetElementCount() const
return count;
}
-NS_IMETHODIMP
-nsHTMLFormElement::GetElementAt(PRInt32 aIndex,
- nsIFormControl** aFormControl) const
+NS_IMETHODIMP_(nsIFormControl*)
+nsHTMLFormElement::GetElementAt(PRInt32 aIndex) const
{
- // Converting to unsigned int will handle negative indices.
- if (PRUint32(aIndex) >= mControls->mElements.Length()) {
- *aFormControl = nsnull;
- } else {
- *aFormControl = mControls->mElements[aIndex];
- NS_ADDREF(*aFormControl);
- }
-
- return NS_OK;
+ return mControls->mElements.SafeElementAt(aIndex, nsnull);
}
/**
@@ -1286,21 +991,17 @@ nsHTMLFormElement::GetElementAt(PRInt32 aIndex,
* > 0 if aControl1 is after aControl2,
* 0 otherwise
*/
-static PRInt32 CompareFormControlPosition(nsIFormControl *aControl1,
- nsIFormControl *aControl2,
- const nsIContent* aForm)
+static inline PRInt32
+CompareFormControlPosition(nsGenericHTMLFormElement *aControl1,
+ nsGenericHTMLFormElement *aControl2,
+ const nsIContent* aForm)
{
NS_ASSERTION(aControl1 != aControl2, "Comparing a form control to itself");
- nsCOMPtr content1 = do_QueryInterface(aControl1);
- nsCOMPtr content2 = do_QueryInterface(aControl2);
-
- NS_ASSERTION(content1 && content2,
- "We should be able to QI to nsIContent here!");
- NS_ASSERTION(content1->GetParent() && content2->GetParent(),
+ NS_ASSERTION(aControl1->GetParent() && aControl2->GetParent(),
"Form controls should always have parents");
- return nsLayoutUtils::CompareTreePosition(content1, content2, aForm);
+ return nsLayoutUtils::CompareTreePosition(aControl1, aControl2, aForm);
}
#ifdef DEBUG
@@ -1312,7 +1013,7 @@ static PRInt32 CompareFormControlPosition(nsIFormControl *aControl1,
* @param aForm Parent form of the controls.
*/
static void
-AssertDocumentOrder(const nsTArray& aControls,
+AssertDocumentOrder(const nsTArray& aControls,
nsIContent* aForm)
{
// Only iterate if aControls is not empty, since otherwise
@@ -1328,29 +1029,23 @@ AssertDocumentOrder(const nsTArray& aControls,
}
#endif
-NS_IMETHODIMP
-nsHTMLFormElement::AddElement(nsIFormControl* aChild,
+nsresult
+nsHTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
PRBool aNotify)
{
-#ifdef DEBUG
- {
- nsCOMPtr content = do_QueryInterface(aChild);
- NS_ASSERTION(content->GetParent(),
- "Form control should have a parent");
- }
-#endif
+ NS_ASSERTION(aChild->GetParent(), "Form control should have a parent");
// Determine whether to add the new element to the elements or
// the not-in-elements list.
PRBool childInElements = ShouldBeInElements(aChild);
- nsTArray& controlList = childInElements ?
+ nsTArray& controlList = childInElements ?
mControls->mElements : mControls->mNotInElements;
NS_ASSERTION(controlList.IndexOf(aChild) == controlList.NoIndex,
"Form control already in form");
PRUint32 count = controlList.Length();
- nsCOMPtr element;
+ nsGenericHTMLFormElement* element;
// Optimize most common case where we insert at the end.
PRBool lastElement = PR_FALSE;
@@ -1396,7 +1091,8 @@ nsHTMLFormElement::AddElement(nsIFormControl* aChild,
//
PRInt32 type = aChild->GetType();
if (type == NS_FORM_INPUT_RADIO) {
- nsCOMPtr radio = do_QueryInterface(aChild);
+ nsCOMPtr radio;
+ CallQueryInterface(aChild, getter_AddRefs(radio));
nsresult rv = radio->AddedToRadioGroup();
NS_ENSURE_SUCCESS(rv, rv);
}
@@ -1418,7 +1114,7 @@ nsHTMLFormElement::AddElement(nsIFormControl* aChild,
// Update mDefaultSubmitElement, mFirstSubmitInElements,
// mFirstSubmitNotInElements.
- nsIFormControl** firstSubmitSlot =
+ nsGenericHTMLFormElement** firstSubmitSlot =
childInElements ? &mFirstSubmitInElements : &mFirstSubmitNotInElements;
// The new child is the new first submit in its list if the firstSubmitSlot
@@ -1469,16 +1165,16 @@ nsHTMLFormElement::AddElement(nsIFormControl* aChild,
return NS_OK;
}
-NS_IMETHODIMP
-nsHTMLFormElement::AddElementToTable(nsIFormControl* aChild,
+nsresult
+nsHTMLFormElement::AddElementToTable(nsGenericHTMLFormElement* aChild,
const nsAString& aName)
{
return mControls->AddElementToTable(aChild, aName);
}
-NS_IMETHODIMP
-nsHTMLFormElement::RemoveElement(nsIFormControl* aChild,
+nsresult
+nsHTMLFormElement::RemoveElement(nsGenericHTMLFormElement* aChild,
PRBool aNotify)
{
//
@@ -1486,7 +1182,8 @@ nsHTMLFormElement::RemoveElement(nsIFormControl* aChild,
//
nsresult rv = NS_OK;
if (aChild->GetType() == NS_FORM_INPUT_RADIO) {
- nsCOMPtr radio = do_QueryInterface(aChild);
+ nsCOMPtr radio;
+ CallQueryInterface(aChild, getter_AddRefs(radio));
rv = radio->WillRemoveFromRadioGroup();
NS_ENSURE_SUCCESS(rv, rv);
}
@@ -1494,7 +1191,7 @@ nsHTMLFormElement::RemoveElement(nsIFormControl* aChild,
// Determine whether to remove the child from the elements list
// or the not in elements list.
PRBool childInElements = ShouldBeInElements(aChild);
- nsTArray& controls = childInElements ?
+ nsTArray& controls = childInElements ?
mControls->mElements : mControls->mNotInElements;
// Find the index of the child. This will be used later if necessary
@@ -1505,7 +1202,7 @@ nsHTMLFormElement::RemoveElement(nsIFormControl* aChild,
controls.RemoveElementAt(index);
// Update our mFirstSubmit* values.
- nsIFormControl** firstSubmitSlot =
+ nsGenericHTMLFormElement** firstSubmitSlot =
childInElements ? &mFirstSubmitInElements : &mFirstSubmitNotInElements;
if (aChild == *firstSubmitSlot) {
*firstSubmitSlot = nsnull;
@@ -1513,7 +1210,7 @@ nsHTMLFormElement::RemoveElement(nsIFormControl* aChild,
// We are removing the first submit in this list, find the new first submit
PRUint32 length = controls.Length();
for (PRUint32 i = index; i < length; ++i) {
- nsIFormControl* currentControl = controls[i];
+ nsGenericHTMLFormElement* currentControl = controls[i];
if (currentControl->IsSubmitControl()) {
*firstSubmitSlot = currentControl;
break;
@@ -1567,15 +1264,14 @@ nsHTMLFormElement::HandleDefaultSubmitRemoval(PRBool aNotify)
nsIDocument* document = GetCurrentDoc();
if (document) {
MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, PR_TRUE);
- nsCOMPtr newElement(do_QueryInterface(mDefaultSubmitElement));
- document->ContentStatesChanged(newElement, nsnull,
+ document->ContentStatesChanged(mDefaultSubmitElement, nsnull,
NS_EVENT_STATE_DEFAULT);
}
}
}
-NS_IMETHODIMP
-nsHTMLFormElement::RemoveElementFromTable(nsIFormControl* aElement,
+nsresult
+nsHTMLFormElement::RemoveElementFromTable(nsGenericHTMLFormElement* aElement,
const nsAString& aName)
{
return mControls->RemoveElementFromTable(aElement, aName);
@@ -1596,7 +1292,7 @@ nsHTMLFormElement::DoResolveName(const nsAString& aName,
return result;
}
-NS_IMETHODIMP
+void
nsHTMLFormElement::OnSubmitClickBegin()
{
mDeferSubmission = PR_TRUE;
@@ -1609,7 +1305,7 @@ nsHTMLFormElement::OnSubmitClickBegin()
rv = GetActionURL(getter_AddRefs(actionURI));
if (NS_FAILED(rv) || !actionURI)
- return NS_OK;
+ return;
//
// Notify observers of submit
@@ -1620,24 +1316,21 @@ nsHTMLFormElement::OnSubmitClickBegin()
mNotifiedObservers = PR_TRUE;
mNotifiedObserversResult = cancelSubmit;
}
-
- return NS_OK;
}
-NS_IMETHODIMP
+void
nsHTMLFormElement::OnSubmitClickEnd()
{
mDeferSubmission = PR_FALSE;
- return NS_OK;
}
-NS_IMETHODIMP
+void
nsHTMLFormElement::FlushPendingSubmission()
{
nsCOMPtr kunkFuDeathGrip(mPendingSubmission);
if (!mPendingSubmission) {
- return NS_OK;
+ return;
}
//
@@ -1647,18 +1340,16 @@ nsHTMLFormElement::FlushPendingSubmission()
// now delete the pending submission object
mPendingSubmission = nsnull;
- return NS_OK;
}
-NS_IMETHODIMP
+void
nsHTMLFormElement::ForgetPendingSubmission()
{
// just delete the pending submission
mPendingSubmission = nsnull;
- return NS_OK;
}
-NS_IMETHODIMP
+nsresult
nsHTMLFormElement::GetActionURL(nsIURI** aActionURL)
{
nsresult rv = NS_OK;
@@ -1736,12 +1427,6 @@ nsHTMLFormElement::GetActionURL(nsIURI** aActionURL)
return rv;
}
-NS_IMETHODIMP
-nsHTMLFormElement::GetSortedControls(nsTArray& aControls) const
-{
- return mControls->GetSortedControls(aControls);
-}
-
NS_IMETHODIMP_(nsIFormControl*)
nsHTMLFormElement::GetDefaultSubmitElement() const
{
@@ -1752,7 +1437,7 @@ nsHTMLFormElement::GetDefaultSubmitElement() const
return mDefaultSubmitElement;
}
-NS_IMETHODIMP_(PRBool)
+PRBool
nsHTMLFormElement::IsDefaultSubmitElement(const nsIFormControl* aControl) const
{
NS_PRECONDITION(aControl, "Unexpected call");
@@ -1787,7 +1472,7 @@ nsHTMLFormElement::IsDefaultSubmitElement(const nsIFormControl* aControl) const
return aControl == defaultSubmit;
}
-NS_IMETHODIMP_(PRBool)
+PRBool
nsHTMLFormElement::HasSingleTextControl() const
{
// Input text controls are always in the elements list.
@@ -1938,12 +1623,8 @@ nsHTMLFormElement::GetPositionInGroup(nsIDOMHTMLInputElement *aRadio,
nsCOMPtr itemWithName;
itemWithName = ResolveName(name);
NS_ENSURE_TRUE(itemWithName, NS_ERROR_FAILURE);
- nsCOMPtr radioNodeList(do_QueryInterface(itemWithName));
+ nsCOMPtr radioGroup(do_QueryInterface(itemWithName));
- // XXX If ResolveName could return an nsContentList instead then we
- // could get an nsContentList instead of using this hacky upcast
- nsBaseContentList *radioGroup =
- static_cast((nsIDOMNodeList *)radioNodeList);
NS_ASSERTION(radioGroup, "No such radio group in this container");
if (!radioGroup) {
return NS_OK;
@@ -1951,7 +1632,7 @@ nsHTMLFormElement::GetPositionInGroup(nsIDOMHTMLInputElement *aRadio,
nsCOMPtr currentRadioNode(do_QueryInterface(aRadio));
NS_ASSERTION(currentRadioNode, "No nsIContent for current radio button");
- *aPositionIndex = radioGroup->IndexOf(currentRadioNode, PR_TRUE);
+ *aPositionIndex = radioGroup->IndexOf(currentRadioNode);
NS_ASSERTION(*aPositionIndex >= 0, "Radio button not found in its own group");
PRUint32 itemsInGroup;
radioGroup->GetLength(&itemsInGroup);
@@ -1979,20 +1660,15 @@ nsHTMLFormElement::GetNextRadioButton(const nsAString& aName,
}
nsCOMPtr itemWithName = ResolveName(aName);
- nsCOMPtr radioNodeList(do_QueryInterface(itemWithName));
+ nsCOMPtr radioGroup(do_QueryInterface(itemWithName));
- // XXX If ResolveName could return an nsContentList instead then we
- // could get an nsContentList instead of using this hacky upcast
-
- nsBaseContentList *radioGroup =
- static_cast((nsIDOMNodeList *)radioNodeList);
if (!radioGroup) {
return NS_ERROR_FAILURE;
}
nsCOMPtr currentRadioNode(do_QueryInterface(currentRadio));
NS_ASSERTION(currentRadioNode, "No nsIContent for current radio button");
- PRInt32 index = radioGroup->IndexOf(currentRadioNode, PR_TRUE);
+ PRInt32 index = radioGroup->IndexOf(currentRadioNode);
if (index < 0) {
return NS_ERROR_FAILURE;
}
@@ -2001,7 +1677,6 @@ nsHTMLFormElement::GetNextRadioButton(const nsAString& aName,
radioGroup->GetLength(&numRadios);
PRBool disabled = PR_TRUE;
nsCOMPtr radio;
- nsCOMPtr radioDOMNode;
nsCOMPtr formControl;
do {
@@ -2013,11 +1688,11 @@ nsHTMLFormElement::GetNextRadioButton(const nsAString& aName,
else if (++index >= (PRInt32)numRadios) {
index = 0;
}
- radioGroup->Item(index, getter_AddRefs(radioDOMNode));
- radio = do_QueryInterface(radioDOMNode);
+ radio = do_QueryInterface(radioGroup->GetNodeAt(index));
if (!radio)
continue;
+ // XXXbz why is this formControl check needed, exactly?
formControl = do_QueryInterface(radio);
if (!formControl || formControl->GetType() != NS_FORM_INPUT_RADIO)
continue;
@@ -2046,7 +1721,7 @@ nsHTMLFormElement::WalkRadioGroup(const nsAString& aName,
nsCOMPtr control;
PRUint32 len = GetElementCount();
for (PRUint32 i=0; iGetType() == NS_FORM_INPUT_RADIO) {
nsCOMPtr controlContent(do_QueryInterface(control));
if (controlContent) {
@@ -2292,7 +1967,7 @@ nsFormControlList::NamedItemInternal(const nsAString& aName,
}
nsresult
-nsFormControlList::AddElementToTable(nsIFormControl* aChild,
+nsFormControlList::AddElementToTable(nsGenericHTMLFormElement* aChild,
const nsAString& aName)
{
if (!ShouldBeInElements(aChild)) {
@@ -2304,20 +1979,19 @@ nsFormControlList::AddElementToTable(nsIFormControl* aChild,
if (!supports) {
// No entry found, add the form control
- nsCOMPtr child(do_QueryInterface(aChild));
-
- NS_ENSURE_TRUE( mNameLookupTable.Put(aName, child), NS_ERROR_FAILURE );
+ NS_ENSURE_TRUE( mNameLookupTable.Put(aName,
+ NS_ISUPPORTS_CAST(nsIContent*, aChild)),
+ NS_ERROR_FAILURE );
} else {
// Found something in the hash, check its type
nsCOMPtr content(do_QueryInterface(supports));
- nsCOMPtr newChild(do_QueryInterface(aChild));
if (content) {
// Check if the new content is the same as the one we found in the
// hash, if it is then we leave it in the hash as it is, this will
// happen if a form control has both a name and an id with the same
// value
- if (content == newChild) {
+ if (content == aChild) {
return NS_OK;
}
@@ -2329,10 +2003,10 @@ nsFormControlList::AddElementToTable(nsIFormControl* aChild,
NS_ASSERTION(content->GetParent(), "Item in list without parent");
// Determine the ordering between the new and old element.
- PRBool newFirst = nsContentUtils::PositionIsBefore(newChild, content);
+ PRBool newFirst = nsContentUtils::PositionIsBefore(aChild, content);
- list->AppendElement(newFirst ? newChild : content);
- list->AppendElement(newFirst ? content : newChild);
+ list->AppendElement(newFirst ? aChild : content);
+ list->AppendElement(newFirst ? content : aChild);
nsCOMPtr listSupports =
@@ -2353,8 +2027,8 @@ nsFormControlList::AddElementToTable(nsIFormControl* aChild,
NS_ASSERTION(list->Length() > 1,
"List should have been converted back to a single element");
- if(nsContentUtils::PositionIsBefore(list->GetNodeAt(list->Length() - 1), newChild)) {
- list->AppendElement(newChild);
+ if(nsContentUtils::PositionIsBefore(list->GetNodeAt(list->Length() - 1), aChild)) {
+ list->AppendElement(aChild);
return NS_OK;
}
@@ -2368,13 +2042,13 @@ nsFormControlList::AddElementToTable(nsIFormControl* aChild,
while (last != first) {
mid = (first + last) / 2;
- if (nsContentUtils::PositionIsBefore(newChild, list->GetNodeAt(mid)))
+ if (nsContentUtils::PositionIsBefore(aChild, list->GetNodeAt(mid)))
last = mid;
else
first = mid + 1;
}
- list->InsertElementAt(newChild, first);
+ list->InsertElementAt(aChild, first);
}
}
@@ -2395,18 +2069,13 @@ nsFormControlList::IndexOfControl(nsIFormControl* aControl,
}
nsresult
-nsFormControlList::RemoveElementFromTable(nsIFormControl* aChild,
+nsFormControlList::RemoveElementFromTable(nsGenericHTMLFormElement* aChild,
const nsAString& aName)
{
if (!ShouldBeInElements(aChild)) {
return NS_OK;
}
- nsCOMPtr content = do_QueryInterface(aChild);
- if (!content) {
- return NS_OK;
- }
-
nsCOMPtr supports;
if (!mNameLookupTable.Get(aName, getter_AddRefs(supports)))
@@ -2431,7 +2100,7 @@ nsFormControlList::RemoveElementFromTable(nsIFormControl* aChild,
nsBaseContentList *list = static_cast
((nsIDOMNodeList *)nodeList.get());
- list->RemoveElement(content);
+ list->RemoveElement(aChild);
PRUint32 length = 0;
list->GetLength(&length);
@@ -2443,12 +2112,9 @@ nsFormControlList::RemoveElementFromTable(nsIFormControl* aChild,
} else if (length == 1) {
// Only one element left, replace the list in the hash with the
// single element.
- nsCOMPtr node;
- list->Item(0, getter_AddRefs(node));
-
+ nsIContent* node = list->GetNodeAt(0);
if (node) {
- nsCOMPtr tmp(do_QueryInterface(node));
- NS_ENSURE_TRUE(mNameLookupTable.Put(aName, tmp),NS_ERROR_FAILURE);
+ NS_ENSURE_TRUE(mNameLookupTable.Put(aName, node),NS_ERROR_FAILURE);
}
}
@@ -2456,7 +2122,7 @@ nsFormControlList::RemoveElementFromTable(nsIFormControl* aChild,
}
nsresult
-nsFormControlList::GetSortedControls(nsTArray& aControls) const
+nsFormControlList::GetSortedControls(nsTArray& aControls) const
{
#ifdef DEBUG
AssertDocumentOrder(mElements, mForm);
@@ -2507,7 +2173,7 @@ nsFormControlList::GetSortedControls(nsTArray& aControls) const
"Should have remaining elements");
// Determine which of the two elements should be ordered
// first and add it to the end of the list.
- nsIFormControl* elementToAdd;
+ nsGenericHTMLFormElement* elementToAdd;
if (CompareFormControlPosition(mElements[elementsIdx],
mNotInElements[notInElementsIdx],
mForm) < 0) {
diff --git a/content/html/content/src/nsHTMLFormElement.h b/content/html/content/src/nsHTMLFormElement.h
new file mode 100644
index 000000000000..b38e391bfc8a
--- /dev/null
+++ b/content/html/content/src/nsHTMLFormElement.h
@@ -0,0 +1,394 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsCOMPtr.h"
+#include "nsIForm.h"
+#include "nsIFormControl.h"
+#include "nsIFormSubmission.h"
+#include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLFormElement.h"
+#include "nsIDOMNSHTMLFormElement.h"
+#include "nsIWebProgressListener.h"
+#include "nsIRadioGroupContainer.h"
+#include "nsIURI.h"
+#include "nsIWeakReferenceUtils.h"
+#include "nsPIDOMWindow.h"
+#include "nsUnicharUtils.h"
+#include "nsThreadUtils.h"
+
+class nsFormControlList;
+
+/**
+ * hashkey wrapper using nsAString KeyType
+ *
+ * @see nsTHashtable::EntryType for specification
+ */
+class nsStringCaseInsensitiveHashKey : public PLDHashEntryHdr
+{
+public:
+ typedef const nsAString& KeyType;
+ typedef const nsAString* KeyTypePointer;
+ nsStringCaseInsensitiveHashKey(KeyTypePointer aStr) : mStr(*aStr) { } //take it easy just deal HashKey
+ nsStringCaseInsensitiveHashKey(const nsStringCaseInsensitiveHashKey& toCopy) : mStr(toCopy.mStr) { }
+ ~nsStringCaseInsensitiveHashKey() { }
+
+ KeyType GetKey() const { return mStr; }
+ PRBool KeyEquals(const KeyTypePointer aKey) const
+ {
+ return mStr.Equals(*aKey,nsCaseInsensitiveStringComparator());
+ }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
+ static PLDHashNumber HashKey(const KeyTypePointer aKey)
+ {
+ nsAutoString tmKey(*aKey);
+ ToLowerCase(tmKey);
+ return HashString(tmKey);
+ }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const nsString mStr;
+};
+
+class nsHTMLFormElement : public nsGenericHTMLElement,
+ public nsIDOMHTMLFormElement,
+ public nsIDOMNSHTMLFormElement,
+ public nsIWebProgressListener,
+ public nsIForm,
+ public nsIRadioGroupContainer
+{
+public:
+ nsHTMLFormElement(nsINodeInfo *aNodeInfo);
+ virtual ~nsHTMLFormElement();
+
+ nsresult Init();
+
+ // nsISupports
+ NS_DECL_ISUPPORTS_INHERITED
+
+ // nsIDOMNode
+ NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
+
+ // nsIDOMElement
+ NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
+
+ // nsIDOMHTMLElement
+ NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
+
+ // nsIDOMHTMLFormElement
+ NS_DECL_NSIDOMHTMLFORMELEMENT
+
+ // nsIDOMNSHTMLFormElement
+ NS_DECL_NSIDOMNSHTMLFORMELEMENT
+
+ // nsIWebProgressListener
+ NS_DECL_NSIWEBPROGRESSLISTENER
+
+ // nsIForm
+ NS_IMETHOD_(nsIFormControl*) GetElementAt(PRInt32 aIndex) const;
+ NS_IMETHOD_(PRUint32) GetElementCount() const;
+ NS_IMETHOD_(already_AddRefed) ResolveName(const nsAString& aName);
+ NS_IMETHOD_(PRInt32) IndexOfControl(nsIFormControl* aControl);
+ NS_IMETHOD_(nsIFormControl*) GetDefaultSubmitElement() const;
+
+ // nsIRadioGroupContainer
+ NS_IMETHOD SetCurrentRadioButton(const nsAString& aName,
+ nsIDOMHTMLInputElement* aRadio);
+ NS_IMETHOD GetCurrentRadioButton(const nsAString& aName,
+ nsIDOMHTMLInputElement** aRadio);
+ NS_IMETHOD GetPositionInGroup(nsIDOMHTMLInputElement *aRadio,
+ PRInt32 *aPositionIndex,
+ PRInt32 *aItemsInGroup);
+ NS_IMETHOD GetNextRadioButton(const nsAString& aName,
+ const PRBool aPrevious,
+ nsIDOMHTMLInputElement* aFocusedRadio,
+ nsIDOMHTMLInputElement** aRadioOut);
+ NS_IMETHOD WalkRadioGroup(const nsAString& aName, nsIRadioVisitor* aVisitor,
+ PRBool aFlushContent);
+ NS_IMETHOD AddToRadioGroup(const nsAString& aName,
+ nsIFormControl* aRadio);
+ NS_IMETHOD RemoveFromRadioGroup(const nsAString& aName,
+ nsIFormControl* aRadio);
+
+ // nsIContent
+ virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
+ nsIAtom* aAttribute,
+ const nsAString& aValue,
+ nsAttrValue& aResult);
+ virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
+ virtual nsresult WillHandleEvent(nsEventChainPostVisitor& aVisitor);
+ virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
+
+ virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+ nsIContent* aBindingParent,
+ PRBool aCompileEventHandlers);
+ virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
+ PRBool aNullParent = PR_TRUE);
+ nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+ const nsAString& aValue, PRBool aNotify)
+ {
+ return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
+ }
+ virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+ nsIAtom* aPrefix, const nsAString& aValue,
+ PRBool aNotify);
+
+ /**
+ * Forget all information about the current submission (and the fact that we
+ * are currently submitting at all).
+ */
+ void ForgetCurrentSubmission();
+
+ virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLFormElement,
+ nsGenericHTMLElement)
+
+ /**
+ * Remove an element from this form's list of elements
+ *
+ * @param aElement the element to remove
+ * @param aNotify If true, send nsIDocumentObserver notifications as needed.
+ * @return NS_OK if the element was successfully removed.
+ */
+ nsresult RemoveElement(nsGenericHTMLFormElement* aElement, PRBool aNotify);
+
+ /**
+ * Remove an element from the lookup table mainted by the form.
+ * We can't fold this method into RemoveElement() because when
+ * RemoveElement() is called it doesn't know if the element is
+ * removed because the id attribute has changed, or bacause the
+ * name attribute has changed.
+ *
+ * @param aElement the element to remove
+ * @param aName the name or id of the element to remove
+ * @return NS_OK if the element was successfully removed.
+ */
+ nsresult RemoveElementFromTable(nsGenericHTMLFormElement* aElement,
+ const nsAString& aName);
+ /**
+ * Add an element to end of this form's list of elements
+ *
+ * @param aElement the element to add
+ * @param aNotify If true, send nsIDocumentObserver notifications as needed.
+ * @return NS_OK if the element was successfully added
+ */
+ nsresult AddElement(nsGenericHTMLFormElement* aElement, PRBool aNotify);
+
+ /**
+ * Add an element to the lookup table mainted by the form.
+ *
+ * We can't fold this method into AddElement() because when
+ * AddElement() is called, the form control has no
+ * attributes. The name or id attributes of the form control
+ * are used as a key into the table.
+ */
+ nsresult AddElementToTable(nsGenericHTMLFormElement* aChild,
+ const nsAString& aName);
+ /**
+ * Return whether there is one and only one input text control.
+ *
+ * @return Whether there is exactly one input text control.
+ */
+ PRBool HasSingleTextControl() const;
+
+ /**
+ * Check whether a given nsIFormControl is the default submit
+ * element. This is different from just comparing to
+ * GetDefaultSubmitElement() in certain situations inside an update
+ * when GetDefaultSubmitElement() might not be up to date. aControl
+ * is expected to not be null.
+ */
+ PRBool IsDefaultSubmitElement(const nsIFormControl* aControl) const;
+
+ /**
+ * Flag the form to know that a button or image triggered scripted form
+ * submission. In that case the form will defer the submission until the
+ * script handler returns and the return value is known.
+ */
+ void OnSubmitClickBegin();
+ void OnSubmitClickEnd();
+
+protected:
+ class RemoveElementRunnable;
+ friend class RemoveElementRunnable;
+
+ class RemoveElementRunnable : public nsRunnable {
+ public:
+ RemoveElementRunnable(nsHTMLFormElement* aForm, PRBool aNotify):
+ mForm(aForm), mNotify(aNotify)
+ {}
+
+ NS_IMETHOD Run() {
+ mForm->HandleDefaultSubmitRemoval(mNotify);
+ return NS_OK;
+ }
+
+ private:
+ nsRefPtr mForm;
+ PRBool mNotify;
+ };
+
+ nsresult DoSubmitOrReset(nsEvent* aEvent,
+ PRInt32 aMessage);
+ nsresult DoReset();
+
+ // Async callback to handle removal of our default submit
+ void HandleDefaultSubmitRemoval(PRBool aNotify);
+
+ //
+ // Submit Helpers
+ //
+ //
+ /**
+ * Attempt to submit (submission might be deferred)
+ * (called by DoSubmitOrReset)
+ *
+ * @param aPresContext the presentation context
+ * @param aEvent the DOM event that was passed to us for the submit
+ */
+ nsresult DoSubmit(nsEvent* aEvent);
+
+ /**
+ * Prepare the submission object (called by DoSubmit)
+ *
+ * @param aFormSubmission the submission object
+ * @param aEvent the DOM event that was passed to us for the submit
+ */
+ nsresult BuildSubmission(nsCOMPtr& aFormSubmission,
+ nsEvent* aEvent);
+ /**
+ * Perform the submission (called by DoSubmit and FlushPendingSubmission)
+ *
+ * @param aFormSubmission the submission object
+ */
+ nsresult SubmitSubmission(nsIFormSubmission* aFormSubmission);
+ /**
+ * Walk over the form elements and call SubmitNamesValues() on them to get
+ * their data pumped into the FormSubmitter.
+ *
+ * @param aFormSubmission the form submission object
+ * @param aSubmitElement the element that was clicked on (nsnull if none)
+ */
+ nsresult WalkFormElements(nsIFormSubmission* aFormSubmission,
+ nsIContent* aSubmitElement);
+
+ /**
+ * Notify any submit observers of the submit.
+ *
+ * @param aActionURL the URL being submitted to
+ * @param aCancelSubmit out param where submit observers can specify that the
+ * submit should be cancelled.
+ */
+ nsresult NotifySubmitObservers(nsIURI* aActionURL, PRBool* aCancelSubmit,
+ PRBool aEarlyNotify);
+
+ /**
+ * Just like ResolveName(), but takes an arg for whether to flush
+ */
+ already_AddRefed DoResolveName(const nsAString& aName, PRBool aFlushContent);
+
+ /**
+ * Get the full URL to submit to. Do not submit if the returned URL is null.
+ *
+ * @param aActionURL the full, unadulterated URL you'll be submitting to [OUT]
+ */
+ nsresult GetActionURL(nsIURI** aActionURL);
+
+public:
+ /**
+ * Flush a possible pending submission. If there was a scripted submission
+ * triggered by a button or image, the submission was defered. This method
+ * forces the pending submission to be submitted. (happens when the handler
+ * returns false or there is an action/target change in the script)
+ */
+ void FlushPendingSubmission();
+protected:
+ /**
+ * Forget a possible pending submission. Same as above but this time we
+ * get rid of the pending submission because the handler returned true
+ * so we will rebuild the submission with the name/value of the triggering
+ * element
+ */
+ void ForgetPendingSubmission();
+
+ //
+ // Data members
+ //
+ /** The list of controls (form.elements as well as stuff not in elements) */
+ nsRefPtr mControls;
+ /** The currently selected radio button of each group */
+ nsInterfaceHashtable mSelectedRadioButtons;
+ /** Whether we are currently processing a submit event or not */
+ PRPackedBool mGeneratingSubmit;
+ /** Whether we are currently processing a reset event or not */
+ PRPackedBool mGeneratingReset;
+ /** Whether we are submitting currently */
+ PRPackedBool mIsSubmitting;
+ /** Whether the submission is to be deferred in case a script triggers it */
+ PRPackedBool mDeferSubmission;
+ /** Whether we notified NS_FORMSUBMIT_SUBJECT listeners already */
+ PRPackedBool mNotifiedObservers;
+ /** If we notified the listeners early, what was the result? */
+ PRPackedBool mNotifiedObserversResult;
+ /** Keep track of what the popup state was when the submit was initiated */
+ PopupControlState mSubmitPopupState;
+ /** Keep track of whether a submission was user-initiated or not */
+ PRBool mSubmitInitiatedFromUserInput;
+
+ /** The pending submission object */
+ nsCOMPtr mPendingSubmission;
+ /** The request currently being submitted */
+ nsCOMPtr mSubmittingRequest;
+ /** The web progress object we are currently listening to */
+ nsWeakPtr mWebProgress;
+
+ /** The default submit element -- WEAK */
+ nsGenericHTMLFormElement* mDefaultSubmitElement;
+
+ /** The first submit element in mElements -- WEAK */
+ nsGenericHTMLFormElement* mFirstSubmitInElements;
+
+ /** The first submit element in mNotInElements -- WEAK */
+ nsGenericHTMLFormElement* mFirstSubmitNotInElements;
+
+protected:
+ /** Detection of first form to notify observers */
+ static PRBool gFirstFormSubmitted;
+ /** Detection of first password input to initialize the password manager */
+ static PRBool gPasswordManagerInitialized;
+};
diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp
index 6beb2e516b30..c85b98106caa 100644
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -115,6 +115,7 @@
#include "nsIDOMWindowInternal.h"
#include "mozAutoDocUpdate.h"
+#include "nsHTMLFormElement.h"
// XXX align=left, hspace, vspace, border? other nav4 attrs
@@ -1341,10 +1342,11 @@ nsHTMLInputElement::MaybeSubmitForm(nsPresContext* aPresContext)
shell->HandleDOMEventWithTarget(submitContent, &event, &status);
} else if (mForm->HasSingleTextControl()) {
// If there's only one text control, just submit the form
- nsCOMPtr form = do_QueryInterface(mForm);
+ // Hold strong ref across the event
+ nsRefPtr form(mForm);
nsFormEvent event(PR_TRUE, NS_FORM_SUBMIT);
nsEventStatus status = nsEventStatus_eIgnore;
- shell->HandleDOMEventWithTarget(form, &event, &status);
+ shell->HandleDOMEventWithTarget(mForm, &event, &status);
}
return NS_OK;
@@ -2050,8 +2052,9 @@ nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
// handling the event the pres context will return a null
// pres shell. See bug 125624.
if (presShell) {
- nsCOMPtr form(do_QueryInterface(mForm));
- presShell->HandleDOMEventWithTarget(form, &event, &status);
+ // Hold a strong ref while dispatching
+ nsRefPtr form(mForm);
+ presShell->HandleDOMEventWithTarget(mForm, &event, &status);
}
}
break;
diff --git a/content/html/content/src/nsHTMLSharedElement.cpp b/content/html/content/src/nsHTMLSharedElement.cpp
index e5c07438a9a1..76de6488c59c 100644
--- a/content/html/content/src/nsHTMLSharedElement.cpp
+++ b/content/html/content/src/nsHTMLSharedElement.cpp
@@ -48,6 +48,7 @@
#include "nsRuleData.h"
#include "nsMappedAttributes.h"
#include "nsNetUtil.h"
+#include "nsHTMLFormElement.h"
// XXX nav4 has type= start= (same as OL/UL)
extern nsAttrValue::EnumTable kListTypeTable[];
@@ -203,7 +204,7 @@ NS_IMPL_INT_ATTR(nsHTMLSharedElement, Size, size)
NS_IMETHODIMP
nsHTMLSharedElement::GetForm(nsIDOMHTMLFormElement** aForm)
{
- *aForm = FindForm().get();
+ NS_IF_ADDREF(*aForm = FindForm());
return NS_OK;
}
diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp
index c7434086aa84..57a59565250f 100644
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -9207,8 +9207,7 @@ nsHTMLFormElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
PRInt32 n = GetArrayIndexFromId(cx, id);
if (n >= 0) {
- nsCOMPtr control;
- form->GetElementAt(n, getter_AddRefs(control));
+ nsIFormControl* control = form->GetElementAt(n);
if (control) {
nsresult rv = WrapNative(cx, obj, control, PR_TRUE, vp);
@@ -9256,8 +9255,7 @@ nsHTMLFormElementSH::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
PRUint32 count = form->GetElementCount();
if ((PRUint32)index < count) {
- nsCOMPtr controlNode;
- form->GetElementAt(index, getter_AddRefs(controlNode));
+ nsIFormControl* controlNode = form->GetElementAt(index);
NS_ENSURE_TRUE(controlNode, NS_ERROR_FAILURE);
nsCOMPtr domElement = do_QueryInterface(controlNode);