Back out d3b8c0394c5e, 701372c96a92, f2c16b13cf65, 367ff8c94636 (bug 683290, bug 684919, bug 685516) for Android reftest failures

This commit is contained in:
Matt Brubeck 2011-10-10 13:45:13 -07:00
parent 4151b38db0
commit 57442b74d1
19 changed files with 136 additions and 532 deletions

View File

@ -65,7 +65,7 @@ interface nsIDocument;
* sufficient, when combined with the imageBlockingStatus information.)
*/
[scriptable, uuid(4bf1a7c5-6edb-4191-a257-e31a90f6aa85)]
[scriptable, uuid(95c74255-df9a-4060-b5a0-0d111fcafe08)]
interface nsIImageLoadingContent : imgIDecoderObserver
{
/**
@ -175,4 +175,9 @@ interface nsIImageLoadingContent : imgIDecoderObserver
* as PR_FALSE to revert ImageState() to its original behaviour.
*/
void forceImageState(in boolean aForce, in unsigned long long aState);
/**
* We need to be notified when our document changes.
*/
[noscript, notxpcom] void NotifyOwnerDocumentChanged(in nsIDocument aOldDoc);
};

View File

@ -67,10 +67,6 @@ public:
}
// nsIContent overrides
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers);
virtual void UnbindFromTree(bool aDeep, bool aNullParent);
virtual nsEventStates IntrinsicState() const;
private:
@ -103,28 +99,6 @@ nsGenConImageContent::~nsGenConImageContent()
DestroyImageLoadingContent();
}
nsresult
nsGenConImageContent::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers)
{
nsresult rv;
rv = nsXMLElement::BindToTree(aDocument, aParent, aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
aCompileEventHandlers);
return NS_OK;
}
void
nsGenConImageContent::UnbindFromTree(bool aDeep, bool aNullParent)
{
nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
nsXMLElement::UnbindFromTree(aDeep, aNullParent);
}
nsEventStates
nsGenConImageContent::IntrinsicState() const
{

View File

@ -132,7 +132,7 @@ nsImageLoadingContent::DestroyImageLoadingContent()
nsImageLoadingContent::~nsImageLoadingContent()
{
NS_ASSERTION(!mCurrentRequest.Ptr() && !mPendingRequest.Ptr(),
NS_ASSERTION(!mCurrentRequest && !mPendingRequest,
"DestroyImageLoadingContent not called");
NS_ASSERTION(!mObserverList.mObserver && !mObserverList.mNext,
"Observers still registered?");
@ -181,7 +181,7 @@ nsImageLoadingContent::OnStartDecode(imgIRequest* aRequest)
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
// Onload blocking. This only applies for the current request.
if (aRequest == mCurrentRequest.Ptr()) {
if (aRequest == mCurrentRequest) {
// Determine whether this is a background request (this can be the case
// with multipart/x-mixed-replace images, for example).
@ -243,7 +243,7 @@ nsImageLoadingContent::OnStopFrame(imgIRequest* aRequest,
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
// If we're blocking a load, one frame is enough
if (aRequest == mCurrentRequest.Ptr())
if (aRequest == mCurrentRequest)
SetBlockingOnload(PR_FALSE);
LOOP_OVER_OBSERVERS(OnStopFrame(aRequest, aFrame));
@ -262,7 +262,7 @@ nsImageLoadingContent::OnStopContainer(imgIRequest* aRequest,
// until we fix bug 505385. OnStopContainer is actually going away at that
// point. So for now we take advantage of the fact that OnStopContainer is
// always fired in the decoders at the same time as OnStopDecode.
if (aRequest == mCurrentRequest.Ptr())
if (aRequest == mCurrentRequest)
SetBlockingOnload(PR_FALSE);
LOOP_OVER_OBSERVERS(OnStopContainer(aRequest, aContainer));
@ -282,8 +282,7 @@ nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest,
// We should definitely have a request here
NS_ABORT_IF_FALSE(aRequest, "no request?");
NS_PRECONDITION(aRequest == mCurrentRequest.Ptr() ||
aRequest == mPendingRequest.Ptr(),
NS_PRECONDITION(aRequest == mCurrentRequest || aRequest == mPendingRequest,
"Unknown request");
LOOP_OVER_OBSERVERS(OnStopDecode(aRequest, aStatus, aStatusArg));
@ -294,19 +293,18 @@ nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest,
AutoStateChanger changer(this, PR_TRUE);
// If the pending request is loaded, switch to it.
if (aRequest == mPendingRequest.Ptr()) {
PrepareCurrentRequest();
mCurrentRequest = mPendingRequest;
mPendingRequest.Clear();
if (aRequest == mPendingRequest) {
PrepareCurrentRequest() = mPendingRequest;
mPendingRequest = nsnull;
mCurrentRequestNeedsResetAnimation = mPendingRequestNeedsResetAnimation;
mPendingRequestNeedsResetAnimation = PR_FALSE;
}
NS_ABORT_IF_FALSE(aRequest == mCurrentRequest.Ptr(),
NS_ABORT_IF_FALSE(aRequest == mCurrentRequest,
"One way or another, we should be current by now");
if (mCurrentRequestNeedsResetAnimation) {
nsCOMPtr<imgIContainer> container;
mCurrentRequest.Ptr()->GetImage(getter_AddRefs(container));
mCurrentRequest->GetImage(getter_AddRefs(container));
if (container)
container->ResetAnimation();
mCurrentRequestNeedsResetAnimation = PR_FALSE;
@ -327,9 +325,7 @@ nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest,
// decoding, so we can't wait for them to finish. See bug 512435.
// We can only do this if we have a presshell
// XXXkhuey should this be GetOurCurrentDoc? Decoding if we're not in
// the document seems silly.
nsIDocument* doc = GetOurOwnerDoc();
nsIDocument* doc = GetOurDocument();
nsIPresShell* shell = doc ? doc->GetShell() : nsnull;
if (shell) {
@ -350,7 +346,7 @@ nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest,
// If we're requesting a decode, do it
if (doRequestDecode)
mCurrentRequest.Ptr()->RequestDecode();
mCurrentRequest->RequestDecode();
}
// Fire the appropriate DOM event.
@ -490,10 +486,10 @@ nsImageLoadingContent::GetRequest(PRInt32 aRequestType,
{
switch(aRequestType) {
case CURRENT_REQUEST:
*aRequest = mCurrentRequest.Ptr();
*aRequest = mCurrentRequest;
break;
case PENDING_REQUEST:
*aRequest = mPendingRequest.Ptr();
*aRequest = mPendingRequest;
break;
default:
NS_ERROR("Unknown request type");
@ -514,12 +510,12 @@ nsImageLoadingContent::GetRequestType(imgIRequest* aRequest,
NS_PRECONDITION(aRequestType, "Null out param");
if (aRequest == mCurrentRequest.Ptr()) {
if (aRequest == mCurrentRequest) {
*aRequestType = CURRENT_REQUEST;
return NS_OK;
}
if (aRequest == mPendingRequest.Ptr()) {
if (aRequest == mPendingRequest) {
*aRequestType = PENDING_REQUEST;
return NS_OK;
}
@ -532,8 +528,8 @@ nsImageLoadingContent::GetRequestType(imgIRequest* aRequest,
NS_IMETHODIMP
nsImageLoadingContent::GetCurrentURI(nsIURI** aURI)
{
if (mCurrentRequest.Ptr()) {
return mCurrentRequest.Ptr()->GetURI(aURI);
if (mCurrentRequest) {
return mCurrentRequest->GetURI(aURI);
}
if (!mCurrentURI) {
@ -554,7 +550,7 @@ nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel,
return NS_ERROR_NULL_POINTER;
}
nsCOMPtr<nsIDocument> doc = GetOurOwnerDoc();
nsCOMPtr<nsIDocument> doc = GetOurDocument();
if (!doc) {
// Don't bother
return NS_OK;
@ -568,7 +564,7 @@ nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel,
AutoStateChanger changer(this, PR_TRUE);
// Do the load.
RequestWithState& req = PrepareNextRequest();
nsCOMPtr<imgIRequest>& req = PrepareNextRequest();
nsresult rv = nsContentUtils::GetImgLoader()->
LoadImageWithChannel(aChannel, this, doc, aListener,
getter_AddRefs(req));
@ -577,7 +573,7 @@ nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel,
} else {
// If we don't have a current URI, we might as well store this URI so people
// know what we tried (and failed) to load.
if (!mCurrentRequest.Ptr())
if (!mCurrentRequest)
aChannel->GetURI(getter_AddRefs(mCurrentURI));
FireEvent(NS_LITERAL_STRING("error"));
return rv;
@ -602,13 +598,29 @@ NS_IMETHODIMP nsImageLoadingContent::ForceReload()
* 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
TrackImage(mCurrentRequest);
TrackImage(mPendingRequest);
}
nsresult
nsImageLoadingContent::LoadImage(const nsAString& aNewURI,
bool aForce,
bool aNotify)
{
// First, get a document (needed for security checks and the like)
nsIDocument* doc = GetOurOwnerDoc();
nsIDocument* doc = GetOurDocument();
if (!doc) {
// No reason to bother, I think...
return NS_OK;
@ -656,11 +668,11 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
return NS_OK;
}
NS_ASSERTION(!aDocument || aDocument == GetOurOwnerDoc(),
NS_ASSERTION(!aDocument || aDocument == GetOurDocument(),
"Bogus document passed in");
// First, get a document (needed for security checks and the like)
if (!aDocument) {
aDocument = GetOurOwnerDoc();
aDocument = GetOurDocument();
if (!aDocument) {
// No reason to bother, I think...
return NS_OK;
@ -716,7 +728,7 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
}
// Not blocked. Do the load.
RequestWithState& req = PrepareNextRequest();
nsCOMPtr<imgIRequest>& req = PrepareNextRequest();
nsresult rv;
rv = nsContentUtils::LoadImage(aNewURI, aDocument,
aDocument->NodePrincipal(),
@ -728,7 +740,7 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
} else {
// If we don't have a current URI, we might as well store this URI so people
// know what we tried (and failed) to load.
if (!mCurrentRequest.Ptr())
if (!mCurrentRequest)
mCurrentURI = aNewURI;
FireEvent(NS_LITERAL_STRING("error"));
return NS_OK;
@ -799,12 +811,12 @@ nsImageLoadingContent::UpdateImageState(bool aNotify)
mSuppressed = PR_TRUE;
} else if (mImageBlockingStatus == nsIContentPolicy::REJECT_TYPE) {
mUserDisabled = PR_TRUE;
} else if (!mCurrentRequest.Ptr()) {
} else if (!mCurrentRequest) {
// No current request means error, since we weren't disabled or suppressed
mBroken = PR_TRUE;
} else {
PRUint32 currentLoadStatus;
nsresult rv = mCurrentRequest.Ptr()->GetImageStatus(&currentLoadStatus);
nsresult rv = mCurrentRequest->GetImageStatus(&currentLoadStatus);
if (NS_FAILED(rv) || (currentLoadStatus & imgIRequest::STATUS_ERROR)) {
mBroken = PR_TRUE;
} else if (!(currentLoadStatus & imgIRequest::STATUS_SIZE_AVAILABLE)) {
@ -836,7 +848,7 @@ nsImageLoadingContent::UseAsPrimaryRequest(imgIRequest* aRequest,
ClearCurrentRequest(NS_BINDING_ABORTED);
// Clone the request we were given.
RequestWithState& req = PrepareNextRequest();
nsCOMPtr<imgIRequest>& req = PrepareNextRequest();;
nsresult rv = aRequest->Clone(this, getter_AddRefs(req));
if (NS_SUCCEEDED(rv))
TrackImage(req);
@ -847,7 +859,7 @@ nsImageLoadingContent::UseAsPrimaryRequest(imgIRequest* aRequest,
}
nsIDocument*
nsImageLoadingContent::GetOurOwnerDoc()
nsImageLoadingContent::GetOurDocument()
{
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
NS_ENSURE_TRUE(thisContent, nsnull);
@ -855,15 +867,6 @@ nsImageLoadingContent::GetOurOwnerDoc()
return thisContent->GetOwnerDoc();
}
nsIDocument*
nsImageLoadingContent::GetOurCurrentDoc()
{
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
NS_ENSURE_TRUE(thisContent, nsnull);
return thisContent->GetCurrentDoc();
}
nsresult
nsImageLoadingContent::StringToURI(const nsAString& aSpec,
nsIDocument* aDocument,
@ -904,19 +907,16 @@ nsImageLoadingContent::FireEvent(const nsAString& aEventType)
return NS_OK;
}
nsImageLoadingContent::RequestWithState&
nsCOMPtr<imgIRequest>&
nsImageLoadingContent::PrepareNextRequest()
{
// If we don't have a usable current request, get rid of any half-baked
// request that might be sitting there and make this one current.
if (!HaveSize(mCurrentRequest.Ptr())) {
PrepareCurrentRequest();
return mCurrentRequest;
}
if (!HaveSize(mCurrentRequest))
return PrepareCurrentRequest();
// Otherwise, make it pending.
PreparePendingRequest();
return mPendingRequest;
return PreparePendingRequest();
}
void
@ -935,7 +935,7 @@ nsImageLoadingContent::SetBlockedRequest(nsIURI* aURI, PRInt16 aContentDecision)
// For the blocked case, we only want to cancel the existing current request
// if size is not available. bz says the web depends on this behavior.
if (!HaveSize(mCurrentRequest.Ptr())) {
if (!HaveSize(mCurrentRequest)) {
mImageBlockingStatus = aContentDecision;
ClearCurrentRequest(NS_ERROR_IMAGE_BLOCKED);
@ -946,7 +946,7 @@ nsImageLoadingContent::SetBlockedRequest(nsIURI* aURI, PRInt16 aContentDecision)
}
}
void
nsCOMPtr<imgIRequest>&
nsImageLoadingContent::PrepareCurrentRequest()
{
// Blocked images go through SetBlockedRequest, which is a separate path. For
@ -957,21 +957,27 @@ nsImageLoadingContent::PrepareCurrentRequest()
ClearCurrentRequest(NS_ERROR_IMAGE_SRC_CHANGED);
mCurrentRequestNeedsResetAnimation = mNewRequestsWillNeedAnimationReset;
// Return a reference.
return mCurrentRequest;
}
void
nsCOMPtr<imgIRequest>&
nsImageLoadingContent::PreparePendingRequest()
{
// Get rid of anything that was there previously.
ClearPendingRequest(NS_ERROR_IMAGE_SRC_CHANGED);
mPendingRequestNeedsResetAnimation = mNewRequestsWillNeedAnimationReset;
// Return a reference.
return mPendingRequest;
}
void
nsImageLoadingContent::ClearCurrentRequest(nsresult aReason)
{
if (!mCurrentRequest.Ptr()) {
if (!mCurrentRequest) {
// Even if we didn't have a current request, we might have been keeping
// a URI as a placeholder for a failed load. Clear that now.
mCurrentURI = nsnull;
@ -982,8 +988,8 @@ nsImageLoadingContent::ClearCurrentRequest(nsresult aReason)
// Clean up the request.
UntrackImage(mCurrentRequest);
mCurrentRequest.Ptr()->CancelAndForgetObserver(aReason);
mCurrentRequest.Clear();
mCurrentRequest->CancelAndForgetObserver(aReason);
mCurrentRequest = nsnull;
mCurrentRequestNeedsResetAnimation = PR_FALSE;
// We only block onload during the decoding of "current" images. This one is
@ -994,7 +1000,7 @@ nsImageLoadingContent::ClearCurrentRequest(nsresult aReason)
void
nsImageLoadingContent::ClearPendingRequest(nsresult aReason)
{
if (!mPendingRequest.Ptr())
if (!mPendingRequest)
return;
// Push a null JSContext on the stack so that code that runs within
@ -1004,8 +1010,8 @@ nsImageLoadingContent::ClearPendingRequest(nsresult aReason)
pusher.PushNull();
UntrackImage(mPendingRequest);
mPendingRequest.Ptr()->CancelAndForgetObserver(aReason);
mPendingRequest.Clear();
mPendingRequest->CancelAndForgetObserver(aReason);
mPendingRequest = nsnull;
mPendingRequestNeedsResetAnimation = PR_FALSE;
}
@ -1030,7 +1036,7 @@ nsImageLoadingContent::SetBlockingOnload(bool aBlocking)
return;
// Get the document
nsIDocument* doc = GetOurOwnerDoc();
nsIDocument* doc = GetOurDocument();
if (doc) {
// Take the appropriate action
@ -1044,68 +1050,30 @@ nsImageLoadingContent::SetBlockingOnload(bool aBlocking)
}
}
void
nsImageLoadingContent::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers)
{
// We may be entering the document, so if our image should be tracked,
// track it.
if (!aDocument)
return;
if (mCurrentRequest.Flag())
aDocument->AddImage(mCurrentRequest.Ptr());
if (mPendingRequest.Flag())
aDocument->AddImage(mPendingRequest.Ptr());
}
void
nsImageLoadingContent::UnbindFromTree(bool aDeep, bool aNullParent)
{
// We may be leaving the document, so if our image is tracked, untrack it.
nsCOMPtr<nsIDocument> doc = GetOurCurrentDoc();
if (!doc)
return;
if (mCurrentRequest.Flag())
doc->RemoveImage(mCurrentRequest.Ptr());
if (mPendingRequest.Flag())
doc->RemoveImage(mPendingRequest.Ptr());
}
nsresult
nsImageLoadingContent::TrackImage(RequestWithState& aImage)
nsImageLoadingContent::TrackImage(imgIRequest* aImage)
{
if (!aImage.Ptr())
if (!aImage)
return NS_OK;
NS_ASSERTION(!aImage.Flag(), "Already tracked!?");
aImage.SetFlag(true);
nsIDocument* doc = GetOurCurrentDoc();
nsIDocument* doc = GetOurDocument();
if (doc)
return doc->AddImage(aImage.Ptr());
return doc->AddImage(aImage);
return NS_OK;
}
nsresult
nsImageLoadingContent::UntrackImage(RequestWithState& aImage)
nsImageLoadingContent::UntrackImage(imgIRequest* aImage)
{
if (!aImage.Ptr())
if (!aImage)
return NS_OK;
NS_ASSERTION(aImage.Flag(), "Not already tracked!?");
aImage.SetFlag(false);
// If GetOurCurrentDoc() returns null here, we've outlived our document.
// If GetOurDocument() returns null here, we've outlived our document.
// That's fine, because the document empties out the tracker and unlocks
// all locked images on destruction.
nsIDocument* doc = GetOurCurrentDoc();
nsIDocument* doc = GetOurDocument();
if (doc)
return doc->RemoveImage(aImage.Ptr());
return doc->RemoveImage(aImage);
return NS_OK;
}
@ -1113,7 +1081,7 @@ nsImageLoadingContent::UntrackImage(RequestWithState& aImage)
void
nsImageLoadingContent::CreateStaticImageClone(nsImageLoadingContent* aDest) const
{
aDest->mCurrentRequest.SetPtr(nsContentUtils::GetStaticRequest(mCurrentRequest.Ptr()));
aDest->mCurrentRequest = nsContentUtils::GetStaticRequest(mCurrentRequest);
aDest->TrackImage(aDest->mCurrentRequest);
aDest->mForcedImageState = mForcedImageState;
aDest->mImageBlockingStatus = mImageBlockingStatus;

View File

@ -53,7 +53,6 @@
#include "nsContentUtils.h" // NS_CONTENT_DELETE_LIST_MEMBER
#include "nsString.h"
#include "nsEventStates.h"
#include "mozilla/COMPtrAndFlag.h"
class nsIURI;
class nsIDocument;
@ -139,14 +138,13 @@ protected:
nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL);
/**
* helpers to get the document for this content (from the nodeinfo
* and such). Not named GetOwnerDoc/GetCurrentDoc to prevent ambiguous
* method names in subclasses
* helper to get the document for this content (from the nodeinfo
* and such). Not named GetDocument to prevent ambiguous method
* names in subclasses
*
* @return the document we belong to
*/
nsIDocument* GetOurOwnerDoc();
nsIDocument* GetOurCurrentDoc();
nsIDocument* GetOurDocument();
/**
* CancelImageRequests is called by subclasses when they want to
@ -187,11 +185,6 @@ protected:
*/
virtual CORSMode GetCORSMode();
// Subclasses are *required* to call BindToTree/UnbindFromTree.
void BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent, bool aCompileEventHandlers);
void UnbindFromTree(bool aDeep, bool aNullParent);
private:
/**
* Struct used to manage the image observers.
@ -279,18 +272,13 @@ protected:
void CreateStaticImageClone(nsImageLoadingContent* aDest) const;
// The flag on these pointers tells whether or not the image "should" be
// tracked by the document. The only situation in which we should be
// tracked but aren't is when we are not in a document.
typedef mozilla::COMPtrAndFlag<imgIRequest> RequestWithState;
/**
* Prepare and returns a reference to the "next request". If there's already
* a _usable_ current request (one with SIZE_AVAILABLE), this request is
* "pending" until it becomes usable. Otherwise, this becomes the current
* request.
*/
RequestWithState& PrepareNextRequest();
nsCOMPtr<imgIRequest>& PrepareNextRequest();
/**
* Called when we would normally call PrepareNextRequest(), but the request was
@ -299,13 +287,14 @@ protected:
void SetBlockedRequest(nsIURI* aURI, PRInt16 aContentDecision);
/**
* Cleans up and cancels the appropriate request. Note that if you just want
* Returns a COMPtr reference to the current/pending image requests, cleaning
* up and canceling anything that was there before. Note that if you just want
* to get rid of one of the requests, you should call
* Clear*Request(NS_BINDING_ABORTED) instead, since it passes a more appropriate
* aReason than Prepare*Request() does (NS_ERROR_IMAGE_SRC_CHANGED).
*/
void PrepareCurrentRequest();
void PreparePendingRequest();
nsCOMPtr<imgIRequest>& PrepareCurrentRequest();
nsCOMPtr<imgIRequest>& PreparePendingRequest();
/**
* Cancels and nulls-out the "current" and "pending" requests if they exist.
@ -324,12 +313,12 @@ protected:
*
* No-op if aImage is null.
*/
nsresult TrackImage(RequestWithState& aImage);
nsresult UntrackImage(RequestWithState& aImage);
nsresult TrackImage(imgIRequest* aImage);
nsresult UntrackImage(imgIRequest* aImage);
/* MEMBERS */
RequestWithState mCurrentRequest;
RequestWithState mPendingRequest;
nsCOMPtr<imgIRequest> mCurrentRequest;
nsCOMPtr<imgIRequest> mPendingRequest;
// If the image was blocked or if there was an error loading, it's nice to
// still keep track of what the URI was despite not having an imgIRequest.

View File

@ -62,6 +62,7 @@
#ifdef MOZ_MEDIA
#include "nsHTMLMediaElement.h"
#endif // MOZ_MEDIA
#include "nsImageLoadingContent.h"
#include "jsgc.h"
#include "nsWrapperCacheInlines.h"
@ -586,6 +587,13 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
}
#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();
}

View File

@ -965,7 +965,7 @@ nsObjectLoadingContent::HasNewFrame(nsIObjectFrame* aFrame)
// When in a plugin document, the document will take care of calling
// instantiate
nsCOMPtr<nsIPluginDocument> pDoc (do_QueryInterface(GetOurOwnerDoc()));
nsCOMPtr<nsIPluginDocument> pDoc (do_QueryInterface(GetOurDocument()));
if (pDoc) {
bool willHandleInstantiation;
pDoc->GetWillHandleInstantiation(&willHandleInstantiation);

View File

@ -144,7 +144,6 @@ public:
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers);
virtual void UnbindFromTree(bool aDeep, bool aNullParent);
virtual nsEventStates IntrinsicState() const;
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
@ -254,12 +253,12 @@ nsHTMLImageElement::GetComplete(bool* aComplete)
NS_PRECONDITION(aComplete, "Null out param!");
*aComplete = PR_TRUE;
if (!mCurrentRequest.Ptr()) {
if (!mCurrentRequest) {
return NS_OK;
}
PRUint32 status;
mCurrentRequest.Ptr()->GetImageStatus(&status);
mCurrentRequest->GetImageStatus(&status);
*aComplete =
(status &
(imgIRequest::STATUS_LOAD_COMPLETE | imgIRequest::STATUS_ERROR)) != 0;
@ -282,8 +281,8 @@ nsHTMLImageElement::GetWidthHeight()
} else {
const nsAttrValue* value;
nsCOMPtr<imgIContainer> image;
if (mCurrentRequest.Ptr()) {
mCurrentRequest.Ptr()->GetImage(getter_AddRefs(image));
if (mCurrentRequest) {
mCurrentRequest->GetImage(getter_AddRefs(image));
}
if ((value = GetParsedAttr(nsGkAtoms::width)) &&
@ -530,9 +529,6 @@ nsHTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
aCompileEventHandlers);
if (HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
// FIXME: Bug 660963 it would be nice if we could just have
// ClearBrokenState update our state and do it fast...
@ -550,13 +546,6 @@ nsHTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
return rv;
}
void
nsHTMLImageElement::UnbindFromTree(bool aDeep, bool aNullParent)
{
nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
}
void
nsHTMLImageElement::MaybeLoadImage()
{
@ -614,12 +603,12 @@ nsHTMLImageElement::GetNaturalHeight(PRUint32* aNaturalHeight)
*aNaturalHeight = 0;
if (!mCurrentRequest.Ptr()) {
if (!mCurrentRequest) {
return NS_OK;
}
nsCOMPtr<imgIContainer> image;
mCurrentRequest.Ptr()->GetImage(getter_AddRefs(image));
mCurrentRequest->GetImage(getter_AddRefs(image));
if (!image) {
return NS_OK;
}
@ -638,12 +627,12 @@ nsHTMLImageElement::GetNaturalWidth(PRUint32* aNaturalWidth)
*aNaturalWidth = 0;
if (!mCurrentRequest.Ptr()) {
if (!mCurrentRequest) {
return NS_OK;
}
nsCOMPtr<imgIContainer> image;
mCurrentRequest.Ptr()->GetImage(getter_AddRefs(image));
mCurrentRequest->GetImage(getter_AddRefs(image));
if (!image) {
return NS_OK;
}

View File

@ -2320,9 +2320,6 @@ nsHTMLInputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
aCompileEventHandlers);
if (mType == NS_FORM_INPUT_IMAGE) {
// Our base URI may have changed; claim that our URI changed, and the
// nsImageLoadingContent will decide whether a new image load is warranted.
@ -2369,8 +2366,6 @@ nsHTMLInputElement::UnbindFromTree(bool aDeep, bool aNullParent)
WillRemoveFromRadioGroup();
}
nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
// GetCurrentDoc is returning nsnull so we can update the value

View File

@ -245,9 +245,6 @@ nsHTMLObjectElement::BindToTree(nsIDocument *aDocument,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
aCompileEventHandlers);
// If we already have all the children, start the load.
if (mIsDoneAddingChildren) {
void (nsHTMLObjectElement::*start)() = &nsHTMLObjectElement::StartObjectLoad;
@ -262,7 +259,6 @@ nsHTMLObjectElement::UnbindFromTree(bool aDeep,
bool aNullParent)
{
RemovedFromDocument();
nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
}

View File

@ -272,9 +272,6 @@ nsHTMLSharedObjectElement::BindToTree(nsIDocument *aDocument,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
aCompileEventHandlers);
// If we already have all the children, start the load.
if (mIsDoneAddingChildren) {
void (nsHTMLSharedObjectElement::*start)() =
@ -290,7 +287,6 @@ nsHTMLSharedObjectElement::UnbindFromTree(bool aDeep,
bool aNullParent)
{
RemovedFromDocument();
nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
}

View File

@ -5343,7 +5343,6 @@ public:
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers);
virtual void UnbindFromTree(bool aDeep, bool aNullParent);
virtual nsEventStates IntrinsicState() const;
// imgIDecoderObserver
@ -5501,9 +5500,6 @@ nsSVGFEImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
aCompileEventHandlers);
if (mStringAttributes[HREF].IsExplicitlySet()) {
// FIXME: Bug 660963 it would be nice if we could just have
// ClearBrokenState update our state and do it fast...
@ -5516,13 +5512,6 @@ nsSVGFEImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
return rv;
}
void
nsSVGFEImageElement::UnbindFromTree(bool aDeep, bool aNullParent)
{
nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
nsSVGFEImageElementBase::UnbindFromTree(aDeep, aNullParent);
}
nsEventStates
nsSVGFEImageElement::IntrinsicState() const
{

View File

@ -208,9 +208,6 @@ nsSVGImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
aCompileEventHandlers);
if (mStringAttributes[HREF].IsExplicitlySet()) {
// FIXME: Bug 660963 it would be nice if we could just have
// ClearBrokenState update our state and do it fast...
@ -223,13 +220,6 @@ nsSVGImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
return rv;
}
void
nsSVGImageElement::UnbindFromTree(bool aDeep, bool aNullParent)
{
nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
nsSVGImageElementBase::UnbindFromTree(aDeep, aNullParent);
}
nsEventStates
nsSVGImageElement::IntrinsicState() const
{

View File

@ -82,7 +82,6 @@ public:
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers);
virtual void UnbindFromTree(bool aDeep, bool aNullParent);
virtual nsEventStates IntrinsicState() const;

View File

@ -85,6 +85,7 @@ static PRLogModuleInfo *gCompressedImageAccountingLog = PR_NewLogModule ("Compre
// Tweakable progressive decoding parameters
static PRUint32 gDecodeBytesAtATime = 200000;
static PRUint32 gMaxMSBeforeYield = 400;
static PRUint32 gMaxBytesForSyncDecode = 150000;
void
RasterImage::SetDecodeBytesAtATime(PRUint32 aBytesAtATime)
@ -96,6 +97,11 @@ RasterImage::SetMaxMSBeforeYield(PRUint32 aMaxMS)
{
gMaxMSBeforeYield = aMaxMS;
}
void
RasterImage::SetMaxBytesForSyncDecode(PRUint32 aMaxBytes)
{
gMaxBytesForSyncDecode = aMaxBytes;
}
/* We define our own error checking macros here for 2 reasons:
*
@ -683,12 +689,10 @@ RasterImage::GetFrame(PRUint32 aWhichFrame,
nsresult rv = NS_OK;
PRUint32 desiredDecodeFlags = aFlags & DECODE_FLAGS_MASK;
if (mDecoded) {
// If we have decoded data, and it is not a perfect match for what we are
// looking for, we must discard to be able to generate the proper data.
PRUint32 desiredDecodeFlags = aFlags & DECODE_FLAGS_MASK;
if (desiredDecodeFlags != mFrameDecodeFlags) {
// if we can't discard, then we're screwed; we have no way
// to re-decode. Similarly if we aren't allowed to do a sync
@ -699,11 +703,11 @@ RasterImage::GetFrame(PRUint32 aWhichFrame,
return NS_ERROR_NOT_AVAILABLE;
ForceDiscard();
mFrameDecodeFlags = desiredDecodeFlags;
}
}
mFrameDecodeFlags = desiredDecodeFlags;
// If the caller requested a synchronous decode, do it
if (aFlags & FLAG_SYNC_DECODE) {
rv = SyncDecode();
@ -2382,12 +2386,13 @@ RasterImage::RequestDecode()
if (mBytesDecoded == mSourceData.Length())
return NS_OK;
// If we can do decoding now, do so. Small images will decode completely,
// large images will decode a bit and post themselves to the event loop
// to finish decoding.
if (!mDecoded && !mInDecoder && mHasSourceData)
return mWorker->Run();
// If it's a smallish image, it's not worth it to do things async
if (!mDecoded && !mInDecoder && mHasSourceData && (mSourceData.Length() < gMaxBytesForSyncDecode))
return SyncDecode();
// If we get this far, dispatch the worker. We do this instead of starting
// any immediate decoding to guarantee that all our decode notifications are
// dispatched asynchronously, and to ensure we stay responsive.
return mWorker->Dispatch();
}

View File

@ -88,6 +88,7 @@
#define DECODEONDRAW_PREF "image.mem.decodeondraw"
#define BYTESATATIME_PREF "image.mem.decode_bytes_at_a_time"
#define MAXMS_PREF "image.mem.max_ms_before_yield"
#define MAXBYTESFORSYNC_PREF "image.mem.max_bytes_for_sync_decode"
#define SVG_MIMETYPE "image/svg+xml"
using namespace mozilla;
@ -131,6 +132,11 @@ ReloadPrefs()
RasterImage::SetMaxMSBeforeYield(maxMS);
}
if (NS_SUCCEEDED(Preferences::GetInt(MAXBYTESFORSYNC_PREF,
&maxBytesForSync))) {
RasterImage::SetMaxBytesForSyncDecode(maxBytesForSync);
}
// Discard timeout
mozilla::imagelib::DiscardTracker::ReloadTimeout();
}

View File

@ -3276,6 +3276,9 @@ pref("image.mem.decode_bytes_at_a_time", 4096);
// The longest time we can spend in an iteration of an async decode
pref("image.mem.max_ms_before_yield", 5);
// The maximum source data size for which we auto sync decode
pref("image.mem.max_bytes_for_sync_decode", 150000);
// WebGL prefs
pref("webgl.force-enabled", false);
pref("webgl.disabled", false);

View File

@ -1,269 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Kyle Huey <me@kylehuey.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_PtrAndFlag_h__
#define mozilla_PtrAndFlag_h__
#include "nsCOMPtr.h"
#include "mozilla/Types.h"
namespace mozilla {
namespace please_dont_use_this_directly {
template <class T>
class COMPtrAndFlagGetterAddRefs;
}
// A class designed to allow stealing a bit from an nsCOMPtr.
template <class T>
class COMPtrAndFlag
{
// A RAII class that saves/restores the flag, allowing the COMPtr to be
// manipulated directly.
class AutoFlagPersister
{
public:
AutoFlagPersister(uintptr_t* aPtr)
: mPtr(aPtr), mFlag(*aPtr & 0x1)
{
if (mFlag)
*mPtr &= ~0x1;
}
~AutoFlagPersister()
{
if (mFlag)
*mPtr |= 0x1;
}
private:
uintptr_t *mPtr;
bool mFlag;
};
template <class U>
friend class please_dont_use_this_directly::COMPtrAndFlagGetterAddRefs;
public:
COMPtrAndFlag()
{
Set(nsnull, false);
}
COMPtrAndFlag(T* aPtr, bool aFlag)
{
Set(aPtr, aFlag);
}
COMPtrAndFlag(const nsQueryInterface aPtr, bool aFlag)
{
Set(aPtr, aFlag);
}
COMPtrAndFlag(const already_AddRefed<T>& aPtr, bool aFlag)
{
Set(aPtr, aFlag);
}
~COMPtrAndFlag()
{
// Make sure we unset the flag before nsCOMPtr's dtor tries to
// Release, or we might explode.
UnsetFlag();
}
COMPtrAndFlag<T>&
operator= (const COMPtrAndFlag<T>& rhs)
{
Set(rhs.Ptr(), rhs.Flag());
return *this;
}
void Set(T* aPtr, bool aFlag)
{
SetInternal(aPtr, aFlag);
}
void Set(const nsQueryInterface aPtr, bool aFlag)
{
SetInternal(aPtr, aFlag);
}
void Set(const already_AddRefed<T>& aPtr, bool aFlag)
{
SetInternal(aPtr, aFlag);
}
void UnsetFlag()
{
SetFlag(false);
}
void SetFlag(bool aFlag)
{
if (aFlag) {
*VoidPtr() |= 0x1;
} else {
*VoidPtr() &= ~0x1;
}
}
bool Flag() const
{
return *VoidPtr() & 0x1;
}
void SetPtr(T* aPtr)
{
SetInternal(aPtr);
}
void SetPtr(const nsQueryInterface aPtr)
{
SetInternal(aPtr);
}
void SetPtr(const already_AddRefed<T>& aPtr)
{
SetInternal(aPtr);
}
T* Ptr() const
{
return reinterpret_cast<T*>(*VoidPtr() & ~0x1);
}
void Clear()
{
Set(nsnull, false);
}
private:
template<class PtrType>
void SetInternal(PtrType aPtr, bool aFlag)
{
UnsetFlag();
mCOMPtr = aPtr;
SetFlag(aFlag);
}
template<class PtrType>
void SetInternal(PtrType aPtr)
{
AutoFlagPersister saveFlag(VoidPtr());
mCOMPtr = aPtr;
}
uintptr_t* VoidPtr() const {
return (uintptr_t*)(&mCOMPtr);
}
// Don't modify this without using the AutoFlagPersister, or you will explode
nsCOMPtr<T> mCOMPtr;
};
namespace please_dont_use_this_directly {
/*
...
This class is designed to be used for anonymous temporary objects in the
argument list of calls that return COM interface pointers, e.g.,
COMPtrAndFlag<IFoo> fooP;
...->GetAddRefedPointer(getter_AddRefs(fooP))
DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
When initialized with a |COMPtrAndFlag|, as in the example above, it returns
a |void**|, a |T**|, or an |nsISupports**| as needed, that the
outer call (|GetAddRefedPointer| in this case) can fill in.
*/
template <class T>
class COMPtrAndFlagGetterAddRefs
{
public:
explicit
COMPtrAndFlagGetterAddRefs( COMPtrAndFlag<T>& aSmartPtr )
: mTargetSmartPtr(aSmartPtr), mFlag(aSmartPtr.Flag())
{
if (mFlag)
aSmartPtr.UnsetFlag();
}
~COMPtrAndFlagGetterAddRefs()
{
if (mFlag)
mTargetSmartPtr.SetFlag(true);
}
operator void**()
{
return reinterpret_cast<void**>(mTargetSmartPtr.VoidPtr());
}
operator T**()
{
return reinterpret_cast<T**>(mTargetSmartPtr.VoidPtr());
}
T*&
operator*()
{
return *reinterpret_cast<T**>(mTargetSmartPtr.VoidPtr());
}
private:
COMPtrAndFlag<T>& mTargetSmartPtr;
bool mFlag;
};
} // namespace please_dont_use_this_directly
} // namespace mozilla
template <class T>
inline
mozilla::please_dont_use_this_directly::COMPtrAndFlagGetterAddRefs<T>
getter_AddRefs( mozilla::COMPtrAndFlag<T>& aSmartPtr )
/*
Used around a |COMPtrWithFlag| when
...makes the class |COMPtrWithFlag::GetterAddRefs<T>| invisible.
*/
{
return mozilla::please_dont_use_this_directly::COMPtrAndFlagGetterAddRefs<T>(aSmartPtr);
}
#endif

View File

@ -119,7 +119,6 @@ EXPORTS = \
EXPORTS_mozilla = \
AutoRestore.h \
BlockingResourceBase.h \
COMPtrAndFlag.h \
CondVar.h \
DeadlockDetector.h \
FileUtils.h \

View File

@ -40,7 +40,6 @@
#include <stdio.h>
#include "nsCOMPtr.h"
#include "nsISupports.h"
#include "mozilla/COMPtrAndFlag.h"
#define NS_IFOO_IID \
{ 0x6f7652e0, 0xee43, 0x11d1, \
@ -588,43 +587,6 @@ main()
AnISupportsPtrPtrContext( getter_AddRefs(supportsP) );
}
{
IBar* ibar1 = new IBar;
mozilla::COMPtrAndFlag<IFoo> foop( do_QueryInterface(ibar1) , false);
if (foop.Flag())
return -1;
if (foop.Ptr() != ibar1)
return -1;
foop.SetFlag(true);
if (!foop.Flag())
return -1;
if (foop.Ptr() != ibar1)
return -1;
IBar* ibar2 = new IBar;
mozilla::COMPtrAndFlag<IFoo> foop2( do_QueryInterface(ibar2) , true);
if (!foop2.Flag())
return -1;
if (foop2.Ptr() != ibar2)
return -1;
foop2.SetFlag(false);
if (foop2.Flag())
return -1;
if (foop2.Ptr() != ibar2)
return -1;
}
{
mozilla::COMPtrAndFlag<nsISupports> supportsP;
AVoidPtrPtrContext( getter_AddRefs(supportsP) );
AnISupportsPtrPtrContext( getter_AddRefs(supportsP) );
}
printf("\n### Test 25: will a static |nsCOMPtr| |Release| before program termination?\n");
gFoop = do_QueryInterface(new IFoo);