Bug 1226362 - Use HTML Drag and Drop API in Messenger. r=mkmelin
authorKhushil Mistry <khushil324@gmail.com>
Sat, 25 Jan 2020 16:10:25 +0200
changeset 38010 7ed85c4ae6bf85b278c73cbced91bb829a0c93fa
parent 38009 3b281b9a0b409202fd555893700881cfc1e65ce4
child 38011 4e33fd9bc7b6cb8a04c50c1993b8e3f9184b0b9b
push id398
push userclokep@gmail.com
push dateMon, 09 Mar 2020 19:10:28 +0000
reviewersmkmelin
bugs1226362
Bug 1226362 - Use HTML Drag and Drop API in Messenger. r=mkmelin
mail/base/content/mailCore.js
mail/base/content/messageWindow.js
mail/base/content/messageWindow.xhtml
mail/base/content/messenger.xhtml
mail/base/content/msgAttachmentView.inc.xhtml
mail/base/content/msgHdrView.js
mail/components/compose/content/MsgComposeCommands.js
mail/components/compose/content/messengercompose.xhtml
--- a/mail/base/content/mailCore.js
+++ b/mail/base/content/mailCore.js
@@ -849,68 +849,77 @@ function SanitizeAttachmentDisplayName(a
   let displayName = aAttachment.name.trim().replace(/\s+/g, " ");
   if (AppConstants.platform == "win") {
     displayName = displayName.replace(/[ \.]+$/, "");
   }
   return displayName.replace(/(.)\1{9,}/g, "$1…$1");
 }
 
 /**
- * Create a TransferData object for a message attachment, either from the
- * message reader or the composer.
+ * Appends a dataTransferItem to the associated event for message attachments,
+ * either from the message reader or the composer.
  *
- * @param aAttachment the attachment object
- * @return the TransferData
+ * @param {Event} event - The associated event.
+ * @param {nsIMsgAttachment[]} attachments - The attachments to setup
  */
-function CreateAttachmentTransferData(aAttachment) {
+function setupDataTransfer(event, attachments) {
   // For now, disallow drag-and-drop on cloud attachments. In the future, we
   // should allow this.
-  if (
-    aAttachment.contentType == "text/x-moz-deleted" ||
-    aAttachment.sendViaCloud
-  ) {
-    return null;
-  }
+  let index = 0;
+  for (let attachment of attachments) {
+    if (
+      attachment.contentType == "text/x-moz-deleted" ||
+      attachment.sendViaCloud
+    ) {
+      return;
+    }
 
-  var name = aAttachment.name || aAttachment.displayName;
+    let name = attachment.name || attachment.displayName;
 
-  var data = new TransferData();
-  if (aAttachment.url && name) {
+    if (!attachment.url || !name) {
+      continue;
+    }
+
     // Only add type/filename info for non-file URLs that don't already
     // have it.
-    var info;
-    if (/(^file:|&filename=)/.test(aAttachment.url)) {
-      info = aAttachment.url;
+    let info;
+    if (/(^file:|&filename=)/.test(attachment.url)) {
+      info = attachment.url;
     } else {
       info =
-        aAttachment.url +
+        attachment.url +
         "&type=" +
-        aAttachment.contentType +
+        attachment.contentType +
         "&filename=" +
         encodeURIComponent(name);
     }
 
-    data.addDataForFlavour(
+    event.dataTransfer.mozSetDataAt(
       "text/x-moz-url",
-      info + "\n" + name + "\n" + aAttachment.size
+      info + "\n" + name + "\n" + attachment.size,
+      index
     );
-    data.addDataForFlavour("text/x-moz-url-data", aAttachment.url);
-    data.addDataForFlavour("text/x-moz-url-desc", name);
-    data.addDataForFlavour(
+    event.dataTransfer.mozSetDataAt(
+      "text/x-moz-url-data",
+      attachment.url,
+      index
+    );
+    event.dataTransfer.mozSetDataAt("text/x-moz-url-desc", name, index);
+    event.dataTransfer.mozSetDataAt(
       "application/x-moz-file-promise-url",
-      aAttachment.url
+      attachment.url,
+      index
     );
-    data.addDataForFlavour(
+    event.dataTransfer.mozSetDataAt(
       "application/x-moz-file-promise",
       new nsFlavorDataProvider(),
-      0,
-      Ci.nsISupports
+      index
     );
+    index++;
   }
-  return data;
 }
 
 function nsFlavorDataProvider() {}
 
 nsFlavorDataProvider.prototype = {
   QueryInterface: ChromeUtils.generateQI(["nsIFlavorDataProvider"]),
 
   getFlavorData(aTransferable, aFlavor, aData) {
--- a/mail/base/content/messageWindow.js
+++ b/mail/base/content/messageWindow.js
@@ -14,17 +14,16 @@
 /* import-globals-from mail-offline.js */
 /* import-globals-from mailCommands.js */
 /* import-globals-from mailCore.js */
 /* import-globals-from mailWindow.js */
 /* import-globals-from mailWindowOverlay.js */
 /* import-globals-from messageDisplay.js */
 /* import-globals-from msgHdrView.js */
 /* import-globals-from msgViewNavigation.js */
-/* import-globals-from nsDragAndDrop.js */
 /* import-globals-from phishingDetector.js */
 /* import-globals-from toolbarIconColor.js */
 /* globals PanelUI */
 
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 var { MailUtils } = ChromeUtils.import("resource:///modules/MailUtils.jsm");
 var { AppConstants } = ChromeUtils.import(
   "resource://gre/modules/AppConstants.jsm"
@@ -313,54 +312,55 @@ StandaloneMessageDisplayWidget.prototype
     ) {
       window.close();
       return true;
     }
     return false;
   },
 };
 
-var messagepaneObserver = {
-  canHandleMultipleItems: false,
-
-  onDrop(aEvent, aData, aDragSession) {
-    var sourceUri = aData.data;
+let messagepaneObserver = {
+  onDrop(event) {
+    let dragSession = Cc["@mozilla.org/widget/dragservice;1"]
+      .getService(Ci.nsIDragService)
+      .getCurrentSession();
+    if (!this.canDrop(event, dragSession)) {
+      return;
+    }
+    let sourceUri = event.dataTransfer.getData("text/x-moz-message");
     if (
       !gFolderDisplay.selectedMessage ||
       sourceUri != gFolderDisplay.selectedMessageUris[0]
     ) {
-      var msgHdr = messenger.msgHdrFromURI(sourceUri);
-      let originGlobal = aDragSession.sourceNode.ownerDocument.defaultValue;
+      let msgHdr = messenger.msgHdrFromURI(sourceUri);
+      let originGlobal = dragSession.sourceNode.ownerGlobal;
       gFolderDisplay.cloneView(originGlobal.gFolderDisplay.view);
       gFolderDisplay.selectMessage(msgHdr);
     }
+    event.stopPropagation();
   },
 
-  onDragOver(aEvent, aFlavour, aDragSession) {
-    var messagepanebox = document.getElementById("messagepanebox");
+  onDragOver(event) {
+    let messagepanebox = document.getElementById("messagepanebox");
     messagepanebox.setAttribute("dragover", "true");
+    event.stopPropagation();
+    event.preventDefault();
   },
 
-  onDragExit(aEvent, aDragSession) {
-    var messagepanebox = document.getElementById("messagepanebox");
+  onDragExit(event) {
+    let messagepanebox = document.getElementById("messagepanebox");
     messagepanebox.removeAttribute("dragover");
   },
 
-  canDrop(aEvent, aDragSession) {
+  canDrop(event, dragSession) {
     // allow drop from mail:3pane window only - 4xp
-    var doc = aDragSession.sourceNode.ownerDocument;
-    var elem = doc.getElementById("messengerWindow");
+    let doc = dragSession.sourceNode.ownerDocument;
+    let elem = doc.getElementById("messengerWindow");
     return elem && elem.getAttribute("windowtype") == "mail:3pane";
   },
-
-  getSupportedFlavours() {
-    var flavourSet = new FlavourSet();
-    flavourSet.appendFlavour("text/x-moz-message");
-    return flavourSet;
-  },
 };
 
 function UpdateStatusMessageCounts() {
   // hook for extra toolbar items
   Services.obs.notifyObservers(window, "mail:updateStandAloneMessageCounts");
 }
 
 // we won't show the window until the onload() handler is finished
--- a/mail/base/content/messageWindow.xhtml
+++ b/mail/base/content/messageWindow.xhtml
@@ -92,17 +92,16 @@
   <script src="chrome://messenger/content/mailWindow.js"/>
   <script src="chrome://messenger/content/messageWindow.js"/>
   <script src="chrome://messenger/content/accountUtils.js"/>
   <script src="chrome://global/content/contentAreaUtils.js"/>
   <script src="chrome://messenger/content/nsContextMenu.js"/>
   <script src="chrome://messenger/content/mailContextMenus.js"/>
   <script src="chrome://messenger/content/phishingDetector.js"/>
   <script src="chrome://communicator/content/contentAreaClick.js"/>
-  <script src="chrome://global/content/nsDragAndDrop.js"/>
   <script src="chrome://messenger/content/msgViewNavigation.js"/>
   <script src="chrome://messenger/content/editContactPanel.js"/>
   <script src="chrome://messenger/content/toolbarIconColor.js"/>
   <script src="chrome://messenger/content/msgHdrView.js"/>
   <script src="chrome://messenger-smime/content/msgHdrViewSMIMEOverlay.js"/>
   <script src="chrome://messenger-smime/content/msgReadSMIMEOverlay.js"/>
 #ifdef MOZ_OPENPGP
   <script src="chrome://openpgp/content/BondOpenPGP.jsm"/>
@@ -209,19 +208,19 @@
 #include mainMailToolbox.inc.xhtml
 
   <tooltip id="aHTMLTooltip" page="true"/>
 
   <!-- msg header view -->
   <!-- a convenience box for ease of extension overlaying -->
   <hbox id="messagepaneboxwrapper" flex="1">
     <vbox id="messagepanebox" flex="3"
-          ondragover="nsDragAndDrop.dragOver(event, messagepaneObserver);"
-          ondrop="nsDragAndDrop.drop(event, messagepaneObserver);"
-          ondragexit="nsDragAndDrop.dragExit(event, messagepaneObserver);">
+          ondragover="messagepaneObserver.onDragOver(event);"
+          ondrop="messagepaneObserver.onDrop(event);"
+          ondragexit="messagepaneObserver.onDragExit(event);">
 
       <hbox id="msgHeaderView" collapsed="true" class="main-header-area">
 #include msgHdrView.inc.xhtml
       </hbox>
       <!-- The msgNotificationBar appears on top of the message and displays
            information like: junk, mdn, remote content and phishing warnings -->
       <hbox id="mail-notification-top">
         <!-- notificationbox will be added here lazily. -->
--- a/mail/base/content/messenger.xhtml
+++ b/mail/base/content/messenger.xhtml
@@ -120,22 +120,20 @@
 <script src="chrome://messenger/content/mail3PaneWindowCommands.js"/>
 <script src="chrome://global/content/contentAreaUtils.js"/>
 <script src="chrome://messenger/content/nsContextMenu.js"/>
 <script src="chrome://messenger/content/mailContextMenus.js"/>
 <script src="chrome://messenger/content/accountUtils.js"/>
 <script src="chrome://messenger/content/folderPane.js"/>
 <script src="chrome://messenger/content/phishingDetector.js"/>
 <script src="chrome://communicator/content/contentAreaClick.js"/>
-<script src="chrome://global/content/nsDragAndDrop.js"/>
 <script src="chrome://messenger/content/editContactPanel.js"/>
 <script src="chrome://messenger/content/toolbarIconColor.js"/>
 <script src="chrome://messenger/content/jsTreeView.js"/>
 <script src="chrome://messenger/content/msgHdrView.js"/>
-<script src="chrome://global/content/nsDragAndDrop.js"/>
 <script src="chrome://messenger-smime/content/msgHdrViewSMIMEOverlay.js"/>
 <script src="chrome://messenger-smime/content/msgReadSMIMEOverlay.js"/>
 #ifdef MOZ_OPENPGP
 <script src="chrome://openpgp/content/BondOpenPGP.jsm"/>
 <script src="chrome://openpgp/content/ui/enigmailMessengerOverlay.js"/>
 <script src="chrome://openpgp/content/ui/enigmailMsgHdrViewOverlay.js"/>
 #endif
 <script src="chrome://messenger/content/chat/chat-messenger.js"/>
--- a/mail/base/content/msgAttachmentView.inc.xhtml
+++ b/mail/base/content/msgAttachmentView.inc.xhtml
@@ -14,17 +14,17 @@
                           <hbox align="center" id="attachmentInfo" flex="1">
                             <image id="attachmentIcon"/>
                             <label id="attachmentCount"/>
                             <label id="attachmentName" crop="center" flex="1"
                                    role="button"
                                    tooltiptext="&openAttachment.tooltip;"
                                    tooltiptextopen="&openAttachment.tooltip;"
                                    onclick="OpenAttachmentFromBar(event);"
-                                   ondragstart="nsDragAndDrop.startDrag(event, attachmentNameDNDObserver);"/>
+                                   ondragstart="attachmentNameDNDObserver.onDragStart(event);"/>
                             <label id="attachmentSize"/>
                           </hbox>
                           <!-- Use a very large flex value here so that attachmentCount doesn't take
                                up more space than necessary, but still crops itself if there's not
                                enough space. -->
                           <spacer flex="9999"/>
 
                           <vbox id="attachment-view-toolbox" class="inline-toolbox">
@@ -97,11 +97,10 @@
                         <hbox class="attachments-container">
                           <richlistbox is="attachment-list" id="attachmentList"
                                        class="attachmentList"
                                        orient="horizontal"
                                        seltype="multiple"
                                        context="attachmentListContext"
                                        itemcontext="attachmentItemContext"
                                        role="listbox"
-                                       ondragstart="nsDragAndDrop.startDrag(event, attachmentListDNDObserver);"
-                                       ondragover="nsDragAndDrop.dragOver(event, attachmentListDNDObserver);"/>
+                                       ondragstart="attachmentListDNDObserver.onDragStart(event);"/>
                         </hbox>
--- a/mail/base/content/msgHdrView.js
+++ b/mail/base/content/msgHdrView.js
@@ -6,17 +6,16 @@
  * Functions related to displaying the headers for a selected message in the
  * message pane.
  */
 
 /* import-globals-from editContactPanel.js */
 /* import-globals-from folderDisplay.js */
 /* import-globals-from mailWindow.js */
 /* import-globals-from messageDisplay.js */
-/* import-globals-from nsDragAndDrop.js */
 /* global Enigmail */
 
 var { XPCOMUtils } = ChromeUtils.import(
   "resource://gre/modules/XPCOMUtils.jsm"
 );
 var { MailConstants } = ChromeUtils.import(
   "resource:///modules/MailConstants.jsm"
 );
@@ -3379,39 +3378,35 @@ function ClearAttachmentList() {
   var list = document.getElementById("attachmentList");
   list.clearSelection();
 
   while (list.hasChildNodes()) {
     list.lastChild.remove();
   }
 }
 
-var attachmentListDNDObserver = {
-  onDragStart(aEvent, aAttachmentData, aDragAction) {
-    let target = aEvent.target;
-
+let attachmentListDNDObserver = {
+  onDragStart(event) {
+    let target = event.target;
     if (target.localName == "richlistitem") {
-      let selection = target.parentNode.selectedItems;
-      aAttachmentData.data = new TransferDataSet();
-      for (let item of selection) {
-        let transferData = CreateAttachmentTransferData(item.attachment);
-        if (transferData) {
-          aAttachmentData.data.push(transferData);
-        }
+      let attachments = [];
+      for (let item of target.parentNode.selectedItems) {
+        attachments.push(item.attachment);
       }
+      setupDataTransfer(event, attachments);
     }
+    event.stopPropagation();
   },
 };
 
-var attachmentNameDNDObserver = {
-  onDragStart(aEvent, aAttachmentData, aDragAction) {
-    var attachmentList = document.getElementById("attachmentList");
-    aAttachmentData.data = CreateAttachmentTransferData(
-      attachmentList.getItemAtIndex(0).attachment
-    );
+let attachmentNameDNDObserver = {
+  onDragStart(event) {
+    let attachmentList = document.getElementById("attachmentList");
+    setupDataTransfer(event, [attachmentList.getItemAtIndex(0).attachment]);
+    event.stopPropagation();
   },
 };
 
 /**
  * CopyWebsiteAddress takes the website address title button, extracts
  * the website address we stored in there and copies it to the clipboard
  */
 function CopyWebsiteAddress(websiteAddressNode) {
--- a/mail/components/compose/content/MsgComposeCommands.js
+++ b/mail/components/compose/content/MsgComposeCommands.js
@@ -6034,20 +6034,16 @@ function attachmentBucketOnKeyPress(aEve
     // We can get away with hardcoding the access key modifier key as aEvent.altKey
     // because it's ALT for Windows and Linux.
     if (aEvent.key == attachmentsAccessKey && aEvent.altKey) {
       goDoCommand("cmd_toggleAttachmentPane");
     }
   }
 }
 
-function attachmentBucketOnDragStart(aEvent) {
-  nsDragAndDrop.startDrag(aEvent, attachmentBucketDNDObserver);
-}
-
 function attachmentBucketOnClick(aEvent) {
   // Handle click on attachment pane whitespace:
   // - With selected attachments, clear selection first.
   // - Otherwise, e.g. on a plain empty bucket, show 'Attach File(s)' dialog.
   if (attachmentsSelectedCount() == 0) {
     let boundTarget = aEvent.originalTarget;
     if (
       aEvent.button == 0 &&
@@ -6526,72 +6522,75 @@ function fromKeyPress(event) {
 
 function subjectKeyPress(event) {
   gSubjectChanged = true;
   if (event.keyCode == KeyEvent.DOM_VK_RETURN) {
     SetMsgBodyFrameFocus();
   }
 }
 
+// content types supported in the envelopeDragObserver.
+let flavours = [
+  "text/x-moz-address",
+  "text/x-moz-message",
+  "application/x-moz-file",
+  "text/x-moz-url",
+];
 // we can drag and drop addresses, files, messages and urls into the compose envelope
 var envelopeDragObserver = {
-  canHandleMultipleItems: true,
-
   /**
    * Adjust the drop target when dragging from the attachment bucket onto itself
    * by picking the nearest possible insertion point (generally, between two
    * list items).
    *
-   * @param aEvent the drag-and-drop event being performed
-   * @return {attachmentitem|string} the adjusted drop target:
-   *                                 - an attachmentitem node for inserting
-   *                                   *before*
-   *                                 - "none" if this isn't a valid insertion point
-   *                                 - "afterLastItem" for appending at the
-   *                                   bottom of the list.
+   * @param {Event} event - The drag-and-drop event being performed.
+   * @return {attachmentitem|string} - the adjusted drop target:
+   *   - an attachmentitem node for inserting *before*
+   *   - "none" if this isn't a valid insertion point
+   *   - "afterLastItem" for appending at the bottom of the list.
    */
-  _adjustDropTarget(aEvent) {
-    let target = aEvent.target;
+  _adjustDropTarget(event) {
+    let target = event.target;
     let bucket = document.getElementById("attachmentBucket");
 
     if (target == bucket) {
       // Dragging or dropping at top/bottom border of the listbox
       if (
-        (aEvent.screenY - target.screenY) /
+        (event.screenY - target.screenY) /
           target.getBoundingClientRect().height <
         0.5
       ) {
         target = bucket.firstElementChild;
       } else {
         target = bucket.lastElementChild;
       }
       // We'll check below if this is a valid target.
     } else if (target.id == "attachmentBucketCount") {
       // Dragging or dropping at top border of the listbox.
       // Allow bottom half of attachment list header as extended drop target
       // for top of list, because otherwise it would be too small.
       if (
-        (aEvent.screenY - target.screenY) /
+        (event.screenY - target.screenY) /
           target.getBoundingClientRect().height >=
         0.5
       ) {
         target = bucket.firstElementChild;
         // We'll check below if this is a valid target.
       } else {
         // Top half of attachment list header: sorry, can't drop here.
         return "none";
       }
     }
 
     // Target is an attachmentitem.
     if (target.matches("richlistitem.attachmentItem")) {
       // If we're dragging/dropping in bottom half of attachmentitem,
       // adjust target to target.nextElementSibling (to show dropmarker above that).
       if (
-        (aEvent.screenY - target.screenY) /
+        (event.screenY - target.screenY) /
           target.getBoundingClientRect().height >=
         0.5
       ) {
         target = target.nextElementSibling;
 
         // If there's no target.nextElementSibling, we're dragging/dropping
         // to the bottom of the list.
         if (!target) {
@@ -6647,25 +6646,29 @@ var envelopeDragObserver = {
     let oldDropMarkerItem = document
       .getElementById("attachmentBucket")
       .querySelector("richlistitem.attachmentItem[dropOn]");
     if (oldDropMarkerItem) {
       oldDropMarkerItem.removeAttribute("dropOn");
     }
   },
 
-  onDrop(aEvent, aData, aDragSession) {
+  // eslint-disable-next-line complexity
+  onDrop(event) {
     let bucket = document.getElementById("attachmentBucket");
-    let dragSourceNode = aDragSession.sourceNode;
+    let dragSession = Cc["@mozilla.org/widget/dragservice;1"]
+      .getService(Ci.nsIDragService)
+      .getCurrentSession();
+    let dragSourceNode = dragSession.sourceNode;
     if (dragSourceNode && dragSourceNode.parentNode == bucket) {
       // We dragged from the attachment pane onto itself, so instead of
       // attaching a new object, we're just reordering them.
 
       // Adjust the drop target according to mouse position on list (items).
-      let target = this._adjustDropTarget(aEvent);
+      let target = this._adjustDropTarget(event);
 
       // Get a non-live, sorted list of selected attachment list items.
       let selItems = attachmentsSelectionGetSortedArray();
       // Keep track of the item we had focused originally. Deselect it though,
       // since listbox gets confused if you move its focused item around.
       let focus = bucket.currentItem;
       bucket.currentItem = null;
 
@@ -6727,185 +6730,182 @@ var envelopeDragObserver = {
         }
       }
 
       bucket.currentItem = focus;
       this._hideDropMarker();
       return;
     }
 
-    let dataList = aData.dataList;
     let attachments = [];
-
-    for (let dataListObj of dataList) {
-      let item = dataListObj.first;
-      let rawData = item.data;
+    let dt = event.dataTransfer;
+    let dataList = [];
+    for (let i = 0; i < dt.mozItemCount; i++) {
+      let types = Array.from(dt.mozTypesAt(i));
+      for (let flavour of flavours) {
+        if (types.includes(flavour)) {
+          let data = dt.mozGetDataAt(flavour, i);
+          if (data) {
+            dataList.push({ data, flavour });
+          }
+          break;
+        }
+      }
+    }
+
+    for (let { data, flavour } of dataList) {
       let isValidAttachment = false;
       let prettyName;
       let size;
 
       // We could be dropping an attachment of various flavours OR an address;
       // check and do the right thing.
-      // Note that case blocks {...} are recommended to avoid redeclaration errors
-      // when using 'let'.
-      switch (item.flavour.contentType) {
+      switch (flavour) {
         // Process attachments.
         case "application/x-moz-file": {
-          let fileHandler = Services.io
-            .getProtocolHandler("file")
-            .QueryInterface(Ci.nsIFileProtocolHandler);
-          if (!rawData.exists() || !rawData.isReadable()) {
-            // For some reason we couldn't read the file just dragged. Permission problem?
-            Cu.reportError(
-              "Couldn't access the dragged file " + rawData.leafName
-            );
-            break;
+          if (data instanceof Ci.nsIFile) {
+            size = data.fileSize;
           }
-
           try {
-            size = rawData.fileSize;
-            rawData = fileHandler.getURLSpecFromFile(rawData);
+            data = Services.io
+              .getProtocolHandler("file")
+              .QueryInterface(Ci.nsIFileProtocolHandler)
+              .getURLSpecFromFile(data);
             isValidAttachment = true;
           } catch (e) {
             Cu.reportError(
-              "Couldn't process the dragged file " + rawData.leafName + ":" + e
+              "Couldn't process the dragged file " + data.leafName + ":" + e
             );
           }
           break;
         }
 
         case "text/x-moz-message": {
           isValidAttachment = true;
           let msgHdr = gMessenger
-            .messageServiceFromURI(rawData)
-            .messageURIToMsgHdr(rawData);
+            .messageServiceFromURI(data)
+            .messageURIToMsgHdr(data);
           prettyName = msgHdr.mime2DecodedSubject + ".eml";
           size = msgHdr.messageSize;
           break;
         }
 
         case "text/x-moz-url": {
-          let pieces = rawData.split("\n");
-          rawData = pieces[0];
+          let pieces = data.split("\n");
+          data = pieces[0];
           if (pieces.length > 1) {
             prettyName = pieces[1];
           }
           if (pieces.length > 2) {
             size = parseInt(pieces[2]);
           }
 
           // If this is a URL (or selected text), check if it's a valid URL
           // by checking if we can extract a scheme using Services.io.
           // Don't attach invalid or mailto: URLs.
           try {
-            let scheme = Services.io.extractScheme(rawData);
+            let scheme = Services.io.extractScheme(data);
             if (scheme != "mailto") {
               isValidAttachment = true;
             }
           } catch (ex) {}
           break;
         }
 
         // Process address: Drop it into recipient field.
         case "text/x-moz-address": {
-          if (rawData) {
-            DropRecipient(aEvent.target, rawData);
-
-            // Since we are now using ondrop (eDrop) instead of previously using
-            // ondragdrop (eLegacyDragDrop), we must prevent the default
-            // which is dropping the address text into the widget.
-            // Note that stopPropagation() is called by our caller in
-            // nsDragAndDrop.js.
-            aEvent.preventDefault();
-          }
+          DropRecipient(event.target, data);
+
+          // Since we are now using ondrop (eDrop) instead of previously using
+          // ondragdrop (eLegacyDragDrop), we must prevent the default
+          // which is dropping the address text into the widget.
+          event.preventDefault();
           break;
         }
       }
 
       // Create the attachment and add it to attachments array.
       if (isValidAttachment) {
         let attachment = Cc[
           "@mozilla.org/messengercompose/attachment;1"
         ].createInstance(Ci.nsIMsgAttachment);
-        attachment.url = rawData;
+        attachment.url = data;
         attachment.name = prettyName;
 
         if (size !== undefined) {
           attachment.size = size;
         }
 
         attachments.push(attachment);
       }
     }
 
     // Add attachments if any.
     if (attachments.length > 0) {
       AddAttachments(attachments);
     }
 
     bucket.focus();
+    event.stopPropagation();
   },
 
-  onDragOver(aEvent, aFlavour, aDragSession) {
+  onDragOver(event) {
+    let dragSession = Cc["@mozilla.org/widget/dragservice;1"]
+      .getService(Ci.nsIDragService)
+      .getCurrentSession();
     let bucket = document.getElementById("attachmentBucket");
-    let dragSourceNode = aDragSession.sourceNode;
+    let dragSourceNode = dragSession.sourceNode;
     if (dragSourceNode && dragSourceNode.parentNode == bucket) {
       // If we're dragging from the attachment bucket onto itself, we need to
       // show a drop marker.
 
-      let target = this._adjustDropTarget(aEvent);
+      let target = this._adjustDropTarget(event);
 
       if (
         (target.matches && target.matches("richlistitem.attachmentItem")) ||
         target == "afterLastItem"
       ) {
         // Adjusted target is an attachment list item; show dropmarker.
         this._showDropMarker(target);
       } else {
         // target == "none", target is not a listItem, or no target:
         // Indicate that we can't drop here.
         this._hideDropMarker();
-        aEvent.dataTransfer.dropEffect = "none";
+        event.dataTransfer.dropEffect = "none";
       }
       return;
     }
 
-    if (aFlavour.contentType != "text/x-moz-address") {
-      // Make sure the attachment pane is visible during drag over.
-      toggleAttachmentPane("show");
-    } else {
-      DragAddressOverTargetControl(aEvent);
+    for (let flavour of flavours) {
+      if (dragSession.isDataFlavorSupported(flavour)) {
+        if (flavour != "text/x-moz-address") {
+          // Make sure the attachment pane is visible during drag over.
+          toggleAttachmentPane("show");
+        } else {
+          DragAddressOverTargetControl(event);
+        }
+        event.stopPropagation();
+        event.preventDefault();
+        break;
+      }
     }
   },
 
-  onDragExit(aEvent, aDragSession) {
+  onDragExit(event) {
     this._hideDropMarker();
   },
-
-  getSupportedFlavours() {
-    let flavourSet = new FlavourSet();
-    // Prefer "text/x-moz-address", so when an address from the address book
-    // is dragged, this flavour is tested first. Otherwise the attachment
-    // bucket would open since the addresses also carry the
-    // "application/x-moz-file" flavour.
-    flavourSet.appendFlavour("text/x-moz-address");
-    flavourSet.appendFlavour("text/x-moz-message");
-    flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
-    flavourSet.appendFlavour("text/x-moz-url");
-    return flavourSet;
-  },
 };
 
-var attachmentBucketDNDObserver = {
-  onDragStart(aEvent, aAttachmentData, aDragAction) {
-    var target = aEvent.target;
-
+let attachmentBucketDNDObserver = {
+  onDragStart(event) {
+    let target = event.target;
     if (target.matches("richlistitem.attachmentItem")) {
-      aAttachmentData.data = CreateAttachmentTransferData(target.attachment);
-    }
+      setupDataTransfer(event, [target.attachment]);
+    }
+    event.stopPropagation();
   },
 };
 
 function DisplaySaveFolderDlg(folderURI) {
   try {
     var showDialog = gCurrentIdentity.showSaveMsgDlg;
   } catch (e) {
     return;
--- a/mail/components/compose/content/messengercompose.xhtml
+++ b/mail/components/compose/content/messengercompose.xhtml
@@ -75,17 +75,16 @@
 <script src="chrome://messenger/content/messengercompose/MsgComposeCommands.js"/>
 <script src="chrome://messenger/content/messengercompose/bigFileObserver.js"/>
 <script src="chrome://messenger/content/messengercompose/cloudAttachmentLinkManager.js"/>
 <script src="chrome://messenger/content/messenger-customization.js"/>
 <script src="chrome://messenger/content/customizable-toolbar.js"/>
 
 <!-- drag and drop -->
 <script src="chrome://messenger/content/addressbook/abDragDrop.js"/>
-<script src="chrome://global/content/nsDragAndDrop.js"/>
 
 <!-- move needed functions into a single js file -->
 <script src="chrome://messenger/content/messengercompose/addressingWidgetOverlay.js"/>
 <script src="chrome://global/content/contentAreaUtils.js"/>
 <script src="chrome://messenger/content/viewZoomOverlay.js"/>
 #ifdef XP_MACOSX
 <script src="chrome://global/content/macWindowMenu.js"/>
 #endif
@@ -1801,19 +1800,19 @@
                oncommand="toggleAddressPicker();"/>
 
     <toolbarbutton is="toolbarbutton-menu-button" id="button-attach"
                    type="menu-button"
                    class="toolbarbutton-1"
                    label="&attachButton.label;"
                    tooltiptext="&attachButton.tooltip2;"
                    command="cmd_attachFile"
-                   ondragover="nsDragAndDrop.dragOver(event, envelopeDragObserver);"
-                   ondrop="nsDragAndDrop.drop(event, envelopeDragObserver);"
-                   ondragexit="nsDragAndDrop.dragExit(event, envelopeDragObserver);">
+                   ondragover="envelopeDragObserver.onDragOver(event);"
+                   ondrop="envelopeDragObserver.onDrop(event);"
+                   ondragexit="envelopeDragObserver.onDragExit(event);">
       <menupopup id="button-attachPopup" onpopupshowing="updateAttachmentItems();">
         <menuitem id="button-attachPopup_attachFileItem"
                   label="&attachFileCmd.label;"
                   accesskey="&attachFileCmd.accesskey;"
                   command="cmd_attachFile"/>
         <menu id="button-attachPopup_attachCloudMenu"
               label="&attachCloudCmd.label;"
               accesskey="&attachCloudCmd.accesskey;"
@@ -2005,19 +2004,19 @@
     <splitter id="sidebar-splitter" hidden="true"/>
 
     <vbox id="headers-parent" flex="1">
     <toolbox id="headers-box" class="toolbox-top" mode="icons">
     <toolbar is="customizable-toolbar" id="MsgHeadersToolbar"
              persist="collapsed"
              flex="1"
              customizable="true" nowindowdrag="true"
-             ondragover="nsDragAndDrop.dragOver(event, envelopeDragObserver);"
-             ondrop="nsDragAndDrop.drop(event, envelopeDragObserver);"
-             ondragexit="nsDragAndDrop.dragExit(event, envelopeDragObserver);">
+             ondragover="envelopeDragObserver.onDragOver(event);"
+             ondrop="envelopeDragObserver.onDrop(event);"
+             ondragexit="envelopeDragObserver.onDragExit(event);">
       <hbox id="msgheaderstoolbar-box" flex="1">
         <vbox flex="1" id="addresses-box">
           <hbox id="top-gradient-box" class="address-identity-recipient">
             <hbox class="aw-firstColBox"/>
             <hbox id="identityLabel-box" align="center"
                   pack="end" style="&headersSpace2.style;">
               <label id="identityLabel" value="&fromAddr2.label;"
                      accesskey="&fromAddr.accesskey;" control="msgIdentity"/>
@@ -2345,17 +2344,17 @@
                        flex="1"
                        height="0"
                        role="listbox"
                        context="msgComposeAttachmentListContext"
                        itemcontext="msgComposeAttachmentItemContext"
                        onclick="attachmentBucketOnClick(event);"
                        onkeypress="attachmentBucketOnKeyPress(event);"
                        onselect="attachmentBucketOnSelect();"
-                       ondragstart="attachmentBucketOnDragStart(event);"
+                       ondragstart="attachmentBucketDNDObserver.onDragStart(event);"
                        onblur="attachmentBucketOnBlur();"/>
         </vbox>
         <vbox id="attachments-placeholder-box"
               hidden="true"
               tooltiptext=""
               onclick="goDoCommand('cmd_toggleAttachmentPane')"/>
       </hbox>
     </toolbar>