Bug 1611407 [Linux/X11] Don't try to get text clipboard data of binary MIME types, r=jhorak

X11 tries to convert any binary clipboard data to text if text MIME type is missing in clipboard.
This leads to various errors, wrong conversions and timeouts.
So get clipboard content first and if there are only binary MIME types in clipboard advertise only these types.

Differential Revision: https://phabricator.services.mozilla.com/D123687
This commit is contained in:
stransky 2021-09-09 09:46:09 +00:00
Родитель 8197b9611b
Коммит 646adf404e
3 изменённых файлов: 89 добавлений и 4 удалений

Просмотреть файл

@ -253,6 +253,76 @@ void nsClipboard::SetTransferableData(nsITransferable* aTransferable,
aTransferable->SetTransferData(aFlavor.get(), wrapper);
}
static bool IsMIMEAtFlavourList(const nsTArray<nsCString>& aFlavourList,
const char* aMime) {
for (const auto& flavorStr : aFlavourList) {
if (flavorStr.Equals(aMime)) {
return true;
}
}
return false;
}
// When clipboard contains only images, X11/Gtk tries to convert them
// to text when we request text instead of just fail to provide the data.
// So if clipboard contains images only remove text MIME offer.
bool nsClipboard::FilterImportedFlavors(int32_t aWhichClipboard,
nsTArray<nsCString>& aFlavors) {
LOGCLIP(("nsClipboard::FilterImportedFlavors"));
int targetNums;
GdkAtom* targets = mContext->GetTargets(aWhichClipboard, &targetNums);
if (!targets) {
LOGCLIP((" X11: no targes at clipboard (null), quit.\n"));
return false;
}
for (int i = 0; i < targetNums; i++) {
gchar* atom_name = gdk_atom_name(targets[i]);
if (!atom_name) {
continue;
}
// Filter out system MIME types.
if (strcmp(atom_name, "TARGETS") == 0 ||
strcmp(atom_name, "TIMESTAMP") == 0 ||
strcmp(atom_name, "SAVE_TARGETS") == 0 ||
strcmp(atom_name, "MULTIPLE") == 0) {
continue;
}
// Filter out types which can't be converted to text.
if (strncmp(atom_name, "image/", 6) == 0 ||
strncmp(atom_name, "application/", 12) == 0 ||
strncmp(atom_name, "audio/", 6) == 0 ||
strncmp(atom_name, "video/", 6) == 0) {
continue;
}
// We have some other MIME type on clipboard which can be hopefully
// converted to text without any problem.
LOGCLIP((" X11: text types in clipboard, no need to filter them.\n"));
return true;
}
// So make sure we offer only types we have at clipboard.
nsTArray<nsCString> clipboardFlavors;
for (int i = 0; i < targetNums; i++) {
gchar* atom_name = gdk_atom_name(targets[i]);
if (!atom_name) {
continue;
}
if (IsMIMEAtFlavourList(aFlavors, atom_name)) {
clipboardFlavors.AppendElement(nsCString(atom_name));
}
}
aFlavors.SwapElements(clipboardFlavors);
#ifdef MOZ_LOGGING
LOGCLIP((" X11: Flavors which match clipboard content:\n"));
for (uint32_t i = 0; i < aFlavors.Length(); i++) {
LOGCLIP((" %s\n", aFlavors[i].get()));
}
#endif
return true;
}
NS_IMETHODIMP
nsClipboard::GetData(nsITransferable* aTransferable, int32_t aWhichClipboard) {
LOGCLIP(("nsClipboard::GetData (%s)\n",
@ -270,7 +340,6 @@ nsClipboard::GetData(nsITransferable* aTransferable, int32_t aWhichClipboard) {
LOGCLIP((" FlavorsTransferableCanImport falied!\n"));
return rv;
}
#ifdef MOZ_LOGGING
LOGCLIP(("Flavors which can be imported:\n"));
for (uint32_t i = 0; i < flavors.Length(); i++) {
@ -278,6 +347,14 @@ nsClipboard::GetData(nsITransferable* aTransferable, int32_t aWhichClipboard) {
}
#endif
// Filter out MIME types on X11 to prevent unwanted conversions,
// see Bug 1611407
if (widget::GdkIsX11Display()) {
if (!FilterImportedFlavors(aWhichClipboard, flavors)) {
return NS_OK;
}
}
for (uint32_t i = 0; i < flavors.Length(); i++) {
nsCString& flavorStr = flavors[i];

Просмотреть файл

@ -80,6 +80,9 @@ class nsClipboard : public nsIClipboard, public nsIObserver {
void ClearTransferable(int32_t aWhichClipboard);
bool FilterImportedFlavors(int32_t aWhichClipboard,
nsTArray<nsCString>& aFlavors);
// Hang on to our owners and transferables so we can transfer data
// when asked.
nsCOMPtr<nsIClipboardOwner> mSelectionOwner;

Просмотреть файл

@ -204,9 +204,11 @@ void nsRetrievalContextX11::Complete(ClipboardDataType aDataType,
gint dataLength = gtk_selection_data_get_length(selection);
const guchar* data = gtk_selection_data_get_data(selection);
LOGCLIP((" got data %p len %d\n", data, dataLength));
#ifdef MOZ_LOGGING
GdkAtom target = gtk_selection_data_get_target(selection);
LOGCLIP((" got data %p len %d MIME %s\n", data, dataLength,
gdk_atom_name(target)));
#endif
if (dataLength > 0) {
mClipboardDataLength = dataLength;
mClipboardData = moz_xmalloc(dataLength);
@ -266,14 +268,17 @@ bool nsRetrievalContextX11::WaitForClipboardData(ClipboardDataType aDataType,
switch (aDataType) {
case CLIPBOARD_DATA:
LOGCLIP((" getting DATA MIME %s\n", aMimeType));
gtk_clipboard_request_contents(clipboard,
gdk_atom_intern(aMimeType, FALSE),
clipboard_contents_received, handler);
break;
case CLIPBOARD_TEXT:
LOGCLIP((" getting TEXT\n"));
gtk_clipboard_request_text(clipboard, clipboard_text_received, handler);
break;
case CLIPBOARD_TARGETS:
LOGCLIP((" getting TARGETS\n"));
gtk_clipboard_request_contents(clipboard, mTargetMIMEType,
clipboard_contents_received, handler);
break;