b=571287; let canvas participate in cycle collection; r=bz

This commit is contained in:
Vladimir Vukicevic 2010-06-15 14:38:05 -07:00
parent e377dc66c7
commit 58b27f08d0
6 changed files with 89 additions and 53 deletions

View File

@ -104,19 +104,15 @@ WebGLContext::Invalidate()
return;
mInvalidated = true;
mCanvasElement->InvalidateFrame();
HTMLCanvasElement()->InvalidateFrame();
}
/* readonly attribute nsIDOMHTMLCanvasElement canvas; */
NS_IMETHODIMP
WebGLContext::GetCanvas(nsIDOMHTMLCanvasElement **canvas)
{
if (mCanvasElement == nsnull) {
*canvas = nsnull;
return NS_OK;
}
NS_IF_ADDREF(*canvas = mCanvasElement);
NS_ADDREF(*canvas = static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement));
return NS_OK;
}
@ -127,14 +123,7 @@ WebGLContext::GetCanvas(nsIDOMHTMLCanvasElement **canvas)
NS_IMETHODIMP
WebGLContext::SetCanvasElement(nsHTMLCanvasElement* aParentCanvas)
{
if (aParentCanvas == nsnull) {
// we get this on shutdown; we should do some more cleanup here,
// but instead we just let our destructor do it.
mCanvasElement = nsnull;
return NS_OK;
}
if (!SafeToCreateCanvas3DContext(aParentCanvas))
if (aParentCanvas && !SafeToCreateCanvas3DContext(aParentCanvas))
return NS_ERROR_FAILURE;
mCanvasElement = aParentCanvas;
@ -354,12 +343,20 @@ WebGLContext::GetCanvasLayer(LayerManager *manager)
// XPCOM goop
//
NS_IMPL_ADDREF(WebGLContext)
NS_IMPL_RELEASE(WebGLContext)
NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(WebGLContext, nsICanvasRenderingContextWebGL)
NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(WebGLContext, nsICanvasRenderingContextWebGL)
NS_IMPL_CYCLE_COLLECTION_CLASS(WebGLContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebGLContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCanvasElement)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WebGLContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCanvasElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
DOMCI_DATA(CanvasRenderingContextWebGL, WebGLContext)
NS_INTERFACE_MAP_BEGIN(WebGLContext)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLContext)
NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextWebGL)
NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)

View File

@ -266,7 +266,10 @@ public:
WebGLContext();
virtual ~WebGLContext();
NS_DECL_ISUPPORTS
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(WebGLContext, nsICanvasRenderingContextWebGL)
NS_DECL_NSICANVASRENDERINGCONTEXTWEBGL
// nsICanvasRenderingContextInternal
@ -295,7 +298,10 @@ public:
// all context resources to be lost.
PRUint32 Generation() { return mGeneration; }
protected:
nsHTMLCanvasElement* mCanvasElement;
nsCOMPtr<nsIDOMHTMLCanvasElement> mCanvasElement;
nsHTMLCanvasElement *HTMLCanvasElement() {
return static_cast<nsHTMLCanvasElement*>(mCanvasElement.get());
}
nsRefPtr<gl::GLContext> gl;

View File

@ -2065,7 +2065,7 @@ WebGLContext::ReadPixels(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei he
if (NS_FAILED(js.error))
return js.error;
if (mCanvasElement->IsWriteOnly() && !nsContentUtils::IsCallerTrustedForRead()) {
if (HTMLCanvasElement()->IsWriteOnly() && !nsContentUtils::IsCallerTrustedForRead()) {
LogMessage("ReadPixels: Not allowed");
return NS_ERROR_DOM_SECURITY_ERR;
}
@ -2187,7 +2187,7 @@ WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
if (!res.mSurface)
return NS_ERROR_FAILURE;
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement, res.mPrincipal, res.mIsWriteOnly);
CanvasUtils::DoDrawImageSecurityCheck(HTMLCanvasElement(), res.mPrincipal, res.mIsWriteOnly);
if (res.mSurface->GetType() != gfxASurface::SurfaceTypeImage) {
// SurfaceFromElement lied!
@ -3035,7 +3035,7 @@ WebGLContext::GetImageData(PRUint32 x, PRUint32 y, PRUint32 w, PRUint32 h)
if (!mCanvasElement)
return NS_ERROR_FAILURE;
if (mCanvasElement->IsWriteOnly() && !IsCallerTrustedForRead()) {
if (HTMLCanvasElement()->IsWriteOnly() && !IsCallerTrustedForRead()) {
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
return NS_ERROR_DOM_SECURITY_ERR;
}

View File

@ -364,8 +364,10 @@ public:
already_AddRefed<CanvasLayer> GetCanvasLayer(LayerManager *manager);
void MarkContextClean();
// nsISupports interface
NS_DECL_ISUPPORTS
// nsISupports interface + CC
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsCanvasRenderingContext2D, nsIDOMCanvasRenderingContext2D)
// nsIDOMCanvasRenderingContext2D interface
NS_DECL_NSIDOMCANVASRENDERINGCONTEXT2D
@ -427,9 +429,11 @@ protected:
PRPackedBool mValid;
PRPackedBool mOpaque;
// the canvas element informs us when it's going away,
// so these are not nsCOMPtrs
nsHTMLCanvasElement* mCanvasElement;
// the canvas element we're a context of
nsCOMPtr<nsIDOMHTMLCanvasElement> mCanvasElement;
nsHTMLCanvasElement *HTMLCanvasElement() {
return static_cast<nsHTMLCanvasElement*>(mCanvasElement.get());
}
// If mCanvasElement is not provided, then a docshell is
nsCOMPtr<nsIDocShell> mDocShell;
@ -688,12 +692,20 @@ protected:
friend struct nsCanvasBidiProcessor;
};
NS_IMPL_ADDREF(nsCanvasRenderingContext2D)
NS_IMPL_RELEASE(nsCanvasRenderingContext2D)
NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsCanvasRenderingContext2D, nsIDOMCanvasRenderingContext2D)
NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsCanvasRenderingContext2D, nsIDOMCanvasRenderingContext2D)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsCanvasRenderingContext2D)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCanvasRenderingContext2D)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCanvasElement)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCanvasRenderingContext2D)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCanvasElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
DOMCI_DATA(CanvasRenderingContext2D, nsCanvasRenderingContext2D)
NS_INTERFACE_MAP_BEGIN(nsCanvasRenderingContext2D)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCanvasRenderingContext2D)
NS_INTERFACE_MAP_ENTRY(nsIDOMCanvasRenderingContext2D)
NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMCanvasRenderingContext2D)
@ -877,7 +889,7 @@ nsCanvasRenderingContext2D::ApplyStyle(Style aWhichStyle,
nsCanvasPattern* pattern = CurrentState().patternStyles[aWhichStyle];
if (pattern) {
if (mCanvasElement)
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
CanvasUtils::DoDrawImageSecurityCheck(HTMLCanvasElement(),
pattern->Principal(),
pattern->GetForceWriteOnly());
@ -908,15 +920,17 @@ nsCanvasRenderingContext2D::ApplyStyle(Style aWhichStyle,
nsresult
nsCanvasRenderingContext2D::Redraw()
{
if (!mCanvasElement)
if (!mCanvasElement) {
NS_ASSERTION(mDocShell, "Redraw with no canvas element or docshell!");
return NS_OK;
}
if (mIsEntireFrameInvalid)
return NS_OK;
mIsEntireFrameInvalid = PR_TRUE;
mCanvasElement->InvalidateFrame();
HTMLCanvasElement()->InvalidateFrame();
return NS_OK;
}
@ -924,8 +938,10 @@ nsCanvasRenderingContext2D::Redraw()
nsresult
nsCanvasRenderingContext2D::Redraw(const gfxRect& r)
{
if (!mCanvasElement)
if (!mCanvasElement) {
NS_ASSERTION(mDocShell, "Redraw with no canvas element or docshell!");
return NS_OK;
}
if (mIsEntireFrameInvalid)
return NS_OK;
@ -933,7 +949,7 @@ nsCanvasRenderingContext2D::Redraw(const gfxRect& r)
if (++mInvalidateCount > kCanvasMaxInvalidateCount)
return Redraw();
mCanvasElement->InvalidateFrame(&r);
HTMLCanvasElement()->InvalidateFrame(&r);
return NS_OK;
}
@ -1146,7 +1162,6 @@ nsCanvasRenderingContext2D::GetInputStream(const char *aMimeType,
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetCanvasElement(nsHTMLCanvasElement* aCanvasElement)
{
// don't hold a ref to this!
mCanvasElement = aCanvasElement;
return NS_OK;
@ -1155,12 +1170,8 @@ nsCanvasRenderingContext2D::SetCanvasElement(nsHTMLCanvasElement* aCanvasElement
NS_IMETHODIMP
nsCanvasRenderingContext2D::GetCanvas(nsIDOMHTMLCanvasElement **canvas)
{
if (mCanvasElement == nsnull) {
*canvas = nsnull;
return NS_OK;
}
NS_IF_ADDREF(*canvas = mCanvasElement);
NS_ADDREF(*canvas = static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement));
return NS_OK;
}
@ -2041,8 +2052,7 @@ nsCanvasRenderingContext2D::SetFont(const nsAString& font)
* string is equal to the old one.
*/
nsCOMPtr<nsIContent> content =
do_QueryInterface(static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement));
nsCOMPtr<nsIContent> content = do_QueryInterface(mCanvasElement);
if (!content && !mDocShell) {
NS_WARNING("Canvas element must be an nsIContent and non-null or a docshell must be provided");
return NS_ERROR_FAILURE;
@ -2395,8 +2405,7 @@ nsCanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
if (aMaxWidth < 0)
return NS_ERROR_INVALID_ARG;
nsCOMPtr<nsIContent> content =
do_QueryInterface(static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement));
nsCOMPtr<nsIContent> content = do_QueryInterface(mCanvasElement);
if (!content && !mDocShell) {
NS_WARNING("Canvas element must be an nsIContent and non-null or a docshell must be provided");
return NS_ERROR_FAILURE;
@ -3116,7 +3125,7 @@ nsCanvasRenderingContext2D::DrawImage(nsIDOMElement *imgElt, float a1,
PRBool forceWriteOnly = res.mIsWriteOnly;
if (mCanvasElement)
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement, principal, forceWriteOnly);
CanvasUtils::DoDrawImageSecurityCheck(HTMLCanvasElement(), principal, forceWriteOnly);
gfxContextPathAutoSaveRestore pathSR(mThebes, PR_FALSE);
@ -3503,7 +3512,17 @@ nsCanvasRenderingContext2D::GetImageData_explicit(PRInt32 x, PRInt32 y, PRUint32
if (!mValid)
return NS_ERROR_FAILURE;
if (mCanvasElement && mCanvasElement->IsWriteOnly() && !nsContentUtils::IsCallerTrustedForRead()) {
if (!mCanvasElement && !mDocShell) {
NS_ERROR("No canvas element and no docshell in GetImageData!!!");
return NS_ERROR_DOM_SECURITY_ERR;
}
// Check only if we have a canvas element; if we were created with a docshell,
// then it's special internal use.
if (mCanvasElement &&
HTMLCanvasElement()->IsWriteOnly() &&
!nsContentUtils::IsCallerTrustedForRead())
{
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
return NS_ERROR_DOM_SECURITY_ERR;
}

View File

@ -83,6 +83,10 @@ public:
// nsIDOMHTMLCanvasElement
NS_DECL_NSIDOMHTMLCANVASELEMENT
// CC
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLCanvasElement,
nsGenericHTMLElement)
/**
* Ask the canvas Element to return the primary frame, if any
*/

View File

@ -68,19 +68,20 @@ nsHTMLCanvasElement::nsHTMLCanvasElement(nsINodeInfo *aNodeInfo)
nsHTMLCanvasElement::~nsHTMLCanvasElement()
{
if (mCurrentContext) {
nsCOMPtr<nsICanvasRenderingContextInternal> internalctx(do_QueryInterface(mCurrentContext));
internalctx->SetCanvasElement(nsnull);
mCurrentContext = nsnull;
}
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLCanvasElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLCanvasElement,
nsGenericHTMLElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCurrentContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_ADDREF_INHERITED(nsHTMLCanvasElement, nsGenericElement)
NS_IMPL_RELEASE_INHERITED(nsHTMLCanvasElement, nsGenericElement)
DOMCI_DATA(HTMLCanvasElement, nsHTMLCanvasElement)
NS_INTERFACE_TABLE_HEAD(nsHTMLCanvasElement)
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLCanvasElement)
NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLCanvasElement,
nsIDOMHTMLCanvasElement,
nsICanvasElementExternal)
@ -323,6 +324,15 @@ nsHTMLCanvasElement::GetContext(const nsAString& aContextId,
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
return NS_ERROR_INVALID_ARG;
// Ensure that the context participates in CC. Note that returning a
// CC participant from QI doesn't addref.
nsXPCOMCycleCollectionParticipant *cp = nsnull;
CallQueryInterface(mCurrentContext, &cp);
if (!cp) {
mCurrentContext = nsnull;
return NS_ERROR_FAILURE;
}
rv = mCurrentContext->SetCanvasElement(this);
if (NS_FAILED(rv)) {
mCurrentContext = nsnull;