diff --git a/mozilla/content/base/public/nsIImageLoadingContent.idl b/mozilla/content/base/public/nsIImageLoadingContent.idl index c8f0d9581e9..833b3d5a34f 100644 --- a/mozilla/content/base/public/nsIImageLoadingContent.idl +++ b/mozilla/content/base/public/nsIImageLoadingContent.idl @@ -39,6 +39,8 @@ #include "imgIDecoderObserver.idl" interface imgIRequest; +interface nsIChannel; +interface nsIStreamListener; /** * This interface represents a content node that loads images. The interface @@ -139,6 +141,20 @@ interface nsIImageLoadingContent : imgIDecoderObserver */ long getRequestType(in imgIRequest aRequest); + /** + * loadImageWithChannel allows data from an existing channel to be + * used as the image data for this content node. + * + * @param aChannel the channel that will deliver the data + * + * @return a stream listener to pump the image data into + * + * @see imgILoader::loadImageWithChannel + * + * @throws NS_ERROR_NULL_POINTER if aChannel is null + */ + nsIStreamListener loadImageWithChannel(in nsIChannel aChannel); + /** * ImageURIChanged is called when the appropriate attributes (eg * 'src' for tags) change. The string passed in is the new @@ -148,5 +164,5 @@ interface nsIImageLoadingContent : imgIDecoderObserver // XXXbz and do everything from frames, not content. // XXXbz Once those are moved to content, this method should become // XXXbz a protected method on nsImageLoadingContent! - void imageURIChanged(in AString aNewURI); + [noscript] void imageURIChanged(in AString aNewURI); }; diff --git a/mozilla/content/base/src/nsImageLoadingContent.cpp b/mozilla/content/base/src/nsImageLoadingContent.cpp index 21d7abe2a06..024821ccffa 100644 --- a/mozilla/content/base/src/nsImageLoadingContent.cpp +++ b/mozilla/content/base/src/nsImageLoadingContent.cpp @@ -60,6 +60,9 @@ #include "nsIPresShell.h" #include "nsGUIEvent.h" +#include "nsIChannel.h" +#include "nsIStreamListener.h" + nsImageLoadingContent::nsImageLoadingContent() : mObserverList(nsnull), mLoadingEnabled(PR_TRUE), @@ -181,7 +184,7 @@ nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest, } /* - * nsIImageLoadingElement impl + * nsIImageLoadingContent impl */ NS_IMETHODIMP @@ -309,6 +312,33 @@ nsImageLoadingContent::GetRequestType(imgIRequest* aRequest, return NS_ERROR_UNEXPECTED; } +NS_IMETHODIMP +nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel, + nsIStreamListener** aListener) +{ + NS_PRECONDITION(aListener, "null out param"); + + NS_ENSURE_ARG_POINTER(aChannel); + + // XXX what should we do with content policies here, if anything? + // Shouldn't that be done before the start of the load? + + // Get the image loader... + nsresult rv; + nsCOMPtr loader = do_GetService("@mozilla.org/image/loader;1", &rv); + NS_ENSURE_TRUE(loader, rv); + + nsCOMPtr doc; + rv = GetOurDocument(getter_AddRefs(doc)); + NS_ENSURE_TRUE(doc, rv); + + CancelImageRequests(NS_ERROR_IMAGE_SRC_CHANGED); + + nsCOMPtr & req = mCurrentRequest ? mPendingRequest : mCurrentRequest; + + return loader->LoadImageWithChannel(aChannel, this, doc, aListener, getter_AddRefs(req)); +} + // XXX This should be a protected method, not an interface method!!! NS_IMETHODIMP nsImageLoadingContent::ImageURIChanged(const nsAString& aNewURI) { diff --git a/mozilla/content/html/document/src/nsImageDocument.cpp b/mozilla/content/html/document/src/nsImageDocument.cpp index 7c158de4302..0841b944625 100644 --- a/mozilla/content/html/document/src/nsImageDocument.cpp +++ b/mozilla/content/html/document/src/nsImageDocument.cpp @@ -41,6 +41,7 @@ #include "nsRect.h" #include "nsHTMLDocument.h" #include "nsIImageDocument.h" +#include "nsIImageLoadingContent.h" #include "nsGenericHTMLElement.h" #include "nsIDOMHTMLImageElement.h" #include "nsIDOMEvent.h" @@ -122,7 +123,6 @@ protected: nsCOMPtr mStringBundle; nsCOMPtr mImageElement; - nsCOMPtr mImageRequest; nscoord mVisibleWidth; nscoord mVisibleHeight; @@ -154,19 +154,16 @@ NS_IMETHODIMP ImageListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt) { nsImageDocument *imgDoc = (nsImageDocument*)mDocument.get(); - NS_PRECONDITION(!imgDoc->mImageRequest, "OnStartRequest called twice!"); nsCOMPtr channel = do_QueryInterface(request); if (!channel) { return NS_ERROR_FAILURE; } - nsCOMPtr il(do_GetService("@mozilla.org/image/loader;1")); - nsCOMPtr docSupports; - CallQueryInterface(imgDoc, NS_STATIC_CAST(nsISupports**, - getter_AddRefs(docSupports))); - il->LoadImageWithChannel(channel, imgDoc, docSupports, - getter_AddRefs(mNextStream), - getter_AddRefs(imgDoc->mImageRequest)); + nsCOMPtr imageLoader = do_QueryInterface(imgDoc->mImageElement); + NS_ENSURE_TRUE(imageLoader, NS_ERROR_UNEXPECTED); + + imageLoader->AddObserver(imgDoc); + imageLoader->LoadImageWithChannel(channel, getter_AddRefs(mNextStream)); return nsMediaDocumentStreamListener::OnStartRequest(request, ctxt); } @@ -175,7 +172,13 @@ NS_IMETHODIMP ImageListener::OnStopRequest(nsIRequest* request, nsISupports *ctxt, nsresult status) { - ((nsImageDocument*) mDocument.get())->UpdateTitle(); + nsImageDocument *imgDoc = (nsImageDocument*)mDocument.get(); + imgDoc->UpdateTitle(); + + nsCOMPtr imageLoader = do_QueryInterface(imgDoc->mImageElement); + NS_ENSURE_TRUE(imageLoader, NS_ERROR_UNEXPECTED); + + imageLoader->RemoveObserver(imgDoc); return nsMediaDocumentStreamListener::OnStopRequest(request, ctxt, status); } @@ -194,9 +197,6 @@ nsImageDocument::nsImageDocument() nsImageDocument::~nsImageDocument() { - if (mImageRequest) { - mImageRequest->Cancel(NS_ERROR_FAILURE); - } } NS_IMPL_ADDREF_INHERITED(nsImageDocument, nsMediaDocument) @@ -265,15 +265,6 @@ NS_IMETHODIMP nsImageDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject) { if (!aScriptGlobalObject) { - // If the global object is being set to null, then it means we are going - // away soon. Drop our ref to imgRequest so that we don't end up leaking - // due to cycles through imgLib. This should not be really necessary - // anymore, but it's a belt-and-suspenders thing. - if (mImageRequest) { - mImageRequest->Cancel(NS_ERROR_FAILURE); - mImageRequest = nsnull; - } - if (mImageResizingEnabled) { nsCOMPtr target = do_QueryInterface(mImageElement); target->RemoveEventListener(NS_LITERAL_STRING("click"), this, PR_FALSE); @@ -283,6 +274,9 @@ nsImageDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObjec target->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, PR_FALSE); } + + // drop the ref to mImageElement, in case it has a ref to us + mImageElement = nsnull; } // Set the script global object on the superclass before doing @@ -504,13 +498,17 @@ nsImageDocument::CreateSyntheticDocument() } image->SetDocument(this, PR_FALSE, PR_TRUE); mImageElement = do_QueryInterface(image); + nsCOMPtr imageLoader = do_QueryInterface(image); + NS_ENSURE_TRUE(imageLoader, NS_ERROR_UNEXPECTED); nsCAutoString src; mDocumentURL->GetSpec(src); NS_ConvertUTF8toUCS2 srcString(src); - + // Make sure not to start the image load from here... + imageLoader->SetLoadingEnabled(PR_FALSE); image->SetAttr(kNameSpaceID_None, nsHTMLAtoms::src, srcString, PR_FALSE); + imageLoader->SetLoadingEnabled(PR_TRUE); if (mStringBundle) { const PRUnichar* formatString[1] = { srcString.get() }; @@ -606,9 +604,16 @@ nsImageDocument::UpdateTitle() widthStr.AppendInt(mImageWidth); heightStr.AppendInt(mImageHeight); - if (mImageRequest) { + nsCOMPtr imageRequest; + nsCOMPtr imageLoader = do_QueryInterface(mImageElement); + if (imageLoader) { + imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST, + getter_AddRefs(imageRequest)); + } + + if (imageRequest) { nsXPIDLCString mimeType; - mImageRequest->GetMimeType(getter_Copies(mimeType)); + imageRequest->GetMimeType(getter_Copies(mimeType)); ToUpperCase(mimeType); nsXPIDLCString::const_iterator start, end; mimeType.BeginReading(start);