Bug 589469 - Notify nsImageLoadingContent when its document switches.r+sr=bz,a=blocking-beta-5
--- a/content/base/public/nsIImageLoadingContent.idl
+++ b/content/base/public/nsIImageLoadingContent.idl
@@ -36,16 +36,17 @@
* ***** END LICENSE BLOCK ***** */
#include "imgIDecoderObserver.idl"
interface imgIRequest;
interface nsIChannel;
interface nsIStreamListener;
interface nsIURI;
+interface nsIDocument;
/**
* This interface represents a content node that loads images. The interface
* exists to allow getting information on the images that the content node
* loads and to allow registration of observers for the image loads.
*
* Implementors of this interface should handle all the mechanics of actually
* loading an image -- getting the URI, checking with content policies and
@@ -59,17 +60,17 @@ interface nsIURI;
* observers to check which request they are getting notifications for.
*
* Observers added in mid-load will not get any notifications they
* missed. We should NOT freeze this interface without considering
* this issue. (It could be that the image status on imgIRequest is
* sufficient, when combined with the imageBlockingStatus information.)
*/
-[scriptable, uuid(e036857e-3417-4812-a5f2-89668a616781)]
+[scriptable, uuid(7974082c-3267-4ab1-96fa-bd47d7e3a093)]
interface nsIImageLoadingContent : imgIDecoderObserver
{
/**
* Request types. Image loading content nodes attempt to do atomic
* image changes when the image url is changed. This means that
* when the url changes the new image load will start, but the old
* image will remain the "current" request until the new image is
* fully loaded. At that point, the old "current" request will be
@@ -169,10 +170,14 @@ interface nsIImageLoadingContent : imgID
void forceReload();
/**
* Enables/disables image state forcing. When |aForce| is PR_TRUE, we force
* nsImageLoadingContent::ImageState() to return |aState|. Call again with |aForce|
* as PR_FALSE to revert ImageState() to its original behaviour.
*/
void forceImageState(in boolean aForce, in long aState);
-
+
+ /**
+ * We need to be notified when our document changes.
+ */
+ [noscript, notxpcom] void NotifyOwnerDocumentChanged(in nsIDocument aOldDoc);
};
--- a/content/base/src/nsImageLoadingContent.cpp
+++ b/content/base/src/nsImageLoadingContent.cpp
@@ -550,16 +550,34 @@ NS_IMETHODIMP nsImageLoadingContent::For
return LoadImage(currentURI, PR_TRUE, PR_TRUE, nsnull, nsIRequest::VALIDATE_ALWAYS);
}
/*
* Non-interface methods
*/
+void
+nsImageLoadingContent::NotifyOwnerDocumentChanged(nsIDocument *aOldDoc)
+{
+ // If we had a document before, unregister ourselves with it.
+ if (aOldDoc) {
+ if (mCurrentRequest)
+ aOldDoc->RemoveImage(mCurrentRequest);
+ if (mPendingRequest)
+ aOldDoc->RemoveImage(mPendingRequest);
+ }
+
+ // Re-track the images
+ if (mCurrentRequest)
+ TrackImage(mCurrentRequest);
+ if (mPendingRequest)
+ TrackImage(mPendingRequest);
+}
+
nsresult
nsImageLoadingContent::LoadImage(const nsAString& aNewURI,
PRBool aForce,
PRBool aNotify)
{
// First, get a document (needed for security checks and the like)
nsIDocument* doc = GetOurDocument();
if (!doc) {
--- a/content/base/src/nsNodeUtils.cpp
+++ b/content/base/src/nsNodeUtils.cpp
@@ -55,16 +55,17 @@
#ifdef MOZ_XUL
#include "nsXULElement.h"
#endif
#include "nsBindingManager.h"
#include "nsGenericHTMLElement.h"
#ifdef MOZ_MEDIA
#include "nsHTMLMediaElement.h"
#endif // MOZ_MEDIA
+#include "nsImageLoadingContent.h"
using namespace mozilla::dom;
// This macro expects the ownerDocument of content_ to be in scope as
// |nsIDocument* doc|
#define IMPL_MUTATION_NOTIFICATION(func_, content_, params_) \
PR_BEGIN_MACRO \
nsINode* node = content_; \
@@ -525,16 +526,23 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aNode));
if (domMediaElem) {
nsHTMLMediaElement* mediaElem = static_cast<nsHTMLMediaElement*>(aNode);
mediaElem->NotifyOwnerDocumentActivityChanged();
}
}
#endif
+ // nsImageLoadingContent needs to know when its document changes
+ if (oldDoc != newDoc) {
+ nsCOMPtr<nsIImageLoadingContent> imageContent(do_QueryInterface(aNode));
+ if (imageContent)
+ imageContent->NotifyOwnerDocumentChanged(oldDoc);
+ }
+
if (elem) {
elem->RecompileScriptEventListeners();
}
if (aCx) {
nsIXPConnect *xpc = nsContentUtils::XPConnect();
if (xpc) {
nsCOMPtr<nsIXPConnectJSObjectHolder> oldWrapper;