mirror of
https://github.com/servo/servo
synced 2026-04-25 17:15:48 +02:00
canvas: Reset origin clean flag on reset the context to its default state (#39768)
The canvas `origin clean` flag for 2D rendering context should be reset on the reset the context to its default state. See https://html.spec.whatwg.org/multipage/#security-with-canvas-elements The following operations are resetting the `origin clean` flag: - reset() method https://html.spec.whatwg.org/multipage/#dom-context-2d-reset - canvas (output bitmap) dimensions change https://html.spec.whatwg.org/multipage/#concept-canvas-set-bitmap-dimensions Testing: Improvements in the following tests - html/semantics/embedded-content/the-canvas-element/security.reset.* - html/semantics/embedded-content/the-canvas-element/security.resize.* Signed-off-by: Andrei Volykhin <andrei.volykhin@gmail.com>
This commit is contained in:
@@ -304,8 +304,10 @@ impl CanvasState {
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#concept-canvas-set-bitmap-dimensions>
|
||||
pub(super) fn set_bitmap_dimensions(&self, size: Size2D<u64>) {
|
||||
// Step 1. Reset the rendering context to its default state.
|
||||
self.reset_to_initial_state();
|
||||
|
||||
// Step 2. Resize the output bitmap to the new width and height.
|
||||
self.size.replace(adjust_canvas_size(size));
|
||||
|
||||
self.ipc_renderer
|
||||
@@ -316,6 +318,7 @@ impl CanvasState {
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#reset-the-rendering-context-to-its-default-state>
|
||||
pub(super) fn reset(&self) {
|
||||
self.reset_to_initial_state();
|
||||
|
||||
@@ -323,15 +326,29 @@ impl CanvasState {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 1. Clear canvas's bitmap to transparent black.
|
||||
self.ipc_renderer
|
||||
.send(CanvasMsg::Recreate(None, self.get_canvas_id()))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub(super) fn reset_to_initial_state(&self) {
|
||||
/// <https://html.spec.whatwg.org/multipage/#reset-the-rendering-context-to-its-default-state>
|
||||
fn reset_to_initial_state(&self) {
|
||||
// Step 2. Empty the list of subpaths in context's current default path.
|
||||
*self.current_default_path.borrow_mut() = Path::new();
|
||||
|
||||
// Step 3. Clear the context's drawing state stack.
|
||||
self.saved_states.borrow_mut().clear();
|
||||
|
||||
// Step 4. Reset everything that drawing state consists of to their initial values.
|
||||
*self.state.borrow_mut() = CanvasContextState::new();
|
||||
|
||||
// <https://html.spec.whatwg.org/multipage/#security-with-canvas-elements>
|
||||
// The flag can be reset in certain situations; for example, when changing the value of the
|
||||
// width or the height content attribute of the canvas element to which a
|
||||
// CanvasRenderingContext2D is bound, the bitmap is cleared and its origin-clean flag is
|
||||
// reset.
|
||||
self.set_origin_clean(true);
|
||||
}
|
||||
|
||||
pub(super) fn reset_bitmap(&self) {
|
||||
@@ -364,8 +381,8 @@ impl CanvasState {
|
||||
self.origin_clean.get()
|
||||
}
|
||||
|
||||
fn set_origin_unclean(&self) {
|
||||
self.origin_clean.set(false)
|
||||
fn set_origin_clean(&self, origin_clean: bool) {
|
||||
self.origin_clean.set(origin_clean);
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#the-image-argument-is-not-origin-clean>
|
||||
@@ -540,7 +557,7 @@ impl CanvasState {
|
||||
};
|
||||
|
||||
if result.is_ok() && !self.is_origin_clean(image) {
|
||||
self.set_origin_unclean()
|
||||
self.set_origin_clean(false);
|
||||
}
|
||||
result
|
||||
}
|
||||
@@ -1143,7 +1160,7 @@ impl CanvasState {
|
||||
self.state.borrow_mut().stroke_style =
|
||||
CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern));
|
||||
if !pattern.origin_is_clean() {
|
||||
self.set_origin_unclean();
|
||||
self.set_origin_clean(false);
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -1186,7 +1203,7 @@ impl CanvasState {
|
||||
self.state.borrow_mut().fill_style =
|
||||
CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern));
|
||||
if !pattern.origin_is_clean() {
|
||||
self.set_origin_unclean();
|
||||
self.set_origin_clean(false);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -79,16 +79,6 @@ impl CanvasRenderingContext2D {
|
||||
.map(|context| reflect_dom_object(Box::new(context), global, can_gc))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#reset-the-rendering-context-to-its-default-state
|
||||
fn reset_to_initial_state(&self) {
|
||||
self.canvas_state.reset_to_initial_state();
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#concept-canvas-set-bitmap-dimensions>
|
||||
pub(crate) fn set_canvas_bitmap_dimensions(&self, size: Size2D<u64>) {
|
||||
self.canvas_state.set_bitmap_dimensions(size);
|
||||
}
|
||||
|
||||
pub(crate) fn take_missing_image_urls(&self) -> Vec<ServoUrl> {
|
||||
std::mem::take(&mut self.canvas_state.get_missing_image_urls().borrow_mut())
|
||||
}
|
||||
@@ -133,7 +123,7 @@ impl CanvasContext for CanvasRenderingContext2D {
|
||||
}
|
||||
|
||||
fn resize(&self) {
|
||||
self.set_canvas_bitmap_dimensions(self.size().cast())
|
||||
self.canvas_state.set_bitmap_dimensions(self.size().cast());
|
||||
}
|
||||
|
||||
fn reset_bitmap(&self) {
|
||||
|
||||
18
tests/wpt/meta/MANIFEST.json
vendored
18
tests/wpt/meta/MANIFEST.json
vendored
@@ -750592,14 +750592,28 @@
|
||||
]
|
||||
],
|
||||
"security.reset.cross.html": [
|
||||
"f823bbd8ac484202100ec8aa737fe46fce95faab",
|
||||
"bdf784e84996ca4cbebffa4b6446b32b92a14d95",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
]
|
||||
],
|
||||
"security.reset.redirect.html": [
|
||||
"af881c5fdc3a584d5bba0dc166b91d5873249c41",
|
||||
"4db862e28ca350a3ba21a22946f09d0b36f98f10",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
]
|
||||
],
|
||||
"security.resize.cross.html": [
|
||||
"1236e4a9a96db4a314bd86b2ed507995a0d57dae",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
]
|
||||
],
|
||||
"security.resize.redirect.html": [
|
||||
"fb593d7b077185c067147a1e504e003dce90e065",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
[security.reset.cross.html]
|
||||
[Resetting the canvas state resets the origin-clean flag]
|
||||
expected: FAIL
|
||||
@@ -1,3 +0,0 @@
|
||||
[security.reset.redirect.html]
|
||||
[Resetting the canvas state resets the origin-clean flag]
|
||||
expected: FAIL
|
||||
@@ -22,7 +22,7 @@ _addTest(function(canvas, ctx) {
|
||||
canvas.width = 50;
|
||||
ctx.drawImage(document.getElementById('yellow.png'), 0, 0);
|
||||
assert_throws_dom("SECURITY_ERR", function() { canvas.toDataURL(); });
|
||||
canvas.width = 100;
|
||||
ctx.reset();
|
||||
canvas.toDataURL();
|
||||
ctx.getImageData(0, 0, 1, 1);
|
||||
_assert(true, "true"); // okay if there was no exception
|
||||
|
||||
@@ -22,7 +22,7 @@ _addTest(function(canvas, ctx) {
|
||||
canvas.width = 50;
|
||||
ctx.drawImage(document.getElementById('yellow.png'), 0, 0);
|
||||
assert_throws_dom("SECURITY_ERR", function() { canvas.toDataURL(); });
|
||||
canvas.width = 100;
|
||||
ctx.reset();
|
||||
canvas.toDataURL();
|
||||
ctx.getImageData(0, 0, 1, 1);
|
||||
_assert(true, "true"); // okay if there was no exception
|
||||
|
||||
35
tests/wpt/tests/html/semantics/embedded-content/the-canvas-element/security.resize.cross.html
vendored
Normal file
35
tests/wpt/tests/html/semantics/embedded-content/the-canvas-element/security.resize.cross.html
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
|
||||
<title>Canvas test: security.resize.cross</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/html/canvas/resources/canvas-tests.js"></script>
|
||||
<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
|
||||
<body class="show_output">
|
||||
|
||||
<h1>security.resize.cross</h1>
|
||||
<p class="desc">Resizing the canvas dimensions resets the origin-clean flag</p>
|
||||
|
||||
|
||||
<p class="output">Actual output:</p>
|
||||
<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
|
||||
|
||||
<ul id="d"></ul>
|
||||
<script>
|
||||
var t = async_test("Resizing the canvas dimensions resets the origin-clean flag");
|
||||
_addTest(function(canvas, ctx) {
|
||||
|
||||
canvas.width = 50;
|
||||
ctx.drawImage(document.getElementById('yellow.png'), 0, 0);
|
||||
assert_throws_dom("SECURITY_ERR", function() { canvas.toDataURL(); });
|
||||
canvas.width = 100;
|
||||
canvas.toDataURL();
|
||||
ctx.getImageData(0, 0, 1, 1);
|
||||
_assert(true, "true"); // okay if there was no exception
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
<script src="/common/get-host-info.sub.js"></script>
|
||||
<script src="data:text/javascript,addCrossOriginYellowImage()"></script>
|
||||
|
||||
35
tests/wpt/tests/html/semantics/embedded-content/the-canvas-element/security.resize.redirect.html
vendored
Normal file
35
tests/wpt/tests/html/semantics/embedded-content/the-canvas-element/security.resize.redirect.html
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
|
||||
<title>Canvas test: security.resize.redirect</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/html/canvas/resources/canvas-tests.js"></script>
|
||||
<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
|
||||
<body class="show_output">
|
||||
|
||||
<h1>security.resize.redirect</h1>
|
||||
<p class="desc">Resizing the canvas dimensions resets the origin-clean flag</p>
|
||||
|
||||
|
||||
<p class="output">Actual output:</p>
|
||||
<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
|
||||
|
||||
<ul id="d"></ul>
|
||||
<script>
|
||||
var t = async_test("Resizing the canvas dimensions resets the origin-clean flag");
|
||||
_addTest(function(canvas, ctx) {
|
||||
|
||||
canvas.width = 50;
|
||||
ctx.drawImage(document.getElementById('yellow.png'), 0, 0);
|
||||
assert_throws_dom("SECURITY_ERR", function() { canvas.toDataURL(); });
|
||||
canvas.width = 100;
|
||||
canvas.toDataURL();
|
||||
ctx.getImageData(0, 0, 1, 1);
|
||||
_assert(true, "true"); // okay if there was no exception
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
<script src="/common/get-host-info.sub.js"></script>
|
||||
<script src="data:text/javascript,addCrossOriginRedirectYellowImage()"></script>
|
||||
|
||||
Reference in New Issue
Block a user