Bug 1301673, properly handle disabled drag feedback image and failed drag feedbacks in content processes, r=tn
authorNeil Deakin <neil@mozilla.com>
Wed, 19 Oct 2016 15:01:39 -0400
changeset 318652 a8fd4f51596a460a2a5969329ac5d83eb86fb835
parent 318651 4afa256ec14fc12798346eaf423ecc02c7135020
child 318653 e6f320965d24073a97365a948a87240b640e9762
push id20725
push userphilringnalda@gmail.com
push dateThu, 20 Oct 2016 01:36:01 +0000
treeherderfx-team@998ad5a74da8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn
bugs1301673
milestone52.0a1
Bug 1301673, properly handle disabled drag feedback image and failed drag feedbacks in content processes, r=tn
dom/ipc/PBrowser.ipdl
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
widget/nsBaseDragService.cpp
widget/nsDragServiceProxy.cpp
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -580,19 +580,18 @@ parent:
     async SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY, int32_t aCx, int32_t aCy);
 
     nested(inside_sync) sync DispatchWheelEvent(WidgetWheelEvent event);
     nested(inside_sync) sync DispatchMouseEvent(WidgetMouseEvent event);
     nested(inside_sync) sync DispatchKeyboardEvent(WidgetKeyboardEvent event);
 
     async InvokeDragSession(IPCDataTransfer[] transfers, uint32_t action,
                             OptionalShmem visualData,
-                            uint32_t width, uint32_t height,
                             uint32_t stride, uint8_t format,
-                            int32_t dragAreaX, int32_t dragAreaY);
+                            LayoutDeviceIntRect dragRect);
 
     async AudioChannelActivityNotification(uint32_t aAudioChannel,
                                            bool aActive);
 
     // After a compositor reset, it is necessary to reconnect each layers ID to
     // the compositor of the widget that will render those layers. Note that
     // this is sync so we can ensure that messages to the window compositor
     // arrive before the TabChild attempts to use its cross-process compositor
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -283,18 +283,17 @@ TabParent::TabParent(nsIContentParent* a
   , mSizeMode(nsSizeMode_Normal)
   , mManager(aManager)
   , mDocShellIsActive(false)
   , mMarkedDestroying(false)
   , mIsDestroyed(false)
   , mIsDetached(true)
   , mAppPackageFileDescriptorSent(false)
   , mChromeFlags(aChromeFlags)
-  , mDragAreaX(0)
-  , mDragAreaY(0)
+  , mDragValid(false)
   , mInitedByParent(false)
   , mTabId(aTabId)
   , mCreatingWindow(false)
   , mCursor(nsCursor(-1))
   , mTabSetsCursor(false)
   , mHasContentOpener(false)
 #ifdef DEBUG
   , mActiveSupressDisplayportCount(0)
@@ -3228,19 +3227,18 @@ TabParent::RecvAsyncAuthPrompt(const nsC
 
   return rv == NS_OK;
 }
 
 bool
 TabParent::RecvInvokeDragSession(nsTArray<IPCDataTransfer>&& aTransfers,
                                  const uint32_t& aAction,
                                  const OptionalShmem& aVisualDnDData,
-                                 const uint32_t& aWidth, const uint32_t& aHeight,
                                  const uint32_t& aStride, const uint8_t& aFormat,
-                                 const int32_t& aDragAreaX, const int32_t& aDragAreaY)
+                                 const LayoutDeviceIntRect& aDragRect)
 {
   mInitialDataTransferItems.Clear();
   nsIPresShell* shell = mFrameElement->OwnerDoc()->GetShell();
   if (!shell) {
     if (Manager()->IsContentParent()) {
       Unused << Manager()->AsContentParent()->SendEndDragSession(true, true,
                                                                  LayoutDeviceIntPoint());
     }
@@ -3256,27 +3254,28 @@ TabParent::RecvInvokeDragSession(nsTArra
       do_GetService("@mozilla.org/widget/dragservice;1");
     if (dragService) {
       dragService->MaybeAddChildProcess(Manager()->AsContentParent());
     }
   }
 
   if (aVisualDnDData.type() == OptionalShmem::Tvoid_t ||
       !aVisualDnDData.get_Shmem().IsReadable() ||
-      aVisualDnDData.get_Shmem().Size<char>() < aHeight * aStride) {
+      aVisualDnDData.get_Shmem().Size<char>() < aDragRect.height * aStride) {
     mDnDVisualization = nullptr;
   } else {
     mDnDVisualization =
-        gfx::CreateDataSourceSurfaceFromData(gfx::IntSize(aWidth, aHeight),
+        gfx::CreateDataSourceSurfaceFromData(gfx::IntSize(aDragRect.width, aDragRect.height),
                                              static_cast<gfx::SurfaceFormat>(aFormat),
                                              aVisualDnDData.get_Shmem().get<uint8_t>(),
                                              aStride);
   }
-  mDragAreaX = aDragAreaX;
-  mDragAreaY = aDragAreaY;
+
+  mDragValid = true;
+  mDragRect = aDragRect;
 
   esm->BeginTrackingRemoteDragGesture(mFrameElement);
 
   if (aVisualDnDData.type() == OptionalShmem::TShmem) {
     Unused << DeallocShmem(aVisualDnDData);
   }
 
   return true;
@@ -3330,23 +3329,27 @@ TabParent::AddInitialDnDDataTo(DataTrans
                                                           variant, i,
                                                           nsContentUtils::GetSystemPrincipal(),
                                                           /* aHidden = */ false);
     }
   }
   mInitialDataTransferItems.Clear();
 }
 
-void
+bool
 TabParent::TakeDragVisualization(RefPtr<mozilla::gfx::SourceSurface>& aSurface,
-                                 int32_t& aDragAreaX, int32_t& aDragAreaY)
+                                 LayoutDeviceIntRect* aDragRect)
 {
+  if (!mDragValid)
+    return false;
+
   aSurface = mDnDVisualization.forget();
-  aDragAreaX = mDragAreaX;
-  aDragAreaY = mDragAreaY;
+  *aDragRect = mDragRect;
+  mDragValid = false;
+  return true;
 }
 
 bool
 TabParent::AsyncPanZoomEnabled() const
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   return widget && widget->AsyncPanZoomEnabled();
 }
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -569,24 +569,23 @@ public:
                             const bool& aRunInGlobalScope);
 
   void LayerTreeUpdate(uint64_t aEpoch, bool aActive);
 
   virtual bool
   RecvInvokeDragSession(nsTArray<IPCDataTransfer>&& aTransfers,
                         const uint32_t& aAction,
                         const OptionalShmem& aVisualDnDData,
-                        const uint32_t& aWidth, const uint32_t& aHeight,
                         const uint32_t& aStride, const uint8_t& aFormat,
-                        const int32_t& aDragAreaX, const int32_t& aDragAreaY) override;
+                        const LayoutDeviceIntRect& aDragRect) override;
 
   void AddInitialDnDDataTo(DataTransfer* aDataTransfer);
 
-  void TakeDragVisualization(RefPtr<mozilla::gfx::SourceSurface>& aSurface,
-                             int32_t& aDragAreaX, int32_t& aDragAreaY);
+  bool TakeDragVisualization(RefPtr<mozilla::gfx::SourceSurface>& aSurface,
+                             LayoutDeviceIntRect* aDragRect);
 
   layout::RenderFrameParent* GetRenderFrame();
 
   void AudioChannelChangeNotification(nsPIDOMWindowOuter* aWindow,
                                       AudioChannel aAudioChannel,
                                       float aVolume,
                                       bool aMuted);
   bool SetRenderFrame(PRenderFrameParent* aRFParent);
@@ -680,18 +679,18 @@ private:
   // Whether we have already sent a FileDescriptor for the app package.
   bool mAppPackageFileDescriptorSent;
 
   uint32_t mChromeFlags;
 
   nsTArray<nsTArray<IPCDataTransferItem>> mInitialDataTransferItems;
 
   RefPtr<gfx::DataSourceSurface> mDnDVisualization;
-  int32_t mDragAreaX;
-  int32_t mDragAreaY;
+  bool mDragValid;
+  LayoutDeviceIntRect mDragRect;
 
   // When true, the TabParent is initialized without child side's request.
   // When false, the TabParent is initialized by window.open() from child side.
   bool mInitedByParent;
 
   nsCOMPtr<nsILoadContext> mLoadContext;
 
   // We keep a strong reference to the frameloader after we've sent the
--- a/widget/nsBaseDragService.cpp
+++ b/widget/nsBaseDragService.cpp
@@ -524,34 +524,23 @@ nsBaseDragService::DrawDrag(nsIDOMNode* 
   *aPresContext = presShell->GetPresContext();
 
   nsCOMPtr<nsIFrameLoaderOwner> flo = do_QueryInterface(dragNode);
   if (flo) {
     RefPtr<nsFrameLoader> fl = flo->GetFrameLoader();
     if (fl) {
       mozilla::dom::TabParent* tp =
         static_cast<mozilla::dom::TabParent*>(fl->GetRemoteBrowser());
-      if (tp) {
-        int32_t x, y;
-        tp->TakeDragVisualization(*aSurface, x, y);
-        if (*aSurface) {
-          if (mImage) {
-            // Just clear the surface if chrome has overridden it with an image.
-            *aSurface = nullptr;
-          } else {
-            nsIFrame* f = fl->GetOwnerContent()->GetPrimaryFrame();
-            if (f) {
-              aScreenDragRect->x = x;
-              aScreenDragRect->y = y;
-              aScreenDragRect->width = (*aSurface)->GetSize().width;
-              aScreenDragRect->height = (*aSurface)->GetSize().height;
-            }
-            return NS_OK;
-          }
+      if (tp && tp->TakeDragVisualization(*aSurface, aScreenDragRect)) {
+        if (mImage) {
+          // Just clear the surface if chrome has overridden it with an image.
+          *aSurface = nullptr;
         }
+
+        return NS_OK;
       }
     }
   }
 
   // convert mouse position to dev pixels of the prescontext
   CSSIntPoint screenPosition(aScreenPosition);
   screenPosition.x -= mImageOffset.x;
   screenPosition.y -= mImageOffset.y;
--- a/widget/nsDragServiceProxy.cpp
+++ b/widget/nsDragServiceProxy.cpp
@@ -38,18 +38,18 @@ nsDragServiceProxy::InvokeDragSessionImp
   NS_ENSURE_STATE(child);
   nsTArray<mozilla::dom::IPCDataTransfer> dataTransfers;
   nsContentUtils::TransferablesToIPCTransferables(aArrayTransferables,
                                                   dataTransfers,
                                                   false,
                                                   child->Manager(),
                                                   nullptr);
 
+  LayoutDeviceIntRect dragRect;
   if (mHasImage || mSelection) {
-    LayoutDeviceIntRect dragRect;
     nsPresContext* pc;
     RefPtr<mozilla::gfx::SourceSurface> surface;
     DrawDrag(mSourceNode, aRegion, mScreenPosition, &dragRect, &surface, &pc);
 
     if (surface) {
       RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
         surface->GetDataSurface();
       if (dataSurface) {
@@ -59,26 +59,23 @@ nsDragServiceProxy::InvokeDragSessionImp
         nsContentUtils::GetSurfaceData(dataSurface, &length, &stride, child,
                                        &surfaceData);
         // Save the surface data to shared memory.
         if (!surfaceData.IsReadable() || !surfaceData.get<char>()) {
           NS_WARNING("Failed to create shared memory for drag session.");
           return NS_ERROR_FAILURE;
         }
 
-        mozilla::gfx::IntSize size = dataSurface->GetSize();
         mozilla::Unused <<
           child->SendInvokeDragSession(dataTransfers, aActionType, surfaceData,
-                                       size.width, size.height, stride,
-                                       static_cast<uint8_t>(dataSurface->GetFormat()),
-                                       dragRect.x, dragRect.y);
+                                       stride, static_cast<uint8_t>(dataSurface->GetFormat()),
+                                       dragRect);
         StartDragSession();
         return NS_OK;
       }
     }
   }
 
   mozilla::Unused << child->SendInvokeDragSession(dataTransfers, aActionType,
-                                                  mozilla::void_t(),
-                                                  0, 0, 0, 0, 0, 0);
+                                                  mozilla::void_t(), 0, 0, dragRect);
   StartDragSession();
   return NS_OK;
 }