Skip to content
Extraits de code Groupes Projets
Non vérifiée Valider d8d43a42 rédigé par ThibG's avatar ThibG Validation de GitHub
Parcourir les fichiers

Fix image uploads being random data when canvas read access is blocked (#15180)

Fixes #15178

PR #11499 introduced a way to deal with all-white canvas, but newer
Firefox versions set random data instead.

This PR detects whether canvas operations are reliable by comparing
the results on a hardcoded 2×2 pixels image, and memoizing the result.

This should be both more reliable and faster than the previous check.
parent 18ca4e0e
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
...@@ -41,6 +41,45 @@ const dropOrientationIfNeeded = (orientation) => new Promise(resolve => { ...@@ -41,6 +41,45 @@ const dropOrientationIfNeeded = (orientation) => new Promise(resolve => {
} }
}); });
// Some browsers don't allow reading from a canvas and instead return all-white
// or randomized data. Use a pre-defined image to check if reading the canvas
// works.
const checkCanvasReliability = () => new Promise((resolve, reject) => {
switch(_browser_quirks['canvas-read-unreliable']) {
case true:
reject('Canvas reading unreliable');
break;
case false:
resolve();
break;
default:
// 2×2 GIF with white, red, green and blue pixels
const testImageURL =
'data:image/gif;base64,R0lGODdhAgACAKEDAAAA//8AAAD/AP///ywAAAAAAgACAAACA1wEBQA7';
const refData =
[255, 255, 255, 255, 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255];
const img = new Image();
img.onload = () => {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
context.drawImage(img, 0, 0, 2, 2);
const imageData = context.getImageData(0, 0, 2, 2);
if (imageData.data.every((x, i) => refData[i] === x)) {
_browser_quirks['canvas-read-unreliable'] = false;
resolve();
} else {
_browser_quirks['canvas-read-unreliable'] = true;
reject('Canvas reading unreliable');
}
};
img.onerror = () => {
_browser_quirks['canvas-read-unreliable'] = true;
reject('Failed to load test image');
};
img.src = testImageURL;
}
});
const getImageUrl = inputFile => new Promise((resolve, reject) => { const getImageUrl = inputFile => new Promise((resolve, reject) => {
if (window.URL && URL.createObjectURL) { if (window.URL && URL.createObjectURL) {
try { try {
...@@ -110,14 +149,6 @@ const processImage = (img, { width, height, orientation, type = 'image/png' }) = ...@@ -110,14 +149,6 @@ const processImage = (img, { width, height, orientation, type = 'image/png' }) =
context.drawImage(img, 0, 0, width, height); context.drawImage(img, 0, 0, width, height);
// The Tor Browser and maybe other browsers may prevent reading from canvas
// and return an all-white image instead. Assume reading failed if the resized
// image is perfectly white.
const imageData = context.getImageData(0, 0, width, height);
if (imageData.data.every(value => value === 255)) {
throw 'Failed to read from canvas';
}
canvas.toBlob(resolve, type); canvas.toBlob(resolve, type);
}); });
...@@ -127,7 +158,8 @@ const resizeImage = (img, type = 'image/png') => new Promise((resolve, reject) = ...@@ -127,7 +158,8 @@ const resizeImage = (img, type = 'image/png') => new Promise((resolve, reject) =
const newWidth = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (width / height))); const newWidth = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (width / height)));
const newHeight = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (height / width))); const newHeight = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (height / width)));
getOrientation(img, type) checkCanvasReliability()
.then(getOrientation(img, type))
.then(orientation => processImage(img, { .then(orientation => processImage(img, {
width: newWidth, width: newWidth,
height: newHeight, height: newHeight,
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter