Don't crash on SVG-as-canvas drawImage

The check for same-origin for image files with EXIF in canvas
drawImage was crashing for SVG images because their security
origin status is not available until the image has loaded.

Change things to not check SVG images for canvas drawImage,
which is safe because the image will be checked when drawing
the SVG itself.

Add a test for various uses of images in SVG.

Bug: 1141412
Change-Id: I4bd39b6d10afec4c4134b24609aa02c53359361b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2521049
Reviewed-by: Yi Xu <yiyix@chromium.org>
Reviewed-by: Fredrik Söderquist <fs@opera.com>
Commit-Queue: Stephen Chenney <schenney@chromium.org>
Cr-Commit-Position: refs/heads/master@{#825112}
diff --git a/css/css-images/image-orientation/image-orientation-none-cross-origin-svg.html b/css/css-images/image-orientation/image-orientation-none-cross-origin-svg.html
new file mode 100644
index 0000000..23e5cbf
--- /dev/null
+++ b/css/css-images/image-orientation/image-orientation-none-cross-origin-svg.html
@@ -0,0 +1,181 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+<meta charset="utf-8">
+<title>CSS Images: image-orientation, CORS detection for SVG content</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/5165">
+<link rel="match" href="reference/image-orientation-none-cross-origin-svg-ref.html">
+<meta name=fuzzy content="10;100">
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/rendering-utils.js"></script>
+<style>
+    .image {
+        width: 40px;
+        height: 20px;
+        position: fixed;
+    }
+</style>
+<script>
+    function toCors(src) {
+        return src.replace(new URL(src).origin, get_host_info().HTTP_REMOTE_ORIGIN)
+    }
+
+    window.onload = () => {
+        const images = [
+            {
+                id_image: "cors_from_image",
+                id_foreign: "cors_from_foreign",
+                cors: true,
+                orientation: 'from-image',
+                shouldBeRotated: true,
+                left: '10px'
+            },
+            {
+                id_image: "cors_none_image",
+                id_foreign: "cors_none_foreign",
+                cors: true,
+                orientation: 'none',
+                shouldBeRotated: true,
+                left: '60px'
+            },
+            {
+                id_image: "same_from_image",
+                id_foreign: "same_from_foreign",
+                cors: false,
+                orientation: 'from-image',
+                shouldBeRotated: true,
+                left: '110px'
+            },
+            {
+                id_image: "same_none_image",
+                id_foreign: "same_none_foreign",
+                cors: false,
+                orientation: 'none',
+                shouldBeRotated: false,
+                left: '160px'
+            },
+        ];
+
+        images.forEach(data => {
+            if (data.cors) {
+                image_src = document.getElementById("cors_img");
+                image = document.getElementById(data.id_image);
+                image.setAttribute("href", image_src.src);
+                foreign = document.getElementById(data.id_foreign);
+                foreign.src = image_src.src;
+            } else {
+                image_src = document.getElementById("same_img");
+                image = document.getElementById(data.id_image);
+                image.setAttribute("href", image_src.src);
+                foreign = document.getElementById(data.id_foreign);
+                foreign.src = image_src.src;
+            }
+
+            const canvas_svg_image = document.createElement('canvas');
+            canvas_svg_image.className = "image";
+            canvas_svg_image.width = canvas_svg_image.height = 1;
+            canvas_svg_image.style.left = data.left;
+            canvas_svg_image.style.top = "140px";
+            // The source of image-orientation preference for canvas drawImage
+            // is currently not standardized.
+            // See https://github.com/w3c/csswg-drafts/issues/4666
+            canvas_svg_image.style.imageOrientation = data.orientation;
+            document.body.appendChild(canvas_svg_image);
+            ctx = canvas_svg_image.getContext('2d');
+            sx = data.shouldBeRotated ? 80 : 0;
+            sy = data.shouldBeRotated ? 40 : 0;
+            ctx.drawImage(image, sx, sy, 1, 1, 0, 0, 1, 1);
+
+            const canvas_svg_foreign = document.createElement('canvas');
+            canvas_svg_foreign.className = "image";
+            canvas_svg_foreign.width = canvas_svg_foreign.height = 1;
+            canvas_svg_foreign.style.left = data.left;
+            canvas_svg_foreign.style.top = "170px";
+            canvas_svg_foreign.style.imageOrientation = data.orientation;
+            document.body.appendChild(canvas_svg_foreign);
+            ctx = canvas_svg_foreign.getContext('2d');
+            sx = data.shouldBeRotated ? 80 : 0;
+            sy = data.shouldBeRotated ? 40 : 0;
+            ctx.drawImage(foreign, sx, sy, 1, 1, 0, 0, 1, 1);
+        })
+        waitForAtLeastOneFrame().then(() => { takeScreenshot() });
+    }
+
+</script>
+</head>
+<body>
+    <svg class="image" id="svg_cors_from" style="left: 10px; top: 50px; image-orientation: from-image;">
+        <image id="cors_from_image" href="support/exif-orientation-3-lr.jpg" X="-57" Y="-27"></image>
+    </svg>
+    <!-- This should be functionally identical to a plain <img> element. We test it here to verify
+         that SVG foreign object correctly tracks the security origin for the image. -->
+    <svg class="image" style="left: 10px; top: 80px; image-orientation: from-image;">
+        <foreignObject  x="-57" y="-27" width="100" height="50">
+            <img id="cors_from_foreign" src="support/exif-orientation-3-lr.jpg"></img>
+        </foreignObject>
+    </svg>
+    <!-- Note SVG-as-image requires any <image> elements to use (base64 encoded) data: URLs, that can
+         never be cross origin. This just tests that we don't crash or do other strange things. -->
+    <img class="image" id="img_cors_from" src="support/svg-with-image-rotated.svg" style="left: 10px; top: 110px; image-orientation: from-image;"/>
+
+    <svg class="image" style="left: 60px; top: 50px; image-orientation: none;">
+        <image id="cors_none_image" href="support/exif-orientation-3-lr.jpg" X="-57" Y="-27"></image>
+    </svg>
+    <!-- This should be functionally identical to a plain <img> element. We test it here to verify
+         that SVG foreign object correctly tracks the security origin for the image. -->
+    <svg class="image" style="left: 60px; top: 80px; image-orientation: none;">
+        <foreignObject  x="-57" y="-27" width="100" height="50">
+            <img id="cors_none_foreign" src="support/exif-orientation-3-lr.jpg"></img>
+        </foreignObject>
+    </svg>
+    <!-- Note SVG-as-image requires any <image> elements to use (base64 encoded) data: URLs, that can
+         never be cross origin. This just tests that we don't crash or do other strange things. -->
+    <img class="image" id="img_cors_none" src="support/svg-with-image-rotated.svg" style="left: 60px; top: 110px; image-orientation: none;"/>
+
+    <svg class="image" style="left: 110px; top: 50px; image-orientation: from-image;">
+        <image id="same_from_image" href="support/exif-orientation-3-lr.jpg" X="-57" Y="-27"></image>
+    </svg>
+    <!-- This should be functionally identical to a plain <img> element. We test it here to verify
+         that SVG foreign object correctly tracks the security origin for the image. -->
+    <svg class="image" style="left: 110px; top: 80px; image-orientation: from-image;">
+        <foreignObject  x="-57" y="-27" width="100" height="50">
+            <img id="same_from_foreign" src="support/exif-orientation-3-lr.jpg"></img>
+        </foreignObject>
+    </svg>
+    <!-- Note SVG-as-image requires any <image> elements to use (base64 encoded) data: URLs, that can
+         never be cross origin. This just tests that we don't crash or do other strange things. -->
+    <img class="image" id="img_same_from" src="support/svg-with-image-rotated.svg" style="left: 110px; top: 110px; image-orientation: from-image;"/>
+
+    <svg class="image" style="left: 160px; top: 50px; image-orientation: none;">
+        <image id="same_none_image" href="support/exif-orientation-3-lr.jpg" X="0" Y="0"></image>
+    </svg>
+    <!-- This should be functionally identical to a plain <img> element. We test it here to verify
+         that SVG foreign object correctly tracks the security origin for the image. -->
+    <svg class="image" style="left: 160px; top: 80px; image-orientation: none;">
+        <foreignObject x="0" y="0" width="100" height="50">
+            <img id="same_none_foreign" src="support/exif-orientation-3-lr.jpg"></img>
+        </foreignObject>
+    </svg>
+    <!-- Note SVG-as-image requires any <image> elements to use (base64 encoded) data: URLs, that can
+         never be cross origin. This just tests that we don't crash or do other strange things. -->
+    <img class="image" id="img_same_none" src="support/svg-with-image-rotated.svg" style="left: 160px; top: 110px; image-orientation: none;"/>
+
+    <!-- This is the easiest way to get a cross origin url for SVG <image> -->
+    <script>
+        const img = document.createElement('img')
+        img.src = "support/exif-orientation-3-lr.jpg"
+        img.id = "same_img";
+        img.style.display = "none";
+        document.body.appendChild(img)
+        const imgCors = document.createElement('img')
+        imgCors.src = img.src
+        imgCors.src = toCors(imgCors.src)
+        imgCors.id = "cors_img";
+        imgCors.style.display = "none";
+        document.body.appendChild(imgCors)
+    </script>
+
+</body>
+</html>
diff --git a/css/css-images/image-orientation/reference/image-orientation-none-cross-origin-svg-ref.html b/css/css-images/image-orientation/reference/image-orientation-none-cross-origin-svg-ref.html
new file mode 100644
index 0000000..e34a708
--- /dev/null
+++ b/css/css-images/image-orientation/reference/image-orientation-none-cross-origin-svg-ref.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Images: image-orientation, CORS detection for SVG content, reference</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+<style>
+    div {
+        background-image: url("../support/exif-orientation-1-ul.jpg");
+        width: 40px;
+        height: 20px;
+        position: fixed;
+    }
+</style>
+</head>
+<body>
+    <div style="left: 10px; top: 50px"></div>
+    <div style="left: 10px; top: 80px"></div>
+    <div style="left: 10px; top: 110px"></div>
+    <div style="left: 10px; top: 140px"></div>
+    <div style="left: 10px; top: 170px"></div>
+
+    <div style="left: 60px; top: 50px"></div>
+    <div style="left: 60px; top: 80px"></div>
+    <div style="left: 60px; top: 110px"></div>
+    <div style="left: 60px; top: 140px"></div>
+    <div style="left: 60px; top: 170px"></div>
+
+    <div style="left: 110px; top: 50px"></div>
+    <div style="left: 110px; top: 80px"></div>
+    <div style="left: 110px; top: 110px"></div>
+    <div style="left: 110px; top: 140px"></div>
+    <div style="left: 110px; top: 170px"></div>
+
+    <div style="left: 160px; top: 50px"></div>
+    <div style="left: 160px; top: 80px"></div>
+    <div style="left: 160px; top: 110px"></div>
+    <div style="left: 160px; top: 140px"></div>
+    <div style="left: 160px; top: 170px"></div>
+</body>
+</html>
diff --git a/css/css-images/image-orientation/support/svg-with-image-rotated.svg b/css/css-images/image-orientation/support/svg-with-image-rotated.svg
new file mode 100644
index 0000000..e465816
--- /dev/null
+++ b/css/css-images/image-orientation/support/svg-with-image-rotated.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="40" height="20">
+    <image xlink:href="data:image/jpeg;base64,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" x="-57" y="-27"></image>
+</svg>