Bug 1309698 - Remove usage of nsISupportsArray from nsIDragService. r=smaug
authorEric Rahm <erahm@mozilla.com>
Tue, 18 Oct 2016 11:56:20 -0700
changeset 363636 32b590e82c8ec5251e77451f91f1e3f8b9ccb92f
parent 363635 ae62367e77a92d321ca62a7dccab092feab74a1b
child 363637 86b36f82fce6b46f84ee1aa78419380aca764baa
push id1369
push userjlorenzo@mozilla.com
push dateMon, 27 Feb 2017 14:59:41 +0000
treeherdermozilla-release@d75a1dba431f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1309698
milestone52.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 1309698 - Remove usage of nsISupportsArray from nsIDragService. r=smaug
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/events/DataTransfer.cpp
dom/events/DataTransfer.h
dom/events/EventStateManager.cpp
dom/ipc/ContentParent.cpp
widget/cocoa/nsDragService.h
widget/cocoa/nsDragService.mm
widget/gtk/nsDragService.cpp
widget/gtk/nsDragService.h
widget/nsBaseDragService.cpp
widget/nsBaseDragService.h
widget/nsDragServiceProxy.cpp
widget/nsDragServiceProxy.h
widget/nsIDragService.idl
widget/windows/nsDragService.cpp
widget/windows/nsDragService.h
widget/windows/tests/TestWinDND.cpp
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -7539,31 +7539,29 @@ nsContentUtils::IPCTransferableToTransfe
   }
 
   aTransferable->SetIsPrivateData(aIsPrivateData);
   aTransferable->SetRequestingPrincipal(aRequestingPrincipal);
   return NS_OK;
 }
 
 void
-nsContentUtils::TransferablesToIPCTransferables(nsISupportsArray* aTransferables,
+nsContentUtils::TransferablesToIPCTransferables(nsIArray* aTransferables,
                                                 nsTArray<IPCDataTransfer>& aIPC,
                                                 bool aInSyncMessage,
                                                 mozilla::dom::nsIContentChild* aChild,
                                                 mozilla::dom::nsIContentParent* aParent)
 {
   aIPC.Clear();
   if (aTransferables) {
     uint32_t transferableCount = 0;
-    aTransferables->Count(&transferableCount);
+    aTransferables->GetLength(&transferableCount);
     for (uint32_t i = 0; i < transferableCount; ++i) {
       IPCDataTransfer* dt = aIPC.AppendElement();
-      nsCOMPtr<nsISupports> genericItem;
-      aTransferables->GetElementAt(i, getter_AddRefs(genericItem));
-      nsCOMPtr<nsITransferable> transferable(do_QueryInterface(genericItem));
+      nsCOMPtr<nsITransferable> transferable = do_QueryElementAt(aTransferables, i);
       TransferableToIPCTransferable(transferable, dt, aInSyncMessage, aChild, aParent);
     }
   }
 }
 
 nsresult
 nsContentUtils::SlurpFileToString(nsIFile* aFile, nsACString& aString)
 {
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2495,17 +2495,17 @@ public:
 
   static nsresult IPCTransferableToTransferable(const mozilla::dom::IPCDataTransfer& aDataTransfer,
                                                 const bool& aIsPrivateData,
                                                 nsIPrincipal* aRequestingPrincipal,
                                                 nsITransferable* aTransferable,
                                                 mozilla::dom::nsIContentParent* aContentParent,
                                                 mozilla::dom::TabChild* aTabChild);
 
-  static void TransferablesToIPCTransferables(nsISupportsArray* aTransferables,
+  static void TransferablesToIPCTransferables(nsIArray* aTransferables,
                                               nsTArray<mozilla::dom::IPCDataTransfer>& aIPC,
                                               bool aInSyncMessage,
                                               mozilla::dom::nsIContentChild* aChild,
                                               mozilla::dom::nsIContentParent* aParent);
 
   static void TransferableToIPCTransferable(nsITransferable* aTransferable,
                                             mozilla::dom::IPCDataTransfer* aIPCDataTransfer,
                                             bool aInSyncMessage,
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -8,16 +8,17 @@
 #include "mozilla/BasicEvents.h"
 
 #include "DataTransfer.h"
 
 #include "nsIDOMDocument.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIScriptSecurityManager.h"
 #include "mozilla/dom/DOMStringList.h"
+#include "nsArray.h"
 #include "nsError.h"
 #include "nsIDragService.h"
 #include "nsIClipboard.h"
 #include "nsContentUtils.h"
 #include "nsIContent.h"
 #include "nsIBinaryInputStream.h"
 #include "nsIBinaryOutputStream.h"
 #include "nsIStorageStream.h"
@@ -871,17 +872,17 @@ DataTransfer::Clone(nsISupports* aParent
                      mIsExternal, aUserCancelled, aIsCrossDomainSubFrameDrop,
                      mClipboardType, mItems, mDragImage, mDragImageX,
                      mDragImageY);
 
   newDataTransfer.forget(aNewDataTransfer);
   return NS_OK;
 }
 
-already_AddRefed<nsISupportsArray>
+already_AddRefed<nsIArray>
 DataTransfer::GetTransferables(nsIDOMNode* aDragTarget)
 {
   MOZ_ASSERT(aDragTarget);
 
   nsCOMPtr<nsINode> dragNode = do_QueryInterface(aDragTarget);
   if (!dragNode) {
     return nullptr;
   }
@@ -889,31 +890,29 @@ DataTransfer::GetTransferables(nsIDOMNod
   nsIDocument* doc = dragNode->GetComposedDoc();
   if (!doc) {
     return nullptr;
   }
 
   return GetTransferables(doc->GetLoadContext());
 }
 
-already_AddRefed<nsISupportsArray>
+already_AddRefed<nsIArray>
 DataTransfer::GetTransferables(nsILoadContext* aLoadContext)
 {
-
-  nsCOMPtr<nsISupportsArray> transArray =
-    do_CreateInstance("@mozilla.org/supports-array;1");
+  nsCOMPtr<nsIMutableArray> transArray = nsArray::Create();
   if (!transArray) {
     return nullptr;
   }
 
   uint32_t count = MozItemCount();
   for (uint32_t i = 0; i < count; i++) {
     nsCOMPtr<nsITransferable> transferable = GetTransferable(i, aLoadContext);
     if (transferable) {
-      transArray->AppendElement(transferable);
+      transArray->AppendElement(transferable, /*weak =*/ false);
     }
   }
 
   return transArray.forget();
 }
 
 already_AddRefed<nsITransferable>
 DataTransfer::GetTransferable(uint32_t aIndex, nsILoadContext* aLoadContext)
--- a/dom/events/DataTransfer.h
+++ b/dom/events/DataTransfer.h
@@ -230,19 +230,19 @@ public:
     return mEventMessage;
   }
   bool IsCrossDomainSubFrameDrop() const {
     return mIsCrossDomainSubFrameDrop;
   }
 
   // converts the data into an array of nsITransferable objects to be used for
   // drag and drop or clipboard operations.
-  already_AddRefed<nsISupportsArray> GetTransferables(nsIDOMNode* aDragTarget);
+  already_AddRefed<nsIArray> GetTransferables(nsIDOMNode* aDragTarget);
 
-  already_AddRefed<nsISupportsArray>
+  already_AddRefed<nsIArray>
   GetTransferables(nsILoadContext* aLoadContext);
 
   // converts the data for a single item at aIndex into an nsITransferable
   // object.
   already_AddRefed<nsITransferable>
   GetTransferable(uint32_t aIndex, nsILoadContext* aLoadContext);
 
   // converts the data in the variant to an nsISupportString if possible or
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -1970,17 +1970,17 @@ EventStateManager::DoDefaultDragStart(ns
     action = nsIDragService::DRAGDROP_ACTION_COPY |
              nsIDragService::DRAGDROP_ACTION_MOVE |
              nsIDragService::DRAGDROP_ACTION_LINK;
 
   // get any custom drag image that was set
   int32_t imageX, imageY;
   Element* dragImage = aDataTransfer->GetDragImage(&imageX, &imageY);
 
-  nsCOMPtr<nsISupportsArray> transArray =
+  nsCOMPtr<nsIArray> transArray =
     aDataTransfer->GetTransferables(dragTarget->AsDOMNode());
   if (!transArray)
     return false;
 
   // XXXndeakin don't really want to create a new drag DOM event
   // here, but we need something to pass to the InvokeDragSession
   // methods.
   RefPtr<DragEvent> event =
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -4687,17 +4687,17 @@ ContentParent::MaybeInvokeDragSession(Ta
         session->SetDataTransfer(transfer);
       }
       // Note, even though this fills the DataTransfer object with
       // external data, the data is usually transfered over IPC lazily when
       // needed.
       transfer->FillAllExternalData();
       nsCOMPtr<nsILoadContext> lc = aParent ?
                                      aParent->GetLoadContext() : nullptr;
-      nsCOMPtr<nsISupportsArray> transferables =
+      nsCOMPtr<nsIArray> transferables =
         transfer->GetTransferables(lc);
       nsContentUtils::TransferablesToIPCTransferables(transferables,
                                                       dataTransfers,
                                                       false,
                                                       nullptr,
                                                       this);
       uint32_t action;
       session->GetDragAction(&action);
--- a/widget/cocoa/nsDragService.h
+++ b/widget/cocoa/nsDragService.h
@@ -17,17 +17,17 @@ extern NSString* const kCorePboardType_u
 extern NSString* const kCustomTypesPboardType;
 
 class nsDragService : public nsBaseDragService
 {
 public:
   nsDragService();
 
   // nsBaseDragService
-  virtual nsresult InvokeDragSessionImpl(nsISupportsArray* anArrayTransferables,
+  virtual nsresult InvokeDragSessionImpl(nsIArray* anArrayTransferables,
                                          nsIScriptableRegion* aRegion,
                                          uint32_t aActionType);
   // nsIDragService
   NS_IMETHOD EndDragSession(bool aDoneDrag);
 
   // nsIDragSession
   NS_IMETHOD GetData(nsITransferable * aTransferable, uint32_t aItemIndex);
   NS_IMETHOD IsDataFlavorSupported(const char *aDataFlavor, bool *_retval);
@@ -42,14 +42,14 @@ private:
                               nsIntRect* aDragRect,
                               nsIScriptableRegion* aRegion);
   bool IsValidType(NSString* availableType, bool allowFileURL);
   NSString* GetStringForType(NSPasteboardItem* item, const NSString* type,
                              bool allowFileURL = false);
   NSString* GetTitleForURL(NSPasteboardItem* item);
   NSString* GetFilePath(NSPasteboardItem* item);
 
-  nsCOMPtr<nsISupportsArray> mDataItems; // only valid for a drag started within gecko
+  nsCOMPtr<nsIArray> mDataItems; // only valid for a drag started within gecko
   NSView* mNativeDragView;
   NSEvent* mNativeDragEvent;
 };
 
 #endif // nsDragService_h_
--- a/widget/cocoa/nsDragService.mm
+++ b/widget/cocoa/nsDragService.mm
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Logging.h"
 
+#include "nsArrayUtils.h"
 #include "nsDragService.h"
 #include "nsArrayUtils.h"
 #include "nsObjCExceptions.h"
 #include "nsITransferable.h"
 #include "nsString.h"
 #include "nsClipboard.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
@@ -38,17 +39,17 @@ extern void EnsureLogInitialized();
 
 extern NSPasteboard* globalDragPboard;
 extern NSView* gLastDragView;
 extern NSEvent* gLastDragMouseDownEvent;
 extern bool gUserCancelledDrag;
 
 // This global makes the transferable array available to Cocoa's promised
 // file destination callback.
-nsISupportsArray *gDraggedTransferables = nullptr;
+nsIArray *gDraggedTransferables = nullptr;
 
 NSString* const kWildcardPboardType = @"MozillaWildcard";
 NSString* const kCorePboardType_url  = @"CorePasteboardFlavorType 0x75726C20"; // 'url '  url
 NSString* const kCorePboardType_urld = @"CorePasteboardFlavorType 0x75726C64"; // 'urld'  desc
 NSString* const kCorePboardType_urln = @"CorePasteboardFlavorType 0x75726C6E"; // 'urln'  title
 NSString* const kUTTypeURLName = @"public.url-name";
 NSString* const kCustomTypesPboardType = @"org.mozilla.custom-clipdata";
 
@@ -59,35 +60,30 @@ nsDragService::nsDragService()
 
   EnsureLogInitialized();
 }
 
 nsDragService::~nsDragService()
 {
 }
 
-static nsresult SetUpDragClipboard(nsISupportsArray* aTransferableArray)
+static nsresult SetUpDragClipboard(nsIArray* aTransferableArray)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   if (!aTransferableArray)
     return NS_ERROR_FAILURE;
 
   uint32_t count = 0;
-  aTransferableArray->Count(&count);
+  aTransferableArray->GetLength(&count);
 
   NSPasteboard* dragPBoard = [NSPasteboard pasteboardWithName:NSDragPboard];
 
   for (uint32_t j = 0; j < count; j++) {
-    nsCOMPtr<nsISupports> currentTransferableSupports;
-    aTransferableArray->GetElementAt(j, getter_AddRefs(currentTransferableSupports));
-    if (!currentTransferableSupports)
-      return NS_ERROR_FAILURE;
-
-    nsCOMPtr<nsITransferable> currentTransferable(do_QueryInterface(currentTransferableSupports));
+    nsCOMPtr<nsITransferable> currentTransferable = do_QueryElementAt(aTransferableArray, j);
     if (!currentTransferable)
       return NS_ERROR_FAILURE;
 
     // Transform the transferable to an NSDictionary
     NSDictionary* pasteboardOutputDict = nsClipboard::PasteboardDictFromTransferable(currentTransferable);
     if (!pasteboardOutputDict)
       return NS_ERROR_FAILURE;
 
@@ -305,17 +301,17 @@ nsDragService::GetFilePath(NSPasteboardI
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
 // We can only invoke NSView's 'dragImage:at:offset:event:pasteboard:source:slideBack:' from
 // within NSView's 'mouseDown:' or 'mouseDragged:'. Luckily 'mouseDragged' is always on the
 // stack when InvokeDragSession gets called.
 nsresult
-nsDragService::InvokeDragSessionImpl(nsISupportsArray* aTransferableArray,
+nsDragService::InvokeDragSessionImpl(nsIArray* aTransferableArray,
                                      nsIScriptableRegion* aDragRgn,
                                      uint32_t aActionType)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   mDataItems = aTransferableArray;
 
   // put data on the clipboard
@@ -394,35 +390,31 @@ nsDragService::GetData(nsITransferable* 
     return NS_ERROR_FAILURE;
 
   uint32_t acceptableFlavorCount;
   flavorList->GetLength(&acceptableFlavorCount);
 
   // if this drag originated within Mozilla we should just use the cached data from
   // when the drag started if possible
   if (mDataItems) {
-    nsCOMPtr<nsISupports> currentTransferableSupports;
-    mDataItems->GetElementAt(aItemIndex, getter_AddRefs(currentTransferableSupports));
-    if (currentTransferableSupports) {
-      nsCOMPtr<nsITransferable> currentTransferable(do_QueryInterface(currentTransferableSupports));
-      if (currentTransferable) {
-        for (uint32_t i = 0; i < acceptableFlavorCount; i++) {
-          nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
-          if (!currentFlavor)
-            continue;
-          nsXPIDLCString flavorStr;
-          currentFlavor->ToString(getter_Copies(flavorStr));
+    nsCOMPtr<nsITransferable> currentTransferable = do_QueryElementAt(mDataItems, aItemIndex);
+    if (currentTransferable) {
+      for (uint32_t i = 0; i < acceptableFlavorCount; i++) {
+        nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
+        if (!currentFlavor)
+          continue;
+        nsXPIDLCString flavorStr;
+        currentFlavor->ToString(getter_Copies(flavorStr));
 
-          nsCOMPtr<nsISupports> dataSupports;
-          uint32_t dataSize = 0;
-          rv = currentTransferable->GetTransferData(flavorStr, getter_AddRefs(dataSupports), &dataSize);
-          if (NS_SUCCEEDED(rv)) {
-            aTransferable->SetTransferData(flavorStr, dataSupports, dataSize);
-            return NS_OK; // maybe try to fill in more types? Is there a point?
-          }
+        nsCOMPtr<nsISupports> dataSupports;
+        uint32_t dataSize = 0;
+        rv = currentTransferable->GetTransferData(flavorStr, getter_AddRefs(dataSupports), &dataSize);
+        if (NS_SUCCEEDED(rv)) {
+          aTransferable->SetTransferData(flavorStr, dataSupports, dataSize);
+          return NS_OK; // maybe try to fill in more types? Is there a point?
         }
       }
     }
   }
 
   // now check the actual clipboard for data
   for (uint32_t i = 0; i < acceptableFlavorCount; i++) {
     nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
@@ -578,24 +570,19 @@ nsDragService::IsDataFlavorSupported(con
   if (!globalDragPboard)
     return NS_ERROR_FAILURE;
 
   nsDependentCString dataFlavor(aDataFlavor);
 
   // first see if we have data for this in our cached transferable
   if (mDataItems) {
     uint32_t dataItemsCount;
-    mDataItems->Count(&dataItemsCount);
+    mDataItems->GetLength(&dataItemsCount);
     for (unsigned int i = 0; i < dataItemsCount; i++) {
-      nsCOMPtr<nsISupports> currentTransferableSupports;
-      mDataItems->GetElementAt(i, getter_AddRefs(currentTransferableSupports));
-      if (!currentTransferableSupports)
-        continue;
-
-      nsCOMPtr<nsITransferable> currentTransferable(do_QueryInterface(currentTransferableSupports));
+      nsCOMPtr<nsITransferable> currentTransferable = do_QueryElementAt(mDataItems, i);
       if (!currentTransferable)
         continue;
 
       nsCOMPtr<nsIArray> flavorList;
       nsresult rv = currentTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
       if (NS_FAILED(rv))
         continue;
 
@@ -649,17 +636,17 @@ NS_IMETHODIMP
 nsDragService::GetNumDropItems(uint32_t* aNumItems)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   *aNumItems = 0;
 
   // first check to see if we have a number of items cached
   if (mDataItems) {
-    mDataItems->Count(aNumItems);
+    mDataItems->GetLength(aNumItems);
     return NS_OK;
   }
 
   NSArray* droppedItems = [globalDragPboard pasteboardItems];
   if (droppedItems) {
     *aNumItems = [droppedItems count];
   }
 
--- a/widget/gtk/nsDragService.cpp
+++ b/widget/gtk/nsDragService.cpp
@@ -35,16 +35,17 @@
 #include "nsIDocument.h"
 #include "nsISelection.h"
 #include "nsViewManager.h"
 #include "nsIFrame.h"
 #include "nsGtkUtils.h"
 #include "mozilla/gfx/2D.h"
 #include "gfxPlatform.h"
 #include "nsScreenGtk.h"
+#include "nsArrayUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
 // This sets how opaque the drag image is
 #define DRAG_IMAGE_ALPHA_LEVEL 0.5
 
 // These values are copied from GtkDragResult (rather than using GtkDragResult
@@ -296,17 +297,17 @@ GetGtkWindow(nsIDOMDocument *aDocument)
 
     return GTK_WINDOW(toplevel);
 }   
 
 // nsIDragService
 
 NS_IMETHODIMP
 nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode,
-                                 nsISupportsArray * aArrayTransferables,
+                                 nsIArray * aArrayTransferables,
                                  nsIScriptableRegion * aRegion,
                                  uint32_t aActionType,
                                  nsContentPolicyType aContentPolicyType =
                                    nsIContentPolicy::TYPE_OTHER)
 {
     MOZ_LOG(sDragLm, LogLevel::Debug, ("nsDragService::InvokeDragSession"));
 
     // If the previous source drag has not yet completed, signal handlers need
@@ -318,17 +319,17 @@ nsDragService::InvokeDragSession(nsIDOMN
 
     return nsBaseDragService::InvokeDragSession(aDOMNode, aArrayTransferables,
                                                 aRegion, aActionType,
                                                 aContentPolicyType);
 }
 
 // nsBaseDragService
 nsresult
-nsDragService::InvokeDragSessionImpl(nsISupportsArray* aArrayTransferables,
+nsDragService::InvokeDragSessionImpl(nsIArray* aArrayTransferables,
                                      nsIScriptableRegion* aRegion,
                                      uint32_t aActionType)
 {
     // make sure that we have an array of transferables to use
     if (!aArrayTransferables)
         return NS_ERROR_INVALID_ARG;
     // set our reference to the transferables.  this will also addref
     // the transferables since we're going to hang onto this beyond the
@@ -664,17 +665,17 @@ nsDragService::GetNumDropItems(uint32_t 
                ("*** warning: GetNumDropItems \
                called without a valid target widget!\n"));
         *aNumItems = 0;
         return NS_OK;
     }
 
     bool isList = IsTargetContextList();
     if (isList)
-        mSourceDataItems->Count(aNumItems);
+        mSourceDataItems->GetLength(aNumItems);
     else {
         GdkAtom gdkFlavor = gdk_atom_intern(gTextUriListType, FALSE);
         GetTargetDragData(gdkFlavor);
         if (mTargetDragData) {
             const char *data = reinterpret_cast<char*>(mTargetDragData);
             *aNumItems = CountTextUriListItems(data, mTargetDragDataLen);
         } else
             *aNumItems = 1;
@@ -728,20 +729,18 @@ nsDragService::GetData(nsITransferable *
                 continue;
 
             nsXPIDLCString flavorStr;
             currentFlavor->ToString(getter_Copies(flavorStr));
             MOZ_LOG(sDragLm,
                    LogLevel::Debug,
                    ("flavor is %s\n", (const char *)flavorStr));
             // get the item with the right index
-            nsCOMPtr<nsISupports> genericItem;
-            mSourceDataItems->GetElementAt(aItemIndex,
-                                           getter_AddRefs(genericItem));
-            nsCOMPtr<nsITransferable> item(do_QueryInterface(genericItem));
+            nsCOMPtr<nsITransferable> item =
+                do_QueryElementAt(mSourceDataItems, aItemIndex);
             if (!item)
                 continue;
 
             nsCOMPtr<nsISupports> data;
             uint32_t tmpDataLen = 0;
             MOZ_LOG(sDragLm, LogLevel::Debug,
                    ("trying to get transfer data for %s\n",
                    (const char *)flavorStr));
@@ -1018,22 +1017,20 @@ nsDragService::IsDataFlavorSupported(con
     // for it.
     if (isList) {
         MOZ_LOG(sDragLm, LogLevel::Debug, ("It's a list.."));
         uint32_t numDragItems = 0;
         // if we don't have mDataItems we didn't start this drag so it's
         // an external client trying to fool us.
         if (!mSourceDataItems)
             return NS_OK;
-        mSourceDataItems->Count(&numDragItems);
+        mSourceDataItems->GetLength(&numDragItems);
         for (uint32_t itemIndex = 0; itemIndex < numDragItems; ++itemIndex) {
-            nsCOMPtr<nsISupports> genericItem;
-            mSourceDataItems->GetElementAt(itemIndex,
-                                           getter_AddRefs(genericItem));
-            nsCOMPtr<nsITransferable> currItem(do_QueryInterface(genericItem));
+            nsCOMPtr<nsITransferable> currItem =
+                do_QueryElementAt(mSourceDataItems, itemIndex);
             if (currItem) {
                 nsCOMPtr <nsIArray> flavorList;
                 currItem->FlavorsTransferableCanExport(
                           getter_AddRefs(flavorList));
                 if (flavorList) {
                     uint32_t numFlavors;
                     flavorList->GetLength( &numFlavors );
                     for ( uint32_t flavorIndex = 0;
@@ -1238,17 +1235,17 @@ nsDragService::GetSourceList(void)
     if (!mSourceDataItems)
         return nullptr;
     nsTArray<GtkTargetEntry*> targetArray;
     GtkTargetEntry *targets;
     GtkTargetList  *targetList = 0;
     uint32_t targetCount = 0;
     unsigned int numDragItems = 0;
 
-    mSourceDataItems->Count(&numDragItems);
+    mSourceDataItems->GetLength(&numDragItems);
 
     // Check to see if we're dragging > 1 item.
     if (numDragItems > 1) {
         // as the Xdnd protocol only supports a single item (or is it just
         // gtk's implementation?), we don't advertise all flavours listed
         // in the nsITransferable.
 
         // the application/x-moz-internal-item-list format, which preserves
@@ -1258,19 +1255,18 @@ nsDragService::GetSourceList(void)
         listTarget->target = g_strdup(gMimeListType);
         listTarget->flags = 0;
         MOZ_LOG(sDragLm, LogLevel::Debug,
                ("automatically adding target %s\n", listTarget->target));
         targetArray.AppendElement(listTarget);
 
         // check what flavours are supported so we can decide what other
         // targets to advertise.
-        nsCOMPtr<nsISupports> genericItem;
-        mSourceDataItems->GetElementAt(0, getter_AddRefs(genericItem));
-        nsCOMPtr<nsITransferable> currItem(do_QueryInterface(genericItem));
+        nsCOMPtr<nsITransferable> currItem =
+            do_QueryElementAt(mSourceDataItems, 0);
 
         if (currItem) {
             nsCOMPtr <nsIArray> flavorList;
             currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
             if (flavorList) {
                 uint32_t numFlavors;
                 flavorList->GetLength( &numFlavors );
                 for (uint32_t flavorIndex = 0;
@@ -1295,19 +1291,18 @@ nsDragService::GetSourceList(void)
                                     listTarget->target));
                             targetArray.AppendElement(listTarget);
                         }
                     }
                 } // foreach flavor in item
             } // if valid flavor list
         } // if item is a transferable
     } else if (numDragItems == 1) {
-        nsCOMPtr<nsISupports> genericItem;
-        mSourceDataItems->GetElementAt(0, getter_AddRefs(genericItem));
-        nsCOMPtr<nsITransferable> currItem(do_QueryInterface(genericItem));
+        nsCOMPtr<nsITransferable> currItem =
+            do_QueryElementAt(mSourceDataItems, 0);
         if (currItem) {
             nsCOMPtr <nsIArray> flavorList;
             currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
             if (flavorList) {
                 uint32_t numFlavors;
                 flavorList->GetLength( &numFlavors );
                 for (uint32_t flavorIndex = 0;
                      flavorIndex < numFlavors ;
@@ -1458,27 +1453,25 @@ nsDragService::SourceEndDragSession(GdkD
         mDataTransfer->SetDropEffectInt(dropEffect);
     }
 
     // Schedule the appropriate drag end dom events.
     Schedule(eDragTaskSourceEnd, nullptr, nullptr, LayoutDeviceIntPoint(), 0);
 }
 
 static void
-CreateUriList(nsISupportsArray *items, gchar **text, gint *length)
+CreateUriList(nsIArray *items, gchar **text, gint *length)
 {
     uint32_t i, count;
     GString *uriList = g_string_new(nullptr);
 
-    items->Count(&count);
+    items->GetLength(&count);
     for (i = 0; i < count; i++) {
-        nsCOMPtr<nsISupports> genericItem;
-        items->GetElementAt(i, getter_AddRefs(genericItem));
         nsCOMPtr<nsITransferable> item;
-        item = do_QueryInterface(genericItem);
+        item = do_QueryElementAt(items, i);
 
         if (item) {
             uint32_t tmpDataLen = 0;
             void    *tmpData = nullptr;
             nsresult rv = NS_OK;
             nsCOMPtr<nsISupports> data;
             rv = item->GetTransferData(kURLMime,
                                        getter_AddRefs(data),
@@ -1547,20 +1540,18 @@ nsDragService::SourceDataGet(GtkWidget  
     mimeFlavor.Adopt(strdup(typeName));
     g_free(typeName);
     // check to make sure that we have data items to return.
     if (!mSourceDataItems) {
         MOZ_LOG(sDragLm, LogLevel::Debug, ("Failed to get our data items\n"));
         return;
     }
 
-    nsCOMPtr<nsISupports> genericItem;
-    mSourceDataItems->GetElementAt(0, getter_AddRefs(genericItem));
     nsCOMPtr<nsITransferable> item;
-    item = do_QueryInterface(genericItem);
+    item = do_QueryElementAt(mSourceDataItems, 0);
     if (item) {
         // if someone was asking for text/plain, lookup unicode instead so
         // we can convert it.
         bool needToDoConversionToPlainText = false;
         const char* actualFlavor = mimeFlavor;
         if (strcmp(mimeFlavor, kTextMime) == 0 ||
             strcmp(mimeFlavor, gTextPlainUTF8Type) == 0) {
             actualFlavor = kUnicodeMime;
--- a/widget/gtk/nsDragService.h
+++ b/widget/gtk/nsDragService.h
@@ -54,22 +54,22 @@ class nsDragService final : public nsBas
 public:
     nsDragService();
 
     NS_DECL_ISUPPORTS_INHERITED
 
     NS_DECL_NSIOBSERVER
 
     // nsBaseDragService
-    virtual nsresult InvokeDragSessionImpl(nsISupportsArray* anArrayTransferables,
+    virtual nsresult InvokeDragSessionImpl(nsIArray* anArrayTransferables,
                                            nsIScriptableRegion* aRegion,
                                            uint32_t aActionType) override;
     // nsIDragService
     NS_IMETHOD InvokeDragSession (nsIDOMNode *aDOMNode,
-                                  nsISupportsArray * anArrayTransferables,
+                                  nsIArray * anArrayTransferables,
                                   nsIScriptableRegion * aRegion,
                                   uint32_t aActionType,
                                   nsContentPolicyType aContentPolicyType) override;
     NS_IMETHOD StartDragSession() override;
     NS_IMETHOD EndDragSession(bool aDoneDrag) override;
 
     // nsIDragSession
     NS_IMETHOD SetCanDrop            (bool             aCanDrop) override;
@@ -189,17 +189,17 @@ private:
     // this will reset all of the target vars
     void           TargetResetData(void);
 
     // source side vars
 
     // the source of our drags
     GtkWidget     *mHiddenWidget;
     // our source data items
-    nsCOMPtr<nsISupportsArray> mSourceDataItems;
+    nsCOMPtr<nsIArray> mSourceDataItems;
 
     nsCOMPtr<nsIScriptableRegion> mSourceRegion;
 
     // get a list of the sources in gtk's format
     GtkTargetList *GetSourceList(void);
 
     // attempts to create a semi-transparent drag image. Returns TRUE if
     // successful, FALSE if not
--- a/widget/nsBaseDragService.cpp
+++ b/widget/nsBaseDragService.cpp
@@ -202,17 +202,17 @@ nsBaseDragService::SetDataTransfer(nsIDO
 {
   mDataTransfer = aDataTransfer;
   return NS_OK;
 }
 
 //-------------------------------------------------------------------------
 NS_IMETHODIMP
 nsBaseDragService::InvokeDragSession(nsIDOMNode *aDOMNode,
-                                     nsISupportsArray* aTransferableArray,
+                                     nsIArray* aTransferableArray,
                                      nsIScriptableRegion* aDragRgn,
                                      uint32_t aActionType,
                                      nsContentPolicyType aContentPolicyType =
                                        nsIContentPolicy::TYPE_OTHER)
 {
   PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
 
   NS_ENSURE_TRUE(aDOMNode, NS_ERROR_INVALID_ARG);
@@ -238,17 +238,17 @@ nsBaseDragService::InvokeDragSession(nsI
     mSourceDocument = nullptr;
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsBaseDragService::InvokeDragSessionWithImage(nsIDOMNode* aDOMNode,
-                                              nsISupportsArray* aTransferableArray,
+                                              nsIArray* aTransferableArray,
                                               nsIScriptableRegion* aRegion,
                                               uint32_t aActionType,
                                               nsIDOMNode* aImage,
                                               int32_t aImageX, int32_t aImageY,
                                               nsIDOMDragEvent* aDragEvent,
                                               nsIDOMDataTransfer* aDataTransfer)
 {
   NS_ENSURE_TRUE(aDragEvent, NS_ERROR_NULL_POINTER);
@@ -276,17 +276,17 @@ nsBaseDragService::InvokeDragSessionWith
     mDataTransfer = nullptr;
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsBaseDragService::InvokeDragSessionWithSelection(nsISelection* aSelection,
-                                                  nsISupportsArray* aTransferableArray,
+                                                  nsIArray* aTransferableArray,
                                                   uint32_t aActionType,
                                                   nsIDOMDragEvent* aDragEvent,
                                                   nsIDOMDataTransfer* aDataTransfer)
 {
   NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
   NS_ENSURE_TRUE(aDragEvent, NS_ERROR_NULL_POINTER);
   NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
 
--- a/widget/nsBaseDragService.h
+++ b/widget/nsBaseDragService.h
@@ -70,17 +70,17 @@ public:
 protected:
   virtual ~nsBaseDragService();
 
   /**
    * Called from nsBaseDragService to initiate a platform drag from a source
    * in this process.  This is expected to ensure that StartDragSession() and
    * EndDragSession() get called if the platform drag is successfully invoked.
    */
-  virtual nsresult InvokeDragSessionImpl(nsISupportsArray* aTransferableArray,
+  virtual nsresult InvokeDragSessionImpl(nsIArray* aTransferableArray,
                                          nsIScriptableRegion* aDragRgn,
                                          uint32_t aActionType) = 0;
 
   /**
    * Draw the drag image, if any, to a surface and return it. The drag image
    * is constructed from mImage if specified, or aDOMNode if mImage is null.
    *
    * aRegion may be used to draw only a subset of the element. This region
--- a/widget/nsDragServiceProxy.cpp
+++ b/widget/nsDragServiceProxy.cpp
@@ -23,17 +23,17 @@ nsDragServiceProxy::nsDragServiceProxy()
 {
 }
 
 nsDragServiceProxy::~nsDragServiceProxy()
 {
 }
 
 nsresult
-nsDragServiceProxy::InvokeDragSessionImpl(nsISupportsArray* aArrayTransferables,
+nsDragServiceProxy::InvokeDragSessionImpl(nsIArray* aArrayTransferables,
                                           nsIScriptableRegion* aRegion,
                                           uint32_t aActionType)
 {
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(mSourceDocument);
   NS_ENSURE_STATE(doc->GetDocShell());
   TabChild* child = TabChild::GetFrom(doc->GetDocShell());
   NS_ENSURE_STATE(child);
   nsTArray<mozilla::dom::IPCDataTransfer> dataTransfers;
--- a/widget/nsDragServiceProxy.h
+++ b/widget/nsDragServiceProxy.h
@@ -11,16 +11,16 @@
 class nsDragServiceProxy : public nsBaseDragService
 {
 public:
   nsDragServiceProxy();
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsBaseDragService
-  virtual nsresult InvokeDragSessionImpl(nsISupportsArray* anArrayTransferables,
+  virtual nsresult InvokeDragSessionImpl(nsIArray* anArrayTransferables,
                                          nsIScriptableRegion* aRegion,
                                          uint32_t aActionType) override;
 private:
   virtual ~nsDragServiceProxy();
 };
 
 #endif // NSDRAGSERVICEPROXY_H
--- a/widget/nsIDragService.idl
+++ b/widget/nsIDragService.idl
@@ -1,16 +1,16 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "nsIArray.idl"
 #include "nsISupports.idl"
-#include "nsISupportsArray.idl"
 #include "nsIDragSession.idl"
 #include "nsIScriptableRegion.idl"
 #include "nsIContentPolicyBase.idl"
 
 interface nsIDOMNode;
 interface nsIDOMDragEvent;
 interface nsIDOMDataTransfer;
 interface nsISelection;
@@ -33,36 +33,40 @@ interface nsIDragService : nsISupports
 {
   const long DRAGDROP_ACTION_NONE = 0;
   const long DRAGDROP_ACTION_COPY = 1;
   const long DRAGDROP_ACTION_MOVE = 2;
   const long DRAGDROP_ACTION_LINK = 4;
   const long DRAGDROP_ACTION_UNINITIALIZED = 64;
 
   /**
-    * Starts a modal drag session with an array of transaferables 
+    * Starts a modal drag session with an array of transaferables.
+    *
+    * Note: This method is deprecated for non-native code.
     *
     * @param  aTransferables - an array of transferables to be dragged
     * @param  aRegion - a region containing rectangles for cursor feedback, 
     *            in window coordinates.
     * @param  aActionType - specified which of copy/move/link are allowed
     * @param  aContentPolicyType - the contentPolicyType that will be
     *           passed to the loadInfo when creating a new channel
     *           (defaults to TYPE_OTHER)
     */
   void invokeDragSession (in nsIDOMNode aDOMNode,
-                          in nsISupportsArray aTransferables, 
+                          in nsIArray aTransferables, 
                           in nsIScriptableRegion aRegion,
                           in unsigned long aActionType,
                           [optional] in nsContentPolicyType aContentPolicyType);
 
   /**
    * Starts a modal drag session using an image. The first four arguments are
    * the same as invokeDragSession.
    *
+   * Note: This method is deprecated for non-native code.
+   *
    * A custom image may be specified using the aImage argument. If this is
    * supplied, the aImageX and aImageY arguments specify the offset within
    * the image where the cursor would be positioned. That is, when the image
    * is drawn, it is offset up and left the amount so that the cursor appears
    * at that location within the image.
    *
    * If aImage is null, aImageX and aImageY are not used and the image is instead
    * determined from the source node aDOMNode, and the offset calculated so that
@@ -75,32 +79,34 @@ interface nsIDragService : nsISupports
    * rendered at its real size. For other types of elements, the element is
    * rendered into an offscreen buffer in the same manner as it is currently
    * displayed. The document selection is hidden while drawing.
    *
    * The aDragEvent must be supplied as the current screen coordinates of the
    * event are needed to calculate the image location.
    */
   void invokeDragSessionWithImage(in nsIDOMNode aDOMNode,
-                                  in nsISupportsArray aTransferableArray,
+                                  in nsIArray aTransferableArray,
                                   in nsIScriptableRegion aRegion,
                                   in unsigned long aActionType,
                                   in nsIDOMNode aImage,
                                   in long aImageX,
                                   in long aImageY,
                                   in nsIDOMDragEvent aDragEvent,
                                   in nsIDOMDataTransfer aDataTransfer);
 
   /**
    * Start a modal drag session using the selection as the drag image.
    * The aDragEvent must be supplied as the current screen coordinates of the
    * event are needed to calculate the image location.
+   *
+   * Note: This method is deprecated for non-native code.
    */
   void invokeDragSessionWithSelection(in nsISelection aSelection,
-                                      in nsISupportsArray aTransferableArray,
+                                      in nsIArray aTransferableArray,
                                       in unsigned long aActionType,
                                       in nsIDOMDragEvent aDragEvent,
                                       in nsIDOMDataTransfer aDataTransfer);
 
   /**
     * Returns the current Drag Session  
     */
   nsIDragSession getCurrentSession ( ) ;
--- a/widget/windows/nsDragService.cpp
+++ b/widget/windows/nsDragService.cpp
@@ -15,20 +15,20 @@
 #include "nsDragService.h"
 #include "nsITransferable.h"
 #include "nsDataObj.h"
 
 #include "nsWidgetsCID.h"
 #include "nsNativeDragTarget.h"
 #include "nsNativeDragSource.h"
 #include "nsClipboard.h"
-#include "nsISupportsArray.h"
 #include "nsIDocument.h"
 #include "nsDataObjCollection.h"
 
+#include "nsArrayUtils.h"
 #include "nsString.h"
 #include "nsEscape.h"
 #include "nsIScreenManager.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIURL.h"
 #include "nsCWebBrowserPersist.h"
 #include "nsToolkit.h"
 #include "nsCRT.h"
@@ -166,30 +166,30 @@ nsDragService::CreateDragImage(nsIDOMNod
 
   dataSurface->Unmap();
 
   return psdi->hbmpDragImage != nullptr;
 }
 
 //-------------------------------------------------------------------------
 nsresult
-nsDragService::InvokeDragSessionImpl(nsISupportsArray* anArrayTransferables,
+nsDragService::InvokeDragSessionImpl(nsIArray* anArrayTransferables,
                                      nsIScriptableRegion* aRegion,
                                      uint32_t aActionType)
 {
   // Try and get source URI of the items that are being dragged
   nsIURI *uri = nullptr;
 
   nsCOMPtr<nsIDocument> doc(do_QueryInterface(mSourceDocument));
   if (doc) {
     uri = doc->GetDocumentURI();
   }
 
   uint32_t numItemsToDrag = 0;
-  nsresult rv = anArrayTransferables->Count(&numItemsToDrag);
+  nsresult rv = anArrayTransferables->GetLength(&numItemsToDrag);
   if (!numItemsToDrag)
     return NS_ERROR_FAILURE;
 
   // The clipboard class contains some static utility methods that we
   // can use to create an IDataObject from the transferable
 
   // if we're dragging more than one item, we need to create a
   // "collection" object to fake out the OS. This collection contains
@@ -197,19 +197,18 @@ nsDragService::InvokeDragSessionImpl(nsI
   // (most cases), only pass around the native |IDataObject|.
   RefPtr<IDataObject> itemToDrag;
   if (numItemsToDrag > 1) {
     nsDataObjCollection * dataObjCollection = new nsDataObjCollection();
     if (!dataObjCollection)
       return NS_ERROR_OUT_OF_MEMORY;
     itemToDrag = dataObjCollection;
     for (uint32_t i=0; i<numItemsToDrag; ++i) {
-      nsCOMPtr<nsISupports> supports;
-      anArrayTransferables->GetElementAt(i, getter_AddRefs(supports));
-      nsCOMPtr<nsITransferable> trans(do_QueryInterface(supports));
+      nsCOMPtr<nsITransferable> trans =
+          do_QueryElementAt(anArrayTransferables, i);
       if (trans) {
         // set the requestingPrincipal on the transferable
         nsCOMPtr<nsINode> node = do_QueryInterface(mSourceNode);
         trans->SetRequestingPrincipal(node->NodePrincipal());
         trans->SetContentPolicyType(mContentPolicyType);
         RefPtr<IDataObject> dataObj;
         rv = nsClipboard::CreateNativeDataObject(trans,
                                                  getter_AddRefs(dataObj), uri);
@@ -218,19 +217,18 @@ nsDragService::InvokeDragSessionImpl(nsI
         rv = nsClipboard::SetupNativeDataObject(trans, dataObjCollection);
         NS_ENSURE_SUCCESS(rv, rv);
 
         dataObjCollection->AddDataObject(dataObj);
       }
     }
   } // if dragging multiple items
   else {
-    nsCOMPtr<nsISupports> supports;
-    anArrayTransferables->GetElementAt(0, getter_AddRefs(supports));
-    nsCOMPtr<nsITransferable> trans(do_QueryInterface(supports));
+    nsCOMPtr<nsITransferable> trans =
+        do_QueryElementAt(anArrayTransferables, 0);
     if (trans) {
       // set the requestingPrincipal on the transferable
       nsCOMPtr<nsINode> node = do_QueryInterface(mSourceNode);
       trans->SetRequestingPrincipal(node->NodePrincipal());
       trans->SetContentPolicyType(mContentPolicyType);
       rv = nsClipboard::CreateNativeDataObject(trans,
                                                getter_AddRefs(itemToDrag),
                                                uri);
--- a/widget/windows/nsDragService.h
+++ b/widget/windows/nsDragService.h
@@ -19,17 +19,17 @@ class  nsDataObjCollection;
 
 class nsDragService : public nsBaseDragService
 {
 public:
   nsDragService();
   virtual ~nsDragService();
   
   // nsBaseDragService
-  virtual nsresult InvokeDragSessionImpl(nsISupportsArray* anArrayTransferables,
+  virtual nsresult InvokeDragSessionImpl(nsIArray* anArrayTransferables,
                                          nsIScriptableRegion* aRegion,
                                          uint32_t aActionType);
 
   // nsIDragSession
   NS_IMETHOD GetData(nsITransferable * aTransferable, uint32_t anItem);
   NS_IMETHOD GetNumDropItems(uint32_t * aNumItems);
   NS_IMETHOD IsDataFlavorSupported(const char *aDataFlavor, bool *_retval);
   NS_IMETHOD EndDragSession(bool aDoneDrag);
--- a/widget/windows/tests/TestWinDND.cpp
+++ b/widget/windows/tests/TestWinDND.cpp
@@ -3,17 +3,17 @@
  * 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/. */
 #define MOZILLA_INTERNAL_API
 
 #include <ole2.h>
 #include <shlobj.h>
 
 #include "TestHarness.h"
-#include "nsIArray.h"
+#include "nsArray.h"
 #include "nsIFile.h"
 #include "nsNetUtil.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIFileURL.h"
 #include "nsITransferable.h"
 #include "nsClipboard.h"
 #include "nsDataObjCollection.h"
 
@@ -221,79 +221,70 @@ nsresult GetTransferableURI(nsCOMPtr<nsI
   nsCOMPtr<nsISupports> genericWrapper = do_QueryInterface(xferURI);
 
   pTransferable = do_CreateInstance("@mozilla.org/widget/transferable;1");
   pTransferable->Init(nullptr);
   rv = pTransferable->SetTransferData("text/x-moz-url", genericWrapper, 0);
   return rv;
 }
 
-nsresult MakeDataObject(nsISupportsArray* transferableArray,
+nsresult MakeDataObject(nsIArray* transferableArray,
                         RefPtr<IDataObject>& itemToDrag)
 {
   nsresult rv;
   uint32_t itemCount = 0;
 
   nsCOMPtr<nsIURI> uri;
   rv = NS_NewURI(getter_AddRefs(uri), "http://www.mozilla.org");
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = transferableArray->Count(&itemCount);
+  rv = transferableArray->GetLength(&itemCount);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Copied more or less exactly from nsDragService::InvokeDragSession
   // This is what lets us play fake Drag Service for the test
   if (itemCount > 1) {
     nsDataObjCollection * dataObjCollection = new nsDataObjCollection();
     if (!dataObjCollection)
       return NS_ERROR_OUT_OF_MEMORY;
     itemToDrag = dataObjCollection;
     for (uint32_t i=0; i<itemCount; ++i) {
-      nsCOMPtr<nsISupports> supports;
-      transferableArray->GetElementAt(i, getter_AddRefs(supports));
-      nsCOMPtr<nsITransferable> trans(do_QueryInterface(supports));
+      nsCOMPtr<nsITransferable> trans = do_QueryElementAt(transferableArray, i);
       if (trans) {
         RefPtr<IDataObject> dataObj;
         rv = nsClipboard::CreateNativeDataObject(trans,
                                                  getter_AddRefs(dataObj), uri);
         NS_ENSURE_SUCCESS(rv, rv);
         // Add the flavors to the collection object too
         rv = nsClipboard::SetupNativeDataObject(trans, dataObjCollection);
         NS_ENSURE_SUCCESS(rv, rv);
 
         dataObjCollection->AddDataObject(dataObj);
       }
     }
   } // if dragging multiple items
   else {
-    nsCOMPtr<nsISupports> supports;
-    transferableArray->GetElementAt(0, getter_AddRefs(supports));
-    nsCOMPtr<nsITransferable> trans(do_QueryInterface(supports));
+    nsCOMPtr<nsITransferable> trans = do_QueryElementAt(transferableArray, 0);
     if (trans) {
       rv = nsClipboard::CreateNativeDataObject(trans,
                                                getter_AddRefs(itemToDrag),
                                                uri);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   } // else dragging a single object
   return rv;
 }
 
 nsresult Do_CheckOneFile()
 {
   nsresult rv;
   nsCOMPtr<nsITransferable> transferable;
-  nsCOMPtr<nsISupportsArray> transferableArray;
+  nsCOMPtr<nsIMutableArray> transferableArray = nsArray::Create();
   nsCOMPtr<nsISupports> genericWrapper;
   RefPtr<IDataObject> dataObj;
-  rv = NS_NewISupportsArray(getter_AddRefs(transferableArray));
-  if (NS_FAILED(rv)) {
-    fail("Could not create the necessary nsISupportsArray");
-    return rv;
-  }
 
   rv = GetTransferableFile(transferable);
   if (NS_FAILED(rv)) {
     fail("Could not create the proper nsITransferable!");
     return rv;
   }
   genericWrapper = do_QueryInterface(transferable);
   rv = transferableArray->AppendElement(genericWrapper);
@@ -332,24 +323,19 @@ nsresult Do_CheckOneFile()
 
   return NS_OK;
 }
 
 nsresult Do_CheckTwoFiles()
 {
   nsresult rv;
   nsCOMPtr<nsITransferable> transferable;
-  nsCOMPtr<nsISupportsArray> transferableArray;
+  nsCOMPtr<nsIMutableArray> transferableArray = nsArray::Create();
   nsCOMPtr<nsISupports> genericWrapper;
   RefPtr<IDataObject> dataObj;
-  rv = NS_NewISupportsArray(getter_AddRefs(transferableArray));
-  if (NS_FAILED(rv)) {
-    fail("Could not create the necessary nsISupportsArray");
-    return rv;
-  }
 
   rv = GetTransferableFile(transferable);
   if (NS_FAILED(rv)) {
     fail("Could not create the proper nsITransferable!");
     return rv;
   }
   genericWrapper = do_QueryInterface(transferable);
   rv = transferableArray->AppendElement(genericWrapper);
@@ -400,24 +386,19 @@ nsresult Do_CheckTwoFiles()
 
   return NS_OK;
 }
 
 nsresult Do_CheckOneString()
 {
   nsresult rv;
   nsCOMPtr<nsITransferable> transferable;
-  nsCOMPtr<nsISupportsArray> transferableArray;
+  nsCOMPtr<nsIMutableArray> transferableArray = nsArray::Create();
   nsCOMPtr<nsISupports> genericWrapper;
   RefPtr<IDataObject> dataObj;
-  rv = NS_NewISupportsArray(getter_AddRefs(transferableArray));
-  if (NS_FAILED(rv)) {
-    fail("Could not create the necessary nsISupportsArray");
-    return rv;
-  }
 
   rv = GetTransferableText(transferable);
   if (NS_FAILED(rv)) {
     fail("Could not create the proper nsITransferable!");
     return rv;
   }
   genericWrapper = do_QueryInterface(transferable);
   rv = transferableArray->AppendElement(genericWrapper);
@@ -473,24 +454,19 @@ nsresult Do_CheckOneString()
   
   return NS_OK;
 }
 
 nsresult Do_CheckTwoStrings()
 {
   nsresult rv;
   nsCOMPtr<nsITransferable> transferable;
-  nsCOMPtr<nsISupportsArray> transferableArray;
+  nsCOMPtr<nsIMutableArray> transferableArray = nsArray::Create();
   nsCOMPtr<nsISupports> genericWrapper;
   RefPtr<IDataObject> dataObj;
-  rv = NS_NewISupportsArray(getter_AddRefs(transferableArray));
-  if (NS_FAILED(rv)) {
-    fail("Could not create the necessary nsISupportsArray");
-    return rv;
-  }
 
   rv = GetTransferableText(transferable);
   if (NS_FAILED(rv)) {
     fail("Could not create the proper nsITransferable!");
     return rv;
   }
   genericWrapper = do_QueryInterface(transferable);
   rv = transferableArray->AppendElement(genericWrapper);
@@ -558,24 +534,19 @@ nsresult Do_CheckTwoStrings()
   
   return NS_OK;
 }
 
 nsresult Do_CheckSetArbitraryData(bool aMultiple)
 {
   nsresult rv;
   nsCOMPtr<nsITransferable> transferable;
-  nsCOMPtr<nsISupportsArray> transferableArray;
+  nsCOMPtr<nsIMutableArray> transferableArray = nsArray::Create();
   nsCOMPtr<nsISupports> genericWrapper;
   RefPtr<IDataObject> dataObj;
-  rv = NS_NewISupportsArray(getter_AddRefs(transferableArray));
-  if (NS_FAILED(rv)) {
-    fail("Could not create the necessary nsISupportsArray");
-    return rv;
-  }
 
   rv = GetTransferableText(transferable);
   if (NS_FAILED(rv)) {
     fail("Could not create the proper nsITransferable!");
     return rv;
   }
   genericWrapper = do_QueryInterface(transferable);
   rv = transferableArray->AppendElement(genericWrapper);