summaryrefslogtreecommitdiffstats
path: root/dom/canvas
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas')
-rw-r--r--dom/canvas/CanvasRenderingContext2D.cpp44
-rw-r--r--dom/canvas/CanvasRenderingContext2D.h12
-rw-r--r--dom/canvas/CanvasRenderingContextHelper.cpp14
-rw-r--r--dom/canvas/ImageBitmap.cpp101
-rw-r--r--dom/canvas/ImageBitmap.h12
-rw-r--r--dom/canvas/ImageBitmapRenderingContext.cpp5
-rw-r--r--dom/canvas/ImageData.cpp1
-rw-r--r--dom/canvas/WebGL1Context.cpp3
-rw-r--r--dom/canvas/WebGLBuffer.cpp3
-rw-r--r--dom/canvas/WebGLContext.cpp103
-rw-r--r--dom/canvas/WebGLContext.h9
-rw-r--r--dom/canvas/WebGLContextBuffers.cpp12
-rw-r--r--dom/canvas/WebGLExtensionDebugShaders.cpp7
-rw-r--r--dom/canvas/WebGLExtensionDisjointTimerQuery.cpp42
-rw-r--r--dom/canvas/WebGLExtensionDrawBuffers.cpp4
-rw-r--r--dom/canvas/WebGLExtensionInstancedArrays.cpp18
-rw-r--r--dom/canvas/WebGLExtensionLoseContext.cpp2
-rw-r--r--dom/canvas/WebGLExtensionVertexArray.cpp8
-rw-r--r--dom/canvas/WebGLObjectModel.h4
-rw-r--r--dom/canvas/WebGLRenderbuffer.cpp10
-rw-r--r--dom/canvas/WebGLShader.cpp10
-rw-r--r--dom/canvas/WebGLTexture.cpp8
-rw-r--r--dom/canvas/WebGLTexture.h1
-rw-r--r--dom/canvas/WebGLTextureUpload.cpp30
-rw-r--r--dom/canvas/test/test_imagebitmap.html23
25 files changed, 255 insertions, 231 deletions
diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp
index 18af28e9f..111519c71 100644
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -783,6 +783,15 @@ public:
: mCanvas(aCanvas)
{}
+ void OnShutdown() {
+ if(!mCanvas) {
+ return;
+ }
+
+ mCanvas = nullptr;
+ nsContentUtils::UnregisterShutdownObserver(this);
+ }
+
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
private:
@@ -800,7 +809,7 @@ CanvasShutdownObserver::Observe(nsISupports* aSubject,
{
if (mCanvas && strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
mCanvas->OnShutdown();
- nsContentUtils::UnregisterShutdownObserver(this);
+ OnShutdown();
}
return NS_OK;
@@ -1038,7 +1047,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CanvasRenderingContext2D)
ImplCycleCollectionTraverse(cb, info.mElement, "Hit region fallback element");
}
}
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(CanvasRenderingContext2D)
@@ -1097,6 +1105,7 @@ CanvasRenderingContext2D::CanvasRenderingContext2D(layers::LayersBackend aCompos
, mIsCapturedFrameInvalid(false)
, mPathTransformWillUpdate(false)
, mInvalidateCount(0)
+ , mWriteOnly(false) // == !origin-clean
{
sNumLivingContexts++;
@@ -1218,7 +1227,7 @@ void
CanvasRenderingContext2D::RemoveShutdownObserver()
{
if (mShutdownObserver) {
- nsContentUtils::UnregisterShutdownObserver(mShutdownObserver);
+ mShutdownObserver->OnShutdown();
mShutdownObserver = nullptr;
}
}
@@ -2554,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();
}
@@ -4209,6 +4219,12 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcess
if (state->gradientStyles[style]) { // Gradient
pattern = GetGradientFor(style);
} else if (state->patternStyles[style]) { // Pattern
+ if (mCtx->mCanvasElement) {
+ CanvasUtils::DoDrawImageSecurityCheck(
+ mCtx->mCanvasElement, state->patternStyles[style]->mPrincipal,
+ state->patternStyles[style]->mForceWriteOnly,
+ state->patternStyles[style]->mCORSUsed);
+ }
pattern = GetPatternFor(style);
} else {
MOZ_ASSERT(false, "Should never reach here.");
@@ -4944,6 +4960,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);
@@ -4952,6 +4972,10 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
return;
}
+ if (imageBitmap.IsWriteOnly()) {
+ SetWriteOnly();
+ }
+
imgSize = gfx::IntSize(imageBitmap.Width(), imageBitmap.Height());
}
else {
@@ -5666,9 +5690,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;
@@ -6312,6 +6335,13 @@ CanvasRenderingContext2D::ShouldForceInactiveLayer(LayerManager* aManager)
return !aManager->CanUseCanvasLayerForSize(GetSize());
}
+void CanvasRenderingContext2D::SetWriteOnly() {
+ mWriteOnly = true;
+ if (mCanvasElement) {
+ mCanvasElement->SetWriteOnly();
+ }
+}
+
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(CanvasPath, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CanvasPath, Release)
diff --git a/dom/canvas/CanvasRenderingContext2D.h b/dom/canvas/CanvasRenderingContext2D.h
index 848b3ee08..d4f295a03 100644
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -40,6 +40,7 @@ class SourceSurface;
namespace dom {
class HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap;
typedef HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap CanvasImageSource;
+class ImageBitmap;
class ImageData;
class StringOrCanvasGradientOrCanvasPattern;
class OwningStringOrCanvasGradientOrCanvasPattern;
@@ -1151,6 +1152,17 @@ 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();
+
+ bool IsWriteOnly() const {
+ return mWriteOnly;
+ }
+
+ bool mWriteOnly;
};
} // namespace dom
diff --git a/dom/canvas/CanvasRenderingContextHelper.cpp b/dom/canvas/CanvasRenderingContextHelper.cpp
index 3000e59bd..61317fb51 100644
--- a/dom/canvas/CanvasRenderingContextHelper.cpp
+++ b/dom/canvas/CanvasRenderingContextHelper.cpp
@@ -7,7 +7,6 @@
#include "ImageBitmapRenderingContext.h"
#include "ImageEncoder.h"
#include "mozilla/dom/CanvasRenderingContext2D.h"
-#include "mozilla/Telemetry.h"
#include "mozilla/UniquePtr.h"
#include "nsContentUtils.h"
#include "nsDOMJSUtils.h"
@@ -138,13 +137,10 @@ CanvasRenderingContextHelper::CreateContextHelper(CanvasContextType aContextType
break;
case CanvasContextType::Canvas2D:
- Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1);
ret = new CanvasRenderingContext2D(aCompositorBackend);
break;
case CanvasContextType::WebGL1:
- Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
-
ret = WebGL1Context::Create();
if (!ret)
return nullptr;
@@ -152,8 +148,6 @@ CanvasRenderingContextHelper::CreateContextHelper(CanvasContextType aContextType
break;
case CanvasContextType::WebGL2:
- Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
-
ret = WebGL2Context::Create();
if (!ret)
return nullptr;
@@ -205,16 +199,8 @@ CanvasRenderingContextHelper::GetContext(JSContext* aCx,
// See bug 645792 and bug 1215072.
// We want to throw only if dictionary initialization fails,
// so only in case aRv has been set to some error value.
- if (contextType == CanvasContextType::WebGL1)
- Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_SUCCESS, 0);
- else if (contextType == CanvasContextType::WebGL2)
- Telemetry::Accumulate(Telemetry::CANVAS_WEBGL2_SUCCESS, 0);
return nullptr;
}
- if (contextType == CanvasContextType::WebGL1)
- Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_SUCCESS, 1);
- else if (contextType == CanvasContextType::WebGL2)
- Telemetry::Accumulate(Telemetry::CANVAS_WEBGL2_SUCCESS, 1);
} else {
// We already have a context of some type.
if (contextType != mCurrentContextType)
diff --git a/dom/canvas/ImageBitmap.cpp b/dom/canvas/ImageBitmap.cpp
index e45cdfc6f..6efe1b318 100644
--- a/dom/canvas/ImageBitmap.cpp
+++ b/dom/canvas/ImageBitmap.cpp
@@ -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;
}
diff --git a/dom/canvas/ImageBitmap.h b/dom/canvas/ImageBitmap.h
index 2119c6bda..25084b6ac 100644
--- a/dom/canvas/ImageBitmap.h
+++ b/dom/canvas/ImageBitmap.h
@@ -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
diff --git a/dom/canvas/ImageBitmapRenderingContext.cpp b/dom/canvas/ImageBitmapRenderingContext.cpp
index 8f5074554..ad313906a 100644
--- a/dom/canvas/ImageBitmapRenderingContext.cpp
+++ b/dom/canvas/ImageBitmapRenderingContext.cpp
@@ -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));
}
diff --git a/dom/canvas/ImageData.cpp b/dom/canvas/ImageData.cpp
index b201fa279..d24fbca95 100644
--- a/dom/canvas/ImageData.cpp
+++ b/dom/canvas/ImageData.cpp
@@ -29,7 +29,6 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ImageData)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ImageData)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ImageData)
diff --git a/dom/canvas/WebGL1Context.cpp b/dom/canvas/WebGL1Context.cpp
index c1818a3f9..e82cafbe5 100644
--- a/dom/canvas/WebGL1Context.cpp
+++ b/dom/canvas/WebGL1Context.cpp
@@ -6,7 +6,6 @@
#include "WebGL1Context.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
-#include "mozilla/Telemetry.h"
#include "WebGLFormats.h"
namespace mozilla {
@@ -43,8 +42,6 @@ WebGL1Context::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
nsresult
NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** out_result)
{
- mozilla::Telemetry::Accumulate(mozilla::Telemetry::CANVAS_WEBGL_USED, 1);
-
nsIDOMWebGLRenderingContext* ctx = mozilla::WebGL1Context::Create();
NS_ADDREF(*out_result = ctx);
diff --git a/dom/canvas/WebGLBuffer.cpp b/dom/canvas/WebGLBuffer.cpp
index f202c9950..02a8f649f 100644
--- a/dom/canvas/WebGLBuffer.cpp
+++ b/dom/canvas/WebGLBuffer.cpp
@@ -115,7 +115,7 @@ WebGLBuffer::BufferData(GLenum target, size_t size, const void* data, GLenum usa
const ScopedLazyBind lazyBind(gl, target, this);
mContext->InvalidateBufferFetching();
-#ifdef XP_MACOSX
+#if defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK)
// bug 790879
if (gl->WorkAroundDriverBugs() &&
size > INT32_MAX)
@@ -134,6 +134,7 @@ WebGLBuffer::BufferData(GLenum target, size_t size, const void* data, GLenum usa
if (error) {
MOZ_ASSERT(error == LOCAL_GL_OUT_OF_MEMORY);
mContext->ErrorOutOfMemory("%s: Error from driver: 0x%04x", funcName, error);
+ mByteLength = 0;
return;
}
} else {
diff --git a/dom/canvas/WebGLContext.cpp b/dom/canvas/WebGLContext.cpp
index 32eed6354..e2e05e5fd 100644
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -47,7 +47,6 @@
#include "nsSVGEffects.h"
#include "prenv.h"
#include "ScopedGLHelpers.h"
-#include "VRManagerChild.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
// Local
@@ -825,10 +824,6 @@ NS_IMETHODIMP
WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
{
if (signedWidth < 0 || signedHeight < 0) {
- if (!gl) {
- Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID,
- NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_SIZE"));
- }
GenerateWarning("Canvas size is too large (seems like a negative value wrapped)");
return NS_ERROR_OUT_OF_MEMORY;
}
@@ -884,12 +879,6 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
return NS_OK;
}
- nsCString failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_UNKOWN");
- auto autoTelemetry = mozilla::MakeScopeExit([&] {
- Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID,
- failureId);
- });
-
// End of early return cases.
// At this point we know that we're not just resizing an existing context,
// we are initializing a new context.
@@ -911,7 +900,6 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
// resource handles created from older context generations.
if (!(mGeneration + 1).isValid()) {
// exit without changing the value of mGeneration
- failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_TOO_MANY");
const nsLiteralCString text("Too many WebGL contexts created this run.");
ThrowEvent_WebGLContextCreationError(text);
return NS_ERROR_FAILURE;
@@ -928,11 +916,6 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
disabled |= gfxPlatform::InSafeMode();
if (disabled) {
- if (gfxPlatform::InSafeMode()) {
- failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_SAFEMODE");
- } else {
- failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_DISABLED");
- }
const nsLiteralCString text("WebGL is currently disabled.");
ThrowEvent_WebGLContextCreationError(text);
return NS_ERROR_FAILURE;
@@ -945,7 +928,6 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
if (mOptions.failIfMajorPerformanceCaveat) {
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
if (!HasAcceleratedLayers(gfxInfo)) {
- failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_PERF_CAVEAT");
const nsLiteralCString text("failIfMajorPerformanceCaveat: Compositor is not"
" hardware-accelerated.");
ThrowEvent_WebGLContextCreationError(text);
@@ -961,12 +943,9 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
if (!CreateAndInitGL(forceEnabled, &failReasons)) {
nsCString text("WebGL creation failed: ");
for (const auto& cur : failReasons) {
- Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID, cur.key);
-
text.AppendASCII("\n* ");
text.Append(cur.info);
}
- failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_REASON");
ThrowEvent_WebGLContextCreationError(text);
return NS_ERROR_FAILURE;
}
@@ -978,7 +957,6 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
DestroyResourcesAndContext();
MOZ_ASSERT(!gl);
- failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_PERF_WARP");
const nsLiteralCString text("failIfMajorPerformanceCaveat: Driver is not"
" hardware-accelerated.");
ThrowEvent_WebGLContextCreationError(text);
@@ -992,7 +970,6 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
DestroyResourcesAndContext();
MOZ_ASSERT(!gl);
- failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_DXGL_INTEROP2");
const nsLiteralCString text("Caveat: WGL without DXGLInterop2.");
ThrowEvent_WebGLContextCreationError(text);
return NS_ERROR_FAILURE;
@@ -1001,7 +978,6 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
}
if (!ResizeBackbuffer(width, height)) {
- failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_BACKBUFFER");
const nsLiteralCString text("Initializing WebGL backbuffer failed.");
ThrowEvent_WebGLContextCreationError(text);
return NS_ERROR_FAILURE;
@@ -1085,7 +1061,6 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
//////
- failureId = NS_LITERAL_CSTRING("SUCCESS");
return NS_OK;
}
@@ -2263,84 +2238,6 @@ WebGLContext::GetUnpackSize(bool isFunc3D, uint32_t width, uint32_t height,
return totalBytes;
}
-already_AddRefed<layers::SharedSurfaceTextureClient>
-WebGLContext::GetVRFrame()
-{
- if (!mLayerIsMirror) {
- /**
- * Do not allow VR frame submission until a mirroring canvas layer has
- * been returned by GetCanvasLayer
- */
- return nullptr;
- }
-
- VRManagerChild* vrmc = VRManagerChild::Get();
- if (!vrmc) {
- return nullptr;
- }
-
- /**
- * Swap buffers as though composition has occurred.
- * We will then share the resulting front buffer to be submitted to the VR
- * compositor.
- */
- BeginComposition();
- EndComposition();
-
- gl::GLScreenBuffer* screen = gl->Screen();
- if (!screen) {
- return nullptr;
- }
-
- RefPtr<SharedSurfaceTextureClient> sharedSurface = screen->Front();
- if (!sharedSurface) {
- return nullptr;
- }
-
- if (sharedSurface && sharedSurface->GetAllocator() != vrmc) {
- RefPtr<SharedSurfaceTextureClient> dest =
- screen->Factory()->NewTexClient(sharedSurface->GetSize());
- if (!dest) {
- return nullptr;
- }
- gl::SharedSurface* destSurf = dest->Surf();
- destSurf->ProducerAcquire();
- SharedSurface::ProdCopy(sharedSurface->Surf(), dest->Surf(),
- screen->Factory());
- destSurf->ProducerRelease();
-
- return dest.forget();
- }
-
- return sharedSurface.forget();
-}
-
-bool
-WebGLContext::StartVRPresentation()
-{
- VRManagerChild* vrmc = VRManagerChild::Get();
- if (!vrmc) {
- return false;
- }
- gl::GLScreenBuffer* screen = gl->Screen();
- if (!screen) {
- return false;
- }
- gl::SurfaceCaps caps = screen->mCaps;
-
- UniquePtr<gl::SurfaceFactory> factory =
- gl::GLScreenBuffer::CreateFactory(gl,
- caps,
- vrmc,
- vrmc->GetBackendType(),
- TextureFlags::ORIGIN_BOTTOM_LEFT);
-
- if (factory) {
- screen->Morph(Move(factory));
- }
- return true;
-}
-
////////////////////////////////////////////////////////////////////////////////
static inline size_t
diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h
index b4d416a33..0510e6898 100644
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -20,6 +20,7 @@
#include "mozilla/gfx/2D.h"
#include "mozilla/LinkedList.h"
#include "mozilla/UniquePtr.h"
+#include "mozilla/WeakPtr.h"
#include "nsCycleCollectionNoteChild.h"
#include "nsICanvasRenderingContextInternal.h"
#include "nsLayoutUtils.h"
@@ -275,8 +276,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*) {
@@ -298,6 +300,7 @@ class WebGLContext
, public WebGLContextUnchecked
, public WebGLRectangleObject
, public nsWrapperCache
+ , public SupportsWeakPtr<WebGLContext>
{
friend class ScopedDrawHelper;
friend class ScopedDrawWithTransformFeedback;
@@ -341,6 +344,7 @@ public:
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(WebGLContext,
nsIDOMWebGLRenderingContext)
+ MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLContext)
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override = 0;
@@ -656,9 +660,6 @@ public:
void PixelStorei(GLenum pname, GLint param);
void PolygonOffset(GLfloat factor, GLfloat units);
- already_AddRefed<layers::SharedSurfaceTextureClient> GetVRFrame();
- bool StartVRPresentation();
-
////
webgl::PackingInfo
diff --git a/dom/canvas/WebGLContextBuffers.cpp b/dom/canvas/WebGLContextBuffers.cpp
index af506c01c..f53f9d7d7 100644
--- a/dom/canvas/WebGLContextBuffers.cpp
+++ b/dom/canvas/WebGLContextBuffers.cpp
@@ -9,6 +9,8 @@
#include "WebGLBuffer.h"
#include "WebGLVertexArray.h"
+#include "mozilla/CheckedInt.h"
+
namespace mozilla {
WebGLRefPtr<WebGLBuffer>*
@@ -345,6 +347,16 @@ WebGLContext::BufferData(GLenum target, WebGLsizeiptr size, GLenum usage)
////
+ const auto checkedSize = CheckedInt<size_t>(size);
+ if (!checkedSize.isValid())
+ return ErrorOutOfMemory("%s: Size too large for platform.", funcName);
+
+#if defined(XP_MACOSX)
+ if (gl->WorkAroundDriverBugs() && size > 1200000000) {
+ return ErrorOutOfMemory("Allocations larger than 1200000000 fail on MacOS.");
+ }
+#endif
+
const UniqueBuffer zeroBuffer(calloc(size, 1));
if (!zeroBuffer)
return ErrorOutOfMemory("%s: Failed to allocate zeros.", funcName);
diff --git a/dom/canvas/WebGLExtensionDebugShaders.cpp b/dom/canvas/WebGLExtensionDebugShaders.cpp
index 75880465e..8399aeb95 100644
--- a/dom/canvas/WebGLExtensionDebugShaders.cpp
+++ b/dom/canvas/WebGLExtensionDebugShaders.cpp
@@ -29,15 +29,10 @@ WebGLExtensionDebugShaders::GetTranslatedShaderSource(const WebGLShader& shader,
{
retval.SetIsVoid(true);
- if (mIsLost) {
- mContext->ErrorInvalidOperation("%s: Extension is lost.",
- "getTranslatedShaderSource");
+ if (mIsLost || !mContext) {
return;
}
- if (mContext->IsContextLost())
- return;
-
if (!mContext->ValidateObject("getShaderTranslatedSource: shader", shader))
return;
diff --git a/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp b/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp
index e2e34f14e..da76eeb2d 100644
--- a/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp
+++ b/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp
@@ -40,8 +40,10 @@ void
WebGLExtensionDisjointTimerQuery::DeleteQueryEXT(WebGLQuery* query) const
{
const char funcName[] = "deleteQueryEXT";
- if (mIsLost)
- return;
+
+ if (mIsLost || !mContext) {
+ return;
+ }
mContext->DeleteQuery(query, funcName);
}
@@ -50,8 +52,10 @@ bool
WebGLExtensionDisjointTimerQuery::IsQueryEXT(const WebGLQuery* query) const
{
const char funcName[] = "isQueryEXT";
- if (mIsLost)
- return false;
+
+ if (mIsLost || !mContext) {
+ return false;
+ }
return mContext->IsQuery(query, funcName);
}
@@ -60,8 +64,10 @@ void
WebGLExtensionDisjointTimerQuery::BeginQueryEXT(GLenum target, WebGLQuery& query) const
{
const char funcName[] = "beginQueryEXT";
- if (mIsLost)
- return;
+
+ if (mIsLost || !mContext) {
+ return;
+ }
mContext->BeginQuery(target, query, funcName);
}
@@ -70,8 +76,10 @@ void
WebGLExtensionDisjointTimerQuery::EndQueryEXT(GLenum target) const
{
const char funcName[] = "endQueryEXT";
- if (mIsLost)
- return;
+
+ if (mIsLost || !mContext) {
+ return;
+ }
mContext->EndQuery(target, funcName);
}
@@ -80,8 +88,10 @@ void
WebGLExtensionDisjointTimerQuery::QueryCounterEXT(WebGLQuery& query, GLenum target) const
{
const char funcName[] = "queryCounterEXT";
- if (mIsLost)
- return;
+
+ if (mIsLost || !mContext) {
+ return;
+ }
if (!mContext->ValidateObject(funcName, query))
return;
@@ -95,8 +105,10 @@ WebGLExtensionDisjointTimerQuery::GetQueryEXT(JSContext* cx, GLenum target, GLen
{
const char funcName[] = "getQueryEXT";
retval.setNull();
- if (mIsLost)
- return;
+
+ if (mIsLost || !mContext) {
+ return;
+ }
mContext->GetQuery(cx, target, pname, retval, funcName);
}
@@ -108,8 +120,10 @@ WebGLExtensionDisjointTimerQuery::GetQueryObjectEXT(JSContext* cx,
{
const char funcName[] = "getQueryObjectEXT";
retval.setNull();
- if (mIsLost)
- return;
+
+ if (mIsLost || !mContext) {
+ return;
+ }
mContext->GetQueryParameter(cx, query, pname, retval, funcName);
}
diff --git a/dom/canvas/WebGLExtensionDrawBuffers.cpp b/dom/canvas/WebGLExtensionDrawBuffers.cpp
index 27aa76cc7..6f386621f 100644
--- a/dom/canvas/WebGLExtensionDrawBuffers.cpp
+++ b/dom/canvas/WebGLExtensionDrawBuffers.cpp
@@ -36,7 +36,9 @@ void
WebGLExtensionDrawBuffers::DrawBuffersWEBGL(const dom::Sequence<GLenum>& buffers)
{
if (mIsLost) {
- mContext->ErrorInvalidOperation("drawBuffersWEBGL: Extension is lost.");
+ if (mContext) {
+ mContext->ErrorInvalidOperation("drawBuffersWEBGL: Extension is lost.");
+ }
return;
}
diff --git a/dom/canvas/WebGLExtensionInstancedArrays.cpp b/dom/canvas/WebGLExtensionInstancedArrays.cpp
index 10d0533fe..22b3ec12c 100644
--- a/dom/canvas/WebGLExtensionInstancedArrays.cpp
+++ b/dom/canvas/WebGLExtensionInstancedArrays.cpp
@@ -28,8 +28,10 @@ WebGLExtensionInstancedArrays::DrawArraysInstancedANGLE(GLenum mode,
GLsizei primcount)
{
if (mIsLost) {
- mContext->ErrorInvalidOperation("%s: Extension is lost.",
- "drawArraysInstancedANGLE");
+ if (mContext) {
+ mContext->ErrorInvalidOperation("%s: Extension is lost.",
+ "drawArraysInstancedANGLE");
+ }
return;
}
@@ -44,8 +46,10 @@ WebGLExtensionInstancedArrays::DrawElementsInstancedANGLE(GLenum mode,
GLsizei primcount)
{
if (mIsLost) {
- mContext->ErrorInvalidOperation("%s: Extension is lost.",
- "drawElementsInstancedANGLE");
+ if (mContext) {
+ mContext->ErrorInvalidOperation("%s: Extension is lost.",
+ "drawElementsInstancedANGLE");
+ }
return;
}
@@ -57,8 +61,10 @@ WebGLExtensionInstancedArrays::VertexAttribDivisorANGLE(GLuint index,
GLuint divisor)
{
if (mIsLost) {
- mContext->ErrorInvalidOperation("%s: Extension is lost.",
- "vertexAttribDivisorANGLE");
+ if (mContext) {
+ mContext->ErrorInvalidOperation("%s: Extension is lost.",
+ "vertexAttribDivisorANGLE");
+ }
return;
}
diff --git a/dom/canvas/WebGLExtensionLoseContext.cpp b/dom/canvas/WebGLExtensionLoseContext.cpp
index 020731e63..41f1633d8 100644
--- a/dom/canvas/WebGLExtensionLoseContext.cpp
+++ b/dom/canvas/WebGLExtensionLoseContext.cpp
@@ -22,12 +22,14 @@ WebGLExtensionLoseContext::~WebGLExtensionLoseContext()
void
WebGLExtensionLoseContext::LoseContext()
{
+ if (!mContext) return;
mContext->LoseContext();
}
void
WebGLExtensionLoseContext::RestoreContext()
{
+ if (!mContext) return;
mContext->RestoreContext();
}
diff --git a/dom/canvas/WebGLExtensionVertexArray.cpp b/dom/canvas/WebGLExtensionVertexArray.cpp
index 0984582f5..39aa96801 100644
--- a/dom/canvas/WebGLExtensionVertexArray.cpp
+++ b/dom/canvas/WebGLExtensionVertexArray.cpp
@@ -25,7 +25,7 @@ WebGLExtensionVertexArray::~WebGLExtensionVertexArray()
already_AddRefed<WebGLVertexArray>
WebGLExtensionVertexArray::CreateVertexArrayOES()
{
- if (mIsLost)
+ if (mIsLost || !mContext)
return nullptr;
return mContext->CreateVertexArray();
@@ -34,7 +34,7 @@ WebGLExtensionVertexArray::CreateVertexArrayOES()
void
WebGLExtensionVertexArray::DeleteVertexArrayOES(WebGLVertexArray* array)
{
- if (mIsLost)
+ if (mIsLost || !mContext)
return;
mContext->DeleteVertexArray(array);
@@ -43,7 +43,7 @@ WebGLExtensionVertexArray::DeleteVertexArrayOES(WebGLVertexArray* array)
bool
WebGLExtensionVertexArray::IsVertexArrayOES(const WebGLVertexArray* array)
{
- if (mIsLost)
+ if (mIsLost || !mContext)
return false;
return mContext->IsVertexArray(array);
@@ -52,7 +52,7 @@ WebGLExtensionVertexArray::IsVertexArrayOES(const WebGLVertexArray* array)
void
WebGLExtensionVertexArray::BindVertexArrayOES(WebGLVertexArray* array)
{
- if (mIsLost)
+ if (mIsLost || !mContext)
return;
mContext->BindVertexArray(array);
diff --git a/dom/canvas/WebGLObjectModel.h b/dom/canvas/WebGLObjectModel.h
index b18b790c0..6371c7b03 100644
--- a/dom/canvas/WebGLObjectModel.h
+++ b/dom/canvas/WebGLObjectModel.h
@@ -6,8 +6,8 @@
#ifndef WEBGLOBJECTMODEL_H_
#define WEBGLOBJECTMODEL_H_
+#include "mozilla/WeakPtr.h"
#include "nsCycleCollectionNoteChild.h"
-
#include "WebGLTypes.h"
namespace mozilla {
@@ -24,7 +24,7 @@ class WebGLContext;
class WebGLContextBoundObject
{
public:
- WebGLContext* const mContext;
+ const WeakPtr<WebGLContext> mContext;
private:
const uint32_t mContextGeneration;
diff --git a/dom/canvas/WebGLRenderbuffer.cpp b/dom/canvas/WebGLRenderbuffer.cpp
index ec076fdbb..32397dd1a 100644
--- a/dom/canvas/WebGLRenderbuffer.cpp
+++ b/dom/canvas/WebGLRenderbuffer.cpp
@@ -215,6 +215,16 @@ WebGLRenderbuffer::RenderbufferStorage(const char* funcName, uint32_t samples,
if (error) {
const char* errorName = mContext->ErrorName(error);
mContext->GenerateWarning("%s generated error %s", funcName, errorName);
+ if (error == LOCAL_GL_OUT_OF_MEMORY) {
+ // Truncate.
+ mSamples = 0;
+ mFormat = nullptr;
+ mWidth = 0;
+ mHeight = 0;
+ mImageDataStatus = WebGLImageDataStatus::NoImageData;
+
+ InvalidateStatusOfAttachedFBs();
+ }
return;
}
diff --git a/dom/canvas/WebGLShader.cpp b/dom/canvas/WebGLShader.cpp
index 37380f1e0..69ca03fc4 100644
--- a/dom/canvas/WebGLShader.cpp
+++ b/dom/canvas/WebGLShader.cpp
@@ -168,16 +168,6 @@ WebGLShader::ShaderSource(const nsAString& source)
// 7-bit ASCII range, so we can skip the NS_IsAscii() check.
const NS_LossyConvertUTF16toASCII sourceCString(cleanSource);
- if (mContext->gl->WorkAroundDriverBugs()) {
- const size_t maxSourceLength = 0x3ffff;
- if (sourceCString.Length() > maxSourceLength) {
- mContext->ErrorInvalidValue("shaderSource: Source has more than %d"
- " characters. (Driver workaround)",
- maxSourceLength);
- return;
- }
- }
-
if (PR_GetEnv("MOZ_WEBGL_DUMP_SHADERS")) {
printf_stderr("////////////////////////////////////////\n");
printf_stderr("// MOZ_WEBGL_DUMP_SHADERS:\n");
diff --git a/dom/canvas/WebGLTexture.cpp b/dom/canvas/WebGLTexture.cpp
index 767ff610a..65bb71153 100644
--- a/dom/canvas/WebGLTexture.cpp
+++ b/dom/canvas/WebGLTexture.cpp
@@ -51,8 +51,6 @@ WebGLTexture::ImageInfo::Clear()
WebGLTexture::ImageInfo&
WebGLTexture::ImageInfo::operator =(const ImageInfo& a)
{
- MOZ_ASSERT(a.IsDefined());
-
Mutable(mFormat) = a.mFormat;
Mutable(mWidth) = a.mWidth;
Mutable(mHeight) = a.mHeight;
@@ -1216,6 +1214,12 @@ WebGLTexture::TexParameter(TexTarget texTarget, GLenum pname, const FloatOrInt&
mContext->gl->fTexParameterf(texTarget.get(), pname, clamped.f);
}
+void WebGLTexture::Truncate() {
+ for (auto& cur : mImageInfoArr) {
+ SetImageInfo(&cur, ImageInfo());
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLTexture)
diff --git a/dom/canvas/WebGLTexture.h b/dom/canvas/WebGLTexture.h
index 66e781f23..8d3024590 100644
--- a/dom/canvas/WebGLTexture.h
+++ b/dom/canvas/WebGLTexture.h
@@ -386,6 +386,7 @@ public:
bool* const out_initFailed);
bool IsMipmapCubeComplete() const;
+ void Truncate();
bool IsCubeMap() const { return (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP); }
diff --git a/dom/canvas/WebGLTextureUpload.cpp b/dom/canvas/WebGLTextureUpload.cpp
index 612d5889d..ae60d2a2b 100644
--- a/dom/canvas/WebGLTextureUpload.cpp
+++ b/dom/canvas/WebGLTextureUpload.cpp
@@ -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) {
@@ -1160,6 +1178,7 @@ WebGLTexture::TexStorage(const char* funcName, TexTarget target, GLsizei levels,
if (error == LOCAL_GL_OUT_OF_MEMORY) {
mContext->ErrorOutOfMemory("%s: Ran out of memory during texture allocation.",
funcName);
+ Truncate();
return;
}
if (error) {
@@ -1292,6 +1311,7 @@ WebGLTexture::TexImage(const char* funcName, TexImageTarget target, GLint level,
if (glError == LOCAL_GL_OUT_OF_MEMORY) {
mContext->ErrorOutOfMemory("%s: Driver ran out of memory during upload.",
funcName);
+ Truncate();
return;
}
@@ -1380,6 +1400,7 @@ WebGLTexture::TexSubImage(const char* funcName, TexImageTarget target, GLint lev
if (glError == LOCAL_GL_OUT_OF_MEMORY) {
mContext->ErrorOutOfMemory("%s: Driver ran out of memory during upload.",
funcName);
+ Truncate();
return;
}
@@ -1496,6 +1517,7 @@ WebGLTexture::CompressedTexImage(const char* funcName, TexImageTarget target, GL
blob->mAvailBytes, blob->mPtr);
if (error == LOCAL_GL_OUT_OF_MEMORY) {
mContext->ErrorOutOfMemory("%s: Ran out of memory during upload.", funcName);
+ Truncate();
return;
}
if (error) {
@@ -1646,6 +1668,7 @@ WebGLTexture::CompressedTexSubImage(const char* funcName, TexImageTarget target,
blob->mAvailBytes, blob->mPtr);
if (error == LOCAL_GL_OUT_OF_MEMORY) {
mContext->ErrorOutOfMemory("%s: Ran out of memory during upload.", funcName);
+ Truncate();
return;
}
if (error) {
@@ -1974,7 +1997,7 @@ WebGLTexture::ValidateCopyTexImageForFeedback(const char* funcName, uint32_t lev
static bool
DoCopyTexOrSubImage(WebGLContext* webgl, const char* funcName, bool isSubImage,
- const WebGLTexture* tex, TexImageTarget target, GLint level,
+ WebGLTexture* tex, TexImageTarget target, GLint level,
GLint xWithinSrc, GLint yWithinSrc,
uint32_t srcTotalWidth, uint32_t srcTotalHeight,
const webgl::FormatUsageInfo* srcUsage,
@@ -2051,6 +2074,7 @@ DoCopyTexOrSubImage(WebGLContext* webgl, const char* funcName, bool isSubImage,
if (error == LOCAL_GL_OUT_OF_MEMORY) {
webgl->ErrorOutOfMemory("%s: Ran out of memory during texture copy.", funcName);
+ tex->Truncate();
return false;
}
diff --git a/dom/canvas/test/test_imagebitmap.html b/dom/canvas/test/test_imagebitmap.html
index b3d3c08ad..3b74970ac 100644
--- a/dom/canvas/test/test_imagebitmap.html
+++ b/dom/canvas/test/test_imagebitmap.html
@@ -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([