Bug 1497831 - Use nsTArray instead of nsIArray for nsITransferable. r=smaug
authorTom Schuster <evilpies@gmail.com>
Wed, 10 Oct 2018 20:25:54 +0000
changeset 496358 2852663b840e9a4348130dcbf8efdd494f738a76
parent 496357 4530cf55b7b4d86e41080dae86a2ec85f0b29edf
child 496359 55588bdd2ee8f5bcd66c6af0b340d5b02bf0411e
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1497831
milestone64.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 1497831 - Use nsTArray instead of nsIArray for nsITransferable. r=smaug Differential Revision: https://phabricator.services.mozilla.com/D8194
dom/base/nsContentUtils.cpp
widget/cocoa/nsClipboard.mm
widget/cocoa/nsDragService.mm
widget/gtk/nsClipboard.cpp
widget/gtk/nsDragService.cpp
widget/nsClipboardProxy.cpp
widget/nsITransferable.idl
widget/nsTransferable.cpp
widget/nsTransferable.h
widget/windows/nsClipboard.cpp
widget/windows/nsDataObj.cpp
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -7961,217 +7961,208 @@ nsContentUtils::TransferableToIPCTransfe
                                               IPCDataTransfer* aIPCDataTransfer,
                                               bool aInSyncMessage,
                                               mozilla::dom::nsIContentChild* aChild,
                                               mozilla::dom::nsIContentParent* aParent)
 {
   MOZ_ASSERT((aChild && !aParent) || (!aChild && aParent));
 
   if (aTransferable) {
-    nsCOMPtr<nsIArray> flavorList;
-    aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
-    if (flavorList) {
-      uint32_t flavorCount = 0;
-      flavorList->GetLength(&flavorCount);
-      for (uint32_t j = 0; j < flavorCount; ++j) {
-        nsCOMPtr<nsISupportsCString> flavor = do_QueryElementAt(flavorList, j);
-        if (!flavor) {
-          continue;
-        }
-
-        nsAutoCString flavorStr;
-        flavor->GetData(flavorStr);
-        if (!flavorStr.Length()) {
+    nsTArray<nsCString> flavorList;
+    aTransferable->FlavorsTransferableCanExport(flavorList);
+
+    for (uint32_t j = 0; j < flavorList.Length(); ++j) {
+      nsCString& flavorStr = flavorList[j];
+      if (!flavorStr.Length()) {
+        continue;
+      }
+
+      nsCOMPtr<nsISupports> data;
+      uint32_t dataLen = 0;
+      aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data), &dataLen);
+
+      nsCOMPtr<nsISupportsString> text = do_QueryInterface(data);
+      nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data);
+      if (text) {
+        nsAutoString dataAsString;
+        text->GetData(dataAsString);
+        IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
+        item->flavor() = flavorStr;
+        item->data() = dataAsString;
+      } else if (ctext) {
+        nsAutoCString dataAsString;
+        ctext->GetData(dataAsString);
+        IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
+        item->flavor() = flavorStr;
+
+        Shmem dataAsShmem = ConvertToShmem(aChild, aParent, dataAsString);
+        if (!dataAsShmem.IsReadable() || !dataAsShmem.Size<char>()) {
           continue;
         }
 
-        nsCOMPtr<nsISupports> data;
-        uint32_t dataLen = 0;
-        aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data), &dataLen);
-
-        nsCOMPtr<nsISupportsString> text = do_QueryInterface(data);
-        nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data);
-        if (text) {
-          nsAutoString dataAsString;
-          text->GetData(dataAsString);
+        item->data() = dataAsShmem;
+      } else {
+        // Images to be pasted on the clipboard are nsIInputStreams
+        nsCOMPtr<nsIInputStream> stream(do_QueryInterface(data));
+        if (stream) {
           IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
           item->flavor() = flavorStr;
-          item->data() = dataAsString;
-        } else if (ctext) {
-          nsAutoCString dataAsString;
-          ctext->GetData(dataAsString);
-          IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
-          item->flavor() = flavorStr;
-
-          Shmem dataAsShmem = ConvertToShmem(aChild, aParent, dataAsString);
-          if (!dataAsShmem.IsReadable() || !dataAsShmem.Size<char>()) {
+
+          nsCString imageData;
+          NS_ConsumeStream(stream, UINT32_MAX, imageData);
+
+          Shmem imageDataShmem = ConvertToShmem(aChild, aParent, imageData);
+          if (!imageDataShmem.IsReadable() || !imageDataShmem.Size<char>()) {
             continue;
           }
 
-          item->data() = dataAsShmem;
-        } else {
-          // Images to be pasted on the clipboard are nsIInputStreams
-          nsCOMPtr<nsIInputStream> stream(do_QueryInterface(data));
-          if (stream) {
-            IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
-            item->flavor() = flavorStr;
-
-            nsCString imageData;
-            NS_ConsumeStream(stream, UINT32_MAX, imageData);
-
-            Shmem imageDataShmem = ConvertToShmem(aChild, aParent, imageData);
-            if (!imageDataShmem.IsReadable() || !imageDataShmem.Size<char>()) {
-              continue;
-            }
-
-            item->data() = imageDataShmem;
+          item->data() = imageDataShmem;
+          continue;
+        }
+
+        // Images to be placed on the clipboard are imgIContainers.
+        nsCOMPtr<imgIContainer> image(do_QueryInterface(data));
+        if (image) {
+          RefPtr<mozilla::gfx::SourceSurface> surface =
+            image->GetFrame(imgIContainer::FRAME_CURRENT,
+                            imgIContainer::FLAG_SYNC_DECODE);
+          if (!surface) {
+            continue;
+          }
+          RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
+            surface->GetDataSurface();
+          if (!dataSurface) {
+            continue;
+          }
+          size_t length;
+          int32_t stride;
+          IShmemAllocator* allocator = aChild ? static_cast<IShmemAllocator*>(aChild)
+                                              : static_cast<IShmemAllocator*>(aParent);
+          Maybe<Shmem> surfaceData = GetSurfaceData(dataSurface, &length, &stride,
+                                                    allocator);
+
+          if (surfaceData.isNothing()) {
             continue;
           }
 
-          // Images to be placed on the clipboard are imgIContainers.
-          nsCOMPtr<imgIContainer> image(do_QueryInterface(data));
-          if (image) {
-            RefPtr<mozilla::gfx::SourceSurface> surface =
-              image->GetFrame(imgIContainer::FRAME_CURRENT,
-                              imgIContainer::FLAG_SYNC_DECODE);
-            if (!surface) {
-              continue;
-            }
-            RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
-              surface->GetDataSurface();
-            if (!dataSurface) {
-              continue;
+          IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
+          item->flavor() = flavorStr;
+          // Turn item->data() into an nsCString prior to accessing it.
+          item->data() = surfaceData.ref();
+
+          IPCDataTransferImage& imageDetails = item->imageDetails();
+          mozilla::gfx::IntSize size = dataSurface->GetSize();
+          imageDetails.width() = size.width;
+          imageDetails.height() = size.height;
+          imageDetails.stride() = stride;
+          imageDetails.format() = dataSurface->GetFormat();
+
+          continue;
+        }
+
+        // Otherwise, handle this as a file.
+        nsCOMPtr<BlobImpl> blobImpl;
+        nsCOMPtr<nsIFile> file = do_QueryInterface(data);
+        if (file) {
+          // If we can send this over as a blob, do so. Otherwise, we're
+          // responding to a sync message and the child can't process the blob
+          // constructor before processing our response, which would crash. In
+          // that case, hope that the caller is nsClipboardProxy::GetData,
+          // called from editor and send over images as raw data.
+          if (aInSyncMessage) {
+            nsAutoCString type;
+            if (IsFileImage(file, type)) {
+              IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
+              item->flavor() = type;
+              nsAutoCString data;
+              SlurpFileToString(file, data);
+
+              Shmem dataAsShmem = ConvertToShmem(aChild, aParent, data);
+              item->data() = dataAsShmem;
             }
-            size_t length;
-            int32_t stride;
-            IShmemAllocator* allocator = aChild ? static_cast<IShmemAllocator*>(aChild)
-                                                : static_cast<IShmemAllocator*>(aParent);
-            Maybe<Shmem> surfaceData = GetSurfaceData(dataSurface, &length, &stride,
-                                                      allocator);
-
-            if (surfaceData.isNothing()) {
-              continue;
-            }
-
-            IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
-            item->flavor() = flavorStr;
-            // Turn item->data() into an nsCString prior to accessing it.
-            item->data() = surfaceData.ref();
-
-            IPCDataTransferImage& imageDetails = item->imageDetails();
-            mozilla::gfx::IntSize size = dataSurface->GetSize();
-            imageDetails.width() = size.width;
-            imageDetails.height() = size.height;
-            imageDetails.stride() = stride;
-            imageDetails.format() = dataSurface->GetFormat();
 
             continue;
           }
 
-          // Otherwise, handle this as a file.
-          nsCOMPtr<BlobImpl> blobImpl;
-          nsCOMPtr<nsIFile> file = do_QueryInterface(data);
-          if (file) {
-            // If we can send this over as a blob, do so. Otherwise, we're
-            // responding to a sync message and the child can't process the blob
-            // constructor before processing our response, which would crash. In
-            // that case, hope that the caller is nsClipboardProxy::GetData,
-            // called from editor and send over images as raw data.
-            if (aInSyncMessage) {
-              nsAutoCString type;
-              if (IsFileImage(file, type)) {
-                IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
-                item->flavor() = type;
-                nsAutoCString data;
-                SlurpFileToString(file, data);
-
-                Shmem dataAsShmem = ConvertToShmem(aChild, aParent, data);
-                item->data() = dataAsShmem;
+          if (aParent) {
+            bool isDir = false;
+            if (NS_SUCCEEDED(file->IsDirectory(&isDir)) && isDir) {
+              nsAutoString path;
+              if (NS_WARN_IF(NS_FAILED(file->GetPath(path)))) {
+                continue;
               }
 
-              continue;
+              RefPtr<FileSystemSecurity> fss = FileSystemSecurity::GetOrCreate();
+              fss->GrantAccessToContentProcess(aParent->ChildID(), path);
             }
-
-            if (aParent) {
-              bool isDir = false;
-              if (NS_SUCCEEDED(file->IsDirectory(&isDir)) && isDir) {
-                nsAutoString path;
-                if (NS_WARN_IF(NS_FAILED(file->GetPath(path)))) {
-                  continue;
-                }
-
-                RefPtr<FileSystemSecurity> fss = FileSystemSecurity::GetOrCreate();
-                fss->GrantAccessToContentProcess(aParent->ChildID(), path);
-              }
-            }
-
-            blobImpl = new FileBlobImpl(file);
-
-            IgnoredErrorResult rv;
-
-            // Ensure that file data is cached no that the content process
-            // has this data available to it when passed over:
-            blobImpl->GetSize(rv);
-            if (NS_WARN_IF(rv.Failed())) {
+          }
+
+          blobImpl = new FileBlobImpl(file);
+
+          IgnoredErrorResult rv;
+
+          // Ensure that file data is cached no that the content process
+          // has this data available to it when passed over:
+          blobImpl->GetSize(rv);
+          if (NS_WARN_IF(rv.Failed())) {
+            continue;
+          }
+
+          blobImpl->GetLastModified(rv);
+          if (NS_WARN_IF(rv.Failed())) {
+            continue;
+          }
+        } else {
+          if (aInSyncMessage) {
+            // Can't do anything.
+            continue;
+          }
+          blobImpl = do_QueryInterface(data);
+        }
+        if (blobImpl) {
+          IPCDataTransferData data;
+          IPCBlob ipcBlob;
+
+          // If we failed to create the blob actor, then this blob probably
+          // can't get the file size for the underlying file, ignore it for
+          // now. TODO pass this through anyway.
+          if (aChild) {
+            nsresult rv = IPCBlobUtils::Serialize(blobImpl, aChild, ipcBlob);
+            if (NS_WARN_IF(NS_FAILED(rv))) {
               continue;
             }
 
-            blobImpl->GetLastModified(rv);
-            if (NS_WARN_IF(rv.Failed())) {
-              continue;
-            }
-          } else {
-            if (aInSyncMessage) {
-              // Can't do anything.
+            data = ipcBlob;
+          } else if (aParent) {
+            nsresult rv = IPCBlobUtils::Serialize(blobImpl, aParent, ipcBlob);
+            if (NS_WARN_IF(NS_FAILED(rv))) {
               continue;
             }
-            blobImpl = do_QueryInterface(data);
+
+            data = ipcBlob;
           }
-          if (blobImpl) {
-            IPCDataTransferData data;
-            IPCBlob ipcBlob;
-
-            // If we failed to create the blob actor, then this blob probably
-            // can't get the file size for the underlying file, ignore it for
-            // now. TODO pass this through anyway.
-            if (aChild) {
-              nsresult rv = IPCBlobUtils::Serialize(blobImpl, aChild, ipcBlob);
-              if (NS_WARN_IF(NS_FAILED(rv))) {
-                continue;
-              }
-
-              data = ipcBlob;
-            } else if (aParent) {
-              nsresult rv = IPCBlobUtils::Serialize(blobImpl, aParent, ipcBlob);
-              if (NS_WARN_IF(NS_FAILED(rv))) {
-                continue;
-              }
-
-              data = ipcBlob;
-            }
-
+
+          IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
+          item->flavor() = flavorStr;
+          item->data() = data;
+        } else {
+          // This is a hack to support kFilePromiseMime.
+          // On Windows there just needs to be an entry for it,
+          // and for OSX we need to create
+          // nsContentAreaDragDropDataProvider as nsIFlavorDataProvider.
+          if (flavorStr.EqualsLiteral(kFilePromiseMime)) {
             IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
             item->flavor() = flavorStr;
-            item->data() = data;
-          } else {
-            // This is a hack to support kFilePromiseMime.
-            // On Windows there just needs to be an entry for it,
-            // and for OSX we need to create
-            // nsContentAreaDragDropDataProvider as nsIFlavorDataProvider.
-            if (flavorStr.EqualsLiteral(kFilePromiseMime)) {
-              IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
-              item->flavor() = flavorStr;
-              item->data() = NS_ConvertUTF8toUTF16(flavorStr);
-            } else if (!data) {
-              // Empty element, transfer only the flavor
-              IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
-              item->flavor() = flavorStr;
-              item->data() = nsString();
-              continue;
-            }
+            item->data() = NS_ConvertUTF8toUTF16(flavorStr);
+          } else if (!data) {
+            // Empty element, transfer only the flavor
+            IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
+            item->flavor() = flavorStr;
+            item->data() = nsString();
+            continue;
           }
         }
       }
     }
   }
 }
 
 namespace {
--- a/widget/cocoa/nsClipboard.mm
+++ b/widget/cocoa/nsClipboard.mm
@@ -186,31 +186,23 @@ nsClipboard::SetNativeClipboardData(int3
 }
 
 nsresult
 nsClipboard::TransferableFromPasteboard(nsITransferable *aTransferable, NSPasteboard *cocoaPasteboard)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   // get flavor list that includes all acceptable flavors (including ones obtained through conversion)
-  nsCOMPtr<nsIArray> flavorList;
-  nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
+  nsTArray<nsCString> flavors;
+  nsresult rv = aTransferable->FlavorsTransferableCanImport(flavors);
   if (NS_FAILED(rv))
     return NS_ERROR_FAILURE;
 
-  uint32_t flavorCount;
-  flavorList->GetLength(&flavorCount);
-
-  for (uint32_t i = 0; i < flavorCount; i++) {
-    nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
-    if (!currentFlavor)
-      continue;
-
-    nsCString flavorStr;
-    currentFlavor->ToString(getter_Copies(flavorStr)); // i has a flavr
+  for (uint32_t i = 0; i < flavors.Length(); i++) {
+    nsCString& flavorStr = flavors[i];
 
     // printf("looking for clipboard data of type %s\n", flavorStr.get());
 
     NSString *pboardType = nil;
     if (nsClipboard::IsStringType(flavorStr, &pboardType)) {
       NSString* pString = [cocoaPasteboard stringForType:pboardType];
       if (!pString)
         continue;
@@ -378,36 +370,28 @@ nsClipboard::GetNativeClipboardData(nsIT
     cocoaPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard];
   } else {
     cocoaPasteboard = [NSPasteboard generalPasteboard];
   }
   if (!cocoaPasteboard)
     return NS_ERROR_FAILURE;
 
   // get flavor list that includes all acceptable flavors (including ones obtained through conversion)
-  nsCOMPtr<nsIArray> flavorList;
-  nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
+  nsTArray<nsCString> flavors;
+  nsresult rv = aTransferable->FlavorsTransferableCanImport(flavors);
   if (NS_FAILED(rv))
     return NS_ERROR_FAILURE;
 
-  uint32_t flavorCount;
-  flavorList->GetLength(&flavorCount);
-
   // If we were the last ones to put something on the pasteboard, then just use the cached
   // transferable. Otherwise clear it because it isn't relevant any more.
   if (mCachedClipboard == aWhichClipboard &&
       mChangeCount == [cocoaPasteboard changeCount]) {
     if (mTransferable) {
-      for (uint32_t i = 0; i < flavorCount; i++) {
-        nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
-        if (!currentFlavor)
-          continue;
-
-        nsCString flavorStr;
-        currentFlavor->ToString(getter_Copies(flavorStr));
+      for (uint32_t i = 0; i < flavors.Length(); i++) {
+        nsCString& flavorStr = flavors[i];
 
         nsCOMPtr<nsISupports> dataSupports;
         uint32_t dataSize = 0;
         rv = mTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(dataSupports), &dataSize);
         if (NS_SUCCEEDED(rv)) {
           aTransferable->SetTransferData(flavorStr.get(), dataSupports, dataSize);
           return NS_OK; // maybe try to fill in more types? Is there a point?
         }
@@ -434,37 +418,30 @@ nsClipboard::HasDataMatchingFlavors(cons
 
   *outResult = false;
 
   if ((aWhichClipboard != kGlobalClipboard) || !aFlavorList)
     return NS_OK;
 
   // first see if we have data for this in our cached transferable
   if (mTransferable) {
-    nsCOMPtr<nsIArray> transferableFlavorList;
-    nsresult rv = mTransferable->FlavorsTransferableCanImport(getter_AddRefs(transferableFlavorList));
+    nsTArray<nsCString> flavors;
+    nsresult rv = mTransferable->FlavorsTransferableCanImport(flavors);
     if (NS_SUCCEEDED(rv)) {
-      uint32_t transferableFlavorCount;
-      transferableFlavorList->GetLength(&transferableFlavorCount);
-      for (uint32_t j = 0; j < transferableFlavorCount; j++) {
-        nsCOMPtr<nsISupportsCString> currentTransferableFlavor =
-            do_QueryElementAt(transferableFlavorList, j);
-        if (!currentTransferableFlavor)
-          continue;
-        nsCString transferableFlavorStr;
-        currentTransferableFlavor->ToString(getter_Copies(transferableFlavorStr));
+      for (uint32_t j = 0; j < flavors.Length(); j++) {
+        nsCString transferableFlavorStr = flavors[j];
 
         for (uint32_t k = 0; k < aLength; k++) {
           if (transferableFlavorStr.Equals(aFlavorList[k])) {
             *outResult = true;
             return NS_OK;
           }
         }
-      }      
-    }    
+      }
+    }
   }
 
   NSPasteboard* generalPBoard = [NSPasteboard generalPasteboard];
 
   for (uint32_t i = 0; i < aLength; i++) {
     nsDependentCString mimeType(aFlavorList[i]);
     NSString *pboardType = nil;
 
@@ -522,30 +499,23 @@ nsClipboard::PasteboardDictFromTransfera
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
   if (!aTransferable)
     return nil;
 
   NSMutableDictionary* pasteboardOutputDict = [NSMutableDictionary dictionary];
 
-  nsCOMPtr<nsIArray> flavorList;
-  nsresult rv = aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
+  nsTArray<nsCString> flavors;
+  nsresult rv = aTransferable->FlavorsTransferableCanExport(flavors);
   if (NS_FAILED(rv))
     return nil;
 
-  uint32_t flavorCount;
-  flavorList->GetLength(&flavorCount);
-  for (uint32_t i = 0; i < flavorCount; i++) {
-    nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
-    if (!currentFlavor)
-      continue;
-
-    nsCString flavorStr;
-    currentFlavor->ToString(getter_Copies(flavorStr));
+  for (uint32_t i = 0; i < flavors.Length(); i++) {
+    nsCString& flavorStr = flavors[i];
 
     MOZ_LOG(sCocoaLog, LogLevel::Info, ("writing out clipboard data of type %s (%d)\n", flavorStr.get(), i));
 
     NSString *pboardType = nil;
 
     if (nsClipboard::IsStringType(flavorStr, &pboardType)) {
       void* data = nullptr;
       uint32_t dataSize = 0;
--- a/widget/cocoa/nsDragService.mm
+++ b/widget/cocoa/nsDragService.mm
@@ -374,55 +374,43 @@ NS_IMETHODIMP
 nsDragService::GetData(nsITransferable* aTransferable, uint32_t aItemIndex)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   if (!aTransferable)
     return NS_ERROR_FAILURE;
 
   // get flavor list that includes all acceptable flavors (including ones obtained through conversion)
-  nsCOMPtr<nsIArray> flavorList;
-  nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
+  nsTArray<nsCString> flavors;
+  nsresult rv = aTransferable->FlavorsTransferableCanImport(flavors);
   if (NS_FAILED(rv))
     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<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;
-        nsCString flavorStr;
-        currentFlavor->ToString(getter_Copies(flavorStr));
+      for (uint32_t i = 0; i < flavors.Length(); i++) {
+        nsCString& flavorStr = flavors[i];
 
         nsCOMPtr<nsISupports> dataSupports;
         uint32_t dataSize = 0;
         rv = currentTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(dataSupports), &dataSize);
         if (NS_SUCCEEDED(rv)) {
           aTransferable->SetTransferData(flavorStr.get(), 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);
-    if (!currentFlavor)
-      continue;
-
-    nsCString flavorStr;
-    currentFlavor->ToString(getter_Copies(flavorStr));
+  for (uint32_t i = 0; i < flavors.Length(); i++) {
+    nsCString& flavorStr = flavors[i];
 
     MOZ_LOG(sCocoaLog, LogLevel::Info, ("nsDragService::GetData: looking for clipboard data of type %s\n", flavorStr.get()));
 
     NSArray* droppedItems = [globalDragPboard pasteboardItems];
     if (!droppedItems) {
       continue;
     }
 
@@ -583,30 +571,23 @@ nsDragService::IsDataFlavorSupported(con
   if (mDataItems) {
     uint32_t dataItemsCount;
     mDataItems->GetLength(&dataItemsCount);
     for (unsigned int i = 0; i < dataItemsCount; i++) {
       nsCOMPtr<nsITransferable> currentTransferable = do_QueryElementAt(mDataItems, i);
       if (!currentTransferable)
         continue;
 
-      nsCOMPtr<nsIArray> flavorList;
-      nsresult rv = currentTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
+      nsTArray<nsCString> flavors;
+      nsresult rv = currentTransferable->FlavorsTransferableCanImport(flavors);
       if (NS_FAILED(rv))
         continue;
 
-      uint32_t flavorCount;
-      flavorList->GetLength(&flavorCount);
-      for (uint32_t j = 0; j < flavorCount; j++) {
-        nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, j);
-        if (!currentFlavor)
-          continue;
-        nsCString flavorStr;
-        currentFlavor->ToString(getter_Copies(flavorStr));
-        if (dataFlavor.Equals(flavorStr)) {
+      for (uint32_t j = 0; j < flavors.Length(); j++) {
+        if (dataFlavor.Equals(flavors[i])) {
           *_retval = true;
           return NS_OK;
         }
       }
     }
   }
 
   const NSString* type = nil;
--- a/widget/gtk/nsClipboard.cpp
+++ b/widget/gtk/nsClipboard.cpp
@@ -147,62 +147,54 @@ nsClipboard::SetData(nsITransferable *aT
 
     // Clear out the clipboard in order to set the new data
     EmptyClipboard(aWhichClipboard);
 
     // List of suported targets
     GtkTargetList *list = gtk_target_list_new(nullptr, 0);
 
     // Get the types of supported flavors
-    nsCOMPtr<nsIArray> flavors;
-
-    nsresult rv =
-        aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavors));
-    if (!flavors || NS_FAILED(rv))
-        return NS_ERROR_FAILURE;
+    nsTArray<nsCString> flavors;
+    nsresult rv = aTransferable->FlavorsTransferableCanExport(flavors);
+    if (NS_FAILED(rv)) {
+        return rv;
+    }
 
     // Add all the flavors to this widget's supported type.
     bool imagesAdded = false;
-    uint32_t count;
-    flavors->GetLength(&count);
-    for (uint32_t i=0; i < count; i++) {
-        nsCOMPtr<nsISupportsCString> flavor = do_QueryElementAt(flavors, i);
-
-        if (flavor) {
-            nsCString flavorStr;
-            flavor->ToString(getter_Copies(flavorStr));
+    for (uint32_t i = 0; i < flavors.Length(); i++) {
+        nsCString& flavorStr = flavors[i];
 
-            // special case text/unicode since we can handle all of
-            // the string types
-            if (flavorStr.EqualsLiteral(kUnicodeMime)) {
-                gtk_target_list_add(list, gdk_atom_intern("UTF8_STRING", FALSE), 0, 0);
-                gtk_target_list_add(list, gdk_atom_intern("COMPOUND_TEXT", FALSE), 0, 0);
-                gtk_target_list_add(list, gdk_atom_intern("TEXT", FALSE), 0, 0);
-                gtk_target_list_add(list, GDK_SELECTION_TYPE_STRING, 0, 0);
-                continue;
-            }
+        // special case text/unicode since we can handle all of
+        // the string types
+        if (flavorStr.EqualsLiteral(kUnicodeMime)) {
+            gtk_target_list_add(list, gdk_atom_intern("UTF8_STRING", FALSE), 0, 0);
+            gtk_target_list_add(list, gdk_atom_intern("COMPOUND_TEXT", FALSE), 0, 0);
+            gtk_target_list_add(list, gdk_atom_intern("TEXT", FALSE), 0, 0);
+            gtk_target_list_add(list, GDK_SELECTION_TYPE_STRING, 0, 0);
+            continue;
+        }
 
-            if (flavorStr.EqualsLiteral(kNativeImageMime) ||
-                flavorStr.EqualsLiteral(kPNGImageMime) ||
-                flavorStr.EqualsLiteral(kJPEGImageMime) ||
-                flavorStr.EqualsLiteral(kJPGImageMime) ||
-                flavorStr.EqualsLiteral(kGIFImageMime)) {
-                // don't bother adding image targets twice
-                if (!imagesAdded) {
-                    // accept any writable image type
-                    gtk_target_list_add_image_targets(list, 0, TRUE);
-                    imagesAdded = true;
-                }
-                continue;
+        if (flavorStr.EqualsLiteral(kNativeImageMime) ||
+            flavorStr.EqualsLiteral(kPNGImageMime) ||
+            flavorStr.EqualsLiteral(kJPEGImageMime) ||
+            flavorStr.EqualsLiteral(kJPGImageMime) ||
+            flavorStr.EqualsLiteral(kGIFImageMime)) {
+            // don't bother adding image targets twice
+            if (!imagesAdded) {
+                // accept any writable image type
+                gtk_target_list_add_image_targets(list, 0, TRUE);
+                imagesAdded = true;
             }
+            continue;
+        }
 
-            // Add this to our list of valid targets
-            GdkAtom atom = gdk_atom_intern(flavorStr.get(), FALSE);
-            gtk_target_list_add(list, atom, 0, 0);
-        }
+        // Add this to our list of valid targets
+        GdkAtom atom = gdk_atom_intern(flavorStr.get(), FALSE);
+        gtk_target_list_add(list, atom, 0, 0);
     }
 
     // Get GTK clipboard (CLIPBOARD or PRIMARY)
     GtkClipboard *gtkClipboard = gtk_clipboard_get(GetSelectionAtom(aWhichClipboard));
 
     gint numTargets;
     GtkTargetEntry *gtkTargets = gtk_target_table_new_from_list(list, &numTargets);
 
@@ -253,32 +245,24 @@ nsClipboard::SetTransferableData(nsITran
 
 NS_IMETHODIMP
 nsClipboard::GetData(nsITransferable *aTransferable, int32_t aWhichClipboard)
 {
     if (!aTransferable)
         return NS_ERROR_FAILURE;
 
     // Get a list of flavors this transferable can import
-    nsCOMPtr<nsIArray> flavors;
-    nsresult rv;
-    rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavors));
-    if (!flavors || NS_FAILED(rv))
-        return NS_ERROR_FAILURE;
+    nsTArray<nsCString> flavors;
+    nsresult rv = aTransferable->FlavorsTransferableCanImport(flavors);
+    if (NS_FAILED(rv)) {
+        return rv;
+    }
 
-    uint32_t count;
-    flavors->GetLength(&count);
-    for (uint32_t i=0; i < count; i++) {
-        nsCOMPtr<nsISupportsCString> currentFlavor;
-        currentFlavor = do_QueryElementAt(flavors, i);
-        if (!currentFlavor)
-            continue;
-
-        nsCString flavorStr;
-        currentFlavor->ToString(getter_Copies(flavorStr));
+    for (uint32_t i = 0; i < flavors.Length(); i++) {
+        nsCString& flavorStr = flavors[i];
 
         if (flavorStr.EqualsLiteral(kJPEGImageMime) ||
             flavorStr.EqualsLiteral(kJPGImageMime) ||
             flavorStr.EqualsLiteral(kPNGImageMime) ||
             flavorStr.EqualsLiteral(kGIFImageMime)) {
             // Emulate support for image/jpg
             if (flavorStr.EqualsLiteral(kJPGImageMime)) {
                 flavorStr.Assign(kJPEGImageMime);
--- a/widget/gtk/nsDragService.cpp
+++ b/widget/gtk/nsDragService.cpp
@@ -680,43 +680,30 @@ nsDragService::GetData(nsITransferable *
     if (!mTargetWidget) {
         MOZ_LOG(sDragLm, LogLevel::Debug,
                ("*** warning: GetData \
                called without a valid target widget!\n"));
         return NS_ERROR_FAILURE;
     }
 
     // get flavor list that includes all acceptable flavors (including
-    // ones obtained through conversion). Flavors are nsISupportsStrings
-    // so that they can be seen from JS.
-    nsCOMPtr<nsIArray> flavorList;
-    nsresult rv = aTransferable->FlavorsTransferableCanImport(
-                        getter_AddRefs(flavorList));
+    // ones obtained through conversion).
+    nsTArray<nsCString> flavors;
+    nsresult rv = aTransferable->FlavorsTransferableCanImport(flavors);
     if (NS_FAILED(rv))
         return rv;
 
-    // count the number of flavors
-    uint32_t cnt;
-    flavorList->GetLength(&cnt);
-    unsigned int i;
-
     // check to see if this is an internal list
     bool isList = IsTargetContextList();
 
     if (isList) {
         MOZ_LOG(sDragLm, LogLevel::Debug, ("it's a list..."));
         // find a matching flavor
-        for (i = 0; i < cnt; ++i) {
-            nsCOMPtr<nsISupportsCString> currentFlavor;
-            currentFlavor = do_QueryElementAt(flavorList, i);
-            if (!currentFlavor)
-                continue;
-
-            nsCString flavorStr;
-            currentFlavor->ToString(getter_Copies(flavorStr));
+        for (uint32_t i = 0; i < flavors.Length(); ++i) {
+            nsCString& flavorStr = flavors[i];
             MOZ_LOG(sDragLm,
                    LogLevel::Debug,
                    ("flavor is %s\n", flavorStr.get()));
             // get the item with the right index
             nsCOMPtr<nsITransferable> item =
                 do_QueryElementAt(mSourceDataItems, aItemIndex);
             if (!item)
                 continue;
@@ -747,233 +734,227 @@ nsDragService::GetData(nsITransferable *
         }
         // if we got this far, we failed
         return NS_ERROR_FAILURE;
     }
 
     // Now walk down the list of flavors. When we find one that is
     // actually present, copy out the data into the transferable in that
     // format. SetTransferData() implicitly handles conversions.
-    for ( i = 0; i < cnt; ++i ) {
-        nsCOMPtr<nsISupportsCString> currentFlavor;
-        currentFlavor = do_QueryElementAt(flavorList, i);
-        if (currentFlavor) {
-            // find our gtk flavor
-            nsCString flavorStr;
-            currentFlavor->ToString(getter_Copies(flavorStr));
-            GdkAtom gdkFlavor = gdk_atom_intern(flavorStr.get(), FALSE);
-            MOZ_LOG(sDragLm, LogLevel::Debug,
-                   ("looking for data in type %s, gdk flavor %p\n",
-                   flavorStr.get(), gdkFlavor));
-            bool dataFound = false;
-            if (gdkFlavor) {
+    for (uint32_t i = 0; i < flavors.Length(); ++i) {
+        nsCString& flavorStr = flavors[i];
+        GdkAtom gdkFlavor = gdk_atom_intern(flavorStr.get(), FALSE);
+        MOZ_LOG(sDragLm, LogLevel::Debug,
+               ("looking for data in type %s, gdk flavor %p\n",
+               flavorStr.get(), gdkFlavor));
+        bool dataFound = false;
+        if (gdkFlavor) {
+            GetTargetDragData(gdkFlavor);
+        }
+        if (mTargetDragData) {
+            MOZ_LOG(sDragLm, LogLevel::Debug, ("dataFound = true\n"));
+            dataFound = true;
+        }
+        else {
+            MOZ_LOG(sDragLm, LogLevel::Debug, ("dataFound = false\n"));
+
+            // Dragging and dropping from the file manager would cause us
+            // to parse the source text as a nsIFile URL.
+            if (flavorStr.EqualsLiteral(kFileMime)) {
+                gdkFlavor = gdk_atom_intern(kTextMime, FALSE);
                 GetTargetDragData(gdkFlavor);
-            }
-            if (mTargetDragData) {
-                MOZ_LOG(sDragLm, LogLevel::Debug, ("dataFound = true\n"));
-                dataFound = true;
-            }
-            else {
-                MOZ_LOG(sDragLm, LogLevel::Debug, ("dataFound = false\n"));
-
-                // Dragging and dropping from the file manager would cause us
-                // to parse the source text as a nsIFile URL.
-                if (flavorStr.EqualsLiteral(kFileMime)) {
-                    gdkFlavor = gdk_atom_intern(kTextMime, FALSE);
+                if (!mTargetDragData) {
+                    gdkFlavor = gdk_atom_intern(gTextUriListType, FALSE);
                     GetTargetDragData(gdkFlavor);
-                    if (!mTargetDragData) {
-                        gdkFlavor = gdk_atom_intern(gTextUriListType, FALSE);
-                        GetTargetDragData(gdkFlavor);
-                    }
-                    if (mTargetDragData) {
-                        const char* text = static_cast<char*>(mTargetDragData);
-                        char16_t* convertedText = nullptr;
-                        uint32_t convertedTextLen = 0;
+                }
+                if (mTargetDragData) {
+                    const char* text = static_cast<char*>(mTargetDragData);
+                    char16_t* convertedText = nullptr;
+                    uint32_t convertedTextLen = 0;
 
-                        GetTextUriListItem(text, mTargetDragDataLen, aItemIndex,
-                                           &convertedText, &convertedTextLen);
+                    GetTextUriListItem(text, mTargetDragDataLen, aItemIndex,
+                                       &convertedText, &convertedTextLen);
 
-                        if (convertedText) {
-                            nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
-                            nsCOMPtr<nsIURI> fileURI;
-                            rv = ioService->NewURI(NS_ConvertUTF16toUTF8(convertedText),
-                                                   nullptr, nullptr, getter_AddRefs(fileURI));
+                    if (convertedText) {
+                        nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
+                        nsCOMPtr<nsIURI> fileURI;
+                        rv = ioService->NewURI(NS_ConvertUTF16toUTF8(convertedText),
+                                               nullptr, nullptr, getter_AddRefs(fileURI));
+                        if (NS_SUCCEEDED(rv)) {
+                            nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(fileURI, &rv);
                             if (NS_SUCCEEDED(rv)) {
-                                nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(fileURI, &rv);
+                                nsCOMPtr<nsIFile> file;
+                                rv = fileURL->GetFile(getter_AddRefs(file));
                                 if (NS_SUCCEEDED(rv)) {
-                                    nsCOMPtr<nsIFile> file;
-                                    rv = fileURL->GetFile(getter_AddRefs(file));
-                                    if (NS_SUCCEEDED(rv)) {
-                                        // The common wrapping code at the end of
-                                        // this function assumes the data is text
-                                        // and calls text-specific operations.
-                                        // Make a secret hideout here for nsIFile
-                                        // objects and return early.
-                                        aTransferable->SetTransferData(flavorStr.get(), file,
-                                                                       convertedTextLen);
-                                        g_free(convertedText);
-                                        return NS_OK;
-                                    }
+                                    // The common wrapping code at the end of
+                                    // this function assumes the data is text
+                                    // and calls text-specific operations.
+                                    // Make a secret hideout here for nsIFile
+                                    // objects and return early.
+                                    aTransferable->SetTransferData(flavorStr.get(), file,
+                                                                   convertedTextLen);
+                                    g_free(convertedText);
+                                    return NS_OK;
                                 }
                             }
-                            g_free(convertedText);
                         }
-                        continue;
+                        g_free(convertedText);
                     }
+                    continue;
                 }
+            }
 
-                // if we are looking for text/unicode and we fail to find it
-                // on the clipboard first, try again with text/plain. If that
-                // is present, convert it to unicode.
-                if (flavorStr.EqualsLiteral(kUnicodeMime)) {
+            // if we are looking for text/unicode and we fail to find it
+            // on the clipboard first, try again with text/plain. If that
+            // is present, convert it to unicode.
+            if (flavorStr.EqualsLiteral(kUnicodeMime)) {
+                MOZ_LOG(sDragLm, LogLevel::Debug,
+                       ("we were looking for text/unicode... \
+                       trying with text/plain;charset=utf-8\n"));
+                gdkFlavor = gdk_atom_intern(gTextPlainUTF8Type, FALSE);
+                GetTargetDragData(gdkFlavor);
+                if (mTargetDragData) {
+                    MOZ_LOG(sDragLm, LogLevel::Debug, ("Got textplain data\n"));
+                    const char* castedText =
+                                reinterpret_cast<char*>(mTargetDragData);
+                    char16_t* convertedText = nullptr;
+                    NS_ConvertUTF8toUTF16 ucs2string(castedText,
+                                                     mTargetDragDataLen);
+                    convertedText = ToNewUnicode(ucs2string);
+                    if ( convertedText ) {
+                        MOZ_LOG(sDragLm, LogLevel::Debug,
+                               ("successfully converted plain text \
+                               to unicode.\n"));
+                        // out with the old, in with the new
+                        g_free(mTargetDragData);
+                        mTargetDragData = convertedText;
+                        mTargetDragDataLen = ucs2string.Length() * 2;
+                        dataFound = true;
+                    } // if plain text data on clipboard
+                } else {
                     MOZ_LOG(sDragLm, LogLevel::Debug,
                            ("we were looking for text/unicode... \
-                           trying with text/plain;charset=utf-8\n"));
-                    gdkFlavor = gdk_atom_intern(gTextPlainUTF8Type, FALSE);
+                           trying again with text/plain\n"));
+                    gdkFlavor = gdk_atom_intern(kTextMime, FALSE);
                     GetTargetDragData(gdkFlavor);
                     if (mTargetDragData) {
                         MOZ_LOG(sDragLm, LogLevel::Debug, ("Got textplain data\n"));
                         const char* castedText =
                                     reinterpret_cast<char*>(mTargetDragData);
                         char16_t* convertedText = nullptr;
-                        NS_ConvertUTF8toUTF16 ucs2string(castedText,
-                                                         mTargetDragDataLen);
-                        convertedText = ToNewUnicode(ucs2string);
+                        uint32_t convertedTextLen = 0;
+                        UTF8ToNewUTF16(castedText, mTargetDragDataLen,
+                                       &convertedText, &convertedTextLen);
                         if ( convertedText ) {
                             MOZ_LOG(sDragLm, LogLevel::Debug,
                                    ("successfully converted plain text \
                                    to unicode.\n"));
                             // out with the old, in with the new
                             g_free(mTargetDragData);
                             mTargetDragData = convertedText;
-                            mTargetDragDataLen = ucs2string.Length() * 2;
+                            mTargetDragDataLen = convertedTextLen * 2;
                             dataFound = true;
                         } // if plain text data on clipboard
-                    } else {
+                    } // if plain text flavor present
+                } // if plain text charset=utf-8 flavor present
+            } // if looking for text/unicode
+
+            // if we are looking for text/x-moz-url and we failed to find
+            // it on the clipboard, try again with text/uri-list, and then
+            // _NETSCAPE_URL
+            if (flavorStr.EqualsLiteral(kURLMime)) {
+                MOZ_LOG(sDragLm, LogLevel::Debug,
+                       ("we were looking for text/x-moz-url...\
+                       trying again with text/uri-list\n"));
+                gdkFlavor = gdk_atom_intern(gTextUriListType, FALSE);
+                GetTargetDragData(gdkFlavor);
+                if (mTargetDragData) {
+                    MOZ_LOG(sDragLm, LogLevel::Debug,
+                           ("Got text/uri-list data\n"));
+                    const char *data =
+                               reinterpret_cast<char*>(mTargetDragData);
+                    char16_t* convertedText = nullptr;
+                    uint32_t convertedTextLen = 0;
+
+                    GetTextUriListItem(data, mTargetDragDataLen, aItemIndex,
+                                       &convertedText, &convertedTextLen);
+
+                    if ( convertedText ) {
                         MOZ_LOG(sDragLm, LogLevel::Debug,
-                               ("we were looking for text/unicode... \
-                               trying again with text/plain\n"));
-                        gdkFlavor = gdk_atom_intern(kTextMime, FALSE);
-                        GetTargetDragData(gdkFlavor);
-                        if (mTargetDragData) {
-                            MOZ_LOG(sDragLm, LogLevel::Debug, ("Got textplain data\n"));
-                            const char* castedText =
-                                        reinterpret_cast<char*>(mTargetDragData);
-                            char16_t* convertedText = nullptr;
-                            uint32_t convertedTextLen = 0;
-                            UTF8ToNewUTF16(castedText, mTargetDragDataLen,
-                                           &convertedText, &convertedTextLen);
-                            if ( convertedText ) {
-                                MOZ_LOG(sDragLm, LogLevel::Debug,
-                                       ("successfully converted plain text \
-                                       to unicode.\n"));
-                                // out with the old, in with the new
-                                g_free(mTargetDragData);
-                                mTargetDragData = convertedText;
-                                mTargetDragDataLen = convertedTextLen * 2;
-                                dataFound = true;
-                            } // if plain text data on clipboard
-                        } // if plain text flavor present
-                    } // if plain text charset=utf-8 flavor present
-                } // if looking for text/unicode
-
-                // if we are looking for text/x-moz-url and we failed to find
-                // it on the clipboard, try again with text/uri-list, and then
-                // _NETSCAPE_URL
-                if (flavorStr.EqualsLiteral(kURLMime)) {
+                               ("successfully converted \
+                               _NETSCAPE_URL to unicode.\n"));
+                        // out with the old, in with the new
+                        g_free(mTargetDragData);
+                        mTargetDragData = convertedText;
+                        mTargetDragDataLen = convertedTextLen * 2;
+                        dataFound = true;
+                    }
+                }
+                else {
+                    MOZ_LOG(sDragLm, LogLevel::Debug,
+                           ("failed to get text/uri-list data\n"));
+                }
+                if (!dataFound) {
                     MOZ_LOG(sDragLm, LogLevel::Debug,
                            ("we were looking for text/x-moz-url...\
-                           trying again with text/uri-list\n"));
-                    gdkFlavor = gdk_atom_intern(gTextUriListType, FALSE);
+                           trying again with _NETSCAP_URL\n"));
+                    gdkFlavor = gdk_atom_intern(gMozUrlType, FALSE);
                     GetTargetDragData(gdkFlavor);
                     if (mTargetDragData) {
                         MOZ_LOG(sDragLm, LogLevel::Debug,
-                               ("Got text/uri-list data\n"));
-                        const char *data =
-                                   reinterpret_cast<char*>(mTargetDragData);
+                               ("Got _NETSCAPE_URL data\n"));
+                        const char* castedText =
+                              reinterpret_cast<char*>(mTargetDragData);
                         char16_t* convertedText = nullptr;
                         uint32_t convertedTextLen = 0;
-
-                        GetTextUriListItem(data, mTargetDragDataLen, aItemIndex,
-                                           &convertedText, &convertedTextLen);
-
+                        UTF8ToNewUTF16(castedText, mTargetDragDataLen, &convertedText, &convertedTextLen);
                         if ( convertedText ) {
-                            MOZ_LOG(sDragLm, LogLevel::Debug,
-                                   ("successfully converted \
-                                   _NETSCAPE_URL to unicode.\n"));
+                            MOZ_LOG(sDragLm,
+                                   LogLevel::Debug,
+                                   ("successfully converted _NETSCAPE_URL \
+                                   to unicode.\n"));
                             // out with the old, in with the new
                             g_free(mTargetDragData);
                             mTargetDragData = convertedText;
                             mTargetDragDataLen = convertedTextLen * 2;
                             dataFound = true;
                         }
                     }
                     else {
                         MOZ_LOG(sDragLm, LogLevel::Debug,
-                               ("failed to get text/uri-list data\n"));
-                    }
-                    if (!dataFound) {
-                        MOZ_LOG(sDragLm, LogLevel::Debug,
-                               ("we were looking for text/x-moz-url...\
-                               trying again with _NETSCAP_URL\n"));
-                        gdkFlavor = gdk_atom_intern(gMozUrlType, FALSE);
-                        GetTargetDragData(gdkFlavor);
-                        if (mTargetDragData) {
-                            MOZ_LOG(sDragLm, LogLevel::Debug,
-                                   ("Got _NETSCAPE_URL data\n"));
-                            const char* castedText =
-                                  reinterpret_cast<char*>(mTargetDragData);
-                            char16_t* convertedText = nullptr;
-                            uint32_t convertedTextLen = 0;
-                            UTF8ToNewUTF16(castedText, mTargetDragDataLen, &convertedText, &convertedTextLen);
-                            if ( convertedText ) {
-                                MOZ_LOG(sDragLm,
-                                       LogLevel::Debug,
-                                       ("successfully converted _NETSCAPE_URL \
-                                       to unicode.\n"));
-                                // out with the old, in with the new
-                                g_free(mTargetDragData);
-                                mTargetDragData = convertedText;
-                                mTargetDragDataLen = convertedTextLen * 2;
-                                dataFound = true;
-                            }
-                        }
-                        else {
-                            MOZ_LOG(sDragLm, LogLevel::Debug,
-                                   ("failed to get _NETSCAPE_URL data\n"));
-                        }
+                               ("failed to get _NETSCAPE_URL data\n"));
                     }
                 }
+            }
 
-            } // else we try one last ditch effort to find our data
+        } // else we try one last ditch effort to find our data
 
-            if (dataFound) {
-                if (!flavorStr.EqualsLiteral(kCustomTypesMime)) {
-                  // the DOM only wants LF, so convert from MacOS line endings
-                  // to DOM line endings.
-                  nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(
-                               flavorStr,
-                               &mTargetDragData,
-                               reinterpret_cast<int*>(&mTargetDragDataLen));
-                }
+        if (dataFound) {
+            if (!flavorStr.EqualsLiteral(kCustomTypesMime)) {
+              // the DOM only wants LF, so convert from MacOS line endings
+              // to DOM line endings.
+              nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(
+                           flavorStr,
+                           &mTargetDragData,
+                           reinterpret_cast<int*>(&mTargetDragDataLen));
+            }
 
-                // put it into the transferable.
-                nsCOMPtr<nsISupports> genericDataWrapper;
-                nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr,
-                                    mTargetDragData, mTargetDragDataLen,
-                                    getter_AddRefs(genericDataWrapper));
-                aTransferable->SetTransferData(flavorStr.get(),
-                                               genericDataWrapper,
-                                               mTargetDragDataLen);
-                // we found one, get out of this loop!
-                MOZ_LOG(sDragLm, LogLevel::Debug, ("dataFound and converted!\n"));
-                break;
-            }
-        } // if (currentFlavor)
-    } // foreach flavor
+            // put it into the transferable.
+            nsCOMPtr<nsISupports> genericDataWrapper;
+            nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr,
+                                mTargetDragData, mTargetDragDataLen,
+                                getter_AddRefs(genericDataWrapper));
+            aTransferable->SetTransferData(flavorStr.get(),
+                                           genericDataWrapper,
+                                           mTargetDragDataLen);
+            // we found one, get out of this loop!
+            MOZ_LOG(sDragLm, LogLevel::Debug, ("dataFound and converted!\n"));
+            break;
+        }
+    }
 
     return NS_OK;
 
 }
 
 NS_IMETHODIMP
 nsDragService::IsDataFlavorSupported(const char *aDataFlavor,
                                      bool *_retval)
@@ -1005,39 +986,26 @@ nsDragService::IsDataFlavorSupported(con
         // an external client trying to fool us.
         if (!mSourceDataItems)
             return NS_OK;
         mSourceDataItems->GetLength(&numDragItems);
         for (uint32_t itemIndex = 0; itemIndex < numDragItems; ++itemIndex) {
             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;
-                          flavorIndex < numFlavors ;
-                          ++flavorIndex ) {
-                        nsCOMPtr<nsISupportsCString> currentFlavor;
-                        currentFlavor = do_QueryElementAt(flavorList, flavorIndex);
-                        if (currentFlavor) {
-                            nsCString flavorStr;
-                            currentFlavor->ToString(getter_Copies(flavorStr));
-                            MOZ_LOG(sDragLm, LogLevel::Debug,
-                                   ("checking %s against %s\n",
-                                   flavorStr.get(), aDataFlavor));
-                            if (flavorStr.Equals(aDataFlavor)) {
-                                MOZ_LOG(sDragLm, LogLevel::Debug,
-                                       ("boioioioiooioioioing!\n"));
-                                *_retval = true;
-                            }
-                        }
+                nsTArray<nsCString> flavors;
+                currItem->FlavorsTransferableCanExport(flavors);
+                for (uint32_t i = 0; i < flavors.Length(); ++i) {
+                    MOZ_LOG(sDragLm, LogLevel::Debug,
+                            ("checking %s against %s\n",
+                            flavors[i].get(), aDataFlavor));
+                    if (flavors[i].Equals(aDataFlavor)) {
+                        MOZ_LOG(sDragLm, LogLevel::Debug,
+                               ("boioioioiooioioioing!\n"));
+                        *_retval = true;
                     }
                 }
             }
         }
         return NS_OK;
     }
 
     // check the target context vs. this flavor, one at a time
@@ -1307,135 +1275,112 @@ nsDragService::GetSourceList(void)
         targetArray.AppendElement(listTarget);
 
         // check what flavours are supported so we can decide what other
         // targets to advertise.
         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 ;
-                     ++flavorIndex ) {
-                    nsCOMPtr<nsISupportsCString> currentFlavor;
-                    currentFlavor = do_QueryElementAt(flavorList, flavorIndex);
-                    if (currentFlavor) {
-                        nsCString flavorStr;
-                        currentFlavor->ToString(getter_Copies(flavorStr));
-
-                        // check if text/x-moz-url is supported.
-                        // If so, advertise
-                        // text/uri-list.
-                        if (flavorStr.EqualsLiteral(kURLMime)) {
-                            listTarget =
-                             (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
-                            listTarget->target = g_strdup(gTextUriListType);
-                            listTarget->flags = 0;
-                            MOZ_LOG(sDragLm, LogLevel::Debug,
-                                   ("automatically adding target %s\n",
-                                    listTarget->target));
-                            targetArray.AppendElement(listTarget);
-                        }
-                    }
-                } // foreach flavor in item
-            } // if valid flavor list
+            nsTArray<nsCString> flavors;
+            currItem->FlavorsTransferableCanExport(flavors);
+            for (uint32_t i = 0; i < flavors.Length(); ++i) {
+                // check if text/x-moz-url is supported.
+                // If so, advertise
+                // text/uri-list.
+                if (flavors[i].EqualsLiteral(kURLMime)) {
+                    listTarget =
+                     (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
+                    listTarget->target = g_strdup(gTextUriListType);
+                    listTarget->flags = 0;
+                    MOZ_LOG(sDragLm, LogLevel::Debug,
+                           ("automatically adding target %s\n",
+                            listTarget->target));
+                    targetArray.AppendElement(listTarget);
+                }
+            }
         } // if item is a transferable
     } else if (numDragItems == 1) {
         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 ;
-                     ++flavorIndex ) {
-                    nsCOMPtr<nsISupportsCString> currentFlavor;
-                    currentFlavor = do_QueryElementAt(flavorList, flavorIndex);
-                    if (currentFlavor) {
-                        nsCString flavorStr;
-                        currentFlavor->ToString(getter_Copies(flavorStr));
-                        GtkTargetEntry *target =
-                          (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
-                        target->target = g_strdup(flavorStr.get());
-                        target->flags = 0;
-                        MOZ_LOG(sDragLm, LogLevel::Debug,
-                               ("adding target %s\n", target->target));
-                        targetArray.AppendElement(target);
+            nsTArray<nsCString> flavors;
+            currItem->FlavorsTransferableCanExport(flavors);
+            for (uint32_t i = 0; i < flavors.Length(); ++i) {
+                nsCString& flavorStr = flavors[i];
+
+                GtkTargetEntry *target =
+                  (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
+                target->target = g_strdup(flavorStr.get());
+                target->flags = 0;
+                MOZ_LOG(sDragLm, LogLevel::Debug,
+                       ("adding target %s\n", target->target));
+                targetArray.AppendElement(target);
 
-                        // If there is a file, add the text/uri-list type.
-                        if (flavorStr.EqualsLiteral(kFileMime)) {
-                            GtkTargetEntry *urilistTarget =
-                             (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
-                            urilistTarget->target = g_strdup(gTextUriListType);
-                            urilistTarget->flags = 0;
-                            MOZ_LOG(sDragLm, LogLevel::Debug,
-                                   ("automatically adding target %s\n",
-                                    urilistTarget->target));
-                            targetArray.AppendElement(urilistTarget);
-                        }
-                        // Check to see if this is text/unicode.
-                        // If it is, add text/plain
-                        // since we automatically support text/plain
-                        // if we support text/unicode.
-                        else if (flavorStr.EqualsLiteral(kUnicodeMime)) {
-                            GtkTargetEntry *plainUTF8Target =
-                             (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
-                            plainUTF8Target->target = g_strdup(gTextPlainUTF8Type);
-                            plainUTF8Target->flags = 0;
-                            MOZ_LOG(sDragLm, LogLevel::Debug,
-                                   ("automatically adding target %s\n",
-                                    plainUTF8Target->target));
-                            targetArray.AppendElement(plainUTF8Target);
+                // If there is a file, add the text/uri-list type.
+                if (flavorStr.EqualsLiteral(kFileMime)) {
+                    GtkTargetEntry *urilistTarget =
+                     (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
+                    urilistTarget->target = g_strdup(gTextUriListType);
+                    urilistTarget->flags = 0;
+                    MOZ_LOG(sDragLm, LogLevel::Debug,
+                           ("automatically adding target %s\n",
+                            urilistTarget->target));
+                    targetArray.AppendElement(urilistTarget);
+                }
+                // Check to see if this is text/unicode.
+                // If it is, add text/plain
+                // since we automatically support text/plain
+                // if we support text/unicode.
+                else if (flavorStr.EqualsLiteral(kUnicodeMime)) {
+                    GtkTargetEntry *plainUTF8Target =
+                     (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
+                    plainUTF8Target->target = g_strdup(gTextPlainUTF8Type);
+                    plainUTF8Target->flags = 0;
+                    MOZ_LOG(sDragLm, LogLevel::Debug,
+                           ("automatically adding target %s\n",
+                            plainUTF8Target->target));
+                    targetArray.AppendElement(plainUTF8Target);
 
-                            GtkTargetEntry *plainTarget =
-                             (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
-                            plainTarget->target = g_strdup(kTextMime);
-                            plainTarget->flags = 0;
-                            MOZ_LOG(sDragLm, LogLevel::Debug,
-                                   ("automatically adding target %s\n",
-                                    plainTarget->target));
-                            targetArray.AppendElement(plainTarget);
-                        }
-                        // Check to see if this is the x-moz-url type.
-                        // If it is, add _NETSCAPE_URL
-                        // this is a type used by everybody.
-                        else if (flavorStr.EqualsLiteral(kURLMime)) {
-                            GtkTargetEntry *urlTarget =
-                             (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
-                            urlTarget->target = g_strdup(gMozUrlType);
-                            urlTarget->flags = 0;
-                            MOZ_LOG(sDragLm, LogLevel::Debug,
-                                   ("automatically adding target %s\n",
-                                    urlTarget->target));
-                            targetArray.AppendElement(urlTarget);
-                        }
-                        // XdndDirectSave
-                        else if (flavorStr.EqualsLiteral(kFilePromiseMime)) {
-                            GtkTargetEntry *directsaveTarget =
-                             (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
-                            directsaveTarget->target = g_strdup(gXdndDirectSaveType);
-                            directsaveTarget->flags = 0;
-                            MOZ_LOG(sDragLm, LogLevel::Debug,
-                                   ("automatically adding target %s\n",
-                                    directsaveTarget->target));
-                            targetArray.AppendElement(directsaveTarget);
-                        }
-                    }
-                } // foreach flavor in item
-            } // if valid flavor list
-        } // if item is a transferable
-    } // if it is a single item drag
+                    GtkTargetEntry *plainTarget =
+                     (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
+                    plainTarget->target = g_strdup(kTextMime);
+                    plainTarget->flags = 0;
+                    MOZ_LOG(sDragLm, LogLevel::Debug,
+                           ("automatically adding target %s\n",
+                            plainTarget->target));
+                    targetArray.AppendElement(plainTarget);
+                }
+                // Check to see if this is the x-moz-url type.
+                // If it is, add _NETSCAPE_URL
+                // this is a type used by everybody.
+                else if (flavorStr.EqualsLiteral(kURLMime)) {
+                    GtkTargetEntry *urlTarget =
+                     (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
+                    urlTarget->target = g_strdup(gMozUrlType);
+                    urlTarget->flags = 0;
+                    MOZ_LOG(sDragLm, LogLevel::Debug,
+                           ("automatically adding target %s\n",
+                            urlTarget->target));
+                    targetArray.AppendElement(urlTarget);
+                }
+                // XdndDirectSave
+                else if (flavorStr.EqualsLiteral(kFilePromiseMime)) {
+                    GtkTargetEntry *directsaveTarget =
+                     (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
+                    directsaveTarget->target = g_strdup(gXdndDirectSaveType);
+                    directsaveTarget->flags = 0;
+                    MOZ_LOG(sDragLm, LogLevel::Debug,
+                           ("automatically adding target %s\n",
+                            directsaveTarget->target));
+                    targetArray.AppendElement(directsaveTarget);
+                }
+            }
+        }
+    }
 
     // get all the elements that we created.
     targetCount = targetArray.Length();
     if (targetCount) {
         // allocate space to create the list of valid targets
         targets =
           (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry) * targetCount);
         uint32_t targetIndex;
@@ -1818,32 +1763,22 @@ nsDragService::SourceDataGet(GtkWidget  
 void
 nsDragService::SourceBeginDrag(GdkDragContext *aContext)
 {
     nsCOMPtr<nsITransferable> transferable =
         do_QueryElementAt(mSourceDataItems, 0);
     if (!transferable)
         return;
 
-    nsCOMPtr<nsIArray> flavorList;
-    nsresult rv = transferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
+    nsTArray<nsCString> flavors;
+    nsresult rv = transferable->FlavorsTransferableCanImport(flavors);
     NS_ENSURE_SUCCESS(rv,);
 
-    uint32_t length;
-    flavorList->GetLength(&length);
-
-    for (uint32_t i = 0; i < length; ++i) {
-        nsCOMPtr<nsISupportsCString> currentFlavor =
-            do_QueryElementAt(flavorList, i);
-        if (!currentFlavor)
-            return;
-
-        nsCString flavorStr;
-        currentFlavor->ToString(getter_Copies(flavorStr));
-        if (flavorStr.EqualsLiteral(kFilePromiseDestFilename)) {
+    for (uint32_t i = 0; i < flavors.Length(); ++i) {
+        if (flavors[i].EqualsLiteral(kFilePromiseDestFilename)) {
             nsCOMPtr<nsISupports> data;
             uint32_t dataSize = 0;
             transferable->GetTransferData(kFilePromiseDestFilename,
                                           getter_AddRefs(data), &dataSize);
             nsCOMPtr<nsISupportsString> fileName = do_QueryInterface(data);
             if (!fileName)
                 return;
 
--- a/widget/nsClipboardProxy.cpp
+++ b/widget/nsClipboardProxy.cpp
@@ -44,34 +44,18 @@ nsClipboardProxy::SetData(nsITransferabl
                           contentPolicyType, aWhichClipboard);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsClipboardProxy::GetData(nsITransferable *aTransferable, int32_t aWhichClipboard)
 {
-   nsTArray<nsCString> types;
-  
-  nsCOMPtr<nsIArray> flavorList;
-  aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
-  if (flavorList) {
-    uint32_t flavorCount = 0;
-    flavorList->GetLength(&flavorCount);
-    for (uint32_t j = 0; j < flavorCount; ++j) {
-      nsCOMPtr<nsISupportsCString> flavor = do_QueryElementAt(flavorList, j);
-      if (flavor) {
-        nsAutoCString flavorStr;
-        flavor->GetData(flavorStr);
-        if (flavorStr.Length()) {
-          types.AppendElement(flavorStr);
-        }
-      }
-    }
-  }
+  nsTArray<nsCString> types;
+  aTransferable->FlavorsTransferableCanImport(types);
 
   nsresult rv;
   IPCDataTransfer dataTransfer;
   ContentChild::GetSingleton()->SendGetClipboard(types, aWhichClipboard, &dataTransfer);
 
   auto& items = dataTransfer.items();
   for (uint32_t j = 0; j < items.Length(); ++j) {
     const IPCDataTransferItem& item = items[j];
--- a/widget/nsITransferable.idl
+++ b/widget/nsITransferable.idl
@@ -117,23 +117,20 @@ interface nsITransferable : nsISupports
    * nsIDocument::GetLoadContext to get to the load context object.
    *
    * @param aContext the load context associated with the transferable object.
    *        This can be set to null if a load context is not available.
    */
   void init(in nsILoadContext aContext);
 
   /**
-    * Computes a list of flavors (mime types as nsISupportsCString) that the transferable 
-    * can export, either through intrinsic knowledge or output data converters.
-    *
-    * @param  aDataFlavorList fills list with supported flavors. This is a copy of
-    *          the internal list, so it may be edited w/out affecting the transferable.
+    * Computes a list of flavors that the transferable can export, either
+    * through intrinsic knowledge or output data converters.
     */
-  nsIArray flavorsTransferableCanExport ( ) ;
+  Array<ACString> flavorsTransferableCanExport();
 
   /**
     * Given a flavor retrieve the data. 
     *
     * @param  aFlavor (in parameter) the flavor of data to retrieve
     * @param  aData the data. Some variant of class in nsISupportsPrimitives.idl
     * @param  aDataLen the length of the data
     */
@@ -156,23 +153,21 @@ interface nsITransferable : nsISupports
   boolean isLargeDataSet ( ) ;
   
 
     ///////////////////////////////
     // Setter part of interface 
     ///////////////////////////////
 
   /**
-    * Computes a list of flavors (mime types as nsISupportsCString) that the transferable can
+    * Computes a list of flavors that the transferable can
     * accept into it, either through intrinsic knowledge or input data converters.
     *
-    * @param  outFlavorList fills list with supported flavors. This is a copy of
-    *          the internal list, so it may be edited w/out affecting the transferable.
     */
-  nsIArray flavorsTransferableCanImport ( ) ;
+  Array<ACString> flavorsTransferableCanImport();
 
   /**
     * Sets the data in the transferable with the specified flavor. The transferable
     * will maintain its own copy the data, so it is not necessary to do that beforehand.
     *
     * @param  aFlavor the flavor of data that is being set
     * @param  aData the data, either some variant of class in nsISupportsPrimitives.idl,
     *         an nsIFile, or an nsIFlavorDataProvider (see above)
--- a/widget/nsTransferable.cpp
+++ b/widget/nsTransferable.cpp
@@ -224,37 +224,27 @@ nsTransferable::Init(nsILoadContext* aCo
 #endif
   return NS_OK;
 }
 
 //
 // GetTransferDataFlavors
 //
 // Returns a copy of the internal list of flavors. This does NOT take into
-// account any converter that may be registered. This list consists of
-// nsISupportsCString objects so that the flavor list can be accessed from JS.
+// account any converter that may be registered.
 //
-already_AddRefed<nsIMutableArray>
-nsTransferable::GetTransferDataFlavors()
+void
+nsTransferable::GetTransferDataFlavors(nsTArray<nsCString>& aFlavors)
 {
   MOZ_ASSERT(mInitialized);
 
-  nsCOMPtr<nsIMutableArray> array = nsArray::Create();
-
   for (size_t i = 0; i < mDataArray.Length(); ++i) {
     DataStruct& data = mDataArray.ElementAt(i);
-    nsCOMPtr<nsISupportsCString> flavorWrapper = do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID);
-    if ( flavorWrapper ) {
-      flavorWrapper->SetData ( data.GetFlavor() );
-      nsCOMPtr<nsISupports> genericWrapper ( do_QueryInterface(flavorWrapper) );
-      array->AppendElement( genericWrapper );
-    }
+    aFlavors.AppendElement(data.GetFlavor());
   }
-
-  return array.forget();
 }
 
 
 //
 // GetTransferData
 //
 // Returns the data of the requested flavor, obtained from either having the data on hand or
 // using a converter to get it. The data is wrapped in a nsISupports primitive so that it is
@@ -495,97 +485,92 @@ NS_IMETHODIMP nsTransferable::GetConvert
 
 //
 // FlavorsTransferableCanImport
 //
 // Computes a list of flavors that the transferable can accept into it, either through
 // intrinsic knowledge or input data converters.
 //
 NS_IMETHODIMP
-nsTransferable::FlavorsTransferableCanImport(nsIArray **_retval)
+nsTransferable::FlavorsTransferableCanImport(nsTArray<nsCString>& aFlavors)
 {
   MOZ_ASSERT(mInitialized);
 
-  NS_ENSURE_ARG_POINTER(_retval);
-
   // Get the flavor list, and on to the end of it, append the list of flavors we
   // can also get to through a converter. This is so that we can just walk the list
   // in one go, looking for the desired flavor.
-  nsCOMPtr<nsIMutableArray> array = GetTransferDataFlavors();
-  nsCOMPtr<nsIFormatConverter> converter;
-  GetConverter(getter_AddRefs(converter));
-  if ( converter ) {
+  GetTransferDataFlavors(aFlavors);
+
+  if (mFormatConv) {
     nsCOMPtr<nsIArray> convertedList;
-    converter->GetInputDataFlavors(getter_AddRefs(convertedList));
+    mFormatConv->GetInputDataFlavors(getter_AddRefs(convertedList));
 
     if ( convertedList ) {
       uint32_t importListLen;
       convertedList->GetLength(&importListLen);
 
       for (uint32_t i = 0; i < importListLen; ++i ) {
         nsCOMPtr<nsISupportsCString> flavorWrapper =
             do_QueryElementAt(convertedList, i);
         nsAutoCString flavorStr;
         flavorWrapper->GetData( flavorStr );
 
-        if (GetDataForFlavor (mDataArray, flavorStr.get())
-            == mDataArray.NoIndex) // Don't append if already in intrinsic list
-          array->AppendElement (flavorWrapper);
-      } // foreach flavor that can be converted to
+        // Don't append if already in intrinsic list
+        if (!aFlavors.Contains(flavorStr)) {
+          aFlavors.AppendElement(flavorStr);
+        }
+      }
     }
-  } // if a converter exists
+  }
 
-  array.forget(_retval);
   return NS_OK;
-} // FlavorsTransferableCanImport
+}
 
 
 //
 // FlavorsTransferableCanExport
 //
 // Computes a list of flavors that the transferable can export, either through
 // intrinsic knowledge or output data converters.
 //
 NS_IMETHODIMP
-nsTransferable::FlavorsTransferableCanExport(nsIArray **_retval)
+nsTransferable::FlavorsTransferableCanExport(nsTArray<nsCString>& aFlavors)
 {
   MOZ_ASSERT(mInitialized);
 
-  NS_ENSURE_ARG_POINTER(_retval);
 
   // Get the flavor list, and on to the end of it, append the list of flavors we
   // can also get to through a converter. This is so that we can just walk the list
   // in one go, looking for the desired flavor.
-  nsCOMPtr<nsIMutableArray> array = GetTransferDataFlavors();
-  nsCOMPtr<nsIFormatConverter> converter;
-  GetConverter(getter_AddRefs(converter));
-  if ( converter ) {
+  GetTransferDataFlavors(aFlavors);
+
+  if (mFormatConv) {
     nsCOMPtr<nsIArray> convertedList;
-    converter->GetOutputDataFlavors(getter_AddRefs(convertedList));
+    mFormatConv->GetOutputDataFlavors(getter_AddRefs(convertedList));
 
     if ( convertedList ) {
       uint32_t importListLen;
       convertedList->GetLength(&importListLen);
 
       for ( uint32_t i=0; i < importListLen; ++i ) {
         nsCOMPtr<nsISupportsCString> flavorWrapper =
             do_QueryElementAt(convertedList, i);
         nsAutoCString flavorStr;
         flavorWrapper->GetData( flavorStr );
 
-        if (GetDataForFlavor (mDataArray, flavorStr.get())
-            == mDataArray.NoIndex) // Don't append if already in intrinsic list
-          array->AppendElement (flavorWrapper);
-      } // foreach flavor that can be converted to
+        // Don't append if already in intrinsic list
+        if (!aFlavors.Contains(flavorStr)) {
+          aFlavors.AppendElement(flavorStr);
+        }
+      }
     }
-  } // if a converter exists
+  }
 
-  array.forget(_retval);
   return NS_OK;
-} // FlavorsTransferableCanExport
+}
 
 NS_IMETHODIMP
 nsTransferable::GetIsPrivateData(bool *aIsPrivateData)
 {
   MOZ_ASSERT(mInitialized);
 
   NS_ENSURE_ARG_POINTER(aIsPrivateData);
 
--- a/widget/nsTransferable.h
+++ b/widget/nsTransferable.h
@@ -68,18 +68,18 @@ public:
 
     // nsISupports
   NS_DECL_ISUPPORTS
   NS_DECL_NSITRANSFERABLE
 
 protected:
   virtual ~nsTransferable();
 
-    // get flavors w/out converter
-  already_AddRefed<nsIMutableArray> GetTransferDataFlavors();
+  // get flavors w/out converter
+  void GetTransferDataFlavors(nsTArray<nsCString>& aFlavors);
  
   nsTArray<DataStruct> mDataArray;
   nsCOMPtr<nsIFormatConverter> mFormatConv;
   bool mPrivateData;
   nsCOMPtr<nsIPrincipal> mRequestingPrincipal;
   nsContentPolicyType mContentPolicyType;
 #if DEBUG
   bool mInitialized;
--- a/widget/windows/nsClipboard.cpp
+++ b/widget/windows/nsClipboard.cpp
@@ -158,104 +158,98 @@ nsresult nsClipboard::SetupNativeDataObj
 
   nsDataObj * dObj = static_cast<nsDataObj *>(aDataObj);
 
   // Now give the Transferable to the DataObject 
   // for getting the data out of it
   dObj->SetTransferable(aTransferable);
 
   // Get the transferable list of data flavors
-  nsCOMPtr<nsIArray> dfList;
-  aTransferable->FlavorsTransferableCanExport(getter_AddRefs(dfList));
+  nsTArray<nsCString> flavors;
+  aTransferable->FlavorsTransferableCanExport(flavors);
 
   // Walk through flavors that contain data and register them
   // into the DataObj as supported flavors
-  uint32_t i;
-  uint32_t cnt;
-  dfList->GetLength(&cnt);
-  for (i=0;i<cnt;i++) {
-    nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(dfList, i);
-    if ( currentFlavor ) {
-      nsCString flavorStr;
-      currentFlavor->ToString(getter_Copies(flavorStr));
-      // When putting data onto the clipboard, we want to maintain kHTMLMime
-      // ("text/html") and not map it to CF_HTML here since this will be done below.
-      UINT format = GetFormat(flavorStr.get(), false);
+  for (uint32_t i = 0; i < flavors.Length(); i++) {
+    nsCString& flavorStr = flavors[i];
+
+    // When putting data onto the clipboard, we want to maintain kHTMLMime
+    // ("text/html") and not map it to CF_HTML here since this will be done below.
+    UINT format = GetFormat(flavorStr.get(), false);
 
-      // Now tell the native IDataObject about both our mime type and 
-      // the native data format
-      FORMATETC fe;
-      SET_FORMATETC(fe, format, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
-      dObj->AddDataFlavor(flavorStr.get(), &fe);
-      
-      // Do various things internal to the implementation, like map one
-      // flavor to another or add additional flavors based on what's required
-      // for the win32 impl.
-      if (flavorStr.EqualsLiteral(kUnicodeMime)) {
-        // if we find text/unicode, also advertise text/plain (which we will convert
-        // on our own in nsDataObj::GetText().
-        FORMATETC textFE;
-        SET_FORMATETC(textFE, CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
-        dObj->AddDataFlavor(kTextMime, &textFE);
-      }
-      else if (flavorStr.EqualsLiteral(kHTMLMime)) {
-        // if we find text/html, also advertise win32's html flavor (which we will convert
-        // on our own in nsDataObj::GetText().
-        FORMATETC htmlFE;
-        SET_FORMATETC(htmlFE, CF_HTML, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
-        dObj->AddDataFlavor(kHTMLMime, &htmlFE);     
-      }
-      else if (flavorStr.EqualsLiteral(kURLMime)) {
-        // if we're a url, in addition to also being text, we need to register
-        // the "file" flavors so that the win32 shell knows to create an internet
-        // shortcut when it sees one of these beasts.
-        FORMATETC shortcutFE;
-        SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
-        dObj->AddDataFlavor(kURLMime, &shortcutFE);      
-        SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
-        dObj->AddDataFlavor(kURLMime, &shortcutFE);      
-        SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_FILECONTENTS), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
-        dObj->AddDataFlavor(kURLMime, &shortcutFE);  
-        SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_INETURLA), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
-        dObj->AddDataFlavor(kURLMime, &shortcutFE);      
-        SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_INETURLW), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
-        dObj->AddDataFlavor(kURLMime, &shortcutFE);      
-      }
-      else if (flavorStr.EqualsLiteral(kPNGImageMime) ||
-               flavorStr.EqualsLiteral(kJPEGImageMime) ||
-               flavorStr.EqualsLiteral(kJPGImageMime) ||
-               flavorStr.EqualsLiteral(kGIFImageMime) ||
-               flavorStr.EqualsLiteral(kNativeImageMime)) {
-        // if we're an image, register the native bitmap flavor
-        FORMATETC imageFE;
-        // Add DIBv5
-        SET_FORMATETC(imageFE, CF_DIBV5, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
-        dObj->AddDataFlavor(flavorStr.get(), &imageFE);
-        // Add DIBv3 
-        SET_FORMATETC(imageFE, CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
-        dObj->AddDataFlavor(flavorStr.get(), &imageFE);
-      }
-      else if (flavorStr.EqualsLiteral(kFilePromiseMime)) {
-         // if we're a file promise flavor, also register the 
-         // CFSTR_PREFERREDDROPEFFECT format.  The data object
-         // returns a value of DROPEFFECTS_MOVE to the drop target
-         // when it asks for the value of this format.  This causes
-         // the file to be moved from the temporary location instead
-         // of being copied.  The right thing to do here is to call
-         // SetData() on the data object and set the value of this format
-         // to DROPEFFECTS_MOVE on this particular data object.  But,
-         // since all the other clipboard formats follow the model of setting
-         // data on the data object only when the drop object calls GetData(),
-         // I am leaving this format's value hard coded in the data object.
-         // We can change this if other consumers of this format get added to this
-         // codebase and they need different values.
-        FORMATETC shortcutFE;
-        SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
-        dObj->AddDataFlavor(kFilePromiseMime, &shortcutFE);
-      }
+    // Now tell the native IDataObject about both our mime type and 
+    // the native data format
+    FORMATETC fe;
+    SET_FORMATETC(fe, format, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
+    dObj->AddDataFlavor(flavorStr.get(), &fe);
+    
+    // Do various things internal to the implementation, like map one
+    // flavor to another or add additional flavors based on what's required
+    // for the win32 impl.
+    if (flavorStr.EqualsLiteral(kUnicodeMime)) {
+      // if we find text/unicode, also advertise text/plain (which we will convert
+      // on our own in nsDataObj::GetText().
+      FORMATETC textFE;
+      SET_FORMATETC(textFE, CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
+      dObj->AddDataFlavor(kTextMime, &textFE);
+    }
+    else if (flavorStr.EqualsLiteral(kHTMLMime)) {
+      // if we find text/html, also advertise win32's html flavor (which we will convert
+      // on our own in nsDataObj::GetText().
+      FORMATETC htmlFE;
+      SET_FORMATETC(htmlFE, CF_HTML, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
+      dObj->AddDataFlavor(kHTMLMime, &htmlFE);     
+    }
+    else if (flavorStr.EqualsLiteral(kURLMime)) {
+      // if we're a url, in addition to also being text, we need to register
+      // the "file" flavors so that the win32 shell knows to create an internet
+      // shortcut when it sees one of these beasts.
+      FORMATETC shortcutFE;
+      SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
+      dObj->AddDataFlavor(kURLMime, &shortcutFE);      
+      SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
+      dObj->AddDataFlavor(kURLMime, &shortcutFE);      
+      SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_FILECONTENTS), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
+      dObj->AddDataFlavor(kURLMime, &shortcutFE);  
+      SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_INETURLA), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
+      dObj->AddDataFlavor(kURLMime, &shortcutFE);      
+      SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_INETURLW), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
+      dObj->AddDataFlavor(kURLMime, &shortcutFE);      
+    }
+    else if (flavorStr.EqualsLiteral(kPNGImageMime) ||
+             flavorStr.EqualsLiteral(kJPEGImageMime) ||
+             flavorStr.EqualsLiteral(kJPGImageMime) ||
+             flavorStr.EqualsLiteral(kGIFImageMime) ||
+             flavorStr.EqualsLiteral(kNativeImageMime)) {
+      // if we're an image, register the native bitmap flavor
+      FORMATETC imageFE;
+      // Add DIBv5
+      SET_FORMATETC(imageFE, CF_DIBV5, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
+      dObj->AddDataFlavor(flavorStr.get(), &imageFE);
+      // Add DIBv3 
+      SET_FORMATETC(imageFE, CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
+      dObj->AddDataFlavor(flavorStr.get(), &imageFE);
+    }
+    else if (flavorStr.EqualsLiteral(kFilePromiseMime)) {
+       // if we're a file promise flavor, also register the 
+       // CFSTR_PREFERREDDROPEFFECT format.  The data object
+       // returns a value of DROPEFFECTS_MOVE to the drop target
+       // when it asks for the value of this format.  This causes
+       // the file to be moved from the temporary location instead
+       // of being copied.  The right thing to do here is to call
+       // SetData() on the data object and set the value of this format
+       // to DROPEFFECTS_MOVE on this particular data object.  But,
+       // since all the other clipboard formats follow the model of setting
+       // data on the data object only when the drop object calls GetData(),
+       // I am leaving this format's value hard coded in the data object.
+       // We can change this if other consumers of this format get added to this
+       // codebase and they need different values.
+      FORMATETC shortcutFE;
+      SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
+      dObj->AddDataFlavor(kFilePromiseMime, &shortcutFE);
     }
   }
 
   return NS_OK;
 }
 
 //-------------------------------------------------------------------------
 NS_IMETHODIMP nsClipboard::SetNativeClipboardData ( int32_t aWhichClipboard )
@@ -591,146 +585,138 @@ nsresult nsClipboard::GetDataFromDataObj
   if (!aTransferable) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsresult res = NS_ERROR_FAILURE;
 
   // get flavor list that includes all flavors that can be written (including ones 
   // obtained through conversion)
-  nsCOMPtr<nsIArray> flavorList;
-  res = aTransferable->FlavorsTransferableCanImport ( getter_AddRefs(flavorList) );
+  nsTArray<nsCString> flavors;
+  res = aTransferable->FlavorsTransferableCanImport(flavors);
   if (NS_FAILED(res)) {
     return NS_ERROR_FAILURE;
   }
 
   // Walk through flavors and see which flavor is on the clipboard them on the native clipboard,
-  uint32_t i;
-  uint32_t cnt;
-  flavorList->GetLength(&cnt);
-  for (i=0;i<cnt;i++) {
-    nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
-    if ( currentFlavor ) {
-      nsCString flavorStr;
-      currentFlavor->ToString(getter_Copies(flavorStr));
-      UINT format = GetFormat(flavorStr.get());
+  for (uint32_t i = 0; i < flavors.Length(); i++) {
+    nsCString& flavorStr = flavors[i];
+    UINT format = GetFormat(flavorStr.get());
 
-      // Try to get the data using the desired flavor. This might fail, but all is
-      // not lost.
-      void* data = nullptr;
-      uint32_t dataLen = 0;
-      bool dataFound = false;
-      if (nullptr != aDataObject) {
-        if (NS_SUCCEEDED(GetNativeDataOffClipboard(aDataObject, anIndex, format, flavorStr.get(), &data, &dataLen))) {
-          dataFound = true;
-        }
-      } 
-      else if (nullptr != aWindow) {
-        if (NS_SUCCEEDED(GetNativeDataOffClipboard(aWindow, anIndex, format, &data, &dataLen))) {
-          dataFound = true;
+    // Try to get the data using the desired flavor. This might fail, but all is
+    // not lost.
+    void* data = nullptr;
+    uint32_t dataLen = 0;
+    bool dataFound = false;
+    if (nullptr != aDataObject) {
+      if (NS_SUCCEEDED(GetNativeDataOffClipboard(aDataObject, anIndex, format, flavorStr.get(), &data, &dataLen))) {
+        dataFound = true;
+      }
+    } 
+    else if (nullptr != aWindow) {
+      if (NS_SUCCEEDED(GetNativeDataOffClipboard(aWindow, anIndex, format, &data, &dataLen))) {
+        dataFound = true;
+      }
+    }
+
+    // This is our second chance to try to find some data, having not found it
+    // when directly asking for the flavor. Let's try digging around in other
+    // flavors to help satisfy our craving for data.
+    if ( !dataFound ) {
+      if (flavorStr.EqualsLiteral(kUnicodeMime)) {
+        dataFound = FindUnicodeFromPlainText(aDataObject, anIndex, &data, &dataLen);
+      }
+      else if (flavorStr.EqualsLiteral(kURLMime)) {
+        // drags from other windows apps expose the native
+        // CFSTR_INETURL{A,W} flavor
+        dataFound = FindURLFromNativeURL ( aDataObject, anIndex, &data, &dataLen );
+        if (!dataFound) {
+          dataFound = FindURLFromLocalFile(aDataObject, anIndex, &data, &dataLen);
         }
       }
-
-      // This is our second chance to try to find some data, having not found it
-      // when directly asking for the flavor. Let's try digging around in other
-      // flavors to help satisfy our craving for data.
-      if ( !dataFound ) {
-        if (flavorStr.EqualsLiteral(kUnicodeMime)) {
-          dataFound = FindUnicodeFromPlainText(aDataObject, anIndex, &data, &dataLen);
-        }
-        else if (flavorStr.EqualsLiteral(kURLMime)) {
-          // drags from other windows apps expose the native
-          // CFSTR_INETURL{A,W} flavor
-          dataFound = FindURLFromNativeURL ( aDataObject, anIndex, &data, &dataLen );
-          if (!dataFound) {
-            dataFound = FindURLFromLocalFile(aDataObject, anIndex, &data, &dataLen);
-          }
-        }
-      } // if we try one last ditch effort to find our data
+    } // if we try one last ditch effort to find our data
 
-      // Hopefully by this point we've found it and can go about our business
-      if ( dataFound ) {
-        nsCOMPtr<nsISupports> genericDataWrapper;
-          if (flavorStr.EqualsLiteral(kFileMime)) {
-            // we have a file path in |data|. Create an nsLocalFile object.
-            nsDependentString filepath(reinterpret_cast<char16_t*>(data));
-            nsCOMPtr<nsIFile> file;
-            if (NS_SUCCEEDED(NS_NewLocalFile(filepath, false, getter_AddRefs(file)))) {
-              genericDataWrapper = do_QueryInterface(file);
-            }
-            free(data);
-          }
-        else if (flavorStr.EqualsLiteral(kNativeHTMLMime)) {
-          uint32_t dummy;
-          // the editor folks want CF_HTML exactly as it's on the clipboard, no conversions,
-          // no fancy stuff. Pull it off the clipboard, stuff it into a wrapper and hand
-          // it back to them.
-          if (FindPlatformHTML(aDataObject, anIndex, &data, &dummy, &dataLen)) {
-            nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, data, dataLen, getter_AddRefs(genericDataWrapper));
-          }
-          else
-          {
-            free(data);
-            continue;     // something wrong with this flavor, keep looking for other data
+    // Hopefully by this point we've found it and can go about our business
+    if ( dataFound ) {
+      nsCOMPtr<nsISupports> genericDataWrapper;
+        if (flavorStr.EqualsLiteral(kFileMime)) {
+          // we have a file path in |data|. Create an nsLocalFile object.
+          nsDependentString filepath(reinterpret_cast<char16_t*>(data));
+          nsCOMPtr<nsIFile> file;
+          if (NS_SUCCEEDED(NS_NewLocalFile(filepath, false, getter_AddRefs(file)))) {
+            genericDataWrapper = do_QueryInterface(file);
           }
           free(data);
         }
-        else if (flavorStr.EqualsLiteral(kHTMLMime)) {
-          uint32_t startOfData = 0;
-          // The JS folks want CF_HTML exactly as it is on the clipboard, but
-          // minus the CF_HTML header index information.
-          // It also needs to be converted to UTF16 and have linebreaks changed.
-          if ( FindPlatformHTML(aDataObject, anIndex, &data, &startOfData, &dataLen) ) {
-            dataLen -= startOfData;
-            nsPrimitiveHelpers::CreatePrimitiveForCFHTML ( static_cast<char*>(data) + startOfData,
-                                                           &dataLen, getter_AddRefs(genericDataWrapper) );
-          }
-          else
-          {
-            free(data);
-            continue;     // something wrong with this flavor, keep looking for other data
-          }
+      else if (flavorStr.EqualsLiteral(kNativeHTMLMime)) {
+        uint32_t dummy;
+        // the editor folks want CF_HTML exactly as it's on the clipboard, no conversions,
+        // no fancy stuff. Pull it off the clipboard, stuff it into a wrapper and hand
+        // it back to them.
+        if (FindPlatformHTML(aDataObject, anIndex, &data, &dummy, &dataLen)) {
+          nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, data, dataLen, getter_AddRefs(genericDataWrapper));
+        }
+        else
+        {
           free(data);
+          continue;     // something wrong with this flavor, keep looking for other data
+        }
+        free(data);
+      }
+      else if (flavorStr.EqualsLiteral(kHTMLMime)) {
+        uint32_t startOfData = 0;
+        // The JS folks want CF_HTML exactly as it is on the clipboard, but
+        // minus the CF_HTML header index information.
+        // It also needs to be converted to UTF16 and have linebreaks changed.
+        if ( FindPlatformHTML(aDataObject, anIndex, &data, &startOfData, &dataLen) ) {
+          dataLen -= startOfData;
+          nsPrimitiveHelpers::CreatePrimitiveForCFHTML ( static_cast<char*>(data) + startOfData,
+                                                         &dataLen, getter_AddRefs(genericDataWrapper) );
         }
-        else if (flavorStr.EqualsLiteral(kJPEGImageMime) ||
-                 flavorStr.EqualsLiteral(kJPGImageMime) ||
-                 flavorStr.EqualsLiteral(kPNGImageMime)) {
-          nsIInputStream * imageStream = reinterpret_cast<nsIInputStream*>(data);
-          genericDataWrapper = do_QueryInterface(imageStream);
-          NS_IF_RELEASE(imageStream);
+        else
+        {
+          free(data);
+          continue;     // something wrong with this flavor, keep looking for other data
         }
-        else {
-          // Treat custom types as a string of bytes.
-          if (!flavorStr.EqualsLiteral(kCustomTypesMime)) {
-            // we probably have some form of text. The DOM only wants LF, so convert from Win32 line 
-            // endings to DOM line endings.
-            int32_t signedLen = static_cast<int32_t>(dataLen);
-            nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(flavorStr, &data, &signedLen);
-            dataLen = signedLen;
+        free(data);
+      }
+      else if (flavorStr.EqualsLiteral(kJPEGImageMime) ||
+               flavorStr.EqualsLiteral(kJPGImageMime) ||
+               flavorStr.EqualsLiteral(kPNGImageMime)) {
+        nsIInputStream * imageStream = reinterpret_cast<nsIInputStream*>(data);
+        genericDataWrapper = do_QueryInterface(imageStream);
+        NS_IF_RELEASE(imageStream);
+      }
+      else {
+        // Treat custom types as a string of bytes.
+        if (!flavorStr.EqualsLiteral(kCustomTypesMime)) {
+          // we probably have some form of text. The DOM only wants LF, so convert from Win32 line 
+          // endings to DOM line endings.
+          int32_t signedLen = static_cast<int32_t>(dataLen);
+          nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(flavorStr, &data, &signedLen);
+          dataLen = signedLen;
 
-            if (flavorStr.EqualsLiteral(kRTFMime)) {
-              // RTF on Windows is known to sometimes deliver an extra null byte.
-              if (dataLen > 0 && static_cast<char*>(data)[dataLen - 1] == '\0') {
-                dataLen--;
-              }
+          if (flavorStr.EqualsLiteral(kRTFMime)) {
+            // RTF on Windows is known to sometimes deliver an extra null byte.
+            if (dataLen > 0 && static_cast<char*>(data)[dataLen - 1] == '\0') {
+              dataLen--;
             }
           }
+        }
 
-          nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, data, dataLen, getter_AddRefs(genericDataWrapper));
-          free(data);
-        }
-        
-        NS_ASSERTION ( genericDataWrapper, "About to put null data into the transferable" );
-        aTransferable->SetTransferData(flavorStr.get(), genericDataWrapper, dataLen);
-        res = NS_OK;
+        nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, data, dataLen, getter_AddRefs(genericDataWrapper));
+        free(data);
+      }
+      
+      NS_ASSERTION ( genericDataWrapper, "About to put null data into the transferable" );
+      aTransferable->SetTransferData(flavorStr.get(), genericDataWrapper, dataLen);
+      res = NS_OK;
 
-        // we found one, get out of the loop
-        break;
-      }
-
+      // we found one, get out of the loop
+      break;
     }
   } // foreach flavor
 
   return res;
 
 }
 
 
--- a/widget/windows/nsDataObj.cpp
+++ b/widget/windows/nsDataObj.cpp
@@ -1273,32 +1273,25 @@ nsDataObj :: GetFileContentsInternetShor
 
 // check if specified flavour is present in the transferable
 bool nsDataObj :: IsFlavourPresent(const char *inFlavour)
 {
   bool retval = false;
   NS_ENSURE_TRUE(mTransferable, false);
   
   // get the list of flavors available in the transferable
-  nsCOMPtr<nsIArray> flavorList;
-  mTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
-  NS_ENSURE_TRUE(flavorList, false);
+  nsTArray<nsCString> flavors;
+  nsresult rv = mTransferable->FlavorsTransferableCanExport(flavors);
+  NS_ENSURE_SUCCESS(rv, false);
 
   // try to find requested flavour
-  uint32_t cnt;
-  flavorList->GetLength(&cnt);
-  for (uint32_t i = 0; i < cnt; ++i) {
-    nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
-    if (currentFlavor) {
-      nsAutoCString flavorStr;
-      currentFlavor->GetData(flavorStr);
-      if (flavorStr.Equals(inFlavour)) {
-        retval = true;         // found it!
-        break;
-      }
+  for (uint32_t i = 0; i < flavors.Length(); ++i) {
+    if (flavors[i].Equals(inFlavour)) {
+      retval = true;         // found it!
+      break;
     }
   } // for each flavor
 
   return retval;
 }
 
 HRESULT nsDataObj::GetPreferredDropEffect ( FORMATETC& aFE, STGMEDIUM& aSTG )
 {