diff options
Diffstat (limited to 'dom')
-rw-r--r-- | dom/base/Location.cpp | 4 | ||||
-rw-r--r-- | dom/canvas/CanvasRenderingContext2D.cpp | 17 | ||||
-rw-r--r-- | dom/canvas/CanvasRenderingContext2D.h | 14 | ||||
-rw-r--r-- | dom/canvas/ImageBitmap.cpp | 101 | ||||
-rw-r--r-- | dom/canvas/ImageBitmap.h | 12 | ||||
-rw-r--r-- | dom/canvas/ImageBitmapRenderingContext.cpp | 5 | ||||
-rw-r--r-- | dom/canvas/WebGLContext.h | 3 | ||||
-rw-r--r-- | dom/canvas/WebGLTextureUpload.cpp | 22 | ||||
-rw-r--r-- | dom/canvas/test/test_imagebitmap.html | 23 | ||||
-rw-r--r-- | dom/fetch/FetchDriver.cpp | 10 | ||||
-rw-r--r-- | dom/html/HTMLCanvasElement.cpp | 2 | ||||
-rw-r--r-- | dom/html/HTMLCanvasElement.h | 4 | ||||
-rw-r--r-- | dom/html/nsTextEditorState.cpp | 6 | ||||
-rw-r--r-- | dom/locales/en-US/chrome/security/security.properties | 2 | ||||
-rw-r--r-- | dom/security/nsContentSecurityManager.cpp | 56 | ||||
-rw-r--r-- | dom/security/nsContentSecurityManager.h | 1 | ||||
-rw-r--r-- | dom/webidl/AddonEvent.webidl | 12 | ||||
-rw-r--r-- | dom/webidl/AddonManager.webidl | 91 | ||||
-rw-r--r-- | dom/webidl/moz.build | 6 | ||||
-rw-r--r-- | dom/xslt/xslt/txMozillaStylesheetCompiler.cpp | 4 |
20 files changed, 207 insertions, 188 deletions
diff --git a/dom/base/Location.cpp b/dom/base/Location.cpp index 3a39a9e66..1483c32f9 100644 --- a/dom/base/Location.cpp +++ b/dom/base/Location.cpp @@ -789,10 +789,6 @@ Location::GetSearch(nsAString& aSearch) NS_IMETHODIMP Location::SetSearch(const nsAString& aSearch) { - if (aSearch.IsEmpty()) { - return NS_OK; // Ignore empty string - } - nsresult rv = SetSearchInternal(aSearch); if (NS_FAILED(rv)) { return rv; diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index b60ab239d..a750c69b0 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -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; diff --git a/dom/canvas/CanvasRenderingContext2D.h b/dom/canvas/CanvasRenderingContext2D.h index 848b3ee08..46758ec88 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,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 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/WebGLContext.h b/dom/canvas/WebGLContext.h index 3ec307b00..8a20237ff 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -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*) { diff --git a/dom/canvas/WebGLTextureUpload.cpp b/dom/canvas/WebGLTextureUpload.cpp index 612d5889d..3839b5d5e 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) { 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([ diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index 1791399b7..6294b0dc5 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -903,11 +903,7 @@ FetchDriver::SetRequestHeaders(nsIHttpChannel* aChannel) const AutoTArray<InternalHeaders::Entry, 5> headers; mRequest->Headers()->GetEntries(headers); - bool hasAccept = false; for (uint32_t i = 0; i < headers.Length(); ++i) { - if (!hasAccept && headers[i].mName.EqualsLiteral("accept")) { - hasAccept = true; - } if (headers[i].mValue.IsEmpty()) { aChannel->SetEmptyRequestHeader(headers[i].mName); } else { @@ -915,12 +911,6 @@ FetchDriver::SetRequestHeaders(nsIHttpChannel* aChannel) const } } - if (!hasAccept) { - aChannel->SetRequestHeader(NS_LITERAL_CSTRING("accept"), - NS_LITERAL_CSTRING("*/*"), - false /* merge */); - } - if (mRequest->ForceOriginHeader()) { nsAutoString origin; if (NS_SUCCEEDED(nsContentUtils::GetUTFOrigin(mPrincipal, origin))) { diff --git a/dom/html/HTMLCanvasElement.cpp b/dom/html/HTMLCanvasElement.cpp index 527135a80..a01795d9e 100644 --- a/dom/html/HTMLCanvasElement.cpp +++ b/dom/html/HTMLCanvasElement.cpp @@ -1000,7 +1000,7 @@ HTMLCanvasElement::GetSize() } bool -HTMLCanvasElement::IsWriteOnly() +HTMLCanvasElement::IsWriteOnly() const { return mWriteOnly; } diff --git a/dom/html/HTMLCanvasElement.h b/dom/html/HTMLCanvasElement.h index 746fab198..e77db6ff1 100644 --- a/dom/html/HTMLCanvasElement.h +++ b/dom/html/HTMLCanvasElement.h @@ -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. diff --git a/dom/html/nsTextEditorState.cpp b/dom/html/nsTextEditorState.cpp index 0b4cb1920..25be6016c 100644 --- a/dom/html/nsTextEditorState.cpp +++ b/dom/html/nsTextEditorState.cpp @@ -2255,7 +2255,11 @@ nsTextEditorState::UpdatePlaceholderText(bool aNotify) nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement); content->GetAttr(kNameSpaceID_None, nsGkAtoms::placeholder, placeholderValue); - nsContentUtils::RemoveNewlines(placeholderValue); + if (mTextCtrlElement->IsTextArea()) { // <textarea>s preserve newlines... + nsContentUtils::PlatformToDOMLineBreaks(placeholderValue); + } else { // ...<input>s don't + nsContentUtils::RemoveNewlines(placeholderValue); + } NS_ASSERTION(mPlaceholderDiv->GetFirstChild(), "placeholder div has no child"); mPlaceholderDiv->GetFirstChild()->SetText(placeholderValue, aNotify); } diff --git a/dom/locales/en-US/chrome/security/security.properties b/dom/locales/en-US/chrome/security/security.properties index 8efdb0a6d..2be56fb9d 100644 --- a/dom/locales/en-US/chrome/security/security.properties +++ b/dom/locales/en-US/chrome/security/security.properties @@ -85,3 +85,5 @@ BlockScriptWithWrongMimeType=Script from “%1$S” was blocked because of a dis # LOCALIZATION NOTE: Do not translate "data: URI". BlockTopLevelDataURINavigation=Navigation to toplevel data: URI not allowed (Blocked loading of: “%1$S”) + +BlockSubresourceFTP=Loading FTP subresource within http(s) page not allowed (Blocked loading of: “%1$S”) diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp index 570730312..f2cbc8fcf 100644 --- a/dom/security/nsContentSecurityManager.cpp +++ b/dom/security/nsContentSecurityManager.cpp @@ -92,6 +92,55 @@ nsContentSecurityManager::AllowTopLevelNavigationToDataURI(nsIChannel* aChannel) return false; } +/* static */ nsresult +nsContentSecurityManager::CheckFTPSubresourceLoad(nsIChannel* aChannel) +{ + // We dissallow using FTP resources as a subresource everywhere. + // The only valid way to use FTP resources is loading it as + // a top level document. + + nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo(); + if (!loadInfo) { + return NS_OK; + } + + nsContentPolicyType type = loadInfo->GetExternalContentPolicyType(); + if (type == nsIContentPolicy::TYPE_DOCUMENT) { + return NS_OK; + } + + nsCOMPtr<nsIURI> uri; + nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri)); + NS_ENSURE_SUCCESS(rv, rv); + if (!uri) { + return NS_OK; + } + + bool isFtpURI = (NS_SUCCEEDED(uri->SchemeIs("ftp", &isFtpURI)) && isFtpURI); + if (!isFtpURI) { + return NS_OK; + } + + nsCOMPtr<nsIDocument> doc; + if (nsINode* node = loadInfo->LoadingNode()) { + doc = node->OwnerDoc(); + } + + nsAutoCString spec; + uri->GetSpec(spec); + NS_ConvertUTF8toUTF16 specUTF16(NS_UnescapeURL(spec)); + const char16_t* params[] = { specUTF16.get() }; + + nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, + NS_LITERAL_CSTRING("FTP_URI_BLOCKED"), + doc, + nsContentUtils::eSECURITY_PROPERTIES, + "BlockSubresourceFTP", + params, ArrayLength(params)); + + return NS_ERROR_CONTENT_BLOCKED; +} + static nsresult ValidateSecurityFlags(nsILoadInfo* aLoadInfo) { @@ -574,6 +623,10 @@ nsContentSecurityManager::doContentSecurityCheck(nsIChannel* aChannel, rv = DoContentSecurityChecks(aChannel, loadInfo); NS_ENSURE_SUCCESS(rv, rv); + // Apply this after CSP checks to allow CSP reporting. + rv = CheckFTPSubresourceLoad(aChannel); + NS_ENSURE_SUCCESS(rv, rv); + // now lets set the initalSecurityFlag for subsequent calls loadInfo->SetInitialSecurityCheckDone(true); @@ -591,6 +644,9 @@ nsContentSecurityManager::AsyncOnChannelRedirect(nsIChannel* aOldChannel, // Are we enforcing security using LoadInfo? if (loadInfo && loadInfo->GetEnforceSecurity()) { nsresult rv = CheckChannel(aNewChannel); + if (NS_SUCCEEDED(rv)) { + rv = CheckFTPSubresourceLoad(aNewChannel); + } if (NS_FAILED(rv)) { aOldChannel->Cancel(rv); return rv; diff --git a/dom/security/nsContentSecurityManager.h b/dom/security/nsContentSecurityManager.h index bab847743..750dd8803 100644 --- a/dom/security/nsContentSecurityManager.h +++ b/dom/security/nsContentSecurityManager.h @@ -36,6 +36,7 @@ public: private: static nsresult CheckChannel(nsIChannel* aChannel); + static nsresult CheckFTPSubresourceLoad(nsIChannel* aChannel); virtual ~nsContentSecurityManager() {} diff --git a/dom/webidl/AddonEvent.webidl b/dom/webidl/AddonEvent.webidl deleted file mode 100644 index 235f81ec2..000000000 --- a/dom/webidl/AddonEvent.webidl +++ /dev/null @@ -1,12 +0,0 @@ -[ Func="mozilla::AddonManagerWebAPI::IsAPIEnabled", - Constructor(DOMString type, AddonEventInit eventInitDict)] -interface AddonEvent : Event { - readonly attribute DOMString id; - readonly attribute boolean needsRestart; -}; - -dictionary AddonEventInit : EventInit { - required DOMString id; - required boolean needsRestart; -}; - diff --git a/dom/webidl/AddonManager.webidl b/dom/webidl/AddonManager.webidl deleted file mode 100644 index 02c7953e6..000000000 --- a/dom/webidl/AddonManager.webidl +++ /dev/null @@ -1,91 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -/* We need a JSImplementation but cannot get one without a contract ID. - Since Addon and AddonInstall are only ever created from JS they don't need - real contract IDs. */ -[ChromeOnly, JSImplementation="dummy"] -interface Addon { - // The add-on's ID. - readonly attribute DOMString id; - // The add-on's version. - readonly attribute DOMString version; - // The add-on's type (extension, theme, etc.). - readonly attribute DOMString type; - // The add-on's name in the current locale. - readonly attribute DOMString name; - // The add-on's description in the current locale. - readonly attribute DOMString description; - // If the user has enabled this add-on, note that it still may not be running - // depending on whether enabling requires a restart or if the add-on is - // incompatible in some way. - readonly attribute boolean isEnabled; - // If the add-on is currently active in the browser. - readonly attribute boolean isActive; - // If the add-on may be uninstalled - readonly attribute boolean canUninstall; - - Promise<boolean> uninstall(); - Promise<void> setEnabled(boolean value); -}; - -[ChromeOnly, JSImplementation="dummy"] -interface AddonInstall : EventTarget { - // One of the STATE_* symbols from AddonManager.jsm - readonly attribute DOMString state; - // One of the ERROR_* symbols from AddonManager.jsm, or null - readonly attribute DOMString? error; - // How many bytes have been downloaded - readonly attribute long long progress; - // How many total bytes will need to be downloaded or -1 if unknown - readonly attribute long long maxProgress; - - Promise<void> install(); - Promise<void> cancel(); -}; - -dictionary addonInstallOptions { - required DOMString url; - // If a non-empty string is passed for "hash", it is used to verify the - // checksum of the downloaded XPI before installing. If is omitted or if - // it is null or empty string, no checksum verification is performed. - DOMString? hash = null; -}; - -[HeaderFile="mozilla/AddonManagerWebAPI.h", - Func="mozilla::AddonManagerWebAPI::IsAPIEnabled", - NavigatorProperty="mozAddonManager", - JSImplementation="@mozilla.org/addon-web-api/manager;1"] -interface AddonManager : EventTarget { - /** - * Gets information about an add-on - * - * @param id - * The ID of the add-on to test for. - * @return A promise. It will resolve to an Addon if the add-on is installed. - */ - Promise<Addon> getAddonByID(DOMString id); - - /** - * Creates an AddonInstall object for a given URL. - * - * @param options - * Only one supported option: 'url', the URL of the addon to install. - * @return A promise that resolves to an instance of AddonInstall. - */ - Promise<AddonInstall> createInstall(optional addonInstallOptions options); - - /* Hooks for managing event listeners */ - [ChromeOnly] - void eventListenerWasAdded(DOMString type); - [ChromeOnly] - void eventListenerWasRemoved(DOMString type); -}; - -[ChromeOnly,Exposed=System,HeaderFile="mozilla/AddonManagerWebAPI.h"] -interface AddonManagerPermissions { - static boolean isHostPermitted(DOMString host); -}; - diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 06fea2f20..aae7e479c 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -591,9 +591,6 @@ WEBIDL_FILES = [ 'XULElement.webidl', ] -if CONFIG['MOZ_WEBEXTENSIONS']: - WEBIDL_FILES += ['AddonManager.webidl'] - if CONFIG['MOZ_AUDIO_CHANNEL_MANAGER']: WEBIDL_FILES += [ 'AudioChannelManager.webidl', @@ -722,9 +719,6 @@ GENERATED_EVENTS_WEBIDL_FILES = [ 'WebGLContextEvent.webidl', ] -if CONFIG['MOZ_WEBEXTENSIONS']: - GENERATED_EVENTS_WEBIDL_FILES += ['AddonEvent.webidl'] - if CONFIG['MOZ_WEBRTC']: GENERATED_EVENTS_WEBIDL_FILES += [ 'RTCDataChannelEvent.webidl', diff --git a/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp b/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp index 726441757..c9bcc31ff 100644 --- a/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp +++ b/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp @@ -462,10 +462,6 @@ txCompileObserver::startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler, nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); if (httpChannel) { - httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"), - NS_LITERAL_CSTRING("*/*"), - false); - nsCOMPtr<nsIURI> referrerURI; aReferrerPrincipal->GetURI(getter_AddRefs(referrerURI)); if (referrerURI) { |