зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1689886 - Add a test-only clipboard.read implementation with ClipboardItem. r=nika
Differential Revision: https://phabricator.services.mozilla.com/D103588
This commit is contained in:
Родитель
c1b72d4f7a
Коммит
be7f4c6ca9
|
@ -65,27 +65,78 @@ already_AddRefed<Promise> Clipboard::ReadHelper(
|
|||
RefPtr<DataTransfer> dataTransfer = new DataTransfer(
|
||||
this, ePaste, /* is external */ true, nsIClipboard::kGlobalClipboard);
|
||||
|
||||
RefPtr<nsPIDOMWindowInner> owner = GetOwner();
|
||||
|
||||
// Create a new runnable
|
||||
RefPtr<nsIRunnable> r = NS_NewRunnableFunction(
|
||||
"Clipboard::Read",
|
||||
[p, dataTransfer, &aSubjectPrincipal, aClipboardReadType]() {
|
||||
"Clipboard::Read", [p, dataTransfer, aClipboardReadType, owner,
|
||||
principal = RefPtr{&aSubjectPrincipal}]() {
|
||||
IgnoredErrorResult ier;
|
||||
switch (aClipboardReadType) {
|
||||
case eRead:
|
||||
case eRead: {
|
||||
MOZ_LOG(GetClipboardLog(), LogLevel::Debug,
|
||||
("Clipboard, ReadHelper, read case\n"));
|
||||
dataTransfer->FillAllExternalData();
|
||||
// If there are items on the clipboard, data transfer will contain
|
||||
// those, else, data transfer will be empty and we will be resolving
|
||||
// with an empty data transfer
|
||||
p->MaybeResolve(dataTransfer);
|
||||
|
||||
// Convert the DataTransferItems to ClipboardItems.
|
||||
// FIXME(bug 1691825): This is only suitable for testing!
|
||||
// A real implementation would only read from the clipboard
|
||||
// in ClipboardItem::getType instead of doing it here.
|
||||
nsTArray<ClipboardItem::ItemEntry> entries;
|
||||
DataTransferItemList* items = dataTransfer->Items();
|
||||
for (size_t i = 0; i < items->Length(); i++) {
|
||||
bool found = false;
|
||||
DataTransferItem* item = items->IndexedGetter(i, found);
|
||||
|
||||
// Only allow strings and files.
|
||||
if (!found || item->Kind() == DataTransferItem::KIND_OTHER) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoString type;
|
||||
item->GetType(type);
|
||||
|
||||
if (item->Kind() == DataTransferItem::KIND_STRING) {
|
||||
// We just ignore items that we can't access.
|
||||
IgnoredErrorResult ignored;
|
||||
nsCOMPtr<nsIVariant> data = item->Data(principal, ignored);
|
||||
if (NS_WARN_IF(!data || ignored.Failed())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoString string;
|
||||
if (NS_WARN_IF(NS_FAILED(data->GetAsAString(string)))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ClipboardItem::ItemEntry* entry = entries.AppendElement();
|
||||
entry->mType = type;
|
||||
entry->mData.SetAsString() = string;
|
||||
} else {
|
||||
IgnoredErrorResult ignored;
|
||||
RefPtr<File> file = item->GetAsFile(*principal, ignored);
|
||||
if (NS_WARN_IF(!file || ignored.Failed())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ClipboardItem::ItemEntry* entry = entries.AppendElement();
|
||||
entry->mType = type;
|
||||
entry->mData.SetAsBlob() = file;
|
||||
}
|
||||
}
|
||||
|
||||
nsTArray<RefPtr<ClipboardItem>> sequence;
|
||||
sequence.AppendElement(MakeRefPtr<ClipboardItem>(
|
||||
owner, PresentationStyle::Unspecified, std::move(entries)));
|
||||
p->MaybeResolve(sequence);
|
||||
break;
|
||||
}
|
||||
case eReadText:
|
||||
MOZ_LOG(GetClipboardLog(), LogLevel::Debug,
|
||||
("Clipboard, ReadHelper, read text case\n"));
|
||||
nsAutoString str;
|
||||
dataTransfer->GetData(NS_LITERAL_STRING_FROM_CSTRING(kTextMime),
|
||||
str, aSubjectPrincipal, ier);
|
||||
str, *principal, ier);
|
||||
// Either resolve with a string extracted from data transfer item
|
||||
// or resolve with an empty string if nothing was found
|
||||
p->MaybeResolve(str);
|
||||
|
|
|
@ -14,8 +14,8 @@ typedef sequence<ClipboardItem> ClipboardItems;
|
|||
|
||||
[SecureContext, Exposed=Window, Pref="dom.events.asyncClipboard"]
|
||||
interface Clipboard : EventTarget {
|
||||
[Pref="dom.events.asyncClipboard.dataTransfer", Throws, NeedsSubjectPrincipal]
|
||||
Promise<DataTransfer> read();
|
||||
[Pref="dom.events.asyncClipboard.clipboardItem", Throws, NeedsSubjectPrincipal]
|
||||
Promise<ClipboardItems> read();
|
||||
[Func="Clipboard::ReadTextEnabled", Throws, NeedsSubjectPrincipal]
|
||||
Promise<DOMString> readText();
|
||||
|
||||
|
|
|
@ -1805,13 +1805,7 @@
|
|||
value: true
|
||||
mirror: always
|
||||
|
||||
# Disable clipboard read() by default
|
||||
- name: dom.events.asyncClipboard.dataTransfer
|
||||
type: bool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# Disable ClipboardItem and clipboard.write by default
|
||||
# Disable ClipboardItem and clipboard.read/write by default
|
||||
- name: dom.events.asyncClipboard.clipboardItem
|
||||
type: bool
|
||||
value: false
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
prefs: [dom.events.asyncClipboard:true, dom.events.asyncClipboard.dataTransfer:true, dom.events.asyncClipboard.clipboardItem: true, dom.events.testing.asyncClipboard:true]
|
||||
prefs: [dom.events.asyncClipboard:true, dom.events.asyncClipboard.clipboardItem: true,
|
||||
dom.events.testing.asyncClipboard:true]
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[async-navigator-clipboard-basics.https.html]
|
||||
[navigator.clipboard.read() succeeds]
|
||||
expected: FAIL
|
||||
|
|
@ -59,7 +59,6 @@ function clearClipboard() {
|
|||
add_task(async function setup() {
|
||||
await SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.events.asyncClipboard", true],
|
||||
["dom.events.asyncClipboard.dataTransfer", true],
|
||||
["dom.events.asyncClipboard.clipboardItem", true],
|
||||
]});
|
||||
});
|
||||
|
@ -241,8 +240,9 @@ add_task(async function test_contentscript_clipboard_permission_write() {
|
|||
// Test that with enough permissions, we are allowed to use read in content script
|
||||
add_task(async function test_contentscript_clipboard_permission_read() {
|
||||
function contentScript() {
|
||||
clipboardRead().then(function(dt) {
|
||||
let s = dt.getData("text/plain");
|
||||
clipboardRead().then(async function(items) {
|
||||
let blob = await items[0].getType("text/plain");
|
||||
let s = await blob.text();
|
||||
if (s == "HELLO") {
|
||||
browser.test.succeed("Read promise successfully read the right thing");
|
||||
} else {
|
||||
|
@ -323,24 +323,15 @@ add_task(async function test_contentscript_clipboard_nocontents_readtext() {
|
|||
await extension.unload();
|
||||
});
|
||||
|
||||
// Test that performing read(...) when the clipboard is empty returns an empty data transfer
|
||||
// Test that performing read(...) when the clipboard is empty returns an empty ClipboardItem
|
||||
add_task(async function test_contentscript_clipboard_nocontents_read() {
|
||||
function contentScript() {
|
||||
clipboardRead().then(function(dataT) {
|
||||
// On macOS if we clear the clipboard and read from it, there will be
|
||||
// no items in the data transfer object.
|
||||
// On linux with e10s enabled clearing of the clipboard does not happen in
|
||||
// the same way as it does on other platforms. So when we clear the clipboard
|
||||
// and read from it, the data transfer object contains an item of type
|
||||
// text/plain and kind string, but we can't call getAsString on it to verify
|
||||
// that at least it is an empty string because the callback never gets invoked.
|
||||
if (!dataT.items.length ||
|
||||
(dataT.items.length == 1 && dataT.items[0].type == "text/plain" &&
|
||||
dataT.items[0].kind == "string")) {
|
||||
browser.test.succeed("Read promise successfully resolved");
|
||||
} else {
|
||||
clipboardRead().then(function(items) {
|
||||
if (items[0].types.length) {
|
||||
browser.test.fail("Read read the wrong thing from clipboard, " +
|
||||
"data transfer has this many items:" + dataT.items.length);
|
||||
"ClipboardItem has this many entries: " + items[0].types.length);
|
||||
} else {
|
||||
browser.test.succeed("Read promise successfully resolved");
|
||||
}
|
||||
browser.test.sendMessage("ready");
|
||||
}, function(err) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче