Bug 1854747 - Stop exposing the image data as file to clipboard; r=evilpie

Differential Revision: https://phabricator.services.mozilla.com/D189242
This commit is contained in:
Edgar Chen 2023-10-05 15:26:35 +00:00
parent 7739355410
commit 3be03351ff
7 changed files with 73 additions and 37 deletions

View File

@ -40,6 +40,7 @@
#include "nsContentCID.h"
#ifdef XP_WIN
# include "mozilla/StaticPrefs_clipboard.h"
# include "nsCExternalHandlerService.h"
# include "nsEscape.h"
# include "nsIMIMEInfo.h"
@ -502,8 +503,10 @@ nsresult nsCopySupport::ImageCopy(nsIImageLoadingContent* aImageElement,
}
#ifdef XP_WIN
rv = AppendImagePromise(trans, imgRequest, aImageElement);
NS_ENSURE_SUCCESS(rv, rv);
if (StaticPrefs::clipboard_imageAsFile_enabled()) {
rv = AppendImagePromise(trans, imgRequest, aImageElement);
NS_ENSURE_SUCCESS(rv, rv);
}
#endif
// copy the image data onto the transferable

View File

@ -16,6 +16,7 @@ BROWSER_CHROME_MANIFESTS += [
]
MOCHITEST_MANIFESTS += [
"test/clipboard/mochitest.toml",
"test/mochitest.toml",
"test/pointerevents/mochitest.toml",
]

View File

@ -0,0 +1,7 @@
[DEFAULT]
["test_paste_image.html"]
skip-if = [
"headless", # Bug 1405869
"os == 'android'", # Image type isn't supported
]

View File

@ -14,9 +14,9 @@
images.push(aFile);
};
this.test = function() {
this.test = async function() {
for (var i = 0; i < images.length; i++) {
testImageSize(images[i]);
await testImageSize(images[i]);
}
};
@ -25,28 +25,31 @@
info("returned=" + counter + " images.length=" + images.length);
if (counter == images.length) {
info("test finish");
SimpleTest.finish();
}
};
function testImageSize(aFile) {
async function testImageSize(aFile) {
var source = window.URL.createObjectURL(aFile);
var image = new Image();
image.src = source;
var imageTester = that;
image.onload = function() {
is(this.width, 62, "Check generated image width");
is(this.height, 71, "Check generated image height");
let promise = new Promise(resolve => {
image.addEventListener("load", function(e) {
is(this.width, 62, "Check generated image width");
is(this.height, 71, "Check generated image height");
// This fails on OSX only.
if (!navigator.platform.includes("Mac")) {
testImageCanvas(image);
}
// This fails on OSX only.
if (!navigator.platform.includes("Mac")) {
testImageCanvas(image);
}
imageTester.returned();
}
imageTester.returned();
resolve();
}, { once: true });
});
document.body.appendChild(image);
await promise;
};
function testImageCanvas(aImage) {
@ -80,8 +83,10 @@
documentViewer.copyImage(documentViewer.COPY_IMAGE_ALL);
}
function doTest() {
SimpleTest.waitForExplicitFinish();
async function doTest(imageAsFileEnabled) {
await SpecialPowers.pushPrefEnv({
set: [["clipboard.imageAsFile.enabled", imageAsFileEnabled]],
});
copyImage('image');
@ -98,18 +103,30 @@
ok(clipboard.hasDataMatchingFlavors(["image/png"], clipboard.kGlobalClipboard),
"clipboard contains image");
window.addEventListener("paste", onPaste);
let promise = new Promise(resolve => {
window.addEventListener("paste", async (e) => {
isDeeply(e.clipboardData.types,
(navigator.platform.includes("Win") && imageAsFileEnabled) ?
["application/x-moz-file", "Files"] : ["text/html", "text/plain", "Files"]);
await onPaste(e, imageAsFileEnabled);
resolve();
}, { once: true });
});
var textarea = SpecialPowers.wrap(document.getElementById('textarea'));
textarea.focus();
textarea.editor.paste(clipboard.kGlobalClipboard);
await promise;
clipboard.emptyClipboard(clipboard.kGlobalClipboard);
}
function onPaste(e) {
async function onPaste(e, imageAsFileEnabled) {
var imageTester = new ImageTester;
testFiles(e, imageTester);
testFiles(e, imageTester, imageAsFileEnabled);
testItems(e, imageTester);
imageTester.test();
await imageTester.test();
}
function testItems(e, imageTester) {
@ -131,7 +148,7 @@
}
}
function testFiles(e, imageTester) {
function testFiles(e, imageTester, imageAsFileEnabled) {
var files = e.clipboardData.files;
is(files, e.clipboardData.files,
@ -141,15 +158,12 @@
var file = files[i];
ok(file instanceof File, ".files should contain only File objects");
ok(file.size > 0, "This file shouldn't have size 0");
if (navigator.platform.includes("Win")) {
// On Windows the pasted file is (sometimes?) produced from the Windows only
// file promise added by AppendImagePromise.
ok(file.name == "image.png" || (file.name.startsWith("Untitled") && file.name.endsWith(".png")),
`Correct filename, got "${file.name}"`);
if (navigator.platform.includes("Win") && imageAsFileEnabled) {
ok(file.name.startsWith("Untitled") && file.name.endsWith(".png"),
`Check filename, got "${file.name}"`);
} else {
is(file.name, "image.png", "Correct filename");
is(file.name, "image.png", "Check filename");
}
is(file.type, "image/png", "This file should be a image/png");
testSlice(file);
imageTester.add(file);
@ -177,8 +191,16 @@
is(blob.type, "image/png", ".slice @type check");
}
add_task(async function test_imageAsFile_enabled() {
await doTest(true);
});
add_task(async function test_imageAsFile_disabled() {
await doTest(false);
});
</script>
<body onload="doTest();">
<body>
<img id="image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABHCA
IAAADQjmMaAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3goUAwAgSAORBwAAABl0RVh0Q29
tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAABPSURBVGje7c4BDQAACAOga//OmuMbJGAurTbq

View File

@ -483,12 +483,6 @@ support-files = ["window_empty_document.html"]
["test_passive_listeners.html"]
["test_paste_image.html"]
skip-if = [
"headless", # Bug 1405869
"os == 'android'", # Image type isn't supported
]
["test_scroll_per_page.html"]
support-files = ["window_empty_document.html"]
skip-if = ["os == 'android'"] # fail

View File

@ -1857,6 +1857,12 @@
type: bool
value: false
mirror: always
# Whether to put a file promise onto the clipboard when copying images on Windows
- name: clipboard.imageAsFile.enabled
type: bool
value: @IS_NOT_EARLY_BETA_OR_EARLIER@
mirror: always
#endif
#---------------------------------------------------------------------------

View File

@ -372,7 +372,10 @@ if (AppConstants.platform != "macosx") {
// This test checks that copying an image provides the right filename
// for pasting to the local file system. This is only implemented on Windows.
if (AppConstants.platform == "win") {
const imageAsFileEnabled = SpecialPowers.getBoolPref(
"clipboard.imageAsFile.enabled"
);
if (AppConstants.platform == "win" && imageAsFileEnabled) {
add_task(async function copy_image() {
for (let idx = 0; idx < expectedItems.length; idx++) {
if (!expectedItems[idx].draggable) {