Bug 1444686 part 3. Get rid of nsIDOMDataTransfer::Get/SetMozCursor. r=mystor
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 13 Mar 2018 16:23:59 -0400
changeset 461588 5ab74cd16594f58974e3db83e19f89492250b71f
parent 461587 9e93ff8b74816d97288b8f5f4db3464aea93cf8c
child 461589 dbe8af159b77839c87aac2330058e1234aa533cb
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmystor
bugs1444686
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1444686 part 3. Get rid of nsIDOMDataTransfer::Get/SetMozCursor. r=mystor MozReview-Commit-ID: G7vuh1uuWGv
dom/base/nsContentUtils.cpp
dom/events/DataTransfer.cpp
dom/events/DataTransfer.h
dom/events/EventStateManager.cpp
dom/interfaces/events/nsIDOMDataTransfer.idl
dom/ipc/ContentParent.cpp
dom/ipc/TabChild.cpp
dom/ipc/TabParent.cpp
widget/cocoa/nsChildView.mm
widget/nsBaseDragService.cpp
widget/nsBaseDragService.h
widget/nsIDragSession.idl
widget/windows/nsNativeDragSource.cpp
widget/windows/nsNativeDragSource.h
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -6029,25 +6029,19 @@ nsContentUtils::SetDataTransferInEvent(W
   // created before the event fires, so it should already be set. For other
   // drag events, get the object from the drag session.
   NS_ASSERTION(aDragEvent->mMessage != eDragStart,
                "draggesture event created without a dataTransfer");
 
   nsCOMPtr<nsIDragSession> dragSession = GetDragSession();
   NS_ENSURE_TRUE(dragSession, NS_OK); // no drag in progress
 
-  nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
-  nsCOMPtr<DataTransfer> initialDataTransfer;
-  dragSession->GetDataTransfer(getter_AddRefs(dataTransfer));
-  if (dataTransfer) {
-    initialDataTransfer = do_QueryInterface(dataTransfer);
-    if (!initialDataTransfer) {
-      return NS_ERROR_FAILURE;
-    }
-  } else {
+  RefPtr<DataTransfer> initialDataTransfer =
+    dragSession->GetDataTransfer();
+  if (!initialDataTransfer) {
     // A dataTransfer won't exist when a drag was started by some other
     // means, for instance calling the drag service directly, or a drag
     // from another application. In either case, a new dataTransfer should
     // be created that reflects the data.
     initialDataTransfer =
       new DataTransfer(aDragEvent->mTarget, aDragEvent->mMessage, true, -1);
 
     // now set it in the drag session so we don't need to create it again
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -478,32 +478,21 @@ DataTransfer::ClearData(const Optional<n
 
   if (aFormat.WasPassed()) {
     MozClearDataAtHelper(aFormat.Value(), 0, aSubjectPrincipal, aRv);
   } else {
     MozClearDataAtHelper(EmptyString(), 0, aSubjectPrincipal, aRv);
   }
 }
 
-NS_IMETHODIMP
-DataTransfer::GetMozCursor(nsAString& aCursorState)
-{
-  nsString cursor;
-  GetMozCursor(cursor);
-  aCursorState = cursor;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
+void
 DataTransfer::SetMozCursor(const nsAString& aCursorState)
 {
   // Lock the cursor to an arrow during the drag.
   mCursorState = aCursorState.EqualsLiteral("default");
-
-  return NS_OK;
 }
 
 already_AddRefed<nsINode>
 DataTransfer::GetMozSourceNode()
 {
   nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
   if (!dragSession) {
     return nullptr;
--- a/dom/events/DataTransfer.h
+++ b/dom/events/DataTransfer.h
@@ -200,24 +200,25 @@ public:
            nsIPrincipal& aSubjectPrincipal,
            ErrorResult& aRv);
 
 
   void AddElement(Element& aElement, mozilla::ErrorResult& aRv);
 
   uint32_t MozItemCount() const;
 
-  void GetMozCursor(nsString& aCursor)
+  void GetMozCursor(nsAString& aCursor)
   {
     if (mCursorState) {
       aCursor.AssignLiteral("default");
     } else {
       aCursor.AssignLiteral("auto");
     }
   }
+  void SetMozCursor(const nsAString& aCursor);
 
   already_AddRefed<DOMStringList> MozTypesAt(uint32_t aIndex,
                                              CallerType aCallerType,
                                              mozilla::ErrorResult& aRv) const;
 
   void MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
                       nsIPrincipal& aSubjectPrincipal,
                       mozilla::ErrorResult& aRv);
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -1332,18 +1332,17 @@ EventStateManager::DispatchCrossProcessE
     nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
     uint32_t dropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
     uint32_t action = nsIDragService::DRAGDROP_ACTION_NONE;
     nsCString principalURISpec;
     if (dragSession) {
       dragSession->DragEventDispatchedToChildProcess();
       dragSession->GetDragAction(&action);
       dragSession->GetTriggeringPrincipalURISpec(principalURISpec);
-      nsCOMPtr<nsIDOMDataTransfer> initialDataTransfer;
-      dragSession->GetDataTransfer(getter_AddRefs(initialDataTransfer));
+      RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer();
       if (initialDataTransfer) {
         initialDataTransfer->GetDropEffectInt(&dropEffect);
       }
     }
 
     tabParent->SendRealDragEvent(*aEvent->AsDragEvent(), action, dropEffect,
                                  principalURISpec);
     return;
@@ -3529,18 +3528,17 @@ EventStateManager::PostHandleEvent(nsPre
       if (mPresContext) {
         EnsureDocument(mPresContext);
       }
       bool isChromeDoc = nsContentUtils::IsChromeDoc(mDocument);
 
       // the initial dataTransfer is the one from the dragstart event that
       // was set on the dragSession when the drag began.
       nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
-      nsCOMPtr<nsIDOMDataTransfer> initialDataTransfer;
-      dragSession->GetDataTransfer(getter_AddRefs(initialDataTransfer));
+      RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer();
 
       WidgetDragEvent *dragEvent = aEvent->AsDragEvent();
 
       // collect any changes to moz cursor settings stored in the event's
       // data transfer.
       UpdateDragDataTransfer(dragEvent);
 
       // cancelling a dragenter or dragover event means that a drop should be
@@ -4776,18 +4774,17 @@ EventStateManager::UpdateDragDataTransfe
     return;
   }
 
   nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
 
   if (dragSession) {
     // the initial dataTransfer is the one from the dragstart event that
     // was set on the dragSession when the drag began.
-    nsCOMPtr<nsIDOMDataTransfer> initialDataTransfer;
-    dragSession->GetDataTransfer(getter_AddRefs(initialDataTransfer));
+    RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer();
     if (initialDataTransfer) {
       // retrieve the current moz cursor setting and save it.
       nsAutoString mozCursor;
       dragEvent->mDataTransfer->GetMozCursor(mozCursor);
       initialDataTransfer->SetMozCursor(mozCursor);
     }
   }
 }
--- a/dom/interfaces/events/nsIDOMDataTransfer.idl
+++ b/dom/interfaces/events/nsIDOMDataTransfer.idl
@@ -64,30 +64,16 @@ interface nsIDOMDataTransfer : nsISuppor
    * default target is the node that was dragged.
    *
    * @param element drag source to use
    * @throws NO_MODIFICATION_ALLOWED_ERR if the item cannot be modified
    */
   void addElement(in nsIDOMElement element);
 
   /**
-   * Sets the drag cursor state. Primarily used to control the cursor during
-   * tab drags, but could be expanded to other uses. XXX Currently implemented
-   * on Win32 only.
-   *
-   * Possible values:
-   *  auto - use default system behavior.
-   *  default - set the cursor to an arrow during the drag operation.
-   *
-   * Values other than 'default' are indentical to setting mozCursor to
-   * 'auto'.
-   */
-  attribute DOMString mozCursor;
-
-  /**
    * Will be true when the user has cancelled the drag (typically by pressing
    * Escape) and when the drag has been cancelled unexpectedly.  This will be
    * false otherwise, including when the drop has been rejected by its target.
    * This property is only relevant for the dragend event.
    */
   readonly attribute boolean mozUserCancelled;
 
   /**
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -4507,19 +4507,17 @@ ContentParent::MaybeInvokeDragSession(Ta
   nsCOMPtr<nsIDragService> dragService =
     do_GetService("@mozilla.org/widget/dragservice;1");
   if (dragService && dragService->MaybeAddChildProcess(this)) {
     // We need to send transferable data to child process.
     nsCOMPtr<nsIDragSession> session;
     dragService->GetCurrentSession(getter_AddRefs(session));
     if (session) {
       nsTArray<IPCDataTransfer> dataTransfers;
-      nsCOMPtr<nsIDOMDataTransfer> domTransfer;
-      session->GetDataTransfer(getter_AddRefs(domTransfer));
-      nsCOMPtr<DataTransfer> transfer = do_QueryInterface(domTransfer);
+      RefPtr<DataTransfer> transfer = session->GetDataTransfer();
       if (!transfer) {
         // Pass eDrop to get DataTransfer with external
         // drag formats cached.
         transfer = new DataTransfer(nullptr, eDrop, true, -1);
         session->SetDataTransfer(transfer);
       }
       // Note, even though this fills the DataTransfer object with
       // external data, the data is usually transfered over IPC lazily when
@@ -4543,18 +4541,17 @@ ContentParent::MaybeInvokeDragSession(Ta
 
 mozilla::ipc::IPCResult
 ContentParent::RecvUpdateDropEffect(const uint32_t& aDragAction,
                                     const uint32_t& aDropEffect)
 {
   nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
   if (dragSession) {
     dragSession->SetDragAction(aDragAction);
-    nsCOMPtr<nsIDOMDataTransfer> dt;
-    dragSession->GetDataTransfer(getter_AddRefs(dt));
+    RefPtr<DataTransfer> dt = dragSession->GetDataTransfer();
     if (dt) {
       dt->SetDropEffectInt(aDropEffect);
     }
     dragSession->UpdateDragEffect();
   }
   return IPC_OK();
 }
 
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -14,16 +14,17 @@
 #endif
 #include "Layers.h"
 #include "ContentChild.h"
 #include "TabParent.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/BrowserElementParent.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/EventListenerManager.h"
+#include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/indexedDB/PIndexedDBPermissionRequestChild.h"
 #include "mozilla/dom/PaymentRequestChild.h"
 #include "mozilla/dom/TelemetryScrollProbe.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "mozilla/layers/APZChild.h"
 #include "mozilla/layers/APZCCallbackHelper.h"
 #include "mozilla/layers/APZCTreeManagerChild.h"
@@ -1950,18 +1951,17 @@ TabChild::RecvRealDragEvent(const Widget
 {
   WidgetDragEvent localEvent(aEvent);
   localEvent.mWidget = mPuppetWidget;
 
   nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
   if (dragSession) {
     dragSession->SetDragAction(aDragAction);
     dragSession->SetTriggeringPrincipalURISpec(aPrincipalURISpec);
-    nsCOMPtr<nsIDOMDataTransfer> initialDataTransfer;
-    dragSession->GetDataTransfer(getter_AddRefs(initialDataTransfer));
+    RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer();
     if (initialDataTransfer) {
       initialDataTransfer->SetDropEffectInt(aDropEffect);
     }
   }
 
   if (aEvent.mMessage == eDrop) {
     bool canDrop = true;
     if (!dragSession || NS_FAILED(dragSession->GetCanDrop(&canDrop)) ||
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1174,18 +1174,17 @@ TabParent::QueryDropLinksForVerification
   // Before sending the dragEvent, we query the links being dragged and
   // store them on the parent, to make sure the child can not modify links.
   nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
   if (!dragSession) {
     NS_WARNING("No dragSession to query links for verification");
     return false;
   }
 
-  nsCOMPtr<nsIDOMDataTransfer> initialDataTransfer;
-  dragSession->GetDataTransfer(getter_AddRefs(initialDataTransfer));
+  RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer();
   if (!initialDataTransfer) {
     NS_WARNING("No initialDataTransfer to query links for verification");
     return false;
   }
 
   nsCOMPtr<nsIDroppedLinkHandler> dropHandler =
     do_GetService("@mozilla.org/content/dropped-link-handler;1");
   if (!dropHandler) {
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -12,16 +12,17 @@
 
 #include "nsChildView.h"
 #include "nsCocoaWindow.h"
 
 #include "mozilla/MiscEvents.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TouchEvents.h"
+#include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/SimpleGestureEventBinding.h"
 
 #include "nsArrayUtils.h"
 #include "nsExceptionHandler.h"
 #include "nsObjCExceptions.h"
 #include "nsCOMPtr.h"
 #include "nsThreadUtils.h"
 #include "nsToolkit.h"
@@ -6255,20 +6256,20 @@ GetIntegerDeltaForEvent(NSEvent* aEvent)
     // As things stand though, |aOperation| isn't well handled within "our"
     // events, that is, when the drop happens within the window: it is set
     // either to NSDragOperationGeneric or to NSDragOperationNone.
     // For that reason, it's not yet possible to override dropEffect per the
     // given OS value, and it's also unclear what's the correct dropEffect
     // value for NSDragOperationGeneric that is passed by other applications.
     // All that said, NSDragOperationNone is still reliable.
     if (aOperation == NSDragOperationNone) {
-      nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
-      dragService->GetDataTransfer(getter_AddRefs(dataTransfer));
-      if (dataTransfer)
+      RefPtr<dom::DataTransfer> dataTransfer = dragService->GetDataTransfer();
+      if (dataTransfer) {
         dataTransfer->SetDropEffectInt(nsIDragService::DRAGDROP_ACTION_NONE);
+      }
     }
 
     mDragService->EndDragSession(
       true, nsCocoaUtils::ModifiersForEvent(currentEvent));
     NS_RELEASE(mDragService);
   }
 
   [globalDragPboard release];
--- a/widget/nsBaseDragService.cpp
+++ b/widget/nsBaseDragService.cpp
@@ -18,28 +18,28 @@
 #include "nsIContent.h"
 #include "nsIPresShell.h"
 #include "nsViewManager.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMDragEvent.h"
 #include "nsISelection.h"
 #include "nsISelectionPrivate.h"
 #include "nsPresContext.h"
-#include "nsIDOMDataTransfer.h"
 #include "nsIImageLoadingContent.h"
 #include "imgIContainer.h"
 #include "imgIRequest.h"
 #include "ImageRegion.h"
 #include "nsRegion.h"
 #include "nsXULPopupManager.h"
 #include "nsMenuPopupFrame.h"
 #include "SVGImageContext.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/DataTransferItemList.h"
+#include "mozilla/dom/DataTransfer.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/Unused.h"
 #include "nsFrameLoader.h"
 #include "TabParent.h"
 
 #include "gfxContext.h"
 #include "gfxPlatform.h"
 #include <algorithm>
@@ -196,28 +196,41 @@ nsBaseDragService::GetData(nsITransferab
 NS_IMETHODIMP
 nsBaseDragService::IsDataFlavorSupported(const char *aDataFlavor,
                                          bool *_retval)
 {
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-nsBaseDragService::GetDataTransfer(nsIDOMDataTransfer** aDataTransfer)
+nsBaseDragService::GetDataTransferXPCOM(nsIDOMDataTransfer** aDataTransfer)
 {
   *aDataTransfer = mDataTransfer;
   NS_IF_ADDREF(*aDataTransfer);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsBaseDragService::SetDataTransfer(nsIDOMDataTransfer* aDataTransfer)
+nsBaseDragService::SetDataTransferXPCOM(nsIDOMDataTransfer* aDataTransfer)
+{
+  // Cast is safe because nsIDOMDataTransfer is builtinclass.
+  mDataTransfer = static_cast<DataTransfer*>(aDataTransfer);
+  return NS_OK;
+}
+
+DataTransfer*
+nsBaseDragService::GetDataTransfer()
+{
+  return mDataTransfer;
+}
+
+void
+nsBaseDragService::SetDataTransfer(DataTransfer* aDataTransfer)
 {
   mDataTransfer = aDataTransfer;
-  return NS_OK;
 }
 
 //-------------------------------------------------------------------------
 NS_IMETHODIMP
 nsBaseDragService::InvokeDragSession(nsIDOMNode *aDOMNode,
                                      const nsACString& aPrincipalURISpec,
                                      nsIArray* aTransferableArray,
                                      nsIScriptableRegion* aDragRgn,
@@ -266,17 +279,18 @@ nsBaseDragService::InvokeDragSessionWith
                                               int32_t aImageX, int32_t aImageY,
                                               nsIDOMDragEvent* aDragEvent,
                                               nsIDOMDataTransfer* aDataTransfer)
 {
   NS_ENSURE_TRUE(aDragEvent, NS_ERROR_NULL_POINTER);
   NS_ENSURE_TRUE(aDataTransfer, NS_ERROR_NULL_POINTER);
   NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
 
-  mDataTransfer = aDataTransfer;
+  // Cast is safe because nsIDOMDataTransfer is builtinclass.
+  mDataTransfer = static_cast<DataTransfer*>(aDataTransfer);
   mSelection = nullptr;
   mHasImage = true;
   mDragPopup = nullptr;
   mImage = aImage;
   mImageOffset = CSSIntPoint(aImageX, aImageY);
 
   aDragEvent->GetScreenX(&mScreenPosition.x);
   aDragEvent->GetScreenY(&mScreenPosition.y);
@@ -303,17 +317,18 @@ nsBaseDragService::InvokeDragSessionWith
                                                   uint32_t aActionType,
                                                   nsIDOMDragEvent* aDragEvent,
                                                   nsIDOMDataTransfer* aDataTransfer)
 {
   NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
   NS_ENSURE_TRUE(aDragEvent, NS_ERROR_NULL_POINTER);
   NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
 
-  mDataTransfer = aDataTransfer;
+  // Cast is safe because nsIDOMDataTransfer is builtinclass.
+  mDataTransfer = static_cast<DataTransfer*>(aDataTransfer);
   mSelection = aSelection;
   mHasImage = true;
   mDragPopup = nullptr;
   mImage = nullptr;
   mImageOffset = CSSIntPoint();
 
   aDragEvent->GetScreenX(&mScreenPosition.x);
   aDragEvent->GetScreenY(&mScreenPosition.y);
--- a/widget/nsBaseDragService.h
+++ b/widget/nsBaseDragService.h
@@ -5,17 +5,16 @@
 
 #ifndef nsBaseDragService_h__
 #define nsBaseDragService_h__
 
 #include "nsIDragService.h"
 #include "nsIDragSession.h"
 #include "nsITransferable.h"
 #include "nsIDOMDocument.h"
-#include "nsIDOMDataTransfer.h"
 #include "nsCOMPtr.h"
 #include "nsRect.h"
 #include "nsPoint.h"
 #include "nsString.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
 #include "nsTArray.h"
@@ -28,16 +27,20 @@ class nsIContent;
 class nsIDOMNode;
 class nsPresContext;
 class nsIImageLoadingContent;
 
 namespace mozilla {
 namespace gfx {
 class SourceSurface;
 } // namespace gfx
+
+namespace dom {
+class DataTransfer;
+} // namespace dom
 } // namespace mozilla
 
 /**
  * XP DragService wrapper base class
  */
 
 class nsBaseDragService : public nsIDragService,
                           public nsIDragSession
@@ -160,17 +163,17 @@ protected:
 
   nsSize mTargetSize;
   nsCOMPtr<nsIDOMNode> mSourceNode;
   nsCString mTriggeringPrincipalURISpec;
   nsCOMPtr<nsIDOMDocument> mSourceDocument;       // the document at the drag source. will be null
                                                   //  if it came from outside the app.
   nsContentPolicyType mContentPolicyType;         // the contentpolicy type passed to the channel
                                                   // when initiating the drag session
-  nsCOMPtr<nsIDOMDataTransfer> mDataTransfer;
+  RefPtr<mozilla::dom::DataTransfer> mDataTransfer;
 
   // used to determine the image to appear on the cursor while dragging
   nsCOMPtr<nsIDOMNode> mImage;
   // offset of cursor within the image
   mozilla::CSSIntPoint mImageOffset;
 
   // set if a selection is being dragged
   nsCOMPtr<nsISelection> mSelection;
--- a/widget/nsIDragSession.idl
+++ b/widget/nsIDragSession.idl
@@ -5,26 +5,32 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 #include "nsITransferable.idl"
 
 
 %{ C++
 #include "nsSize.h"
+
+namespace mozilla {
+namespace dom {
+class DataTransfer;
+} // namespace dom
+} // namespace mozilla
 %}
 
 native nsSize (nsSize);
-
+[ptr] native DataTransferPtr(mozilla::dom::DataTransfer);
 
 interface nsIDOMDocument;
 interface nsIDOMNode;
 interface nsIDOMDataTransfer;
 
-[scriptable, uuid(25bce737-73f0-43c7-bc20-c71044a73c5a)]
+[scriptable, builtinclass, uuid(25bce737-73f0-43c7-bc20-c71044a73c5a)]
 interface nsIDragSession : nsISupports
 {
   /**
     * Set the current state of the drag, whether it can be dropped or not.
     * usually the target "frame" sets this so the native system can render the correct feedback
     */
   attribute boolean canDrop;
 
@@ -67,17 +73,20 @@ interface nsIDragSession : nsISupports
    * sourceNode's principal when sourceNode is xul:browser and the drag is
    * triggered in a browsing context inside it.
    */
   attribute AUTF8String triggeringPrincipalURISpec;
 
   /**
    * The data transfer object for the current drag.
    */
+  [binaryname(DataTransferXPCOM)]
   attribute nsIDOMDataTransfer dataTransfer;
+  [notxpcom, nostdcall] DataTransferPtr getDataTransfer();
+  [notxpcom, nostdcall] void setDataTransfer(in DataTransferPtr aDataTransfer);
 
   /**
     * Get data from a Drag&Drop. Can be called while the drag is in process
     * or after the drop has completed.  
     *
     * @param  aTransferable the transferable for the data to be put into
     * @param  aItemIndex which of multiple drag items, zero-based
     */
--- a/widget/windows/nsNativeDragSource.cpp
+++ b/widget/windows/nsNativeDragSource.cpp
@@ -10,22 +10,22 @@
 #include "nsIServiceManager.h"
 #include "nsToolkit.h"
 #include "nsWidgetsCID.h"
 #include "nsIDragService.h"
 
 /*
  * class nsNativeDragSource
  */
-nsNativeDragSource::nsNativeDragSource(nsIDOMDataTransfer* aDataTransfer) :
+nsNativeDragSource::nsNativeDragSource(mozilla::dom::DataTransfer* aDataTransfer) :
   m_cRef(0),
   m_hCursor(nullptr),
   mUserCancelled(false)
 {
-  mDataTransfer = do_QueryInterface(aDataTransfer);
+  mDataTransfer = aDataTransfer;
 }
 
 nsNativeDragSource::~nsNativeDragSource()
 {
 }
 
 STDMETHODIMP
 nsNativeDragSource::QueryInterface(REFIID riid, void** ppv)
--- a/widget/windows/nsNativeDragSource.h
+++ b/widget/windows/nsNativeDragSource.h
@@ -2,34 +2,40 @@
 /* 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 _nsNativeDragSource_h_
 #define _nsNativeDragSource_h_
 
 #include "nscore.h"
 #include "nsIDOMDataTransfer.h"
-#include "nsCOMPtr.h"
 #include <ole2.h>
 #include <oleidl.h>
 #include "mozilla/Attributes.h"
+#inclide "mozilla/RefPtr.h"
+
+namespace mozilla {
+namespace dom {
+class DataTransfer;
+} // namespace dom
+} // namespace mozilla
 
 //class nsIDragSource;
 
 /*
  * nsNativeDragSource implements the IDropSource interface and gets
  * most of its behavior from the associated adapter (m_dragDrop).
  */
 class nsNativeDragSource final : public IDropSource
 {
 public:
 
   // construct an nsNativeDragSource referencing adapter
   // nsNativeDragSource(nsIDragSource * adapter);
-  explicit nsNativeDragSource(nsIDOMDataTransfer* aDataTransfer);
+  explicit nsNativeDragSource(mozilla::dom::DataTransfer* aDataTransfer);
   ~nsNativeDragSource();
 
   // IUnknown methods - see iunknown.h for documentation
 
   STDMETHODIMP QueryInterface(REFIID, void**);
   STDMETHODIMP_(ULONG) AddRef();
   STDMETHODIMP_(ULONG) Release();
 
@@ -48,17 +54,17 @@ public:
 
   bool UserCancelled() { return mUserCancelled; }
 
 protected:
   // Reference count
   ULONG m_cRef;
 
   // Data object, hold information about cursor state
-  nsCOMPtr<nsIDOMDataTransfer> mDataTransfer;
+  RefPtr<mozilla::dom::DataTransfer> mDataTransfer;
 
   // Custom drag cursor
   HCURSOR m_hCursor;
 
   // true if the user cancelled the drag by pressing escape
   bool mUserCancelled;
 };