mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
Don't render SVG nodes if it taints canvas
This commit is contained in:
parent
c765e2042f
commit
37a9249a4a
@ -25,6 +25,21 @@ const testRangeBounds = document => {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const testSVG = document => {
|
||||||
|
const img = new Image();
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
img.src = `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ctx.drawImage(img, 0, 0);
|
||||||
|
canvas.toDataURL();
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
const FEATURES = {
|
const FEATURES = {
|
||||||
// $FlowFixMe - get/set properties not yet supported
|
// $FlowFixMe - get/set properties not yet supported
|
||||||
get SUPPORT_RANGE_BOUNDS() {
|
get SUPPORT_RANGE_BOUNDS() {
|
||||||
@ -32,6 +47,12 @@ const FEATURES = {
|
|||||||
const value = testRangeBounds(document);
|
const value = testRangeBounds(document);
|
||||||
Object.defineProperty(FEATURES, 'SUPPORT_RANGE_BOUNDS', {value});
|
Object.defineProperty(FEATURES, 'SUPPORT_RANGE_BOUNDS', {value});
|
||||||
return value;
|
return value;
|
||||||
|
},
|
||||||
|
get SUPPORT_SVG_DRAWING() {
|
||||||
|
'use strict';
|
||||||
|
const value = testSVG(document);
|
||||||
|
Object.defineProperty(FEATURES, 'SUPPORT_SVG_DRAWING', {value});
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ import type Logger from './Logger';
|
|||||||
export type ImageElement = Image | HTMLCanvasElement;
|
export type ImageElement = Image | HTMLCanvasElement;
|
||||||
type ImageCache = {[string]: Promise<?ImageElement>};
|
type ImageCache = {[string]: Promise<?ImageElement>};
|
||||||
|
|
||||||
|
import FEATURES from './Feature';
|
||||||
|
|
||||||
export default class ImageLoader {
|
export default class ImageLoader {
|
||||||
origin: string;
|
origin: string;
|
||||||
options: Options;
|
options: Options;
|
||||||
@ -30,10 +32,20 @@ export default class ImageLoader {
|
|||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options.allowTaint === true || this.isInlineImage(src) || this.isSameOrigin(src)) {
|
if (isSVG(src)) {
|
||||||
return this.addImage(src, src);
|
if (this.options.allowTaint === true || FEATURES.SUPPORT_SVG_DRAWING) {
|
||||||
} else if (typeof this.options.proxy === 'string' && !this.isSameOrigin(src)) {
|
return this.addImage(src, src);
|
||||||
// TODO proxy
|
}
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
this.options.allowTaint === true ||
|
||||||
|
isInlineImage(src) ||
|
||||||
|
this.isSameOrigin(src)
|
||||||
|
) {
|
||||||
|
return this.addImage(src, src);
|
||||||
|
} else if (typeof this.options.proxy === 'string' && !this.isSameOrigin(src)) {
|
||||||
|
// TODO proxy
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,10 +55,6 @@ export default class ImageLoader {
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
isInlineImage(src: string): boolean {
|
|
||||||
return /data:image\/.*;base64,/i.test(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
hasImageInCache(key: string): boolean {
|
hasImageInCache(key: string): boolean {
|
||||||
return typeof this.cache[key] !== 'undefined';
|
return typeof this.cache[key] !== 'undefined';
|
||||||
}
|
}
|
||||||
@ -112,3 +120,11 @@ export class ImageStore {
|
|||||||
return index === -1 ? null : this._images[index];
|
return index === -1 ? null : this._images[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const INLINE_SVG = /^data:image\/svg\+xml/i;
|
||||||
|
const INLINE_IMG = /^data:image\/.*;base64,/i;
|
||||||
|
|
||||||
|
const isInlineImage = (src: string): boolean => INLINE_IMG.test(src);
|
||||||
|
|
||||||
|
const isSVG = (src: string): boolean =>
|
||||||
|
src.substr(-3).toLowerCase() === 'svg' || INLINE_SVG.test(src);
|
||||||
|
@ -3,7 +3,7 @@ import parseRefTest from '../scripts/parse-reftest';
|
|||||||
import reftests from './reftests';
|
import reftests from './reftests';
|
||||||
import querystring from 'querystring';
|
import querystring from 'querystring';
|
||||||
|
|
||||||
const DOWNLOAD_REFTESTS = true;
|
const DOWNLOAD_REFTESTS = false;
|
||||||
const query = querystring.parse(location.search.replace(/^\?/, ''));
|
const query = querystring.parse(location.search.replace(/^\?/, ''));
|
||||||
|
|
||||||
const downloadResult = (filename, data) => {
|
const downloadResult = (filename, data) => {
|
||||||
@ -126,7 +126,7 @@ const assertPath = (result, expected, desc) => {
|
|||||||
|
|
||||||
const delta = 10;
|
const delta = 10;
|
||||||
|
|
||||||
if (REFTEST) {
|
if (REFTEST && query.refTest === 'true') {
|
||||||
const RESULTS = parseRefTest(result);
|
const RESULTS = parseRefTest(result);
|
||||||
REFTEST.forEach(({action, line, ...args}, i) => {
|
REFTEST.forEach(({action, line, ...args}, i) => {
|
||||||
const RESULT = RESULTS[i];
|
const RESULT = RESULTS[i];
|
||||||
|
Loading…
Reference in New Issue
Block a user