fixing bug 75185 r=brendan sr=attinasi

This commit is contained in:
pavlov%netscape.com 2001-04-15 02:13:49 +00:00
parent 2fa656fb4b
commit 4f028f9c98
4 changed files with 418 additions and 154 deletions

View File

@ -69,6 +69,8 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsIDOMNode.h" #include "nsIDOMNode.h"
#include "nsContentPolicyUtils.h"
#ifdef DEBUG #ifdef DEBUG
#undef NOISY_IMAGE_LOADING #undef NOISY_IMAGE_LOADING
@ -189,13 +191,19 @@ nsImageFrame::Destroy(nsIPresContext* aPresContext)
} }
#ifdef USE_IMG2 #ifdef USE_IMG2
if (mImageRequest) if (mImageRequest)
mImageRequest->Cancel(NS_ERROR_FAILURE); // NS_BINDING_ABORT ? mImageRequest->Cancel(NS_ERROR_FAILURE); // NS_BINDING_ABORT ?
if (mLowImageRequest) if (mLowImageRequest)
mLowImageRequest->Cancel(NS_ERROR_FAILURE); // NS_BINDING_ABORT ? mLowImageRequest->Cancel(NS_ERROR_FAILURE); // NS_BINDING_ABORT ?
// set the frame to null so we don't send messages to a dead object.
if (mListener)
NS_REINTERPRET_CAST(nsImageListener*, mListener.get())->SetFrame(nsnull);
mImageRequest = nsnull;
mLowImageRequest = nsnull;
mListener = nsnull;
if (mListener)
NS_REINTERPRET_CAST(nsImageListener*, mListener.get())->SetFrame(nsnull); // set the frame to null so we don't send messages to a dead object.
#endif #endif
#ifndef USE_IMG2 #ifndef USE_IMG2
@ -245,19 +253,21 @@ nsImageFrame::Init(nsIPresContext* aPresContext,
nsresult lowSrcResult; nsresult lowSrcResult;
lowSrcResult = mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::lowsrc, lowSrc); lowSrcResult = mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::lowsrc, lowSrc);
// Set the image loader's source URL and base URL #ifndef USE_IMG2
nsCOMPtr<nsIURI> baseURL; nsCOMPtr<nsIURI> baseURL;
GetBaseURI(getter_AddRefs(baseURL)); GetBaseURI(getter_AddRefs(baseURL));
#endif
// Set the image loader's source URL and base URL
#ifdef USE_IMG2 #ifdef USE_IMG2
nsImageListener *listener; if (!mListener) {
NS_NEWXPCOM(listener, nsImageListener); nsImageListener *listener = new nsImageListener(this);
NS_ADDREF(listener); if (!listener) return NS_ERROR_OUT_OF_MEMORY;
listener->SetFrame(this); NS_ADDREF(listener);
listener->QueryInterface(NS_GET_IID(imgIDecoderObserver), getter_AddRefs(mListener)); listener->QueryInterface(NS_GET_IID(imgIDecoderObserver), getter_AddRefs(mListener));
NS_ASSERTION(mListener, "queryinterface for the listener failed"); NS_ASSERTION(mListener, "queryinterface for the listener failed");
NS_RELEASE(listener); NS_RELEASE(listener);
}
nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1", &rv)); nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1", &rv));
if (NS_FAILED(rv)) if (NS_FAILED(rv))
@ -270,9 +280,11 @@ nsImageFrame::Init(nsIPresContext* aPresContext,
if (NS_CONTENT_ATTR_HAS_VALUE == lowSrcResult && lowSrc.Length() > 0) { if (NS_CONTENT_ATTR_HAS_VALUE == lowSrcResult && lowSrc.Length() > 0) {
#ifdef USE_IMG2 #ifdef USE_IMG2
nsCOMPtr<nsIURI> lowURI; nsCOMPtr<nsIURI> lowURI;
NS_NewURI(getter_AddRefs(lowURI), src, baseURL); GetURI(lowSrc, getter_AddRefs(lowURI));
il->LoadImage(lowURI, loadGroup, mListener, aPresContext, getter_AddRefs(mLowImageRequest)); if (CanLoadImage(lowURI)) {
il->LoadImage(lowURI, loadGroup, mListener, aPresContext, getter_AddRefs(mLowImageRequest));
}
#else #else
mLowSrcImageLoader = new nsHTMLImageLoader; mLowSrcImageLoader = new nsHTMLImageLoader;
if (mLowSrcImageLoader) { if (mLowSrcImageLoader) {
@ -287,9 +299,11 @@ nsImageFrame::Init(nsIPresContext* aPresContext,
mCanSendLoadEvent = PR_TRUE; mCanSendLoadEvent = PR_TRUE;
nsCOMPtr<nsIURI> srcURI; nsCOMPtr<nsIURI> srcURI;
NS_NewURI(getter_AddRefs(srcURI), src, baseURL); GetURI(src, getter_AddRefs(srcURI));
il->LoadImage(srcURI, loadGroup, mListener, aPresContext, getter_AddRefs(mImageRequest)); if (CanLoadImage(srcURI)) {
// if the image was found in the cache, it is possible that LoadImage will result in a call to OnStartContainer() il->LoadImage(srcURI, loadGroup, mListener, aPresContext, getter_AddRefs(mImageRequest));
// if the image was found in the cache, it is possible that LoadImage will result in a call to OnStartContainer()
}
#else #else
mImageLoader.Init(this, UpdateImageFrame, (void*)&mImageLoader, baseURL, src); mImageLoader.Init(this, UpdateImageFrame, (void*)&mImageLoader, baseURL, src);
@ -324,10 +338,6 @@ NS_IMETHODIMP nsImageFrame::OnStartDecode(imgIRequest *aRequest, nsIPresContext
NS_IMETHODIMP nsImageFrame::OnStartContainer(imgIRequest *aRequest, nsIPresContext *aPresContext, imgIContainer *aImage) NS_IMETHODIMP nsImageFrame::OnStartContainer(imgIRequest *aRequest, nsIPresContext *aPresContext, imgIContainer *aImage)
{ {
nsCOMPtr<nsIPresShell> presShell;
nsresult rv = aPresContext->GetShell(getter_AddRefs(presShell));
if (NS_FAILED(rv)) return rv;
mInitialLoadCompleted = PR_TRUE; mInitialLoadCompleted = PR_TRUE;
nscoord w, h; nscoord w, h;
@ -350,26 +360,16 @@ NS_IMETHODIMP nsImageFrame::OnStartContainer(imgIRequest *aRequest, nsIPresConte
if (mComputedSize.width != 0 && mComputedSize.height != 0) if (mComputedSize.width != 0 && mComputedSize.height != 0)
mTransform.SetToScale((float(mIntrinsicSize.width) / float(mComputedSize.width)), (float(mIntrinsicSize.height) / float(mComputedSize.height))); mTransform.SetToScale((float(mIntrinsicSize.width) / float(mComputedSize.width)), (float(mIntrinsicSize.height) / float(mComputedSize.height)));
if (mParent) { if (!mSizeConstrained) {
if (mGotInitialReflow) { // don't reflow if we havn't gotten the inital reflow yet nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
NS_ASSERTION(mParent, "No parent to pass the reflow request up to.");
NS_ASSERTION(presShell, "No PresShell.");
if (mParent && presShell && mGotInitialReflow) { // don't reflow if we havn't gotten the inital reflow yet
mState |= NS_FRAME_IS_DIRTY; mState |= NS_FRAME_IS_DIRTY;
mParent->ReflowDirtyChild(presShell, (nsIFrame*) this); mParent->ReflowDirtyChild(presShell, NS_STATIC_CAST(nsIFrame*, this));
} }
} }
else {
NS_ASSERTION(0, "No parent to pass the reflow request up to.");
}
}
if (mCanSendLoadEvent && presShell) {
// Send load event
mCanSendLoadEvent = PR_FALSE;
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_IMAGE_LOAD;
presShell->HandleEventWithTarget(&event,this,mContent,NS_EVENT_FLAG_INIT | NS_EVENT_FLAG_CANT_BUBBLE,&status);
} }
return NS_OK; return NS_OK;
@ -382,19 +382,18 @@ NS_IMETHODIMP nsImageFrame::OnStartFrame(imgIRequest *aRequest, nsIPresContext *
NS_IMETHODIMP nsImageFrame::OnDataAvailable(imgIRequest *aRequest, nsIPresContext *aPresContext, gfxIImageFrame *aFrame, const nsRect *aRect) NS_IMETHODIMP nsImageFrame::OnDataAvailable(imgIRequest *aRequest, nsIPresContext *aPresContext, gfxIImageFrame *aFrame, const nsRect *aRect)
{ {
nsCOMPtr<nsIPresShell> presShell; // XXX do we need to make sure that the reflow from the OnStartContainer has been
nsresult rv = aPresContext->GetShell(getter_AddRefs(presShell));
if (NS_FAILED(rv)) return rv;
// XXX we need to make sure that the reflow from the OnContainerStart has been
// processed before we start calling invalidate // processed before we start calling invalidate
if (!aRect) if (!aRect)
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
nsRect r(aRect->x, aRect->y, aRect->width, aRect->height); nsRect r(aRect->x, aRect->y, aRect->width, aRect->height);
/* XXX Why do we subtract 1 here? The rect is (for example): (0, 0, 600, 1)..
Why do we have to make y -1?
*/
// The y coordinate of aRect is passed as a scanline where the first scanline is given // The y coordinate of aRect is passed as a scanline where the first scanline is given
// a value of 1. We need to convert this to the nsFrames coordinate space by subtracting // a value of 1. We need to convert this to the nsFrames coordinate space by subtracting
// 1. // 1.
@ -426,15 +425,76 @@ NS_IMETHODIMP nsImageFrame::OnStopContainer(imgIRequest *aRequest, nsIPresContex
NS_IMETHODIMP nsImageFrame::OnStopDecode(imgIRequest *aRequest, nsIPresContext *aPresContext, nsresult aStatus, const PRUnichar *aStatusArg) NS_IMETHODIMP nsImageFrame::OnStopDecode(imgIRequest *aRequest, nsIPresContext *aPresContext, nsresult aStatus, const PRUnichar *aStatusArg)
{ {
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
// check to see if an image error occurred
PRBool imageFailedToLoad = PR_FALSE;
if (NS_FAILED(aStatus)) { // We failed to load the image. Notify the pres shell
PRBool lowFailed = PR_FALSE;
PRBool imageFailed = PR_FALSE;
// One of the two images didn't load, which one?
if (mLowImageRequest == aRequest || !mLowImageRequest) {
lowFailed = PR_TRUE;
}
if (mImageRequest == aRequest || !mImageRequest) {
imageFailed = PR_TRUE;
}
if (imageFailed && lowFailed)
imageFailedToLoad = PR_TRUE;
}
// if src failed and there is no lowsrc
// or both failed to load, then notify the PresShell
if (imageFailedToLoad) {
if (presShell) {
nsAutoString usemap;
mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::usemap, usemap);
// We failed to load the image. Notify the pres shell if we aren't an image map
if (usemap.IsEmpty()) {
presShell->CantRenderReplacedElement(aPresContext, this);
}
}
}
// After these DOM events are fired its possible that this frame may be deleted. As a result
// the code should not attempt to access any of the frames internal data after this point.
if (presShell) {
if (imageFailedToLoad) {
// Send error event
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_IMAGE_ERROR;
presShell->HandleEventWithTarget(&event,this,mContent,NS_EVENT_FLAG_INIT,&status);
} else if (mCanSendLoadEvent) {
// Send load event
mCanSendLoadEvent = PR_FALSE;
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_IMAGE_LOAD;
presShell->HandleEventWithTarget(&event,this,mContent,NS_EVENT_FLAG_INIT | NS_EVENT_FLAG_CANT_BUBBLE,&status);
}
}
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsImageFrame::FrameChanged(imgIContainer *aContainer, nsIPresContext *aPresContext, gfxIImageFrame *aNewFrame, nsRect *aDirtyRect) NS_IMETHODIMP nsImageFrame::FrameChanged(imgIContainer *aContainer, nsIPresContext *aPresContext, gfxIImageFrame *aNewFrame, nsRect *aDirtyRect)
{ {
nsRect r(*aDirtyRect);
float p2t; float p2t;
aPresContext->GetPixelsToTwips(&p2t); aPresContext->GetPixelsToTwips(&p2t);
nsRect r(*aDirtyRect); r.x = NSIntPixelsToTwips(r.x, p2t);
r *= p2t; // convert to twips r.y = NSIntPixelsToTwips(r.y, p2t);
r.width = NSIntPixelsToTwips(r.width, p2t);
r.height = NSIntPixelsToTwips(r.height, p2t);
mTransform.TransformCoord(&r.x, &r.y, &r.width, &r.height); mTransform.TransformCoord(&r.x, &r.y, &r.width, &r.height);
@ -487,7 +547,7 @@ nsImageFrame::UpdateImage(nsIPresContext* aPresContext, PRUint32 aStatus, void*
nsAutoString usemap; nsAutoString usemap;
mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::usemap, usemap); mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::usemap, usemap);
// We failed to load the image. Notify the pres shell if we aren't an image map // We failed to load the image. Notify the pres shell if we aren't an image map
if (usemap.Length() == 0) { if (usemap.IsEmpty()) {
presShell->CantRenderReplacedElement(aPresContext, this); presShell->CantRenderReplacedElement(aPresContext, this);
} }
} }
@ -616,7 +676,7 @@ nsImageFrame::GetDesiredSize(nsIPresContext* aPresContext,
newHeight = (mIntrinsicSize.height * newWidth) / mIntrinsicSize.width; newHeight = (mIntrinsicSize.height * newWidth) / mIntrinsicSize.width;
haveComputedSize = PR_TRUE; haveComputedSize = PR_TRUE;
} else { } else {
newHeight = NSIntPixelsToTwips(1, p2t); // XXX? newHeight = 0;
needIntrinsicImageSize = PR_TRUE; needIntrinsicImageSize = PR_TRUE;
} }
} }
@ -628,30 +688,31 @@ nsImageFrame::GetDesiredSize(nsIPresContext* aPresContext,
newWidth = (mIntrinsicSize.width * newHeight) / mIntrinsicSize.height; newWidth = (mIntrinsicSize.width * newHeight) / mIntrinsicSize.height;
haveComputedSize = PR_TRUE; haveComputedSize = PR_TRUE;
} else { } else {
newWidth = NSIntPixelsToTwips(1, p2t); newWidth = 0;
needIntrinsicImageSize = PR_TRUE; needIntrinsicImageSize = PR_TRUE;
} }
} else { } else {
// auto size the image // auto size the image
if (mIntrinsicSize.width == 0 && mIntrinsicSize.height == 0) { if (mIntrinsicSize.width == 0 && mIntrinsicSize.height == 0)
newWidth = NSIntPixelsToTwips(1, p2t);
newHeight = NSIntPixelsToTwips(1, p2t);
needIntrinsicImageSize = PR_TRUE; needIntrinsicImageSize = PR_TRUE;
} else { else
newWidth = mIntrinsicSize.width;
newHeight = mIntrinsicSize.height;
haveComputedSize = PR_TRUE; haveComputedSize = PR_TRUE;
}
newWidth = mIntrinsicSize.width;
newHeight = mIntrinsicSize.height;
} }
mComputedSize.width = newWidth; mComputedSize.width = newWidth;
mComputedSize.height = newHeight; mComputedSize.height = newHeight;
if (mComputedSize == mIntrinsicSize) if (mComputedSize == mIntrinsicSize) {
mTransform.SetToIdentity(); mTransform.SetToIdentity();
else } else {
mTransform.SetToScale((float(mIntrinsicSize.width) / float(mComputedSize.width)), (float(mIntrinsicSize.height) / float(mComputedSize.height))); if (mComputedSize.width != 0 && mComputedSize.height != 0) {
mTransform.SetToScale(float(mIntrinsicSize.width) / float(mComputedSize.width),
float(mIntrinsicSize.height) / float(mComputedSize.height));
}
}
aDesiredSize.width = mComputedSize.width; aDesiredSize.width = mComputedSize.width;
aDesiredSize.height = mComputedSize.height; aDesiredSize.height = mComputedSize.height;
@ -977,12 +1038,12 @@ nsImageFrame::Paint(nsIPresContext* aPresContext,
PRInt32 imgSrcLinesLoaded = -1; PRInt32 imgSrcLinesLoaded = -1;
#ifdef USE_IMG2 #ifdef USE_IMG2
NS_ASSERTION(mImageRequest, "no image request! this is bad");
nsCOMPtr<imgIContainer> imgCon; nsCOMPtr<imgIContainer> imgCon;
nsCOMPtr<imgIContainer> lowImgCon; nsCOMPtr<imgIContainer> lowImgCon;
mImageRequest->GetImage(getter_AddRefs(imgCon)); if (mImageRequest) {
mImageRequest->GetImage(getter_AddRefs(imgCon));
}
#else #else
nsIImage * lowImage = nsnull; nsIImage * lowImage = nsnull;
nsIImage * image = nsnull; nsIImage * image = nsnull;
@ -1001,8 +1062,10 @@ nsImageFrame::Paint(nsIPresContext* aPresContext,
#endif #endif
#ifdef USE_IMG2 #ifdef USE_IMG2
PRUint32 loadStatus; PRUint32 loadStatus = imgIRequest::STATUS_NONE;
mImageRequest->GetImageStatus(&loadStatus); if (mImageRequest) {
mImageRequest->GetImageStatus(&loadStatus);
}
if (!(loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE) || (!imgCon && !lowImgCon)) { if (!(loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE) || (!imgCon && !lowImgCon)) {
#else #else
image = mImageLoader.GetImage(); image = mImageLoader.GetImage();
@ -1143,7 +1206,7 @@ nsImageFrame::GetImageMap(nsIPresContext* aPresContext)
if (nsnull == mImageMap) { if (nsnull == mImageMap) {
nsAutoString usemap; nsAutoString usemap;
mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::usemap, usemap); mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::usemap, usemap);
if (0 == usemap.Length()) { if (usemap.IsEmpty()) {
return nsnull; return nsnull;
} }
@ -1480,18 +1543,17 @@ nsImageFrame::AttributeChanged(nsIPresContext* aPresContext,
PRUint32 loadStatus; PRUint32 loadStatus;
#ifdef USE_IMG2 #ifdef USE_IMG2
nsCOMPtr<nsIURI> baseURI;
GetBaseURI(getter_AddRefs(baseURI));
nsCOMPtr<nsILoadGroup> loadGroup; nsCOMPtr<nsILoadGroup> loadGroup;
GetLoadGroup(aPresContext, getter_AddRefs(loadGroup)); GetLoadGroup(aPresContext, getter_AddRefs(loadGroup));
mImageRequest->GetImageStatus(&loadStatus); mImageRequest->GetImageStatus(&loadStatus);
if (loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE) { if (loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE) {
nsCOMPtr<nsIURI> uri; nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), newSRC, baseURI); GetURI(newSRC, getter_AddRefs(uri));
nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1")); nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1"));
NS_ASSERTION(il, "no image loader!"); NS_ASSERTION(il, "no image loader!");
il->LoadImage(uri, loadGroup, mListener, aPresContext, getter_AddRefs(mImageRequest)); il->LoadImage(uri, loadGroup, mListener, aPresContext, getter_AddRefs(mImageRequest));
mImageRequest->GetImageStatus(&loadStatus); mImageRequest->GetImageStatus(&loadStatus);
@ -1516,9 +1578,11 @@ nsImageFrame::AttributeChanged(nsIPresContext* aPresContext,
mCanSendLoadEvent = PR_TRUE; mCanSendLoadEvent = PR_TRUE;
nsCOMPtr<nsIURI> uri; nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), newSRC, baseURI); GetURI(newSRC, getter_AddRefs(uri));
nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1")); nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1"));
NS_ASSERTION(il, "no image loader!"); NS_ASSERTION(il, "no image loader!");
il->LoadImage(uri, loadGroup, mListener, aPresContext, getter_AddRefs(mImageRequest)); il->LoadImage(uri, loadGroup, mListener, aPresContext, getter_AddRefs(mImageRequest));
#else #else
mImageLoader.StopLoadImage(aPresContext); mImageLoader.StopLoadImage(aPresContext);
@ -1619,6 +1683,35 @@ void HaveFixedSize(const nsHTMLReflowState& aReflowState, PRPackedBool& aConstra
heightUnit == eStyleUnit_Percent)); heightUnit == eStyleUnit_Percent));
} }
#define INTERNAL_GOPHER_STRING "internal-gopher-"
#define INTERNAL_GOPHER_LENGTH 17
void
nsImageFrame::GetURI(const nsAReadableString& aSpec, nsIURI **aURI)
{
nsAutoString newURI;
/* Note: navigator 4.* and earlier releases ignored the base tags
effect on the builtin images. So we do too. Use aSpec instead
of the absolute url...
*/
/* The prefix for special "internal" images that are well known.
Look and see if this is an internal-gopher- url.
*/
if (NS_LITERAL_STRING(INTERNAL_GOPHER_STRING).Equals(Substring(aSpec, 0, INTERNAL_GOPHER_LENGTH))) {
newURI.Assign(NS_LITERAL_STRING("resource:/res/html/gopher-") +
Substring(aSpec, INTERNAL_GOPHER_LENGTH, aSpec.Length() - INTERNAL_GOPHER_LENGTH) +
NS_LITERAL_STRING(".gif"));
} else {
newURI.Assign(aSpec);
}
nsCOMPtr<nsIURI> baseURI;
GetBaseURI(getter_AddRefs(baseURI));
NS_NewURI(aURI, newURI, baseURI);
}
void void
nsImageFrame::GetBaseURI(nsIURI **aURI) nsImageFrame::GetBaseURI(nsIURI **aURI)
{ {
@ -1664,6 +1757,40 @@ nsImageFrame::GetLoadGroup(nsIPresContext *aPresContext, nsILoadGroup **aLoadGro
} }
// Check with the content-policy things to make sure this load is permitted.
PRBool
nsImageFrame::CanLoadImage(nsIURI *aURI)
{
PRBool shouldLoad = PR_TRUE; // default permit
// XXX leave this if 0'd until there is a good way to test it.
#if 0
nsresult rv;
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mContent));
if (!element) // this would seem bad(tm)
return PR_FALSE;
nsXPIDLCString uric;
aURI->GetSpec(getter_Copies(uric));
nsString uri = NS_ConvertUTF8toUCS2(uric);
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::CONTENT_IMAGE,
uri, element, &shouldLoad);
if (NS_SUCCEEDED(rv) && !shouldLoad)
return PR_FALSE;
/* ... additional checks ? */
#endif
return shouldLoad;
}
#ifdef DEBUG #ifdef DEBUG
NS_IMETHODIMP NS_IMETHODIMP
nsImageFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const nsImageFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const
@ -1692,7 +1819,8 @@ nsImageFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const
#ifdef USE_IMG2 #ifdef USE_IMG2
NS_IMPL_ISUPPORTS2(nsImageListener, imgIDecoderObserver, imgIContainerObserver) NS_IMPL_ISUPPORTS2(nsImageListener, imgIDecoderObserver, imgIContainerObserver)
nsImageListener::nsImageListener() nsImageListener::nsImageListener(nsImageFrame *aFrame) :
mFrame(aFrame)
{ {
NS_INIT_ISUPPORTS(); NS_INIT_ISUPPORTS();
} }

View File

@ -24,6 +24,7 @@
#include "nsLeafFrame.h" #include "nsLeafFrame.h"
#include "nsString.h" #include "nsString.h"
#include "nsAReadableString.h"
#include "nsIPresContext.h" #include "nsIPresContext.h"
#include "nsHTMLImageLoader.h" #include "nsHTMLImageLoader.h"
#include "nsIImageFrame.h" #include "nsIImageFrame.h"
@ -49,7 +50,7 @@ class nsImageFrame;
class nsImageListener : imgIDecoderObserver class nsImageListener : imgIDecoderObserver
{ {
public: public:
nsImageListener(); nsImageListener(nsImageFrame *aFrame);
virtual ~nsImageListener(); virtual ~nsImageListener();
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
@ -182,8 +183,11 @@ protected:
PRUint32 aStatus); PRUint32 aStatus);
#endif #endif
void GetBaseURI(nsIURI **uri); PRBool CanLoadImage(nsIURI *aURI);
void GetLoadGroup(nsIPresContext *aPresContext, nsILoadGroup **aLoadGroup);
inline void GetURI(const nsAReadableString& aSpec, nsIURI **aURI);
inline void GetBaseURI(nsIURI **uri);
inline void GetLoadGroup(nsIPresContext *aPresContext, nsILoadGroup **aLoadGroup);
nsHTMLImageLoader mImageLoader; nsHTMLImageLoader mImageLoader;
nsHTMLImageLoader * mLowSrcImageLoader; nsHTMLImageLoader * mLowSrcImageLoader;

View File

@ -69,6 +69,8 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsIDOMNode.h" #include "nsIDOMNode.h"
#include "nsContentPolicyUtils.h"
#ifdef DEBUG #ifdef DEBUG
#undef NOISY_IMAGE_LOADING #undef NOISY_IMAGE_LOADING
@ -189,13 +191,19 @@ nsImageFrame::Destroy(nsIPresContext* aPresContext)
} }
#ifdef USE_IMG2 #ifdef USE_IMG2
if (mImageRequest) if (mImageRequest)
mImageRequest->Cancel(NS_ERROR_FAILURE); // NS_BINDING_ABORT ? mImageRequest->Cancel(NS_ERROR_FAILURE); // NS_BINDING_ABORT ?
if (mLowImageRequest) if (mLowImageRequest)
mLowImageRequest->Cancel(NS_ERROR_FAILURE); // NS_BINDING_ABORT ? mLowImageRequest->Cancel(NS_ERROR_FAILURE); // NS_BINDING_ABORT ?
// set the frame to null so we don't send messages to a dead object.
if (mListener)
NS_REINTERPRET_CAST(nsImageListener*, mListener.get())->SetFrame(nsnull);
mImageRequest = nsnull;
mLowImageRequest = nsnull;
mListener = nsnull;
if (mListener)
NS_REINTERPRET_CAST(nsImageListener*, mListener.get())->SetFrame(nsnull); // set the frame to null so we don't send messages to a dead object.
#endif #endif
#ifndef USE_IMG2 #ifndef USE_IMG2
@ -245,19 +253,21 @@ nsImageFrame::Init(nsIPresContext* aPresContext,
nsresult lowSrcResult; nsresult lowSrcResult;
lowSrcResult = mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::lowsrc, lowSrc); lowSrcResult = mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::lowsrc, lowSrc);
// Set the image loader's source URL and base URL #ifndef USE_IMG2
nsCOMPtr<nsIURI> baseURL; nsCOMPtr<nsIURI> baseURL;
GetBaseURI(getter_AddRefs(baseURL)); GetBaseURI(getter_AddRefs(baseURL));
#endif
// Set the image loader's source URL and base URL
#ifdef USE_IMG2 #ifdef USE_IMG2
nsImageListener *listener; if (!mListener) {
NS_NEWXPCOM(listener, nsImageListener); nsImageListener *listener = new nsImageListener(this);
NS_ADDREF(listener); if (!listener) return NS_ERROR_OUT_OF_MEMORY;
listener->SetFrame(this); NS_ADDREF(listener);
listener->QueryInterface(NS_GET_IID(imgIDecoderObserver), getter_AddRefs(mListener)); listener->QueryInterface(NS_GET_IID(imgIDecoderObserver), getter_AddRefs(mListener));
NS_ASSERTION(mListener, "queryinterface for the listener failed"); NS_ASSERTION(mListener, "queryinterface for the listener failed");
NS_RELEASE(listener); NS_RELEASE(listener);
}
nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1", &rv)); nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1", &rv));
if (NS_FAILED(rv)) if (NS_FAILED(rv))
@ -270,9 +280,11 @@ nsImageFrame::Init(nsIPresContext* aPresContext,
if (NS_CONTENT_ATTR_HAS_VALUE == lowSrcResult && lowSrc.Length() > 0) { if (NS_CONTENT_ATTR_HAS_VALUE == lowSrcResult && lowSrc.Length() > 0) {
#ifdef USE_IMG2 #ifdef USE_IMG2
nsCOMPtr<nsIURI> lowURI; nsCOMPtr<nsIURI> lowURI;
NS_NewURI(getter_AddRefs(lowURI), src, baseURL); GetURI(lowSrc, getter_AddRefs(lowURI));
il->LoadImage(lowURI, loadGroup, mListener, aPresContext, getter_AddRefs(mLowImageRequest)); if (CanLoadImage(lowURI)) {
il->LoadImage(lowURI, loadGroup, mListener, aPresContext, getter_AddRefs(mLowImageRequest));
}
#else #else
mLowSrcImageLoader = new nsHTMLImageLoader; mLowSrcImageLoader = new nsHTMLImageLoader;
if (mLowSrcImageLoader) { if (mLowSrcImageLoader) {
@ -287,9 +299,11 @@ nsImageFrame::Init(nsIPresContext* aPresContext,
mCanSendLoadEvent = PR_TRUE; mCanSendLoadEvent = PR_TRUE;
nsCOMPtr<nsIURI> srcURI; nsCOMPtr<nsIURI> srcURI;
NS_NewURI(getter_AddRefs(srcURI), src, baseURL); GetURI(src, getter_AddRefs(srcURI));
il->LoadImage(srcURI, loadGroup, mListener, aPresContext, getter_AddRefs(mImageRequest)); if (CanLoadImage(srcURI)) {
// if the image was found in the cache, it is possible that LoadImage will result in a call to OnStartContainer() il->LoadImage(srcURI, loadGroup, mListener, aPresContext, getter_AddRefs(mImageRequest));
// if the image was found in the cache, it is possible that LoadImage will result in a call to OnStartContainer()
}
#else #else
mImageLoader.Init(this, UpdateImageFrame, (void*)&mImageLoader, baseURL, src); mImageLoader.Init(this, UpdateImageFrame, (void*)&mImageLoader, baseURL, src);
@ -324,10 +338,6 @@ NS_IMETHODIMP nsImageFrame::OnStartDecode(imgIRequest *aRequest, nsIPresContext
NS_IMETHODIMP nsImageFrame::OnStartContainer(imgIRequest *aRequest, nsIPresContext *aPresContext, imgIContainer *aImage) NS_IMETHODIMP nsImageFrame::OnStartContainer(imgIRequest *aRequest, nsIPresContext *aPresContext, imgIContainer *aImage)
{ {
nsCOMPtr<nsIPresShell> presShell;
nsresult rv = aPresContext->GetShell(getter_AddRefs(presShell));
if (NS_FAILED(rv)) return rv;
mInitialLoadCompleted = PR_TRUE; mInitialLoadCompleted = PR_TRUE;
nscoord w, h; nscoord w, h;
@ -350,26 +360,16 @@ NS_IMETHODIMP nsImageFrame::OnStartContainer(imgIRequest *aRequest, nsIPresConte
if (mComputedSize.width != 0 && mComputedSize.height != 0) if (mComputedSize.width != 0 && mComputedSize.height != 0)
mTransform.SetToScale((float(mIntrinsicSize.width) / float(mComputedSize.width)), (float(mIntrinsicSize.height) / float(mComputedSize.height))); mTransform.SetToScale((float(mIntrinsicSize.width) / float(mComputedSize.width)), (float(mIntrinsicSize.height) / float(mComputedSize.height)));
if (mParent) { if (!mSizeConstrained) {
if (mGotInitialReflow) { // don't reflow if we havn't gotten the inital reflow yet nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
NS_ASSERTION(mParent, "No parent to pass the reflow request up to.");
NS_ASSERTION(presShell, "No PresShell.");
if (mParent && presShell && mGotInitialReflow) { // don't reflow if we havn't gotten the inital reflow yet
mState |= NS_FRAME_IS_DIRTY; mState |= NS_FRAME_IS_DIRTY;
mParent->ReflowDirtyChild(presShell, (nsIFrame*) this); mParent->ReflowDirtyChild(presShell, NS_STATIC_CAST(nsIFrame*, this));
} }
} }
else {
NS_ASSERTION(0, "No parent to pass the reflow request up to.");
}
}
if (mCanSendLoadEvent && presShell) {
// Send load event
mCanSendLoadEvent = PR_FALSE;
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_IMAGE_LOAD;
presShell->HandleEventWithTarget(&event,this,mContent,NS_EVENT_FLAG_INIT | NS_EVENT_FLAG_CANT_BUBBLE,&status);
} }
return NS_OK; return NS_OK;
@ -382,19 +382,18 @@ NS_IMETHODIMP nsImageFrame::OnStartFrame(imgIRequest *aRequest, nsIPresContext *
NS_IMETHODIMP nsImageFrame::OnDataAvailable(imgIRequest *aRequest, nsIPresContext *aPresContext, gfxIImageFrame *aFrame, const nsRect *aRect) NS_IMETHODIMP nsImageFrame::OnDataAvailable(imgIRequest *aRequest, nsIPresContext *aPresContext, gfxIImageFrame *aFrame, const nsRect *aRect)
{ {
nsCOMPtr<nsIPresShell> presShell; // XXX do we need to make sure that the reflow from the OnStartContainer has been
nsresult rv = aPresContext->GetShell(getter_AddRefs(presShell));
if (NS_FAILED(rv)) return rv;
// XXX we need to make sure that the reflow from the OnContainerStart has been
// processed before we start calling invalidate // processed before we start calling invalidate
if (!aRect) if (!aRect)
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
nsRect r(aRect->x, aRect->y, aRect->width, aRect->height); nsRect r(aRect->x, aRect->y, aRect->width, aRect->height);
/* XXX Why do we subtract 1 here? The rect is (for example): (0, 0, 600, 1)..
Why do we have to make y -1?
*/
// The y coordinate of aRect is passed as a scanline where the first scanline is given // The y coordinate of aRect is passed as a scanline where the first scanline is given
// a value of 1. We need to convert this to the nsFrames coordinate space by subtracting // a value of 1. We need to convert this to the nsFrames coordinate space by subtracting
// 1. // 1.
@ -426,15 +425,76 @@ NS_IMETHODIMP nsImageFrame::OnStopContainer(imgIRequest *aRequest, nsIPresContex
NS_IMETHODIMP nsImageFrame::OnStopDecode(imgIRequest *aRequest, nsIPresContext *aPresContext, nsresult aStatus, const PRUnichar *aStatusArg) NS_IMETHODIMP nsImageFrame::OnStopDecode(imgIRequest *aRequest, nsIPresContext *aPresContext, nsresult aStatus, const PRUnichar *aStatusArg)
{ {
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
// check to see if an image error occurred
PRBool imageFailedToLoad = PR_FALSE;
if (NS_FAILED(aStatus)) { // We failed to load the image. Notify the pres shell
PRBool lowFailed = PR_FALSE;
PRBool imageFailed = PR_FALSE;
// One of the two images didn't load, which one?
if (mLowImageRequest == aRequest || !mLowImageRequest) {
lowFailed = PR_TRUE;
}
if (mImageRequest == aRequest || !mImageRequest) {
imageFailed = PR_TRUE;
}
if (imageFailed && lowFailed)
imageFailedToLoad = PR_TRUE;
}
// if src failed and there is no lowsrc
// or both failed to load, then notify the PresShell
if (imageFailedToLoad) {
if (presShell) {
nsAutoString usemap;
mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::usemap, usemap);
// We failed to load the image. Notify the pres shell if we aren't an image map
if (usemap.IsEmpty()) {
presShell->CantRenderReplacedElement(aPresContext, this);
}
}
}
// After these DOM events are fired its possible that this frame may be deleted. As a result
// the code should not attempt to access any of the frames internal data after this point.
if (presShell) {
if (imageFailedToLoad) {
// Send error event
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_IMAGE_ERROR;
presShell->HandleEventWithTarget(&event,this,mContent,NS_EVENT_FLAG_INIT,&status);
} else if (mCanSendLoadEvent) {
// Send load event
mCanSendLoadEvent = PR_FALSE;
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_IMAGE_LOAD;
presShell->HandleEventWithTarget(&event,this,mContent,NS_EVENT_FLAG_INIT | NS_EVENT_FLAG_CANT_BUBBLE,&status);
}
}
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsImageFrame::FrameChanged(imgIContainer *aContainer, nsIPresContext *aPresContext, gfxIImageFrame *aNewFrame, nsRect *aDirtyRect) NS_IMETHODIMP nsImageFrame::FrameChanged(imgIContainer *aContainer, nsIPresContext *aPresContext, gfxIImageFrame *aNewFrame, nsRect *aDirtyRect)
{ {
nsRect r(*aDirtyRect);
float p2t; float p2t;
aPresContext->GetPixelsToTwips(&p2t); aPresContext->GetPixelsToTwips(&p2t);
nsRect r(*aDirtyRect); r.x = NSIntPixelsToTwips(r.x, p2t);
r *= p2t; // convert to twips r.y = NSIntPixelsToTwips(r.y, p2t);
r.width = NSIntPixelsToTwips(r.width, p2t);
r.height = NSIntPixelsToTwips(r.height, p2t);
mTransform.TransformCoord(&r.x, &r.y, &r.width, &r.height); mTransform.TransformCoord(&r.x, &r.y, &r.width, &r.height);
@ -487,7 +547,7 @@ nsImageFrame::UpdateImage(nsIPresContext* aPresContext, PRUint32 aStatus, void*
nsAutoString usemap; nsAutoString usemap;
mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::usemap, usemap); mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::usemap, usemap);
// We failed to load the image. Notify the pres shell if we aren't an image map // We failed to load the image. Notify the pres shell if we aren't an image map
if (usemap.Length() == 0) { if (usemap.IsEmpty()) {
presShell->CantRenderReplacedElement(aPresContext, this); presShell->CantRenderReplacedElement(aPresContext, this);
} }
} }
@ -616,7 +676,7 @@ nsImageFrame::GetDesiredSize(nsIPresContext* aPresContext,
newHeight = (mIntrinsicSize.height * newWidth) / mIntrinsicSize.width; newHeight = (mIntrinsicSize.height * newWidth) / mIntrinsicSize.width;
haveComputedSize = PR_TRUE; haveComputedSize = PR_TRUE;
} else { } else {
newHeight = NSIntPixelsToTwips(1, p2t); // XXX? newHeight = 0;
needIntrinsicImageSize = PR_TRUE; needIntrinsicImageSize = PR_TRUE;
} }
} }
@ -628,30 +688,31 @@ nsImageFrame::GetDesiredSize(nsIPresContext* aPresContext,
newWidth = (mIntrinsicSize.width * newHeight) / mIntrinsicSize.height; newWidth = (mIntrinsicSize.width * newHeight) / mIntrinsicSize.height;
haveComputedSize = PR_TRUE; haveComputedSize = PR_TRUE;
} else { } else {
newWidth = NSIntPixelsToTwips(1, p2t); newWidth = 0;
needIntrinsicImageSize = PR_TRUE; needIntrinsicImageSize = PR_TRUE;
} }
} else { } else {
// auto size the image // auto size the image
if (mIntrinsicSize.width == 0 && mIntrinsicSize.height == 0) { if (mIntrinsicSize.width == 0 && mIntrinsicSize.height == 0)
newWidth = NSIntPixelsToTwips(1, p2t);
newHeight = NSIntPixelsToTwips(1, p2t);
needIntrinsicImageSize = PR_TRUE; needIntrinsicImageSize = PR_TRUE;
} else { else
newWidth = mIntrinsicSize.width;
newHeight = mIntrinsicSize.height;
haveComputedSize = PR_TRUE; haveComputedSize = PR_TRUE;
}
newWidth = mIntrinsicSize.width;
newHeight = mIntrinsicSize.height;
} }
mComputedSize.width = newWidth; mComputedSize.width = newWidth;
mComputedSize.height = newHeight; mComputedSize.height = newHeight;
if (mComputedSize == mIntrinsicSize) if (mComputedSize == mIntrinsicSize) {
mTransform.SetToIdentity(); mTransform.SetToIdentity();
else } else {
mTransform.SetToScale((float(mIntrinsicSize.width) / float(mComputedSize.width)), (float(mIntrinsicSize.height) / float(mComputedSize.height))); if (mComputedSize.width != 0 && mComputedSize.height != 0) {
mTransform.SetToScale(float(mIntrinsicSize.width) / float(mComputedSize.width),
float(mIntrinsicSize.height) / float(mComputedSize.height));
}
}
aDesiredSize.width = mComputedSize.width; aDesiredSize.width = mComputedSize.width;
aDesiredSize.height = mComputedSize.height; aDesiredSize.height = mComputedSize.height;
@ -977,12 +1038,12 @@ nsImageFrame::Paint(nsIPresContext* aPresContext,
PRInt32 imgSrcLinesLoaded = -1; PRInt32 imgSrcLinesLoaded = -1;
#ifdef USE_IMG2 #ifdef USE_IMG2
NS_ASSERTION(mImageRequest, "no image request! this is bad");
nsCOMPtr<imgIContainer> imgCon; nsCOMPtr<imgIContainer> imgCon;
nsCOMPtr<imgIContainer> lowImgCon; nsCOMPtr<imgIContainer> lowImgCon;
mImageRequest->GetImage(getter_AddRefs(imgCon)); if (mImageRequest) {
mImageRequest->GetImage(getter_AddRefs(imgCon));
}
#else #else
nsIImage * lowImage = nsnull; nsIImage * lowImage = nsnull;
nsIImage * image = nsnull; nsIImage * image = nsnull;
@ -1001,8 +1062,10 @@ nsImageFrame::Paint(nsIPresContext* aPresContext,
#endif #endif
#ifdef USE_IMG2 #ifdef USE_IMG2
PRUint32 loadStatus; PRUint32 loadStatus = imgIRequest::STATUS_NONE;
mImageRequest->GetImageStatus(&loadStatus); if (mImageRequest) {
mImageRequest->GetImageStatus(&loadStatus);
}
if (!(loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE) || (!imgCon && !lowImgCon)) { if (!(loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE) || (!imgCon && !lowImgCon)) {
#else #else
image = mImageLoader.GetImage(); image = mImageLoader.GetImage();
@ -1143,7 +1206,7 @@ nsImageFrame::GetImageMap(nsIPresContext* aPresContext)
if (nsnull == mImageMap) { if (nsnull == mImageMap) {
nsAutoString usemap; nsAutoString usemap;
mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::usemap, usemap); mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::usemap, usemap);
if (0 == usemap.Length()) { if (usemap.IsEmpty()) {
return nsnull; return nsnull;
} }
@ -1480,18 +1543,17 @@ nsImageFrame::AttributeChanged(nsIPresContext* aPresContext,
PRUint32 loadStatus; PRUint32 loadStatus;
#ifdef USE_IMG2 #ifdef USE_IMG2
nsCOMPtr<nsIURI> baseURI;
GetBaseURI(getter_AddRefs(baseURI));
nsCOMPtr<nsILoadGroup> loadGroup; nsCOMPtr<nsILoadGroup> loadGroup;
GetLoadGroup(aPresContext, getter_AddRefs(loadGroup)); GetLoadGroup(aPresContext, getter_AddRefs(loadGroup));
mImageRequest->GetImageStatus(&loadStatus); mImageRequest->GetImageStatus(&loadStatus);
if (loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE) { if (loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE) {
nsCOMPtr<nsIURI> uri; nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), newSRC, baseURI); GetURI(newSRC, getter_AddRefs(uri));
nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1")); nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1"));
NS_ASSERTION(il, "no image loader!"); NS_ASSERTION(il, "no image loader!");
il->LoadImage(uri, loadGroup, mListener, aPresContext, getter_AddRefs(mImageRequest)); il->LoadImage(uri, loadGroup, mListener, aPresContext, getter_AddRefs(mImageRequest));
mImageRequest->GetImageStatus(&loadStatus); mImageRequest->GetImageStatus(&loadStatus);
@ -1516,9 +1578,11 @@ nsImageFrame::AttributeChanged(nsIPresContext* aPresContext,
mCanSendLoadEvent = PR_TRUE; mCanSendLoadEvent = PR_TRUE;
nsCOMPtr<nsIURI> uri; nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), newSRC, baseURI); GetURI(newSRC, getter_AddRefs(uri));
nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1")); nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1"));
NS_ASSERTION(il, "no image loader!"); NS_ASSERTION(il, "no image loader!");
il->LoadImage(uri, loadGroup, mListener, aPresContext, getter_AddRefs(mImageRequest)); il->LoadImage(uri, loadGroup, mListener, aPresContext, getter_AddRefs(mImageRequest));
#else #else
mImageLoader.StopLoadImage(aPresContext); mImageLoader.StopLoadImage(aPresContext);
@ -1619,6 +1683,35 @@ void HaveFixedSize(const nsHTMLReflowState& aReflowState, PRPackedBool& aConstra
heightUnit == eStyleUnit_Percent)); heightUnit == eStyleUnit_Percent));
} }
#define INTERNAL_GOPHER_STRING "internal-gopher-"
#define INTERNAL_GOPHER_LENGTH 17
void
nsImageFrame::GetURI(const nsAReadableString& aSpec, nsIURI **aURI)
{
nsAutoString newURI;
/* Note: navigator 4.* and earlier releases ignored the base tags
effect on the builtin images. So we do too. Use aSpec instead
of the absolute url...
*/
/* The prefix for special "internal" images that are well known.
Look and see if this is an internal-gopher- url.
*/
if (NS_LITERAL_STRING(INTERNAL_GOPHER_STRING).Equals(Substring(aSpec, 0, INTERNAL_GOPHER_LENGTH))) {
newURI.Assign(NS_LITERAL_STRING("resource:/res/html/gopher-") +
Substring(aSpec, INTERNAL_GOPHER_LENGTH, aSpec.Length() - INTERNAL_GOPHER_LENGTH) +
NS_LITERAL_STRING(".gif"));
} else {
newURI.Assign(aSpec);
}
nsCOMPtr<nsIURI> baseURI;
GetBaseURI(getter_AddRefs(baseURI));
NS_NewURI(aURI, newURI, baseURI);
}
void void
nsImageFrame::GetBaseURI(nsIURI **aURI) nsImageFrame::GetBaseURI(nsIURI **aURI)
{ {
@ -1664,6 +1757,40 @@ nsImageFrame::GetLoadGroup(nsIPresContext *aPresContext, nsILoadGroup **aLoadGro
} }
// Check with the content-policy things to make sure this load is permitted.
PRBool
nsImageFrame::CanLoadImage(nsIURI *aURI)
{
PRBool shouldLoad = PR_TRUE; // default permit
// XXX leave this if 0'd until there is a good way to test it.
#if 0
nsresult rv;
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mContent));
if (!element) // this would seem bad(tm)
return PR_FALSE;
nsXPIDLCString uric;
aURI->GetSpec(getter_Copies(uric));
nsString uri = NS_ConvertUTF8toUCS2(uric);
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::CONTENT_IMAGE,
uri, element, &shouldLoad);
if (NS_SUCCEEDED(rv) && !shouldLoad)
return PR_FALSE;
/* ... additional checks ? */
#endif
return shouldLoad;
}
#ifdef DEBUG #ifdef DEBUG
NS_IMETHODIMP NS_IMETHODIMP
nsImageFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const nsImageFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const
@ -1692,7 +1819,8 @@ nsImageFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const
#ifdef USE_IMG2 #ifdef USE_IMG2
NS_IMPL_ISUPPORTS2(nsImageListener, imgIDecoderObserver, imgIContainerObserver) NS_IMPL_ISUPPORTS2(nsImageListener, imgIDecoderObserver, imgIContainerObserver)
nsImageListener::nsImageListener() nsImageListener::nsImageListener(nsImageFrame *aFrame) :
mFrame(aFrame)
{ {
NS_INIT_ISUPPORTS(); NS_INIT_ISUPPORTS();
} }

View File

@ -24,6 +24,7 @@
#include "nsLeafFrame.h" #include "nsLeafFrame.h"
#include "nsString.h" #include "nsString.h"
#include "nsAReadableString.h"
#include "nsIPresContext.h" #include "nsIPresContext.h"
#include "nsHTMLImageLoader.h" #include "nsHTMLImageLoader.h"
#include "nsIImageFrame.h" #include "nsIImageFrame.h"
@ -49,7 +50,7 @@ class nsImageFrame;
class nsImageListener : imgIDecoderObserver class nsImageListener : imgIDecoderObserver
{ {
public: public:
nsImageListener(); nsImageListener(nsImageFrame *aFrame);
virtual ~nsImageListener(); virtual ~nsImageListener();
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
@ -182,8 +183,11 @@ protected:
PRUint32 aStatus); PRUint32 aStatus);
#endif #endif
void GetBaseURI(nsIURI **uri); PRBool CanLoadImage(nsIURI *aURI);
void GetLoadGroup(nsIPresContext *aPresContext, nsILoadGroup **aLoadGroup);
inline void GetURI(const nsAReadableString& aSpec, nsIURI **aURI);
inline void GetBaseURI(nsIURI **uri);
inline void GetLoadGroup(nsIPresContext *aPresContext, nsILoadGroup **aLoadGroup);
nsHTMLImageLoader mImageLoader; nsHTMLImageLoader mImageLoader;
nsHTMLImageLoader * mLowSrcImageLoader; nsHTMLImageLoader * mLowSrcImageLoader;