Skip to content
Snippets Groups Projects
Unverified Commit d8d43a42 authored by ThibG's avatar ThibG Committed by GitHub
Browse files

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
No related branches found
No related tags found
No related merge requests found
......@@ -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) => {
if (window.URL && URL.createObjectURL) {
try {
......@@ -110,14 +149,6 @@ const processImage = (img, { width, height, orientation, type = 'image/png' }) =
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);
});
......@@ -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 newHeight = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (height / width)));
getOrientation(img, type)
checkCanvasReliability()
.then(getOrientation(img, type))
.then(orientation => processImage(img, {
width: newWidth,
height: newHeight,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment