зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1810850 - Part 3: Move clipboard cache code for HasDataMatchingFlavors to nsBaseClipboard; r=cmartin,mstange
Depends on D179993 Differential Revision: https://phabricator.services.mozilla.com/D179999
This commit is contained in:
Родитель
2dd7f27175
Коммит
1d8c57b7a7
|
@ -24,8 +24,6 @@ class nsClipboard : public nsBaseClipboard {
|
|||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIClipboard
|
||||
NS_IMETHOD HasDataMatchingFlavors(const nsTArray<nsCString>& aFlavorList, int32_t aWhichClipboard,
|
||||
bool* _retval) override;
|
||||
NS_IMETHOD EmptyClipboard(int32_t aWhichClipboard) override;
|
||||
|
||||
// On macOS, cache the transferable of the current selection (chrome/content)
|
||||
|
@ -50,6 +48,8 @@ class nsClipboard : public nsBaseClipboard {
|
|||
int32_t aWhichClipboard) override;
|
||||
mozilla::Result<int32_t, nsresult> GetNativeClipboardSequenceNumber(
|
||||
int32_t aWhichClipboard) override;
|
||||
mozilla::Result<bool, nsresult> HasNativeClipboardDataMatchingFlavors(
|
||||
const nsTArray<nsCString>& aFlavorList, int32_t aWhichClipboard) override;
|
||||
|
||||
void ClearSelectionCache();
|
||||
void SetSelectionCache(nsITransferable* aTransferable);
|
||||
|
|
|
@ -347,59 +347,16 @@ nsClipboard::GetNativeClipboardData(nsITransferable* aTransferable, int32_t aWhi
|
|||
}
|
||||
|
||||
// returns true if we have *any* of the passed in flavors available for pasting
|
||||
NS_IMETHODIMP
|
||||
nsClipboard::HasDataMatchingFlavors(const nsTArray<nsCString>& aFlavorList, int32_t aWhichClipboard,
|
||||
bool* outResult) {
|
||||
mozilla::Result<bool, nsresult> nsClipboard::HasNativeClipboardDataMatchingFlavors(
|
||||
const nsTArray<nsCString>& aFlavorList, int32_t aWhichClipboard) {
|
||||
NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
|
||||
|
||||
CLIPBOARD_LOG("%s: clipboard=%i", __FUNCTION__, aWhichClipboard);
|
||||
CLIPBOARD_LOG(" Asking for content:\n");
|
||||
for (auto& flavor : aFlavorList) {
|
||||
CLIPBOARD_LOG(" MIME %s\n", flavor.get());
|
||||
}
|
||||
|
||||
*outResult = false;
|
||||
|
||||
// We only support the set operation on kSelectionCache type, see bug 1835059.
|
||||
if ((aWhichClipboard != kGlobalClipboard && aWhichClipboard != kFindClipboard)) {
|
||||
return NS_OK;
|
||||
}
|
||||
// XXX we only support the set operation on kSelectionCache type, see bug 1835059.
|
||||
MOZ_DIAGNOSTIC_ASSERT(kSelectionCache != aWhichClipboard);
|
||||
MOZ_DIAGNOSTIC_ASSERT(nsIClipboard::IsClipboardTypeSupported(aWhichClipboard));
|
||||
|
||||
NSPasteboard* cocoaPasteboard = GetPasteboard(aWhichClipboard);
|
||||
MOZ_ASSERT(cocoaPasteboard);
|
||||
if (mCachedClipboard == aWhichClipboard) {
|
||||
const auto& clipboardCache = mCaches[mCachedClipboard];
|
||||
MOZ_ASSERT(clipboardCache);
|
||||
if (mChangeCount != [cocoaPasteboard changeCount]) {
|
||||
// Clear the cached transferable as it is no longer valid.
|
||||
clipboardCache->Clear();
|
||||
} else if (nsITransferable* cachedTrans = clipboardCache->GetTransferable()) {
|
||||
// See if we have data for this in our cached transferable.
|
||||
nsTArray<nsCString> flavors;
|
||||
nsresult rv = cachedTrans->FlavorsTransferableCanImport(flavors);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (CLIPBOARD_LOG_ENABLED()) {
|
||||
CLIPBOARD_LOG(" Cached transferable types (nums %zu)\n", flavors.Length());
|
||||
for (uint32_t j = 0; j < flavors.Length(); j++) {
|
||||
CLIPBOARD_LOG(" MIME %s\n", flavors[j].get());
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t j = 0; j < flavors.Length(); j++) {
|
||||
const nsCString& transferableFlavorStr = flavors[j];
|
||||
|
||||
for (uint32_t k = 0; k < aFlavorList.Length(); k++) {
|
||||
if (transferableFlavorStr.Equals(aFlavorList[k])) {
|
||||
CLIPBOARD_LOG(" has %s\n", aFlavorList[k].get());
|
||||
*outResult = true;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CLIPBOARD_LOG_ENABLED()) {
|
||||
NSArray* types = [cocoaPasteboard types];
|
||||
uint32_t count = [types count];
|
||||
|
@ -421,8 +378,7 @@ nsClipboard::HasDataMatchingFlavors(const nsTArray<nsCString>& aFlavorList, int3
|
|||
[cocoaPasteboard availableTypeFromArray:[NSArray arrayWithObject:pboardType]];
|
||||
if (availableType && [availableType isEqualToString:pboardType]) {
|
||||
CLIPBOARD_LOG(" has %s\n", mimeType.get());
|
||||
*outResult = true;
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
} else if (mimeType.EqualsLiteral(kCustomTypesMime)) {
|
||||
NSString* availableType = [cocoaPasteboard
|
||||
|
@ -430,8 +386,7 @@ nsClipboard::HasDataMatchingFlavors(const nsTArray<nsCString>& aFlavorList, int3
|
|||
[NSArray arrayWithObject:[UTIHelper stringFromPboardType:kMozCustomTypesPboardType]]];
|
||||
if (availableType) {
|
||||
CLIPBOARD_LOG(" has %s\n", mimeType.get());
|
||||
*outResult = true;
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
} else if (mimeType.EqualsLiteral(kJPEGImageMime) || mimeType.EqualsLiteral(kJPGImageMime) ||
|
||||
mimeType.EqualsLiteral(kPNGImageMime) || mimeType.EqualsLiteral(kGIFImageMime)) {
|
||||
|
@ -441,8 +396,7 @@ nsClipboard::HasDataMatchingFlavors(const nsTArray<nsCString>& aFlavorList, int3
|
|||
[UTIHelper stringFromPboardType:NSPasteboardTypePNG], nil]];
|
||||
if (availableType) {
|
||||
CLIPBOARD_LOG(" has %s\n", mimeType.get());
|
||||
*outResult = true;
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
} else if (mimeType.EqualsLiteral(kFileMime)) {
|
||||
NSArray* items = [cocoaPasteboard pasteboardItems];
|
||||
|
@ -456,21 +410,20 @@ nsClipboard::HasDataMatchingFlavors(const nsTArray<nsCString>& aFlavorList, int3
|
|||
stringFromPboardType:(NSString*)kUTTypeFileURL],
|
||||
nil]]) {
|
||||
CLIPBOARD_LOG(" has %s\n", mimeType.get());
|
||||
*outResult = true;
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CLIPBOARD_LOG_ENABLED() && !(*outResult)) {
|
||||
if (CLIPBOARD_LOG_ENABLED()) {
|
||||
CLIPBOARD_LOG(" no targets at clipboard (bad match)\n");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return false;
|
||||
|
||||
NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
|
||||
NS_OBJC_END_TRY_BLOCK_RETURN(mozilla::Err(NS_ERROR_FAILURE));
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -293,8 +293,67 @@ NS_IMETHODIMP nsBaseClipboard::EmptyClipboard(int32_t aWhichClipboard) {
|
|||
NS_IMETHODIMP
|
||||
nsBaseClipboard::HasDataMatchingFlavors(const nsTArray<nsCString>& aFlavorList,
|
||||
int32_t aWhichClipboard,
|
||||
bool* outResult) {
|
||||
*outResult = true; // say we always do.
|
||||
bool* aOutResult) {
|
||||
CLIPBOARD_LOG("%s: clipboard=%d", __FUNCTION__, aWhichClipboard);
|
||||
if (CLIPBOARD_LOG_ENABLED()) {
|
||||
CLIPBOARD_LOG(" Asking for content clipboard=%i:\n", aWhichClipboard);
|
||||
for (const auto& flavor : aFlavorList) {
|
||||
CLIPBOARD_LOG(" MIME %s", flavor.get());
|
||||
}
|
||||
}
|
||||
|
||||
*aOutResult = false;
|
||||
|
||||
// XXX as of now, we only support the set operation on kSelectionCache type,
|
||||
// should we also support the get operation? See also bug 1835059.
|
||||
if (kSelectionCache == aWhichClipboard ||
|
||||
!nsIClipboard::IsClipboardTypeSupported(aWhichClipboard)) {
|
||||
CLIPBOARD_LOG("%s: clipboard %d is not supported.", __FUNCTION__,
|
||||
aWhichClipboard);
|
||||
// XXX should we return a error instead?
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mozilla::StaticPrefs::widget_clipboard_use_cached_data_enabled()) {
|
||||
if (auto* clipboardCache = GetClipboardCacheIfValid(aWhichClipboard)) {
|
||||
MOZ_ASSERT(clipboardCache->GetTransferable());
|
||||
|
||||
// first see if we have data for this in our cached transferable
|
||||
nsTArray<nsCString> transferableFlavors;
|
||||
nsresult rv =
|
||||
clipboardCache->GetTransferable()->FlavorsTransferableCanImport(
|
||||
transferableFlavors);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (CLIPBOARD_LOG_ENABLED()) {
|
||||
CLIPBOARD_LOG(" Cached transferable types (nums %zu)\n",
|
||||
transferableFlavors.Length());
|
||||
for (const auto& transferableFlavor : transferableFlavors) {
|
||||
CLIPBOARD_LOG(" MIME %s", transferableFlavor.get());
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& transferableFlavor : transferableFlavors) {
|
||||
for (const auto& flavor : aFlavorList) {
|
||||
if (transferableFlavor.Equals(flavor)) {
|
||||
CLIPBOARD_LOG(" has %s", flavor.get());
|
||||
*aOutResult = true;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto resultOrError =
|
||||
HasNativeClipboardDataMatchingFlavors(aFlavorList, aWhichClipboard);
|
||||
if (resultOrError.isErr()) {
|
||||
CLIPBOARD_LOG("%s: checking native clipboard data matching flavors falied.",
|
||||
__FUNCTION__);
|
||||
return resultOrError.unwrapErr();
|
||||
}
|
||||
|
||||
*aOutResult = resultOrError.unwrap();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -110,13 +110,14 @@ class nsBaseClipboard : public ClipboardSetDataHelper {
|
|||
NS_IMETHOD EmptyClipboard(int32_t aWhichClipboard) override;
|
||||
NS_IMETHOD HasDataMatchingFlavors(const nsTArray<nsCString>& aFlavorList,
|
||||
int32_t aWhichClipboard,
|
||||
bool* _retval) override;
|
||||
bool* aOutResult) override final;
|
||||
NS_IMETHOD IsClipboardTypeSupported(int32_t aWhichClipboard,
|
||||
bool* aRetval) override final;
|
||||
RefPtr<mozilla::GenericPromise> AsyncGetData(
|
||||
nsITransferable* aTransferable, int32_t aWhichClipboard) override final;
|
||||
RefPtr<DataFlavorsPromise> AsyncHasDataMatchingFlavors(
|
||||
const nsTArray<nsCString>& aFlavorList, int32_t aWhichClipboard) override;
|
||||
const nsTArray<nsCString>& aFlavorList,
|
||||
int32_t aWhichClipboard) override final;
|
||||
|
||||
protected:
|
||||
virtual ~nsBaseClipboard() = default;
|
||||
|
@ -126,7 +127,12 @@ class nsBaseClipboard : public ClipboardSetDataHelper {
|
|||
int32_t aWhichClipboard) = 0;
|
||||
virtual mozilla::Result<int32_t, nsresult> GetNativeClipboardSequenceNumber(
|
||||
int32_t aWhichClipboard) = 0;
|
||||
virtual mozilla::Result<bool, nsresult> HasNativeClipboardDataMatchingFlavors(
|
||||
const nsTArray<nsCString>& aFlavorList, int32_t aWhichClipboard) = 0;
|
||||
|
||||
bool mEmptyingForSetData = false;
|
||||
|
||||
private:
|
||||
class ClipboardCache final {
|
||||
public:
|
||||
~ClipboardCache() {
|
||||
|
@ -157,14 +163,11 @@ class nsBaseClipboard : public ClipboardSetDataHelper {
|
|||
int32_t mSequenceNumber = -1;
|
||||
};
|
||||
|
||||
mozilla::UniquePtr<ClipboardCache> mCaches[nsIClipboard::kClipboardTypeCount];
|
||||
bool mEmptyingForSetData = false;
|
||||
|
||||
private:
|
||||
// Return clipboard cache if the cached data is valid, otherwise clear the
|
||||
// cached data and returns null.
|
||||
ClipboardCache* GetClipboardCacheIfValid(int32_t aClipboardType);
|
||||
|
||||
mozilla::UniquePtr<ClipboardCache> mCaches[nsIClipboard::kClipboardTypeCount];
|
||||
const mozilla::dom::ClipboardCapabilities mClipboardCaps;
|
||||
bool mIgnoreEmptyNotification = false;
|
||||
};
|
||||
|
|
|
@ -82,28 +82,56 @@ clipboardTypes.forEach(function(type) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (clipboard.kGlobalClipboard != type) {
|
||||
add_task(function test_clipboard_hasDataMatchingFlavors() {
|
||||
info(`Test write data to clipboard type ${type}`);
|
||||
add_task(function test_clipboard_hasDataMatchingFlavors() {
|
||||
const trans = generateNewTransferable("text/plain", generateRandomString());
|
||||
|
||||
// Write text/plain data to main clipboard.
|
||||
writeRandomStringToClipboard("text/plain", clipboard.kGlobalClipboard);
|
||||
ok(clipboard.hasDataMatchingFlavors(["text/plain"], clipboard.kGlobalClipboard),
|
||||
"Should have text/plain flavor");
|
||||
ok(!clipboard.hasDataMatchingFlavors(["text/html"], clipboard.kGlobalClipboard),
|
||||
"Should not have text/html flavor");
|
||||
info(`Write text/plain data to clipboard ${type}`);
|
||||
clipboard.setData(trans, null, type);
|
||||
ok(clipboard.hasDataMatchingFlavors(["text/plain"], type),
|
||||
`Check if there is text/plain flavor on clipboard ${type}`);
|
||||
ok(!clipboard.hasDataMatchingFlavors(["text/foo"], type),
|
||||
`Check if there is text/foo flavor on clipboard ${type}`);
|
||||
|
||||
// Write text/html data to other clipboard.
|
||||
writeRandomStringToClipboard("text/html", type);
|
||||
ok(clipboard.hasDataMatchingFlavors(["text/plain"], clipboard.kGlobalClipboard),
|
||||
"Should have text/plain flavor");
|
||||
ok(!clipboard.hasDataMatchingFlavors(["text/html"], clipboard.kGlobalClipboard),
|
||||
"Should not have text/html flavor");
|
||||
info(`Add text/foo data to transferable`);
|
||||
addStringToTransferable("text/foo", generateRandomString(), trans);
|
||||
ok(clipboard.hasDataMatchingFlavors(["text/plain"], type),
|
||||
`Check if there is text/plain flavor on clipboard ${type}`);
|
||||
is(clipboard.hasDataMatchingFlavors(["text/foo"], type),
|
||||
isSupportGetFromCachedTransferable,
|
||||
`Check if there is text/foo flavor on clipboard ${type}`);
|
||||
|
||||
// Clean clipboard data.
|
||||
cleanupAllClipboard();
|
||||
// Check other clipboard types.
|
||||
clipboardTypes.forEach(function(otherType) {
|
||||
if (otherType != clipboard.kSelectionCache &&
|
||||
otherType != type &&
|
||||
clipboard.isClipboardTypeSupported(otherType)) {
|
||||
ok(!clipboard.hasDataMatchingFlavors(["text/plain"], otherType),
|
||||
`Check if there is text/plain flavor on clipboard ${otherType}`);
|
||||
ok(!clipboard.hasDataMatchingFlavors(["text/foo"], otherType),
|
||||
`Check if there is text/foo flavor on clipboard ${otherType}`);
|
||||
|
||||
info(`Write text/plain data to clipboard ${otherType}`);
|
||||
writeRandomStringToClipboard("text/plain", otherType);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Check again.
|
||||
ok(clipboard.hasDataMatchingFlavors(["text/plain"], type),
|
||||
`Check if there is text/plain flavor on clipboard ${type}`);
|
||||
is(clipboard.hasDataMatchingFlavors(["text/foo"], type),
|
||||
isSupportGetFromCachedTransferable,
|
||||
`Check if there is text/foo flavor on clipboard ${type}`);
|
||||
|
||||
info(`Write text/plain data to clipboard ${type} again`);
|
||||
writeRandomStringToClipboard("text/plain", type);
|
||||
ok(clipboard.hasDataMatchingFlavors(["text/plain"], type),
|
||||
`Check if there is text/plain flavor on clipboard ${type}`);
|
||||
ok(!clipboard.hasDataMatchingFlavors(["text/foo"], type),
|
||||
`Check if there is text/foo flavor on clipboard ${type}`);
|
||||
|
||||
// Clean clipboard data.
|
||||
cleanupAllClipboard();
|
||||
});
|
||||
|
||||
// Test sync set clipboard data.
|
||||
testClipboardCache(type, false);
|
||||
|
|
|
@ -1361,23 +1361,18 @@ nsClipboard::GetNativeClipboardSequenceNumber(int32_t aWhichClipboard) {
|
|||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsClipboard::HasDataMatchingFlavors(
|
||||
const nsTArray<nsCString>& aFlavorList, int32_t aWhichClipboard,
|
||||
bool* _retval) {
|
||||
*_retval = false;
|
||||
if (aWhichClipboard != kGlobalClipboard) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
for (auto& flavor : aFlavorList) {
|
||||
mozilla::Result<bool, nsresult>
|
||||
nsClipboard::HasNativeClipboardDataMatchingFlavors(
|
||||
const nsTArray<nsCString>& aFlavorList, int32_t aWhichClipboard) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
nsIClipboard::IsClipboardTypeSupported(aWhichClipboard));
|
||||
for (const auto& flavor : aFlavorList) {
|
||||
UINT format = GetFormat(flavor.get());
|
||||
if (IsClipboardFormatAvailable(format)) {
|
||||
*_retval = true;
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
|
|
@ -34,9 +34,6 @@ class nsClipboard : public nsBaseClipboard, public nsIObserver {
|
|||
NS_DECL_NSIOBSERVER
|
||||
|
||||
// nsIClipboard
|
||||
NS_IMETHOD HasDataMatchingFlavors(const nsTArray<nsCString>& aFlavorList,
|
||||
int32_t aWhichClipboard,
|
||||
bool* _retval) override;
|
||||
NS_IMETHOD EmptyClipboard(int32_t aWhichClipboard) override;
|
||||
|
||||
// Internal Native Routines
|
||||
|
@ -84,6 +81,8 @@ class nsClipboard : public nsBaseClipboard, public nsIObserver {
|
|||
int32_t aWhichClipboard) override;
|
||||
mozilla::Result<int32_t, nsresult> GetNativeClipboardSequenceNumber(
|
||||
int32_t aWhichClipboard) override;
|
||||
mozilla::Result<bool, nsresult> HasNativeClipboardDataMatchingFlavors(
|
||||
const nsTArray<nsCString>& aFlavorList, int32_t aWhichClipboard) override;
|
||||
|
||||
static bool IsInternetShortcut(const nsAString& inFileName);
|
||||
static bool FindURLFromLocalFile(IDataObject* inDataObject, UINT inIndex,
|
||||
|
|
Загрузка…
Ссылка в новой задаче