1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  *
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "nsDragServiceProxy.h"
8 #include "mozilla/dom/Document.h"
9 #include "mozilla/dom/BrowserChild.h"
10 #include "mozilla/gfx/2D.h"
11 #include "mozilla/UniquePtr.h"
12 #include "mozilla/Unused.h"
13 #include "nsContentUtils.h"
14 
15 using mozilla::CSSIntRegion;
16 using mozilla::LayoutDeviceIntRect;
17 using mozilla::Maybe;
18 using mozilla::Nothing;
19 using mozilla::Some;
20 using mozilla::dom::BrowserChild;
21 using mozilla::gfx::DataSourceSurface;
22 using mozilla::gfx::SourceSurface;
23 using mozilla::gfx::SurfaceFormat;
24 using mozilla::ipc::Shmem;
25 
26 nsDragServiceProxy::nsDragServiceProxy() = default;
27 
28 nsDragServiceProxy::~nsDragServiceProxy() = default;
29 
InvokeDragSessionImpl(nsIArray * aArrayTransferables,const Maybe<CSSIntRegion> & aRegion,uint32_t aActionType)30 nsresult nsDragServiceProxy::InvokeDragSessionImpl(
31     nsIArray* aArrayTransferables, const Maybe<CSSIntRegion>& aRegion,
32     uint32_t aActionType) {
33   NS_ENSURE_STATE(mSourceDocument->GetDocShell());
34   BrowserChild* child = BrowserChild::GetFrom(mSourceDocument->GetDocShell());
35   NS_ENSURE_STATE(child);
36   nsTArray<mozilla::dom::IPCDataTransfer> dataTransfers;
37   nsContentUtils::TransferablesToIPCTransferables(
38       aArrayTransferables, dataTransfers, false, child->Manager(), nullptr);
39 
40   nsCOMPtr<nsIPrincipal> principal;
41   if (mSourceNode) {
42     principal = mSourceNode->NodePrincipal();
43   }
44 
45   nsCOMPtr<nsIContentSecurityPolicy> csp;
46   if (mSourceDocument) {
47     csp = mSourceDocument->GetCsp();
48   }
49 
50   LayoutDeviceIntRect dragRect;
51   if (mHasImage || mSelection) {
52     nsPresContext* pc;
53     RefPtr<SourceSurface> surface;
54     DrawDrag(mSourceNode, aRegion, mScreenPosition, &dragRect, &surface, &pc);
55 
56     if (surface) {
57       RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();
58       if (dataSurface) {
59         size_t length;
60         int32_t stride;
61         Maybe<Shmem> maybeShm = nsContentUtils::GetSurfaceData(
62             dataSurface, &length, &stride, child);
63         if (maybeShm.isNothing()) {
64           return NS_ERROR_FAILURE;
65         }
66 
67         auto surfaceData = maybeShm.value();
68 
69         // Save the surface data to shared memory.
70         if (!surfaceData.IsReadable() || !surfaceData.get<char>()) {
71           NS_WARNING("Failed to create shared memory for drag session.");
72           return NS_ERROR_FAILURE;
73         }
74 
75         mozilla::Unused << child->SendInvokeDragSession(
76             dataTransfers, aActionType, Some(std::move(surfaceData)), stride,
77             dataSurface->GetFormat(), dragRect, principal, csp);
78         StartDragSession();
79         return NS_OK;
80       }
81     }
82   }
83 
84   mozilla::Unused << child->SendInvokeDragSession(
85       dataTransfers, aActionType, Nothing(), 0, static_cast<SurfaceFormat>(0),
86       dragRect, principal, csp);
87   StartDragSession();
88   return NS_OK;
89 }
90