Bug 1901197: do synchronous Content Analysis for clipboard operations on a background thread r=dlp-reviewers,ipc-reviewers,handyman
Differential Revision: https://phabricator.services.mozilla.com/D215457
This commit is contained in:
@@ -20,6 +20,9 @@
|
|||||||
# Used by `nsUpdateProcessor` to check for updates. May also be used for polling
|
# Used by `nsUpdateProcessor` to check for updates. May also be used for polling
|
||||||
# the update process.
|
# the update process.
|
||||||
UpdateProcessor
|
UpdateProcessor
|
||||||
|
# Used by `BackgroundClipboardContentAnalysisParent` to handle clipboard requests
|
||||||
|
# from content processes.
|
||||||
|
BkgrndClipboard
|
||||||
|
|
||||||
######
|
######
|
||||||
# Thunderbird-only thread names
|
# Thunderbird-only thread names
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "imgLoader.h"
|
#include "imgLoader.h"
|
||||||
#include "ScrollingMetrics.h"
|
#include "ScrollingMetrics.h"
|
||||||
#include "mozilla/BasePrincipal.h"
|
#include "mozilla/BasePrincipal.h"
|
||||||
|
#include "mozilla/ClipboardContentAnalysisChild.h"
|
||||||
#include "mozilla/ClipboardReadRequestChild.h"
|
#include "mozilla/ClipboardReadRequestChild.h"
|
||||||
#include "mozilla/Components.h"
|
#include "mozilla/Components.h"
|
||||||
#include "mozilla/HangDetails.h"
|
#include "mozilla/HangDetails.h"
|
||||||
@@ -1544,6 +1545,14 @@ mozilla::ipc::IPCResult ContentChild::RecvInitGMPService(
|
|||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult ContentChild::RecvInitClipboardContentAnalysis(
|
||||||
|
Endpoint<PClipboardContentAnalysisChild>&& aEndpoint) {
|
||||||
|
if (!ClipboardContentAnalysisChild::Create(std::move(aEndpoint))) {
|
||||||
|
return IPC_FAIL_NO_REASON(this);
|
||||||
|
}
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult ContentChild::RecvInitProfiler(
|
mozilla::ipc::IPCResult ContentChild::RecvInitProfiler(
|
||||||
Endpoint<PProfilerChild>&& aEndpoint) {
|
Endpoint<PProfilerChild>&& aEndpoint) {
|
||||||
mProfilerController = ChildProfilerController::Create(std::move(aEndpoint));
|
mProfilerController = ChildProfilerController::Create(std::move(aEndpoint));
|
||||||
|
|||||||
@@ -160,6 +160,9 @@ class ContentChild final : public PContentChild,
|
|||||||
mozilla::ipc::IPCResult RecvInitProfiler(
|
mozilla::ipc::IPCResult RecvInitProfiler(
|
||||||
Endpoint<PProfilerChild>&& aEndpoint);
|
Endpoint<PProfilerChild>&& aEndpoint);
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult RecvInitClipboardContentAnalysis(
|
||||||
|
Endpoint<PClipboardContentAnalysisChild>&& aEndpoint);
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvGMPsChanged(
|
mozilla::ipc::IPCResult RecvGMPsChanged(
|
||||||
nsTArray<GMPCapabilityData>&& capabilities);
|
nsTArray<GMPCapabilityData>&& capabilities);
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
#include "mozilla/AntiTrackingUtils.h"
|
#include "mozilla/AntiTrackingUtils.h"
|
||||||
#include "mozilla/AppShutdown.h"
|
#include "mozilla/AppShutdown.h"
|
||||||
#include "mozilla/AutoRestore.h"
|
#include "mozilla/AutoRestore.h"
|
||||||
|
#include "mozilla/ClipboardContentAnalysisParent.h"
|
||||||
#include "mozilla/BasePrincipal.h"
|
#include "mozilla/BasePrincipal.h"
|
||||||
#include "mozilla/BenchmarkStorageParent.h"
|
#include "mozilla/BenchmarkStorageParent.h"
|
||||||
#include "mozilla/Casting.h"
|
#include "mozilla/Casting.h"
|
||||||
@@ -1114,6 +1115,65 @@ static nsIDocShell* GetOpenerDocShellHelper(Element* aFrameElement) {
|
|||||||
return docShell;
|
return docShell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult ContentParent::RecvCreateClipboardContentAnalysis() {
|
||||||
|
Endpoint<PClipboardContentAnalysisParent> parentEndpoint;
|
||||||
|
Endpoint<PClipboardContentAnalysisChild> childEndpoint;
|
||||||
|
|
||||||
|
if (mClipboardContentAnalysisCreated) {
|
||||||
|
return IPC_FAIL(this, "ClipboardContentAnalysisParent already created");
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
rv = PClipboardContentAnalysis::CreateEndpoints(
|
||||||
|
base::GetCurrentProcId(), OtherPid(), &parentEndpoint, &childEndpoint);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return IPC_FAIL(this, "CreateEndpoints failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mClipboardContentAnalysisThread) {
|
||||||
|
rv = NS_NewNamedThread("BkgrndClipboard",
|
||||||
|
getter_AddRefs(mClipboardContentAnalysisThread));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return IPC_FAIL(this, "NS_NewNamedThread failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<ContentParent> contentParent = this;
|
||||||
|
// Bind the new endpoint to the backgroundClipboardContentAnalysis thread,
|
||||||
|
// then send them from the main thread.
|
||||||
|
rv = NS_DispatchToThreadQueue(
|
||||||
|
NS_NewRunnableFunction(
|
||||||
|
"Create ClipboardContentAnalysisParent",
|
||||||
|
[contentParent = std::move(contentParent),
|
||||||
|
parentEndpoint = std::move(parentEndpoint),
|
||||||
|
childEndpoint = std::move(childEndpoint)]() mutable {
|
||||||
|
RefPtr<ClipboardContentAnalysisParent> parentActor =
|
||||||
|
new ClipboardContentAnalysisParent();
|
||||||
|
parentEndpoint.Bind(parentActor, nullptr);
|
||||||
|
DebugOnly<nsresult> rv = NS_DispatchToMainThread(
|
||||||
|
NS_NewRunnableFunction(
|
||||||
|
"SendInitClipboardContentAnalysis",
|
||||||
|
[contentParent = std::move(contentParent),
|
||||||
|
childEndpoint = std::move(childEndpoint)]() mutable {
|
||||||
|
DebugOnly<bool> success =
|
||||||
|
contentParent->SendInitClipboardContentAnalysis(
|
||||||
|
std::move(childEndpoint));
|
||||||
|
MOZ_ASSERT(success,
|
||||||
|
"SendInitClipboardContentAnalysis failed");
|
||||||
|
}),
|
||||||
|
0);
|
||||||
|
MOZ_ASSERT(NS_SUCCEEDED(rv),
|
||||||
|
"Failed to dispatch "
|
||||||
|
"SendInitClipboardContentAnalysis");
|
||||||
|
}),
|
||||||
|
mClipboardContentAnalysisThread, EventQueuePriority::Normal);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return IPC_FAIL(this, "NS_DispatchToThreadQueue failed");
|
||||||
|
}
|
||||||
|
mClipboardContentAnalysisCreated = true;
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult ContentParent::RecvCreateGMPService() {
|
mozilla::ipc::IPCResult ContentParent::RecvCreateGMPService() {
|
||||||
Endpoint<PGMPServiceParent> parent;
|
Endpoint<PGMPServiceParent> parent;
|
||||||
Endpoint<PGMPServiceChild> child;
|
Endpoint<PGMPServiceChild> child;
|
||||||
@@ -2531,6 +2591,7 @@ ContentParent::ContentParent(const nsACString& aRemoteType)
|
|||||||
mIsInputPriorityEventEnabled(false),
|
mIsInputPriorityEventEnabled(false),
|
||||||
mIsInPool(false),
|
mIsInPool(false),
|
||||||
mGMPCreated(false),
|
mGMPCreated(false),
|
||||||
|
mClipboardContentAnalysisCreated(false),
|
||||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||||
mBlockShutdownCalled(false),
|
mBlockShutdownCalled(false),
|
||||||
#endif
|
#endif
|
||||||
@@ -3115,10 +3176,8 @@ mozilla::ipc::IPCResult ContentParent::RecvSetClipboard(
|
|||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
/* static */ Result<nsCOMPtr<nsITransferable>, nsresult>
|
||||||
|
ContentParent::CreateClipboardTransferable(const nsTArray<nsCString>& aTypes) {
|
||||||
static Result<nsCOMPtr<nsITransferable>, nsresult> CreateTransferable(
|
|
||||||
const nsTArray<nsCString>& aTypes) {
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
nsCOMPtr<nsITransferable> trans =
|
nsCOMPtr<nsITransferable> trans =
|
||||||
do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
|
do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
|
||||||
@@ -3141,8 +3200,6 @@ static Result<nsCOMPtr<nsITransferable>, nsresult> CreateTransferable(
|
|||||||
return std::move(trans);
|
return std::move(trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
mozilla::ipc::IPCResult ContentParent::RecvGetClipboard(
|
mozilla::ipc::IPCResult ContentParent::RecvGetClipboard(
|
||||||
nsTArray<nsCString>&& aTypes, const int32_t& aWhichClipboard,
|
nsTArray<nsCString>&& aTypes, const int32_t& aWhichClipboard,
|
||||||
const MaybeDiscarded<WindowContext>& aRequestingWindowContext,
|
const MaybeDiscarded<WindowContext>& aRequestingWindowContext,
|
||||||
@@ -3171,7 +3228,7 @@ mozilla::ipc::IPCResult ContentParent::RecvGetClipboard(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create transferable
|
// Create transferable
|
||||||
auto result = CreateTransferable(aTypes);
|
auto result = CreateClipboardTransferable(aTypes);
|
||||||
if (result.isErr()) {
|
if (result.isErr()) {
|
||||||
*aTransferableDataOrError = result.unwrapErr();
|
*aTransferableDataOrError = result.unwrapErr();
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "mozilla/MemoryReportingProcess.h"
|
#include "mozilla/MemoryReportingProcess.h"
|
||||||
#include "mozilla/MozPromise.h"
|
#include "mozilla/MozPromise.h"
|
||||||
#include "mozilla/RecursiveMutex.h"
|
#include "mozilla/RecursiveMutex.h"
|
||||||
|
#include "mozilla/Result.h"
|
||||||
#include "mozilla/StaticPtr.h"
|
#include "mozilla/StaticPtr.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
@@ -44,6 +45,7 @@
|
|||||||
#include "nsIInterfaceRequestor.h"
|
#include "nsIInterfaceRequestor.h"
|
||||||
#include "nsIObserver.h"
|
#include "nsIObserver.h"
|
||||||
#include "nsIRemoteTab.h"
|
#include "nsIRemoteTab.h"
|
||||||
|
#include "nsITransferable.h"
|
||||||
#include "nsIDOMGeoPositionCallback.h"
|
#include "nsIDOMGeoPositionCallback.h"
|
||||||
#include "nsIDOMGeoPositionErrorCallback.h"
|
#include "nsIDOMGeoPositionErrorCallback.h"
|
||||||
#include "nsRefPtrHashtable.h"
|
#include "nsRefPtrHashtable.h"
|
||||||
@@ -228,6 +230,12 @@ class ContentParent final : public PContentParent,
|
|||||||
hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND,
|
hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND,
|
||||||
bool aPreferUsed = false, uint64_t aBrowserId = 0);
|
bool aPreferUsed = false, uint64_t aBrowserId = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an nsITransferable with the specified data flavor types.
|
||||||
|
*/
|
||||||
|
static mozilla::Result<nsCOMPtr<nsITransferable>, nsresult>
|
||||||
|
CreateClipboardTransferable(const nsTArray<nsCString>& aTypes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronously wait for this content process to finish launching, such that
|
* Asynchronously wait for this content process to finish launching, such that
|
||||||
* the ContentParent actor is ready for IPC.
|
* the ContentParent actor is ready for IPC.
|
||||||
@@ -343,6 +351,7 @@ class ContentParent final : public PContentParent,
|
|||||||
// been updated and so full reflows are in order.
|
// been updated and so full reflows are in order.
|
||||||
static void NotifyUpdatedFonts(bool aFullRebuild);
|
static void NotifyUpdatedFonts(bool aFullRebuild);
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult RecvCreateClipboardContentAnalysis();
|
||||||
mozilla::ipc::IPCResult RecvCreateGMPService();
|
mozilla::ipc::IPCResult RecvCreateGMPService();
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ContentParent, nsIObserver)
|
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ContentParent, nsIObserver)
|
||||||
@@ -1510,6 +1519,9 @@ class ContentParent final : public PContentParent,
|
|||||||
|
|
||||||
// True if we already created a GMP service.
|
// True if we already created a GMP service.
|
||||||
uint8_t mGMPCreated : 1;
|
uint8_t mGMPCreated : 1;
|
||||||
|
// True if we already created the
|
||||||
|
// ClipboardContentAnalysis actor
|
||||||
|
uint8_t mClipboardContentAnalysisCreated : 1;
|
||||||
|
|
||||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||||
bool mBlockShutdownCalled;
|
bool mBlockShutdownCalled;
|
||||||
@@ -1590,6 +1602,8 @@ class ContentParent final : public PContentParent,
|
|||||||
|
|
||||||
bool mIsSignaledImpendingShutdown = false;
|
bool mIsSignaledImpendingShutdown = false;
|
||||||
bool mIsNotifiedShutdownSuccess = false;
|
bool mIsNotifiedShutdownSuccess = false;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIThread> mClipboardContentAnalysisThread;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_DEFINE_STATIC_IID_ACCESSOR(ContentParent, NS_CONTENTPARENT_IID)
|
NS_DEFINE_STATIC_IID_ACCESSOR(ContentParent, NS_CONTENTPARENT_IID)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
include protocol PBackgroundStarter;
|
include protocol PBackgroundStarter;
|
||||||
include protocol PBrowser;
|
include protocol PBrowser;
|
||||||
|
include protocol PClipboardContentAnalysis;
|
||||||
include protocol PClipboardReadRequest;
|
include protocol PClipboardReadRequest;
|
||||||
include protocol PClipboardWriteRequest;
|
include protocol PClipboardWriteRequest;
|
||||||
include protocol PCompositorManager;
|
include protocol PCompositorManager;
|
||||||
@@ -578,6 +579,7 @@ child:
|
|||||||
async InitGMPService(Endpoint<PGMPServiceChild> service);
|
async InitGMPService(Endpoint<PGMPServiceChild> service);
|
||||||
async InitProcessHangMonitor(Endpoint<PProcessHangMonitorChild> hangMonitor);
|
async InitProcessHangMonitor(Endpoint<PProcessHangMonitorChild> hangMonitor);
|
||||||
async InitProfiler(Endpoint<PProfilerChild> aEndpoint);
|
async InitProfiler(Endpoint<PProfilerChild> aEndpoint);
|
||||||
|
async InitClipboardContentAnalysis(Endpoint<PClipboardContentAnalysisChild> aEndpoint);
|
||||||
|
|
||||||
// Give the content process its endpoints to the compositor.
|
// Give the content process its endpoints to the compositor.
|
||||||
async InitRendering(
|
async InitRendering(
|
||||||
@@ -1088,6 +1090,8 @@ parent:
|
|||||||
|
|
||||||
async CreateGMPService();
|
async CreateGMPService();
|
||||||
|
|
||||||
|
async CreateClipboardContentAnalysis();
|
||||||
|
|
||||||
async InitStreamFilter(uint64_t channelId, nsString addonId)
|
async InitStreamFilter(uint64_t channelId, nsString addonId)
|
||||||
returns (Endpoint<PStreamFilterChild> aEndpoint);
|
returns (Endpoint<PStreamFilterChild> aEndpoint);
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ description = Only used by gtests
|
|||||||
description = Only used by gtests
|
description = Only used by gtests
|
||||||
|
|
||||||
# Clipboard
|
# Clipboard
|
||||||
|
[PClipboardContentAnalysis::GetClipboard]
|
||||||
|
description = Legacy synchronous clipboard API
|
||||||
[PContent::GetClipboard]
|
[PContent::GetClipboard]
|
||||||
description = Legacy synchronous clipboard API
|
description = Legacy synchronous clipboard API
|
||||||
[PContent::ClipboardHasType]
|
[PContent::ClipboardHasType]
|
||||||
|
|||||||
14
widget/ClipboardContentAnalysisChild.cpp
Normal file
14
widget/ClipboardContentAnalysisChild.cpp
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#include "ClipboardContentAnalysisChild.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
StaticRefPtr<ClipboardContentAnalysisChild>
|
||||||
|
ClipboardContentAnalysisChild::sSingleton;
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
39
widget/ClipboardContentAnalysisChild.h
Normal file
39
widget/ClipboardContentAnalysisChild.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* 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 MOZILLA_WIDGET_CLIPBOARDCONTENTANALYSISCHILD_H_
|
||||||
|
#define MOZILLA_WIDGET_CLIPBOARDCONTENTANALYSISCHILD_H_
|
||||||
|
|
||||||
|
#include "mozilla/ipc/Endpoint.h"
|
||||||
|
#include "mozilla/PClipboardContentAnalysisChild.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
class ClipboardContentAnalysisChild final
|
||||||
|
: public PClipboardContentAnalysisChild {
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ClipboardContentAnalysisChild, override)
|
||||||
|
|
||||||
|
static bool Create(Endpoint<PClipboardContentAnalysisChild>&& aEndpoint) {
|
||||||
|
MOZ_ASSERT(!sSingleton);
|
||||||
|
sSingleton = new ClipboardContentAnalysisChild();
|
||||||
|
DebugOnly<bool> success = aEndpoint.Bind(sSingleton);
|
||||||
|
MOZ_ASSERT(success);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static ClipboardContentAnalysisChild* GetSingleton() { return sSingleton; }
|
||||||
|
void ActorDestroy(ActorDestroyReason aReason) override final {
|
||||||
|
// There's only one singleton, so remove our reference to it.
|
||||||
|
sSingleton = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend PClipboardContentAnalysisChild;
|
||||||
|
ClipboardContentAnalysisChild() { MOZ_ASSERT(XRE_IsContentProcess()); }
|
||||||
|
~ClipboardContentAnalysisChild() = default;
|
||||||
|
static StaticRefPtr<ClipboardContentAnalysisChild> sSingleton;
|
||||||
|
};
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // MOZILLA_WIDGET_CLIPBOARDCONTENTANALYSISCHILD_H_
|
||||||
165
widget/ClipboardContentAnalysisParent.cpp
Normal file
165
widget/ClipboardContentAnalysisParent.cpp
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#include "ContentAnalysis.h"
|
||||||
|
#include "mozilla/ClipboardContentAnalysisParent.h"
|
||||||
|
#include "mozilla/dom/ContentParent.h"
|
||||||
|
#include "mozilla/dom/WindowGlobalParent.h"
|
||||||
|
#include "mozilla/Maybe.h"
|
||||||
|
#include "mozilla/Variant.h"
|
||||||
|
#include "mozilla/SpinEventLoopUntil.h"
|
||||||
|
#include "nsBaseClipboard.h"
|
||||||
|
#include "nsIClipboard.h"
|
||||||
|
#include "nsID.h"
|
||||||
|
#include "nsITransferable.h"
|
||||||
|
#include "nsWidgetsCID.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
|
||||||
|
|
||||||
|
ipc::IPCResult ClipboardContentAnalysisParent::RecvGetClipboard(
|
||||||
|
nsTArray<nsCString>&& aTypes, const int32_t& aWhichClipboard,
|
||||||
|
const uint64_t& aRequestingWindowContextId,
|
||||||
|
IPCTransferableDataOrError* aTransferableDataOrError) {
|
||||||
|
// The whole point of having this actor is that it runs on a background thread
|
||||||
|
// and so waiting for the content analysis result won't cause the main thread
|
||||||
|
// to use SpinEventLoopUntil() which can cause a shutdownhang per bug 1901197.
|
||||||
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
|
RefPtr<nsIThread> actorThread = NS_GetCurrentThread();
|
||||||
|
NS_ASSERTION(actorThread, "NS_GetCurrentThread() should not fail");
|
||||||
|
// Ideally this would be a Maybe<Result>, but Result<> doesn't have a way to
|
||||||
|
// get a reference to the IPCTransferableData inside it which makes it awkward
|
||||||
|
// to use in this case.
|
||||||
|
mozilla::Maybe<mozilla::Variant<IPCTransferableData, nsresult>>
|
||||||
|
maybeTransferableResult;
|
||||||
|
std::atomic<bool> transferableResultSet = false;
|
||||||
|
|
||||||
|
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||||
|
__func__, [actorThread, aTypes = std::move(aTypes), aWhichClipboard,
|
||||||
|
aRequestingWindowContextId, &maybeTransferableResult,
|
||||||
|
&transferableResultSet]() {
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
// Make sure we reply to the actor thread on error.
|
||||||
|
auto sendRv = MakeScopeExit([&]() {
|
||||||
|
maybeTransferableResult = Some(AsVariant(rv));
|
||||||
|
transferableResultSet = true;
|
||||||
|
// Wake up the actor thread so SpinEventLoopUntil() can check its
|
||||||
|
// condition again.
|
||||||
|
NS_DispatchToThreadQueue(NS_NewRunnableFunction(__func__, []() {}),
|
||||||
|
actorThread, EventQueuePriority::Normal);
|
||||||
|
});
|
||||||
|
nsCOMPtr<nsIClipboard> clipboard;
|
||||||
|
RefPtr<dom::WindowGlobalParent> window =
|
||||||
|
dom::WindowGlobalParent::GetByInnerWindowId(
|
||||||
|
aRequestingWindowContextId);
|
||||||
|
// We expect content processes to always pass a non-null window so
|
||||||
|
// Content Analysis can analyze it. (if Content Analysis is
|
||||||
|
// active) There may be some cases when a window is closing, etc.,
|
||||||
|
// in which case returning no clipboard content should not be a
|
||||||
|
// problem.
|
||||||
|
if (!window) {
|
||||||
|
rv = NS_ERROR_FAILURE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->IsDiscarded()) {
|
||||||
|
NS_WARNING(
|
||||||
|
"discarded window passed to RecvGetClipboard(); returning "
|
||||||
|
"no clipboard "
|
||||||
|
"content");
|
||||||
|
rv = NS_ERROR_FAILURE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve clipboard
|
||||||
|
clipboard = do_GetService(kCClipboardCID, &rv);
|
||||||
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
|
|
||||||
|
auto transferableToCheck =
|
||||||
|
dom::ContentParent::CreateClipboardTransferable(aTypes);
|
||||||
|
if (transferableToCheck.isErr()) {
|
||||||
|
rv = transferableToCheck.unwrapErr();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass nullptr for the window here because we will be doing
|
||||||
|
// content analysis ourselves asynchronously (so it doesn't block
|
||||||
|
// main thread we're running on now)
|
||||||
|
nsCOMPtr transferable = transferableToCheck.unwrap();
|
||||||
|
rv = clipboard->GetData(transferable, aWhichClipboard, nullptr);
|
||||||
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
|
|
||||||
|
auto contentAnalysisCallback =
|
||||||
|
mozilla::MakeRefPtr<mozilla::contentanalysis::ContentAnalysis::
|
||||||
|
SafeContentAnalysisResultCallback>(
|
||||||
|
[actorThread, transferable, aRequestingWindowContextId,
|
||||||
|
&maybeTransferableResult, &transferableResultSet](
|
||||||
|
RefPtr<nsIContentAnalysisResult>&& aResult) {
|
||||||
|
bool shouldAllow = aResult->GetShouldAllowContent();
|
||||||
|
if (!shouldAllow) {
|
||||||
|
maybeTransferableResult =
|
||||||
|
Some(AsVariant(NS_ERROR_CONTENT_BLOCKED));
|
||||||
|
} else {
|
||||||
|
IPCTransferableData transferableData;
|
||||||
|
RefPtr<dom::WindowGlobalParent> window =
|
||||||
|
dom::WindowGlobalParent::GetByInnerWindowId(
|
||||||
|
aRequestingWindowContextId);
|
||||||
|
if (!window && window->IsDiscarded()) {
|
||||||
|
maybeTransferableResult =
|
||||||
|
Some(AsVariant(NS_ERROR_UNEXPECTED));
|
||||||
|
} else {
|
||||||
|
maybeTransferableResult =
|
||||||
|
Some(AsVariant(IPCTransferableData()));
|
||||||
|
nsContentUtils::TransferableToIPCTransferableData(
|
||||||
|
transferable,
|
||||||
|
&(maybeTransferableResult.ref()
|
||||||
|
.as<IPCTransferableData>()),
|
||||||
|
true /* aInSyncMessage */,
|
||||||
|
window->BrowsingContext()->GetContentParent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
transferableResultSet = true;
|
||||||
|
|
||||||
|
// Setting maybeTransferableResult is done on the main thread
|
||||||
|
// instead of inside the runnable function here because some
|
||||||
|
// of the objects that can be inside a maybeTransferableResult
|
||||||
|
// are not thread-safe.
|
||||||
|
// Wake up the actor thread so SpinEventLoopUntil() can check
|
||||||
|
// its condition again.
|
||||||
|
NS_DispatchToThreadQueue(
|
||||||
|
NS_NewRunnableFunction(__func__, []() {}), actorThread,
|
||||||
|
EventQueuePriority::Normal);
|
||||||
|
});
|
||||||
|
|
||||||
|
contentanalysis::ContentAnalysis::CheckClipboardContentAnalysis(
|
||||||
|
static_cast<nsBaseClipboard*>(clipboard.get()), window,
|
||||||
|
transferable, aWhichClipboard, contentAnalysisCallback);
|
||||||
|
|
||||||
|
sendRv.release();
|
||||||
|
}));
|
||||||
|
|
||||||
|
mozilla::SpinEventLoopUntil(
|
||||||
|
"Waiting for clipboard and content analysis"_ns,
|
||||||
|
[&transferableResultSet] { return transferableResultSet.load(); });
|
||||||
|
|
||||||
|
NS_ASSERTION(maybeTransferableResult.isSome(),
|
||||||
|
"maybeTransferableResult should be set when "
|
||||||
|
"transferableResultSet is true!");
|
||||||
|
auto& transferableResult = *maybeTransferableResult;
|
||||||
|
if (transferableResult.is<nsresult>()) {
|
||||||
|
*aTransferableDataOrError = transferableResult.as<nsresult>();
|
||||||
|
NS_WARNING(
|
||||||
|
nsPrintfCString("ClipboardContentAnalysisParent::"
|
||||||
|
"RecvGetClipboard got error %x",
|
||||||
|
static_cast<int>(transferableResult.as<nsresult>()))
|
||||||
|
.get());
|
||||||
|
} else {
|
||||||
|
*aTransferableDataOrError =
|
||||||
|
std::move(transferableResult.as<IPCTransferableData>());
|
||||||
|
}
|
||||||
|
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
} // namespace mozilla
|
||||||
29
widget/ClipboardContentAnalysisParent.h
Normal file
29
widget/ClipboardContentAnalysisParent.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* 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 MOZILLA_WIDGET_CLIPBOARDCONTENTANALYSISPARENT_H_
|
||||||
|
#define MOZILLA_WIDGET_CLIPBOARDCONTENTANALYSISPARENT_H_
|
||||||
|
|
||||||
|
#include "mozilla/PClipboardContentAnalysisParent.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
class ClipboardContentAnalysisParent final
|
||||||
|
: public PClipboardContentAnalysisParent {
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_REFCOUNTING(ClipboardContentAnalysisParent, override)
|
||||||
|
|
||||||
|
private:
|
||||||
|
~ClipboardContentAnalysisParent() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ipc::IPCResult RecvGetClipboard(
|
||||||
|
nsTArray<nsCString>&& aTypes, const int32_t& aWhichClipboard,
|
||||||
|
const uint64_t& aRequestingWindowContextId,
|
||||||
|
IPCTransferableDataOrError* aTransferableDataOrError);
|
||||||
|
};
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // MOZILLA_WIDGET_CLIPBOARDCONTENTANALYSISPARENT_H_
|
||||||
24
widget/PClipboardContentAnalysis.ipdl
Normal file
24
widget/PClipboardContentAnalysis.ipdl
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/* -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
include IPCTransferable;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
[ChildProc=Content]
|
||||||
|
sync protocol PClipboardContentAnalysis
|
||||||
|
{
|
||||||
|
parent:
|
||||||
|
// Given a list of supported types, returns the clipboard data for the
|
||||||
|
// first type that matches.
|
||||||
|
// aRequestingWindowContext is the window that is requesting the clipboard,
|
||||||
|
// which is used for content analysis.
|
||||||
|
sync GetClipboard(nsCString[] aTypes, int32_t aWhichClipboard,
|
||||||
|
uint64_t aRequestingWindowContextId)
|
||||||
|
returns (IPCTransferableDataOrError transferableDataOrError);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -166,6 +166,8 @@ EXPORTS += [
|
|||||||
|
|
||||||
EXPORTS.mozilla += [
|
EXPORTS.mozilla += [
|
||||||
"BasicEvents.h",
|
"BasicEvents.h",
|
||||||
|
"ClipboardContentAnalysisChild.h",
|
||||||
|
"ClipboardContentAnalysisParent.h",
|
||||||
"ClipboardReadRequestChild.h",
|
"ClipboardReadRequestChild.h",
|
||||||
"ClipboardReadRequestParent.h",
|
"ClipboardReadRequestParent.h",
|
||||||
"ClipboardWriteRequestChild.h",
|
"ClipboardWriteRequestChild.h",
|
||||||
@@ -217,6 +219,8 @@ EXPORTS.mozilla.widget += [
|
|||||||
]
|
]
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
|
"ClipboardContentAnalysisChild.cpp",
|
||||||
|
"ClipboardContentAnalysisParent.cpp",
|
||||||
"ClipboardReadRequestParent.cpp",
|
"ClipboardReadRequestParent.cpp",
|
||||||
"ClipboardWriteRequestChild.cpp",
|
"ClipboardWriteRequestChild.cpp",
|
||||||
"ClipboardWriteRequestParent.cpp",
|
"ClipboardWriteRequestParent.cpp",
|
||||||
@@ -377,6 +381,7 @@ else:
|
|||||||
|
|
||||||
IPDL_SOURCES += [
|
IPDL_SOURCES += [
|
||||||
"LookAndFeelTypes.ipdlh",
|
"LookAndFeelTypes.ipdlh",
|
||||||
|
"PClipboardContentAnalysis.ipdl",
|
||||||
"PClipboardReadRequest.ipdl",
|
"PClipboardReadRequest.ipdl",
|
||||||
"PClipboardWriteRequest.ipdl",
|
"PClipboardWriteRequest.ipdl",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -7,15 +7,19 @@
|
|||||||
#if defined(ACCESSIBILITY) && defined(XP_WIN)
|
#if defined(ACCESSIBILITY) && defined(XP_WIN)
|
||||||
# include "mozilla/a11y/Compatibility.h"
|
# include "mozilla/a11y/Compatibility.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "mozilla/ClipboardContentAnalysisChild.h"
|
||||||
#include "mozilla/ClipboardReadRequestChild.h"
|
#include "mozilla/ClipboardReadRequestChild.h"
|
||||||
#include "mozilla/ClipboardWriteRequestChild.h"
|
#include "mozilla/ClipboardWriteRequestChild.h"
|
||||||
|
#include "mozilla/Components.h"
|
||||||
#include "mozilla/dom/ContentChild.h"
|
#include "mozilla/dom/ContentChild.h"
|
||||||
#include "mozilla/net/CookieJarSettings.h"
|
#include "mozilla/net/CookieJarSettings.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/dom/WindowGlobalChild.h"
|
#include "mozilla/dom/WindowGlobalChild.h"
|
||||||
#include "mozilla/Unused.h"
|
#include "mozilla/Unused.h"
|
||||||
|
#include "mozilla/SpinEventLoopUntil.h"
|
||||||
#include "nsArrayUtils.h"
|
#include "nsArrayUtils.h"
|
||||||
#include "nsBaseClipboard.h"
|
#include "nsBaseClipboard.h"
|
||||||
|
#include "nsIContentAnalysis.h"
|
||||||
#include "nsISupportsPrimitives.h"
|
#include "nsISupportsPrimitives.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsComponentManagerUtils.h"
|
#include "nsComponentManagerUtils.h"
|
||||||
@@ -73,8 +77,29 @@ nsClipboardProxy::GetData(nsITransferable* aTransferable,
|
|||||||
aTransferable->FlavorsTransferableCanImport(types);
|
aTransferable->FlavorsTransferableCanImport(types);
|
||||||
|
|
||||||
IPCTransferableDataOrError transferableOrError;
|
IPCTransferableDataOrError transferableOrError;
|
||||||
ContentChild::GetSingleton()->SendGetClipboard(
|
nsCOMPtr<nsIContentAnalysis> contentAnalysis =
|
||||||
types, aWhichClipboard, aWindowContext, &transferableOrError);
|
mozilla::components::nsIContentAnalysis::Service();
|
||||||
|
Unused << NS_WARN_IF(!contentAnalysis);
|
||||||
|
bool contentAnalysisMightBeActive = false;
|
||||||
|
if (contentAnalysis) {
|
||||||
|
contentAnalysis->GetMightBeActive(&contentAnalysisMightBeActive);
|
||||||
|
}
|
||||||
|
if (MOZ_UNLIKELY(contentAnalysisMightBeActive)) {
|
||||||
|
if (!ClipboardContentAnalysisChild::GetSingleton()) {
|
||||||
|
if (!ContentChild::GetSingleton()->SendCreateClipboardContentAnalysis()) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
mozilla::SpinEventLoopUntil(
|
||||||
|
"Wait for ClipboardContentAnalysisChild creation"_ns,
|
||||||
|
[] { return ClipboardContentAnalysisChild::GetSingleton(); });
|
||||||
|
}
|
||||||
|
ClipboardContentAnalysisChild::GetSingleton()->SendGetClipboard(
|
||||||
|
types, aWhichClipboard, aWindowContext->InnerWindowId(),
|
||||||
|
&transferableOrError);
|
||||||
|
} else {
|
||||||
|
ContentChild::GetSingleton()->SendGetClipboard(
|
||||||
|
types, aWhichClipboard, aWindowContext, &transferableOrError);
|
||||||
|
}
|
||||||
|
|
||||||
if (transferableOrError.type() == IPCTransferableDataOrError::Tnsresult) {
|
if (transferableOrError.type() == IPCTransferableDataOrError::Tnsresult) {
|
||||||
MOZ_ASSERT(NS_FAILED(transferableOrError.get_nsresult()));
|
MOZ_ASSERT(NS_FAILED(transferableOrError.get_nsresult()));
|
||||||
|
|||||||
Reference in New Issue
Block a user