mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-05 15:28:39 +09:00
parent
97ec6591f4
commit
1cc92006b6
10 changed files with 143 additions and 60 deletions
|
|
@ -1105,6 +1105,7 @@ CanvasRenderingContext2D::CanvasRenderingContext2D(layers::LayersBackend aCompos
|
|||
, mIsCapturedFrameInvalid(false)
|
||||
, mPathTransformWillUpdate(false)
|
||||
, mInvalidateCount(0)
|
||||
, mWriteOnly(false) // == !origin-clean
|
||||
{
|
||||
sNumLivingContexts++;
|
||||
|
||||
|
|
@ -2562,7 +2563,8 @@ CanvasRenderingContext2D::CreatePattern(const CanvasImageSource& aSource,
|
|||
// nullptr and set CORSUsed to true for passing the security check in
|
||||
// CanvasUtils::DoDrawImageSecurityCheck().
|
||||
RefPtr<CanvasPattern> pat =
|
||||
new CanvasPattern(this, srcSurf, repeatMode, nullptr, false, true);
|
||||
new CanvasPattern(this, srcSurf, repeatMode, nullptr,
|
||||
imgBitmap.IsWriteOnly(), true);
|
||||
|
||||
return pat.forget();
|
||||
}
|
||||
|
|
@ -4952,6 +4954,10 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
|
|||
aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (canvas->IsWriteOnly()) {
|
||||
SetWriteOnly();
|
||||
}
|
||||
} else if (aImage.IsImageBitmap()) {
|
||||
ImageBitmap& imageBitmap = aImage.GetAsImageBitmap();
|
||||
srcSurf = imageBitmap.PrepareForDrawTarget(mTarget);
|
||||
|
|
@ -4960,6 +4966,10 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
|
|||
return;
|
||||
}
|
||||
|
||||
if (imageBitmap.IsWriteOnly()) {
|
||||
SetWriteOnly();
|
||||
}
|
||||
|
||||
imgSize = gfx::IntSize(imageBitmap.Width(), imageBitmap.Height());
|
||||
}
|
||||
else {
|
||||
|
|
@ -5674,9 +5684,8 @@ CanvasRenderingContext2D::GetImageData(JSContext* aCx, double aSx,
|
|||
|
||||
// Check only if we have a canvas element; if we were created with a docshell,
|
||||
// then it's special internal use.
|
||||
if (mCanvasElement && mCanvasElement->IsWriteOnly() &&
|
||||
!nsContentUtils::IsCallerChrome())
|
||||
{
|
||||
if (IsWriteOnly() ||
|
||||
(mCanvasElement && mCanvasElement->IsWriteOnly() && !nsContentUtils::IsCallerChrome())) {
|
||||
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
|
||||
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ class SourceSurface;
|
|||
namespace dom {
|
||||
class HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap;
|
||||
typedef HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap CanvasImageSource;
|
||||
class ImageBitmap;
|
||||
class ImageData;
|
||||
class StringOrCanvasGradientOrCanvasPattern;
|
||||
class OwningStringOrCanvasGradientOrCanvasPattern;
|
||||
|
|
@ -1151,6 +1152,19 @@ protected:
|
|||
|
||||
friend struct CanvasBidiProcessor;
|
||||
friend class CanvasDrawObserver;
|
||||
friend class ImageBitmap;
|
||||
|
||||
// For the origin-clean algorithm (mWriteOnly == !origin-clean)
|
||||
// See https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html
|
||||
void SetWriteOnly() {
|
||||
mWriteOnly = true;
|
||||
}
|
||||
|
||||
bool IsWriteOnly() const {
|
||||
return mWriteOnly;
|
||||
}
|
||||
|
||||
bool mWriteOnly;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
|||
|
|
@ -351,29 +351,27 @@ CheckSecurityForHTMLElements(const nsLayoutUtils::SurfaceFromElementResult& aRes
|
|||
*/
|
||||
template<class HTMLElementType>
|
||||
static already_AddRefed<SourceSurface>
|
||||
GetSurfaceFromElement(nsIGlobalObject* aGlobal, HTMLElementType& aElement, ErrorResult& aRv)
|
||||
GetSurfaceFromElement(nsIGlobalObject* aGlobal, HTMLElementType& aElement,
|
||||
bool* aWriteOnly, ErrorResult& aRv)
|
||||
{
|
||||
nsLayoutUtils::SurfaceFromElementResult res =
|
||||
nsLayoutUtils::SurfaceFromElement(&aElement, nsLayoutUtils::SFE_WANT_FIRST_FRAME);
|
||||
|
||||
// check origin-clean
|
||||
if (!CheckSecurityForHTMLElements(res)) {
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<SourceSurface> surface = res.GetSourceSurface();
|
||||
|
||||
if (NS_WARN_IF(!surface)) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Check origin-clean and pass back
|
||||
*aWriteOnly = !CheckSecurityForHTMLElements(res);
|
||||
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
/*
|
||||
* The specification doesn't allow to create an ImegeBitmap from a vector image.
|
||||
* The specification doesn't allow to create an ImageBitmap from a vector image.
|
||||
* This function is used to check if the given HTMLImageElement contains a
|
||||
* raster image.
|
||||
*/
|
||||
|
|
@ -398,7 +396,7 @@ HasRasterImage(HTMLImageElement& aImageEl)
|
|||
}
|
||||
|
||||
ImageBitmap::ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData,
|
||||
bool aIsPremultipliedAlpha /* = true */)
|
||||
bool aWriteOnly, bool aIsPremultipliedAlpha /* = true */)
|
||||
: mParent(aGlobal)
|
||||
, mData(aData)
|
||||
, mSurface(nullptr)
|
||||
|
|
@ -406,6 +404,7 @@ ImageBitmap::ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData,
|
|||
, mPictureRect(0, 0, aData->GetSize().width, aData->GetSize().height)
|
||||
, mIsPremultipliedAlpha(aIsPremultipliedAlpha)
|
||||
, mIsCroppingAreaOutSideOfSourceImage(false)
|
||||
, mWriteOnly(aWriteOnly)
|
||||
{
|
||||
MOZ_ASSERT(aData, "aData is null in ImageBitmap constructor.");
|
||||
}
|
||||
|
|
@ -698,6 +697,7 @@ ImageBitmap::ToCloneData() const
|
|||
RefPtr<SourceSurface> surface = mData->GetAsSourceSurface();
|
||||
result->mSurface = surface->GetDataSurface();
|
||||
MOZ_ASSERT(result->mSurface);
|
||||
result->mWriteOnly = mWriteOnly;
|
||||
|
||||
return Move(result);
|
||||
}
|
||||
|
|
@ -708,7 +708,7 @@ ImageBitmap::CreateFromCloneData(nsIGlobalObject* aGlobal,
|
|||
{
|
||||
RefPtr<layers::Image> data = CreateImageFromSurface(aData->mSurface);
|
||||
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data,
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, aData->mWriteOnly,
|
||||
aData->mIsPremultipliedAlpha);
|
||||
|
||||
ret->mIsCroppingAreaOutSideOfSourceImage =
|
||||
|
|
@ -724,11 +724,8 @@ ImageBitmap::CreateFromOffscreenCanvas(nsIGlobalObject* aGlobal,
|
|||
OffscreenCanvas& aOffscreenCanvas,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
// Check origin-clean.
|
||||
if (aOffscreenCanvas.IsWriteOnly()) {
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
// Check origin-clean
|
||||
bool writeOnly = aOffscreenCanvas.IsWriteOnly();
|
||||
|
||||
nsLayoutUtils::SurfaceFromElementResult res =
|
||||
nsLayoutUtils::SurfaceFromOffscreenCanvas(&aOffscreenCanvas,
|
||||
|
|
@ -744,7 +741,7 @@ ImageBitmap::CreateFromOffscreenCanvas(nsIGlobalObject* aGlobal,
|
|||
RefPtr<layers::Image> data =
|
||||
CreateImageFromSurface(surface);
|
||||
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data);
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly);
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
|
|
@ -757,16 +754,19 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLImageElement& aImageEl
|
|||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
// Check if the image element is a bitmap (e.g. it's a vector graphic) or not.
|
||||
if (!HasRasterImage(aImageEl)) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool writeOnly = true;
|
||||
|
||||
// Get the SourceSurface out from the image element and then do security
|
||||
// checking.
|
||||
RefPtr<SourceSurface> surface = GetSurfaceFromElement(aGlobal, aImageEl, aRv);
|
||||
RefPtr<SourceSurface> surface = GetSurfaceFromElement(aGlobal, aImageEl,
|
||||
&writeOnly, aRv);
|
||||
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
|
|
@ -780,7 +780,7 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLImageElement& aImageEl
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data);
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly);
|
||||
|
||||
// Set the picture rectangle.
|
||||
if (ret && aCropRect.isSome()) {
|
||||
|
|
@ -812,13 +812,13 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLVideoElement& aVideoEl
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool writeOnly = true;
|
||||
|
||||
// Check security.
|
||||
nsCOMPtr<nsIPrincipal> principal = aVideoEl.GetCurrentVideoPrincipal();
|
||||
bool CORSUsed = aVideoEl.GetCORSMode() != CORS_NONE;
|
||||
if (!CheckSecurityForHTMLElements(false, CORSUsed, principal)) {
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
writeOnly = !CheckSecurityForHTMLElements(false, CORSUsed, principal);
|
||||
|
||||
// Create ImageBitmap.
|
||||
ImageContainer *container = aVideoEl.GetImageContainer();
|
||||
|
|
@ -834,7 +834,7 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLVideoElement& aVideoEl
|
|||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data);
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly);
|
||||
|
||||
// Set the picture rectangle.
|
||||
if (ret && aCropRect.isSome()) {
|
||||
|
|
@ -856,12 +856,18 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLCanvasElement& aCanvas
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<SourceSurface> surface = GetSurfaceFromElement(aGlobal, aCanvasEl, aRv);
|
||||
bool writeOnly = true;
|
||||
|
||||
RefPtr<SourceSurface> surface = GetSurfaceFromElement(aGlobal, aCanvasEl, &writeOnly, aRv);
|
||||
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!writeOnly) {
|
||||
writeOnly = aCanvasEl.IsWriteOnly();
|
||||
}
|
||||
|
||||
// Crop the source surface if needed.
|
||||
RefPtr<SourceSurface> croppedSurface;
|
||||
IntRect cropRect = aCropRect.valueOr(IntRect());
|
||||
|
|
@ -874,8 +880,7 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLCanvasElement& aCanvas
|
|||
aCropRect.isSome()) {
|
||||
// The _surface_ must be a DataSourceSurface.
|
||||
MOZ_ASSERT(surface->GetType() == SurfaceType::DATA,
|
||||
"The snapshot SourceSurface from WebGL rendering contest is not \
|
||||
DataSourceSurface.");
|
||||
"The snapshot SourceSurface from WebGL rendering contest is not DataSourceSurface.");
|
||||
RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();
|
||||
croppedSurface = CropAndCopyDataSourceSurface(dataSurface, cropRect);
|
||||
cropRect.MoveTo(0, 0);
|
||||
|
|
@ -897,7 +902,7 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLCanvasElement& aCanvas
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data);
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly);
|
||||
|
||||
// Set the picture rectangle.
|
||||
if (ret && aCropRect.isSome()) {
|
||||
|
|
@ -958,9 +963,12 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, ImageData& aImageData,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Create an ImageBimtap.
|
||||
// Create an ImageBitmap.
|
||||
// ImageData's underlying data is not alpha-premultiplied.
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, false);
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal,
|
||||
data,
|
||||
false /* write-only */,
|
||||
false /* alpha-premult */);
|
||||
|
||||
// The cropping information has been handled in the CreateImageFromRawData()
|
||||
// function.
|
||||
|
|
@ -975,11 +983,8 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, ImageData& aImageData,
|
|||
ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, CanvasRenderingContext2D& aCanvasCtx,
|
||||
const Maybe<IntRect>& aCropRect, ErrorResult& aRv)
|
||||
{
|
||||
// Check origin-clean.
|
||||
if (aCanvasCtx.GetCanvas()->IsWriteOnly()) {
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
// Check origin-clean
|
||||
bool writeOnly = aCanvasCtx.GetCanvas()->IsWriteOnly() || aCanvasCtx.IsWriteOnly();
|
||||
|
||||
RefPtr<SourceSurface> surface = aCanvasCtx.GetSurfaceSnapshot();
|
||||
|
||||
|
|
@ -1001,7 +1006,7 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, CanvasRenderingContext2D&
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data);
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly);
|
||||
|
||||
// Set the picture rectangle.
|
||||
if (ret && aCropRect.isSome()) {
|
||||
|
|
@ -1024,7 +1029,10 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, ImageBitmap& aImageBitmap,
|
|||
}
|
||||
|
||||
RefPtr<layers::Image> data = aImageBitmap.mData;
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, aImageBitmap.mIsPremultipliedAlpha);
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal,
|
||||
data,
|
||||
aImageBitmap.mWriteOnly,
|
||||
aImageBitmap.mIsPremultipliedAlpha);
|
||||
|
||||
// Set the picture rectangle.
|
||||
if (ret && aCropRect.isSome()) {
|
||||
|
|
@ -1295,7 +1303,7 @@ private:
|
|||
}
|
||||
|
||||
// Create ImageBitmap object.
|
||||
RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(mGlobalObject, data);
|
||||
RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(mGlobalObject, data, false /* write-only */);
|
||||
|
||||
// Set mIsCroppingAreaOutSideOfSourceImage.
|
||||
imageBitmap->SetIsCroppingAreaOutSideOfSourceImage(sourceSize, originalCropRect);
|
||||
|
|
@ -1391,7 +1399,7 @@ private:
|
|||
}
|
||||
|
||||
// Create ImageBitmap object.
|
||||
RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(mGlobalObject, data);
|
||||
RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(mGlobalObject, data, false /* write-only */);
|
||||
|
||||
// Set mIsCroppingAreaOutSideOfSourceImage.
|
||||
imageBitmap->SetIsCroppingAreaOutSideOfSourceImage(sourceSize, originalCropRect);
|
||||
|
|
@ -1486,14 +1494,19 @@ ImageBitmap::ReadStructuredClone(JSContext* aCx,
|
|||
uint32_t picRectHeight_;
|
||||
uint32_t isPremultipliedAlpha_;
|
||||
uint32_t isCroppingAreaOutSideOfSourceImage_;
|
||||
uint32_t writeOnly;
|
||||
uint32_t dummy;
|
||||
|
||||
if (!JS_ReadUint32Pair(aReader, &picRectX_, &picRectY_) ||
|
||||
!JS_ReadUint32Pair(aReader, &picRectWidth_, &picRectHeight_) ||
|
||||
!JS_ReadUint32Pair(aReader, &isPremultipliedAlpha_,
|
||||
&isCroppingAreaOutSideOfSourceImage_)) {
|
||||
&isCroppingAreaOutSideOfSourceImage_) ||
|
||||
!JS_ReadUint32Pair(aReader, &writeOnly, &dummy)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(dummy == 0);
|
||||
|
||||
int32_t picRectX = BitwiseCast<int32_t>(picRectX_);
|
||||
int32_t picRectY = BitwiseCast<int32_t>(picRectY_);
|
||||
int32_t picRectWidth = BitwiseCast<int32_t>(picRectWidth_);
|
||||
|
|
@ -1512,7 +1525,7 @@ ImageBitmap::ReadStructuredClone(JSContext* aCx,
|
|||
{
|
||||
RefPtr<layers::Image> img = CreateImageFromSurface(aClonedSurfaces[aIndex]);
|
||||
RefPtr<ImageBitmap> imageBitmap =
|
||||
new ImageBitmap(aParent, img, isPremultipliedAlpha_);
|
||||
new ImageBitmap(aParent, img, !!writeOnly, isPremultipliedAlpha_);
|
||||
|
||||
imageBitmap->mIsCroppingAreaOutSideOfSourceImage =
|
||||
isCroppingAreaOutSideOfSourceImage_;
|
||||
|
|
@ -1547,6 +1560,7 @@ ImageBitmap::WriteStructuredClone(JSStructuredCloneWriter* aWriter,
|
|||
const uint32_t picRectHeight = BitwiseCast<uint32_t>(aImageBitmap->mPictureRect.height);
|
||||
const uint32_t isPremultipliedAlpha = aImageBitmap->mIsPremultipliedAlpha ? 1 : 0;
|
||||
const uint32_t isCroppingAreaOutSideOfSourceImage = aImageBitmap->mIsCroppingAreaOutSideOfSourceImage ? 1 : 0;
|
||||
const uint32_t isWriteOnly = aImageBitmap->mWriteOnly ? 1 : 0;
|
||||
|
||||
// Indexing the cloned surfaces and send the index to the receiver.
|
||||
uint32_t index = aClonedSurfaces.Length();
|
||||
|
|
@ -1555,7 +1569,8 @@ ImageBitmap::WriteStructuredClone(JSStructuredCloneWriter* aWriter,
|
|||
NS_WARN_IF(!JS_WriteUint32Pair(aWriter, picRectX, picRectY)) ||
|
||||
NS_WARN_IF(!JS_WriteUint32Pair(aWriter, picRectWidth, picRectHeight)) ||
|
||||
NS_WARN_IF(!JS_WriteUint32Pair(aWriter, isPremultipliedAlpha,
|
||||
isCroppingAreaOutSideOfSourceImage))) {
|
||||
isCroppingAreaOutSideOfSourceImage)) ||
|
||||
NS_WARN_IF(!JS_WriteUint32Pair(aWriter, isWriteOnly, 0))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ struct ImageBitmapCloneData final
|
|||
gfx::IntRect mPictureRect;
|
||||
bool mIsPremultipliedAlpha;
|
||||
bool mIsCroppingAreaOutSideOfSourceImage;
|
||||
bool mWriteOnly;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -161,6 +162,10 @@ public:
|
|||
template<typename T>
|
||||
friend class MapDataIntoBufferSource;
|
||||
|
||||
bool IsWriteOnly() const {
|
||||
return mWriteOnly;
|
||||
}
|
||||
|
||||
// Mozilla Extensions
|
||||
ImageBitmapFormat
|
||||
FindOptimalFormat(const Optional<Sequence<ImageBitmapFormat>>& aPossibleFormats,
|
||||
|
|
@ -197,6 +202,7 @@ protected:
|
|||
* CreateInternal(from ImageData) method.
|
||||
*/
|
||||
ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData,
|
||||
bool aWriteOnly,
|
||||
bool aIsPremultipliedAlpha = true);
|
||||
|
||||
virtual ~ImageBitmap();
|
||||
|
|
@ -280,6 +286,12 @@ protected:
|
|||
*/
|
||||
bool mIsCroppingAreaOutSideOfSourceImage;
|
||||
|
||||
/*
|
||||
* Write-Only flag is set to true if this image has been generated from a
|
||||
* cross-origin source. This is the opposite of what is called 'origin-clean'
|
||||
* in the spec.
|
||||
*/
|
||||
bool mWriteOnly;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
|||
|
|
@ -63,6 +63,11 @@ ImageBitmapRenderingContext::TransferFromImageBitmap(ImageBitmap& aImageBitmap)
|
|||
if (!mImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if ImageBitmap is tainted, and if so flag the canvas tainted too.
|
||||
if (aImageBitmap.IsWriteOnly() && mCanvasElement) {
|
||||
mCanvasElement->SetWriteOnly();
|
||||
}
|
||||
|
||||
Redraw(gfxRect(0, 0, mWidth, mHeight));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -275,8 +275,9 @@ struct TexImageSourceAdapter final : public TexImageSource
|
|||
mPboOffset = pboOffset;
|
||||
}
|
||||
|
||||
TexImageSourceAdapter(const dom::ImageBitmap* imageBitmap, ErrorResult*) {
|
||||
TexImageSourceAdapter(const dom::ImageBitmap* imageBitmap, ErrorResult* out_error) {
|
||||
mImageBitmap = imageBitmap;
|
||||
mOut_error = out_error;
|
||||
}
|
||||
|
||||
TexImageSourceAdapter(const dom::ImageData* imageData, ErrorResult*) {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "GLBlitHelper.h"
|
||||
#include "GLContext.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/dom/HTMLCanvasElement.h"
|
||||
#include "mozilla/dom/HTMLVideoElement.h"
|
||||
#include "mozilla/dom/ImageBitmap.h"
|
||||
#include "mozilla/dom/ImageData.h"
|
||||
|
|
@ -214,9 +215,18 @@ FromPboOffset(WebGLContext* webgl, const char* funcName, TexImageTarget target,
|
|||
static UniquePtr<webgl::TexUnpackBlob>
|
||||
FromImageBitmap(WebGLContext* webgl, const char* funcName, TexImageTarget target,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
const dom::ImageBitmap& imageBitmap)
|
||||
const dom::ImageBitmap& imageBitmap, ErrorResult* aRv)
|
||||
{
|
||||
if (imageBitmap.IsWriteOnly()) {
|
||||
aRv->Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UniquePtr<dom::ImageBitmapCloneData> cloneData = Move(imageBitmap.ToCloneData());
|
||||
if (!cloneData) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const RefPtr<gfx::DataSourceSurface> surf = cloneData->mSurface;
|
||||
|
||||
////
|
||||
|
|
@ -293,6 +303,14 @@ WebGLContext::FromDomElem(const char* funcName, TexImageTarget target, uint32_t
|
|||
uint32_t height, uint32_t depth, const dom::Element& elem,
|
||||
ErrorResult* const out_error)
|
||||
{
|
||||
if (elem.IsHTMLElement(nsGkAtoms::canvas)) {
|
||||
const dom::HTMLCanvasElement* canvas = static_cast<const dom::HTMLCanvasElement*>(&elem);
|
||||
if (canvas->IsWriteOnly()) {
|
||||
out_error->Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t flags = nsLayoutUtils::SFE_WANT_IMAGE_SURFACE |
|
||||
nsLayoutUtils::SFE_USE_ELEMENT_SIZE_IF_VECTOR;
|
||||
|
||||
|
|
@ -412,7 +430,7 @@ WebGLContext::From(const char* funcName, TexImageTarget target, GLsizei rawWidth
|
|||
|
||||
if (src.mImageBitmap) {
|
||||
return FromImageBitmap(this, funcName, target, width, height, depth,
|
||||
*(src.mImageBitmap));
|
||||
*(src.mImageBitmap), src.mOut_error);
|
||||
}
|
||||
|
||||
if (src.mImageData) {
|
||||
|
|
|
|||
|
|
@ -270,13 +270,22 @@ function testSecurityErrors() {
|
|||
}
|
||||
|
||||
function checkPromiseFailedWithSecurityError(p) {
|
||||
return p.then( function(reason) { ok(false, "Did not get SecurityError with unclean source. ImageBitmap was created successfully."); },
|
||||
function(reason) { if (reason == "SecurityError: The operation is insecure.") {
|
||||
ok(true, reason);
|
||||
}
|
||||
else {
|
||||
ok(false, "Did not get SecurityError with unclean source. Error Message: " + reason);
|
||||
}});
|
||||
return p.then(imageBitmap => {
|
||||
ok(!!imageBitmap, "ImageBitmaps are always created");
|
||||
const context = document.createElement("canvas").getContext("2d");
|
||||
context.drawImage(imageBitmap, 0, 0);
|
||||
try {
|
||||
context.getImageData(0, 0, 1, 1);
|
||||
ok(false, "Did not get SecurityError with unclean source. ImageBitmap was created successfully.");
|
||||
} catch (ex) {
|
||||
if (ex == "SecurityError: The operation is insecure.") {
|
||||
ok(true, ex);
|
||||
}
|
||||
else {
|
||||
ok(false, "Did not get SecurityError with unclean source. Error Message: " + ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.all([
|
||||
|
|
|
|||
|
|
@ -1000,7 +1000,7 @@ HTMLCanvasElement::GetSize()
|
|||
}
|
||||
|
||||
bool
|
||||
HTMLCanvasElement::IsWriteOnly()
|
||||
HTMLCanvasElement::IsWriteOnly() const
|
||||
{
|
||||
return mWriteOnly;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -224,9 +224,9 @@ public:
|
|||
nsIntSize GetSize();
|
||||
|
||||
/**
|
||||
* Determine whether the canvas is write-only.
|
||||
* Determine whether the canvas is write-only (tainted).
|
||||
*/
|
||||
bool IsWriteOnly();
|
||||
bool IsWriteOnly() const;
|
||||
|
||||
/**
|
||||
* Force the canvas to be write-only.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue