Bug 1809122 - Track top-level window context in DragSession; r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D169121
This commit is contained in:
Edgar Chen 2023-02-13 18:44:04 +00:00
Родитель e39c51f7fd
Коммит 60b2a99aab
17 изменённых файлов: 80 добавлений и 22 удалений

Просмотреть файл

@ -248,15 +248,15 @@ ContentAreaDropListener.prototype = {
}
// If this is an external drag, allow drop.
let sourceWC = dataTransfer.sourceWindowContext;
if (!sourceWC) {
let sourceTopWC = dataTransfer.sourceTopWindowContext;
if (!sourceTopWC) {
return true;
}
// If drag source and drop target are in the same top window, don't allow.
let eventWC =
aEvent.originalTarget.ownerGlobal.browsingContext.currentWindowContext;
if (eventWC && sourceWC.topWindowContext == eventWC.topWindowContext) {
if (eventWC && sourceTopWC == eventWC.topWindowContext) {
return false;
}

Просмотреть файл

@ -440,15 +440,16 @@ already_AddRefed<nsINode> DataTransfer::GetMozSourceNode() {
return sourceNode.forget();
}
already_AddRefed<WindowContext> DataTransfer::GetSourceWindowContext() {
already_AddRefed<WindowContext> DataTransfer::GetSourceTopWindowContext() {
nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
if (!dragSession) {
return nullptr;
}
RefPtr<WindowContext> sourceWindowContext;
dragSession->GetSourceWindowContext(getter_AddRefs(sourceWindowContext));
return sourceWindowContext.forget();
RefPtr<WindowContext> sourceTopWindowContext;
dragSession->GetSourceTopWindowContext(
getter_AddRefs(sourceTopWindowContext));
return sourceTopWindowContext.forget();
}
already_AddRefed<DOMStringList> DataTransfer::MozTypesAt(

Просмотреть файл

@ -255,7 +255,7 @@ class DataTransfer final : public nsISupports, public nsWrapperCache {
already_AddRefed<nsINode> GetMozSourceNode();
already_AddRefed<WindowContext> GetSourceWindowContext();
already_AddRefed<WindowContext> GetSourceTopWindowContext();
/*
* Integer version of dropEffect, set to one of the constants in

Просмотреть файл

@ -23,14 +23,15 @@ RemoteDragStartData::RemoteDragStartData(
BrowserParent* aBrowserParent, nsTArray<IPCDataTransfer>&& aDataTransfer,
const LayoutDeviceIntRect& aRect, nsIPrincipal* aPrincipal,
nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings,
WindowContext* aSourceWindowContext)
WindowContext* aSourceWindowContext, WindowContext* aSourceTopWindowContext)
: mBrowserParent(aBrowserParent),
mDataTransfer(std::move(aDataTransfer)),
mRect(aRect),
mPrincipal(aPrincipal),
mCsp(aCsp),
mCookieJarSettings(aCookieJarSettings),
mSourceWindowContext(aSourceWindowContext) {}
mSourceWindowContext(aSourceWindowContext),
mSourceTopWindowContext(aSourceTopWindowContext) {}
void RemoteDragStartData::AddInitialDnDDataTo(
DataTransfer* aDataTransfer, nsIPrincipal** aPrincipal,

Просмотреть файл

@ -31,7 +31,8 @@ class RemoteDragStartData {
const LayoutDeviceIntRect& aRect,
nsIPrincipal* aPrincipal, nsIContentSecurityPolicy* aCsp,
nsICookieJarSettings* aCookieJarSettings,
WindowContext* aSourceWindowContext);
WindowContext* aSourceWindowContext,
WindowContext* aSourceTopWindowContext);
void SetVisualization(
already_AddRefed<gfx::DataSourceSurface> aVisualization) {
@ -52,6 +53,7 @@ class RemoteDragStartData {
nsICookieJarSettings** aCookieJarSettings);
WindowContext* GetSourceWindowContext() { return mSourceWindowContext; }
WindowContext* GetSourceTopWindowContext() { return mSourceTopWindowContext; }
private:
virtual ~RemoteDragStartData();
@ -63,6 +65,7 @@ class RemoteDragStartData {
nsCOMPtr<nsIContentSecurityPolicy> mCsp;
nsCOMPtr<nsICookieJarSettings> mCookieJarSettings;
RefPtr<WindowContext> mSourceWindowContext;
RefPtr<WindowContext> mSourceTopWindowContext;
RefPtr<mozilla::gfx::SourceSurface> mVisualization;
};

Просмотреть файл

@ -3746,7 +3746,8 @@ mozilla::ipc::IPCResult BrowserParent::RecvInvokeDragSession(
const gfx::SurfaceFormat& aFormat, const LayoutDeviceIntRect& aDragRect,
nsIPrincipal* aPrincipal, nsIContentSecurityPolicy* aCsp,
const CookieJarSettingsArgs& aCookieJarSettingsArgs,
const MaybeDiscarded<WindowContext>& aSourceWindowContext) {
const MaybeDiscarded<WindowContext>& aSourceWindowContext,
const MaybeDiscarded<WindowContext>& aSourceTopWindowContext) {
PresShell* presShell = mFrameElement->OwnerDoc()->GetPresShell();
if (!presShell) {
Unused << Manager()->SendEndDragSession(
@ -3764,7 +3765,8 @@ mozilla::ipc::IPCResult BrowserParent::RecvInvokeDragSession(
RefPtr<RemoteDragStartData> dragStartData = new RemoteDragStartData(
this, std::move(aTransfers), aDragRect, aPrincipal, aCsp,
cookieJarSettings, aSourceWindowContext.GetMaybeDiscarded());
cookieJarSettings, aSourceWindowContext.GetMaybeDiscarded(),
aSourceTopWindowContext.GetMaybeDiscarded());
if (aVisualDnDData && aVisualDnDData->Size() >= aDragRect.height * aStride) {
dragStartData->SetVisualization(gfx::CreateDataSourceSurfaceFromData(

Просмотреть файл

@ -674,7 +674,8 @@ class BrowserParent final : public PBrowserParent,
const gfx::SurfaceFormat& aFormat, const LayoutDeviceIntRect& aDragRect,
nsIPrincipal* aPrincipal, nsIContentSecurityPolicy* aCsp,
const CookieJarSettingsArgs& aCookieJarSettingsArgs,
const MaybeDiscarded<WindowContext>& aSourceWindowContext);
const MaybeDiscarded<WindowContext>& aSourceWindowContext,
const MaybeDiscarded<WindowContext>& aSourceTopWindowContext);
void AddInitialDnDDataTo(DataTransfer* aDataTransfer,
nsIPrincipal** aPrincipal);

Просмотреть файл

@ -3184,6 +3184,7 @@ bool ContentChild::DeallocPWebBrowserPersistDocumentChild(
mozilla::ipc::IPCResult ContentChild::RecvInvokeDragSession(
const MaybeDiscarded<WindowContext>& aSourceWindowContext,
const MaybeDiscarded<WindowContext>& aSourceTopWindowContext,
nsTArray<IPCDataTransfer>&& aTransfers, const uint32_t& aAction) {
nsCOMPtr<nsIDragService> dragService =
do_GetService("@mozilla.org/widget/dragservice;1");
@ -3193,6 +3194,8 @@ mozilla::ipc::IPCResult ContentChild::RecvInvokeDragSession(
dragService->GetCurrentSession(getter_AddRefs(session));
if (session) {
session->SetSourceWindowContext(aSourceWindowContext.GetMaybeDiscarded());
session->SetSourceTopWindowContext(
aSourceTopWindowContext.GetMaybeDiscarded());
session->SetDragAction(aAction);
// Check if we are receiving any file objects. If we are we will want
// to hide any of the other objects coming in from content.

Просмотреть файл

@ -413,6 +413,7 @@ class ContentChild final : public PContentChild,
mozilla::ipc::IPCResult RecvInvokeDragSession(
const MaybeDiscarded<WindowContext>& aSourceWindowContext,
const MaybeDiscarded<WindowContext>& aSourceTopWindowContext,
nsTArray<IPCDataTransfer>&& aTransfers, const uint32_t& aAction);
MOZ_CAN_RUN_SCRIPT_BOUNDARY

Просмотреть файл

@ -5444,8 +5444,10 @@ void ContentParent::MaybeInvokeDragSession(BrowserParent* aParent) {
RefPtr<WindowContext> sourceWC;
session->GetSourceWindowContext(getter_AddRefs(sourceWC));
RefPtr<WindowContext> sourceTopWC;
session->GetSourceTopWindowContext(getter_AddRefs(sourceTopWC));
mozilla::Unused << SendInvokeDragSession(
sourceWC, std::move(dataTransfers), action);
sourceWC, sourceTopWC, std::move(dataTransfers), action);
}
}
}

Просмотреть файл

@ -628,7 +628,8 @@ parent:
LayoutDeviceIntRect dragRect,
nsIPrincipal principal, nsIContentSecurityPolicy csp,
CookieJarSettingsArgs cookieJarSettings,
MaybeDiscardedWindowContext sourceWindowContext);
MaybeDiscardedWindowContext sourceWindowContext,
MaybeDiscardedWindowContext sourceTopWindowContext);
// 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

Просмотреть файл

@ -815,7 +815,8 @@ child:
*/
async NotifyIdleObserver(uint64_t observerId, nsCString topic, nsString str);
async InvokeDragSession(MaybeDiscardedWindowContext aContext,
async InvokeDragSession(MaybeDiscardedWindowContext aSourceWindowContext,
MaybeDiscardedWindowContext aSourceTopWindowContext,
IPCDataTransfer[] transfers, uint32_t action);
async EndDragSession(bool aDoneDrag, bool aUserCancelled,

Просмотреть файл

@ -152,11 +152,11 @@ partial interface DataTransfer {
readonly attribute Node? mozSourceNode;
/**
* The window context that mouse was pressed over to begin the drag. For
* external drags, this will be null.
* The top-level window context that mouse was pressed over to begin the drag.
* For external drags, this will be null.
*/
[ChromeOnly]
readonly attribute WindowContext? sourceWindowContext;
readonly attribute WindowContext? sourceTopWindowContext;
/**
* The URI spec of the triggering principal. This may be different than

Просмотреть файл

@ -150,6 +150,29 @@ nsBaseDragService::SetSourceWindowContext(WindowContext* aSourceWindowContext) {
return NS_OK;
}
//
// GetSourceTopWindowContext
//
// Returns the top-level window context where the drag was initiated. This will
// be nullptr if the drag began outside of our application.
//
NS_IMETHODIMP
nsBaseDragService::GetSourceTopWindowContext(
WindowContext** aSourceTopWindowContext) {
*aSourceTopWindowContext = mSourceTopWindowContext.get();
NS_IF_ADDREF(*aSourceTopWindowContext);
return NS_OK;
}
NS_IMETHODIMP
nsBaseDragService::SetSourceTopWindowContext(
WindowContext* aSourceTopWindowContext) {
// This should only be called in a child process.
MOZ_ASSERT(!XRE_IsParentProcess());
mSourceTopWindowContext = aSourceTopWindowContext;
return NS_OK;
}
//
// GetSourceNode
//
@ -393,6 +416,8 @@ nsBaseDragService::InvokeDragSessionWithImage(
mDragStartData = nullptr;
mSourceWindowContext =
aDOMNode ? aDOMNode->OwnerDoc()->GetWindowContext() : nullptr;
mSourceTopWindowContext =
mSourceWindowContext ? mSourceWindowContext->TopWindowContext() : nullptr;
mScreenPosition = aDragEvent->ScreenPoint(CallerType::System);
mInputSource = aDragEvent->MozInputSource();
@ -441,6 +466,7 @@ nsBaseDragService::InvokeDragSessionWithRemoteImage(
mDragStartData = aDragStartData;
mImageOffset = CSSIntPoint(0, 0);
mSourceWindowContext = mDragStartData->GetSourceWindowContext();
mSourceTopWindowContext = mDragStartData->GetSourceTopWindowContext();
mScreenPosition = aDragEvent->ScreenPoint(CallerType::System);
mInputSource = aDragEvent->MozInputSource();
@ -482,6 +508,8 @@ nsBaseDragService::InvokeDragSessionWithSelection(
// endpoints of the selection
nsCOMPtr<nsINode> node = aSelection->GetFocusNode();
mSourceWindowContext = node ? node->OwnerDoc()->GetWindowContext() : nullptr;
mSourceTopWindowContext =
mSourceWindowContext ? mSourceWindowContext->TopWindowContext() : nullptr;
return InvokeDragSession(node, aPrincipal, aCsp, aCookieJarSettings,
aTransferableArray, aActionType,

Просмотреть файл

@ -170,6 +170,7 @@ class nsBaseDragService : public nsIDragService, public nsIDragSession {
RefPtr<mozilla::dom::Document> mSourceDocument;
RefPtr<mozilla::dom::WindowContext> mSourceWindowContext;
RefPtr<mozilla::dom::WindowContext> mSourceTopWindowContext;
// the contentpolicy type passed to the channel when initiating the drag
// session

Просмотреть файл

@ -46,7 +46,12 @@ nsresult nsDragServiceProxy::InvokeDragSessionImpl(
nsCOMPtr<nsIContentSecurityPolicy> csp;
if (mSourceDocument) {
csp = mSourceDocument->GetCsp();
// XXX why do we need this here? Shouldn't they be set properly in
// nsBaseDragService already?
mSourceWindowContext = mSourceDocument->GetWindowContext();
mSourceTopWindowContext = mSourceWindowContext
? mSourceWindowContext->TopWindowContext()
: nullptr;
}
nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
@ -75,7 +80,7 @@ nsresult nsDragServiceProxy::InvokeDragSessionImpl(
mozilla::Unused << child->SendInvokeDragSession(
std::move(dataTransfers), aActionType, std::move(surfaceData),
stride, dataSurface->GetFormat(), dragRect, principal, csp, csArgs,
mSourceWindowContext);
mSourceWindowContext, mSourceTopWindowContext);
StartDragSession();
return NS_OK;
}
@ -85,7 +90,7 @@ nsresult nsDragServiceProxy::InvokeDragSessionImpl(
mozilla::Unused << child->SendInvokeDragSession(
std::move(dataTransfers), aActionType, Nothing(), 0,
static_cast<SurfaceFormat>(0), dragRect, principal, csp, csArgs,
mSourceWindowContext);
mSourceWindowContext, mSourceTopWindowContext);
StartDragSession();
return NS_OK;
}

Просмотреть файл

@ -53,6 +53,14 @@ interface nsIDragSession : nsISupports
[infallible]
attribute WindowContext sourceWindowContext;
/**
* The top-level window context where the drag was started, which will be
* null if the drag originated outside the application. Useful for
* determining if a drop originated in the same top-level window context.
*/
[infallible]
attribute WindowContext sourceTopWindowContext;
/**
* The dom node that was originally dragged to start the session, which will be null if the
* drag originated outside the application.