1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 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/. */
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/net/CookieJarSettings.h"
12 #include "mozilla/UniquePtr.h"
13 #include "mozilla/Unused.h"
14 #include "nsContentUtils.h"
16 using mozilla::CSSIntRegion
;
17 using mozilla::LayoutDeviceIntRect
;
19 using mozilla::Nothing
;
21 using mozilla::dom::BrowserChild
;
22 using mozilla::gfx::DataSourceSurface
;
23 using mozilla::gfx::SourceSurface
;
24 using mozilla::gfx::SurfaceFormat
;
25 using mozilla::ipc::Shmem
;
27 nsDragServiceProxy::~nsDragServiceProxy() = default;
29 nsDragSessionProxy::~nsDragSessionProxy() = default;
31 already_AddRefed
<nsIDragSession
> nsDragServiceProxy::CreateDragSession() {
32 RefPtr
<nsIDragSession
> session
= new nsDragSessionProxy();
33 return session
.forget();
36 nsresult
nsDragSessionProxy::InvokeDragSession(
37 nsIWidget
* aWidget
, nsINode
* aDOMNode
, nsIPrincipal
* aPrincipal
,
38 nsIContentSecurityPolicy
* aCsp
, nsICookieJarSettings
* aCookieJarSettings
,
39 nsIArray
* aTransferableArray
, uint32_t aActionType
,
40 nsContentPolicyType aContentPolicyType
) {
41 BrowserChild
* sourceBrowser
= aWidget
->GetOwningBrowserChild();
42 NS_ENSURE_TRUE(sourceBrowser
, NS_ERROR_INVALID_ARG
);
43 [[maybe_unused
]] RefPtr
<nsIDragSession
> sourceSession
=
44 sourceBrowser
->GetDragSession();
45 MOZ_ASSERT(!sourceSession
);
47 sourceBrowser
->GetWeakReference(getter_AddRefs(mSourceBrowser
)));
48 sourceBrowser
->SetDragSession(this);
49 nsresult rv
= nsBaseDragSession::InvokeDragSession(
50 aWidget
, aDOMNode
, aPrincipal
, aCsp
, aCookieJarSettings
,
51 aTransferableArray
, aActionType
, aContentPolicyType
);
55 nsresult
nsDragSessionProxy::InvokeDragSessionImpl(
56 nsIWidget
* aWidget
, nsIArray
* aArrayTransferables
,
57 const Maybe
<CSSIntRegion
>& aRegion
, uint32_t aActionType
) {
58 NS_ENSURE_STATE(mSourceDocument
->GetDocShell());
59 BrowserChild
* child
= BrowserChild::GetFrom(mSourceDocument
->GetDocShell());
60 NS_ENSURE_STATE(child
);
61 nsTArray
<mozilla::dom::IPCTransferableData
> transferables
;
62 nsContentUtils::TransferablesToIPCTransferableDatas(
63 aArrayTransferables
, transferables
, false, nullptr);
65 nsCOMPtr
<nsIPrincipal
> principal
;
67 principal
= mSourceNode
->NodePrincipal();
70 nsCOMPtr
<nsIContentSecurityPolicy
> csp
;
71 if (mSourceDocument
) {
72 csp
= mSourceDocument
->GetCsp();
73 // XXX why do we need this here? Shouldn't they be set properly in
74 // nsBaseDragService already?
75 mSourceWindowContext
= mSourceDocument
->GetWindowContext();
76 mSourceTopWindowContext
= mSourceWindowContext
77 ? mSourceWindowContext
->TopWindowContext()
81 nsCOMPtr
<nsICookieJarSettings
> cookieJarSettings
;
82 cookieJarSettings
= mSourceDocument
->CookieJarSettings();
83 mozilla::net::CookieJarSettingsArgs csArgs
;
84 mozilla::net::CookieJarSettings::Cast(cookieJarSettings
)->Serialize(csArgs
);
86 LayoutDeviceIntRect dragRect
;
87 if (mHasImage
|| mSelection
) {
89 RefPtr
<SourceSurface
> surface
;
90 DrawDrag(mSourceNode
, aRegion
, mScreenPosition
, &dragRect
, &surface
, &pc
);
93 RefPtr
<DataSourceSurface
> dataSurface
= surface
->GetDataSurface();
98 nsContentUtils::GetSurfaceData(*dataSurface
, &length
, &stride
);
99 if (surfaceData
.isNothing()) {
100 NS_WARNING("Failed to create shared memory for drag session.");
101 return NS_ERROR_FAILURE
;
104 mozilla::Unused
<< child
->SendInvokeDragSession(
105 std::move(transferables
), aActionType
, std::move(surfaceData
),
106 stride
, dataSurface
->GetFormat(), dragRect
, principal
, csp
, csArgs
,
107 mSourceWindowContext
, mSourceTopWindowContext
);
113 mozilla::Unused
<< child
->SendInvokeDragSession(
114 std::move(transferables
), aActionType
, Nothing(), 0,
115 static_cast<SurfaceFormat
>(0), dragRect
, principal
, csp
, csArgs
,
116 mSourceWindowContext
, mSourceTopWindowContext
);
120 nsIDragSession
* nsDragServiceProxy::StartDragSession(
121 nsISupports
* aWidgetProvider
) {
122 nsIWidget
* widget
= GetWidgetFromWidgetProvider(aWidgetProvider
);
123 NS_ENSURE_TRUE(widget
, nullptr);
124 BrowserChild
* targetBrowser
= widget
->GetOwningBrowserChild();
125 NS_ENSURE_TRUE(targetBrowser
, nullptr);
126 RefPtr
<nsIDragSession
> session
= targetBrowser
->GetDragSession();
128 // session already exists on the browser
132 session
= CreateDragSession();
134 static_cast<nsDragSessionProxy
*>(session
.get())->SetDragTarget(targetBrowser
);
135 targetBrowser
->SetDragSession(session
);
140 nsDragServiceProxy::GetCurrentSession(nsISupports
* aWidgetProvider
,
141 nsIDragSession
** aSession
) {
143 return NS_ERROR_INVALID_ARG
;
147 nsIWidget
* widget
= GetWidgetFromWidgetProvider(aWidgetProvider
);
148 NS_ENSURE_TRUE(widget
, NS_ERROR_INVALID_ARG
);
149 BrowserChild
* browser
= widget
->GetOwningBrowserChild();
150 NS_ENSURE_TRUE(browser
, NS_ERROR_INVALID_ARG
);
151 RefPtr
<nsIDragSession
> session
= browser
->GetDragSession();
153 if (!mSuppressLevel
&& session
) {
154 session
.forget(aSession
);
160 void nsDragSessionProxy::SetDragTarget(BrowserChild
* aTarget
) {
162 if (mTargetBrowser
) {
163 nsCOMPtr
<BrowserChild
> targetBC
= do_QueryReferent(mTargetBrowser
);
164 MOZ_ASSERT(targetBC
);
166 targetBC
->SetDragSession(nullptr);
168 mTargetBrowser
= nullptr;
172 [[maybe_unused
]] RefPtr
<nsIDragSession
> session
= aTarget
->GetDragSession();
173 MOZ_ASSERT(!session
);
175 aTarget
->GetWeakReference(getter_AddRefs(mTargetBrowser
)));
178 nsresult
nsDragSessionProxy::EndDragSessionImpl(bool aDoneDrag
,
179 uint32_t aKeyModifiers
) {
180 // End the drag session before removing it from its BrowserChild(s). This
181 // leaves the drag session in place while EndDragSessionImpl sends dragend.
182 nsresult rv
= nsBaseDragSession::EndDragSessionImpl(aDoneDrag
, aKeyModifiers
);
184 if (mSourceBrowser
) {
185 nsCOMPtr
<BrowserChild
> sourceBC
= do_QueryReferent(mSourceBrowser
);
186 MOZ_ASSERT(sourceBC
);
187 [[maybe_unused
]] RefPtr
<nsIDragSession
> session
=
188 sourceBC
->GetDragSession();
189 MOZ_ASSERT(session
== this);
190 sourceBC
->SetDragSession(nullptr);
191 mSourceBrowser
= nullptr;
194 SetDragTarget(nullptr);