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);