diff options
25 files changed, 233 insertions, 132 deletions
diff --git a/application/basilisk/components/preferences/connection.xul b/application/basilisk/components/preferences/connection.xul index a3f0d082a..1eb0c1544 100644 --- a/application/basilisk/components/preferences/connection.xul +++ b/application/basilisk/components/preferences/connection.xul @@ -145,9 +145,6 @@ </radiogroup> </box> </row> - <label value="&noproxy.label;" accesskey="&noproxy.accesskey;" control="networkProxyNone"/> - <textbox id="networkProxyNone" preference="network.proxy.no_proxies_on" multiline="true" rows="2"/> - <label value="&noproxyExplain.label;" control="networkProxyNone"/> </rows> </grid> <radio value="2" label="&autoTypeRadio.label;" accesskey="&autoTypeRadio.accesskey;"/> @@ -162,6 +159,9 @@ </radiogroup> </groupbox> <separator class="thin"/> + <label value="&noproxy.label;" accesskey="&noproxy.accesskey;" control="networkProxyNone"/> + <textbox id="networkProxyNone" preference="network.proxy.no_proxies_on" multiline="true" rows="2"/> + <label value="&noproxyExplain.label;" control="networkProxyNone"/> <checkbox id="autologinProxy" label="&autologinproxy.label;" accesskey="&autologinproxy.accesskey;" diff --git a/application/palemoon/app/profile/palemoon.js b/application/palemoon/app/profile/palemoon.js index f2b9030b6..3c550ab8b 100644 --- a/application/palemoon/app/profile/palemoon.js +++ b/application/palemoon/app/profile/palemoon.js @@ -46,7 +46,7 @@ pref("extensions.getAddons.cache.enabled", false); pref("extensions.getAddons.maxResults", 10); pref("extensions.getAddons.get.url", "https://@APO_AM_URL@/internal/get?addonguid=%IDS%&os=%OS%&version=%VERSION%"); pref("extensions.getAddons.getWithPerformance.url", "https://@APO_AM_URL@/internal/get?addonguid=%IDS%&os=%OS%&version=%VERSION%"); -pref("extensions.getAddons.search.browseURL", "https://@APO_AM_URL@/external/recommended"); +pref("extensions.getAddons.search.browseURL", "https://@APO_AM_URL@/search/?terms=%TERMS%"); pref("extensions.getAddons.search.url", "https://@APO_AM_URL@/internal/search?q=%TERMS%&locale=%LOCALE%&os=%OS%&version=%VERSION%"); pref("extensions.webservice.discoverURL", "http://@APO_AM_URL@/internal/discover/"); pref("extensions.getAddons.recommended.url", "https://@APO_AM_URL@/internal/recommended?locale=%LOCALE%&os=%OS%"); diff --git a/application/palemoon/components/preferences/connection.xul b/application/palemoon/components/preferences/connection.xul index 491bf4878..e6079dd54 100644 --- a/application/palemoon/components/preferences/connection.xul +++ b/application/palemoon/components/preferences/connection.xul @@ -138,9 +138,6 @@ <radio id="networkProxySOCKSVersion5" value="5" label="&socks5.label;" accesskey="&socks5.accesskey;"/> </radiogroup> </row> - <label value="&noproxy.label;" accesskey="&noproxy.accesskey;" control="networkProxyNone"/> - <textbox id="networkProxyNone" preference="network.proxy.no_proxies_on" multiline="true" rows="2"/> - <label value="&noproxyExplain.label;" control="networkProxyNone"/> </rows> </grid> <radio value="2" label="&autoTypeRadio.label;" accesskey="&autoTypeRadio.accesskey;"/> @@ -154,6 +151,9 @@ </hbox> </radiogroup> <separator class="thin"/> + <label value="&noproxy.label;" accesskey="&noproxy.accesskey;" control="networkProxyNone"/> + <textbox id="networkProxyNone" preference="network.proxy.no_proxies_on" multiline="true" rows="2"/> + <label value="&noproxyExplain.label;" control="networkProxyNone"/> <checkbox id="autologinProxy" preference="signon.autologin.proxy" label="&autologinproxy.label;" accesskey="&autologinproxy.accesskey;" tooltiptext="&autologinproxy.tooltip;"/> diff --git a/application/palemoon/locales/en-US/chrome/browser/browser.properties b/application/palemoon/locales/en-US/chrome/browser/browser.properties index 0144af0c7..4c45e2513 100644 --- a/application/palemoon/locales/en-US/chrome/browser/browser.properties +++ b/application/palemoon/locales/en-US/chrome/browser/browser.properties @@ -201,20 +201,20 @@ update.openUpdateUI.upgradeButton.accesskey=U update.restart.upgradeButton.label=Upgrade Now update.restart.upgradeButton.accesskey=U -# Check for Updates in the Help Menu
-# LOCALIZATION NOTE (updatesItem_*): these are alternative labels for Check for Update item in Help menu.
-# Which one is used depends on Update process state.
-updatesItem_default=Check for Updates…
-updatesItem_defaultFallback=Check for Updates…
-updatesItem_default.accesskey=C
-updatesItem_downloading=Downloading %S…
-updatesItem_downloadingFallback=Downloading Update…
-updatesItem_downloading.accesskey=D
-updatesItem_resume=Resume Downloading %S…
-updatesItem_resumeFallback=Resume Downloading Update…
-updatesItem_resume.accesskey=D
-updatesItem_pending=Apply Downloaded Update Now…
-updatesItem_pendingFallback=Apply Downloaded Update Now…
+# Check for Updates in the Help Menu +# LOCALIZATION NOTE (updatesItem_*): these are alternative labels for Check for Update item in Help menu. +# Which one is used depends on Update process state. +updatesItem_default=Check for Updates… +updatesItem_defaultFallback=Check for Updates… +updatesItem_default.accesskey=C +updatesItem_downloading=Downloading %S… +updatesItem_downloadingFallback=Downloading Update… +updatesItem_downloading.accesskey=D +updatesItem_resume=Resume Downloading %S… +updatesItem_resumeFallback=Resume Downloading Update… +updatesItem_resume.accesskey=D +updatesItem_pending=Apply Downloaded Update Now… +updatesItem_pendingFallback=Apply Downloaded Update Now… updatesItem_pending.accesskey=D # RSS Pretty Print diff --git a/config/milestone.txt b/config/milestone.txt index 776b58af7..219f85529 100644 --- a/config/milestone.txt +++ b/config/milestone.txt @@ -10,4 +10,4 @@ # hardcoded milestones in the tree from these two files. #-------------------------------------------------------- -4.1.8 +4.1.9 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/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/gfx/skia/skia/include/core/SkPath.h b/gfx/skia/skia/include/core/SkPath.h index d1af4f31b..bde07c498 100644 --- a/gfx/skia/skia/include/core/SkPath.h +++ b/gfx/skia/skia/include/core/SkPath.h @@ -373,7 +373,7 @@ public: @param extraPtCount The number of extra points the path should preallocate for. */ - void incReserve(unsigned extraPtCount); + void incReserve(int extraPtCount); /** Set the beginning of the next contour to the point (x,y). diff --git a/gfx/skia/skia/include/core/SkPathRef.h b/gfx/skia/skia/include/core/SkPathRef.h index 0c5cc1aed..d497e7e08 100644 --- a/gfx/skia/skia/include/core/SkPathRef.h +++ b/gfx/skia/skia/include/core/SkPathRef.h @@ -547,6 +547,8 @@ private: friend class PathRefTest_Private; friend class ForceIsRRect_Private; // unit test isRRect + friend class SkPath; + friend class SkPathPriv; }; #endif diff --git a/gfx/skia/skia/src/core/SkPath.cpp b/gfx/skia/skia/src/core/SkPath.cpp index 8f93c9c18..db160d9b7 100644 --- a/gfx/skia/skia/src/core/SkPath.cpp +++ b/gfx/skia/skia/src/core/SkPath.cpp @@ -716,9 +716,11 @@ void SkPath::setConvexity(Convexity c) { fFirstDirection = SkPathPriv::kUnknown_FirstDirection; \ } while (0) -void SkPath::incReserve(U16CPU inc) { +void SkPath::incReserve(int inc) { SkDEBUGCODE(this->validate();) - SkPathRef::Editor(&fPathRef, inc, inc); + if (inc > 0) { + SkPathRef::Editor(&fPathRef, inc, inc); + } SkDEBUGCODE(this->validate();) } @@ -1691,6 +1693,13 @@ static void subdivide_cubic_to(SkPath* path, const SkPoint pts[4], } void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const { + if (matrix.isIdentity()) { + if (dst != nullptr && dst != this) { + *dst = *this; + } + return; + } + SkDEBUGCODE(this->validate();) if (dst == nullptr) { dst = (SkPath*)this; @@ -1738,13 +1747,20 @@ void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const { matrix.mapPoints(ed.points(), ed.pathRef()->countPoints()); dst->fFirstDirection = SkPathPriv::kUnknown_FirstDirection; } else { + Convexity convexity = Convexity(fConvexity); + SkPathRef::CreateTransformedCopy(&dst->fPathRef, *fPathRef.get(), matrix); if (this != dst) { dst->fFillType = fFillType; - dst->fConvexity = fConvexity; dst->fIsVolatile = fIsVolatile; } + + if (matrix.isScaleTranslate() && SkPathPriv::IsAxisAligned(*this)) { + dst->fConvexity = convexity; + } else { + dst->fConvexity = kUnknown_Convexity; + } if (SkPathPriv::kUnknown_FirstDirection == fFirstDirection) { dst->fFirstDirection = SkPathPriv::kUnknown_FirstDirection; @@ -1758,7 +1774,6 @@ void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const { } else if (det2x2 > 0) { dst->fFirstDirection = fFirstDirection.load(); } else { - dst->fConvexity = kUnknown_Convexity; dst->fFirstDirection = SkPathPriv::kUnknown_FirstDirection; } } diff --git a/gfx/skia/skia/src/core/SkPathPriv.h b/gfx/skia/skia/src/core/SkPathPriv.h index 029cb759d..cfcdc4cac 100644 --- a/gfx/skia/skia/src/core/SkPathPriv.h +++ b/gfx/skia/skia/src/core/SkPathPriv.h @@ -121,6 +121,11 @@ public: static const SkScalar* ConicWeightData(const SkPath& path) { return path.fPathRef->conicWeights(); } + + static bool IsAxisAligned(const SkPath& path) { + SkRect tmp; + return (path.fPathRef->fIsRRect | path.fPathRef->fIsOval) || path.isRect(&tmp); + } }; #endif diff --git a/gfx/skia/skia/src/core/SkScan_Path.cpp b/gfx/skia/skia/src/core/SkScan_Path.cpp index d15d2d54b..5e00e3abe 100644 --- a/gfx/skia/skia/src/core/SkScan_Path.cpp +++ b/gfx/skia/skia/src/core/SkScan_Path.cpp @@ -241,9 +241,17 @@ static bool update_edge(SkEdge* edge, int last_y) { return false; } -static void walk_convex_edges(SkEdge* prevHead, SkPath::FillType, - SkBlitter* blitter, int start_y, int stop_y, - PrePostProc proc) { +// Unexpected conditions for which we need to return
+#define ASSERT_RETURN(cond) \
+ do { \
+ if (!(cond)) { \
+ SkASSERT(false); \
+ return; \
+ } \
+ } while (0)
+
+// Needs Y to only change once (looser than convex in X)
+static void walk_simple_edges(SkEdge* prevHead, SkBlitter* blitter, int start_y, int stop_y) { validate_sort(prevHead->fNext); SkEdge* leftE = prevHead->fNext; @@ -258,30 +266,28 @@ static void walk_convex_edges(SkEdge* prevHead, SkPath::FillType, // not lining up, so we take the max. int local_top = SkMax32(leftE->fFirstY, riteE->fFirstY); #endif - SkASSERT(local_top >= start_y); + ASSERT_RETURN(local_top >= start_y); - for (;;) { + while (local_top < stop_y) { SkASSERT(leftE->fFirstY <= stop_y); SkASSERT(riteE->fFirstY <= stop_y); - if (leftE->fX > riteE->fX || (leftE->fX == riteE->fX && - leftE->fDX > riteE->fDX)) { - SkTSwap(leftE, riteE); - } - int local_bot = SkMin32(leftE->fLastY, riteE->fLastY); local_bot = SkMin32(local_bot, stop_y - 1); - SkASSERT(local_top <= local_bot); + ASSERT_RETURN(local_top <= local_bot); SkFixed left = leftE->fX; SkFixed dLeft = leftE->fDX; SkFixed rite = riteE->fX; SkFixed dRite = riteE->fDX; int count = local_bot - local_top; - SkASSERT(count >= 0); + ASSERT_RETURN(count >= 0); if (0 == (dLeft | dRite)) { int L = SkFixedRoundToInt(left); int R = SkFixedRoundToInt(rite); + if (L > R) { + SkTSwap(L, R); + } if (L < R) { count += 1; blitter->blitRect(L, local_top, R - L, count); @@ -291,6 +297,9 @@ static void walk_convex_edges(SkEdge* prevHead, SkPath::FillType, do { int L = SkFixedRoundToInt(left); int R = SkFixedRoundToInt(rite); + if (L > R) { + SkTSwap(L, R); + } if (L < R) { blitter->blitH(L, local_top, R - L); } @@ -303,28 +312,21 @@ static void walk_convex_edges(SkEdge* prevHead, SkPath::FillType, leftE->fX = left; riteE->fX = rite; - if (update_edge(leftE, local_bot)) { + if (!update_edge(leftE, local_bot)) { if (currE->fFirstY >= stop_y) { - break; + return; // we're done } leftE = currE; currE = currE->fNext; + ASSERT_RETURN(leftE->fFirstY == local_top); } - if (update_edge(riteE, local_bot)) { + if (!update_edge(riteE, local_bot)) { if (currE->fFirstY >= stop_y) { - break; + return; // we're done } riteE = currE; currE = currE->fNext; - } - - SkASSERT(leftE); - SkASSERT(riteE); - - // check our bottom clip - SkASSERT(local_top == local_bot + 1); - if (local_top >= stop_y) { - break; + ASSERT_RETURN(riteE->fFirstY == local_top); } } } @@ -500,9 +502,9 @@ void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitte proc = PrePostInverseBlitterProc; } - if (path.isConvex() && (nullptr == proc)) { - SkASSERT(count >= 2); // convex walker does not handle missing right edges - walk_convex_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, nullptr); + // count >= 2 is required as the convex walker does not handle missing right edges + if (path.isConvex() && (nullptr == proc) && count >= 2) { + walk_simple_edges(&headEdge, blitter, start_y, stop_y); } else { int rightEdge; if (clipRect) { @@ -766,8 +768,7 @@ static void sk_fill_triangle(const SkPoint pts[], const SkIRect* clipRect, if (clipRect && start_y < clipRect->fTop) { start_y = clipRect->fTop; } - walk_convex_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, start_y, stop_y, nullptr); -// walk_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, start_y, stop_y, nullptr); + walk_simple_edges(&headEdge, blitter, start_y, stop_y); } void SkScan::FillTriangle(const SkPoint pts[], const SkRasterClip& clip, diff --git a/js/src/old-configure.in b/js/src/old-configure.in index 8abea5956..45108ee59 100644 --- a/js/src/old-configure.in +++ b/js/src/old-configure.in @@ -206,10 +206,6 @@ case "$target" in # -Zc:sizedDealloc- disables C++14 global sized deallocation (see bug 1160146) CXXFLAGS="$CXXFLAGS -Zc:sizedDealloc-" - - # Disable C++11 thread-safe statics due to crashes on XP (bug 1204752) - # See https://connect.microsoft.com/VisualStudio/feedback/details/1789709/visual-c-2015-runtime-broken-on-windows-server-2003-c-11-magic-statics - CXXFLAGS="$CXXFLAGS -Zc:threadSafeInit-" ;; esac AC_SUBST(MSVS_VERSION) diff --git a/mobile/android/app/mobile.js b/mobile/android/app/mobile.js index ef4764d88..a28cba48e 100644 --- a/mobile/android/app/mobile.js +++ b/mobile/android/app/mobile.js @@ -780,9 +780,9 @@ pref("dom.phonenumber.substringmatching.BR", 8); pref("dom.phonenumber.substringmatching.CO", 10); pref("dom.phonenumber.substringmatching.VE", 7); -// Enable hardware-accelerated Skia canvas +// Support, but deprecate, hardware-accelerated Skia canvas pref("gfx.canvas.azure.backends", "skia"); -pref("gfx.canvas.azure.accelerated", true); +pref("gfx.canvas.azure.accelerated", false); // See ua-update.json.in for the packaged UA override list pref("general.useragent.updates.enabled", true); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index f6e90170e..9bdd00c80 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -795,8 +795,6 @@ pref("gfx.content.azure.backends", "direct2d1.1,cairo"); #ifdef XP_MACOSX pref("gfx.content.azure.backends", "cg"); pref("gfx.canvas.azure.backends", "skia,cg"); -// Accelerated cg canvas where available (10.7+) -pref("gfx.canvas.azure.accelerated", true); #else // Linux etc. pref("gfx.canvas.azure.backends", "skia,cairo"); diff --git a/old-configure.in b/old-configure.in index eba476bd0..58a1bc7fa 100644 --- a/old-configure.in +++ b/old-configure.in @@ -215,11 +215,12 @@ case "$target" in # -Zc:sizedDealloc- disables C++14 global sized deallocation (see bug 1160146) CXXFLAGS="$CXXFLAGS -Zc:sizedDealloc-" - - # Disable C++11 thread-safe statics due to crashes on XP (bug 1204752) - # See https://connect.microsoft.com/VisualStudio/feedback/details/1789709/visual-c-2015-runtime-broken-on-windows-server-2003-c-11-magic-statics - CXXFLAGS="$CXXFLAGS -Zc:threadSafeInit-" - + + # C4752: We explicitly use AVX instructions in only some libs, not global + # This is a pointless "helpful warning" to use /arch:AVX which we don't want. + CFLAGS="$CFLAGS -wd4752" + CXXFLAGS="$CXXFLAGS -wd4752" + # https://connect.microsoft.com/VisualStudio/feedback/details/888527/warnings-on-dbghelp-h # for dbghelp.h, imagehlp.h, and shobj.h # C4091: 'typedef ': ignored on left of '' when no variable is declared diff --git a/widget/windows/nsDataObj.cpp b/widget/windows/nsDataObj.cpp index ee2db7b65..a19dcb182 100644 --- a/widget/windows/nsDataObj.cpp +++ b/widget/windows/nsDataObj.cpp @@ -921,7 +921,7 @@ nsDataObj::GetDib(const nsACString& inFlavor, if ( image ) { nsCOMPtr<imgITools> imgTools = do_CreateInstance("@mozilla.org/image/tools;1"); - nsAutoString options; + nsAutoString options(NS_LITERAL_STRING("bpp=32;")); if (aFormat.cfFormat == CF_DIBV5) { options.AppendLiteral("version=5"); } else { @@ -1580,7 +1580,7 @@ HRESULT nsDataObj::DropImage(FORMATETC& aFE, STGMEDIUM& aSTG) nsCOMPtr<imgITools> imgTools = do_CreateInstance("@mozilla.org/image/tools;1"); nsCOMPtr<nsIInputStream> inputStream; rv = imgTools->EncodeImage(image, NS_LITERAL_CSTRING(IMAGE_BMP), - NS_LITERAL_STRING("version=3"), + NS_LITERAL_STRING("bpp=32;version=3"), getter_AddRefs(inputStream)); if (NS_FAILED(rv) || !inputStream) { return E_FAIL; |