Backed out changeset 5c836acf3197 (bug 906420) on developer request by baku
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 09 Jun 2016 15:30:53 +0200
changeset 341277 f8e3b81a79f45ef8647c98281a9a00d1ddb28b73
parent 341276 f3ff62941927bab2862e525c1b68864e59cdc2c3
child 341278 3ccccf8e5036179a3178437cabc154b5e04b333d
child 341293 4678ba5309817e01839b86f14cbc9469e78c8ae8
child 341388 42c6d8f364b68549a4fabce6e9c71600fbbbe784
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs906420
milestone50.0a1
backs out5c836acf3197c5f30be8832e9f822bfeb175dc24
first release with
nightly linux32
f8e3b81a79f4 / 50.0a1 / 20160609064045 / files
nightly linux64
f8e3b81a79f4 / 50.0a1 / 20160609064045 / files
nightly mac
f8e3b81a79f4 / 50.0a1 / 20160609064045 / files
nightly win32
f8e3b81a79f4 / 50.0a1 / 20160609064045 / files
nightly win64
f8e3b81a79f4 / 50.0a1 / 20160609064045 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 5c836acf3197 (bug 906420) on developer request by baku
dom/base/nsCopySupport.cpp
dom/events/DataTransfer.cpp
dom/events/DataTransfer.h
dom/events/DataTransferItem.cpp
dom/events/DataTransferItem.h
dom/events/DataTransferItemList.cpp
dom/events/DataTransferItemList.h
dom/events/EventStateManager.cpp
dom/events/moz.build
dom/events/test/chrome.ini
dom/events/test/test_DataTransferItemList.html
dom/events/test/test_dragstart.html
dom/locales/en-US/chrome/dom/dom.properties
dom/tests/mochitest/general/test_clipboard_events.html
dom/tests/mochitest/general/test_interfaces.html
dom/webidl/DataTransfer.webidl
dom/webidl/DataTransferItem.webidl
dom/webidl/DataTransferItemList.webidl
dom/webidl/moz.build
editor/libeditor/nsEditorEventListener.cpp
layout/forms/nsFileControlFrame.cpp
testing/web-platform/meta/html/dom/interfaces.html.ini
widget/gonk/nsClipboard.cpp
--- a/dom/base/nsCopySupport.cpp
+++ b/dom/base/nsCopySupport.cpp
@@ -686,18 +686,18 @@ nsCopySupport::FireClipboardEvent(EventM
   const bool chromeShell =
     docShell && docShell->ItemType() == nsIDocShellTreeItem::typeChrome;
 
   // next, fire the cut, copy or paste event
   bool doDefault = true;
   RefPtr<DataTransfer> clipboardData;
   if (chromeShell || Preferences::GetBool("dom.event.clipboardevents.enabled", true)) {
     clipboardData =
-      new DataTransfer(doc->GetScopeObject(), aEventMessage,
-                       aEventMessage == ePaste, aClipboardType);
+      new DataTransfer(piWindow, aEventMessage, aEventMessage == ePaste,
+                       aClipboardType);
 
     nsEventStatus status = nsEventStatus_eIgnore;
     InternalClipboardEvent evt(true, aEventMessage);
     evt.mClipboardData = clipboardData;
     EventDispatcher::Dispatch(content, presShell->GetPresContext(), &evt,
                               nullptr, &status);
     // If the event was cancelled, don't do the clipboard operation
     doDefault = (status != nsEventStatus_eConsumeNoDefault);
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -25,39 +25,48 @@
 #include "nsCRT.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptContext.h"
 #include "nsIDocument.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsVariant.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/DataTransferBinding.h"
-#include "mozilla/dom/DataTransferItemList.h"
 #include "mozilla/dom/Directory.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/FileList.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/OSFileSystem.h"
 #include "mozilla/dom/Promise.h"
-#include "nsNetUtil.h"
 
 namespace mozilla {
 namespace dom {
 
+inline void
+ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
+                            TransferItem& aField,
+                            const char* aName,
+                            uint32_t aFlags = 0)
+{
+  ImplCycleCollectionTraverse(aCallback, aField.mData, aName, aFlags);
+}
+
 NS_IMPL_CYCLE_COLLECTION_CLASS(DataTransfer)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DataTransfer)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mFileList)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mItems)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDragTarget)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDragImage)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DataTransfer)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFileList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mItems)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDragTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDragImage)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(DataTransfer)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(DataTransfer)
@@ -91,17 +100,16 @@ DataTransfer::DataTransfer(nsISupports* 
   , mReadOnly(true)
   , mIsExternal(aIsExternal)
   , mUserCancelled(false)
   , mIsCrossDomainSubFrameDrop(false)
   , mClipboardType(aClipboardType)
   , mDragImageX(0)
   , mDragImageY(0)
 {
-  mItems = new DataTransferItemList(this, aIsExternal, false /* aIsCrossDomainSubFrameDrop */);
   // For these events, we want to be able to add data to the data transfer, so
   // clear the readonly state. Otherwise, the data is already present. For
   // external usage, cache the data from the native clipboard or drag.
   if (aEventMessage == eCut ||
       aEventMessage == eCopy ||
       aEventMessage == eDragStart ||
       aEventMessage == eLegacyDragGesture) {
     mReadOnly = false;
@@ -118,40 +126,36 @@ DataTransfer::DataTransfer(nsISupports* 
 DataTransfer::DataTransfer(nsISupports* aParent,
                            EventMessage aEventMessage,
                            const uint32_t aEffectAllowed,
                            bool aCursorState,
                            bool aIsExternal,
                            bool aUserCancelled,
                            bool aIsCrossDomainSubFrameDrop,
                            int32_t aClipboardType,
-                           DataTransferItemList* aItems,
+                           nsTArray<nsTArray<TransferItem> >& aItems,
                            Element* aDragImage,
                            uint32_t aDragImageX,
                            uint32_t aDragImageY)
   : mParent(aParent)
   , mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE)
   , mEffectAllowed(aEffectAllowed)
   , mEventMessage(aEventMessage)
   , mCursorState(aCursorState)
   , mReadOnly(true)
   , mIsExternal(aIsExternal)
   , mUserCancelled(aUserCancelled)
   , mIsCrossDomainSubFrameDrop(aIsCrossDomainSubFrameDrop)
   , mClipboardType(aClipboardType)
+  , mItems(aItems)
   , mDragImage(aDragImage)
   , mDragImageX(aDragImageX)
   , mDragImageY(aDragImageY)
 {
   MOZ_ASSERT(mParent);
-  MOZ_ASSERT(aItems);
-
-  // We clone the items array after everything else, so that it has a valid
-  // mParent value
-  mItems = aItems->Clone(this);
   // The items are copied from aItems into mItems. There is no need to copy
   // the actual data in the items as the data transfer will be read only. The
   // draggesture and dragstart events are the only times when items are
   // modifiable, but those events should have been using the first constructor
   // above.
   NS_ASSERTION(aEventMessage != eLegacyDragGesture &&
                aEventMessage != eDragStart,
                "invalid event type for DataTransfer constructor");
@@ -283,86 +287,112 @@ DataTransfer::GetMozUserCancelled(bool* 
 {
   *aUserCancelled = MozUserCancelled();
   return NS_OK;
 }
 
 FileList*
 DataTransfer::GetFiles(ErrorResult& aRv)
 {
-  return mItems->Files();
+  return GetFileListInternal(aRv, nsContentUtils::SubjectPrincipal());
+}
+
+FileList*
+DataTransfer::GetFileListInternal(ErrorResult& aRv,
+                                  nsIPrincipal* aSubjectPrincipal)
+{
+  if (mEventMessage != eDrop &&
+      mEventMessage != eLegacyDragDrop &&
+      mEventMessage != ePaste) {
+    return nullptr;
+  }
+
+  if (!mFileList) {
+    mFileList = new FileList(static_cast<nsIDOMDataTransfer*>(this));
+
+    uint32_t count = mItems.Length();
+
+    for (uint32_t i = 0; i < count; i++) {
+      nsCOMPtr<nsIVariant> variant;
+      aRv = GetDataAtInternal(NS_ConvertUTF8toUTF16(kFileMime), i,
+                              aSubjectPrincipal, getter_AddRefs(variant));
+      if (NS_WARN_IF(aRv.Failed())) {
+        return nullptr;
+      }
+
+      if (!variant) {
+        continue;
+      }
+
+      nsCOMPtr<nsISupports> supports;
+      nsresult rv = variant->GetAsISupports(getter_AddRefs(supports));
+
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        continue;
+      }
+
+      nsCOMPtr<nsIFile> file = do_QueryInterface(supports);
+
+      RefPtr<File> domFile;
+      if (file) {
+        MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default,
+                   "nsIFile objects are not expected on the content process");
+
+        bool isDir;
+        aRv = file->IsDirectory(&isDir);
+        if (NS_WARN_IF(aRv.Failed())) {
+          return nullptr;
+        }
+
+        if (isDir) {
+          continue;
+        }
+
+        domFile = File::CreateFromFile(GetParentObject(), file);
+      } else {
+        nsCOMPtr<BlobImpl> blobImpl = do_QueryInterface(supports);
+        if (!blobImpl) {
+          continue;
+        }
+
+        MOZ_ASSERT(blobImpl->IsFile());
+
+        domFile = File::Create(GetParentObject(), blobImpl);
+        MOZ_ASSERT(domFile);
+      }
+
+      mFileList->Append(domFile);
+    }
+  }
+
+  return mFileList;
 }
 
 NS_IMETHODIMP
 DataTransfer::GetFiles(nsIDOMFileList** aFileList)
 {
-  if (!aFileList) {
-    return NS_ERROR_FAILURE;
-  }
-
   ErrorResult rv;
-  RefPtr<FileList> files = GetFiles(rv);
-  if (NS_WARN_IF(rv.Failed())) {
-    return rv.StealNSResult();
-  }
-
-  files.forget(aFileList);
-  return NS_OK;
+  NS_IF_ADDREF(*aFileList =
+    GetFileListInternal(rv, nsContentUtils::GetSystemPrincipal()));
+  return rv.StealNSResult();
 }
 
 already_AddRefed<DOMStringList>
-DataTransfer::GetTypes(ErrorResult& aRv) const
+DataTransfer::Types() const
 {
-  RefPtr<DOMStringList> types = new DOMStringList();
-
-  const nsTArray<RefPtr<DataTransferItem>>* items = mItems->MozItemsAt(0);
-  if (!items || items->IsEmpty()) {
-    return types.forget();
-  }
-
-  bool addFile = false;
-  for (uint32_t i = 0; i < items->Length(); i++) {
-    DataTransferItem* item = items->ElementAt(i);
-    MOZ_ASSERT(item);
-
-    nsAutoString type;
-    item->GetType(type);
-    if (NS_WARN_IF(!types->Add(type))) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return nullptr;
-    }
-
-    if (!addFile) {
-      addFile = item->Kind() == DataTransferItem::KIND_FILE;
-    }
-  }
-
-  // If we have any files, we need to also add the "Files" type!
-  if (addFile && NS_WARN_IF(!types->Add(NS_LITERAL_STRING("Files")))) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return nullptr;
-  }
-
-  return types.forget();
+  ErrorResult rv;
+  return MozTypesAt(0, rv);
 }
 
 NS_IMETHODIMP
 DataTransfer::GetTypes(nsISupports** aTypes)
 {
-  if (NS_WARN_IF(!aTypes)) {
-    return NS_ERROR_FAILURE;
-  }
+  RefPtr<DOMStringList> types = Types();
+  types.forget(aTypes);
 
-  ErrorResult rv;
-  RefPtr<DOMStringList> types = GetTypes(rv);
-  if (NS_WARN_IF(rv.Failed())) {
-    return rv.StealNSResult();
-  }
-
-  types.forget(aTypes);
   return NS_OK;
 }
 
 void
 DataTransfer::GetData(const nsAString& aFormat, nsAString& aData,
                       ErrorResult& aRv)
 {
   // return an empty string if data for the format was not found
@@ -440,17 +470,17 @@ DataTransfer::SetData(const nsAString& a
 void
 DataTransfer::ClearData(const Optional<nsAString>& aFormat, ErrorResult& aRv)
 {
   if (mReadOnly) {
     aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     return;
   }
 
-  if (MozItemCount() == 0) {
+  if (mItems.Length() == 0) {
     return;
   }
 
   if (aFormat.WasPassed()) {
     MozClearDataAtHelper(aFormat.Value(), 0, aRv);
   } else {
     MozClearDataAtHelper(EmptyString(), 0, aRv);
   }
@@ -529,27 +559,38 @@ DataTransfer::MozTypesAt(uint32_t aIndex
   if (aIndex > 0 &&
       (mEventMessage == eCut || mEventMessage == eCopy ||
        mEventMessage == ePaste)) {
     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return nullptr;
   }
 
   RefPtr<DOMStringList> types = new DOMStringList();
-  if (aIndex < MozItemCount()) {
+  if (aIndex < mItems.Length()) {
+    bool addFile = false;
     // note that you can retrieve the types regardless of their principal
-    const nsTArray<RefPtr<DataTransferItem>>& items = *mItems->MozItemsAt(aIndex);
+    const nsTArray<TransferItem>& item = mItems[aIndex];
+    for (uint32_t i = 0; i < item.Length(); i++) {
+      const nsString& format = item[i].mFormat;
+      types->Add(format);
+      if (!addFile) {
+        addFile = format.EqualsASCII(kFileMime);
+      }
+    }
 
-    for (uint32_t i = 0; i < items.Length(); i++) {
-      nsAutoString type;
-      items[i]->GetType(type);
-      if (NS_WARN_IF(!types->Add(type))) {
-        aRv.Throw(NS_ERROR_FAILURE);
-        return nullptr;
+    if (addFile) {
+      // If this is a content caller, and a file is in the data transfer, remove
+      // the non-file types. This prevents alternate text forms of the file
+      // from being returned.
+      if (!nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
+        types->Clear();
+        types->Add(NS_LITERAL_STRING(kFileMime));
       }
+
+      types->Add(NS_LITERAL_STRING("Files"));
     }
   }
 
   return types.forget();
 }
 
 NS_IMETHODIMP
 DataTransfer::MozTypesAt(uint32_t aIndex, nsISupports** aTypes)
@@ -575,87 +616,90 @@ DataTransfer::GetDataAtInternal(const ns
                                 nsIVariant** aData)
 {
   *aData = nullptr;
 
   if (aFormat.IsEmpty()) {
     return NS_OK;
   }
 
-  if (aIndex >= MozItemCount()) {
+  if (aIndex >= mItems.Length()) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
 
   // Only the first item is valid for clipboard events
   if (aIndex > 0 &&
       (mEventMessage == eCut || mEventMessage == eCopy ||
        mEventMessage == ePaste)) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
 
   nsAutoString format;
   GetRealFormat(aFormat, format);
 
-  const nsTArray<RefPtr<DataTransferItem>>& items = *mItems->MozItemsAt(aIndex);
-  if (!aFormat.EqualsLiteral(kFileMime) &&
+  nsTArray<TransferItem>& item = mItems[aIndex];
+
+  // If this is a content caller, and a file is in the data transfer, only
+  // return the file type.
+  if (!format.EqualsLiteral(kFileMime) &&
       !nsContentUtils::IsSystemPrincipal(aSubjectPrincipal)) {
-    for (uint32_t i = 0; i < items.Length(); ++i) {
-      if (items[i]->IsFile()) {
+    uint32_t count = item.Length();
+    for (uint32_t i = 0; i < count; i++) {
+      if (item[i].mFormat.EqualsLiteral(kFileMime)) {
         return NS_OK;
       }
     }
   }
 
   // Check if the caller is allowed to access the drag data. Callers with
   // chrome privileges can always read the data. During the
   // drop event, allow retrieving the data except in the case where the
   // source of the drag is in a child frame of the caller. In that case,
   // we only allow access to data of the same principal. During other events,
   // only allow access to the data with the same principal.
   bool checkFormatItemPrincipal = mIsCrossDomainSubFrameDrop ||
       (mEventMessage != eDrop && mEventMessage != eLegacyDragDrop &&
        mEventMessage != ePaste);
-  MOZ_ASSERT(aSubjectPrincipal);
 
-  RefPtr<DataTransferItem> item = mItems->MozItemByTypeAt(format, aIndex);
-  if (!item) {
-    // The index exists but there's no data for the specified format, in this
-    // case we just return undefined
-    return NS_OK;
-  }
-
-  if (item->Principal() && checkFormatItemPrincipal &&
-      !aSubjectPrincipal->Subsumes(item->Principal())) {
-    return NS_ERROR_DOM_SECURITY_ERR;
-  }
-
-  nsCOMPtr<nsIVariant> data = item->Data();
-  MOZ_ASSERT(data);
+  uint32_t count = item.Length();
+  for (uint32_t i = 0; i < count; i++) {
+    TransferItem& formatitem = item[i];
+    if (formatitem.mFormat.Equals(format)) {
+      if (formatitem.mPrincipal && checkFormatItemPrincipal &&
+          !aSubjectPrincipal->Subsumes(formatitem.mPrincipal)) {
+        return NS_ERROR_DOM_SECURITY_ERR;
+      }
 
-  nsCOMPtr<nsISupports> isupportsData;
-  nsresult rv = data->GetAsISupports(getter_AddRefs(isupportsData));
-
-  if (NS_SUCCEEDED(rv) && isupportsData) {
-    // Make sure the code that is calling us is same-origin with the data.
-    nsCOMPtr<EventTarget> pt = do_QueryInterface(isupportsData);
-    if (pt) {
-      nsresult rv = NS_OK;
-      nsIScriptContext* c = pt->GetContextForEventHandlers(&rv);
-      NS_ENSURE_TRUE(c && NS_SUCCEEDED(rv), NS_ERROR_DOM_SECURITY_ERR);
-      nsIGlobalObject* go = c->GetGlobalObject();
-      NS_ENSURE_TRUE(go, NS_ERROR_DOM_SECURITY_ERR);
-      nsCOMPtr<nsIScriptObjectPrincipal> sp = do_QueryInterface(go);
-      MOZ_ASSERT(sp, "This cannot fail on the main thread.");
-      nsIPrincipal* dataPrincipal = sp->GetPrincipal();
-      NS_ENSURE_TRUE(dataPrincipal, NS_ERROR_DOM_SECURITY_ERR);
-      NS_ENSURE_TRUE(aSubjectPrincipal->Subsumes(dataPrincipal), NS_ERROR_DOM_SECURITY_ERR);
+      if (!formatitem.mData) {
+        FillInExternalData(formatitem, aIndex);
+      } else {
+        nsCOMPtr<nsISupports> data;
+        formatitem.mData->GetAsISupports(getter_AddRefs(data));
+        // Make sure the code that is calling us is same-origin with the data.
+        nsCOMPtr<EventTarget> pt = do_QueryInterface(data);
+        if (pt) {
+          nsresult rv = NS_OK;
+          nsIScriptContext* c = pt->GetContextForEventHandlers(&rv);
+          NS_ENSURE_TRUE(c && NS_SUCCEEDED(rv), NS_ERROR_DOM_SECURITY_ERR);
+          nsIGlobalObject* go = c->GetGlobalObject();
+          NS_ENSURE_TRUE(go, NS_ERROR_DOM_SECURITY_ERR);
+          nsCOMPtr<nsIScriptObjectPrincipal> sp = do_QueryInterface(go);
+          MOZ_ASSERT(sp, "This cannot fail on the main thread.");
+          nsIPrincipal* dataPrincipal = sp->GetPrincipal();
+          NS_ENSURE_TRUE(dataPrincipal, NS_ERROR_DOM_SECURITY_ERR);
+          NS_ENSURE_TRUE(aSubjectPrincipal->Subsumes(dataPrincipal),
+                                                     NS_ERROR_DOM_SECURITY_ERR);
+        }
+      }
+      *aData = formatitem.mData;
+      NS_IF_ADDREF(*aData);
+      return NS_OK;
     }
   }
 
-  data.forget(aData);
   return NS_OK;
 }
 
 void
 DataTransfer::MozGetDataAt(JSContext* aCx, const nsAString& aFormat,
                            uint32_t aIndex,
                            JS::MutableHandle<JS::Value> aRetval,
                            mozilla::ErrorResult& aRv)
@@ -689,17 +733,17 @@ DataTransfer::SetDataAtInternal(const ns
   }
 
   if (mReadOnly) {
     return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
   }
 
   // Specifying an index less than the current length will replace an existing
   // item. Specifying an index equal to the current length will add a new item.
-  if (aIndex > MozItemCount()) {
+  if (aIndex > mItems.Length()) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
 
   // Only the first item is valid for clipboard events
   if (aIndex > 0 &&
       (mEventMessage == eCut || mEventMessage == eCopy ||
        mEventMessage == ePaste)) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
@@ -747,57 +791,79 @@ void
 DataTransfer::MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
                              ErrorResult& aRv)
 {
   if (mReadOnly) {
     aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     return;
   }
 
-  if (aIndex >= MozItemCount()) {
+  if (aIndex >= mItems.Length()) {
     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
   // Only the first item is valid for clipboard events
   if (aIndex > 0 &&
       (mEventMessage == eCut || mEventMessage == eCopy ||
        mEventMessage == ePaste)) {
     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
   MozClearDataAtHelper(aFormat, aIndex, aRv);
-
-  // If we just cleared the 0-th index, and there are still more than 1 indexes
-  // remaining, MozClearDataAt should cause the 1st index to become the 0th
-  // index. This should _only_ happen when the MozClearDataAt function is
-  // explicitly called by script, as this behavior is inconsistent with spec.
-  // (however, so is the MozClearDataAt API)
-
-  if (aIndex == 0 && mItems->MozItemCount() > 1 &&
-      mItems->MozItemsAt(0)->Length() == 0) {
-    mItems->PopIndexZero();
-  }
 }
 
 void
 DataTransfer::MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
                                    ErrorResult& aRv)
 {
   MOZ_ASSERT(!mReadOnly);
-  MOZ_ASSERT(aIndex < MozItemCount());
+  MOZ_ASSERT(aIndex < mItems.Length());
   MOZ_ASSERT(aIndex == 0 ||
              (mEventMessage != eCut && mEventMessage != eCopy &&
               mEventMessage != ePaste));
 
   nsAutoString format;
   GetRealFormat(aFormat, format);
 
-  mItems->MozRemoveByTypeAt(format, aIndex, aRv);
+  nsIPrincipal* principal = nsContentUtils::SubjectPrincipal();
+
+  // if the format is empty, clear all formats
+  bool clearall = format.IsEmpty();
+
+  nsTArray<TransferItem>& item = mItems[aIndex];
+  // count backwards so that the count and index don't have to be adjusted
+  // after removing an element
+  for (int32_t i = item.Length() - 1; i >= 0; i--) {
+    TransferItem& formatitem = item[i];
+    if (clearall || formatitem.mFormat.Equals(format)) {
+      // don't allow removing data that has a stronger principal
+      bool subsumes;
+      if (formatitem.mPrincipal && principal &&
+          (NS_FAILED(principal->Subsumes(formatitem.mPrincipal, &subsumes)) ||
+           !subsumes)) {
+        aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+        return;
+      }
+
+      item.RemoveElementAt(i);
+
+      // if a format was specified, break out. Otherwise, loop around until
+      // all formats have been removed
+      if (!clearall) {
+        break;
+      }
+    }
+  }
+
+  // if the last format for an item is removed, remove the entire item
+  if (!item.Length()) {
+     mItems.RemoveElementAt(aIndex);
+  }
 }
 
 NS_IMETHODIMP
 DataTransfer::MozClearDataAt(const nsAString& aFormat, uint32_t aIndex)
 {
   ErrorResult rv;
   MozClearDataAt(aFormat, aIndex, rv);
   return rv.StealNSResult();
@@ -840,27 +906,29 @@ DataTransfer::GetFilesAndDirectories(Err
   nsCOMPtr<nsIGlobalObject> global = parentNode->OwnerDoc()->GetScopeObject();
   MOZ_ASSERT(global);
   if (!global) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   RefPtr<Promise> p = Promise::Create(global, aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
+  if (aRv.Failed()) {
     return nullptr;
   }
 
-  RefPtr<FileList> files = mItems->Files();
-  if (NS_WARN_IF(!files)) {
-    return nullptr;
+  if (!mFileList) {
+    GetFiles(aRv);
+    if (NS_WARN_IF(aRv.Failed())) {
+      return nullptr;
+    }
   }
 
   Sequence<RefPtr<File>> filesSeq;
-  files->ToSequence(filesSeq, aRv);
+  mFileList->ToSequence(filesSeq, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
   p->MaybeResolve(filesSeq);
 
   return p.forget();
 }
@@ -889,23 +957,24 @@ DataTransfer::AddElement(nsIDOMElement* 
   return rv.StealNSResult();
 }
 
 nsresult
 DataTransfer::Clone(nsISupports* aParent, EventMessage aEventMessage,
                     bool aUserCancelled, bool aIsCrossDomainSubFrameDrop,
                     DataTransfer** aNewDataTransfer)
 {
-  RefPtr<DataTransfer> newDataTransfer =
+  DataTransfer* newDataTransfer =
     new DataTransfer(aParent, aEventMessage, mEffectAllowed, mCursorState,
                      mIsExternal, aUserCancelled, aIsCrossDomainSubFrameDrop,
                      mClipboardType, mItems, mDragImage, mDragImageX,
                      mDragImageY);
 
-  newDataTransfer.forget(aNewDataTransfer);
+  *aNewDataTransfer = newDataTransfer;
+  NS_ADDREF(*aNewDataTransfer);
   return NS_OK;
 }
 
 already_AddRefed<nsISupportsArray>
 DataTransfer::GetTransferables(nsIDOMNode* aDragTarget)
 {
   MOZ_ASSERT(aDragTarget);
 
@@ -927,35 +996,35 @@ DataTransfer::GetTransferables(nsILoadCo
 {
 
   nsCOMPtr<nsISupportsArray> transArray =
     do_CreateInstance("@mozilla.org/supports-array;1");
   if (!transArray) {
     return nullptr;
   }
 
-  uint32_t count = MozItemCount();
+  uint32_t count = mItems.Length();
   for (uint32_t i = 0; i < count; i++) {
     nsCOMPtr<nsITransferable> transferable = GetTransferable(i, aLoadContext);
     if (transferable) {
       transArray->AppendElement(transferable);
     }
   }
 
   return transArray.forget();
 }
 
 already_AddRefed<nsITransferable>
 DataTransfer::GetTransferable(uint32_t aIndex, nsILoadContext* aLoadContext)
 {
-  if (aIndex >= MozItemCount()) {
+  if (aIndex >= mItems.Length()) {
     return nullptr;
   }
 
-  const nsTArray<RefPtr<DataTransferItem>>& item = *mItems->MozItemsAt(aIndex);
+  nsTArray<TransferItem>& item = mItems[aIndex];
   uint32_t count = item.Length();
   if (!count) {
     return nullptr;
   }
 
   nsCOMPtr<nsITransferable> transferable =
     do_CreateInstance("@mozilla.org/widget/transferable;1");
   if (!transferable) {
@@ -997,38 +1066,35 @@ DataTransfer::GetTransferable(uint32_t a
    *   <wide string> format
    *   <32-bit> length of data
    *   <wide string> data
    * A type of eCustomClipboardTypeId_None ends the list, without any following
    * data.
    */
   do {
     for (uint32_t f = 0; f < count; f++) {
-      RefPtr<DataTransferItem> formatitem = item[f];
-      if (!formatitem->Data()) { // skip empty items
+      const TransferItem& formatitem = item[f];
+      if (!formatitem.mData) { // skip empty items
         continue;
       }
 
-      nsAutoString type;
-      formatitem->GetType(type);
-
       // If the data is of one of the well-known formats, use it directly.
       bool isCustomFormat = true;
       for (uint32_t f = 0; f < ArrayLength(knownFormats); f++) {
-        if (type.EqualsASCII(knownFormats[f])) {
+        if (formatitem.mFormat.EqualsASCII(knownFormats[f])) {
           isCustomFormat = false;
           break;
         }
       }
 
       uint32_t lengthInBytes;
       nsCOMPtr<nsISupports> convertedData;
 
       if (handlingCustomFormats) {
-        if (!ConvertFromVariant(formatitem->Data(), getter_AddRefs(convertedData),
+        if (!ConvertFromVariant(formatitem.mData, getter_AddRefs(convertedData),
                                 &lengthInBytes)) {
           continue;
         }
 
         // When handling custom types, add the data to the stream if this is a
         // custom type.
         if (isCustomFormat) {
           // If it isn't a string, just ignore it. The dataTransfer is cached in
@@ -1045,21 +1111,22 @@ DataTransfer::GetTransferable(uint32_t a
 
               nsCOMPtr<nsIOutputStream> outputStream;
               storageStream->GetOutputStream(0, getter_AddRefs(outputStream));
 
               stream = do_CreateInstance("@mozilla.org/binaryoutputstream;1");
               stream->SetOutputStream(outputStream);
             }
 
-            int32_t formatLength = type.Length() * sizeof(nsString::char_type);
+            int32_t formatLength =
+              formatitem.mFormat.Length() * sizeof(nsString::char_type);
 
             stream->Write32(eCustomClipboardTypeId_String);
             stream->Write32(formatLength);
-            stream->WriteBytes((const char *)type.get(),
+            stream->WriteBytes((const char *)formatitem.mFormat.get(),
                                formatLength);
             stream->Write32(lengthInBytes);
             stream->WriteBytes((const char *)data.get(), lengthInBytes);
 
             // The total size of the stream is the format length, the data
             // length, two integers to hold the lengths and one integer for the
             // string flag.
             totalCustomLength +=
@@ -1103,25 +1170,25 @@ DataTransfer::GetTransferable(uint32_t a
 
         added = true;
 
         // Clear the stream so it doesn't get used again.
         stream = nullptr;
       } else {
         // This is the second pass of the loop and a known type is encountered.
         // Add it as is.
-        if (!ConvertFromVariant(formatitem->Data(), getter_AddRefs(convertedData),
+        if (!ConvertFromVariant(formatitem.mData, getter_AddRefs(convertedData),
                                 &lengthInBytes)) {
           continue;
         }
 
         // The underlying drag code uses text/unicode, so use that instead of
         // text/plain
         const char* format;
-        NS_ConvertUTF16toUTF8 utf8format(type);
+        NS_ConvertUTF16toUTF8 utf8format(formatitem.mFormat);
         if (utf8format.EqualsLiteral(kTextMime)) {
           format = kUnicodeMime;
         } else {
           format = utf8format.get();
         }
 
         // If a converter is set for a format, set the converter for the
         // transferable and don't add the item
@@ -1163,17 +1230,17 @@ DataTransfer::ConvertFromVariant(nsIVari
   *aLength = 0;
 
   uint16_t type;
   aVariant->GetDataType(&type);
   if (type == nsIDataType::VTYPE_INTERFACE ||
       type == nsIDataType::VTYPE_INTERFACE_IS) {
     nsCOMPtr<nsISupports> data;
     if (NS_FAILED(aVariant->GetAsISupports(getter_AddRefs(data)))) {
-      return false;
+     return false;
     }
 
     nsCOMPtr<nsIFlavorDataProvider> fdp = do_QueryInterface(data);
     if (fdp) {
       // for flavour data providers, use kFlavorHasDataProvider (which has the
       // value 0) as the length.
       fdp.forget(aSupports);
       *aLength = nsITransferable::kFlavorHasDataProvider;
@@ -1219,38 +1286,71 @@ DataTransfer::ConvertFromVariant(nsIVari
   *aLength = str.Length() << 1;
 
   return true;
 }
 
 void
 DataTransfer::ClearAll()
 {
-  mItems->ClearAllItems();
-}
-
-uint32_t
-DataTransfer::MozItemCount() const
-{
-  return mItems->MozItemCount();
+  mItems.Clear();
 }
 
 nsresult
 DataTransfer::SetDataWithPrincipal(const nsAString& aFormat,
                                    nsIVariant* aData,
                                    uint32_t aIndex,
                                    nsIPrincipal* aPrincipal)
 {
   nsAutoString format;
   GetRealFormat(aFormat, format);
 
-  ErrorResult rv;
-  RefPtr<DataTransferItem> item =
-    mItems->SetDataWithPrincipal(format, aData, aIndex, aPrincipal, false, rv);
-  return rv.StealNSResult();
+  // check if the item for the format already exists. In that case,
+  // just replace it.
+  TransferItem* formatitem;
+  if (aIndex < mItems.Length()) {
+    nsTArray<TransferItem>& item = mItems[aIndex];
+    uint32_t count = item.Length();
+    for (uint32_t i = 0; i < count; i++) {
+      TransferItem& itemformat = item[i];
+      if (itemformat.mFormat.Equals(format)) {
+        // don't allow replacing data that has a stronger principal
+        bool subsumes;
+        if (itemformat.mPrincipal && aPrincipal &&
+            (NS_FAILED(aPrincipal->Subsumes(itemformat.mPrincipal,
+                                            &subsumes)) || !subsumes)) {
+          return NS_ERROR_DOM_SECURITY_ERR;
+        }
+
+        itemformat.mPrincipal = aPrincipal;
+        itemformat.mData = aData;
+        return NS_OK;
+      }
+    }
+
+    // add a new format
+    formatitem = item.AppendElement();
+  }
+  else {
+    NS_ASSERTION(aIndex == mItems.Length(), "Index out of range");
+
+    // add a new index
+    nsTArray<TransferItem>* item = mItems.AppendElement();
+    NS_ENSURE_TRUE(item, NS_ERROR_OUT_OF_MEMORY);
+
+    formatitem = item->AppendElement();
+  }
+
+  NS_ENSURE_TRUE(formatitem, NS_ERROR_OUT_OF_MEMORY);
+
+  formatitem->mFormat = format;
+  formatitem->mPrincipal = aPrincipal;
+  formatitem->mData = aData;
+
+  return NS_OK;
 }
 
 void
 DataTransfer::SetDataWithPrincipalFromOtherProcess(const nsAString& aFormat,
                                                    nsIVariant* aData,
                                                    uint32_t aIndex,
                                                    nsIPrincipal* aPrincipal)
 {
@@ -1297,22 +1397,16 @@ DataTransfer::CacheExternalData(const ch
                          aPrincipal);
     return;
   }
 
   SetDataWithPrincipal(NS_ConvertUTF8toUTF16(aFormat), nullptr, aIndex,
                        aPrincipal);
 }
 
-// there isn't a way to get a list of the formats that might be available on
-// all platforms, so just check for the types that can actually be imported
-// XXXndeakin there are some other formats but those are platform specific.
-const char* kFormats[] = { kFileMime, kHTMLMime, kURLMime, kURLDataMime,
-                           kUnicodeMime };
-
 void
 DataTransfer::CacheExternalDragFormats()
 {
   // Called during the constructor to cache the formats available from an
   // external drag. The data associated with each format will be set to null.
   // This data will instead only be retrieved in FillInExternalDragData when
   // asked for, as it may be time consuming for the source application to
   // generate it.
@@ -1344,21 +1438,21 @@ DataTransfer::CacheExternalDragFormats()
     }
 
     for (uint32_t f = 0; f < ArrayLength(formats); f++) {
       // IsDataFlavorSupported doesn't take an index as an argument and just
       // checks if any of the items support a particular flavor, even though
       // the GetData method does take an index. Here, we just assume that
       // every item being dragged has the same set of flavors.
       bool supported;
-      dragSession->IsDataFlavorSupported(kFormats[f], &supported);
+      dragSession->IsDataFlavorSupported(formats[f], &supported);
       // if the format is supported, add an item to the array with null as
       // the data. When retrieved, GetRealData will read the data.
       if (supported) {
-        CacheExternalData(kFormats[f], c, sysPrincipal);
+        CacheExternalData(formats[f], c, sysPrincipal);
       }
     }
   }
 }
 
 void
 DataTransfer::CacheExternalClipboardFormats()
 {
@@ -1398,44 +1492,127 @@ DataTransfer::CacheExternalClipboardForm
       } else {
         CacheExternalData(formats[f], 0, sysPrincipal);
       }
     }
   }
 }
 
 void
+DataTransfer::FillInExternalData(TransferItem& aItem, uint32_t aIndex)
+{
+  NS_PRECONDITION(mIsExternal, "Not an external data transfer");
+
+  if (aItem.mData) {
+    return;
+  }
+
+  // only drag and paste events should be calling FillInExternalData
+  NS_ASSERTION(mEventMessage != eCut && mEventMessage != eCopy,
+               "clipboard event with empty data");
+
+  NS_ConvertUTF16toUTF8 utf8format(aItem.mFormat);
+  const char* format = utf8format.get();
+  if (strcmp(format, "text/plain") == 0) {
+    format = kUnicodeMime;
+  } else if (strcmp(format, "text/uri-list") == 0) {
+    format = kURLDataMime;
+  }
+
+  nsCOMPtr<nsITransferable> trans =
+    do_CreateInstance("@mozilla.org/widget/transferable;1");
+  if (!trans) {
+    return;
+  }
+
+  trans->Init(nullptr);
+  trans->AddDataFlavor(format);
+
+  if (mEventMessage == ePaste) {
+    MOZ_ASSERT(aIndex == 0, "index in clipboard must be 0");
+
+    nsCOMPtr<nsIClipboard> clipboard =
+      do_GetService("@mozilla.org/widget/clipboard;1");
+    if (!clipboard || mClipboardType < 0) {
+      return;
+    }
+
+    clipboard->GetData(trans, mClipboardType);
+  } else {
+    nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
+    if (!dragSession) {
+      return;
+    }
+
+#ifdef DEBUG
+    // Since this is an external drag, the source document will always be null.
+    nsCOMPtr<nsIDOMDocument> domDoc;
+    dragSession->GetSourceDocument(getter_AddRefs(domDoc));
+    MOZ_ASSERT(!domDoc);
+#endif
+
+    dragSession->GetData(trans, aIndex);
+  }
+
+  uint32_t length = 0;
+  nsCOMPtr<nsISupports> data;
+  trans->GetTransferData(format, getter_AddRefs(data), &length);
+  if (!data)
+    return;
+
+  RefPtr<nsVariantCC> variant = new nsVariantCC();
+
+  nsCOMPtr<nsISupportsString> supportsstr = do_QueryInterface(data);
+  if (supportsstr) {
+    nsAutoString str;
+    supportsstr->GetData(str);
+    variant->SetAsAString(str);
+  }
+  else {
+    nsCOMPtr<nsISupportsCString> supportscstr = do_QueryInterface(data);
+    if (supportscstr) {
+      nsAutoCString str;
+      supportscstr->GetData(str);
+      variant->SetAsACString(str);
+    } else {
+      variant->SetAsISupports(data);
+    }
+  }
+
+  aItem.mData = variant;
+}
+
+void
 DataTransfer::FillAllExternalData()
 {
   if (mIsExternal) {
-    for (uint32_t i = 0; i < MozItemCount(); ++i) {
-      const nsTArray<RefPtr<DataTransferItem>>& items = *mItems->MozItemsAt(i);
-      for (uint32_t j = 0; j < items.Length(); ++j) {
-        MOZ_ASSERT(items[j]->Index() == i);
-
-        items[j]->FillInExternalData();
+    for (uint32_t i = 0; i < mItems.Length(); ++i) {
+      nsTArray<TransferItem>& itemArray = mItems[i];
+      for (uint32_t j = 0; j < itemArray.Length(); ++j) {
+        if (!itemArray[j].mData) {
+          FillInExternalData(itemArray[j], i);
+        }
       }
     }
   }
 }
 
 void
 DataTransfer::FillInExternalCustomTypes(uint32_t aIndex,
                                         nsIPrincipal* aPrincipal)
 {
-  RefPtr<DataTransferItem> item = new DataTransferItem(mItems,
-                                                       NS_LITERAL_STRING(kCustomTypesMime));
-  item->SetKind(DataTransferItem::KIND_STRING);
-  item->SetIndex(aIndex);
+  TransferItem item;
+  item.mFormat.AssignLiteral(kCustomTypesMime);
 
-  if (!item->Data()) {
+  FillInExternalData(item, aIndex);
+  if (!item.mData) {
     return;
   }
 
-  FillInExternalCustomTypes(item->Data(), aIndex, aPrincipal);
+  FillInExternalCustomTypes(item.mData, aIndex, aPrincipal);
 }
 
 void
 DataTransfer::FillInExternalCustomTypes(nsIVariant* aData, uint32_t aIndex,
                                         nsIPrincipal* aPrincipal)
 {
   char* chrs;
   uint32_t len = 0;
--- a/dom/events/DataTransfer.h
+++ b/dom/events/DataTransfer.h
@@ -27,27 +27,38 @@ class nsISupportsArray;
 class nsILoadContext;
 
 namespace mozilla {
 
 class EventStateManager;
 
 namespace dom {
 
-class DataTransferItem;
-class DataTransferItemList;
 class DOMStringList;
 class Element;
 class FileList;
 class Promise;
 template<typename T> class Optional;
 
+/**
+ * TransferItem is used to hold data for a particular format. Each piece of
+ * data has a principal set from the caller which added it. This allows a
+ * caller that wishes to retrieve the data to only be able to access the data
+ * it is allowed to, yet still allow a chrome caller to retrieve any of the
+ * data.
+ */
+struct TransferItem {
+  nsString mFormat;
+  nsCOMPtr<nsIPrincipal> mPrincipal;
+  nsCOMPtr<nsIVariant> mData;
+};
+
 #define NS_DATATRANSFER_IID \
-{ 0x6c5f90d1, 0xa886, 0x42c8, \
-  { 0x85, 0x06, 0x10, 0xbe, 0x5c, 0x0d, 0xc6, 0x77 } }
+{ 0x43ee0327, 0xde5d, 0x463d, \
+  { 0x9b, 0xd0, 0xf1, 0x79, 0x09, 0x69, 0xf2, 0xfb } }
 
 class DataTransfer final : public nsIDOMDataTransfer,
                            public nsWrapperCache
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_DATATRANSFER_IID)
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -72,26 +83,27 @@ protected:
   DataTransfer(nsISupports* aParent,
                EventMessage aEventMessage,
                const uint32_t aEffectAllowed,
                bool aCursorState,
                bool aIsExternal,
                bool aUserCancelled,
                bool aIsCrossDomainSubFrameDrop,
                int32_t aClipboardType,
-               DataTransferItemList* aItems,
+               nsTArray<nsTArray<TransferItem> >& aItems,
                Element* aDragImage,
                uint32_t aDragImageX,
                uint32_t aDragImageY);
 
   ~DataTransfer();
 
   static const char sEffects[8][9];
 
 public:
+
   // Constructor for DataTransfer.
   //
   // aIsExternal must only be true when used to create a dataTransfer for a
   // paste or a drag that was started without using a data transfer. The
   // latter will occur when an external drag occurs, that is, a drag where the
   // source is another application, or a drag is started by calling the drag
   // service directly. For clipboard operations, aClipboardType indicates
   // which clipboard to use, from nsIClipboard, or -1 for non-clipboard
@@ -132,33 +144,36 @@ public:
     } else {
       aEffectAllowed.AssignASCII(sEffects[mEffectAllowed]);
     }
   }
 
   void SetDragImage(Element& aElement, int32_t aX, int32_t aY,
                     ErrorResult& aRv);
 
-  already_AddRefed<DOMStringList> GetTypes(ErrorResult& rv) const;
+  already_AddRefed<DOMStringList> Types() const;
 
   void GetData(const nsAString& aFormat, nsAString& aData, ErrorResult& aRv);
 
   void SetData(const nsAString& aFormat, const nsAString& aData,
                ErrorResult& aRv);
 
   void ClearData(const mozilla::dom::Optional<nsAString>& aFormat,
                  mozilla::ErrorResult& aRv);
 
   FileList* GetFiles(mozilla::ErrorResult& aRv);
 
   already_AddRefed<Promise> GetFilesAndDirectories(ErrorResult& aRv);
 
   void AddElement(Element& aElement, mozilla::ErrorResult& aRv);
 
-  uint32_t MozItemCount() const;
+  uint32_t MozItemCount() const
+  {
+    return mItems.Length();
+  }
 
   void GetMozCursor(nsString& aCursor)
   {
     if (mCursorState) {
       aCursor.AssignLiteral("default");
     } else {
       aCursor.AssignLiteral("auto");
     }
@@ -190,24 +205,18 @@ public:
     return mDragTarget;
   }
 
   nsresult GetDataAtNoSecurityCheck(const nsAString& aFormat, uint32_t aIndex,
                                     nsIVariant** aData);
 
   // a readonly dataTransfer cannot have new data added or existing data
   // removed. Only the dropEffect and effectAllowed may be modified.
-  DataTransferItemList* Items() const { return mItems; }
-
-  bool IsReadOnly() const { return mReadOnly; }
   void SetReadOnly() { mReadOnly = true; }
 
-  int32_t ClipboardType() const { return mClipboardType; }
-  EventMessage GetEventMessage() const { return mEventMessage; }
-
   // converts the data into an array of nsITransferable objects to be used for
   // drag and drop or clipboard operations.
   already_AddRefed<nsISupportsArray> GetTransferables(nsIDOMNode* aDragTarget);
 
   already_AddRefed<nsISupportsArray>
   GetTransferables(nsILoadContext* aLoadContext);
 
   // converts the data for a single item at aIndex into an nsITransferable
@@ -246,35 +255,42 @@ public:
     *aY = mDragImageY;
     return mDragImage;
   }
 
   nsresult Clone(nsISupports* aParent, EventMessage aEventMessage,
                  bool aUserCancelled, bool aIsCrossDomainSubFrameDrop,
                  DataTransfer** aResult);
 
+protected:
+
   // converts some formats used for compatibility in aInFormat into aOutFormat.
   // Text and text/unicode become text/plain, and URL becomes text/uri-list
   void GetRealFormat(const nsAString& aInFormat, nsAString& aOutFormat) const;
 
-protected:
-
   // caches text and uri-list data formats that exist in the drag service or
   // clipboard for retrieval later.
   void CacheExternalData(const char* aFormat, uint32_t aIndex,
                          nsIPrincipal* aPrincipal);
 
   // caches the formats that exist in the drag service that were added by an
   // external drag
   void CacheExternalDragFormats();
 
   // caches the formats that exist in the clipboard
   void CacheExternalClipboardFormats();
 
-  FileList* GetFilesInternal(ErrorResult& aRv, nsIPrincipal* aSubjectPrincipal);
+  // fills in the data field of aItem with the data from the drag service or
+  // clipboard for a given index.
+  void FillInExternalData(TransferItem& aItem, uint32_t aIndex);
+
+
+  FileList* GetFileListInternal(ErrorResult& aRv,
+                                nsIPrincipal* aSubjectPrincipal);
+
   nsresult GetDataAtInternal(const nsAString& aFormat, uint32_t aIndex,
                              nsIPrincipal* aSubjectPrincipal,
                              nsIVariant** aData);
 
   nsresult SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData,
                              uint32_t aIndex, nsIPrincipal* aSubjectPrincipal);
 
   friend class ContentParent;
@@ -316,18 +332,22 @@ protected:
   // true if this is a cross-domain drop from a subframe where access to the
   // data should be prevented
   bool mIsCrossDomainSubFrameDrop;
 
   // Indicates which clipboard type to use for clipboard operations. Ignored for
   // drag and drop.
   int32_t mClipboardType;
 
-  // The items contained with the DataTransfer
-  RefPtr<DataTransferItemList> mItems;
+  // array of items, each containing an array of format->data pairs
+  nsTArray<nsTArray<TransferItem> > mItems;
+
+  // array of files and directories, containing only the files present in the
+  // dataTransfer
+  RefPtr<FileList> mFileList;
 
   // the target of the drag. The drag and dragend events will fire at this.
   nsCOMPtr<mozilla::dom::Element> mDragTarget;
 
   // the custom drag image and coordinates within the image. If mDragImage is
   // null, the default image is created from the drag target.
   nsCOMPtr<mozilla::dom::Element> mDragImage;
   uint32_t mDragImageX;
deleted file mode 100644
--- a/dom/events/DataTransferItem.cpp
+++ /dev/null
@@ -1,365 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "DataTransferItem.h"
-#include "DataTransferItemList.h"
-
-#include "mozilla/ContentEvents.h"
-#include "mozilla/EventForwards.h"
-#include "mozilla/dom/DataTransferItemBinding.h"
-#include "nsIClipboard.h"
-#include "nsISupportsPrimitives.h"
-#include "nsNetUtil.h"
-#include "nsQueryObject.h"
-#include "nsContentUtils.h"
-#include "nsVariant.h"
-
-namespace {
-
-struct FileMimeNameData
-{
-  const char* mMimeName;
-  const char* mFileName;
-};
-
-FileMimeNameData kFileMimeNameMap[] = {
-  { kFileMime, "GenericFileName" },
-};
-
-already_AddRefed<mozilla::dom::File>
-FileFromISupports(nsISupports* aSupports)
-{
-  MOZ_ASSERT(aSupports);
-
-  nsCOMPtr<nsIDOMBlob> domBlob = do_QueryInterface(aSupports);
-  if (domBlob) {
-    // Get out the blob - this is OK, because nsIDOMBlob is a builtinclass
-    // and the only implementer is Blob.
-    mozilla::dom::Blob* blob = static_cast<mozilla::dom::Blob*>(domBlob.get());
-    return blob->ToFile();
-  }
-
-  return nullptr;
-}
-
-} // anonymous namespace
-
-namespace mozilla {
-namespace dom {
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DataTransferItem, mData,
-                                      mPrincipal, mParent)
-NS_IMPL_CYCLE_COLLECTING_ADDREF(DataTransferItem)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(DataTransferItem)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DataTransferItem)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-JSObject*
-DataTransferItem::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return DataTransferItemBinding::Wrap(aCx, this, aGivenProto);
-}
-
-already_AddRefed<DataTransferItem>
-DataTransferItem::Clone(DataTransferItemList* aParent) const
-{
-  MOZ_ASSERT(aParent);
-
-  RefPtr<DataTransferItem> it = new DataTransferItem(aParent, mType);
-
-  // Copy over all of the fields
-  it->mKind = mKind;
-  it->mIndex = mIndex;
-  it->mData = mData;
-  it->mPrincipal = mPrincipal;
-
-  return it.forget();
-}
-
-void
-DataTransferItem::SetType(const nsAString& aType)
-{
-  mType = aType;
-}
-
-void
-DataTransferItem::SetData(nsIVariant* aData)
-{
-  if (!aData) {
-    // We are holding a temporary null which will later be filled.
-    // These are provided by the system, and have guaranteed properties about
-    // their kind based on their type.
-    MOZ_ASSERT(!mType.IsEmpty());
-
-    mKind = KIND_STRING;
-    for (uint32_t i = 0; i < ArrayLength(kFileMimeNameMap); ++i) {
-      if (mType.EqualsASCII(kFileMimeNameMap[i].mMimeName)) {
-        mKind = KIND_FILE;
-        break;
-      }
-    }
-
-    mData = nullptr;
-    return;
-  }
-
-  mKind = KIND_OTHER;
-  mData = aData;
-
-  nsCOMPtr<nsISupports> supports;
-  nsresult rv = aData->GetAsISupports(getter_AddRefs(supports));
-  if (NS_SUCCEEDED(rv) && supports) {
-    RefPtr<File> file = FileFromISupports(supports);
-    if (file) {
-      mKind = KIND_FILE;
-      return;
-    }
-  }
-
-  nsAutoString string;
-  // If we can't get the data type as a string, that means that the object
-  // should be considered to be of the "other" type. This is impossible
-  // through the APIs defined by the spec, but we provide extra Moz* APIs,
-  // which allow setting of non-string data. We determine whether we can
-  // consider it a string, by calling GetAsAString, and checking for success.
-  rv = aData->GetAsAString(string);
-  if (NS_SUCCEEDED(rv)) {
-    mKind = KIND_STRING;
-  }
-}
-
-void
-DataTransferItem::FillInExternalData()
-{
-  if (mData) {
-    return;
-  }
-
-  NS_ConvertUTF16toUTF8 utf8format(mType);
-  const char* format = utf8format.get();
-  if (strcmp(format, "text/plain") == 0) {
-    format = kUnicodeMime;
-  } else if (strcmp(format, "text/uri-list") == 0) {
-    format = kURLDataMime;
-  }
-
-  nsCOMPtr<nsITransferable> trans =
-    do_CreateInstance("@mozilla.org/widget/transferable;1");
-  if (NS_WARN_IF(!trans)) {
-    return;
-  }
-
-  trans->Init(nullptr);
-  trans->AddDataFlavor(format);
-
-  if (mParent->GetEventMessage() == ePaste) {
-    MOZ_ASSERT(mIndex == 0, "index in clipboard must be 0");
-
-    nsCOMPtr<nsIClipboard> clipboard =
-      do_GetService("@mozilla.org/widget/clipboard;1");
-    if (!clipboard || mParent->ClipboardType() < 0) {
-      return;
-    }
-
-    nsresult rv = clipboard->GetData(trans, mParent->ClipboardType());
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return;
-    }
-  } else {
-    nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
-    if (!dragSession) {
-      return;
-    }
-
-    nsresult rv = dragSession->GetData(trans, mIndex);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return;
-    }
-  }
-
-  uint32_t length = 0;
-  nsCOMPtr<nsISupports> data;
-  nsresult rv = trans->GetTransferData(format, getter_AddRefs(data), &length);
-  if (NS_WARN_IF(NS_FAILED(rv) || !data)) {
-    return;
-  }
-
-  if (Kind() == KIND_FILE) {
-    // Because this is an external piece of data, mType is kFileMime. We want to
-    // convert whatever type happens to actually be stored into a dom::File.
-
-    RefPtr<File> file = FileFromISupports(data);
-    if (!file) {
-      if (nsCOMPtr<nsIFile> ifile = do_QueryInterface(data)) {
-        file = File::CreateFromFile(GetParentObject(), ifile);
-      } else if (nsCOMPtr<nsIInputStream> stream = do_QueryInterface(data)) {
-        // This consumes the stream object
-        ErrorResult rv;
-        file = CreateFileFromInputStream(GetParentObject(), stream, rv);
-        if (NS_WARN_IF(rv.Failed())) {
-          rv.SuppressException();
-        }
-      } else if (nsCOMPtr<BlobImpl> blobImpl = do_QueryInterface(data)) {
-        MOZ_ASSERT(blobImpl->IsFile());
-        file = File::Create(GetParentObject(), blobImpl);
-      }
-    }
-
-    MOZ_ASSERT(file, "Invalid format for Kind() == KIND_FILE");
-
-    data = do_QueryObject(file);
-  }
-
-  RefPtr<nsVariantCC> variant = new nsVariantCC();
-
-  nsCOMPtr<nsISupportsString> supportsstr = do_QueryInterface(data);
-  if (supportsstr) {
-    MOZ_ASSERT(Kind() == KIND_STRING);
-    nsAutoString str;
-    supportsstr->GetData(str);
-    variant->SetAsAString(str);
-  } else {
-    nsCOMPtr<nsISupportsCString> supportscstr = do_QueryInterface(data);
-    if (supportscstr) {
-      MOZ_ASSERT(Kind() == KIND_STRING);
-      nsAutoCString str;
-      supportscstr->GetData(str);
-      variant->SetAsACString(str);
-    } else {
-      MOZ_ASSERT(Kind() == KIND_FILE);
-      variant->SetAsISupports(data);
-    }
-  }
-
-  SetData(variant);
-}
-
-already_AddRefed<File>
-DataTransferItem::GetAsFile(ErrorResult& aRv)
-{
-  if (mKind != KIND_FILE) {
-    return nullptr;
-  }
-
-  nsIVariant* data = Data();
-  if (NS_WARN_IF(!data)) {
-    return nullptr;
-  }
-
-  nsCOMPtr<nsISupports> supports;
-  aRv = data->GetAsISupports(getter_AddRefs(supports));
-  MOZ_ASSERT(!aRv.Failed() && supports,
-             "Files should be stored with type dom::File!");
-  if (aRv.Failed() || !supports) {
-    return nullptr;
-  }
-
-  RefPtr<File> file = FileFromISupports(supports);
-  MOZ_ASSERT(file, "Files should be stored with type dom::File!");
-  if (!file) {
-    return nullptr;
-  }
-
-  // The File object should have been stored as a File in the nsIVariant. If it
-  // was stored as a Blob, with a file BlobImpl, we could still get to this
-  // point, except that file is a new File object, with a different identity
-  // then the original blob ibject. This should never happen so we assert
-  // against it.
-  MOZ_ASSERT(SameCOMIdentity(supports, NS_ISUPPORTS_CAST(nsIDOMBlob*, file)),
-             "Got back a new File object from FileFromISupports in GetAsFile!");
-
-  return file.forget();
-}
-
-already_AddRefed<File>
-DataTransferItem::CreateFileFromInputStream(nsISupports* aParent,
-                                            nsIInputStream* aStream,
-                                            ErrorResult& aRv)
-{
-  const char* key = nullptr;
-  for (uint32_t i = 0; i < ArrayLength(kFileMimeNameMap); ++i) {
-    if (mType.EqualsASCII(kFileMimeNameMap[i].mMimeName)) {
-      key = kFileMimeNameMap[i].mFileName;
-      break;
-    }
-  }
-  if (!key) {
-    MOZ_ASSERT_UNREACHABLE("Unsupported mime type");
-    key = "GenericFileName";
-  }
-
-  nsXPIDLString fileName;
-  aRv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
-                                           key, fileName);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  uint64_t available;
-  aRv = aStream->Available(&available);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  void* data = nullptr;
-  aRv = NS_ReadInputStreamToBuffer(aStream, &data, available);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  return File::CreateMemoryFile(aParent, data, available, fileName,
-                                mType, PR_Now());
-}
-
-void
-DataTransferItem::GetAsString(const RefPtr<FunctionStringCallback>& aCallback,
-                              ErrorResult& aRv)
-{
-  if (!aCallback || mKind != KIND_STRING) {
-    return;
-  }
-
-  nsIVariant* data = Data();
-  if (NS_WARN_IF(!data)) {
-    return;
-  }
-
-  nsAutoString stringData;
-  data->GetAsAString(stringData);
-
-  // Dispatch the callback to the main thread
-  class GASRunnable final : public Runnable
-  {
-  public:
-    GASRunnable(const RefPtr<FunctionStringCallback>& aCallback,
-                const nsAString& aStringData)
-      : mCallback(aCallback), mStringData(aStringData)
-    {}
-
-    NS_IMETHOD Run() override
-    {
-      ErrorResult rv;
-      mCallback->Call(mStringData, rv);
-      NS_WARN_IF(rv.Failed());
-      return rv.StealNSResult();
-    }
-  private:
-    RefPtr<FunctionStringCallback> mCallback;
-    nsString mStringData;
-  };
-
-  RefPtr<GASRunnable> runnable = new GASRunnable(aCallback, stringData);
-  nsresult rv = NS_DispatchToMainThread(runnable);
-  if (NS_FAILED(rv)) {
-    NS_WARNING("NS_DispatchToMainThread Failed in "
-               "DataTransferItem::GetAsString!");
-  }
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/events/DataTransferItem.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_DataTransferItem_h
-#define mozilla_dom_DataTransferItem_h
-
-#include "mozilla/ErrorResult.h"
-#include "mozilla/dom/DataTransfer.h"
-#include "mozilla/dom/DOMString.h"
-#include "mozilla/dom/File.h"
-
-namespace mozilla {
-namespace dom {
-
-class FunctionStringCallback;
-
-class DataTransferItem final : public nsISupports
-                             , public nsWrapperCache
-{
-public:
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DataTransferItem);
-
-public:
-  // The spec only talks about the "file" and "string" kinds. Due to the Moz*
-  // APIs, it is possible to attach any type to a DataTransferItem, meaning that
-  // we can have other kinds then just FILE and STRING. These others are simply
-  // marked as "other" and can only be produced throug the Moz* APIs.
-  enum eKind {
-    KIND_FILE,
-    KIND_STRING,
-    KIND_OTHER,
-  };
-
-  DataTransferItem(DataTransferItemList* aParent, const nsAString& aType)
-    : mIndex(0), mKind(KIND_OTHER), mType(aType), mParent(aParent)
-  {}
-
-  already_AddRefed<DataTransferItem> Clone(DataTransferItemList* aParent) const;
-
-  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-  void GetAsString(const RefPtr<FunctionStringCallback>& aCallback,
-                   ErrorResult& aRv);
-  void GetKind(nsAString& aKind) const
-  {
-    switch (mKind) {
-    case KIND_FILE:
-      aKind = NS_LITERAL_STRING("file");
-      return;
-    case KIND_STRING:
-      aKind = NS_LITERAL_STRING("string");
-      return;
-    default:
-      aKind = NS_LITERAL_STRING("other");
-      return;
-    }
-  }
-
-  void GetType(nsAString& aType) const
-  {
-    aType = mType;
-  }
-  void SetType(const nsAString& aType);
-
-  eKind Kind() const
-  {
-    return mKind;
-  }
-  void SetKind(eKind aKind)
-  {
-    mKind = aKind;
-  }
-
-  already_AddRefed<File> GetAsFile(ErrorResult& aRv);
-
-  DataTransferItemList* GetParentObject() const
-  {
-    return mParent;
-  }
-
-  nsIPrincipal* Principal() const
-  {
-    return mPrincipal;
-  }
-  void SetPrincipal(nsIPrincipal* aPrincipal)
-  {
-    mPrincipal = aPrincipal;
-  }
-
-  nsIVariant* Data()
-  {
-    if (!mData) {
-      FillInExternalData();
-    }
-    return mData;
-  }
-  void SetData(nsIVariant* aData);
-
-  uint32_t Index() const
-  {
-    return mIndex;
-  }
-  void SetIndex(uint32_t aIndex)
-  {
-    mIndex = aIndex;
-  }
-  void FillInExternalData();
-
-private:
-  ~DataTransferItem() {}
-  already_AddRefed<File> CreateFileFromInputStream(nsISupports* aParent,
-                                                   nsIInputStream* aStream,
-                                                   ErrorResult& aRv);
-
-  // The index in the 2d mIndexedItems array
-  uint32_t mIndex;
-
-  eKind mKind;
-  nsString mType;
-  nsCOMPtr<nsIVariant> mData;
-  nsCOMPtr<nsIPrincipal> mPrincipal;
-  RefPtr<DataTransferItemList> mParent;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif /* mozilla_dom_DataTransferItem_h */
deleted file mode 100644
--- a/dom/events/DataTransferItemList.cpp
+++ /dev/null
@@ -1,585 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "DataTransferItemList.h"
-
-#include "nsContentUtils.h"
-#include "nsIGlobalObject.h"
-#include "nsIClipboard.h"
-#include "nsIScriptObjectPrincipal.h"
-#include "nsIScriptGlobalObject.h"
-#include "nsIScriptContext.h"
-#include "nsISupportsPrimitives.h"
-#include "nsQueryObject.h"
-#include "nsVariant.h"
-#include "mozilla/ContentEvents.h"
-#include "mozilla/EventForwards.h"
-#include "mozilla/storage/Variant.h"
-#include "mozilla/dom/DataTransferItemListBinding.h"
-
-namespace mozilla {
-namespace dom {
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DataTransferItemList, mParent, mItems,
-                                      mIndexedItems, mFiles)
-NS_IMPL_CYCLE_COLLECTING_ADDREF(DataTransferItemList)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(DataTransferItemList)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DataTransferItemList)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-JSObject*
-DataTransferItemList::WrapObject(JSContext* aCx,
-                                 JS::Handle<JSObject*> aGivenProto)
-{
-  return DataTransferItemListBinding::Wrap(aCx, this, aGivenProto);
-}
-
-already_AddRefed<DataTransferItemList>
-DataTransferItemList::Clone(DataTransfer* aParent) const
-{
-  RefPtr<DataTransferItemList> list =
-    new DataTransferItemList(aParent, mIsExternal, mIsCrossDomainSubFrameDrop);
-
-  // We need to clone the mItems and mIndexedItems lists while keeping the same
-  // correspondences between the mIndexedItems and mItems lists (namely, if an
-  // item is in mIndexedItems, and mItems it must have the same new identity)
-
-  // First, we copy over indexedItems, and clone every entry. Then, we go over
-  // mItems. For every entry, we use its mIndex property to locate it in
-  // mIndexedItems on the original DataTransferItemList, and then copy over the
-  // reference from the same index pair on the new DataTransferItemList
-
-  list->mIndexedItems.SetLength(mIndexedItems.Length());
-  list->mItems.SetLength(mItems.Length());
-
-  // Copy over mIndexedItems, cloning every entry
-  for (uint32_t i = 0; i < mIndexedItems.Length(); i++) {
-    const nsTArray<RefPtr<DataTransferItem>>& items = mIndexedItems[i];
-    nsTArray<RefPtr<DataTransferItem>>& newItems = list->mIndexedItems[i];
-    newItems.SetLength(items.Length());
-    for (uint32_t j = 0; j < items.Length(); j++) {
-      newItems[j] = items[j]->Clone(list);
-    }
-  }
-
-  // Copy over mItems, getting the actual entries from mIndexedItems
-  for (uint32_t i = 0; i < mItems.Length(); i++) {
-    uint32_t index = mItems[i]->Index();
-    MOZ_ASSERT(index < mIndexedItems.Length());
-    uint32_t subIndex = mIndexedItems[index].IndexOf(mItems[i]);
-
-    // Copy over the reference
-    list->mItems[i] = list->mIndexedItems[index][subIndex];
-  }
-
-  return list.forget();
-}
-
-void
-DataTransferItemList::Remove(uint32_t aIndex, ErrorResult& aRv)
-{
-  if (IsReadOnly()) {
-    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
-    return;
-  }
-
-  if (aIndex >= Length()) {
-    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
-    return;
-  }
-
-  ClearDataHelper(mItems[aIndex], aIndex, -1, aRv);
-}
-
-DataTransferItem*
-DataTransferItemList::IndexedGetter(uint32_t aIndex, bool& aFound, ErrorResult& aRv) const
-{
-  if (aIndex >= mItems.Length()) {
-    aFound = false;
-    return nullptr;
-  }
-
-  RefPtr<DataTransferItem> item = mItems[aIndex];
-
-  // Check if the caller is allowed to access the drag data. Callers with
-  // chrome privileges can always read the data. During the
-  // drop event, allow retrieving the data except in the case where the
-  // source of the drag is in a child frame of the caller. In that case,
-  // we only allow access to data of the same principal. During other events,
-  // only allow access to the data with the same principal.
-  nsIPrincipal* principal = nullptr;
-  if (mIsCrossDomainSubFrameDrop) {
-    principal = nsContentUtils::SubjectPrincipal();
-  }
-
-  if (item->Principal() && principal &&
-      !principal->Subsumes(item->Principal())) {
-    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
-    aFound = false;
-    return nullptr;
-  }
-
-  nsCOMPtr<nsIVariant> variantData = item->Data();
-  nsCOMPtr<nsISupports> data;
-  if (variantData &&
-      NS_SUCCEEDED(variantData->GetAsISupports(getter_AddRefs(data))) &&
-      data) {
-    // Make sure the code that is calling us is same-origin with the data.
-    nsCOMPtr<EventTarget> pt = do_QueryInterface(data);
-    if (pt) {
-      nsresult rv = NS_OK;
-      nsIScriptContext* c = pt->GetContextForEventHandlers(&rv);
-      if (NS_WARN_IF(NS_FAILED(rv) || !c)) {
-        aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
-        return nullptr;
-      }
-
-      nsIGlobalObject* go = c->GetGlobalObject();
-      if (NS_WARN_IF(!go)) {
-        aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
-        return nullptr;
-      }
-
-      nsCOMPtr<nsIScriptObjectPrincipal> sp = do_QueryInterface(go);
-      MOZ_ASSERT(sp, "This cannot fail on the main thread.");
-
-      nsIPrincipal* dataPrincipal = sp->GetPrincipal();
-      if (!principal) {
-        principal = nsContentUtils::SubjectPrincipal();
-      }
-      if (NS_WARN_IF(!dataPrincipal || !principal->Equals(dataPrincipal))) {
-        aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
-        return nullptr;
-      }
-    }
-  }
-
-  aFound = true;
-  return item;
-}
-
-uint32_t
-DataTransferItemList::MozItemCount() const
-{
-  uint32_t length = mIndexedItems.Length();
-  // XXX: Compat hack - Index 0 always exists due to changes in internals, but
-  // if it is empty, scripts using the moz* APIs should see it as not existing.
-  if (length == 1 && mIndexedItems[0].IsEmpty()) {
-    return 0;
-  }
-  return length;
-}
-
-void
-DataTransferItemList::Clear(ErrorResult& aRv)
-{
-  if (NS_WARN_IF(IsReadOnly())) {
-    return;
-  }
-
-  uint32_t count = Length();
-  for (uint32_t i = 0; i < count; i++) {
-    // We always remove the last item first, to avoid moving items around in
-    // memory as much
-    Remove(Length() - 1, aRv);
-    ENSURE_SUCCESS_VOID(aRv);
-  }
-
-  MOZ_ASSERT(Length() == 0);
-}
-
-DataTransferItem*
-DataTransferItemList::Add(const nsAString& aData,
-                          const nsAString& aType,
-                          ErrorResult& aRv)
-{
-  if (NS_WARN_IF(IsReadOnly())) {
-    return nullptr;
-  }
-
-  nsCOMPtr<nsIVariant> data(new storage::TextVariant(aData));
-
-  nsAutoString format;
-  mParent->GetRealFormat(aType, format);
-
-  // We add the textual data to index 0. We set aInsertOnly to true, as we don't
-  // want to update an existing entry if it is already present, as per the spec.
-  RefPtr<DataTransferItem> item =
-    SetDataWithPrincipal(format, data, 0,
-                         nsContentUtils::SubjectPrincipal(),
-                         true, aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-  MOZ_ASSERT(item->Kind() != DataTransferItem::KIND_FILE);
-
-  return item;
-}
-
-DataTransferItem*
-DataTransferItemList::Add(File& aData, ErrorResult& aRv)
-{
-  if (IsReadOnly()) {
-    return nullptr;
-  }
-
-  nsCOMPtr<nsISupports> supports = do_QueryObject(&aData);
-  nsCOMPtr<nsIWritableVariant> data = new nsVariant();
-  data->SetAsISupports(supports);
-
-  nsAutoString type;
-  aData.GetType(type);
-
-
-  // We need to add this as a new item, as multiple files can't exist in the
-  // same item in the Moz DataTransfer layout. It will be appended at the end of
-  // the internal specced layout.
-  uint32_t index = mIndexedItems.Length();
-  RefPtr<DataTransferItem> item =
-    SetDataWithPrincipal(type, data, index,
-                         nsContentUtils::SubjectPrincipal(),
-                         true, aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-  MOZ_ASSERT(item->Kind() == DataTransferItem::KIND_FILE);
-
-  return item;
-}
-
-FileList*
-DataTransferItemList::Files()
-{
-  if (!mFiles) {
-    mFiles = new FileList(static_cast<nsIDOMDataTransfer*>(mParent));
-    RegenerateFiles();
-  }
-
-  return mFiles;
-}
-
-void
-DataTransferItemList::MozRemoveByTypeAt(const nsAString& aType,
-                                        uint32_t aIndex,
-                                        ErrorResult& aRv)
-{
-  if (NS_WARN_IF(IsReadOnly() ||
-                 aIndex >= mIndexedItems.Length())) {
-    return;
-  }
-
-  bool removeAll = aType.IsEmpty();
-
-  nsTArray<RefPtr<DataTransferItem>>& items = mIndexedItems[aIndex];
-  uint32_t count = items.Length();
-  // We remove the last item of the list repeatedly - that way we don't
-  // have to worry about modifying the loop iterator
-  if (removeAll) {
-    for (uint32_t i = 0; i < count; ++i) {
-      uint32_t index = items.Length() - 1;
-      MOZ_ASSERT(index == count - i - 1);
-
-      ClearDataHelper(items[index], -1, index, aRv);
-      if (NS_WARN_IF(aRv.Failed())) {
-        return;
-      }
-    }
-
-    // items is no longer a valid reference, as removing the last element from
-    // it via ClearDataHelper invalidated it. so we can't MOZ_ASSERT that the
-    // length is now 0.
-    return;
-  }
-
-  for (uint32_t i = 0; i < count; ++i) {
-    nsAutoString type;
-    items[i]->GetType(type);
-    if (type == aType) {
-      ClearDataHelper(items[i], -1, i, aRv);
-      return;
-    }
-  }
-}
-
-DataTransferItem*
-DataTransferItemList::MozItemByTypeAt(const nsAString& aType, uint32_t aIndex)
-{
-  if (NS_WARN_IF(aIndex >= mIndexedItems.Length())) {
-    return nullptr;
-  }
-
-  uint32_t count = mIndexedItems[aIndex].Length();
-  for (uint32_t i = 0; i < count; i++) {
-    RefPtr<DataTransferItem> item = mIndexedItems[aIndex][i];
-    nsString type;
-    item->GetType(type);
-    if (type.Equals(aType)) {
-      return item;
-    }
-  }
-
-  return nullptr;
-}
-
-already_AddRefed<DataTransferItem>
-DataTransferItemList::SetDataWithPrincipal(const nsAString& aType,
-                                           nsIVariant* aData,
-                                           uint32_t aIndex,
-                                           nsIPrincipal* aPrincipal,
-                                           bool aInsertOnly,
-                                           ErrorResult& aRv)
-{
-  if (aIndex < mIndexedItems.Length()) {
-    nsTArray<RefPtr<DataTransferItem>>& items = mIndexedItems[aIndex];
-    uint32_t count = items.Length();
-    for (uint32_t i = 0; i < count; i++) {
-      RefPtr<DataTransferItem> item = items[i];
-      nsString type;
-      item->GetType(type);
-      if (type.Equals(aType)) {
-        if (NS_WARN_IF(aInsertOnly)) {
-          aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
-          return nullptr;
-        }
-
-        // don't allow replacing data that has a stronger principal
-        bool subsumes;
-        if (NS_WARN_IF(item->Principal() && aPrincipal &&
-                       (NS_FAILED(aPrincipal->Subsumes(item->Principal(),
-                                                       &subsumes))
-                        || !subsumes))) {
-          aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
-          return nullptr;
-        }
-        item->SetPrincipal(aPrincipal);
-
-        DataTransferItem::eKind oldKind = item->Kind();
-        item->SetData(aData);
-
-        if (aIndex != 0) {
-          // If the item changes from being a file to not a file or vice-versa,
-          // its presence in the mItems array may need to change.
-          if (item->Kind() == DataTransferItem::KIND_FILE &&
-              oldKind != DataTransferItem::KIND_FILE) {
-            // not file => file
-            mItems.AppendElement(item);
-          } else if (item->Kind() != DataTransferItem::KIND_FILE &&
-                     oldKind == DataTransferItem::KIND_FILE) {
-            // file => not file
-            mItems.RemoveElement(item);
-          }
-        }
-
-        // Regenerate the Files array if we have modified a file's status
-        if (item->Kind() == DataTransferItem::KIND_FILE ||
-            oldKind == DataTransferItem::KIND_FILE) {
-          RegenerateFiles();
-        }
-
-        return item.forget();
-      }
-    }
-  } else {
-    // Make sure that we aren't adding past the end of the mIndexedItems array.
-    // XXX Should this be a MOZ_ASSERT instead?
-    aIndex = mIndexedItems.Length();
-  }
-
-  // Add the new item
-  RefPtr<DataTransferItem> item = AppendNewItem(aIndex, aType, aData, aPrincipal);
-
-  if (item->Kind() == DataTransferItem::KIND_FILE) {
-    RegenerateFiles();
-  }
-
-  return item.forget();
-}
-
-DataTransferItem*
-DataTransferItemList::AppendNewItem(uint32_t aIndex,
-                                    const nsAString& aType,
-                                    nsIVariant* aData,
-                                    nsIPrincipal* aPrincipal)
-{
-  if (mIndexedItems.Length() <= aIndex) {
-    MOZ_ASSERT(mIndexedItems.Length() == aIndex);
-    mIndexedItems.AppendElement();
-  }
-  RefPtr<DataTransferItem> item = new DataTransferItem(this, aType);
-  item->SetIndex(aIndex);
-  item->SetPrincipal(aPrincipal);
-  item->SetData(aData);
-
-  mIndexedItems[aIndex].AppendElement(item);
-
-  // We only want to add the item to the main mItems list if the index we are
-  // adding to is 0, or the item we are adding is a file. If we add an item
-  // which is not a file to a non-zero index, invariants could be broken.
-  // (namely the invariant that there are not 2 non-file entries in the items
-  // array with the same type)
-  if (item->Kind() == DataTransferItem::KIND_FILE || aIndex == 0) {
-    mItems.AppendElement(item);
-  }
-
-  return item;
-}
-
-const nsTArray<RefPtr<DataTransferItem>>*
-DataTransferItemList::MozItemsAt(uint32_t aIndex) // -- INDEXED
-{
-  if (aIndex >= mIndexedItems.Length()) {
-    return nullptr;
-  }
-
-  return &mIndexedItems[aIndex];
-}
-
-bool
-DataTransferItemList::IsReadOnly() const
-{
-  MOZ_ASSERT(mParent);
-  return mParent->IsReadOnly();
-}
-
-int32_t
-DataTransferItemList::ClipboardType() const
-{
-  MOZ_ASSERT(mParent);
-  return mParent->ClipboardType();
-}
-
-EventMessage
-DataTransferItemList::GetEventMessage() const
-{
-  MOZ_ASSERT(mParent);
-  return mParent->GetEventMessage();
-}
-
-void
-DataTransferItemList::PopIndexZero()
-{
-  MOZ_ASSERT(mIndexedItems.Length() > 1);
-  MOZ_ASSERT(mIndexedItems[0].IsEmpty());
-
-  mIndexedItems.RemoveElementAt(0);
-
-  // Update the index of every element which has now been shifted
-  for (uint32_t i = 0; i < mIndexedItems.Length(); i++) {
-    nsTArray<RefPtr<DataTransferItem>>& items = mIndexedItems[i];
-    for (uint32_t j = 0; j < items.Length(); j++) {
-      items[j]->SetIndex(i);
-    }
-  }
-}
-
-void
-DataTransferItemList::ClearAllItems()
-{
-  // We always need to have index 0, so don't delete that one
-  mItems.Clear();
-  mIndexedItems.Clear();
-  mIndexedItems.SetLength(1);
-
-  // Re-generate files (into an empty list)
-  RegenerateFiles();
-}
-
-void
-DataTransferItemList::ClearDataHelper(DataTransferItem* aItem,
-                                      uint32_t aIndexHint,
-                                      uint32_t aMozOffsetHint,
-                                      ErrorResult& aRv)
-{
-  MOZ_ASSERT(aItem);
-  if (NS_WARN_IF(IsReadOnly())) {
-    return;
-  }
-
-  nsIPrincipal* principal = nsContentUtils::SubjectPrincipal();
-  if (aItem->Principal() && principal &&
-      !principal->Subsumes(aItem->Principal())) {
-    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
-    return;
-  }
-
-  // Check if the aIndexHint is actually the index, and then remove the item
-  // from aItems
-  ErrorResult rv;
-  bool found;
-  if (IndexedGetter(aIndexHint, found, rv) == aItem) {
-    mItems.RemoveElementAt(aIndexHint);
-  } else {
-    mItems.RemoveElement(aItem);
-  }
-  rv.SuppressException();
-
-  // Check if the aMozIndexHint and aMozOffsetHint are actually the index and
-  // offset, and then remove them from mIndexedItems
-  MOZ_ASSERT(aItem->Index() < mIndexedItems.Length());
-  nsTArray<RefPtr<DataTransferItem>>& items = mIndexedItems[aItem->Index()];
-  if (aMozOffsetHint < items.Length() && aItem == items[aMozOffsetHint]) {
-    items.RemoveElementAt(aMozOffsetHint);
-  } else {
-    items.RemoveElement(aItem);
-  }
-
-  // Check if we should remove the index. We never remove index 0.
-  if (items.Length() == 0 && aItem->Index() != 0) {
-    mIndexedItems.RemoveElementAt(aItem->Index());
-
-    // Update the index of every element which has now been shifted
-    for (uint32_t i = aItem->Index(); i < mIndexedItems.Length(); i++) {
-      nsTArray<RefPtr<DataTransferItem>>& items = mIndexedItems[i];
-      for (uint32_t j = 0; j < items.Length(); j++) {
-        items[j]->SetIndex(i);
-      }
-    }
-  }
-
-  // Give the removed item the invalid index
-  aItem->SetIndex(-1);
-
-  if (aItem->Kind() == DataTransferItem::KIND_FILE) {
-    RegenerateFiles();
-  }
-}
-
-void
-DataTransferItemList::RegenerateFiles()
-{
-  // We don't want to regenerate the files list unless we already have a files
-  // list. That way we can avoid the unnecessary work if the user never touches
-  // the files list.
-  if (mFiles) {
-    // We clear the list rather than performing smaller updates, because it
-    // simplifies the logic greatly on this code path, which should be very
-    // infrequently used.
-    mFiles->Clear();
-
-    uint32_t count = Length();
-    for (uint32_t i = 0; i < count; i++) {
-      ErrorResult rv;
-      bool found;
-      RefPtr<DataTransferItem> item = IndexedGetter(i, found, rv);
-      if (NS_WARN_IF(!found || rv.Failed())) {
-        continue;
-      }
-
-      if (item->Kind() == DataTransferItem::KIND_FILE) {
-        RefPtr<File> file = item->GetAsFile(rv);
-        if (NS_WARN_IF(rv.Failed() || !file)) {
-          continue;
-        }
-        mFiles->Append(file);
-      }
-    }
-  }
-}
-
-} // namespace mozilla
-} // namespace dom
deleted file mode 100644
--- a/dom/events/DataTransferItemList.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_DataTransferItemList_h
-#define mozilla_dom_DataTransferItemList_h
-
-#include "mozilla/dom/DataTransfer.h"
-#include "mozilla/dom/DataTransferItem.h"
-#include "mozilla/dom/FileList.h"
-
-namespace mozilla {
-namespace dom {
-
-class DataTransferItem;
-
-class DataTransferItemList final : public nsISupports
-                                 , public nsWrapperCache
-{
-public:
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DataTransferItemList);
-
-  DataTransferItemList(DataTransfer* aParent, bool aIsExternal,
-                       bool aIsCrossDomainSubFrameDrop)
-    : mParent(aParent)
-    , mIsCrossDomainSubFrameDrop(aIsCrossDomainSubFrameDrop)
-    , mIsExternal(aIsExternal)
-  {
-    // We always allocate an index 0 in our DataTransferItemList. This is done
-    // in order to maintain the invariants according to the spec. Mainly, within
-    // the spec's list, there is intended to be a single copy of each mime type,
-    // for string typed items. File typed items are allowed to have duplicates.
-    // In the old moz* system, this was modeled by having multiple indexes, each
-    // of which was independent. Files were fetched from all indexes, but
-    // strings were only fetched from the first index. In order to maintain this
-    // correlation and avoid breaking code with the new changes, index 0 is now
-    // always present and used to store strings, and all file items are given
-    // their own index starting at index 1.
-    mIndexedItems.SetLength(1);
-  }
-
-  already_AddRefed<DataTransferItemList> Clone(DataTransfer* aParent) const;
-
-  virtual JSObject* WrapObject(JSContext* aCx,
-                               JS::Handle<JSObject*> aGivenProto) override;
-
-  uint32_t Length() const
-  {
-    return mItems.Length();
-  };
-
-  DataTransferItem* Add(const nsAString& aData, const nsAString& aType,
-                        ErrorResult& rv);
-  DataTransferItem* Add(File& aData, ErrorResult& aRv);
-
-  void Remove(uint32_t aIndex, ErrorResult& aRv);
-
-  DataTransferItem* IndexedGetter(uint32_t aIndex, bool& aFound,
-                                  ErrorResult& aRv) const;
-
-  void Clear(ErrorResult& aRv);
-
-  DataTransfer* GetParentObject() const
-  {
-    return mParent;
-  }
-
-  // Accessors for data from ParentObject
-  bool IsReadOnly() const;
-  int32_t ClipboardType() const;
-  EventMessage GetEventMessage() const;
-
-  already_AddRefed<DataTransferItem>
-  SetDataWithPrincipal(const nsAString& aType, nsIVariant* aData,
-                       uint32_t aIndex, nsIPrincipal* aPrincipal,
-                       bool aInsertOnly, ErrorResult& aRv);
-
-  FileList* Files();
-
-  // Moz-style helper methods for interacting with the stored data
-  void MozRemoveByTypeAt(const nsAString& aType, uint32_t aIndex,
-                         ErrorResult& aRv);
-  DataTransferItem* MozItemByTypeAt(const nsAString& aType, uint32_t aIndex);
-  const nsTArray<RefPtr<DataTransferItem>>* MozItemsAt(uint32_t aIndex);
-  uint32_t MozItemCount() const;
-
-  // Causes everything in indexes above 0 to shift down one index.
-  void PopIndexZero();
-
-  // Delete every item in the DataTransferItemList, without checking for
-  // permissions or read-only status (for internal use only).
-  void ClearAllItems();
-
-private:
-  void ClearDataHelper(DataTransferItem* aItem, uint32_t aIndexHint,
-                       uint32_t aMozOffsetHint, ErrorResult& aRv);
-  DataTransferItem* AppendNewItem(uint32_t aIndex, const nsAString& aType,
-                                  nsIVariant* aData, nsIPrincipal* aPrincipal);
-  void RegenerateFiles();
-
-  ~DataTransferItemList() {}
-
-  RefPtr<DataTransfer> mParent;
-  bool mIsCrossDomainSubFrameDrop;
-  bool mIsExternal;
-  RefPtr<FileList> mFiles;
-  nsTArray<RefPtr<DataTransferItem>> mItems;
-  nsTArray<nsTArray<RefPtr<DataTransferItem>>> mIndexedItems;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_DataTransferItemList_h
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -1807,17 +1807,17 @@ EventStateManager::GenerateDragGesture(n
       // Emit observer event to allow addons to modify the DataTransfer object.
       if (observerService) {
         observerService->NotifyObservers(dataTransfer,
                                          "on-datatransfer-available",
                                          nullptr);
       }
 
       // now that the dataTransfer has been updated in the dragstart and
-      // draggesture events, make it readonly so that the data doesn't
+      // draggesture events, make it read only so that the data doesn't
       // change during the drag.
       dataTransfer->SetReadOnly();
 
       if (status != nsEventStatus_eConsumeNoDefault) {
         bool dragStarted = DoDefaultDragStart(aPresContext, event, dataTransfer,
                                               targetContent, selection);
         if (dragStarted) {
           sActiveESM = nullptr;
--- a/dom/events/moz.build
+++ b/dom/events/moz.build
@@ -39,18 +39,16 @@ EXPORTS.mozilla.dom += [
     'BeforeAfterKeyboardEvent.h',
     'BeforeUnloadEvent.h',
     'ClipboardEvent.h',
     'CommandEvent.h',
     'CompositionEvent.h',
     'CustomEvent.h',
     'DataContainerEvent.h',
     'DataTransfer.h',
-    'DataTransferItem.h',
-    'DataTransferItemList.h',
     'DeviceMotionEvent.h',
     'DragEvent.h',
     'Event.h',
     'EventTarget.h',
     'FocusEvent.h',
     'ImageCaptureError.h',
     'InputEvent.h',
     'KeyboardEvent.h',
@@ -119,18 +117,16 @@ UNIFIED_SOURCES += [
     'UIEvent.cpp',
     'WheelEvent.cpp',
     'WheelHandlingHelper.cpp',
     'XULCommandEvent.cpp',
 ]
 
 # nsEventStateManager.cpp should be built separately because of Mac OS X headers.
 SOURCES += [
-    'DataTransferItem.cpp',
-    'DataTransferItemList.cpp',
     'EventStateManager.cpp',
 ]
 
 if CONFIG['MOZ_WEBSPEECH']:
     UNIFIED_SOURCES += ['SpeechRecognitionError.cpp']
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
--- a/dom/events/test/chrome.ini
+++ b/dom/events/test/chrome.ini
@@ -20,9 +20,8 @@ support-files =
 [test_bug602962.xul]
 [test_bug617528.xul]
 [test_bug679494.xul]
 [test_bug930374-chrome.html]
 [test_bug1128787-1.html]
 [test_bug1128787-2.html]
 [test_bug1128787-3.html]
 [test_eventctors.xul]
-[test_DataTransferItemList.html]
\ No newline at end of file
deleted file mode 100644
--- a/dom/events/test/test_DataTransferItemList.html
+++ /dev/null
@@ -1,227 +0,0 @@
-<html>
-<head>
-  <title>Tests for the DatTransferItemList object</title>
-  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
-  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
-  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
-</head>
-<body style="height: 300px; overflow: auto;">
-<p id="display"> </p>
-<img id="image" draggable="true" src="data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%18%00%00%00%18%02%03%00%00%00%9D%19%D5k%00%00%00%04gAMA%00%00%B1%8F%0B%FCa%05%00%00%00%0CPLTE%FF%FF%FF%FF%FF%FF%F7%DC%13%00%00%00%03%80%01X%00%00%00%01tRNS%08N%3DPT%00%00%00%01bKGD%00%88%05%1DH%00%00%00%09pHYs%00%00%0B%11%00%00%0B%11%01%7Fd_%91%00%00%00%07tIME%07%D2%05%0C%14%0C%0D%D8%3F%1FQ%00%00%00%5CIDATx%9C%7D%8E%CB%09%C0%20%10D%07r%B7%20%2F%E9wV0%15h%EA%D9%12D4%BB%C1x%CC%5C%1E%0C%CC%07%C0%9C0%9Dd7()%C0A%D3%8D%E0%B8%10%1DiCHM%D0%AC%D2d%C3M%F1%B4%E7%FF%10%0BY%AC%25%93%CD%CBF%B5%B2%C0%3Alh%CD%AE%13%DF%A5%F7%E0%03byW%09A%B4%F3%E2%00%00%00%00IEND%AEB%60%82">
-<div id="over" "style="width: 100px; height: 100px; border: 2px black dashed;">
-  drag over here
-</div>
-
-<script>
-  function spin() {
-    // Defer to the event loop twice to wait for any events to be flushed out.
-    return new Promise(function(a) {
-      SimpleTest.executeSoon(function() {
-        SimpleTest.executeSoon(a)
-      });
-    });
-  }
-
-  add_task(function* () {
-    yield spin();
-    var draggable = document.getElementById('image');
-    var over = document.getElementById('over');
-
-    var dragstartFired = 0;
-    draggable.addEventListener('dragstart', onDragStart);
-    function onDragStart(e) {
-      draggable.removeEventListener('dragstart', onDragStart);
-
-      var dt = e.dataTransfer;
-      dragstartFired++;
-
-      ok(true, "dragStart event fired");
-      var dtList = e.dataTransfer.items;
-      ok(dtList instanceof DataTransferItemList,
-         "DataTransfer.items returns a DataTransferItemList");
-
-      for (var i = 0; i < dtList.length; i++) {
-        var item = dtList[i];
-        ok(item instanceof DataTransferItem,
-           "operator[] returns DataTransferItem objects");
-        if (item.kind == "file") {
-          var file = item.getAsFile();
-          ok(file instanceof File, "getAsFile() returns File objects");
-        }
-      }
-
-      dtList.clear();
-      is(dtList.length, 0, "after .clear() DataTransferItemList should be empty");
-
-      dtList.add("this is some text", "text/plain");
-      dtList.add("<a href='www.mozilla.org'>this is a link</a>", "text/html");
-      dtList.add("http://www.mozilla.org", "text/uri-list");
-      dtList.add("this is custom-data", "custom-data");
-
-
-      var file = new File(['<a id="a"><b id="b">hey!</b></a>'], "myfile.html",
-                          {type: "text/html"});
-
-      dtList.add(file);
-
-      checkTypes(["text/plain", "text/html", "text/uri-list", "custom-data", "text/html"],
-                 dtList, "DataTransferItemList.add test");
-
-      var files = e.dataTransfer.files;
-      is(files.length, 1, "DataTransfer.files should contain the one file we added earlier");
-      is(files[0], file, "It should be the same file as the file we originally created");
-      is(file, e.dataTransfer.mozGetDataAt("text/html", 1),
-         "It should be stored in index 1 for mozGetDataAt");
-
-      var file2 = new File(['<a id="c"><b id="d">yo!</b></a>'], "myotherfile.html",
-                           {type: "text/html"});
-      dtList.add(file2);
-
-      is(files.length, 2, "The files property should have been updated in place");
-      is(files[1], file2, "It should be the same file as the file we originally created");
-      is(file2, e.dataTransfer.mozGetDataAt("text/html", 2),
-         "It should be stored in index 2 for mozGetDataAt");
-
-      var oldLength = dtList.length;
-      var randomString = "foo!";
-      e.dataTransfer.mozSetDataAt("random/string", randomString, 3);
-      is(oldLength, dtList.length,
-         "Adding a non-file entry to a non-zero index should not add an item to the items list");
-
-      var file3 = new File(['<a id="e"><b id="f">heya!</b></a>'], "yetanotherfile.html",
-                           {type: "text/html"});
-      e.dataTransfer.mozSetDataAt("random/string", file3, 3);
-      is(oldLength + 1, dtList.length,
-         "Replacing the entry with a file should add it to the list!");
-      is(dtList[oldLength].getAsFile(), file3, "It should be stored in the last index as a file");
-      is(dtList[oldLength].type, "random/string", "It should have the correct type");
-      is(dtList[oldLength].kind, "file", "It should have the correct kind");
-      is(files[files.length - 1], file3, "It should also be in the files list");
-
-      oldLength = dtList.length;
-      var nonstring = {};
-      e.dataTransfer.mozSetDataAt("jsobject", nonstring, 0);
-      is(oldLength + 1, dtList.length,
-         "Adding a non-string object using the mozAPIs to index 0 should add an item to the dataTransfer");
-      is(dtList[oldLength].type, "jsobject", "It should have the correct type");
-      is(dtList[oldLength].kind, "other", "It should have the correct kind");
-
-      // Clear the event's data and get it set up so we can read it later!
-      dtList.clear();
-
-      dtList.add(file);
-      dtList.add("this is some text", "text/plain");
-      is(e.dataTransfer.mozGetDataAt("text/html", 1), file);
-    }
-
-    var getAsStringCalled = 0;
-    var dragenterFired = 0;
-    over.addEventListener('dragenter', onDragEnter);
-    function onDragEnter(e) {
-      over.removeEventListener('dragenter', onDragEnter);
-
-      var dt = e.dataTransfer;
-      dragenterFired++;
-
-      readOnly(e);
-    }
-
-    var dropFired = 0;
-    over.addEventListener('drop', onDrop);
-    function onDrop(e) {
-      over.removeEventListener('drop', onDrop);
-
-      var dt = e.dataTransfer;
-      dropFired++;
-      e.preventDefault();
-
-      readOnly(e);
-    }
-
-
-    function readOnly(e) {
-      var dtList = e.dataTransfer.items;
-      var num = dtList.length;
-
-      // .clear() should have no effect
-      dtList.clear();
-      is(dtList.length, num,
-         ".clear() should have no effect on the object during a readOnly event");
-
-      // .remove(i) should throw InvalidStateError
-      for (var i = 0; i < dtList.length; i++) {
-        expectError(function() { dtList.remove(i); },
-                    "InvalidStateError", ".remove(" + i + ") during a readOnly event");
-      }
-
-      // .add() should return null and have no effect
-      var data = [["This is a plain string",  "text/plain"],
-                  ["This is <em>HTML!</em>",  "text/html"],
-                  ["http://www.mozilla.org/", "text/uri-list"],
-                  ["this is some custom data", "custom-data"]];
-
-      for (var i = 0; i < data.length; i++) {
-        is(dtList.add(data[i][0], data[i][1]), null,
-           ".add() should return null during a readOnly event");
-
-        is(dtList.length, num, ".add() should have no effect during a readOnly event");
-      }
-
-      // .add() with a file should return null and have no effect
-      var file = new File(['<a id="a"><b id="b">hey!</b></a>'], "myfile.html",
-                          {type: "text/html"});
-      is(dtList.add(file), null, ".add() with a file should return null during a readOnly event");
-      is(dtList.length, num, ".add() should have no effect during a readOnly event");
-
-      // We should be able to access the files
-      is(e.dataTransfer.files.length, 1, "Should be able to access files");
-      ok(e.dataTransfer.files[0], "File should be the same file!");
-      is(e.dataTransfer.items.length, 2, "Should be able to see there are 2 items");
-
-      is(e.dataTransfer.items[0].kind, "file", "First item should be a file");
-      is(e.dataTransfer.items[1].kind, "string", "Second item should be a string");
-
-      is(e.dataTransfer.items[0].type, "text/html", "first item should be text/html");
-      is(e.dataTransfer.items[1].type, "text/plain", "second item should be text/plain");
-
-      ok(e.dataTransfer.items[0].getAsFile(), "Should be able to get file");
-      e.dataTransfer.items[1].getAsString(function(s) {
-        getAsStringCalled++;
-        is(s, "this is some text", "Should provide the correct string");
-      });
-    }
-
-    synthesizeDrop(draggable, over, null, null);
-
-    // Wait for the getAsString callbacks to complete
-    yield spin();
-    is(getAsStringCalled, 2, "getAsString should be called twice");
-
-    // Sanity-check to make sure that the events were actually run
-    is(dragstartFired, 1, "dragstart fired");
-    is(dragenterFired, 1, "dragenter fired");
-    is(dropFired, 1, "drop fired");
-  });
-
-  function expectError(fn, eid, testid) {
-    var error = "";
-    try {
-      fn();
-    } catch (ex) {
-      error = ex.name;
-    }
-    is(error, eid, testid + " causes exception " + eid);
-  }
-
-  function checkTypes(aExpectedList, aDtList, aTestid) {
-    is(aDtList.length, aExpectedList.length, aTestid + " length test");
-    for (var i = 0; i < aExpectedList.length; i++) {
-      is(aDtList[i].type, aExpectedList[i], aTestid + " type " + i);
-    }
-  }
-</script>
-
-</body>
-</html>
--- a/dom/events/test/test_dragstart.html
+++ b/dom/events/test/test_dragstart.html
@@ -353,29 +353,24 @@ function test_DataTransfer(dt)
   checkOneDataItem(dt, ["text/plain", "text/html"],
                    ["First Item", "Changed with setData"], 0, "clearData type that does not exist item at index 0");
   checkOneDataItem(dt, ["text/unknown"],
                    ["Unknown type"], 1, "clearData type that does not exist item at index 1");
 
   expectError(() => dt.mozClearDataAt("text/plain", 3),
               "IndexSizeError", "clearData index too high with two items");
 
-  // ensure that clearData() removes all data associated with the first item, but doesn't
-  // shift the second item down into the first item's slot.
+  // ensure that clearData() removes all data associated with the first item
   dt.clearData();
-  is(dt.mozItemCount, 2, "clearData no argument with multiple items itemCount");
-  checkOneDataItem(dt, [], [], 0,
-                   "clearData no argument with multiple items item at index 0");
+  is(dt.mozItemCount, 1, "clearData no argument with multiple items itemCount");
   checkOneDataItem(dt, ["text/unknown"],
-                   ["Unknown type"], 1, "clearData no argument with multiple items item at index 1");
+                   ["Unknown type"], 0, "clearData no argument with multiple items item at index 1");
 
-  // remove tha remaining data in index 1. As index 0 is empty at this point, this will actually
-  // drop mozItemCount to 0. (XXX: This is because of spec-compliance reasons related
-  // to the more-recent dt.item API. It's an unfortunate, but hopefully rare edge case)
-  dt.mozClearDataAt("", 1);
+  // remove tha remaining data
+  dt.mozClearDataAt("", 0);
   is(dt.mozItemCount, 0, "all data cleared");
 
   // now check the effectAllowed and dropEffect properties
   is(dt.dropEffect, "none", "initial dropEffect");
   is(dt.effectAllowed, "uninitialized", "initial effectAllowed");
 
   ["copy", "none", "link", "", "other", "copyMove", "all", "uninitialized", "move"].forEach(
     function (i) {
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -227,15 +227,8 @@ RewriteYoutubeEmbedInvalidQuery=Rewritin
 # LOCALIZATION NOTE: Do not translate "ServiceWorker". %1$S is the ServiceWorker scope URL. %2$S is an error string.
 PushMessageDecryptionFailure=The ServiceWorker for scope ‘%1$S’ encountered an error decrypting a push message: ‘%2$S’. For help with encryption, please see https://developer.mozilla.org/en-US/docs/Web/API/Push_API/Using_the_Push_API#Encryption
 # LOCALIZATION NOTE: %1$S is the type of a DOM event. 'passive' is a literal parameter from the DOM spec.
 PreventDefaultFromPassiveListenerWarning=Ignoring ‘preventDefault()’ call on event of type ‘%1$S’ from a listener registered as ‘passive’.
 FileLastModifiedDateWarning=File.lastModifiedDate is deprecated. Use File.lastModified instead.
 ChromeScriptedDOMParserWithoutPrincipal=Creating DOMParser without a principal is deprecated.
 IIRFilterChannelCountChangeWarning=IIRFilterNode channel count changes may produce audio glitches.
 BiquadFilterChannelCountChangeWarning=BiquadFilterNode channel count changes may produce audio glitches.
-# LOCALIZATION NOTE: Do not translate ".jpeg"
-GenericImageNameJPEG=image.jpeg
-# LOCALIZATION NOTE: Do not translate ".gif"
-GenericImageNameGIF=image.gif
-# LOCALIZATION NOTE: Do not translate ".png"
-GenericImageNamePNG=image.png
-GenericFileName=file
--- a/dom/tests/mochitest/general/test_clipboard_events.html
+++ b/dom/tests/mochitest/general/test_clipboard_events.html
@@ -659,17 +659,17 @@ function checkCachedDataTransfer(cd, eve
   ok(oldtext != "Some Clipboard Text", "clipboard get using " + testprefix);
 
   var exh = false;
   try { cd.mozSetDataAt("text/plain", "Test Cache Data", 0); } catch (ex) { exh = true; }
   ok(eventtype == "paste" ? exh : !exh, "exception occured setting " + testprefix);
 
   var newtext = (eventtype == "paste") ? cd.getData("text/plain") :
                                          cd.mozGetDataAt("text/plain", 0);
-  is(newtext, (eventtype == "paste") ? oldtext : "Test Cache Data",
+  is(newtext, (eventtype == "paste") ? "" : "Test Cache Data",
      " clipboardData not changed using " + testprefix);
 
   is(getClipboardText(), "Some Clipboard Text", "clipboard not changed using " + testprefix);
 
   var exh = false;
   try { cd.mozClearDataAt("text/plain", 0); } catch (ex) { exh = true; }
   ok(eventtype == "paste" ? exh : !exh, "exception occured clearing " + testprefix);
 
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -381,20 +381,16 @@ var interfaceNamesInGlobalScope =
     "CustomEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DataChannel",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DataErrorEvent", b2g: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DataTransfer",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DataTransferItem",
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    "DataTransferItemList",
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "DelayNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DesktopNotification",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DesktopNotificationCenter",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DeviceLightEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/dom/webidl/DataTransfer.webidl
+++ b/dom/webidl/DataTransfer.webidl
@@ -7,22 +7,21 @@
  * http://www.whatwg.org/specs/web-apps/current-work/#the-datatransfer-interface
  */
 
 [ChromeConstructor(DOMString eventType, boolean isExternal)]
 interface DataTransfer {
            attribute DOMString dropEffect;
            attribute DOMString effectAllowed;
 
-  readonly attribute DataTransferItemList items;
+  //readonly attribute DataTransferItemList items;
 
   [Throws]
   void setDragImage(Element image, long x, long y);
 
-  [Throws]
   readonly attribute DOMStringList types;
   [Throws]
   DOMString getData(DOMString format);
   [Throws]
   void setData(DOMString format, DOMString data);
   [Throws]
   void clearData(optional DOMString format);
   [Throws]
deleted file mode 100644
--- a/dom/webidl/DataTransferItem.webidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * The origin of this IDL file is:
- * https://html.spec.whatwg.org/multipage/interaction.html#the-datatransferitem-interface
- */
-
-interface DataTransferItem {
-  readonly attribute DOMString kind;
-  readonly attribute DOMString type;
-  [Throws]
-  void getAsString(FunctionStringCallback? _callback);
-  [Throws]
-  File? getAsFile();
-};
-
-callback FunctionStringCallback = void (DOMString data);
deleted file mode 100644
--- a/dom/webidl/DataTransferItemList.webidl
+++ /dev/null
@@ -1,22 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * The origin of this IDL file is:
- * https://html.spec.whatwg.org/multipage/interaction.html#the-datatransferitemlist-interface
- */
-
-interface DataTransferItemList {
-  readonly attribute unsigned long length;
-  [Throws]
-  getter DataTransferItem (unsigned long index);
-  [Throws]
-  DataTransferItem? add(DOMString data, DOMString type);
-  [Throws]
-  DataTransferItem? add(File data);
-  [Throws]
-  void remove(unsigned long index);
-  [Throws]
-  void clear();
-};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -105,18 +105,16 @@ WEBIDL_FILES = [
     'CSSRuleList.webidl',
     'CSSStyleDeclaration.webidl',
     'CSSStyleSheet.webidl',
     'CSSTransition.webidl',
     'CSSValue.webidl',
     'CSSValueList.webidl',
     'DataContainerEvent.webidl',
     'DataTransfer.webidl',
-    'DataTransferItem.webidl',
-    'DataTransferItemList.webidl',
     'DecoderDoctorNotification.webidl',
     'DedicatedWorkerGlobalScope.webidl',
     'DelayNode.webidl',
     'DesktopNotification.webidl',
     'DeviceMotionEvent.webidl',
     'DeviceStorage.webidl',
     'DeviceStorageAreaListener.webidl',
     'Directory.webidl',
--- a/editor/libeditor/nsEditorEventListener.cpp
+++ b/editor/libeditor/nsEditorEventListener.cpp
@@ -934,21 +934,17 @@ nsEditorEventListener::CanDrop(nsIDOMDra
     return false;
   }
 
   nsCOMPtr<nsIDOMDataTransfer> domDataTransfer;
   aEvent->GetDataTransfer(getter_AddRefs(domDataTransfer));
   nsCOMPtr<DataTransfer> dataTransfer = do_QueryInterface(domDataTransfer);
   NS_ENSURE_TRUE(dataTransfer, false);
 
-  ErrorResult err;
-  RefPtr<DOMStringList> types = dataTransfer->GetTypes(err);
-  if (NS_WARN_IF(err.Failed())) {
-    return false;
-  }
+  RefPtr<DOMStringList> types = dataTransfer->Types();
 
   // Plaintext editors only support dropping text. Otherwise, HTML and files
   // can be dropped as well.
   if (!types->Contains(NS_LITERAL_STRING(kTextMime)) &&
       !types->Contains(NS_LITERAL_STRING(kMozTextInternal)) &&
       (mEditor->IsPlaintextEditor() ||
        (!types->Contains(NS_LITERAL_STRING(kHTMLMime)) &&
         !types->Contains(NS_LITERAL_STRING(kFileMime))))) {
--- a/layout/forms/nsFileControlFrame.cpp
+++ b/layout/forms/nsFileControlFrame.cpp
@@ -289,22 +289,17 @@ nsFileControlFrame::DnDListener::HandleE
 
 /* static */ bool
 nsFileControlFrame::DnDListener::IsValidDropData(nsIDOMDataTransfer* aDOMDataTransfer)
 {
   nsCOMPtr<DataTransfer> dataTransfer = do_QueryInterface(aDOMDataTransfer);
   NS_ENSURE_TRUE(dataTransfer, false);
 
   // We only support dropping files onto a file upload control
-  ErrorResult rv;
-  RefPtr<DOMStringList> types = dataTransfer->GetTypes(rv);
-  if (NS_WARN_IF(rv.Failed())) {
-    return false;
-  }
-
+  RefPtr<DOMStringList> types = dataTransfer->Types();
   return types->Contains(NS_LITERAL_STRING("Files"));
 }
 
 /* static */ bool
 nsFileControlFrame::DnDListener::CanDropTheseFiles(nsIDOMDataTransfer* aDOMDataTransfer,
                                                    bool aSupportsMultiple)
 {
   nsCOMPtr<DataTransfer> dataTransfer = do_QueryInterface(aDOMDataTransfer);
--- a/testing/web-platform/meta/html/dom/interfaces.html.ini
+++ b/testing/web-platform/meta/html/dom/interfaces.html.ini
@@ -1700,16 +1700,70 @@
     expected: FAIL
 
   [Path2D interface: operation addPathByStrokingText(DOMString,CanvasDrawingStyles,SVGMatrix,Path2D,unrestricted double)]
     expected: FAIL
 
   [DataTransfer interface object length]
     expected: FAIL
 
+  [DataTransfer interface: attribute items]
+    expected: FAIL
+
+  [DataTransferItemList interface: existence and properties of interface object]
+    expected: FAIL
+
+  [DataTransferItemList interface object length]
+    expected: FAIL
+
+  [DataTransferItemList interface: existence and properties of interface prototype object]
+    expected: FAIL
+
+  [DataTransferItemList interface: existence and properties of interface prototype object's "constructor" property]
+    expected: FAIL
+
+  [DataTransferItemList interface: attribute length]
+    expected: FAIL
+
+  [DataTransferItemList interface: operation add(DOMString,DOMString)]
+    expected: FAIL
+
+  [DataTransferItemList interface: operation add(File)]
+    expected: FAIL
+
+  [DataTransferItemList interface: operation remove(unsigned long)]
+    expected: FAIL
+
+  [DataTransferItemList interface: operation clear()]
+    expected: FAIL
+
+  [DataTransferItem interface: existence and properties of interface object]
+    expected: FAIL
+
+  [DataTransferItem interface object length]
+    expected: FAIL
+
+  [DataTransferItem interface: existence and properties of interface prototype object]
+    expected: FAIL
+
+  [DataTransferItem interface: existence and properties of interface prototype object's "constructor" property]
+    expected: FAIL
+
+  [DataTransferItem interface: attribute kind]
+    expected: FAIL
+
+  [DataTransferItem interface: attribute type]
+    expected: FAIL
+
+  [DataTransferItem interface: operation getAsString(FunctionStringCallback)]
+    expected: FAIL
+
+  [DataTransferItem interface: operation getAsFile()]
+    expected: FAIL
+
   [Window interface: operation showModalDialog(DOMString,any)]
     disabled:
       if e10s: https://bugzilla.mozilla.org/show_bug.cgi?id=981796
 
   [Window interface: attribute onautocomplete]
     expected: FAIL
 
   [Window interface: attribute onautocompleteerror]
@@ -2477,16 +2531,22 @@
     expected: FAIL
 
   [CanvasProxy interface object name]
     expected: FAIL
 
   [DrawingStyle interface object name]
     expected: FAIL
 
+  [DataTransferItemList interface object name]
+    expected: FAIL
+
+  [DataTransferItem interface object name]
+    expected: FAIL
+
   [ApplicationCache interface object name]
     expected: FAIL
 
   [PortCollection interface object name]
     expected: FAIL
 
   [WorkerGlobalScope interface object name]
     expected: FAIL
--- a/widget/gonk/nsClipboard.cpp
+++ b/widget/gonk/nsClipboard.cpp
@@ -267,28 +267,22 @@ nsClipboard::GetData(nsITransferable *aT
         RefPtr<gfx::DataSourceSurface> image = mClipboard->GetImage();
 
         // Encode according to MIME type.
         RefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(image, image->GetSize());
         nsCOMPtr<imgIContainer> imageContainer(image::ImageOps::CreateFromDrawable(drawable));
         nsCOMPtr<imgITools> imgTool = do_GetService(NS_IMGTOOLS_CID);
 
         nsCOMPtr<nsIInputStream> byteStream;
-        nsresult rv = imgTool->EncodeImage(imageContainer,
-                                           flavorStr,
-                                           EmptyString(),
-                                           getter_AddRefs(byteStream));
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          continue;
-        }
+        imgTool->EncodeImage(imageContainer, flavorStr, EmptyString(), getter_AddRefs(byteStream));
 
         // Set transferable.
-        rv = aTransferable->SetTransferData(flavorStr,
-                                            byteStream,
-                                            sizeof(nsIInputStream*));
+        nsresult rv = aTransferable->SetTransferData(flavorStr,
+                                                     byteStream,
+                                                     sizeof(nsIInputStream*));
         if (NS_WARN_IF(NS_FAILED(rv))) {
           continue;
         }
         break;
       }
     }
   }