Commit 0eea57f8 authored by junov's avatar junov Committed by Commit bot

Make OffscreenCanvas commit() propagate the origin-clean flag.

This change block user code from accessing cross-origin image data
from a placeholder canvas. The placeholder code was modified to
use StaticBitmapImage instead of Image to gain access to the
originClean() method without downcasting.

BUG=673348

Review-Url: https://codereview.chromium.org/2566313002
Cr-Commit-Position: refs/heads/master@{#438172}
parent ea1eb315
<!DOCTYPE html>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script>
async_test(t => {
var image = new Image();
// Notice that we don't set the image.crossOrigin property.
image.src = "http://localhost:8000/security/resources/abe-allow-star.php";
image.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = canvas.height = 10;
var offscreen = canvas.transferControlToOffscreen();
var ctx = offscreen.getContext('2d');
ctx.drawImage(image, 0, 0);
ctx.commit();
t.step(function() {
canvas.toDataURL(); // Succeeds by not throwing
});
setTimeout(function() { // sync barrier for commit() propagation
t.step(function() {
assert_throws("SecurityError", function() {
canvas.toDataURL();
}, "Check toDataURL blocked.");
});
ctx.commit(); // Second frame does not reset origin-clean flag.
setTimeout(function() { // sync barrier for commit() propagation
t.step(function() {
assert_throws("SecurityError", function() {
canvas.toDataURL();
});
});
t.done();
}, 0);
}, 0);
}
}, "Verify that the placeholder <canvas> associated with an OffscreenCanvas tainted with cross-origin content cannot be read once commit has propagated.");
</script>
......@@ -642,6 +642,7 @@ ImageData* HTMLCanvasElement::toImageData(SourceDrawingBuffer sourceBuffer,
if (hasImageBuffer()) {
snapshot = buffer()->newSkImageSnapshot(PreferNoAcceleration, reason);
} else if (placeholderFrame()) {
DCHECK(placeholderFrame()->originClean());
// TODO(ccameron): Canvas should produce sRGB images.
// https://crbug.com/672299
snapshot = placeholderFrame()->imageForCurrentFrame(
......@@ -783,6 +784,8 @@ bool HTMLCanvasElement::originClean() const {
if (document().settings() &&
document().settings()->disableReadingFromCanvas())
return false;
if (placeholderFrame())
return placeholderFrame()->originClean();
return m_originClean;
}
......
......@@ -60,7 +60,7 @@ void OffscreenCanvasRenderingContext2D::commit(ScriptState* scriptState,
return;
}
double commitStartTime = WTF::monotonicallyIncreasingTime();
RefPtr<StaticBitmapImage> image = this->transferToStaticBitmapImage();
RefPtr<StaticBitmapImage> image = transferToStaticBitmapImage();
getOffscreenCanvas()->getOrCreateFrameDispatcher()->dispatchFrame(
std::move(image), commitStartTime);
}
......
......@@ -164,7 +164,7 @@ namespace {
void updatePlaceholderImage(WeakPtr<OffscreenCanvasFrameDispatcher> dispatcher,
std::unique_ptr<WebTaskRunner> taskRunner,
int placeholderCanvasId,
RefPtr<blink::Image> image,
RefPtr<blink::StaticBitmapImage> image,
unsigned resourceId) {
DCHECK(isMainThread());
OffscreenCanvasPlaceholder* placeholderCanvas =
......
......@@ -6,8 +6,8 @@
#include "platform/CrossThreadFunctional.h"
#include "platform/WebTaskRunner.h"
#include "platform/graphics/Image.h"
#include "platform/graphics/OffscreenCanvasFrameDispatcher.h"
#include "platform/graphics/StaticBitmapImage.h"
#include "wtf/HashMap.h"
namespace {
......@@ -62,7 +62,7 @@ void OffscreenCanvasPlaceholder::unregisterPlaceholder() {
}
void OffscreenCanvasPlaceholder::setPlaceholderFrame(
RefPtr<Image> newFrame,
RefPtr<StaticBitmapImage> newFrame,
WeakPtr<OffscreenCanvasFrameDispatcher> dispatcher,
std::unique_ptr<WebTaskRunner> taskRunner,
unsigned resourceId) {
......
......@@ -12,15 +12,15 @@
namespace blink {
class Image;
class OffscreenCanvasFrameDispatcher;
class StaticBitmapImage;
class WebTaskRunner;
class PLATFORM_EXPORT OffscreenCanvasPlaceholder {
public:
~OffscreenCanvasPlaceholder();
void setPlaceholderFrame(RefPtr<Image>,
void setPlaceholderFrame(RefPtr<StaticBitmapImage>,
WeakPtr<OffscreenCanvasFrameDispatcher>,
std::unique_ptr<WebTaskRunner>,
unsigned resourceId);
......@@ -30,14 +30,16 @@ class PLATFORM_EXPORT OffscreenCanvasPlaceholder {
void registerPlaceholder(unsigned placeholderId);
void unregisterPlaceholder();
const RefPtr<Image>& placeholderFrame() const { return m_placeholderFrame; }
const RefPtr<StaticBitmapImage>& placeholderFrame() const {
return m_placeholderFrame;
}
private:
bool isPlaceholderRegistered() const {
return m_placeholderId != kNoPlaceholderId;
}
RefPtr<Image> m_placeholderFrame;
RefPtr<StaticBitmapImage> m_placeholderFrame;
WeakPtr<OffscreenCanvasFrameDispatcher> m_frameDispatcher;
std::unique_ptr<WebTaskRunner> m_frameDispatcherTaskRunner;
unsigned m_placeholderFrameResourceId = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment