mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-26 23:23:33 +00:00
Bug 685518 part 1. Look at the image CORS mode for drawImage into a canvas 2d context. r=roc
This commit is contained in:
parent
cdbf62540d
commit
fde72dbe8b
@ -65,7 +65,8 @@ namespace CanvasUtils {
|
||||
void
|
||||
DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
|
||||
nsIPrincipal *aPrincipal,
|
||||
PRBool forceWriteOnly)
|
||||
PRBool forceWriteOnly,
|
||||
PRBool CORSUsed)
|
||||
{
|
||||
// Callers should ensure that mCanvasElement is non-null before calling this
|
||||
if (!aCanvasElement) {
|
||||
@ -85,6 +86,10 @@ DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
|
||||
if (aPrincipal == nsnull)
|
||||
return;
|
||||
|
||||
// No need to do a security check if the image used CORS for the load
|
||||
if (CORSUsed)
|
||||
return;
|
||||
|
||||
PRBool subsumes;
|
||||
nsresult rv =
|
||||
aCanvasElement->NodePrincipal()->Subsumes(aPrincipal, &subsumes);
|
||||
|
@ -74,7 +74,8 @@ inline PRBool CheckSaneSubrectSize(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h,
|
||||
|
||||
void DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
|
||||
nsIPrincipal *aPrincipal,
|
||||
PRBool forceWriteOnly);
|
||||
PRBool forceWriteOnly,
|
||||
PRBool CORSUsed);
|
||||
|
||||
void LogMessage (const nsCString& errorString);
|
||||
void LogMessagef (const char *fmt, ...);
|
||||
|
@ -3584,19 +3584,13 @@ WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
|
||||
// validated for cross-domain use.
|
||||
// if res.mPrincipal == null, no need for the origin check. See DoDrawImageSecurityCheck.
|
||||
// this case happens in the mochitest for images served from mochi.test:8888
|
||||
if (res.mPrincipal) {
|
||||
if (res.mPrincipal && !res.mCORSUsed) {
|
||||
PRBool subsumes;
|
||||
nsresult rv = HTMLCanvasElement()->NodePrincipal()->Subsumes(res.mPrincipal, &subsumes);
|
||||
if (NS_FAILED(rv) || !subsumes) {
|
||||
PRInt32 corsmode;
|
||||
if (!res.mImageRequest || NS_FAILED(res.mImageRequest->GetCORSMode(&corsmode))) {
|
||||
corsmode = imgIRequest::CORS_NONE;
|
||||
}
|
||||
if (corsmode == imgIRequest::CORS_NONE) {
|
||||
LogMessageIfVerbose("It is forbidden to load a WebGL texture from a cross-domain element that has not been validated with CORS. "
|
||||
"See https://developer.mozilla.org/en/WebGL/Cross-Domain_Textures");
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
LogMessageIfVerbose("It is forbidden to load a WebGL texture from a cross-domain element that has not been validated with CORS. "
|
||||
"See https://developer.mozilla.org/en/WebGL/Cross-Domain_Textures");
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,26 +246,30 @@ public:
|
||||
|
||||
nsCanvasPattern(gfxPattern* pat,
|
||||
nsIPrincipal* principalForSecurityCheck,
|
||||
PRBool forceWriteOnly)
|
||||
PRBool forceWriteOnly,
|
||||
PRBool CORSUsed)
|
||||
: mPattern(pat),
|
||||
mPrincipal(principalForSecurityCheck),
|
||||
mForceWriteOnly(forceWriteOnly)
|
||||
mForceWriteOnly(forceWriteOnly),
|
||||
mCORSUsed(CORSUsed)
|
||||
{
|
||||
}
|
||||
|
||||
gfxPattern* GetPattern() {
|
||||
gfxPattern* GetPattern() const {
|
||||
return mPattern;
|
||||
}
|
||||
|
||||
nsIPrincipal* Principal() { return mPrincipal; }
|
||||
PRBool GetForceWriteOnly() { return mForceWriteOnly; }
|
||||
nsIPrincipal* Principal() const { return mPrincipal; }
|
||||
PRBool GetForceWriteOnly() const { return mForceWriteOnly; }
|
||||
PRBool GetCORSUsed() const { return mCORSUsed; }
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
protected:
|
||||
nsRefPtr<gfxPattern> mPattern;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
PRPackedBool mForceWriteOnly;
|
||||
const PRPackedBool mForceWriteOnly;
|
||||
const PRPackedBool mCORSUsed;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsCanvasPattern, NS_CANVASPATTERN_PRIVATE_IID)
|
||||
@ -994,7 +998,8 @@ nsCanvasRenderingContext2D::ApplyStyle(Style aWhichStyle,
|
||||
if (mCanvasElement)
|
||||
CanvasUtils::DoDrawImageSecurityCheck(HTMLCanvasElement(),
|
||||
pattern->Principal(),
|
||||
pattern->GetForceWriteOnly());
|
||||
pattern->GetForceWriteOnly(),
|
||||
pattern->GetCORSUsed());
|
||||
|
||||
gfxPattern* gpat = pattern->GetPattern();
|
||||
|
||||
@ -1842,7 +1847,8 @@ nsCanvasRenderingContext2D::CreatePattern(nsIDOMHTMLElement *image,
|
||||
thebespat->SetExtend(extend);
|
||||
|
||||
nsRefPtr<nsCanvasPattern> pat = new nsCanvasPattern(thebespat, res.mPrincipal,
|
||||
res.mIsWriteOnly);
|
||||
res.mIsWriteOnly,
|
||||
res.mCORSUsed);
|
||||
if (!pat)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
@ -3438,7 +3444,9 @@ nsCanvasRenderingContext2D::DrawImage(nsIDOMElement *imgElt, float a1,
|
||||
|
||||
if (mCanvasElement) {
|
||||
CanvasUtils::DoDrawImageSecurityCheck(HTMLCanvasElement(),
|
||||
res.mPrincipal, res.mIsWriteOnly);
|
||||
res.mPrincipal,
|
||||
res.mIsWriteOnly,
|
||||
res.mCORSUsed);
|
||||
}
|
||||
|
||||
if (res.mImageRequest) {
|
||||
|
@ -306,20 +306,23 @@ public:
|
||||
nsCanvasPatternAzure(SourceSurface* aSurface,
|
||||
RepeatMode aRepeat,
|
||||
nsIPrincipal* principalForSecurityCheck,
|
||||
PRBool forceWriteOnly)
|
||||
PRBool forceWriteOnly,
|
||||
PRBool CORSUsed)
|
||||
: mSurface(aSurface)
|
||||
, mRepeat(aRepeat)
|
||||
, mPrincipal(principalForSecurityCheck)
|
||||
, mForceWriteOnly(forceWriteOnly)
|
||||
, mCORSUsed(CORSUsed)
|
||||
{
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
RefPtr<SourceSurface> mSurface;
|
||||
RepeatMode mRepeat;
|
||||
const RepeatMode mRepeat;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
PRPackedBool mForceWriteOnly;
|
||||
const PRPackedBool mForceWriteOnly;
|
||||
const PRPackedBool mCORSUsed;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsCanvasPatternAzure, NS_CANVASPATTERNAZURE_PRIVATE_IID)
|
||||
@ -798,7 +801,8 @@ protected:
|
||||
if (aCtx->mCanvasElement) {
|
||||
CanvasUtils::DoDrawImageSecurityCheck(aCtx->HTMLCanvasElement(),
|
||||
state.patternStyles[aStyle]->mPrincipal,
|
||||
state.patternStyles[aStyle]->mForceWriteOnly);
|
||||
state.patternStyles[aStyle]->mForceWriteOnly,
|
||||
state.patternStyles[aStyle]->mCORSUsed);
|
||||
}
|
||||
|
||||
ExtendMode mode;
|
||||
@ -1912,8 +1916,7 @@ nsCanvasRenderingContext2DAzure::CreatePattern(nsIDOMHTMLElement *image,
|
||||
}
|
||||
|
||||
// Special case for Canvas, which could be an Azure canvas!
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(image);
|
||||
if (canvas && node) {
|
||||
if (canvas) {
|
||||
if (canvas->CountContexts() == 1) {
|
||||
nsICanvasRenderingContextInternal *srcCanvas = canvas->GetContextAtIndex(0);
|
||||
|
||||
@ -1922,7 +1925,7 @@ nsCanvasRenderingContext2DAzure::CreatePattern(nsIDOMHTMLElement *image,
|
||||
RefPtr<SourceSurface> srcSurf = srcCanvas->GetSurfaceSnapshot();
|
||||
|
||||
nsRefPtr<nsCanvasPatternAzure> pat =
|
||||
new nsCanvasPatternAzure(srcSurf, repeatMode, node->NodePrincipal(), canvas->IsWriteOnly());
|
||||
new nsCanvasPatternAzure(srcSurf, repeatMode, content->NodePrincipal(), canvas->IsWriteOnly(), PR_FALSE);
|
||||
|
||||
*_retval = pat.forget().get();
|
||||
return NS_OK;
|
||||
@ -1949,7 +1952,8 @@ nsCanvasRenderingContext2DAzure::CreatePattern(nsIDOMHTMLElement *image,
|
||||
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mTarget, res.mSurface);
|
||||
|
||||
nsRefPtr<nsCanvasPatternAzure> pat =
|
||||
new nsCanvasPatternAzure(srcSurf, repeatMode, res.mPrincipal, res.mIsWriteOnly);
|
||||
new nsCanvasPatternAzure(srcSurf, repeatMode, res.mPrincipal,
|
||||
res.mIsWriteOnly, res.mCORSUsed);
|
||||
|
||||
*_retval = pat.forget().get();
|
||||
return NS_OK;
|
||||
@ -3700,7 +3704,8 @@ nsCanvasRenderingContext2DAzure::DrawImage(nsIDOMElement *imgElt, float a1,
|
||||
|
||||
if (mCanvasElement) {
|
||||
CanvasUtils::DoDrawImageSecurityCheck(HTMLCanvasElement(),
|
||||
res.mPrincipal, res.mIsWriteOnly);
|
||||
res.mPrincipal, res.mIsWriteOnly,
|
||||
res.mCORSUsed);
|
||||
}
|
||||
|
||||
if (res.mImageRequest) {
|
||||
|
@ -4118,6 +4118,11 @@ nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement,
|
||||
ctx->Paint();
|
||||
}
|
||||
|
||||
PRInt32 corsmode;
|
||||
if (NS_SUCCEEDED(imgRequest->GetCORSMode(&corsmode))) {
|
||||
result.mCORSUsed = (corsmode != imgIRequest::CORS_NONE);
|
||||
}
|
||||
|
||||
result.mSurface = gfxsurf;
|
||||
result.mSize = gfxIntSize(imgWidth, imgHeight);
|
||||
result.mPrincipal = principal.forget();
|
||||
|
@ -1349,7 +1349,9 @@ public:
|
||||
};
|
||||
|
||||
struct SurfaceFromElementResult {
|
||||
SurfaceFromElementResult() : mIsWriteOnly(PR_TRUE), mIsStillLoading(PR_FALSE) {}
|
||||
SurfaceFromElementResult() :
|
||||
// Use safe default values here
|
||||
mIsWriteOnly(PR_TRUE), mIsStillLoading(PR_FALSE), mCORSUsed(PR_FALSE) {}
|
||||
|
||||
/* mSurface will contain the resulting surface, or will be NULL on error */
|
||||
nsRefPtr<gfxASurface> mSurface;
|
||||
@ -1364,6 +1366,8 @@ public:
|
||||
/* Whether the element was still loading. Some consumers need to handle
|
||||
this case specially. */
|
||||
PRPackedBool mIsStillLoading;
|
||||
/* Whether the element used CORS when loading. */
|
||||
PRPackedBool mCORSUsed;
|
||||
};
|
||||
|
||||
static SurfaceFromElementResult SurfaceFromElement(nsIDOMElement *aElement,
|
||||
|
Loading…
x
Reference in New Issue
Block a user