Fix for bug 799464 (Make Element.getElementsBy* return HTMLCollection). r=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Wed, 26 Sep 2012 16:17:47 +0200
changeset 110767 4c979ca3eb7a1ca1ecd7b671ec61b6af9aa4de43
parent 110766 9806c99965fbf1b5770813b4c6eb4c6dcb3413e4
child 110768 0f68b28becd099bfac0040ba6f7b33b0267b26ce
push id23716
push userryanvm@gmail.com
push dateSat, 20 Oct 2012 01:43:16 +0000
treeherdermozilla-central@ff4af83233dc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs799464
milestone19.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
Fix for bug 799464 (Make Element.getElementsBy* return HTMLCollection). r=bz.
accessible/src/html/HTMLTableAccessible.cpp
content/base/public/nsContentUtils.h
content/base/src/nsContentList.cpp
content/base/src/nsContentList.h
content/base/src/nsContentUtils.cpp
content/base/src/nsDocument.cpp
content/base/src/nsGenericElement.cpp
dom/interfaces/core/nsIDOMElement.idl
dom/plugins/base/nsPluginInstanceOwner.cpp
editor/libeditor/text/nsTextEditRules.cpp
embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
widget/xpwidgets/GfxInfoBase.cpp
--- a/accessible/src/html/HTMLTableAccessible.cpp
+++ b/accessible/src/html/HTMLTableAccessible.cpp
@@ -954,17 +954,17 @@ HTMLTableAccessible::Description(nsStrin
 }
 
 bool
 HTMLTableAccessible::HasDescendant(const nsAString& aTagName, bool aAllowEmpty)
 {
   nsCOMPtr<nsIDOMElement> tableElt(do_QueryInterface(mContent));
   NS_ENSURE_TRUE(tableElt, false);
 
-  nsCOMPtr<nsIDOMNodeList> nodeList;
+  nsCOMPtr<nsIDOMHTMLCollection> nodeList;
   tableElt->GetElementsByTagName(aTagName, getter_AddRefs(nodeList));
   NS_ENSURE_TRUE(nodeList, false);
 
   nsCOMPtr<nsIDOMNode> foundItem;
   nodeList->Item(0, getter_AddRefs(foundItem));
   if (!foundItem)
     return false;
 
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -32,16 +32,17 @@
 #include "nsIDocument.h"
 #include "nsContentSink.h"
 #include "nsMathUtils.h"
 #include "nsThreadUtils.h"
 #include "nsIContent.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "gfxContext.h"
 #include "gfxFont.h"
+#include "nsContentList.h"
 
 #include "mozilla/AutoRestore.h"
 #include "mozilla/GuardObjects.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Assertions.h"
 
 struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will force strange compilation error!
 
@@ -1809,19 +1810,26 @@ public:
   {
     sIsHandlingKeyBoardEvent = aHandling;
   }
 
   /**
    * Utility method for getElementsByClassName.  aRootNode is the node (either
    * document or element), which getElementsByClassName was called on.
    */
-  static nsresult GetElementsByClassName(nsINode* aRootNode,
-                                         const nsAString& aClasses,
-                                         nsIDOMNodeList** aReturn);
+  static already_AddRefed<nsContentList>
+  GetElementsByClassName(nsINode* aRootNode, const nsAString& aClasses)
+  {
+    NS_PRECONDITION(aRootNode, "Must have root node");
+
+    return NS_GetFuncStringHTMLCollection(aRootNode, MatchClassNames,
+                                          DestroyClassNameArray,
+                                          AllocClassMatchingInfo,
+                                          aClasses);
+  }
 
   /**
    * Returns a presshell for this document, if there is one. This will be
    * aDoc's direct presshell if there is one, otherwise we'll look at all
    * ancestor documents to try to find a presshell, so for example this can
    * still find a presshell for documents in display:none frames that have
    * no presentation. So you have to be careful how you use this presshell ---
    * getting generic data like a device context or widget from it is OK, but it
@@ -2175,16 +2183,22 @@ private:
                                 bool aCancelable,
                                 bool aTrusted,
                                 bool *aDefaultAction = nullptr);
 
   static void InitializeModifierStrings();
 
   static void DropFragmentParsers();
 
+  static bool MatchClassNames(nsIContent* aContent, int32_t aNamespaceID,
+                              nsIAtom* aAtom, void* aData);
+  static void DestroyClassNameArray(void* aData);
+  static void* AllocClassMatchingInfo(nsINode* aRootNode,
+                                      const nsString* aClasses);
+
   static nsIDOMScriptObjectFactory *sDOMScriptObjectFactory;
 
   static nsIXPConnect *sXPConnect;
 
   static nsIScriptSecurityManager *sSecurityManager;
 
   static nsIThreadJSContextStack *sThreadJSContextStack;
 
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -409,30 +409,19 @@ GetFuncStringContentList(nsINode* aRootN
     }
   }
 
   if (!list) {
     // We need to create a ContentList and add it to our new entry, if
     // we have an entry
     list = new ListType(aRootNode, aFunc, aDestroyFunc, aDataAllocator,
                         aString);
-    if (list && !list->AllocatedData()) {
-      // Failed to allocate the data
-      delete list;
-      list = nullptr;
+    if (entry) {
+      entry->mContentList = list;
     }
-
-    if (entry) {
-      if (list)
-        entry->mContentList = list;
-      else
-        PL_DHashTableRawRemove(&gContentListHashTable, entry);
-    }
-
-    NS_ENSURE_TRUE(list, nullptr);
   }
 
   NS_ADDREF(list);
 
   // Don't cache these lists globally
 
   return list;
 }
--- a/content/base/src/nsContentList.h
+++ b/content/base/src/nsContentList.h
@@ -474,27 +474,26 @@ private:
  * A function that allocates the matching data for this
  * FuncStringContentList.  Returning aString is perfectly fine; in
  * that case the destructor function should be a no-op.
  */
 typedef void* (*nsFuncStringContentListDataAllocator)(nsINode* aRootNode,
                                                       const nsString* aString);
 
 // aDestroyFunc is allowed to be null
+// aDataAllocator must always return a non-null pointer
 class nsCacheableFuncStringContentList : public nsContentList {
 public:
   virtual ~nsCacheableFuncStringContentList();
 
   bool Equals(const nsFuncStringCacheKey* aKey) {
     return mRootNode == aKey->mRootNode && mFunc == aKey->mFunc &&
       mString == aKey->mString;
   }
 
-  bool AllocatedData() const { return !!mData; }
-
 #ifdef DEBUG
   enum ContentListType {
     eNodeList,
     eHTMLCollection
   };
   ContentListType mType;
 #endif
 
@@ -503,16 +502,17 @@ protected:
                                    nsContentListMatchFunc aFunc,
                                    nsContentListDestroyFunc aDestroyFunc,
                                    nsFuncStringContentListDataAllocator aDataAllocator,
                                    const nsAString& aString) :
     nsContentList(aRootNode, aFunc, aDestroyFunc, nullptr),
     mString(aString)
   {
     mData = (*aDataAllocator)(aRootNode, &mString);
+    MOZ_ASSERT(mData);
   }
 
   virtual void RemoveFromCaches() {
     RemoveFromFuncStringHashtable();
   }
   void RemoveFromFuncStringHashtable();
 
   nsString mString;
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -39,17 +39,16 @@
 #include "nsPIDOMWindow.h"
 #include "nsIJSContextStack.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsParserCIID.h"
 #include "nsIParser.h"
 #include "nsIFragmentContentSink.h"
 #include "nsIContentSink.h"
-#include "nsContentList.h"
 #include "nsIHTMLDocument.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIForm.h"
 #include "nsIFormControl.h"
 #include "nsGkAtoms.h"
 #include "imgINotificationObserver.h"
 #include "imgIRequest.h"
@@ -6240,19 +6239,20 @@ nsContentUtils::StripNullChars(const nsA
   }
 }
 
 struct ClassMatchingInfo {
   nsAttrValue::AtomArray mClasses;
   nsCaseTreatment mCaseTreatment;
 };
 
-static bool
-MatchClassNames(nsIContent* aContent, int32_t aNamespaceID, nsIAtom* aAtom,
-                void* aData)
+// static
+bool
+nsContentUtils::MatchClassNames(nsIContent* aContent, int32_t aNamespaceID,
+                                nsIAtom* aAtom, void* aData)
 {
   // We can't match if there are no class names
   const nsAttrValue* classAttr = aContent->GetClasses();
   if (!classAttr) {
     return false;
   }
   
   // need to match *all* of the classes
@@ -6268,67 +6268,47 @@ MatchClassNames(nsIContent* aContent, in
                              info->mCaseTreatment)) {
       return false;
     }
   }
   
   return true;
 }
 
-static void
-DestroyClassNameArray(void* aData)
+// static
+void
+nsContentUtils::DestroyClassNameArray(void* aData)
 {
   ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
   delete info;
 }
 
-static void*
-AllocClassMatchingInfo(nsINode* aRootNode,
-                       const nsString* aClasses)
+// static
+void*
+nsContentUtils::AllocClassMatchingInfo(nsINode* aRootNode,
+                                       const nsString* aClasses)
 {
   nsAttrValue attrValue;
   attrValue.ParseAtomArray(*aClasses);
   // nsAttrValue::Equals is sensitive to order, so we'll send an array
   ClassMatchingInfo* info = new ClassMatchingInfo;
-  NS_ENSURE_TRUE(info, nullptr);
-
   if (attrValue.Type() == nsAttrValue::eAtomArray) {
     info->mClasses.SwapElements(*(attrValue.GetAtomArrayValue()));
   } else if (attrValue.Type() == nsAttrValue::eAtom) {
     info->mClasses.AppendElement(attrValue.GetAtomValue());
   }
 
   info->mCaseTreatment =
     aRootNode->OwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks ?
     eIgnoreCase : eCaseMatters;
   return info;
 }
 
 // static
 
-nsresult
-nsContentUtils::GetElementsByClassName(nsINode* aRootNode,
-                                       const nsAString& aClasses,
-                                       nsIDOMNodeList** aReturn)
-{
-  NS_PRECONDITION(aRootNode, "Must have root node");
-  
-  nsContentList* elements =
-    NS_GetFuncStringHTMLCollection(aRootNode, MatchClassNames,
-                                   DestroyClassNameArray,
-                                   AllocClassMatchingInfo,
-                                   aClasses).get();
-  NS_ENSURE_TRUE(elements, NS_ERROR_OUT_OF_MEMORY);
-
-  // Transfer ownership
-  *aReturn = elements;
-
-  return NS_OK;
-}
-
 #ifdef DEBUG
 class DebugWrapperTraversalCallback : public nsCycleCollectionTraversalCallback
 {
 public:
   DebugWrapperTraversalCallback(void* aWrapper) : mFound(false),
                                                   mWrapper(aWrapper)
   {
     mFlags = WANT_ALL_TRACES;
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -3029,17 +3029,18 @@ nsDocument::NodesFromRectHelper(float aX
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocument::GetElementsByClassName(const nsAString& aClasses,
                                    nsIDOMNodeList** aReturn)
 {
-  return nsContentUtils::GetElementsByClassName(this, aClasses, aReturn);
+  *aReturn = nsContentUtils::GetElementsByClassName(this, aClasses).get();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocument::ReleaseCapture()
 {
   // only release the capture if the caller can access it. This prevents a
   // page from stopping a scrollbar grab for example.
   nsCOMPtr<nsIDOMNode> node = do_QueryInterface(nsIPresShell::GetCapturingContent());
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -804,19 +804,20 @@ nsGenericElement::GetBoundingClientRect(
           nsLayoutUtils::GetContainingBlockForClientRect(frame),
           nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS);
   rect->SetLayoutRect(r);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGenericElement::GetElementsByClassName(const nsAString& aClasses,
-                                         nsIDOMNodeList** aReturn)
+                                         nsIDOMHTMLCollection** aReturn)
 {
-  return nsContentUtils::GetElementsByClassName(this, aClasses, aReturn);
+  *aReturn = nsContentUtils::GetElementsByClassName(this, aClasses).get();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGenericElement::GetClientRects(nsIDOMClientRectList** aResult)
 {
   *aResult = nullptr;
 
   nsRefPtr<nsClientRectList> rectList = new nsClientRectList(this);
@@ -1000,17 +1001,17 @@ nsGenericElement::RemoveAttributeNode(ns
     }
   }
 
   return rv;
 }
 
 nsresult
 nsGenericElement::GetElementsByTagName(const nsAString& aTagname,
-                                       nsIDOMNodeList** aReturn)
+                                       nsIDOMHTMLCollection** aReturn)
 {
   nsContentList *list = NS_GetContentList(this, kNameSpaceID_Unknown, 
                                           aTagname).get();
 
   // transfer ref to aReturn
   *aReturn = list;
   return NS_OK;
 }
@@ -1130,17 +1131,17 @@ nsGenericElement::SetAttributeNodeNS(nsI
   }
 
   return rv;
 }
 
 nsresult
 nsGenericElement::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
                                          const nsAString& aLocalName,
-                                         nsIDOMNodeList** aReturn)
+                                         nsIDOMHTMLCollection** aReturn)
 {
   int32_t nameSpaceId = kNameSpaceID_Wildcard;
 
   if (!aNamespaceURI.EqualsLiteral("*")) {
     nsresult rv =
       nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
                                                             nameSpaceId);
     NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/interfaces/core/nsIDOMElement.idl
+++ b/dom/interfaces/core/nsIDOMElement.idl
@@ -8,17 +8,17 @@
 /**
  * The nsIDOMElement interface represents an element in an HTML or 
  * XML document. 
  *
  * For more information on this interface please see 
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#interface-element
  */
 
-[scriptable, uuid(69D44CE2-B544-49A8-BB5F-87804B971EE4)]
+[scriptable, uuid(f1465e67-577f-4546-a7a3-bb1293c0dd15)]
 interface nsIDOMElement : nsIDOMNode
 {
   readonly attribute DOMString        tagName;
 
   /**
    * Returns a DOMTokenList object reflecting the class attribute.
    */
   readonly attribute nsIDOMDOMTokenList classList;
@@ -42,24 +42,24 @@ interface nsIDOMElement : nsIDOMNode
   nsIDOMAttr         getAttributeNode(in DOMString name);
   nsIDOMAttr         setAttributeNode(in nsIDOMAttr newAttr);
   nsIDOMAttr         removeAttributeNode(in nsIDOMAttr oldAttr);
   nsIDOMAttr         getAttributeNodeNS(in DOMString namespaceURI, 
                                         in DOMString localName);
   nsIDOMAttr         setAttributeNodeNS(in nsIDOMAttr newAttr)
                                         raises(DOMException);
 
-  nsIDOMNodeList     getElementsByTagName(in DOMString name);
-  nsIDOMNodeList     getElementsByTagNameNS(in DOMString namespaceURI, 
-                                            in DOMString localName);
+  nsIDOMHTMLCollection getElementsByTagName(in DOMString name);
+  nsIDOMHTMLCollection getElementsByTagNameNS(in DOMString namespaceURI, 
+                                              in DOMString localName);
   /**
    * Retrieve elements matching all classes listed in a
    * space-separated string.
    */
-  nsIDOMNodeList getElementsByClassName(in DOMString classes);
+  nsIDOMHTMLCollection getElementsByClassName(in DOMString classes);
 
   /**
    * Returns a live nsIDOMNodeList of the current child elements.
    */
   [binaryname(ChildElements)]
   readonly attribute nsIDOMNodeList children;
   /**
    * Similar as the attributes on nsIDOMNode, but navigates just elements
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -52,16 +52,17 @@ using mozilla::DefaultXDisplay;
 #include "nsIDOMHTMLAppletElement.h"
 #include "nsAttrName.h"
 #include "nsIFocusManager.h"
 #include "nsFocusManager.h"
 #include "nsIDOMDragEvent.h"
 #include "nsIScrollableFrame.h"
 #include "nsIDocShell.h"
 #include "ImageContainer.h"
+#include "nsIDOMHTMLCollection.h"
 
 #include "nsContentCID.h"
 #include "nsWidgetsCID.h"
 static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 #ifdef XP_WIN
 #include <wtypes.h>
@@ -1137,17 +1138,17 @@ nsresult nsPluginInstanceOwner::EnsureCa
 
   // Get all dependent PARAM tags, even if they are not direct children.
   nsCOMPtr<nsIDOMElement> mydomElement = do_QueryInterface(mContent);
   NS_ENSURE_TRUE(mydomElement, NS_ERROR_NO_INTERFACE);
 
   // Making DOM method calls can cause our frame to go away.
   nsCOMPtr<nsIPluginInstanceOwner> kungFuDeathGrip(this);
 
-  nsCOMPtr<nsIDOMNodeList> allParams;
+  nsCOMPtr<nsIDOMHTMLCollection> allParams;
   NS_NAMED_LITERAL_STRING(xhtml_ns, "http://www.w3.org/1999/xhtml");
   mydomElement->GetElementsByTagNameNS(xhtml_ns, NS_LITERAL_STRING("param"),
                                        getter_AddRefs(allParams));
   if (allParams) {
     uint32_t numAllParams; 
     allParams->GetLength(&numAllParams);
     for (uint32_t i = 0; i < numAllParams; i++) {
       nsCOMPtr<nsIDOMNode> pnode;
--- a/editor/libeditor/text/nsTextEditRules.cpp
+++ b/editor/libeditor/text/nsTextEditRules.cpp
@@ -926,35 +926,37 @@ nsTextEditRules::DidRedo(nsISelection *a
 {
   nsresult res = aResult;  // if aResult is an error, we return it.
   if (!aSelection) { return NS_ERROR_NULL_POINTER; }
   if (NS_SUCCEEDED(res)) 
   {
     nsCOMPtr<nsIDOMElement> theRoot = do_QueryInterface(mEditor->GetRoot());
     NS_ENSURE_TRUE(theRoot, NS_ERROR_FAILURE);
     
-    nsCOMPtr<nsIDOMNodeList> nodeList;
+    nsCOMPtr<nsIDOMHTMLCollection> nodeList;
     res = theRoot->GetElementsByTagName(NS_LITERAL_STRING("br"),
                                         getter_AddRefs(nodeList));
     NS_ENSURE_SUCCESS(res, res);
     if (nodeList)
     {
       uint32_t len;
       nodeList->GetLength(&len);
       
       if (len != 1) {
         // only in the case of one br could there be the bogus node
         mBogusNode = nullptr;
         return NS_OK;  
       }
 
-      nsCOMPtr<nsIContent> content = nodeList->GetNodeAt(0);
+      nsCOMPtr<nsIDOMNode> node;
+      nodeList->Item(0, getter_AddRefs(node));
+      nsCOMPtr<nsIContent> content = do_QueryInterface(node);
       MOZ_ASSERT(content);
       if (mEditor->IsMozEditorBogusNode(content)) {
-        mBogusNode = do_QueryInterface(content);
+        mBogusNode = node;
       } else {
         mBogusNode = nullptr;
       }
     }
   }
   return res;
 }
 
--- a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
+++ b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
@@ -4027,17 +4027,17 @@ nsWebBrowserPersist::SetDocumentBase(
     if (!headElement)
     {
         return NS_ERROR_FAILURE;
     }
 
     // Find or create the BASE element
     NS_NAMED_LITERAL_STRING(kBase, "base");
     nsCOMPtr<nsIDOMElement> baseElement;
-    nsCOMPtr<nsIDOMNodeList> baseList;
+    nsCOMPtr<nsIDOMHTMLCollection> baseList;
     if (xmlDoc)
     {
         headElement->GetElementsByTagNameNS(
             kXHTMLNS,
             kBase, getter_AddRefs(baseList));
     }
     else
     {
--- a/widget/xpwidgets/GfxInfoBase.cpp
+++ b/widget/xpwidgets/GfxInfoBase.cpp
@@ -16,16 +16,17 @@
 #include "nsAutoPtr.h"
 #include "nsString.h"
 #include "nsUnicharUtils.h"
 #include "mozilla/Services.h"
 #include "mozilla/Observer.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "nsIDOMElement.h"
+#include "nsIDOMHTMLCollection.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
 #include "nsTArray.h"
 #include "mozilla/Preferences.h"
 
 #if defined(MOZ_CRASHREPORTER)
 #include "nsExceptionHandler.h"
 #endif
@@ -220,17 +221,17 @@ BlacklistOSToOperatingSystem(const nsASt
     return DRIVER_OS_ANDROID;
   else if (os == NS_LITERAL_STRING("All"))
     return DRIVER_OS_ALL;
 
   return DRIVER_OS_UNKNOWN;
 }
 
 static GfxDeviceFamily*
-BlacklistDevicesToDeviceFamily(nsIDOMNodeList* aDevices)
+BlacklistDevicesToDeviceFamily(nsIDOMHTMLCollection* aDevices)
 {
   uint32_t length;
   if (NS_FAILED(aDevices->GetLength(&length)))
     return nullptr;
 
   // For each <device>, get its device ID, and return a freshly-allocated
   // GfxDeviceFamily with the contents of that array.
   GfxDeviceFamily* deviceIds = new GfxDeviceFamily;
@@ -318,17 +319,17 @@ BlacklistComparatorToComparisonOp(const 
 }
 
 // Arbitrarily returns the first |tagname| child of |element|.
 static bool
 BlacklistNodeGetChildByName(nsIDOMElement *element,
                             const nsAString& tagname,
                             nsIDOMNode** firstchild)
 {
-  nsCOMPtr<nsIDOMNodeList> nodelist;
+  nsCOMPtr<nsIDOMHTMLCollection> nodelist;
   if (NS_FAILED(element->GetElementsByTagName(tagname,
                                               getter_AddRefs(nodelist))) ||
       !nodelist) {
     return false;
   }
 
   nsCOMPtr<nsIDOMNode> node;
   if (NS_FAILED(nodelist->Item(0, getter_AddRefs(node))) || !node)
@@ -391,17 +392,17 @@ BlacklistEntryToDriverInfo(nsIDOMNode* a
   // </devices>
   if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("devices"),
                                   getter_AddRefs(dataNode))) {
     nsCOMPtr<nsIDOMElement> devicesElement = do_QueryInterface(dataNode);
     if (devicesElement) {
 
       // Get only the <device> nodes, because BlacklistDevicesToDeviceFamily
       // assumes it is passed no other nodes.
-      nsCOMPtr<nsIDOMNodeList> devices;
+      nsCOMPtr<nsIDOMHTMLCollection> devices;
       if (NS_SUCCEEDED(devicesElement->GetElementsByTagName(NS_LITERAL_STRING("device"),
                                                             getter_AddRefs(devices)))) {
         GfxDeviceFamily* deviceIds = BlacklistDevicesToDeviceFamily(devices);
         if (deviceIds) {
           // Get GfxDriverInfo to adopt the devices array we created.
           aDriverInfo.mDeleteDevices = true;
           aDriverInfo.mDevices = deviceIds;
         }
@@ -440,17 +441,17 @@ BlacklistEntryToDriverInfo(nsIDOMNode* a
   }
 
   // We explicitly ignore unknown elements.
 
   return true;
 }
 
 static void
-BlacklistEntriesToDriverInfo(nsIDOMNodeList* aBlacklistEntries,
+BlacklistEntriesToDriverInfo(nsIDOMHTMLCollection* aBlacklistEntries,
                              nsTArray<GfxDriverInfo>& aDriverInfo)
 {
   uint32_t length;
   if (NS_FAILED(aBlacklistEntries->GetLength(&length)))
     return;
 
   aDriverInfo.Clear();
   aDriverInfo.SetLength(length);
@@ -471,17 +472,17 @@ BlacklistEntriesToDriverInfo(nsIDOMNodeL
 
 NS_IMETHODIMP
 GfxInfoBase::Observe(nsISupports* aSubject, const char* aTopic,
                      const PRUnichar* aData)
 {
   if (strcmp(aTopic, "blocklist-data-gfxItems") == 0) {
     nsCOMPtr<nsIDOMElement> gfxItems = do_QueryInterface(aSubject);
     if (gfxItems) {
-      nsCOMPtr<nsIDOMNodeList> blacklistEntries;
+      nsCOMPtr<nsIDOMHTMLCollection> blacklistEntries;
       if (NS_SUCCEEDED(gfxItems->
             GetElementsByTagName(NS_LITERAL_STRING(BLACKLIST_ENTRY_TAG_NAME),
                                  getter_AddRefs(blacklistEntries))) &&
           blacklistEntries)
       {
         nsTArray<GfxDriverInfo> driverInfo;
         BlacklistEntriesToDriverInfo(blacklistEntries, driverInfo);
         EvaluateDownloadedBlacklist(driverInfo);