Bug 1869868 part 2 - do not consult DLP when copy/pasting items in the same tab r=edgar,dlp-reviewers,credential-management-reviewers,handyman,sgalich

Differential Revision: https://phabricator.services.mozilla.com/D205744
This commit is contained in:
Greg Stoll 2024-04-15 12:10:46 +00:00
parent 8ee343bb45
commit 37d28f9cf5
25 changed files with 205 additions and 70 deletions

View file

@ -2175,7 +2175,10 @@ class nsContextMenu {
var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(
Ci.nsIClipboardHelper
);
clipboard.copyString(addresses);
clipboard.copyString(
addresses,
this.actor.manager.browsingContext.currentWindowGlobal
);
}
// Extract phone and put it on clipboard
@ -2195,7 +2198,10 @@ class nsContextMenu {
var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(
Ci.nsIClipboardHelper
);
clipboard.copyString(phone);
clipboard.copyString(
phone,
this.actor.manager.browsingContext.currentWindowGlobal
);
}
copyLink() {
@ -2204,7 +2210,10 @@ class nsContextMenu {
var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(
Ci.nsIClipboardHelper
);
clipboard.copyString(linkURL);
clipboard.copyString(
linkURL,
this.actor.manager.browsingContext.currentWindowGlobal
);
}
/**
@ -2220,7 +2229,10 @@ class nsContextMenu {
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(
Ci.nsIClipboardHelper
);
clipboard.copyString(strippedLinkURL);
clipboard.copyString(
strippedLinkURL,
this.actor.manager.browsingContext.currentWindowGlobal
);
}
}
@ -2458,7 +2470,10 @@ class nsContextMenu {
var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(
Ci.nsIClipboardHelper
);
clipboard.copyString(this.originalMediaURL);
clipboard.copyString(
this.originalMediaURL,
this.actor.manager.browsingContext.currentWindowGlobal
);
}
getImageText() {

View file

@ -160,7 +160,11 @@ export class AboutLoginsChild extends JSWindowActorChild {
}
#aboutLoginsCopyLoginDetail(detail) {
lazy.ClipboardHelper.copyString(detail, lazy.ClipboardHelper.Sensitive);
lazy.ClipboardHelper.copyString(
detail,
this.windowContext,
lazy.ClipboardHelper.Sensitive
);
}
#aboutLoginsCreateLogin(login) {

View file

@ -553,6 +553,7 @@ export var Policies = {
["IsPerUser", "is_per_user"],
["ShowBlockedResult", "show_blocked_result"],
["DefaultAllow", "default_allow"],
["BypassForSameTabOperations", "bypass_for_same_tab_operations"],
];
for (let pref of boolPrefs) {
if (pref[0] in param) {

View file

@ -267,6 +267,9 @@
},
"DefaultAllow": {
"type": "boolean"
},
"BypassForSameTabOperations": {
"type": "boolean"
}
}
},

View file

@ -332,7 +332,8 @@ static nsresult PutToClipboard(
rv = CreateTransferable(aEncodedDocumentWithContext, aDocument, transferable);
NS_ENSURE_SUCCESS(rv, rv);
rv = clipboard->SetData(transferable, nullptr, aClipboardID);
rv = clipboard->SetData(transferable, nullptr, aClipboardID,
aDocument.GetWindowContext());
NS_ENSURE_SUCCESS(rv, rv);
return rv;
@ -455,9 +456,9 @@ nsresult nsCopySupport::GetContents(const nsACString& aMimeType,
return docEncoder->EncodeToString(outdata);
}
nsresult nsCopySupport::ImageCopy(nsIImageLoadingContent* aImageElement,
nsILoadContext* aLoadContext,
int32_t aCopyFlags) {
nsresult nsCopySupport::ImageCopy(
nsIImageLoadingContent* aImageElement, nsILoadContext* aLoadContext,
int32_t aCopyFlags, mozilla::dom::WindowContext* aSettingWindowContext) {
nsresult rv;
nsCOMPtr<nsINode> imageNode = do_QueryInterface(aImageElement, &rv);
@ -527,11 +528,13 @@ nsresult nsCopySupport::ImageCopy(nsIImageLoadingContent* aImageElement,
// check whether the system supports the selection clipboard or not.
if (clipboard->IsClipboardTypeSupported(nsIClipboard::kSelectionClipboard)) {
// put the transferable on the clipboard
rv = clipboard->SetData(trans, nullptr, nsIClipboard::kSelectionClipboard);
rv = clipboard->SetData(trans, nullptr, nsIClipboard::kSelectionClipboard,
aSettingWindowContext);
NS_ENSURE_SUCCESS(rv, rv);
}
return clipboard->SetData(trans, nullptr, nsIClipboard::kGlobalClipboard);
return clipboard->SetData(trans, nullptr, nsIClipboard::kGlobalClipboard,
aSettingWindowContext);
}
static nsresult AppendString(nsITransferable* aTransferable,
@ -928,7 +931,12 @@ bool nsCopySupport::FireClipboardEvent(EventMessage aEventMessage,
NS_ENSURE_TRUE(transferable, false);
// put the transferable on the clipboard
nsresult rv = clipboard->SetData(transferable, nullptr, aClipboardType);
WindowContext* settingWindowContext = nullptr;
if (aPresShell && aPresShell->GetDocument()) {
settingWindowContext = aPresShell->GetDocument()->GetWindowContext();
}
nsresult rv = clipboard->SetData(transferable, nullptr, aClipboardType,
settingWindowContext);
if (NS_FAILED(rv)) {
return false;
}

View file

@ -23,6 +23,7 @@ class PresShell;
namespace dom {
class Document;
class Selection;
class WindowContext;
} // namespace dom
} // namespace mozilla
@ -46,7 +47,8 @@ class nsCopySupport {
mozilla::dom::Document* aDoc, nsAString& outdata);
static nsresult ImageCopy(nsIImageLoadingContent* aImageElement,
nsILoadContext* aLoadContext, int32_t aCopyFlags);
nsILoadContext* aLoadContext, int32_t aCopyFlags,
mozilla::dom::WindowContext* aSettingWindowContext);
// Get the selection as a transferable.
// @param aSelection Can be nullptr.

View file

@ -731,7 +731,8 @@ already_AddRefed<Promise> Clipboard::Write(
RefPtr<ClipboardWriteCallback> callback =
MakeRefPtr<ClipboardWriteCallback>(p, aData[0]);
nsresult rv = clipboard->AsyncSetData(nsIClipboard::kGlobalClipboard,
callback, getter_AddRefs(request));
owner->GetWindowContext(), callback,
getter_AddRefs(request));
if (NS_FAILED(rv)) {
p->MaybeReject(rv);
return p.forget();

View file

@ -3409,7 +3409,8 @@ void ContentParent::OnVarChanged(const GfxVarUpdate& aVar) {
}
mozilla::ipc::IPCResult ContentParent::RecvSetClipboard(
const IPCTransferable& aTransferable, const int32_t& aWhichClipboard) {
const IPCTransferable& aTransferable, const int32_t& aWhichClipboard,
const MaybeDiscarded<WindowContext>& aRequestingWindowContext) {
// aRequestingPrincipal is allowed to be nullptr here.
if (!ValidatePrincipal(aTransferable.requestingPrincipal(),
@ -3434,7 +3435,12 @@ mozilla::ipc::IPCResult ContentParent::RecvSetClipboard(
true /* aFilterUnknownFlavors */);
NS_ENSURE_SUCCESS(rv, IPC_OK());
clipboard->SetData(trans, nullptr, aWhichClipboard);
// OK if this is null
RefPtr<WindowGlobalParent> window;
if (!aRequestingWindowContext.IsDiscarded()) {
window = aRequestingWindowContext.get_canonical();
}
clipboard->SetData(trans, nullptr, aWhichClipboard, window);
return IPC_OK();
}
@ -3682,10 +3688,15 @@ mozilla::ipc::IPCResult ContentParent::RecvGetClipboardDataSnapshotSync(
already_AddRefed<PClipboardWriteRequestParent>
ContentParent::AllocPClipboardWriteRequestParent(
const int32_t& aClipboardType) {
const int32_t& aClipboardType,
const MaybeDiscarded<WindowContext>& aSettingWindowContext) {
WindowContext* settingWindowContext = nullptr;
if (!aSettingWindowContext.IsDiscarded()) {
settingWindowContext = aSettingWindowContext.get();
}
RefPtr<ClipboardWriteRequestParent> request =
MakeAndAddRef<ClipboardWriteRequestParent>(this);
request->Init(aClipboardType);
request->Init(aClipboardType, settingWindowContext);
return request.forget();
}

View file

@ -949,8 +949,9 @@ class ContentParent final : public PContentParent,
PBrowserParent* aBrowser,
const MaybeDiscarded<BrowsingContext>& aContext);
mozilla::ipc::IPCResult RecvSetClipboard(const IPCTransferable& aTransferable,
const int32_t& aWhichClipboard);
mozilla::ipc::IPCResult RecvSetClipboard(
const IPCTransferable& aTransferable, const int32_t& aWhichClipboard,
const MaybeDiscarded<WindowContext>& aRequestingWindowContext);
mozilla::ipc::IPCResult RecvGetClipboard(
nsTArray<nsCString>&& aTypes, const int32_t& aWhichClipboard,
@ -975,7 +976,9 @@ class ContentParent final : public PContentParent,
ClipboardReadRequestOrError* aRequestOrError);
already_AddRefed<PClipboardWriteRequestParent>
AllocPClipboardWriteRequestParent(const int32_t& aClipboardType);
AllocPClipboardWriteRequestParent(
const int32_t& aClipboardType,
const MaybeDiscarded<WindowContext>& aSettingWindowContext);
mozilla::ipc::IPCResult RecvGetIconForExtension(const nsACString& aFileExt,
const uint32_t& aIconSize,

View file

@ -1219,7 +1219,7 @@ parent:
// Places the items within dataTransfer on the clipboard.
async SetClipboard(IPCTransferable aTransferable,
int32_t aWhichClipboard);
int32_t aWhichClipboard, MaybeDiscardedWindowContext aRequestingWindowContext);
// Given a list of supported types, returns the clipboard data for the
// first type that matches.
@ -1252,8 +1252,12 @@ parent:
* and that the data will be sent over another IPC message once it is ready.
* @param aClipboardType
* The clipboard type defined in nsIClipboard.
* @param aSettingWindowContext
* The window context that is setting the clipboard, if any. This is used
* to possibly bypass Content Analysis if a set clipboard and get clipboard
* operation are done on the same page.
*/
async PClipboardWriteRequest(int32_t aClipboardType);
async PClipboardWriteRequest(int32_t aClipboardType, MaybeDiscardedWindowContext aSettingWindowContext);
sync GetIconForExtension(nsCString aFileExt, uint32_t aIconSize)
returns (uint8_t[] bits);

View file

@ -1265,7 +1265,7 @@ nsresult gfxUtils::EncodeSourceSurface(SourceSurface* aSurface,
nsCOMPtr<nsIClipboardHelper> clipboard(
do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
if (clipboard) {
clipboard->CopyString(NS_ConvertASCIItoUTF16(dataURI));
clipboard->CopyString(NS_ConvertASCIItoUTF16(dataURI), nullptr);
}
}
return NS_OK;

View file

@ -2426,7 +2426,7 @@ NS_IMETHODIMP nsDocumentViewer::CopyLinkLocation() {
NS_ENSURE_SUCCESS(rv, rv);
// copy the href onto the clipboard
return clipboard->CopyString(locationText);
return clipboard->CopyString(locationText, mDocument->GetWindowContext());
}
NS_IMETHODIMP nsDocumentViewer::CopyImage(int32_t aCopyFlags) {
@ -2436,7 +2436,8 @@ NS_IMETHODIMP nsDocumentViewer::CopyImage(int32_t aCopyFlags) {
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
nsCOMPtr<nsILoadContext> loadContext(mContainer);
return nsCopySupport::ImageCopy(node, loadContext, aCopyFlags);
return nsCopySupport::ImageCopy(node, loadContext, aCopyFlags,
mDocument->GetWindowContext());
}
NS_IMETHODIMP nsDocumentViewer::GetCopyable(bool* aCopyable) {

View file

@ -1211,6 +1211,13 @@
value: true
mirror: always
# Should Firefox bypass content analysis for pastes and drags whose source
# is the same tab?
- name: browser.contentanalysis.bypass_for_same_tab_operations
type: bool
value: false
mirror: always
# Content blocking for Enhanced Tracking Protection
- name: browser.contentblocking.database.enabled
type: bool

View file

@ -816,6 +816,7 @@ NS_IMETHODIMP ContentAnalysisResult::GetShouldAllowContent(
ALLOW_DUE_TO_CONTENT_ANALYSIS_NOT_ACTIVE ||
result == NoContentAnalysisResult::
ALLOW_DUE_TO_CONTEXT_EXEMPT_FROM_CONTENT_ANALYSIS ||
result == NoContentAnalysisResult::ALLOW_DUE_TO_SAME_TAB_SOURCE ||
result == NoContentAnalysisResult::ALLOW_DUE_TO_COULD_NOT_GET_DATA;
}
} else {

View file

@ -19,6 +19,7 @@ namespace contentanalysis {
enum class NoContentAnalysisResult : uint8_t {
ALLOW_DUE_TO_CONTENT_ANALYSIS_NOT_ACTIVE,
ALLOW_DUE_TO_CONTEXT_EXEMPT_FROM_CONTENT_ANALYSIS,
ALLOW_DUE_TO_SAME_TAB_SOURCE,
ALLOW_DUE_TO_COULD_NOT_GET_DATA,
DENY_DUE_TO_CANCELED,
DENY_DUE_TO_INVALID_JSON_RESPONSE,

View file

@ -26,6 +26,7 @@ const kClientSignaturePref = "client_signature";
const kPerUserPref = "is_per_user";
const kShowBlockedPref = "show_blocked_result";
const kDefaultAllowPref = "default_allow";
const kBypassForSameTabOperationsPref = "bypass_for_same_tab_operations";
const ca = Cc["@mozilla.org/contentanalysis;1"].getService(
Ci.nsIContentAnalysis
@ -88,6 +89,7 @@ add_task(async function test_ca_enterprise_config() {
IsPerUser: true,
ShowBlockedResult: false,
DefaultAllow: true,
BypassForSameTabOperations: true,
},
},
});
@ -139,6 +141,13 @@ add_task(async function test_ca_enterprise_config() {
true,
"default allow match"
);
is(
Services.prefs.getBoolPref(
"browser.contentanalysis." + kBypassForSameTabOperationsPref
),
true,
"bypass for same tab operations match"
);
PoliciesPrefTracker.stop();
});

View file

@ -27,7 +27,9 @@ ClipboardWriteRequestParent::ClipboardWriteRequestParent(
ClipboardWriteRequestParent::~ClipboardWriteRequestParent() = default;
nsresult ClipboardWriteRequestParent::Init(const int32_t& aClipboardType) {
nsresult ClipboardWriteRequestParent::Init(
const int32_t& aClipboardType,
mozilla::dom::WindowContext* aSettingWindowContext) {
nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID));
if (!clipboard) {
Unused << PClipboardWriteRequestParent::Send__delete__(this,
@ -35,8 +37,9 @@ nsresult ClipboardWriteRequestParent::Init(const int32_t& aClipboardType) {
return NS_ERROR_FAILURE;
}
nsresult rv = clipboard->AsyncSetData(aClipboardType, this,
getter_AddRefs(mAsyncSetClipboardData));
nsresult rv =
clipboard->AsyncSetData(aClipboardType, aSettingWindowContext, this,
getter_AddRefs(mAsyncSetClipboardData));
if (NS_FAILED(rv)) {
Unused << PClipboardWriteRequestParent::Send__delete__(this, rv);
return rv;

View file

@ -27,7 +27,8 @@ class ClipboardWriteRequestParent final
explicit ClipboardWriteRequestParent(ContentParent* aManager);
nsresult Init(const int32_t& aClipboardType);
nsresult Init(const int32_t& aClipboardType,
mozilla::dom::WindowContext* aSettingWindowContext);
IPCResult RecvSetData(const IPCTransferable& aTransferable);
IPCResult Recv__delete__(nsresult aReason);

View file

@ -211,9 +211,11 @@ NS_IMPL_ISUPPORTS(nsBaseClipboard::AsyncSetClipboardData,
nsBaseClipboard::AsyncSetClipboardData::AsyncSetClipboardData(
int32_t aClipboardType, nsBaseClipboard* aClipboard,
mozilla::dom::WindowContext* aSettingWindowContext,
nsIAsyncClipboardRequestCallback* aCallback)
: mClipboardType(aClipboardType),
mClipboard(aClipboard),
mWindowContext(aSettingWindowContext),
mCallback(aCallback) {
MOZ_ASSERT(mClipboard);
MOZ_ASSERT(
@ -247,7 +249,8 @@ nsBaseClipboard::AsyncSetClipboardData::SetData(nsITransferable* aTransferable,
RefPtr<AsyncSetClipboardData> request =
std::move(mClipboard->mPendingWriteRequests[mClipboardType]);
nsresult rv = mClipboard->SetData(aTransferable, aOwner, mClipboardType);
nsresult rv = mClipboard->SetData(aTransferable, aOwner, mClipboardType,
mWindowContext);
MaybeNotifyCallback(rv);
return rv;
@ -292,7 +295,8 @@ void nsBaseClipboard::RejectPendingAsyncSetDataRequestIfAny(
}
NS_IMETHODIMP nsBaseClipboard::AsyncSetData(
int32_t aWhichClipboard, nsIAsyncClipboardRequestCallback* aCallback,
int32_t aWhichClipboard, mozilla::dom::WindowContext* aSettingWindowContext,
nsIAsyncClipboardRequestCallback* aCallback,
nsIAsyncSetClipboardData** _retval) {
MOZ_CLIPBOARD_LOG("%s: clipboard=%d", __FUNCTION__, aWhichClipboard);
@ -308,8 +312,8 @@ NS_IMETHODIMP nsBaseClipboard::AsyncSetData(
// Create a new AsyncSetClipboardData.
RefPtr<AsyncSetClipboardData> request =
mozilla::MakeRefPtr<AsyncSetClipboardData>(aWhichClipboard, this,
aCallback);
mozilla::MakeRefPtr<AsyncSetClipboardData>(
aWhichClipboard, this, aSettingWindowContext, aCallback);
mPendingWriteRequests[aWhichClipboard] = request;
request.forget(_retval);
return NS_OK;
@ -408,7 +412,7 @@ nsBaseClipboard::CheckClipboardContentAnalysisAsFile(
void nsBaseClipboard::CheckClipboardContentAnalysis(
mozilla::dom::WindowGlobalParent* aWindow, nsITransferable* aTransferable,
SafeContentAnalysisResultCallback* aResolver) {
int32_t aClipboardType, SafeContentAnalysisResultCallback* aResolver) {
using namespace mozilla::contentanalysis;
// Content analysis is only needed if an outside webpage has access to
@ -441,8 +445,24 @@ void nsBaseClipboard::CheckClipboardContentAnalysis(
return;
}
nsCOMPtr<nsIURI> currentURI = aWindow->Canonical()->GetDocumentURI();
uint64_t innerWindowId = aWindow->InnerWindowId();
if (mozilla::StaticPrefs::
browser_contentanalysis_bypass_for_same_tab_operations()) {
const auto* clipboardCache = GetClipboardCacheIfValid(aClipboardType);
if (clipboardCache) {
if (clipboardCache->GetInnerWindowId().isSome() &&
*(clipboardCache->GetInnerWindowId()) == innerWindowId) {
// If the same page copied this data to the clipboard (and the above
// preference is set) we can skip content analysis and immediately allow
// this.
aResolver->Callback(ContentAnalysisResult::FromNoResult(
NoContentAnalysisResult::ALLOW_DUE_TO_SAME_TAB_SOURCE));
return;
}
}
}
nsCOMPtr<nsIURI> currentURI = aWindow->Canonical()->GetDocumentURI();
nsTArray<nsCString> flavors;
rv = aTransferable->FlavorsTransferableCanExport(flavors);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -482,7 +502,7 @@ void nsBaseClipboard::CheckClipboardContentAnalysis(
bool nsBaseClipboard::CheckClipboardContentAnalysisSync(
mozilla::dom::WindowGlobalParent* aWindow,
const nsCOMPtr<nsITransferable>& trans) {
const nsCOMPtr<nsITransferable>& trans, int32_t aClipboardType) {
bool requestDone = false;
RefPtr<nsIContentAnalysisResult> result;
auto callback = mozilla::MakeRefPtr<SafeContentAnalysisResultCallback>(
@ -490,7 +510,7 @@ bool nsBaseClipboard::CheckClipboardContentAnalysisSync(
result = std::move(aResult);
requestDone = true;
});
CheckClipboardContentAnalysis(aWindow, trans, callback);
CheckClipboardContentAnalysis(aWindow, trans, aClipboardType, callback);
mozilla::SpinEventLoopUntil("CheckClipboardContentAnalysisSync"_ns,
[&requestDone]() -> bool { return requestDone; });
return result->GetShouldAllowContent();
@ -527,9 +547,9 @@ NS_IMPL_ISUPPORTS(nsBaseClipboard, nsIClipboard)
* Sets the transferable object
*
*/
NS_IMETHODIMP nsBaseClipboard::SetData(nsITransferable* aTransferable,
nsIClipboardOwner* aOwner,
int32_t aWhichClipboard) {
NS_IMETHODIMP nsBaseClipboard::SetData(
nsITransferable* aTransferable, nsIClipboardOwner* aOwner,
int32_t aWhichClipboard, mozilla::dom::WindowContext* aWindowContext) {
NS_ASSERTION(aTransferable, "clipboard given a null transferable");
MOZ_CLIPBOARD_LOG("%s: clipboard=%d", __FUNCTION__, aWhichClipboard);
@ -580,7 +600,10 @@ NS_IMETHODIMP nsBaseClipboard::SetData(nsITransferable* aTransferable,
return result.unwrapErr();
}
clipboardCache->Update(aTransferable, aOwner, result.unwrap());
clipboardCache->Update(aTransferable, aOwner, result.unwrap(),
aWindowContext
? mozilla::Some(aWindowContext->InnerWindowId())
: mozilla::Nothing());
return NS_OK;
}
@ -623,7 +646,7 @@ NS_IMETHODIMP nsBaseClipboard::GetData(
GetDataFromClipboardCache(aTransferable, aWhichClipboard))) {
// maybe try to fill in more types? Is there a point?
if (!CheckClipboardContentAnalysisSync(aWindowContext->Canonical(),
aTransferable)) {
aTransferable, aWhichClipboard)) {
aTransferable->ClearAllData();
return NS_ERROR_CONTENT_BLOCKED;
}
@ -638,7 +661,7 @@ NS_IMETHODIMP nsBaseClipboard::GetData(
return rv;
}
if (!CheckClipboardContentAnalysisSync(aWindowContext->Canonical(),
aTransferable)) {
aTransferable, aWhichClipboard)) {
aTransferable->ClearAllData();
return NS_ERROR_CONTENT_BLOCKED;
}
@ -1203,7 +1226,7 @@ NS_IMETHODIMP nsBaseClipboard::AsyncGetClipboardData::GetData(
mClipboard->CheckClipboardContentAnalysis(
mRequestingWindowContext ? mRequestingWindowContext->Canonical()
: nullptr,
aTransferable, contentAnalysisCallback);
aTransferable, mClipboardType, contentAnalysisCallback);
return NS_OK;
}
@ -1233,7 +1256,7 @@ NS_IMETHODIMP nsBaseClipboard::AsyncGetClipboardData::GetData(
self->mRequestingWindowContext
? self->mRequestingWindowContext->Canonical()
: nullptr,
transferable, contentAnalysisCallback);
transferable, self->mClipboardType, contentAnalysisCallback);
});
return NS_OK;
}

View file

@ -44,9 +44,12 @@ class nsBaseClipboard : public nsIClipboard {
NS_DECL_ISUPPORTS
// nsIClipboard
NS_IMETHOD SetData(nsITransferable* aTransferable, nsIClipboardOwner* aOwner,
int32_t aWhichClipboard) override final;
NS_IMETHOD SetData(
nsITransferable* aTransferable, nsIClipboardOwner* aOwner,
int32_t aWhichClipboard,
mozilla::dom::WindowContext* aWindowContext) override final;
NS_IMETHOD AsyncSetData(int32_t aWhichClipboard,
mozilla::dom::WindowContext* aSettingWindowContext,
nsIAsyncClipboardRequestCallback* aCallback,
nsIAsyncSetClipboardData** _retval) override final;
NS_IMETHOD GetData(
@ -108,6 +111,7 @@ class nsBaseClipboard : public nsIClipboard {
NS_DECL_NSIASYNCSETCLIPBOARDDATA
AsyncSetClipboardData(int32_t aClipboardType, nsBaseClipboard* aClipboard,
mozilla::dom::WindowContext* aRequestingWindowContext,
nsIAsyncClipboardRequestCallback* aCallback);
private:
@ -125,6 +129,7 @@ class nsBaseClipboard : public nsIClipboard {
// NotifyCallback()) once nsBaseClipboard stops tracking us. This is
// also used to indicate whether this request is valid.
nsBaseClipboard* mClipboard;
RefPtr<mozilla::dom::WindowContext> mWindowContext;
// mCallback will be nullified once the callback is notified to ensure the
// callback is only notified once.
nsCOMPtr<nsIAsyncClipboardRequestCallback> mCallback;
@ -174,22 +179,26 @@ class nsBaseClipboard : public nsIClipboard {
*/
void Clear();
void Update(nsITransferable* aTransferable,
nsIClipboardOwner* aClipboardOwner, int32_t aSequenceNumber) {
nsIClipboardOwner* aClipboardOwner, int32_t aSequenceNumber,
mozilla::Maybe<uint64_t> aInnerWindowId) {
// Clear first to notify the old clipboard owner.
Clear();
mTransferable = aTransferable;
mClipboardOwner = aClipboardOwner;
mSequenceNumber = aSequenceNumber;
mInnerWindowId = aInnerWindowId;
}
nsITransferable* GetTransferable() const { return mTransferable; }
nsIClipboardOwner* GetClipboardOwner() const { return mClipboardOwner; }
int32_t GetSequenceNumber() const { return mSequenceNumber; }
mozilla::Maybe<uint64_t> GetInnerWindowId() const { return mInnerWindowId; }
nsresult GetData(nsITransferable* aTransferable) const;
private:
nsCOMPtr<nsITransferable> mTransferable;
nsCOMPtr<nsIClipboardOwner> mClipboardOwner;
int32_t mSequenceNumber = -1;
mozilla::Maybe<uint64_t> mInnerWindowId;
};
class SafeContentAnalysisResultCallback final
@ -245,10 +254,10 @@ class nsBaseClipboard : public nsIClipboard {
int32_t aClipboardType);
bool CheckClipboardContentAnalysisSync(
mozilla::dom::WindowGlobalParent* aWindow,
const nsCOMPtr<nsITransferable>& trans);
const nsCOMPtr<nsITransferable>& trans, int32_t aClipboardType);
void CheckClipboardContentAnalysis(
mozilla::dom::WindowGlobalParent* aWindow, nsITransferable* aTransferable,
SafeContentAnalysisResultCallback* aResolver);
int32_t aClipboardType, SafeContentAnalysisResultCallback* aResolver);
// - true means a content analysis request was fired
// - false means there is no text data in the transferable
// - NoContentAnalysisResult means there was an error

View file

@ -36,9 +36,10 @@ nsClipboardHelper::~nsClipboardHelper() {
*****************************************************************************/
NS_IMETHODIMP
nsClipboardHelper::CopyStringToClipboard(const nsAString& aString,
int32_t aClipboardID,
SensitiveData aSensitive) {
nsClipboardHelper::CopyStringToClipboard(
const nsAString& aString, int32_t aClipboardID,
mozilla::dom::WindowContext* aSettingWindowContext,
SensitiveData aSensitive) {
nsresult rv;
// get the clipboard
@ -92,20 +93,22 @@ nsClipboardHelper::CopyStringToClipboard(const nsAString& aString,
NS_ENSURE_SUCCESS(rv, rv);
// put the transferable on the clipboard
rv = clipboard->SetData(trans, nullptr, aClipboardID);
rv = clipboard->SetData(trans, nullptr, aClipboardID, aSettingWindowContext);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
nsClipboardHelper::CopyString(const nsAString& aString,
SensitiveData aSensitive) {
nsClipboardHelper::CopyString(
const nsAString& aString,
mozilla::dom::WindowContext* aSettingWindowContext,
SensitiveData aSensitive) {
nsresult rv;
// copy to the global clipboard. it's bad if this fails in any way.
rv = CopyStringToClipboard(aString, nsIClipboard::kGlobalClipboard,
aSensitive);
aSettingWindowContext, aSensitive);
NS_ENSURE_SUCCESS(rv, rv);
// unix also needs us to copy to the selection clipboard. this will
@ -117,7 +120,8 @@ nsClipboardHelper::CopyString(const nsAString& aString,
// if this fails in any way other than "not being unix", we'll get
// the assertion we need in CopyStringToClipboard, and we needn't
// assert again here.
CopyStringToClipboard(aString, nsIClipboard::kSelectionClipboard, aSensitive);
CopyStringToClipboard(aString, nsIClipboard::kSelectionClipboard,
aSettingWindowContext, aSensitive);
return NS_OK;
}

View file

@ -32,7 +32,8 @@ nsClipboardProxy::nsClipboardProxy() : mClipboardCaps(false, false, false) {}
NS_IMETHODIMP
nsClipboardProxy::SetData(nsITransferable* aTransferable,
nsIClipboardOwner* anOwner, int32_t aWhichClipboard) {
nsIClipboardOwner* anOwner, int32_t aWhichClipboard,
mozilla::dom::WindowContext* aWindowContext) {
#if defined(ACCESSIBILITY) && defined(XP_WIN)
a11y::Compatibility::SuppressA11yForClipboardCopy();
#endif
@ -41,17 +42,19 @@ nsClipboardProxy::SetData(nsITransferable* aTransferable,
IPCTransferable ipcTransferable;
nsContentUtils::TransferableToIPCTransferable(aTransferable, &ipcTransferable,
false, nullptr);
child->SendSetClipboard(std::move(ipcTransferable), aWhichClipboard);
child->SendSetClipboard(std::move(ipcTransferable), aWhichClipboard,
aWindowContext);
return NS_OK;
}
NS_IMETHODIMP nsClipboardProxy::AsyncSetData(
int32_t aWhichClipboard, nsIAsyncClipboardRequestCallback* aCallback,
int32_t aWhichClipboard, mozilla::dom::WindowContext* aSettingWindowContext,
nsIAsyncClipboardRequestCallback* aCallback,
nsIAsyncSetClipboardData** _retval) {
RefPtr<ClipboardWriteRequestChild> request =
MakeRefPtr<ClipboardWriteRequestChild>(aCallback);
ContentChild::GetSingleton()->SendPClipboardWriteRequestConstructor(
request, aWhichClipboard);
request, aWhichClipboard, aSettingWindowContext);
request.forget(_retval);
return NS_OK;
}

View file

@ -115,20 +115,28 @@ interface nsIClipboard : nsISupports
* @param aTransferable The transferable
* @param anOwner The owner of the transferable
* @param aWhichClipboard Specifies the clipboard to which this operation applies.
* @result NS_Ok if no errors
* @param aSettingWindowContext [optional]
* The window context that is setting the clipboard, if any. This is used
* to possibly bypass Content Analysis if a set clipboard and get clipboard
* operation are done on the same page.
* @result NS_OK if no errors
*/
void setData ( in nsITransferable aTransferable, in nsIClipboardOwner anOwner,
in long aWhichClipboard ) ;
void setData (in nsITransferable aTransferable, in nsIClipboardOwner anOwner,
in long aWhichClipboard, [optional] in WindowContext aSettingWindowContext);
/**
* Requests setting data to the native clipboard. The acutal set occur
* Requests setting data to the native clipboard. The actual set occurs
* when the data is provided by calling nsIAsyncSetClipboardData::setData().
* The result will be notified by nsIClipboardCallback. A new set request
* will cancel any prior pending requests, if any exist.
*
* @param aWhichClipboard
* Specifies the clipboard to which this operation applies.
* @param aSettingWindowContext [optional]
* The window context that is setting the clipboard, if any. This is used
* to possibly bypass Content Analysis if a set clipboard and get clipboard
* operation are done on the same page.
* @param aCallback [optional]
* The callback object that will be notified upon completion.
* @return nsIAsyncSetClipboardData
@ -136,6 +144,7 @@ interface nsIClipboard : nsISupports
* data is provided by calling nsIAsyncSetClipboardData::setData().
*/
nsIAsyncSetClipboardData asyncSetData(in long aWhichClipboard,
[optional] in WindowContext aSettingWindowContext,
[optional] in nsIAsyncClipboardRequestCallback aCallback);
/**

View file

@ -29,17 +29,29 @@ interface nsIClipboardHelper : nsISupports
* @param aString, the string to copy to the clipboard
* @param aClipboardID, the ID of the clipboard to copy to
* (eg. kSelectionClipboard -- see nsIClipboard.idl)
* @param aSettingWindowContext
* The window context that is setting the clipboard, if any. This is used
* to possibly bypass Content Analysis if a set clipboard and get clipboard
* operation are done on the same page.
* @param aSensitive, optional flag to indicate that data is sensitive, like a password.
* That will exclude data from Cloud Clipboard/Clipboard History on Windows.
*/
void copyStringToClipboard(in AString aString, in long aClipboardID,
[optional] in WindowContext aSettingWindowContext,
[optional, default(NotSensitive)] in nsIClipboardHelper_SensitiveData aSensitive);
/**
* copy string to (default) clipboard
*
* @param aString, the string to copy to the clipboard
* @param aSettingWindowContext
* The window context that is setting the clipboard, if any. This is used
* to possibly bypass Content Analysis if a set clipboard and get clipboard
* operation are done on the same page.
* @param aSensitive, optional flag to indicate that data is sensitive, like a password.
* That will exclude data from Cloud Clipboard/Clipboard History on Windows.
*/
void copyString(in AString aString,
[optional] in WindowContext aSettingWindowContext,
[optional, default(NotSensitive)] in nsIClipboardHelper_SensitiveData aSensitive);
};

View file

@ -21,7 +21,7 @@ clipboardTypes.forEach(function (type) {
let priorResult;
let priorRequest;
let priorPromise = new Promise(resolve => {
priorRequest = clipboard.asyncSetData(type, {
priorRequest = clipboard.asyncSetData(type, null, {
QueryInterface: SpecialPowers.ChromeUtils.generateQI([
"nsIAsyncSetClipboardDataCallback",
]),
@ -119,7 +119,7 @@ clipboardTypes.forEach(function (type) {
// Create a pending asyncSetData request
let result;
let request = clipboard.asyncSetData(type, rv => {
let request = clipboard.asyncSetData(type, null, rv => {
result = rv;
});