Bug 1879401 - Make clipboard DataTransfer use sync version of nsIAsyncGetClipboardData r=edgar,ipc-reviewers,nika
Differential Revision: https://phabricator.services.mozilla.com/D224843
This commit is contained in:
@@ -531,9 +531,8 @@ class DataTransfer final : public nsISupports, public nsWrapperCache {
|
|||||||
// drag and drop.
|
// drag and drop.
|
||||||
mozilla::Maybe<nsIClipboard::ClipboardType> mClipboardType;
|
mozilla::Maybe<nsIClipboard::ClipboardType> mClipboardType;
|
||||||
|
|
||||||
// The nsIClipboardDataSnapshot that is used for getting clipboard formats.
|
// The nsIClipboardDataSnapshot that is used for getting clipboard formats and
|
||||||
// XXXedgar we should get the actual data from this in the future, see bug
|
// data.
|
||||||
// 1879401.
|
|
||||||
nsCOMPtr<nsIClipboardDataSnapshot> mClipboardDataSnapshot;
|
nsCOMPtr<nsIClipboardDataSnapshot> mClipboardDataSnapshot;
|
||||||
|
|
||||||
// The items contained with the DataTransfer
|
// The items contained with the DataTransfer
|
||||||
|
|||||||
@@ -172,21 +172,12 @@ void DataTransferItem::FillInExternalData() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIClipboard> clipboard =
|
nsCOMPtr<nsIClipboardDataSnapshot> clipboardDataSnapshot =
|
||||||
do_GetService("@mozilla.org/widget/clipboard;1");
|
mDataTransfer->GetClipboardDataSnapshot();
|
||||||
if (!clipboard) {
|
if (!clipboardDataSnapshot) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
nsresult rv = clipboardDataSnapshot->GetDataSync(trans);
|
||||||
nsCOMPtr<nsIGlobalObject> global = mDataTransfer->GetGlobal();
|
|
||||||
WindowContext* windowContext = nullptr;
|
|
||||||
if (global) {
|
|
||||||
const auto* innerWindow = global->GetAsInnerWindow();
|
|
||||||
windowContext = innerWindow ? innerWindow->GetWindowContext() : nullptr;
|
|
||||||
}
|
|
||||||
MOZ_ASSERT(windowContext);
|
|
||||||
nsresult rv = clipboard->GetData(trans, *mDataTransfer->ClipboardType(),
|
|
||||||
windowContext);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
if (rv == NS_ERROR_CONTENT_BLOCKED) {
|
if (rv == NS_ERROR_CONTENT_BLOCKED) {
|
||||||
// If the load of this content was blocked by Content Analysis,
|
// If the load of this content was blocked by Content Analysis,
|
||||||
|
|||||||
@@ -97,7 +97,9 @@ description = Only used by gtests
|
|||||||
|
|
||||||
# Clipboard
|
# Clipboard
|
||||||
[PClipboardContentAnalysis::GetClipboard]
|
[PClipboardContentAnalysis::GetClipboard]
|
||||||
description = Legacy synchronous clipboard API
|
description = Called from PContent::GetClipboard which is a legacy synchronous clipboard API
|
||||||
|
[PClipboardReadRequest::GetDataSync]
|
||||||
|
description = Called from synchronous DataTransfer constructor
|
||||||
[PContent::GetClipboard]
|
[PContent::GetClipboard]
|
||||||
description = Legacy synchronous clipboard API
|
description = Legacy synchronous clipboard API
|
||||||
[PContent::ClipboardHasType]
|
[PContent::ClipboardHasType]
|
||||||
|
|||||||
@@ -112,4 +112,37 @@ IPCResult ClipboardReadRequestParent::RecvGetData(
|
|||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IPCResult ClipboardReadRequestParent::RecvGetDataSync(
|
||||||
|
const nsTArray<nsCString>& aFlavors,
|
||||||
|
dom::IPCTransferableDataOrError* aTransferableDataOrError) {
|
||||||
|
bool valid = false;
|
||||||
|
if (NS_FAILED(mClipboardDataSnapshot->GetValid(&valid)) || !valid) {
|
||||||
|
Unused << PClipboardReadRequestParent::Send__delete__(this);
|
||||||
|
*aTransferableDataOrError = NS_ERROR_FAILURE;
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create transferable
|
||||||
|
auto result = CreateTransferable(aFlavors);
|
||||||
|
if (result.isErr()) {
|
||||||
|
*aTransferableDataOrError = result.unwrapErr();
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsITransferable> trans = result.unwrap();
|
||||||
|
nsresult rv = mClipboardDataSnapshot->GetDataSync(trans);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
*aTransferableDataOrError = rv;
|
||||||
|
if (NS_FAILED(mClipboardDataSnapshot->GetValid(&valid)) || !valid) {
|
||||||
|
Unused << PClipboardReadRequestParent::Send__delete__(this);
|
||||||
|
}
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
dom::IPCTransferableData ipcTransferableData;
|
||||||
|
nsContentUtils::TransferableToIPCTransferableData(
|
||||||
|
trans, &ipcTransferableData, true /* aInSyncMessage */, mManager);
|
||||||
|
*aTransferableDataOrError = std::move(ipcTransferableData);
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ class ClipboardReadRequestParent final : public PClipboardReadRequestParent {
|
|||||||
// PClipboardReadRequestParent
|
// PClipboardReadRequestParent
|
||||||
IPCResult RecvGetData(const nsTArray<nsCString>& aFlavors,
|
IPCResult RecvGetData(const nsTArray<nsCString>& aFlavors,
|
||||||
GetDataResolver&& aResolver);
|
GetDataResolver&& aResolver);
|
||||||
|
IPCResult RecvGetDataSync(
|
||||||
|
const nsTArray<nsCString>& aFlavors,
|
||||||
|
dom::IPCTransferableDataOrError* aTransferableDataOrError);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~ClipboardReadRequestParent() = default;
|
~ClipboardReadRequestParent() = default;
|
||||||
|
|||||||
@@ -12,11 +12,12 @@ using nsContentPolicyType from "nsIContentPolicy.h";
|
|||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
protocol PClipboardReadRequest {
|
sync protocol PClipboardReadRequest {
|
||||||
manager PContent;
|
manager PContent;
|
||||||
|
|
||||||
parent:
|
parent:
|
||||||
async GetData(nsCString[] aFlavors) returns (IPCTransferableDataOrError aTransferableData);
|
async GetData(nsCString[] aFlavors) returns (IPCTransferableDataOrError aTransferableData);
|
||||||
|
sync GetDataSync(nsCString[] aFlavors) returns (IPCTransferableDataOrError aTransferableData);
|
||||||
|
|
||||||
both:
|
both:
|
||||||
async __delete__();
|
async __delete__();
|
||||||
|
|||||||
@@ -1080,6 +1080,77 @@ NS_IMETHODIMP nsBaseClipboard::ClipboardDataSnapshot::GetData(
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP nsBaseClipboard::ClipboardDataSnapshot::GetDataSync(
|
||||||
|
nsITransferable* aTransferable) {
|
||||||
|
MOZ_CLIPBOARD_LOG("ClipboardDataSnapshot::GetDataSync: %p", this);
|
||||||
|
|
||||||
|
if (!aTransferable) {
|
||||||
|
return NS_ERROR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTArray<nsCString> flavors;
|
||||||
|
nsresult rv = aTransferable->FlavorsTransferableCanImport(flavors);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the requested flavor is not in the list, throw an error.
|
||||||
|
for (const auto& flavor : flavors) {
|
||||||
|
if (!mFlavors.Contains(flavor)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsValid()) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(mClipboard);
|
||||||
|
|
||||||
|
if (mFromCache) {
|
||||||
|
const auto* clipboardCache =
|
||||||
|
mClipboard->GetClipboardCacheIfValid(mClipboardType);
|
||||||
|
// `IsValid()` above ensures we should get a valid cache and matched
|
||||||
|
// sequence number here.
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(clipboardCache);
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(clipboardCache->GetSequenceNumber() ==
|
||||||
|
mSequenceNumber);
|
||||||
|
if (NS_SUCCEEDED(clipboardCache->GetData(aTransferable))) {
|
||||||
|
bool shouldAllowContent = mozilla::contentanalysis::ContentAnalysis::
|
||||||
|
CheckClipboardContentAnalysisSync(
|
||||||
|
mClipboard,
|
||||||
|
mRequestingWindowContext ? mRequestingWindowContext->Canonical()
|
||||||
|
: nullptr,
|
||||||
|
aTransferable, mClipboardType);
|
||||||
|
if (shouldAllowContent) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
aTransferable->ClearAllData();
|
||||||
|
return NS_ERROR_CONTENT_BLOCKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point we can't satisfy the request from cache data so let's look
|
||||||
|
// for things other people put on the system clipboard.
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = mClipboard->GetNativeClipboardData(aTransferable, mClipboardType);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool shouldAllowContent = mozilla::contentanalysis::ContentAnalysis::
|
||||||
|
CheckClipboardContentAnalysisSync(
|
||||||
|
mClipboard,
|
||||||
|
mRequestingWindowContext ? mRequestingWindowContext->Canonical()
|
||||||
|
: nullptr,
|
||||||
|
aTransferable, mClipboardType);
|
||||||
|
if (shouldAllowContent) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
aTransferable->ClearAllData();
|
||||||
|
return NS_ERROR_CONTENT_BLOCKED;
|
||||||
|
}
|
||||||
|
|
||||||
bool nsBaseClipboard::ClipboardDataSnapshot::IsValid() {
|
bool nsBaseClipboard::ClipboardDataSnapshot::IsValid() {
|
||||||
if (!mClipboard) {
|
if (!mClipboard) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -204,6 +204,52 @@ NS_IMETHODIMP ClipboardDataSnapshotProxy::GetData(
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP ClipboardDataSnapshotProxy::GetDataSync(
|
||||||
|
nsITransferable* aTransferable) {
|
||||||
|
if (!aTransferable) {
|
||||||
|
return NS_ERROR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a list of flavors this transferable can import
|
||||||
|
nsTArray<nsCString> flavors;
|
||||||
|
nsresult rv = aTransferable->FlavorsTransferableCanImport(flavors);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(mActor);
|
||||||
|
// If the requested flavor is not in the list, throw an error.
|
||||||
|
for (const auto& flavor : flavors) {
|
||||||
|
if (!mActor->FlavorList().Contains(flavor)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mActor->CanSend()) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPCTransferableDataOrError ipcTransferableDataOrError;
|
||||||
|
bool success = mActor->SendGetDataSync(flavors, &ipcTransferableDataOrError);
|
||||||
|
if (!success) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
if (ipcTransferableDataOrError.type() ==
|
||||||
|
IPCTransferableDataOrError::Tnsresult) {
|
||||||
|
MOZ_ASSERT(NS_FAILED(ipcTransferableDataOrError.get_nsresult()));
|
||||||
|
return ipcTransferableDataOrError.get_nsresult();
|
||||||
|
}
|
||||||
|
rv = nsContentUtils::IPCTransferableDataToTransferable(
|
||||||
|
ipcTransferableDataOrError.get_IPCTransferableData(),
|
||||||
|
false /* aAddDataFlavor */, aTransferable,
|
||||||
|
false /* aFilterUnknownFlavors */);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static Result<RefPtr<ClipboardDataSnapshotProxy>, nsresult>
|
static Result<RefPtr<ClipboardDataSnapshotProxy>, nsresult>
|
||||||
CreateClipboardDataSnapshotProxy(
|
CreateClipboardDataSnapshotProxy(
|
||||||
ClipboardReadRequestOrError&& aClipboardReadRequestOrError) {
|
ClipboardReadRequestOrError&& aClipboardReadRequestOrError) {
|
||||||
|
|||||||
@@ -77,6 +77,19 @@ interface nsIClipboardDataSnapshot : nsISupports {
|
|||||||
*/
|
*/
|
||||||
void getData(in nsITransferable aTransferable,
|
void getData(in nsITransferable aTransferable,
|
||||||
in nsIAsyncClipboardRequestCallback aCallback);
|
in nsIAsyncClipboardRequestCallback aCallback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters the flavors that `aTransferable` can import (see
|
||||||
|
* `nsITransferable::flavorsTransferableCanImport`). Every specified flavors
|
||||||
|
* must exist in `flavorList`, or the request will be rejected. If the request
|
||||||
|
* remains valid, it retrieves the data for the first flavor. The data is then
|
||||||
|
* set for `aTransferable`.
|
||||||
|
*
|
||||||
|
* @param aTransferable
|
||||||
|
* The transferable which contains the flavors to be read.
|
||||||
|
* @result NS_OK if no errors
|
||||||
|
*/
|
||||||
|
void getDataSync(in nsITransferable aTransferable);
|
||||||
};
|
};
|
||||||
|
|
||||||
[scriptable, uuid(ce23c1c4-58fd-4c33-8579-fa0796d9652c)]
|
[scriptable, uuid(ce23c1c4-58fd-4c33-8579-fa0796d9652c)]
|
||||||
|
|||||||
@@ -238,3 +238,32 @@ function asyncClipboardRequestGetData(aRequest, aFlavor, aThrows = false) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function syncClipboardRequestGetData(aRequest, aFlavor, aThrows = false) {
|
||||||
|
var trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(
|
||||||
|
Ci.nsITransferable
|
||||||
|
);
|
||||||
|
trans.init(null);
|
||||||
|
trans.addDataFlavor(aFlavor);
|
||||||
|
let error = undefined;
|
||||||
|
try {
|
||||||
|
aRequest.getDataSync(trans);
|
||||||
|
try {
|
||||||
|
var data = SpecialPowers.createBlankObject();
|
||||||
|
trans.getTransferData(aFlavor, data);
|
||||||
|
return data.value.QueryInterface(Ci.nsISupportsString).data;
|
||||||
|
} catch (ex) {
|
||||||
|
// should widget set empty string to transferable when there no
|
||||||
|
// data in system clipboard?
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
error = e;
|
||||||
|
return error;
|
||||||
|
} finally {
|
||||||
|
ok(
|
||||||
|
aThrows === (error !== undefined),
|
||||||
|
`nsIAsyncGetClipboardData.getData should ${aThrows ? "throw" : "success"}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ clipboardTypes.forEach(function (type) {
|
|||||||
await asyncClipboardRequestGetData(request, "text/plain", true).catch(
|
await asyncClipboardRequestGetData(request, "text/plain", true).catch(
|
||||||
() => {}
|
() => {}
|
||||||
);
|
);
|
||||||
|
syncClipboardRequestGetData(request, "text/plain", true);
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_clipboard_getDataSnapshot_after_write() {
|
add_task(async function test_clipboard_getDataSnapshot_after_write() {
|
||||||
@@ -82,11 +83,19 @@ clipboardTypes.forEach(function (type) {
|
|||||||
"Check data"
|
"Check data"
|
||||||
);
|
);
|
||||||
ok(request.valid, "request should still be valid");
|
ok(request.valid, "request should still be valid");
|
||||||
|
is(
|
||||||
|
syncClipboardRequestGetData(request, "text/plain"),
|
||||||
|
str,
|
||||||
|
"Check data (sync)"
|
||||||
|
);
|
||||||
|
ok(request.valid, "request should still be valid");
|
||||||
// Requesting a flavor that is not in the list should throw error.
|
// Requesting a flavor that is not in the list should throw error.
|
||||||
await asyncClipboardRequestGetData(request, "text/html", true).catch(
|
await asyncClipboardRequestGetData(request, "text/html", true).catch(
|
||||||
() => {}
|
() => {}
|
||||||
);
|
);
|
||||||
ok(request.valid, "request should still be valid");
|
ok(request.valid, "request should still be valid");
|
||||||
|
syncClipboardRequestGetData(request, "text/html", true);
|
||||||
|
ok(request.valid, "request should still be valid");
|
||||||
|
|
||||||
// Writing a new data should invalid existing get request.
|
// Writing a new data should invalid existing get request.
|
||||||
str = writeRandomStringToClipboard("text/plain", type);
|
str = writeRandomStringToClipboard("text/plain", type);
|
||||||
@@ -99,6 +108,8 @@ clipboardTypes.forEach(function (type) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
ok(!request.valid, "request should no longer be valid");
|
ok(!request.valid, "request should no longer be valid");
|
||||||
|
syncClipboardRequestGetData(request, "text/plain", true);
|
||||||
|
ok(!request.valid, "request should no longer be valid");
|
||||||
|
|
||||||
info(`check clipboard data again`);
|
info(`check clipboard data again`);
|
||||||
request = await getClipboardDataSnapshot(type);
|
request = await getClipboardDataSnapshot(type);
|
||||||
@@ -108,6 +119,11 @@ clipboardTypes.forEach(function (type) {
|
|||||||
str,
|
str,
|
||||||
"Check data"
|
"Check data"
|
||||||
);
|
);
|
||||||
|
is(
|
||||||
|
syncClipboardRequestGetData(request, "text/plain"),
|
||||||
|
str,
|
||||||
|
"Check data (sync)"
|
||||||
|
);
|
||||||
|
|
||||||
cleanupAllClipboard();
|
cleanupAllClipboard();
|
||||||
});
|
});
|
||||||
@@ -124,6 +140,12 @@ clipboardTypes.forEach(function (type) {
|
|||||||
"Check data"
|
"Check data"
|
||||||
);
|
);
|
||||||
ok(request.valid, "request should still be valid");
|
ok(request.valid, "request should still be valid");
|
||||||
|
is(
|
||||||
|
syncClipboardRequestGetData(request, "text/plain"),
|
||||||
|
str,
|
||||||
|
"Check data (sync)"
|
||||||
|
);
|
||||||
|
ok(request.valid, "request should still be valid");
|
||||||
|
|
||||||
// Empty clipboard data
|
// Empty clipboard data
|
||||||
emptyClipboardData(type);
|
emptyClipboardData(type);
|
||||||
@@ -155,16 +177,25 @@ add_task(async function test_html_data() {
|
|||||||
|
|
||||||
let request = await getClipboardDataSnapshot(clipboard.kGlobalClipboard);
|
let request = await getClipboardDataSnapshot(clipboard.kGlobalClipboard);
|
||||||
isDeeply(request.flavorList, ["text/html"], "Check flavorList");
|
isDeeply(request.flavorList, ["text/html"], "Check flavorList");
|
||||||
|
// On Windows, widget adds extra data into HTML clipboard.
|
||||||
|
let expectedData = navigator.platform.includes("Win")
|
||||||
|
? `<html><body>\n<!--StartFragment-->${html_str}<!--EndFragment-->\n</body>\n</html>`
|
||||||
|
: html_str;
|
||||||
is(
|
is(
|
||||||
await asyncClipboardRequestGetData(request, "text/html"),
|
await asyncClipboardRequestGetData(request, "text/html"),
|
||||||
// On Windows, widget adds extra data into HTML clipboard.
|
expectedData,
|
||||||
navigator.platform.includes("Win")
|
|
||||||
? `<html><body>\n<!--StartFragment-->${html_str}<!--EndFragment-->\n</body>\n</html>`
|
|
||||||
: html_str,
|
|
||||||
"Check data"
|
"Check data"
|
||||||
);
|
);
|
||||||
// Requesting a flavor that is not in the list should throw error.
|
// Requesting a flavor that is not in the list should throw error.
|
||||||
await asyncClipboardRequestGetData(request, "text/plain", true).catch(
|
await asyncClipboardRequestGetData(request, "text/plain", true).catch(
|
||||||
() => {}
|
() => {}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
is(
|
||||||
|
syncClipboardRequestGetData(request, "text/html"),
|
||||||
|
expectedData,
|
||||||
|
"Check data (sync)"
|
||||||
|
);
|
||||||
|
// Requesting a flavor that is not in the list should throw error.
|
||||||
|
syncClipboardRequestGetData(request, "text/plain", true);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ clipboardTypes.forEach(function (type) {
|
|||||||
await asyncClipboardRequestGetData(request, "text/plain", true).catch(
|
await asyncClipboardRequestGetData(request, "text/plain", true).catch(
|
||||||
() => {}
|
() => {}
|
||||||
);
|
);
|
||||||
|
syncClipboardRequestGetData(request, "text/plain", true);
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_clipboard_getDataSnapshotSync_after_write() {
|
add_task(async function test_clipboard_getDataSnapshotSync_after_write() {
|
||||||
@@ -65,11 +66,19 @@ clipboardTypes.forEach(function (type) {
|
|||||||
"Check data"
|
"Check data"
|
||||||
);
|
);
|
||||||
ok(request.valid, "request should still be valid");
|
ok(request.valid, "request should still be valid");
|
||||||
|
is(
|
||||||
|
syncClipboardRequestGetData(request, "text/plain"),
|
||||||
|
str,
|
||||||
|
"Check data (sync)"
|
||||||
|
);
|
||||||
|
ok(request.valid, "request should still be valid");
|
||||||
// Requesting a flavor that is not in the list should throw error.
|
// Requesting a flavor that is not in the list should throw error.
|
||||||
await asyncClipboardRequestGetData(request, "text/html", true).catch(
|
await asyncClipboardRequestGetData(request, "text/html", true).catch(
|
||||||
() => {}
|
() => {}
|
||||||
);
|
);
|
||||||
ok(request.valid, "request should still be valid");
|
ok(request.valid, "request should still be valid");
|
||||||
|
syncClipboardRequestGetData(request, "text/html", true);
|
||||||
|
ok(request.valid, "request should still be valid");
|
||||||
|
|
||||||
// Writing a new data should invalid existing get request.
|
// Writing a new data should invalid existing get request.
|
||||||
str = writeRandomStringToClipboard("text/plain", type);
|
str = writeRandomStringToClipboard("text/plain", type);
|
||||||
@@ -82,6 +91,8 @@ clipboardTypes.forEach(function (type) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
ok(!request.valid, "request should no longer be valid");
|
ok(!request.valid, "request should no longer be valid");
|
||||||
|
syncClipboardRequestGetData(request, "text/plain", true);
|
||||||
|
ok(!request.valid, "request should no longer be valid");
|
||||||
|
|
||||||
info(`check clipboard data again`);
|
info(`check clipboard data again`);
|
||||||
request = getClipboardDataSnapshotSync(type);
|
request = getClipboardDataSnapshotSync(type);
|
||||||
@@ -91,6 +102,11 @@ clipboardTypes.forEach(function (type) {
|
|||||||
str,
|
str,
|
||||||
"Check data"
|
"Check data"
|
||||||
);
|
);
|
||||||
|
is(
|
||||||
|
syncClipboardRequestGetData(request, "text/plain"),
|
||||||
|
str,
|
||||||
|
"Check data (sync)"
|
||||||
|
);
|
||||||
|
|
||||||
cleanupAllClipboard();
|
cleanupAllClipboard();
|
||||||
});
|
});
|
||||||
@@ -138,16 +154,25 @@ add_task(async function test_clipboard_getDataSnapshotSync_html_data() {
|
|||||||
|
|
||||||
let request = getClipboardDataSnapshotSync(clipboard.kGlobalClipboard);
|
let request = getClipboardDataSnapshotSync(clipboard.kGlobalClipboard);
|
||||||
isDeeply(request.flavorList, ["text/html"], "Check flavorList");
|
isDeeply(request.flavorList, ["text/html"], "Check flavorList");
|
||||||
|
// On Windows, widget adds extra data into HTML clipboard.
|
||||||
|
let expectedData = navigator.platform.includes("Win")
|
||||||
|
? `<html><body>\n<!--StartFragment-->${html_str}<!--EndFragment-->\n</body>\n</html>`
|
||||||
|
: html_str;
|
||||||
is(
|
is(
|
||||||
await asyncClipboardRequestGetData(request, "text/html"),
|
await asyncClipboardRequestGetData(request, "text/html"),
|
||||||
// On Windows, widget adds extra data into HTML clipboard.
|
expectedData,
|
||||||
navigator.platform.includes("Win")
|
|
||||||
? `<html><body>\n<!--StartFragment-->${html_str}<!--EndFragment-->\n</body>\n</html>`
|
|
||||||
: html_str,
|
|
||||||
"Check data"
|
"Check data"
|
||||||
);
|
);
|
||||||
// Requesting a flavor that is not in the list should throw error.
|
// Requesting a flavor that is not in the list should throw error.
|
||||||
await asyncClipboardRequestGetData(request, "text/plain", true).catch(
|
await asyncClipboardRequestGetData(request, "text/plain", true).catch(
|
||||||
() => {}
|
() => {}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
is(
|
||||||
|
syncClipboardRequestGetData(request, "text/html"),
|
||||||
|
expectedData,
|
||||||
|
"Check data (sync)"
|
||||||
|
);
|
||||||
|
// Requesting a flavor that is not in the list should throw error.
|
||||||
|
syncClipboardRequestGetData(request, "text/plain", true);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user