forked from mirrors/gecko-dev
Bug 1858788 - Implement ClipboardItem.supports; r=nika
See https://w3c.github.io/clipboard-apis/#dom-clipboarditem-supports and we currently support mandatory types only. Differential Revision: https://phabricator.services.mozilla.com/D205651
This commit is contained in:
parent
d3b59ee280
commit
cd503d19cf
8 changed files with 69 additions and 34 deletions
|
|
@ -59,6 +59,19 @@ bool Clipboard::IsTestingPrefEnabledOrHasReadPermission(
|
||||||
nsGkAtoms::clipboardRead);
|
nsGkAtoms::clipboardRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mandatory data types defined in
|
||||||
|
// https://w3c.github.io/clipboard-apis/#mandatory-data-types-x. The types
|
||||||
|
// should be in the same order as kNonPlainTextExternalFormats in
|
||||||
|
// DataTransfer.
|
||||||
|
static const nsLiteralCString kMandatoryDataTypes[] = {
|
||||||
|
nsLiteralCString(kHTMLMime), nsLiteralCString(kTextMime),
|
||||||
|
nsLiteralCString(kPNGImageMime)};
|
||||||
|
|
||||||
|
// static
|
||||||
|
Span<const nsLiteralCString> Clipboard::MandatoryDataTypes() {
|
||||||
|
return Span<const nsLiteralCString>(kMandatoryDataTypes);
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -87,16 +100,6 @@ class ClipboardGetCallback : public nsIAsyncClipboardGetCallback {
|
||||||
RefPtr<Promise> mPromise;
|
RefPtr<Promise> mPromise;
|
||||||
};
|
};
|
||||||
|
|
||||||
static nsTArray<nsCString> MandatoryDataTypesAsCStrings() {
|
|
||||||
// Mandatory data types defined in
|
|
||||||
// https://w3c.github.io/clipboard-apis/#mandatory-data-types-x. The types
|
|
||||||
// should be in the same order as kNonPlainTextExternalFormats in
|
|
||||||
// DataTransfer.
|
|
||||||
return nsTArray<nsCString>{nsLiteralCString(kHTMLMime),
|
|
||||||
nsLiteralCString(kTextMime),
|
|
||||||
nsLiteralCString(kPNGImageMime)};
|
|
||||||
}
|
|
||||||
|
|
||||||
class ClipboardGetCallbackForRead final : public ClipboardGetCallback {
|
class ClipboardGetCallbackForRead final : public ClipboardGetCallback {
|
||||||
public:
|
public:
|
||||||
explicit ClipboardGetCallbackForRead(nsIGlobalObject* aGlobal,
|
explicit ClipboardGetCallbackForRead(nsIGlobalObject* aGlobal,
|
||||||
|
|
@ -122,7 +125,7 @@ class ClipboardGetCallbackForRead final : public ClipboardGetCallback {
|
||||||
AutoTArray<RefPtr<ClipboardItem::ItemEntry>, 3> entries;
|
AutoTArray<RefPtr<ClipboardItem::ItemEntry>, 3> entries;
|
||||||
// We might reuse the request from DataTransfer created for paste event,
|
// We might reuse the request from DataTransfer created for paste event,
|
||||||
// which could contain more types that are not in the mandatory list.
|
// which could contain more types that are not in the mandatory list.
|
||||||
for (const auto& format : MandatoryDataTypesAsCStrings()) {
|
for (const auto& format : kMandatoryDataTypes) {
|
||||||
if (flavorList.Contains(format)) {
|
if (flavorList.Contains(format)) {
|
||||||
auto entry = MakeRefPtr<ClipboardItem::ItemEntry>(
|
auto entry = MakeRefPtr<ClipboardItem::ItemEntry>(
|
||||||
mGlobal, NS_ConvertUTF8toUTF16(format));
|
mGlobal, NS_ConvertUTF8toUTF16(format));
|
||||||
|
|
@ -287,10 +290,13 @@ void Clipboard::RequestRead(Promise* aPromise, ReadRequestType aType,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AutoTArray<nsCString, ArrayLength(kMandatoryDataTypes)> types;
|
||||||
|
types.AppendElements(Span<const nsLiteralCString>(kMandatoryDataTypes));
|
||||||
|
|
||||||
callback = MakeRefPtr<ClipboardGetCallbackForRead>(global, std::move(p));
|
callback = MakeRefPtr<ClipboardGetCallbackForRead>(global, std::move(p));
|
||||||
rv = clipboardService->AsyncGetData(
|
rv = clipboardService->AsyncGetData(types, nsIClipboard::kGlobalClipboard,
|
||||||
MandatoryDataTypesAsCStrings(), nsIClipboard::kGlobalClipboard,
|
owner->GetWindowContext(),
|
||||||
owner->GetWindowContext(), &aPrincipal, callback);
|
&aPrincipal, callback);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ReadRequestType::eReadText: {
|
case ReadRequestType::eReadText: {
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,8 @@ class Clipboard : public DOMEventTargetHelper {
|
||||||
// testing purposes.
|
// testing purposes.
|
||||||
static bool ReadTextEnabled(JSContext* aCx, JSObject* aGlobal);
|
static bool ReadTextEnabled(JSContext* aCx, JSObject* aGlobal);
|
||||||
|
|
||||||
|
static Span<const nsLiteralCString> MandatoryDataTypes();
|
||||||
|
|
||||||
virtual JSObject* WrapObject(JSContext* aCx,
|
virtual JSObject* WrapObject(JSContext* aCx,
|
||||||
JS::Handle<JSObject*> aGivenProto) override;
|
JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "mozilla/dom/ClipboardItem.h"
|
#include "mozilla/dom/ClipboardItem.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/Clipboard.h"
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
#include "mozilla/dom/Record.h"
|
#include "mozilla/dom/Record.h"
|
||||||
#include "nsComponentManagerUtils.h"
|
#include "nsComponentManagerUtils.h"
|
||||||
|
|
@ -290,6 +291,17 @@ already_AddRefed<ClipboardItem> ClipboardItem::Constructor(
|
||||||
return item.forget();
|
return item.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
bool ClipboardItem::Supports(const GlobalObject& aGlobal,
|
||||||
|
const nsAString& aType) {
|
||||||
|
for (const auto& mandatoryType : Clipboard::MandatoryDataTypes()) {
|
||||||
|
if (CompareUTF8toUTF16(mandatoryType, aType) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void ClipboardItem::GetTypes(nsTArray<nsString>& aTypes) const {
|
void ClipboardItem::GetTypes(nsTArray<nsString>& aTypes) const {
|
||||||
for (const auto& item : mItems) {
|
for (const auto& item : mItems) {
|
||||||
aTypes.AppendElement(item->Type());
|
aTypes.AppendElement(item->Type());
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,8 @@ class ClipboardItem final : public nsWrapperCache {
|
||||||
const Record<nsString, OwningNonNull<Promise>>& aItems,
|
const Record<nsString, OwningNonNull<Promise>>& aItems,
|
||||||
const ClipboardItemOptions& aOptions, ErrorResult& aRv);
|
const ClipboardItemOptions& aOptions, ErrorResult& aRv);
|
||||||
|
|
||||||
|
static bool Supports(const GlobalObject& aGlobal, const nsAString& aType);
|
||||||
|
|
||||||
dom::PresentationStyle PresentationStyle() const {
|
dom::PresentationStyle PresentationStyle() const {
|
||||||
return mPresentationStyle;
|
return mPresentationStyle;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,8 @@ interface ClipboardItem {
|
||||||
|
|
||||||
[NewObject]
|
[NewObject]
|
||||||
Promise<Blob> getType(DOMString type);
|
Promise<Blob> getType(DOMString type);
|
||||||
|
|
||||||
|
static boolean supports(DOMString type);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PresentationStyle { "unspecified", "inline", "attachment" };
|
enum PresentationStyle { "unspecified", "inline", "attachment" };
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
[clipboard-item.https.html]
|
[clipboard-item.https.html]
|
||||||
expected:
|
expected:
|
||||||
if (os == "android") and fission: [OK, TIMEOUT]
|
if (os == "android") and fission: [OK, TIMEOUT]
|
||||||
[supports(DOMString) returns true for types that are supported, false otherwise]
|
[supports(image/svg+xml) returns true]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[supports(web foo/bar) returns true]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[supports(web text/html) returns true]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
[idlharness.https.window.html]
|
[idlharness.https.window.html]
|
||||||
expected:
|
expected:
|
||||||
if (os == "android") and fission: [OK, TIMEOUT]
|
if (os == "android") and fission: [OK, TIMEOUT]
|
||||||
[ClipboardItem interface: operation supports(DOMString)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
||||||
|
|
@ -96,21 +96,28 @@ promise_test(async () => {
|
||||||
assert_equals(text, 'xxx');
|
assert_equals(text, 'xxx');
|
||||||
}, "getType(DOMString invalid type) converts DOMString to Blob");
|
}, "getType(DOMString invalid type) converts DOMString to Blob");
|
||||||
|
|
||||||
promise_test(async () => {
|
[
|
||||||
assert_true(ClipboardItem.supports('text/plain'));
|
// mandatory data types
|
||||||
assert_true(ClipboardItem.supports('text/html'));
|
['text/plain', true],
|
||||||
assert_true(ClipboardItem.supports('image/png'));
|
['text/html', true],
|
||||||
assert_true(ClipboardItem.supports('image/svg+xml'));
|
['image/png', true],
|
||||||
assert_false(ClipboardItem.supports('web '));
|
// optional data types
|
||||||
assert_false(ClipboardItem.supports('web')); // without space.
|
['image/svg+xml', true],
|
||||||
assert_false(ClipboardItem.supports('web foo'));
|
['web foo/bar', true],
|
||||||
assert_false(ClipboardItem.supports('foo/bar'));
|
['web text/html', true],
|
||||||
assert_true(ClipboardItem.supports('web foo/bar'));
|
// invalid types
|
||||||
assert_true(ClipboardItem.supports('web text/html'));
|
['web ', false],
|
||||||
assert_false(ClipboardItem.supports('weB text/html'));
|
['web', false],
|
||||||
assert_false(ClipboardItem.supports(' web text/html'));
|
['web foo', false],
|
||||||
assert_false(ClipboardItem.supports('not a/real type'));
|
['foo/bar', false],
|
||||||
assert_false(ClipboardItem.supports(''));
|
['weB text/html', false],
|
||||||
assert_false(ClipboardItem.supports(' '));
|
[' web text/html', false],
|
||||||
}, "supports(DOMString) returns true for types that are supported, false otherwise");
|
['not a/real type', false],
|
||||||
|
['', false],
|
||||||
|
[' ', false],
|
||||||
|
].forEach(([type, result]) => {
|
||||||
|
promise_test(async () => {
|
||||||
|
assert_equals(ClipboardItem.supports(type), result);
|
||||||
|
}, `supports(${type}) returns ${result ? "true" : "false"}`);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue