Bug 1418085 part 3. Stop using nsIDOMHTMLElement in form fill. r=mystor
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 30 Jan 2018 00:25:36 -0500
changeset 401344 0ff82b4a39e1d27025b561375e69666b38fafde8
parent 401343 09cb8eececa79ea32be4605c61c291447b8ae986
child 401345 8f73def3b8165ae69b51c811548a3c9862e51cf9
push id99355
push userbzbarsky@mozilla.com
push dateTue, 30 Jan 2018 05:31:02 +0000
treeherdermozilla-inbound@09e8b8497618 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmystor
bugs1418085
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1418085 part 3. Stop using nsIDOMHTMLElement in form fill. r=mystor MozReview-Commit-ID: Ax7RUZQCosr
toolkit/components/satchel/nsFormFillController.cpp
toolkit/components/satchel/nsFormFillController.h
--- a/toolkit/components/satchel/nsFormFillController.cpp
+++ b/toolkit/components/satchel/nsFormFillController.cpp
@@ -35,16 +35,17 @@
 #include "nsIDOMHTMLFormElement.h"
 #include "nsILoginManager.h"
 #include "nsIDOMMouseEvent.h"
 #include "mozilla/ModuleUtils.h"
 #include "nsToolkitCompsCID.h"
 #include "nsEmbedCID.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsContentUtils.h"
+#include "nsGenericHTMLElement.h"
 #include "nsILoadContext.h"
 #include "nsIFrame.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsFocusManager.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using mozilla::ErrorResult;
@@ -88,17 +89,16 @@ NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFormFillController)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFormFillController)
 
 
 
 nsFormFillController::nsFormFillController() :
   mFocusedInput(nullptr),
-  mFocusedInputNode(nullptr),
   mListNode(nullptr),
   // The amount of time a context menu event supresses showing a
   // popup from a focus event in ms. This matches the threshold in
   // toolkit/components/passwordmgr/LoginManagerContent.jsm.
   mFocusAfterRightClickThreshold(400),
   mTimeout(50),
   mMinResultsForPopup(1),
   mMaxRows(0),
@@ -114,19 +114,18 @@ nsFormFillController::nsFormFillControll
 }
 
 nsFormFillController::~nsFormFillController()
 {
   if (mListNode) {
     mListNode->RemoveMutationObserver(this);
     mListNode = nullptr;
   }
-  if (mFocusedInputNode) {
-    MaybeRemoveMutationObserver(mFocusedInputNode);
-    mFocusedInputNode = nullptr;
+  if (mFocusedInput) {
+    MaybeRemoveMutationObserver(mFocusedInput);
     mFocusedInput = nullptr;
   }
   RemoveForDocument(nullptr);
 
   // Remove ourselves as a focus listener from all cached docShells
   uint32_t count = mDocShells.Length();
   for (uint32_t i = 0; i < count; ++i) {
     nsCOMPtr<nsPIDOMWindowOuter> window = GetWindowForDocShell(mDocShells[i]);
@@ -143,24 +142,24 @@ nsFormFillController::AttributeChanged(n
                                        mozilla::dom::Element* aElement,
                                        int32_t aNameSpaceID,
                                        nsAtom* aAttribute, int32_t aModType,
                                        const nsAttrValue* aOldValue)
 {
   if ((aAttribute == nsGkAtoms::type || aAttribute == nsGkAtoms::readonly ||
        aAttribute == nsGkAtoms::autocomplete) &&
       aNameSpaceID == kNameSpaceID_None) {
-    nsCOMPtr<nsIDOMHTMLInputElement> focusedInput(mFocusedInput);
+    RefPtr<HTMLInputElement> focusedInput(mFocusedInput);
     // Reset the current state of the controller, unconditionally.
     StopControllingInput();
     // Then restart based on the new values.  We have to delay this
     // to avoid ending up in an endless loop due to re-registering our
     // mutation observer (which would notify us again for *this* event).
     nsCOMPtr<nsIRunnable> event =
-      mozilla::NewRunnableMethod<nsCOMPtr<nsIDOMHTMLInputElement>>(
+      mozilla::NewRunnableMethod<RefPtr<HTMLInputElement>>(
         "nsFormFillController::MaybeStartControllingInput",
         this,
         &nsFormFillController::MaybeStartControllingInput,
         focusedInput);
     NS_DispatchToCurrentThread(event);
   }
 
   if (mListNode && mListNode->Contains(aElement)) {
@@ -238,18 +237,17 @@ void
 nsFormFillController::NodeWillBeDestroyed(const nsINode* aNode)
 {
   MOZ_LOG(sLogger, LogLevel::Verbose, ("NodeWillBeDestroyed: %p", aNode));
   mPwmgrInputs.Remove(aNode);
   mAutofillInputs.Remove(aNode);
   if (aNode == mListNode) {
     mListNode = nullptr;
     RevalidateDataList();
-  } else if (aNode == mFocusedInputNode) {
-    mFocusedInputNode = nullptr;
+  } else if (aNode == mFocusedInput) {
     mFocusedInput = nullptr;
   }
 }
 
 void
 nsFormFillController::MaybeRemoveMutationObserver(nsINode* aNode)
 {
   // Nodes being tracked in mPwmgrInputs will have their observers removed when
@@ -302,34 +300,33 @@ nsFormFillController::MarkAsLoginManager
 {
   /*
    * The Login Manager can supply autocomplete results for username fields,
    * when a user has multiple logins stored for a site. It uses this
    * interface to indicate that the form manager shouldn't handle the
    * autocomplete. The form manager also checks for this tag when saving
    * form history (so it doesn't save usernames).
    */
-  nsCOMPtr<nsINode> node = do_QueryInterface(aInput);
+  nsCOMPtr<nsIContent> node = do_QueryInterface(aInput);
   NS_ENSURE_STATE(node);
 
   // If the field was already marked, we don't want to show the popup again.
   if (mPwmgrInputs.Get(node)) {
     return NS_OK;
   }
 
   mPwmgrInputs.Put(node, true);
   node->AddMutationObserverUnlessExists(this);
 
   nsFocusManager *fm = nsFocusManager::GetFocusManager();
   if (fm) {
     nsCOMPtr<nsIContent> focusedContent = fm->GetFocusedContent();
-    if (SameCOMIdentity(focusedContent, node)) {
-      nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(node);
+    if (focusedContent == node) {
       if (!mFocusedInput) {
-        MaybeStartControllingInput(input);
+        MaybeStartControllingInput(HTMLInputElement::FromContent(node));
       }
     }
   }
 
   if (!mLoginManager) {
     mLoginManager = do_GetService("@mozilla.org/login-manager;1");
   }
 
@@ -338,17 +335,17 @@ nsFormFillController::MarkAsLoginManager
 
 NS_IMETHODIMP
 nsFormFillController::MarkAsAutofillField(nsIDOMHTMLInputElement *aInput)
 {
   /*
    * Support other components implementing form autofill and handle autocomplete
    * for the field.
    */
-  nsCOMPtr<nsINode> node = do_QueryInterface(aInput);
+  nsCOMPtr<nsIContent> node = do_QueryInterface(aInput);
   NS_ENSURE_STATE(node);
 
   MOZ_LOG(sLogger, LogLevel::Verbose,
           ("MarkAsAutofillField: aInput = %p, node = %p", aInput, node.get()));
 
   if (mAutofillInputs.Get(node)) {
     return NS_OK;
   }
@@ -357,27 +354,27 @@ nsFormFillController::MarkAsAutofillFiel
   node->AddMutationObserverUnlessExists(this);
 
   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(aInput);
   txtCtrl->EnablePreview();
 
   nsFocusManager *fm = nsFocusManager::GetFocusManager();
   if (fm) {
     nsCOMPtr<nsIContent> focusedContent = fm->GetFocusedContent();
-    if (SameCOMIdentity(focusedContent, node)) {
-      nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(node);
-      MaybeStartControllingInput(input);
+    if (focusedContent == node) {
+      MaybeStartControllingInput(HTMLInputElement::FromContent(node));
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsFormFillController::GetFocusedInput(nsIDOMHTMLInputElement **aInput) {
+nsFormFillController::GetFocusedInput(nsIDOMHTMLInputElement **aInput)
+{
   *aInput = mFocusedInput;
   NS_IF_ADDREF(*aInput);
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////
 //// nsIAutoCompleteInput
 
@@ -409,34 +406,33 @@ nsFormFillController::GetPopupOpen(bool 
 }
 
 NS_IMETHODIMP
 nsFormFillController::SetPopupOpen(bool aPopupOpen)
 {
   if (mFocusedPopup) {
     if (aPopupOpen) {
       // make sure input field is visible before showing popup (bug 320938)
-      nsCOMPtr<nsIContent> content = do_QueryInterface(mFocusedInput);
+      nsCOMPtr<nsIContent> content = mFocusedInput;
       NS_ENSURE_STATE(content);
       nsCOMPtr<nsIDocShell> docShell = GetDocShellForInput(mFocusedInput);
       NS_ENSURE_STATE(docShell);
       nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
       NS_ENSURE_STATE(presShell);
       presShell->ScrollContentIntoView(content,
                                        nsIPresShell::ScrollAxis(
                                          nsIPresShell::SCROLL_MINIMUM,
                                          nsIPresShell::SCROLL_IF_NOT_VISIBLE),
                                        nsIPresShell::ScrollAxis(
                                          nsIPresShell::SCROLL_MINIMUM,
                                          nsIPresShell::SCROLL_IF_NOT_VISIBLE),
                                        nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
       // mFocusedPopup can be destroyed after ScrollContentIntoView, see bug 420089
       if (mFocusedPopup) {
-        nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mFocusedInput);
-        mFocusedPopup->OpenAutocompletePopup(this, element);
+        mFocusedPopup->OpenAutocompletePopup(this, mFocusedInput);
       }
     } else {
       mFocusedPopup->ClosePopup();
     }
   }
 
   return NS_OK;
 }
@@ -572,34 +568,33 @@ nsFormFillController::GetSearchParam(nsA
 {
   if (!mFocusedInput) {
     NS_WARNING("mFocusedInput is null for some reason! avoiding a crash. should find out why... - ben");
     return NS_ERROR_FAILURE; // XXX why? fix me.
   }
 
   mFocusedInput->GetName(aSearchParam);
   if (aSearchParam.IsEmpty()) {
-    nsCOMPtr<Element> element = do_QueryInterface(mFocusedInput);
-    element->GetId(aSearchParam);
+    mFocusedInput->GetId(aSearchParam);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFormFillController::GetSearchCount(uint32_t *aSearchCount)
 {
   *aSearchCount = 1;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFormFillController::GetSearchAt(uint32_t index, nsACString & _retval)
 {
-  if (mAutofillInputs.Get(mFocusedInputNode)) {
+  if (mAutofillInputs.Get(mFocusedInput)) {
     MOZ_LOG(sLogger, LogLevel::Debug, ("GetSearchAt: autofill-profiles field"));
     nsCOMPtr<nsIAutoCompleteSearch> profileSearch = do_GetService("@mozilla.org/autocomplete/search;1?name=autofill-profiles");
     if (profileSearch) {
       _retval.AssignLiteral("autofill-profiles");
       return NS_OK;
     }
   }
 
@@ -607,80 +602,73 @@ nsFormFillController::GetSearchAt(uint32
   _retval.AssignLiteral("form-history");
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFormFillController::GetTextValue(nsAString & aTextValue)
 {
   if (mFocusedInput) {
-    nsCOMPtr<nsIContent> content = do_QueryInterface(mFocusedInput);
-    HTMLInputElement::FromContent(content)->GetValue(aTextValue,
-                                                     CallerType::System);
+    mFocusedInput->GetValue(aTextValue, CallerType::System);
   } else {
     aTextValue.Truncate();
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFormFillController::SetTextValue(const nsAString & aTextValue)
 {
-  nsCOMPtr<nsIDOMNSEditableElement> editable = do_QueryInterface(mFocusedInput);
-  if (editable) {
+  if (mFocusedInput) {
     mSuppressOnInput = true;
-    editable->SetUserInput(aTextValue);
+    mFocusedInput->SetUserInput(aTextValue);
     mSuppressOnInput = false;
   }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFormFillController::SetTextValueWithReason(const nsAString & aTextValue,
                                              uint16_t aReason)
 {
   return SetTextValue(aTextValue);
 }
 
 NS_IMETHODIMP
 nsFormFillController::GetSelectionStart(int32_t *aSelectionStart)
 {
-  nsCOMPtr<nsIContent> content = do_QueryInterface(mFocusedInput);
-  if (!content) {
+  if (!mFocusedInput) {
     return NS_ERROR_UNEXPECTED;
   }
   ErrorResult rv;
-  *aSelectionStart =
-    HTMLInputElement::FromContent(content)->GetSelectionStartIgnoringType(rv);
+  *aSelectionStart = mFocusedInput->GetSelectionStartIgnoringType(rv);
   return rv.StealNSResult();
 }
 
 NS_IMETHODIMP
 nsFormFillController::GetSelectionEnd(int32_t *aSelectionEnd)
 {
-  nsCOMPtr<nsIContent> content = do_QueryInterface(mFocusedInput);
-  if (!content) {
+  if (!mFocusedInput) {
     return NS_ERROR_UNEXPECTED;
   }
   ErrorResult rv;
-  *aSelectionEnd =
-    HTMLInputElement::FromContent(content)->GetSelectionEndIgnoringType(rv);
+  *aSelectionEnd = mFocusedInput->GetSelectionEndIgnoringType(rv);
   return rv.StealNSResult();
 }
 
 NS_IMETHODIMP
 nsFormFillController::SelectTextRange(int32_t aStartIndex, int32_t aEndIndex)
 {
-  nsCOMPtr<nsIContent> content = do_QueryInterface(mFocusedInput);
-    if (!content) {
+  if (!mFocusedInput) {
     return NS_ERROR_UNEXPECTED;
   }
   ErrorResult rv;
-  HTMLInputElement::FromContent(content)->
-    SetSelectionRange(aStartIndex, aEndIndex, Optional<nsAString>(), rv);
+  mFocusedInput->SetSelectionRange(aStartIndex, aEndIndex,
+                                   Optional<nsAString>(), rv);
   return rv.StealNSResult();
 }
 
 NS_IMETHODIMP
 nsFormFillController::OnSearchBegin()
 {
   return NS_OK;
 }
@@ -691,35 +679,33 @@ nsFormFillController::OnSearchComplete()
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFormFillController::OnTextEntered(nsIDOMEvent* aEvent,
                                     bool* aPrevent)
 {
   NS_ENSURE_ARG(aPrevent);
-  NS_ENSURE_TRUE(mFocusedInputNode, NS_OK);
+  NS_ENSURE_TRUE(mFocusedInput, NS_OK);
   // Fire off a DOMAutoComplete event
-  nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mFocusedInputNode->OwnerDoc());
+  nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mFocusedInput->OwnerDoc());
 
   nsCOMPtr<nsIDOMEvent> event;
   domDoc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
   NS_ENSURE_STATE(event);
 
   event->InitEvent(NS_LITERAL_STRING("DOMAutoComplete"), true, true);
 
   // XXXjst: We mark this event as a trusted event, it's up to the
   // callers of this to ensure that it's only called from trusted
   // code.
   event->SetTrusted(true);
 
-  nsCOMPtr<EventTarget> targ = do_QueryInterface(mFocusedInput);
-
   bool defaultActionEnabled;
-  targ->DispatchEvent(event, &defaultActionEnabled);
+  mFocusedInput->DispatchEvent(event, &defaultActionEnabled);
   *aPrevent = !defaultActionEnabled;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFormFillController::OnTextReverted(bool *_retval)
 {
   return NS_OK;
@@ -730,22 +716,22 @@ nsFormFillController::GetConsumeRollupEv
 {
   *aConsumeRollupEvent = false;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFormFillController::GetInPrivateContext(bool *aInPrivateContext)
 {
-  if (!mFocusedInputNode) {
+  if (!mFocusedInput) {
     *aInPrivateContext = false;
     return NS_OK;
   }
 
-  nsCOMPtr<nsIDocument> doc = mFocusedInputNode->OwnerDoc();
+  nsCOMPtr<nsIDocument> doc = mFocusedInput->OwnerDoc();
   nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
   *aInPrivateContext = loadContext && loadContext->UsePrivateBrowsing();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFormFillController::GetNoRollupOnCaretMove(bool *aNoRollupOnCaretMove)
 {
@@ -765,24 +751,23 @@ nsFormFillController::GetUserContextId(u
 
 NS_IMETHODIMP
 nsFormFillController::StartSearch(const nsAString &aSearchString, const nsAString &aSearchParam,
                                   nsIAutoCompleteResult *aPreviousResult, nsIAutoCompleteObserver *aListener)
 {
   MOZ_LOG(sLogger, LogLevel::Debug, ("StartSearch for %p", mFocusedInput));
 
   nsresult rv;
-  nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(mFocusedInputNode);
 
   // If the login manager has indicated it's responsible for this field, let it
   // handle the autocomplete. Otherwise, handle with form history.
   // This method is sometimes called in unit tests and from XUL without a focused node.
-  if (mFocusedInputNode &&
-      (mPwmgrInputs.Get(mFocusedInputNode) ||
-       formControl->ControlType() == NS_FORM_INPUT_PASSWORD)) {
+  if (mFocusedInput &&
+      (mPwmgrInputs.Get(mFocusedInput) ||
+       mFocusedInput->ControlType() == NS_FORM_INPUT_PASSWORD)) {
     MOZ_LOG(sLogger, LogLevel::Debug, ("StartSearch: login field"));
 
     // Handle the case where a password field is focused but
     // MarkAsLoginManagerField wasn't called because password manager is disabled.
     if (!mLoginManager) {
       mLoginManager = do_GetService("@mozilla.org/login-manager;1");
     }
 
@@ -826,42 +811,40 @@ nsFormFillController::StartSearch(const 
 
 nsresult
 nsFormFillController::PerformInputListAutoComplete(const nsAString& aSearch,
                                                    nsIAutoCompleteResult** aResult)
 {
   // If an <input> is focused, check if it has a list="<datalist>" which can
   // provide the list of suggestions.
 
-  MOZ_ASSERT(!mPwmgrInputs.Get(mFocusedInputNode));
+  MOZ_ASSERT(!mPwmgrInputs.Get(mFocusedInput));
   nsresult rv;
 
   nsCOMPtr <nsIInputListAutoComplete> inputListAutoComplete =
     do_GetService("@mozilla.org/satchel/inputlist-autocomplete;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = inputListAutoComplete->AutoCompleteSearch(aSearch,
                                                  mFocusedInput,
                                                  aResult);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (mFocusedInput) {
-    nsCOMPtr<nsIDOMHTMLElement> list;
-    mFocusedInput->GetList(getter_AddRefs(list));
+    Element* list = mFocusedInput->GetList();
 
     // Add a mutation observer to check for changes to the items in the <datalist>
     // and update the suggestions accordingly.
-    nsCOMPtr<nsINode> node = do_QueryInterface(list);
-    if (mListNode != node) {
+    if (mListNode != list) {
       if (mListNode) {
         mListNode->RemoveMutationObserver(this);
         mListNode = nullptr;
       }
-      if (node) {
-        node->AddMutationObserverUnlessExists(this);
-        mListNode = node;
+      if (list) {
+        list->AddMutationObserverUnlessExists(this);
+        mListNode = list;
       }
     }
   }
 
   return NS_OK;
 }
 
 void nsFormFillController::RevalidateDataList()
@@ -888,17 +871,17 @@ nsFormFillController::StopSearch()
     mLastFormAutoComplete = nullptr;
   } else if (mLoginManager) {
     mLoginManager->StopSearch();
   }
   return NS_OK;
 }
 
 nsresult
-nsFormFillController::StartQueryLoginReputation(nsIDOMHTMLInputElement *aInput)
+nsFormFillController::StartQueryLoginReputation(HTMLInputElement *aInput)
 {
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////
 //// nsIFormAutoCompleteObserver
 
 NS_IMETHODIMP
@@ -970,17 +953,17 @@ nsFormFillController::HandleEvent(nsIDOM
     {
       nsCOMPtr<nsIDocument> doc = do_QueryInterface(
         aEvent->InternalDOMEvent()->GetTarget());
       if (!doc) {
         return NS_OK;
       }
 
       if (mFocusedInput) {
-        if (doc == mFocusedInputNode->OwnerDoc()) {
+        if (doc == mFocusedInput->OwnerDoc()) {
           StopControllingInput();
         }
       }
 
       // Only remove the observer notifications and marked autofill and password
       // manager fields if the page isn't going to be persisted (i.e. it's being
       // unloaded) so that appropriate autocomplete handling works with bfcache.
       bool persisted = aEvent->InternalDOMEvent()->AsPageTransitionEvent()->Persisted();
@@ -1000,123 +983,113 @@ nsFormFillController::HandleEvent(nsIDOM
 
 void
 nsFormFillController::RemoveForDocument(nsIDocument* aDoc)
 {
   MOZ_LOG(sLogger, LogLevel::Verbose, ("RemoveForDocument: %p", aDoc));
   for (auto iter = mPwmgrInputs.Iter(); !iter.Done(); iter.Next()) {
     const nsINode* key = iter.Key();
     if (key && (!aDoc || key->OwnerDoc() == aDoc)) {
-      // mFocusedInputNode's observer is tracked separately, so don't remove it
+      // mFocusedInput's observer is tracked separately, so don't remove it
       // here.
-      if (key != mFocusedInputNode) {
+      if (key != mFocusedInput) {
         const_cast<nsINode*>(key)->RemoveMutationObserver(this);
       }
       iter.Remove();
     }
   }
 
   for (auto iter = mAutofillInputs.Iter(); !iter.Done(); iter.Next()) {
     const nsINode* key = iter.Key();
     if (key && (!aDoc || key->OwnerDoc() == aDoc)) {
-      // mFocusedInputNode's observer is tracked separately, so don't remove it
+      // mFocusedInput's observer is tracked separately, so don't remove it
       // here.
-      if (key != mFocusedInputNode) {
+      if (key != mFocusedInput) {
         const_cast<nsINode*>(key)->RemoveMutationObserver(this);
       }
       iter.Remove();
     }
   }
 }
 
 bool
 nsFormFillController::IsTextControl(nsINode* aNode)
 {
   nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(aNode);
   return formControl &&
          formControl->IsSingleLineTextControl(false);
 }
 
 void
-nsFormFillController::MaybeStartControllingInput(nsIDOMHTMLInputElement* aInput)
+nsFormFillController::MaybeStartControllingInput(HTMLInputElement* aInput)
 {
   MOZ_LOG(sLogger, LogLevel::Verbose, ("MaybeStartControllingInput for %p", aInput));
-  nsCOMPtr<nsINode> inputNode = do_QueryInterface(aInput);
-  if (!inputNode) {
+  if (!aInput) {
     return;
   }
 
-  if (!IsTextControl(inputNode)) {
+  if (!IsTextControl(aInput)) {
     return;
   }
 
-  bool isReadOnly = false;
-  aInput->GetReadOnly(&isReadOnly);
-  if (isReadOnly) {
+  if (aInput->ReadOnly()) {
     return;
   }
 
   bool autocomplete = nsContentUtils::IsAutocompleteEnabled(aInput);
 
-  nsCOMPtr<nsIDOMHTMLElement> datalist;
-  aInput->GetList(getter_AddRefs(datalist));
-  bool hasList = datalist != nullptr;
+  bool hasList = aInput->GetList() != nullptr;
 
   bool isPwmgrInput = false;
-  nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(aInput);
-  MOZ_ASSERT(formControl, "If we have a text control, we have a form control!");
-  if (mPwmgrInputs.Get(inputNode) ||
-      formControl->ControlType() == NS_FORM_INPUT_PASSWORD) {
+  if (mPwmgrInputs.Get(aInput) ||
+      aInput->ControlType() == NS_FORM_INPUT_PASSWORD) {
     isPwmgrInput = true;
   }
 
   bool isAutofillInput = false;
-  if (mAutofillInputs.Get(inputNode)) {
+  if (mAutofillInputs.Get(aInput)) {
     isAutofillInput = true;
   }
 
   if (isAutofillInput || isPwmgrInput ||  hasList || autocomplete) {
     StartControllingInput(aInput);
   }
 
 #ifdef NIGHTLY_BUILD
   // Trigger an asynchronous login reputation query when user focuses on the
   // password field.
-  if (formControl->ControlType() == NS_FORM_INPUT_PASSWORD) {
+  if (aInput->ControlType() == NS_FORM_INPUT_PASSWORD) {
     StartQueryLoginReputation(aInput);
   }
 #endif
 
 }
 
 nsresult
 nsFormFillController::Focus(nsIDOMEvent* aEvent)
 {
-  nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(
+  nsCOMPtr<nsIContent> input = do_QueryInterface(
     aEvent->InternalDOMEvent()->GetTarget());
-  MaybeStartControllingInput(input);
+  MaybeStartControllingInput(HTMLInputElement::FromContentOrNull(input));
 
   // Bail if we didn't start controlling the input.
-  if (!mFocusedInputNode) {
+  if (!mFocusedInput) {
     return NS_OK;
   }
 
 #ifndef ANDROID
-  nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(mFocusedInputNode);
-  MOZ_ASSERT(formControl);
-
   // If this focus doesn't follow a right click within our specified
   // threshold then show the autocomplete popup for all password fields.
   // This is done to avoid showing both the context menu and the popup
   // at the same time.
   // We use a timestamp instead of a bool to avoid complexity when dealing with
   // multiple input forms and the fact that a mousedown into an already focused
   // field does not trigger another focus.
 
-  if (formControl->ControlType() != NS_FORM_INPUT_PASSWORD) {
+  if (mFocusedInput->ControlType() != NS_FORM_INPUT_PASSWORD) {
     return NS_OK;
   }
 
   // If we have not seen a right click yet, just show the popup.
   if (mLastRightClickTimeStamp.IsNull()) {
     ShowPopup();
     return NS_OK;
   }
@@ -1186,19 +1159,18 @@ nsFormFillController::KeyPress(nsIDOMEve
   case nsIDOMKeyEvent::DOM_VK_UP:
   case nsIDOMKeyEvent::DOM_VK_DOWN:
   case nsIDOMKeyEvent::DOM_VK_LEFT:
   case nsIDOMKeyEvent::DOM_VK_RIGHT:
     {
       // Get the writing-mode of the relevant input element,
       // so that we can remap arrow keys if necessary.
       mozilla::WritingMode wm;
-      if (mFocusedInputNode && mFocusedInputNode->IsElement()) {
-        mozilla::dom::Element *elem = mFocusedInputNode->AsElement();
-        nsIFrame *frame = elem->GetPrimaryFrame();
+      if (mFocusedInput) {
+        nsIFrame *frame = mFocusedInput->GetPrimaryFrame();
         if (frame) {
           wm = frame->GetWritingMode();
         }
       }
       if (wm.IsVertical()) {
         switch (k) {
         case nsIDOMKeyEvent::DOM_VK_LEFT:
           k = wm.IsVerticalLR() ? nsIDOMKeyEvent::DOM_VK_UP
@@ -1376,51 +1348,45 @@ nsFormFillController::RemoveWindowListen
   target->RemoveEventListener(NS_LITERAL_STRING("compositionstart"), this,
                               true);
   target->RemoveEventListener(NS_LITERAL_STRING("compositionend"), this,
                               true);
   target->RemoveEventListener(NS_LITERAL_STRING("contextmenu"), this, true);
 }
 
 void
-nsFormFillController::StartControllingInput(nsIDOMHTMLInputElement *aInput)
+nsFormFillController::StartControllingInput(HTMLInputElement *aInput)
 {
   MOZ_LOG(sLogger, LogLevel::Verbose, ("StartControllingInput for %p", aInput));
   // Make sure we're not still attached to an input
   StopControllingInput();
 
   if (!mController) {
     return;
   }
 
   // Find the currently focused docShell
   nsCOMPtr<nsIDocShell> docShell = GetDocShellForInput(aInput);
   int32_t index = GetIndexOfDocShell(docShell);
   if (index < 0) {
     return;
   }
 
+  MOZ_ASSERT(aInput, "How did we get a docshell index??");
+
   // Cache the popup for the focused docShell
   mFocusedPopup = mPopups.SafeElementAt(index);
 
-  nsCOMPtr<nsINode> node = do_QueryInterface(aInput);
-  if (!node) {
-    return;
-  }
-
-  node->AddMutationObserverUnlessExists(this);
-  mFocusedInputNode = node;
+  aInput->AddMutationObserverUnlessExists(this);
   mFocusedInput = aInput;
 
-  nsCOMPtr<nsIDOMHTMLElement> list;
-  mFocusedInput->GetList(getter_AddRefs(list));
-  nsCOMPtr<nsINode> listNode = do_QueryInterface(list);
-  if (listNode) {
-    listNode->AddMutationObserverUnlessExists(this);
-    mListNode = listNode;
+  Element* list = mFocusedInput->GetList();
+  if (list) {
+    list->AddMutationObserverUnlessExists(this);
+    mListNode = list;
   }
 
   mController->SetInput(this);
 }
 
 void
 nsFormFillController::StopControllingInput()
 {
@@ -1439,36 +1405,34 @@ nsFormFillController::StopControllingInp
       MOZ_LOG(sLogger, LogLevel::Verbose,
               ("StopControllingInput: Nulled controller input for %p", this));
       mController->SetInput(nullptr);
     }
   }
 
   MOZ_LOG(sLogger, LogLevel::Verbose,
           ("StopControllingInput: Stopped controlling %p", mFocusedInput));
-  if (mFocusedInputNode) {
-    MaybeRemoveMutationObserver(mFocusedInputNode);
+  if (mFocusedInput) {
+    MaybeRemoveMutationObserver(mFocusedInput);
 
-    mFocusedInputNode = nullptr;
     mFocusedInput = nullptr;
   }
 
   if (mFocusedPopup) {
     mFocusedPopup->ClosePopup();
   }
   mFocusedPopup = nullptr;
 }
 
 nsIDocShell *
-nsFormFillController::GetDocShellForInput(nsIDOMHTMLInputElement *aInput)
+nsFormFillController::GetDocShellForInput(HTMLInputElement *aInput)
 {
-  nsCOMPtr<nsINode> node = do_QueryInterface(aInput);
-  NS_ENSURE_TRUE(node, nullptr);
+  NS_ENSURE_TRUE(aInput, nullptr);
 
-  nsCOMPtr<nsPIDOMWindowOuter> win = node->OwnerDoc()->GetWindow();
+  nsCOMPtr<nsPIDOMWindowOuter> win = aInput->OwnerDoc()->GetWindow();
   NS_ENSURE_TRUE(win, nullptr);
 
   return win->GetDocShell();
 }
 
 nsPIDOMWindowOuter*
 nsFormFillController::GetWindowForDocShell(nsIDocShell *aDocShell)
 {
--- a/toolkit/components/satchel/nsFormFillController.h
+++ b/toolkit/components/satchel/nsFormFillController.h
@@ -11,32 +11,37 @@
 #include "nsIAutoCompleteSearch.h"
 #include "nsIAutoCompleteController.h"
 #include "nsIAutoCompletePopup.h"
 #include "nsIFormAutoComplete.h"
 #include "nsIDOMEventListener.h"
 #include "nsCOMPtr.h"
 #include "nsDataHashtable.h"
 #include "nsIDocShell.h"
-#include "nsIDOMHTMLInputElement.h"
 #include "nsILoginManager.h"
 #include "nsIMutationObserver.h"
 #include "nsTArray.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsILoginReputation.h"
 
 // X.h defines KeyPress
 #ifdef KeyPress
 #undef KeyPress
 #endif
 
 class nsFormHistory;
 class nsINode;
 class nsPIDOMWindowOuter;
 
+namespace mozilla {
+namespace dom {
+class HTMLInputElement;
+} // namespace dom
+} // namespace mozilla
+
 class nsFormFillController final : public nsIFormFillController,
                                    public nsIAutoCompleteInput,
                                    public nsIAutoCompleteSearch,
                                    public nsIDOMEventListener,
                                    public nsIFormAutoCompleteObserver,
                                    public nsIMutationObserver
 {
 public:
@@ -60,50 +65,49 @@ protected:
   virtual ~nsFormFillController();
 
   void AddWindowListeners(nsPIDOMWindowOuter* aWindow);
   void RemoveWindowListeners(nsPIDOMWindowOuter* aWindow);
 
   void AddKeyListener(nsINode* aInput);
   void RemoveKeyListener();
 
-  void StartControllingInput(nsIDOMHTMLInputElement *aInput);
+  void StartControllingInput(mozilla::dom::HTMLInputElement *aInput);
   void StopControllingInput();
   /**
    * Checks that aElement is a type of element we want to fill, then calls
    * StartControllingInput on it.
    */
-  void MaybeStartControllingInput(nsIDOMHTMLInputElement* aElement);
+  void MaybeStartControllingInput(mozilla::dom::HTMLInputElement* aElement);
 
   nsresult PerformInputListAutoComplete(const nsAString& aSearch,
                                         nsIAutoCompleteResult** aResult);
 
   void RevalidateDataList();
   bool RowMatch(nsFormHistory *aHistory, uint32_t aIndex, const nsAString &aInputName, const nsAString &aInputValue);
 
-  inline nsIDocShell *GetDocShellForInput(nsIDOMHTMLInputElement *aInput);
+  inline nsIDocShell *GetDocShellForInput(mozilla::dom::HTMLInputElement *aInput);
   inline nsPIDOMWindowOuter *GetWindowForDocShell(nsIDocShell *aDocShell);
   inline int32_t GetIndexOfDocShell(nsIDocShell *aDocShell);
 
   void MaybeRemoveMutationObserver(nsINode* aNode);
 
   void RemoveForDocument(nsIDocument* aDoc);
   bool IsEventTrusted(nsIDOMEvent *aEvent);
 
   bool IsTextControl(nsINode* aNode);
 
-  nsresult StartQueryLoginReputation(nsIDOMHTMLInputElement *aInput);
+  nsresult StartQueryLoginReputation(mozilla::dom::HTMLInputElement *aInput);
 
   // members //////////////////////////////////////////
 
   nsCOMPtr<nsIAutoCompleteController> mController;
   nsCOMPtr<nsILoginManager> mLoginManager;
   nsCOMPtr<nsILoginReputationService> mLoginReputationService;
-  nsIDOMHTMLInputElement* mFocusedInput;
-  nsINode* mFocusedInputNode;
+  mozilla::dom::HTMLInputElement* mFocusedInput;
 
   // mListNode is a <datalist> element which, is set, has the form fill controller
   // as a mutation observer for it.
   nsINode* mListNode;
   nsCOMPtr<nsIAutoCompletePopup> mFocusedPopup;
 
   nsTArray<nsCOMPtr<nsIDocShell> > mDocShells;
   nsTArray<nsCOMPtr<nsIAutoCompletePopup> > mPopups;