Bug 1492326, use Element helper methods in accessibility instead of QueryInterface to get interface implementations that might be implemented by custom elements, r=surkov
authorNeil Deakin <neil@mozilla.com>
Tue, 04 Dec 2018 11:32:15 -0500
changeset 449691 8837771de85a7e82d98e83ffdd6b2105d2beb7e1
parent 449690 f69b2af6280a1a7c75b570cdc75c59d2be0a9b6a
child 449692 ce5c9d031921b17c3c1dde4a1d97119d753daa37
push id110417
push userneil@mozilla.com
push dateMon, 10 Dec 2018 16:25:38 +0000
treeherdermozilla-inbound@0c7a54d4cc42 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssurkov
bugs1492326
milestone65.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 1492326, use Element helper methods in accessibility instead of QueryInterface to get interface implementations that might be implemented by custom elements, r=surkov
accessible/base/nsAccUtils.cpp
accessible/generic/Accessible.cpp
accessible/generic/RootAccessible.cpp
accessible/xul/XULComboboxAccessible.cpp
accessible/xul/XULFormControlAccessible.cpp
accessible/xul/XULListboxAccessible.cpp
accessible/xul/XULMenuAccessible.cpp
accessible/xul/XULSelectControlAccessible.cpp
accessible/xul/XULSelectControlAccessible.h
accessible/xul/XULTabAccessible.cpp
accessible/xul/XULTreeAccessible.cpp
browser/base/content/browser.js
--- a/accessible/base/nsAccUtils.cpp
+++ b/accessible/base/nsAccUtils.cpp
@@ -87,32 +87,33 @@ int32_t nsAccUtils::GetARIAOrDefaultLeve
                            &level);
 
   if (level != 0) return level;
 
   return GetDefaultLevel(aAccessible);
 }
 
 int32_t nsAccUtils::GetLevelForXULContainerItem(nsIContent* aContent) {
-  nsCOMPtr<nsIDOMXULContainerItemElement> item(do_QueryInterface(aContent));
+  nsCOMPtr<nsIDOMXULContainerItemElement> item =
+      aContent->AsElement()->AsXULContainerItem();
   if (!item) return 0;
 
   nsCOMPtr<Element> containerElement;
   item->GetParentContainer(getter_AddRefs(containerElement));
   nsCOMPtr<nsIDOMXULContainerElement> container =
-      do_QueryInterface(containerElement);
+      containerElement ? containerElement->AsXULContainer() : nullptr;
   if (!container) return 0;
 
   // Get level of the item.
   int32_t level = -1;
   while (container) {
     level++;
 
     container->GetParentContainer(getter_AddRefs(containerElement));
-    container = do_QueryInterface(containerElement);
+    container = containerElement ? containerElement->AsXULContainer() : nullptr;
   }
 
   return level;
 }
 
 void nsAccUtils::SetLiveContainerAttributes(
     nsIPersistentProperties* aAttributes, nsIContent* aStartContent,
     dom::Element* aTopEl) {
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -729,23 +729,25 @@ void Accessible::XULElmName(DocAccessibl
    *        - label has either value="foo" or children
    * Once a label is found, the search is discontinued, so a control
    *  that has a label child as well as having a label external to
    *  the control that uses the control="controlID" syntax will use
    *  the child label for its Name.
    */
 
   // CASE #1 (via label attribute) -- great majority of the cases
-  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemEl = do_QueryInterface(aElm);
+  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemEl =
+      aElm->AsElement()->AsXULSelectControlItem();
   if (itemEl) {
     itemEl->GetLabel(aName);
   } else {
     // Use @label if this is not a select control element, which uses label
     // attribute to indicate, which option is selected.
-    nsCOMPtr<nsIDOMXULSelectControlElement> select = do_QueryInterface(aElm);
+    nsCOMPtr<nsIDOMXULSelectControlElement> select =
+        aElm->AsElement()->AsXULSelectControl();
     if (!select) {
       aElm->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
     }
   }
 
   // CASES #2 and #3 ------ label as a child or <label control="id" ... >
   // </label>
   if (aName.IsEmpty()) {
@@ -1668,40 +1670,51 @@ Relation Accessible::RelationByType(Rela
             nsCOMPtr<nsIContent> formContent =
                 do_QueryInterface(form->GetDefaultSubmitElement());
             return Relation(mDoc, formContent);
           }
         }
       } else {
         // In XUL, use first <button default="true" .../> in the document
         nsIDocument* doc = mContent->OwnerDoc();
-        nsCOMPtr<nsIDOMXULButtonElement> buttonEl;
+        nsIContent* buttonEl = nullptr;
         if (doc->IsXULDocument()) {
           dom::XULDocument* xulDoc = doc->AsXULDocument();
           nsCOMPtr<nsIHTMLCollection> possibleDefaultButtons =
               xulDoc->GetElementsByAttribute(NS_LITERAL_STRING("default"),
                                              NS_LITERAL_STRING("true"));
           if (possibleDefaultButtons) {
             uint32_t length = possibleDefaultButtons->Length();
             // Check for button in list of default="true" elements
             for (uint32_t count = 0; count < length && !buttonEl; count++) {
-              buttonEl = do_QueryInterface(possibleDefaultButtons->Item(count));
+              nsIContent* item = possibleDefaultButtons->Item(count);
+              RefPtr<nsIDOMXULButtonElement> button =
+                  item->IsElement() ? item->AsElement()->AsXULButton()
+                                    : nullptr;
+              if (button) {
+                buttonEl = item;
+              }
             }
           }
           if (!buttonEl) {  // Check for anonymous accept button in <dialog>
             dom::Element* rootElm = mContent->OwnerDoc()->GetRootElement();
             if (rootElm) {
               nsIContent* possibleButtonEl =
                   rootElm->OwnerDoc()->GetAnonymousElementByAttribute(
                       rootElm, nsGkAtoms::_default, NS_LITERAL_STRING("true"));
-              buttonEl = do_QueryInterface(possibleButtonEl);
+              if (possibleButtonEl && possibleButtonEl->IsElement()) {
+                RefPtr<nsIDOMXULButtonElement> button =
+                    possibleButtonEl->AsElement()->AsXULButton();
+                if (button) {
+                  buttonEl = possibleButtonEl;
+                }
+              }
             }
           }
-          nsCOMPtr<nsIContent> relatedContent(do_QueryInterface(buttonEl));
-          return Relation(mDoc, relatedContent);
+          return Relation(mDoc, buttonEl);
         }
       }
       return Relation();
     }
 
     case RelationType::CONTAINING_DOCUMENT:
       return Relation(mDoc);
 
--- a/accessible/generic/RootAccessible.cpp
+++ b/accessible/generic/RootAccessible.cpp
@@ -332,17 +332,17 @@ void RootAccessible::ProcessDOMEvent(Eve
 
   nsINode* targetNode = accessible->GetNode();
   if (treeItemAcc && eventType.EqualsLiteral("select")) {
     // XXX: We shouldn't be based on DOM select event which doesn't provide us
     // any context info. We should integrate into nsTreeSelection instead.
     // If multiselect tree, we should fire selectionadd or selection removed
     if (FocusMgr()->HasDOMFocus(targetNode)) {
       nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSel =
-          do_QueryInterface(targetNode);
+          targetNode->AsElement()->AsXULMultiSelectControl();
       nsAutoString selType;
       multiSel->GetSelType(selType);
       if (selType.IsEmpty() || !selType.EqualsLiteral("single")) {
         // XXX: We need to fire EVENT_SELECTION_ADD and EVENT_SELECTION_REMOVE
         // for each tree item. Perhaps each tree item will need to cache its
         // selection state and fire an event after a DOM "select" event when
         // that state changes. XULTreeAccessible::UpdateTreeSelection();
         nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_SELECTION_WITHIN,
--- a/accessible/xul/XULComboboxAccessible.cpp
+++ b/accessible/xul/XULComboboxAccessible.cpp
@@ -49,74 +49,74 @@ uint64_t XULComboboxAccessible::NativeSt
   //     STATE_FOCUSABLE
   //     STATE_HASPOPUP
   //     STATE_EXPANDED
   //     STATE_COLLAPSED
 
   // Get focus status from base class
   uint64_t state = Accessible::NativeState();
 
-  nsCOMPtr<nsIDOMXULMenuListElement> menuList(do_QueryInterface(mContent));
+  nsCOMPtr<nsIDOMXULMenuListElement> menuList = Elm()->AsXULMenuList();
   if (menuList) {
     bool isOpen = false;
     menuList->GetOpen(&isOpen);
     if (isOpen)
       state |= states::EXPANDED;
     else
       state |= states::COLLAPSED;
   }
 
   return state | states::HASPOPUP;
 }
 
 void XULComboboxAccessible::Description(nsString& aDescription) {
   aDescription.Truncate();
   // Use description of currently focused option
-  nsCOMPtr<nsIDOMXULMenuListElement> menuListElm(do_QueryInterface(mContent));
+  nsCOMPtr<nsIDOMXULMenuListElement> menuListElm = Elm()->AsXULMenuList();
   if (!menuListElm) return;
 
   nsCOMPtr<Element> focusedOptionItem;
   menuListElm->GetSelectedItem(getter_AddRefs(focusedOptionItem));
   if (focusedOptionItem && mDoc) {
     Accessible* focusedOptionAcc = mDoc->GetAccessible(focusedOptionItem);
     if (focusedOptionAcc) focusedOptionAcc->Description(aDescription);
   }
 }
 
 void XULComboboxAccessible::Value(nsString& aValue) const {
   aValue.Truncate();
 
   // The value is the option or text shown entered in the combobox.
-  nsCOMPtr<nsIDOMXULMenuListElement> menuList(do_QueryInterface(mContent));
+  nsCOMPtr<nsIDOMXULMenuListElement> menuList = Elm()->AsXULMenuList();
   if (menuList) menuList->GetLabel(aValue);
 }
 
 uint8_t XULComboboxAccessible::ActionCount() const {
   // Just one action (click).
   return 1;
 }
 
 bool XULComboboxAccessible::DoAction(uint8_t aIndex) const {
   if (aIndex != XULComboboxAccessible::eAction_Click) return false;
 
   // Programmaticaly toggle the combo box.
-  nsCOMPtr<nsIDOMXULMenuListElement> menuList(do_QueryInterface(mContent));
+  nsCOMPtr<nsIDOMXULMenuListElement> menuList = Elm()->AsXULMenuList();
   if (!menuList) return false;
 
   bool isDroppedDown = false;
   menuList->GetOpen(&isDroppedDown);
   menuList->SetOpen(!isDroppedDown);
   return true;
 }
 
 void XULComboboxAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName) {
   aName.Truncate();
   if (aIndex != XULComboboxAccessible::eAction_Click) return;
 
-  nsCOMPtr<nsIDOMXULMenuListElement> menuList(do_QueryInterface(mContent));
+  nsCOMPtr<nsIDOMXULMenuListElement> menuList = Elm()->AsXULMenuList();
   if (!menuList) return;
 
   bool isDroppedDown = false;
   menuList->GetOpen(&isDroppedDown);
   if (isDroppedDown)
     aName.AssignLiteral("close");
   else
     aName.AssignLiteral("open");
@@ -148,17 +148,17 @@ bool XULComboboxAccessible::AreItemsOper
     if (autoCompleteInputElm) {
       bool isOpen = false;
       autoCompleteInputElm->GetPopupOpen(&isOpen);
       return isOpen;
     }
     return false;
   }
 
-  nsCOMPtr<nsIDOMXULMenuListElement> menuListElm = do_QueryInterface(mContent);
+  nsCOMPtr<nsIDOMXULMenuListElement> menuListElm = Elm()->AsXULMenuList();
   if (menuListElm) {
     bool isOpen = false;
     menuListElm->GetOpen(&isOpen);
     return isOpen;
   }
 
   return false;
 }
--- a/accessible/xul/XULFormControlAccessible.cpp
+++ b/accessible/xul/XULFormControlAccessible.cpp
@@ -70,18 +70,17 @@ role XULButtonAccessible::NativeRole() c
 
 uint64_t XULButtonAccessible::NativeState() const {
   // Possible states: focused, focusable, unavailable(disabled).
 
   // get focus and disable status from base class
   uint64_t state = Accessible::NativeState();
 
   // Buttons can be checked -- they simply appear pressed in rather than checked
-  nsCOMPtr<nsIDOMXULButtonElement> xulButtonElement(
-      do_QueryInterface(mContent));
+  nsCOMPtr<nsIDOMXULButtonElement> xulButtonElement = Elm()->AsXULButton();
   if (xulButtonElement) {
     nsAutoString type;
     xulButtonElement->GetType(type);
     if (type.EqualsLiteral("checkbox") || type.EqualsLiteral("radio")) {
       state |= states::CHECKABLE;
     }
     // Some buttons can have their checked state set without being of type
     // checkbox or radio. Expose the pressed state unconditionally.
@@ -152,25 +151,25 @@ uint8_t XULDropmarkerAccessible::ActionC
 
 bool XULDropmarkerAccessible::DropmarkerOpen(bool aToggleOpen) const {
   bool isOpen = false;
 
   nsIContent* parent = mContent->GetFlattenedTreeParent();
 
   while (parent) {
     nsCOMPtr<nsIDOMXULButtonElement> parentButtonElement =
-        do_QueryInterface(parent);
+        parent->AsElement()->AsXULButton();
     if (parentButtonElement) {
       parentButtonElement->GetOpen(&isOpen);
       if (aToggleOpen) parentButtonElement->SetOpen(!isOpen);
       return isOpen;
     }
 
     nsCOMPtr<nsIDOMXULMenuListElement> parentMenuListElement =
-        do_QueryInterface(parent);
+        parent->AsElement()->AsXULMenuList();
     if (parentMenuListElement) {
       parentMenuListElement->GetOpen(&isOpen);
       if (aToggleOpen) parentMenuListElement->SetOpen(!isOpen);
       return isOpen;
     }
     parent = parent->GetFlattenedTreeParent();
   }
 
@@ -242,17 +241,17 @@ XULRadioButtonAccessible::XULRadioButton
                                                    DocAccessible* aDoc)
     : RadioButtonAccessible(aContent, aDoc) {}
 
 uint64_t XULRadioButtonAccessible::NativeState() const {
   uint64_t state = LeafAccessible::NativeState();
   state |= states::CHECKABLE;
 
   nsCOMPtr<nsIDOMXULSelectControlItemElement> radioButton =
-      do_QueryInterface(mContent);
+      Elm()->AsXULSelectControlItem();
   if (radioButton) {
     bool selected = false;  // Radio buttons can be selected
     radioButton->GetSelected(&selected);
     if (selected) {
       state |= states::CHECKED;
     }
   }
 
--- a/accessible/xul/XULListboxAccessible.cpp
+++ b/accessible/xul/XULListboxAccessible.cpp
@@ -101,23 +101,23 @@ uint64_t XULListboxAccessible::NativeSta
 }
 
 /**
  * Our value is the label of our ( first ) selected child.
  */
 void XULListboxAccessible::Value(nsString& aValue) const {
   aValue.Truncate();
 
-  nsCOMPtr<nsIDOMXULSelectControlElement> select(do_QueryInterface(mContent));
+  nsCOMPtr<nsIDOMXULSelectControlElement> select = Elm()->AsXULSelectControl();
   if (select) {
     RefPtr<Element> element;
     select->GetSelectedItem(getter_AddRefs(element));
 
     nsCOMPtr<nsIDOMXULSelectControlItemElement> selectedItem =
-        do_QueryInterface(element);
+        element->AsXULSelectControlItem();
     if (selectedItem) selectedItem->GetLabel(aValue);
   }
 }
 
 role XULListboxAccessible::NativeRole() const {
   // A richlistbox is used with the new autocomplete URL bar, and has a parent
   // popup <panel>.
   if (mContent->GetParent() &&
@@ -128,118 +128,119 @@ role XULListboxAccessible::NativeRole() 
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULListboxAccessible: Table
 
 uint32_t XULListboxAccessible::ColCount() const { return 0; }
 
 uint32_t XULListboxAccessible::RowCount() {
-  nsCOMPtr<nsIDOMXULSelectControlElement> element(do_QueryInterface(mContent));
+  nsCOMPtr<nsIDOMXULSelectControlElement> element = Elm()->AsXULSelectControl();
 
   uint32_t itemCount = 0;
   if (element) element->GetItemCount(&itemCount);
 
   return itemCount;
 }
 
 Accessible* XULListboxAccessible::CellAt(uint32_t aRowIndex,
                                          uint32_t aColumnIndex) {
-  nsCOMPtr<nsIDOMXULSelectControlElement> control = do_QueryInterface(mContent);
+  nsCOMPtr<nsIDOMXULSelectControlElement> control = Elm()->AsXULSelectControl();
   NS_ENSURE_TRUE(control, nullptr);
 
   RefPtr<Element> element;
   control->GetItemAtIndex(aRowIndex, getter_AddRefs(element));
   if (!element) return nullptr;
 
   Accessible* row = mDoc->GetAccessible(element);
   NS_ENSURE_TRUE(row, nullptr);
 
   return row->GetChildAt(aColumnIndex);
 }
 
 bool XULListboxAccessible::IsColSelected(uint32_t aColIdx) {
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
-      do_QueryInterface(mContent);
+      Elm()->AsXULMultiSelectControl();
   NS_ASSERTION(control,
                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
 
   int32_t selectedrowCount = 0;
   nsresult rv = control->GetSelectedCount(&selectedrowCount);
   NS_ENSURE_SUCCESS(rv, false);
 
   return selectedrowCount == static_cast<int32_t>(RowCount());
 }
 
 bool XULListboxAccessible::IsRowSelected(uint32_t aRowIdx) {
-  nsCOMPtr<nsIDOMXULSelectControlElement> control = do_QueryInterface(mContent);
+  nsCOMPtr<nsIDOMXULSelectControlElement> control = Elm()->AsXULSelectControl();
   NS_ASSERTION(control, "Doesn't implement nsIDOMXULSelectControlElement.");
 
   RefPtr<Element> element;
   nsresult rv = control->GetItemAtIndex(aRowIdx, getter_AddRefs(element));
   NS_ENSURE_SUCCESS(rv, false);
 
-  nsCOMPtr<nsIDOMXULSelectControlItemElement> item = do_QueryInterface(element);
+  nsCOMPtr<nsIDOMXULSelectControlItemElement> item =
+      element->AsXULSelectControlItem();
 
   bool isSelected = false;
   item->GetSelected(&isSelected);
   return isSelected;
 }
 
 bool XULListboxAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx) {
   return IsRowSelected(aRowIdx);
 }
 
 uint32_t XULListboxAccessible::SelectedCellCount() {
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
-      do_QueryInterface(mContent);
+      Elm()->AsXULMultiSelectControl();
   NS_ASSERTION(control,
                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
 
   nsCOMPtr<nsINodeList> selectedItems;
   control->GetSelectedItems(getter_AddRefs(selectedItems));
   if (!selectedItems) return 0;
 
   uint32_t selectedItemsCount = selectedItems->Length();
 
   return selectedItemsCount * ColCount();
 }
 
 uint32_t XULListboxAccessible::SelectedColCount() {
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
-      do_QueryInterface(mContent);
+      Elm()->AsXULMultiSelectControl();
   NS_ASSERTION(control,
                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
 
   int32_t selectedRowCount = 0;
   nsresult rv = control->GetSelectedCount(&selectedRowCount);
   NS_ENSURE_SUCCESS(rv, 0);
 
   return selectedRowCount > 0 &&
                  selectedRowCount == static_cast<int32_t>(RowCount())
              ? ColCount()
              : 0;
 }
 
 uint32_t XULListboxAccessible::SelectedRowCount() {
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
-      do_QueryInterface(mContent);
+      Elm()->AsXULMultiSelectControl();
   NS_ASSERTION(control,
                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
 
   int32_t selectedRowCount = 0;
   nsresult rv = control->GetSelectedCount(&selectedRowCount);
   NS_ENSURE_SUCCESS(rv, 0);
 
   return selectedRowCount >= 0 ? selectedRowCount : 0;
 }
 
 void XULListboxAccessible::SelectedCells(nsTArray<Accessible*>* aCells) {
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
-      do_QueryInterface(mContent);
+      Elm()->AsXULMultiSelectControl();
   NS_ASSERTION(control,
                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
 
   nsCOMPtr<nsINodeList> selectedItems;
   control->GetSelectedItems(getter_AddRefs(selectedItems));
   if (!selectedItems) return;
 
   uint32_t selectedItemsCount = selectedItems->Length();
@@ -255,36 +256,36 @@ void XULListboxAccessible::SelectedCells
         if (cell->Role() == roles::CELL) aCells->AppendElement(cell);
       }
     }
   }
 }
 
 void XULListboxAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells) {
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
-      do_QueryInterface(mContent);
+      Elm()->AsXULMultiSelectControl();
   NS_ASSERTION(control,
                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
 
   nsCOMPtr<nsINodeList> selectedItems;
   control->GetSelectedItems(getter_AddRefs(selectedItems));
   if (!selectedItems) return;
 
   uint32_t selectedItemsCount = selectedItems->Length();
 
   uint32_t colCount = ColCount();
   aCells->SetCapacity(selectedItemsCount * colCount);
   aCells->AppendElements(selectedItemsCount * colCount);
 
   for (uint32_t selItemsIdx = 0, cellsIdx = 0; selItemsIdx < selectedItemsCount;
        selItemsIdx++) {
     nsIContent* itemContent = selectedItems->Item(selItemsIdx);
+
     nsCOMPtr<nsIDOMXULSelectControlItemElement> item =
-        do_QueryInterface(itemContent);
-
+        itemContent->AsElement()->AsXULSelectControlItem();
     if (item) {
       int32_t itemIdx = -1;
       control->GetIndexOfItem(item, &itemIdx);
       if (itemIdx >= 0)
         for (uint32_t colIdx = 0; colIdx < colCount; colIdx++, cellsIdx++)
           aCells->ElementAt(cellsIdx) = itemIdx * colCount + colIdx;
     }
   }
@@ -295,17 +296,17 @@ void XULListboxAccessible::SelectedColIn
   aCols->SetCapacity(selColCount);
 
   for (uint32_t colIdx = 0; colIdx < selColCount; colIdx++)
     aCols->AppendElement(colIdx);
 }
 
 void XULListboxAccessible::SelectedRowIndices(nsTArray<uint32_t>* aRows) {
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
-      do_QueryInterface(mContent);
+      Elm()->AsXULMultiSelectControl();
   NS_ASSERTION(control,
                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
 
   nsCOMPtr<nsINodeList> selectedItems;
   control->GetSelectedItems(getter_AddRefs(selectedItems));
   if (!selectedItems) return;
 
   uint32_t rowCount = selectedItems->Length();
@@ -313,49 +314,51 @@ void XULListboxAccessible::SelectedRowIn
   if (!rowCount) return;
 
   aRows->SetCapacity(rowCount);
   aRows->AppendElements(rowCount);
 
   for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++) {
     nsIContent* itemContent = selectedItems->Item(rowIdx);
     nsCOMPtr<nsIDOMXULSelectControlItemElement> item =
-        do_QueryInterface(itemContent);
+        itemContent->AsElement()->AsXULSelectControlItem();
 
     if (item) {
       int32_t itemIdx = -1;
       control->GetIndexOfItem(item, &itemIdx);
       if (itemIdx >= 0) aRows->ElementAt(rowIdx) = itemIdx;
     }
   }
 }
 
 void XULListboxAccessible::SelectRow(uint32_t aRowIdx) {
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
-      do_QueryInterface(mContent);
+      Elm()->AsXULMultiSelectControl();
   NS_ASSERTION(control,
                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
 
   RefPtr<Element> item;
   control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
 
-  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm = do_QueryInterface(item);
+  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
+      item->AsXULSelectControlItem();
   control->SelectItem(itemElm);
 }
 
 void XULListboxAccessible::UnselectRow(uint32_t aRowIdx) {
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
-      do_QueryInterface(mContent);
+      Elm()->AsXULMultiSelectControl();
   NS_ASSERTION(control,
                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
 
   RefPtr<Element> item;
   control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
 
-  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm = do_QueryInterface(item);
+  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
+      item->AsXULSelectControlItem();
   control->RemoveItemFromSelection(itemElm);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULListboxAccessible: Widgets
 
 bool XULListboxAccessible::IsWidget() const { return true; }
 
@@ -383,23 +386,23 @@ bool XULListboxAccessible::AreItemsOpera
       autoCompletePopupElm->GetPopupOpen(&isOpen);
       return isOpen;
     }
   }
   return true;
 }
 
 Accessible* XULListboxAccessible::ContainerWidget() const {
-  if (IsAutoCompletePopup()) {
+  if (IsAutoCompletePopup() && mContent->GetParent()) {
     // This works for XUL autocompletes. It doesn't work for HTML forms
     // autocomplete because of potential crossprocess calls (when autocomplete
     // lives in content process while popup lives in chrome process). If that's
     // a problem then rethink Widgets interface.
     nsCOMPtr<nsIDOMXULMenuListElement> menuListElm =
-        do_QueryInterface(mContent->GetParent());
+        mContent->GetParent()->AsElement()->AsXULMenuList();
     if (menuListElm) {
       RefPtr<mozilla::dom::Element> inputElm;
       menuListElm->GetInputField(getter_AddRefs(inputElm));
       if (inputElm) {
         Accessible* input = mDoc->GetAccessible(inputElm);
         return input ? input->ContainerWidget() : nullptr;
       }
     }
@@ -424,17 +427,17 @@ XULListitemAccessible::XULListitemAccess
 }
 
 XULListitemAccessible::~XULListitemAccessible() {}
 
 Accessible* XULListitemAccessible::GetListAccessible() const {
   if (IsDefunct()) return nullptr;
 
   nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem =
-      do_QueryInterface(mContent);
+      Elm()->AsXULSelectControlItem();
   if (!listItem) return nullptr;
 
   RefPtr<Element> listElement;
   listItem->GetControl(getter_AddRefs(listElement));
   if (!listElement) return nullptr;
 
   return mDoc->GetAccessible(listElement);
 }
@@ -474,18 +477,17 @@ role XULListitemAccessible::NativeRole()
 }
 
 uint64_t XULListitemAccessible::NativeState() const {
   if (mIsCheckbox) return XULMenuitemAccessible::NativeState();
 
   uint64_t states = NativeInteractiveState();
 
   nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem =
-      do_QueryInterface(mContent);
-
+      Elm()->AsXULSelectControlItem();
   if (listItem) {
     bool isSelected;
     listItem->GetSelected(&isSelected);
     if (isSelected) states |= states::SELECTED;
 
     if (FocusMgr()->IsFocused(this)) states |= states::FOCUSED;
   }
 
--- a/accessible/xul/XULMenuAccessible.cpp
+++ b/accessible/xul/XULMenuAccessible.cpp
@@ -69,18 +69,18 @@ uint64_t XULMenuitemAccessible::NativeSt
       state |= states::CHECKED;
   }
 
   // Combo box listitem
   bool isComboboxOption = (Role() == roles::COMBOBOX_OPTION);
   if (isComboboxOption) {
     // Is selected?
     bool isSelected = false;
-    nsCOMPtr<nsIDOMXULSelectControlItemElement> item(
-        do_QueryInterface(mContent));
+    nsCOMPtr<nsIDOMXULSelectControlItemElement> item =
+        Elm()->AsXULSelectControlItem();
     NS_ENSURE_TRUE(item, state);
     item->GetSelected(&isSelected);
 
     // Is collapsed?
     bool isCollapsed = false;
     Accessible* parent = Parent();
     if (parent && parent->State() & states::INVISIBLE) isCollapsed = true;
 
@@ -215,17 +215,17 @@ KeyBinding XULMenuitemAccessible::Keyboa
   if (modifiersStr.Find("accel") != -1) {
     modifierMask |= KeyBinding::AccelModifier();
   }
 
   return KeyBinding(key, modifierMask);
 }
 
 role XULMenuitemAccessible::NativeRole() const {
-  nsCOMPtr<nsIDOMXULContainerElement> xulContainer(do_QueryInterface(mContent));
+  nsCOMPtr<nsIDOMXULContainerElement> xulContainer = Elm()->AsXULContainer();
   if (xulContainer) return roles::PARENT_MENUITEM;
 
   if (mParent && mParent->Role() == roles::COMBOBOX_LIST)
     return roles::COMBOBOX_OPTION;
 
   if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
                                          nsGkAtoms::radio, eCaseMatters))
     return roles::RADIO_MENU_ITEM;
@@ -335,18 +335,26 @@ uint8_t XULMenuSeparatorAccessible::Acti
 
 XULMenupopupAccessible::XULMenupopupAccessible(nsIContent* aContent,
                                                DocAccessible* aDoc)
     : XULSelectControlAccessible(aContent, aDoc) {
   nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(GetFrame());
   if (menuPopupFrame && menuPopupFrame->IsMenu()) mType = eMenuPopupType;
 
   // May be the anonymous <menupopup> inside <menulist> (a combobox)
-  mSelectControl = do_QueryInterface(mContent->GetFlattenedTreeParent());
-  if (!mSelectControl) mGenericTypes &= ~eSelect;
+  nsIContent* parent = mContent->GetFlattenedTreeParent();
+  nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+      parent && parent->AsElement() ? parent->AsElement()->AsXULSelectControl()
+                                    : nullptr;
+  if (selectControl) {
+    mSelectControl = parent->AsElement();
+  } else {
+    mSelectControl = nullptr;
+    mGenericTypes &= ~eSelect;
+  }
 
   mStateFlags |= eNoXBLKids;
 }
 
 uint64_t XULMenupopupAccessible::NativeState() const {
   uint64_t state = Accessible::NativeState();
 
 #ifdef DEBUG
--- a/accessible/xul/XULSelectControlAccessible.cpp
+++ b/accessible/xul/XULSelectControlAccessible.cpp
@@ -4,17 +4,16 @@
  * 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/. */
 
 #include "XULSelectControlAccessible.h"
 
 #include "nsAccessibilityService.h"
 #include "DocAccessible.h"
 
-#include "nsIDOMXULContainerElement.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
 #include "nsIMutableArray.h"
 #include "nsIServiceManager.h"
 
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/KeyboardEventBinding.h"
 
@@ -24,17 +23,17 @@ using namespace mozilla::a11y;
 ////////////////////////////////////////////////////////////////////////////////
 // XULSelectControlAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 XULSelectControlAccessible::XULSelectControlAccessible(nsIContent* aContent,
                                                        DocAccessible* aDoc)
     : AccessibleWrap(aContent, aDoc) {
   mGenericTypes |= eSelect;
-  mSelectControl = do_QueryInterface(aContent);
+  mSelectControl = aContent->AsElement();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULSelectControlAccessible: Accessible
 
 void XULSelectControlAccessible::Shutdown() {
   mSelectControl = nullptr;
   AccessibleWrap::Shutdown();
@@ -52,127 +51,155 @@ void XULSelectControlAccessible::Selecte
     xulMultiSelect->GetSelectedCount(&length);
     for (int32_t index = 0; index < length; index++) {
       RefPtr<Element> element;
       xulMultiSelect->MultiGetSelectedItem(index, getter_AddRefs(element));
       Accessible* item = mDoc->GetAccessible(element);
       if (item) aItems->AppendElement(item);
     }
   } else {  // Single select?
+    nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+        mSelectControl->AsXULSelectControl();
     RefPtr<Element> element;
-    mSelectControl->GetSelectedItem(getter_AddRefs(element));
+    selectControl->GetSelectedItem(getter_AddRefs(element));
     if (element) {
       Accessible* item = mDoc->GetAccessible(element);
       if (item) aItems->AppendElement(item);
     }
   }
 }
 
 Accessible* XULSelectControlAccessible::GetSelectedItem(uint32_t aIndex) {
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
-      do_QueryInterface(mSelectControl);
+      mSelectControl->AsXULMultiSelectControl();
 
   RefPtr<Element> element;
   if (multiSelectControl) {
     multiSelectControl->MultiGetSelectedItem(aIndex, getter_AddRefs(element));
   } else if (aIndex == 0) {
-    mSelectControl->GetSelectedItem(getter_AddRefs(element));
+    nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+        mSelectControl->AsXULSelectControl();
+    if (selectControl) {
+      selectControl->GetSelectedItem(getter_AddRefs(element));
+    }
   }
 
   return element && mDoc ? mDoc->GetAccessible(element) : nullptr;
 }
 
 uint32_t XULSelectControlAccessible::SelectedItemCount() {
   // For XUL multi-select control
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
-      do_QueryInterface(mSelectControl);
+      mSelectControl->AsXULMultiSelectControl();
   if (multiSelectControl) {
     int32_t count = 0;
     multiSelectControl->GetSelectedCount(&count);
     return count;
   }
 
   // For XUL single-select control/menulist
-  int32_t index;
-  mSelectControl->GetSelectedIndex(&index);
-  return (index >= 0) ? 1 : 0;
+  nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+      mSelectControl->AsXULSelectControl();
+  if (selectControl) {
+    int32_t index = -1;
+    selectControl->GetSelectedIndex(&index);
+    return (index >= 0) ? 1 : 0;
+  }
+
+  return 0;
 }
 
 bool XULSelectControlAccessible::AddItemToSelection(uint32_t aIndex) {
   Accessible* item = GetChildAt(aIndex);
-  if (!item) return false;
+  if (!item || !item->GetContent()) return false;
 
   nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
-      do_QueryInterface(item->GetContent());
+      item->GetContent()->AsElement()->AsXULSelectControlItem();
   if (!itemElm) return false;
 
   bool isItemSelected = false;
   itemElm->GetSelected(&isItemSelected);
   if (isItemSelected) return true;
 
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
-      do_QueryInterface(mSelectControl);
+      mSelectControl->AsXULMultiSelectControl();
 
   if (multiSelectControl) {
     multiSelectControl->AddItemToSelection(itemElm);
   } else {
-    mSelectControl->SetSelectedItem(item->Elm());
+    nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+        mSelectControl->AsXULSelectControl();
+    if (selectControl) {
+      selectControl->SetSelectedItem(item->Elm());
+    }
   }
 
   return true;
 }
 
 bool XULSelectControlAccessible::RemoveItemFromSelection(uint32_t aIndex) {
   Accessible* item = GetChildAt(aIndex);
-  if (!item) return false;
+  if (!item || !item->GetContent()) return false;
 
   nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
-      do_QueryInterface(item->GetContent());
+      item->GetContent()->AsElement()->AsXULSelectControlItem();
   if (!itemElm) return false;
 
   bool isItemSelected = false;
   itemElm->GetSelected(&isItemSelected);
   if (!isItemSelected) return true;
 
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
-      do_QueryInterface(mSelectControl);
+      mSelectControl->AsXULMultiSelectControl();
 
-  if (multiSelectControl)
+  if (multiSelectControl) {
     multiSelectControl->RemoveItemFromSelection(itemElm);
-  else
-    mSelectControl->SetSelectedItem(nullptr);
+  } else {
+    nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+        mSelectControl->AsXULSelectControl();
+    if (selectControl) {
+      selectControl->SetSelectedItem(nullptr);
+    }
+  }
 
   return true;
 }
 
 bool XULSelectControlAccessible::IsItemSelected(uint32_t aIndex) {
   Accessible* item = GetChildAt(aIndex);
-  if (!item) return false;
+  if (!item || !item->GetContent()) return false;
 
   nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
-      do_QueryInterface(item->GetContent());
+      item->GetContent()->AsElement()->AsXULSelectControlItem();
   if (!itemElm) return false;
 
   bool isItemSelected = false;
   itemElm->GetSelected(&isItemSelected);
   return isItemSelected;
 }
 
 bool XULSelectControlAccessible::UnselectAll() {
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
-      do_QueryInterface(mSelectControl);
-  multiSelectControl ? multiSelectControl->ClearSelection()
-                     : mSelectControl->SetSelectedIndex(-1);
+      mSelectControl->AsXULMultiSelectControl();
+  if (multiSelectControl) {
+    multiSelectControl->ClearSelection();
+  } else {
+    nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+        mSelectControl->AsXULSelectControl();
+    if (selectControl) {
+      selectControl->SetSelectedIndex(-1);
+    }
+  }
 
   return true;
 }
 
 bool XULSelectControlAccessible::SelectAll() {
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
-      do_QueryInterface(mSelectControl);
+      mSelectControl->AsXULMultiSelectControl();
   if (multiSelectControl) {
     multiSelectControl->SelectAll();
     return true;
   }
 
   // otherwise, don't support this method
   return false;
 }
@@ -180,34 +207,43 @@ bool XULSelectControlAccessible::SelectA
 ////////////////////////////////////////////////////////////////////////////////
 // XULSelectControlAccessible: Widgets
 
 Accessible* XULSelectControlAccessible::CurrentItem() const {
   if (!mSelectControl) return nullptr;
 
   RefPtr<Element> currentItemElm;
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
-      do_QueryInterface(mSelectControl);
+      mSelectControl->AsXULMultiSelectControl();
   if (multiSelectControl) {
     multiSelectControl->GetCurrentItem(getter_AddRefs(currentItemElm));
   } else {
-    mSelectControl->GetSelectedItem(getter_AddRefs(currentItemElm));
+    nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+        mSelectControl->AsXULSelectControl();
+    if (selectControl) {
+      selectControl->GetSelectedItem(getter_AddRefs(currentItemElm));
+    }
   }
 
   if (currentItemElm) {
     DocAccessible* document = Document();
     if (document) return document->GetAccessible(currentItemElm);
   }
 
   return nullptr;
 }
 
 void XULSelectControlAccessible::SetCurrentItem(const Accessible* aItem) {
   if (!mSelectControl) return;
 
   nsCOMPtr<Element> itemElm = aItem->Elm();
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
-      do_QueryInterface(mSelectControl);
-  if (multiSelectControl)
+      itemElm->AsXULMultiSelectControl();
+  if (multiSelectControl) {
     multiSelectControl->SetCurrentItem(itemElm);
-  else
-    mSelectControl->SetSelectedItem(itemElm);
+  } else {
+    nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+        mSelectControl->AsXULSelectControl();
+    if (selectControl) {
+      selectControl->SetSelectedItem(itemElm);
+    }
+  }
 }
--- a/accessible/xul/XULSelectControlAccessible.h
+++ b/accessible/xul/XULSelectControlAccessible.h
@@ -34,17 +34,15 @@ class XULSelectControlAccessible : publi
   virtual bool SelectAll() override;
   virtual bool UnselectAll() override;
 
   // Widgets
   virtual Accessible* CurrentItem() const override;
   virtual void SetCurrentItem(const Accessible* aItem) override;
 
  protected:
-  // nsIDOMXULMultiSelectControlElement inherits from this, so we'll always have
-  // one of these if the widget is valid and not defunct
-  nsCOMPtr<nsIDOMXULSelectControlElement> mSelectControl;
+  RefPtr<Element> mSelectControl;
 };
 
 }  // namespace a11y
 }  // namespace mozilla
 
 #endif
--- a/accessible/xul/XULTabAccessible.cpp
+++ b/accessible/xul/XULTabAccessible.cpp
@@ -57,17 +57,18 @@ role XULTabAccessible::NativeRole() cons
 
 uint64_t XULTabAccessible::NativeState() const {
   // Possible states: focused, focusable, unavailable(disabled), offscreen.
 
   // get focus and disable status from base class
   uint64_t state = AccessibleWrap::NativeState();
 
   // Check whether the tab is selected and/or pinned
-  nsCOMPtr<nsIDOMXULSelectControlItemElement> tab(do_QueryInterface(mContent));
+  nsCOMPtr<nsIDOMXULSelectControlItemElement> tab =
+      Elm()->AsXULSelectControlItem();
   if (tab) {
     bool selected = false;
     if (NS_SUCCEEDED(tab->GetSelected(&selected)) && selected)
       state |= states::SELECTED;
 
     if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::pinned,
                                            nsGkAtoms::_true, eCaseMatters))
       state |= states::PINNED;
@@ -81,18 +82,21 @@ uint64_t XULTabAccessible::NativeInterac
   return (state & states::UNAVAILABLE) ? state : state | states::SELECTABLE;
 }
 
 Relation XULTabAccessible::RelationByType(RelationType aType) const {
   Relation rel = AccessibleWrap::RelationByType(aType);
   if (aType != RelationType::LABEL_FOR) return rel;
 
   // Expose 'LABEL_FOR' relation on tab accessible for tabpanel accessible.
+  nsIContent* parent = mContent->GetParent();
+  if (!parent) return rel;
+
   nsCOMPtr<nsIDOMXULRelatedElement> tabsElm =
-      do_QueryInterface(mContent->GetParent());
+      parent->AsElement()->AsXULRelated();
   if (!tabsElm) return rel;
 
   RefPtr<mozilla::dom::Element> tabpanelElement;
   tabsElm->GetRelatedElement(GetNode(), getter_AddRefs(tabpanelElement));
   if (!tabpanelElement) return rel;
 
   rel.AppendTarget(mDoc, tabpanelElement);
   return rel;
@@ -192,18 +196,20 @@ XULTabpanelAccessible::XULTabpanelAccess
 
 role XULTabpanelAccessible::NativeRole() const { return roles::PROPERTYPAGE; }
 
 Relation XULTabpanelAccessible::RelationByType(RelationType aType) const {
   Relation rel = AccessibleWrap::RelationByType(aType);
   if (aType != RelationType::LABELLED_BY) return rel;
 
   // Expose 'LABELLED_BY' relation on tabpanel accessible for tab accessible.
+  if (!mContent->GetParent()) return rel;
+
   nsCOMPtr<nsIDOMXULRelatedElement> tabpanelsElm =
-      do_QueryInterface(mContent->GetParent());
+      mContent->GetParent()->AsElement()->AsXULRelated();
   if (!tabpanelsElm) return rel;
 
   RefPtr<mozilla::dom::Element> tabElement;
   tabpanelsElm->GetRelatedElement(GetNode(), getter_AddRefs(tabElement));
   if (!tabElement) return rel;
 
   rel.AppendTarget(mDoc, tabElement);
   return rel;
--- a/accessible/xul/XULTreeAccessible.cpp
+++ b/accessible/xul/XULTreeAccessible.cpp
@@ -405,23 +405,23 @@ bool XULTreeAccessible::AreItemsOperable
       autoCompletePopupElm->GetPopupOpen(&isOpen);
       return isOpen;
     }
   }
   return true;
 }
 
 Accessible* XULTreeAccessible::ContainerWidget() const {
-  if (IsAutoCompletePopup()) {
+  if (IsAutoCompletePopup() && mContent->GetParent()) {
     // This works for XUL autocompletes. It doesn't work for HTML forms
     // autocomplete because of potential crossprocess calls (when autocomplete
     // lives in content process while popup lives in chrome process). If that's
     // a problem then rethink Widgets interface.
     nsCOMPtr<nsIDOMXULMenuListElement> menuListElm =
-        do_QueryInterface(mContent->GetParent());
+        mContent->GetParent()->AsElement()->AsXULMenuList();
     if (menuListElm) {
       RefPtr<mozilla::dom::Element> inputElm;
       menuListElm->GetInputField(getter_AddRefs(inputElm));
       if (inputElm) {
         Accessible* input = mDoc->GetAccessible(inputElm);
         return input ? input->ContainerWidget() : nullptr;
       }
     }
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -6820,17 +6820,17 @@ var CanvasPermissionPromptHelper = {
       return;
     }
 
     let browser;
     if (aSubject instanceof Ci.nsIDOMWindow) {
       let contentWindow = aSubject.QueryInterface(Ci.nsIDOMWindow);
       browser = contentWindow.docShell.chromeEventHandler;
     } else {
-      browser = aSubject.QueryInterface(Ci.nsIBrowser);
+      browser = aSubject;
     }
 
     let uri = Services.io.newURI(aData);
     if (gBrowser.selectedBrowser !== browser) {
       // Must belong to some other window.
       return;
     }