зеркало из https://github.com/mozilla/gecko-dev.git
Bug 505385 - Part 1: Hoist proxy list into imgStatusTracker. r=joe
This commit is contained in:
Родитель
d0c2f1c51f
Коммит
9248a7c43a
|
@ -183,14 +183,14 @@ void imgRequest::AddProxy(imgRequestProxy *proxy)
|
|||
|
||||
// If we're empty before adding, we have to tell the loader we now have
|
||||
// proxies.
|
||||
if (mObservers.IsEmpty()) {
|
||||
if (GetStatusTracker().ConsumerCount() == 0) {
|
||||
NS_ABORT_IF_FALSE(mURI, "Trying to SetHasProxies without key uri.");
|
||||
mLoader->SetHasProxies(mURI);
|
||||
}
|
||||
|
||||
proxy->SetPrincipal(mPrincipal);
|
||||
|
||||
mObservers.AppendElementUnlessExists(proxy);
|
||||
GetStatusTracker().AddConsumer(proxy);
|
||||
}
|
||||
|
||||
nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus)
|
||||
|
@ -202,20 +202,15 @@ nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus)
|
|||
// have animation consumers.
|
||||
proxy->ClearAnimationConsumers();
|
||||
|
||||
if (!mObservers.RemoveElement(proxy)) {
|
||||
// Not one of our proxies; we're done
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Let the status tracker do its thing before we potentially call Cancel()
|
||||
// below, because Cancel() may result in OnStopRequest being called back
|
||||
// before Cancel() returns, leaving the image in a different state then the
|
||||
// one it was in at this point.
|
||||
|
||||
imgStatusTracker& statusTracker = GetStatusTracker();
|
||||
statusTracker.EmulateRequestFinished(proxy, aStatus);
|
||||
if (!statusTracker.RemoveConsumer(proxy, aStatus, !aNotify))
|
||||
return NS_OK;
|
||||
|
||||
if (mObservers.IsEmpty()) {
|
||||
if (statusTracker.ConsumerCount() == 0) {
|
||||
// If we have no observers, there's nothing holding us alive. If we haven't
|
||||
// been cancelled and thus removed from the cache, tell the image loader so
|
||||
// we can be evicted from the cache.
|
||||
|
@ -235,7 +230,7 @@ nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus)
|
|||
/* If |aStatus| is a failure code, then cancel the load if it is still in progress.
|
||||
Otherwise, let the load continue, keeping 'this' in the cache with no observers.
|
||||
This way, if a proxy is destroyed without calling cancel on it, it won't leak
|
||||
and won't leave a bad pointer in mObservers.
|
||||
and won't leave a bad pointer in the observer list.
|
||||
*/
|
||||
if (statusTracker.IsLoading() && NS_FAILED(aStatus)) {
|
||||
LOG_MSG(gImgLog, "imgRequest::RemoveProxy", "load in progress. canceling");
|
||||
|
@ -283,7 +278,7 @@ void imgRequest::Cancel(nsresult aStatus)
|
|||
|
||||
statusTracker.RecordUnblockOnload();
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
statusTracker.SendUnblockOnload(iter.GetNext());
|
||||
}
|
||||
|
@ -353,7 +348,7 @@ void imgRequest::AdjustPriority(imgRequestProxy *proxy, int32_t delta)
|
|||
// concern though is that image loads remain lower priority than other pieces
|
||||
// of content such as link clicks, CSS, and JS.
|
||||
//
|
||||
if (mObservers.SafeElementAt(0, nullptr) != proxy)
|
||||
if (!GetStatusTracker().FirstConsumerIs(proxy))
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(mRequest);
|
||||
|
@ -502,7 +497,7 @@ NS_IMETHODIMP imgRequest::FrameChanged(imgIRequest *request,
|
|||
|
||||
mImage->GetStatusTracker().RecordFrameChanged(container, dirtyRect);
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
mImage->GetStatusTracker().SendFrameChanged(iter.GetNext(), container, dirtyRect);
|
||||
}
|
||||
|
@ -523,7 +518,7 @@ NS_IMETHODIMP imgRequest::OnStartDecode(imgIRequest *request)
|
|||
imgStatusTracker& tracker = mImage->GetStatusTracker();
|
||||
tracker.RecordStartDecode();
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
tracker.SendStartDecode(iter.GetNext());
|
||||
}
|
||||
|
@ -534,7 +529,7 @@ NS_IMETHODIMP imgRequest::OnStartDecode(imgIRequest *request)
|
|||
|
||||
tracker.RecordBlockOnload();
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
tracker.SendBlockOnload(iter.GetNext());
|
||||
}
|
||||
|
@ -571,7 +566,7 @@ NS_IMETHODIMP imgRequest::OnStartContainer(imgIRequest *request, imgIContainer *
|
|||
"OnStartContainer callback from an image we don't own");
|
||||
mImage->GetStatusTracker().RecordStartContainer(image);
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
mImage->GetStatusTracker().SendStartContainer(iter.GetNext(), image);
|
||||
}
|
||||
|
@ -589,7 +584,7 @@ NS_IMETHODIMP imgRequest::OnStartFrame(imgIRequest *request,
|
|||
|
||||
mImage->GetStatusTracker().RecordStartFrame(frame);
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
mImage->GetStatusTracker().SendStartFrame(iter.GetNext(), frame);
|
||||
}
|
||||
|
@ -608,7 +603,7 @@ NS_IMETHODIMP imgRequest::OnDataAvailable(imgIRequest *request,
|
|||
|
||||
mImage->GetStatusTracker().RecordDataAvailable(aCurrentFrame, rect);
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
mImage->GetStatusTracker().SendDataAvailable(iter.GetNext(), aCurrentFrame, rect);
|
||||
}
|
||||
|
@ -627,7 +622,7 @@ NS_IMETHODIMP imgRequest::OnStopFrame(imgIRequest *request,
|
|||
imgStatusTracker& tracker = mImage->GetStatusTracker();
|
||||
tracker.RecordStopFrame(frame);
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
tracker.SendStopFrame(iter.GetNext(), frame);
|
||||
}
|
||||
|
@ -637,7 +632,7 @@ NS_IMETHODIMP imgRequest::OnStopFrame(imgIRequest *request,
|
|||
|
||||
tracker.RecordUnblockOnload();
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
tracker.SendUnblockOnload(iter.GetNext());
|
||||
}
|
||||
|
@ -657,7 +652,7 @@ NS_IMETHODIMP imgRequest::OnStopContainer(imgIRequest *request,
|
|||
imgStatusTracker& tracker = mImage->GetStatusTracker();
|
||||
tracker.RecordStopContainer(image);
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
tracker.SendStopContainer(iter.GetNext(), image);
|
||||
}
|
||||
|
@ -673,7 +668,7 @@ NS_IMETHODIMP imgRequest::OnStopContainer(imgIRequest *request,
|
|||
|
||||
tracker.RecordUnblockOnload();
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
tracker.SendUnblockOnload(iter.GetNext());
|
||||
}
|
||||
|
@ -697,7 +692,7 @@ NS_IMETHODIMP imgRequest::OnStopDecode(imgIRequest *aRequest,
|
|||
|
||||
mImage->GetStatusTracker().RecordStopDecode(aStatus, aStatusArg);
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
mImage->GetStatusTracker().SendStopDecode(iter.GetNext(), aStatus,
|
||||
aStatusArg);
|
||||
|
@ -746,7 +741,7 @@ NS_IMETHODIMP imgRequest::OnDiscard(imgIRequest *aRequest)
|
|||
// Update the cache entry size, since we just got rid of frame data
|
||||
UpdateCacheEntrySize();
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
mImage->GetStatusTracker().SendDiscard(iter.GetNext());
|
||||
}
|
||||
|
@ -760,7 +755,7 @@ NS_IMETHODIMP imgRequest::OnImageIsAnimated(imgIRequest *aRequest)
|
|||
"OnImageIsAnimated callback before we've created our image");
|
||||
mImage->GetStatusTracker().RecordImageIsAnimated();
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
mImage->GetStatusTracker().SendImageIsAnimated(iter.GetNext());
|
||||
}
|
||||
|
@ -820,7 +815,7 @@ NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt
|
|||
if (channel)
|
||||
channel->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
statusTracker.SendStartRequest(iter.GetNext());
|
||||
}
|
||||
|
@ -838,7 +833,7 @@ NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt
|
|||
}
|
||||
|
||||
// Tell all of our proxies that we have a principal.
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
iter.GetNext()->SetPrincipal(mPrincipal);
|
||||
}
|
||||
|
@ -848,7 +843,7 @@ NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt
|
|||
SetCacheValidation(mCacheEntry, aRequest);
|
||||
|
||||
// Shouldn't we be dead already if this gets hit? Probably multipart/x-mixed-replace...
|
||||
if (mObservers.IsEmpty()) {
|
||||
if (GetStatusTracker().ConsumerCount() == 0) {
|
||||
this->Cancel(NS_IMAGELIB_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
|
@ -919,7 +914,7 @@ NS_IMETHODIMP imgRequest::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt,
|
|||
}
|
||||
|
||||
/* notify the kids */
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator srIter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator srIter(GetStatusTracker().GetConsumers());
|
||||
while (srIter.HasMore()) {
|
||||
statusTracker.SendStopRequest(srIter.GetNext(), lastPart, status);
|
||||
}
|
||||
|
@ -1008,7 +1003,9 @@ imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt,
|
|||
// our own any more.
|
||||
if (mResniffMimeType) {
|
||||
NS_ABORT_IF_FALSE(mIsMultiPartChannel, "Resniffing a non-multipart image");
|
||||
mStatusTracker = new imgStatusTracker(nullptr);
|
||||
imgStatusTracker* freshTracker = new imgStatusTracker(nullptr);
|
||||
freshTracker->AdoptConsumers(mStatusTracker);
|
||||
mStatusTracker = freshTracker;
|
||||
}
|
||||
|
||||
mResniffMimeType = false;
|
||||
|
@ -1022,7 +1019,7 @@ imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt,
|
|||
mImage->SetInnerWindowID(mInnerWindowId);
|
||||
|
||||
// Notify any imgRequestProxys that are observing us that we have an Image.
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
|
||||
while (iter.HasMore()) {
|
||||
iter.GetNext()->SetImage(mImage);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "nsCategoryCache.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsError.h"
|
||||
#include "imgIRequest.h"
|
||||
|
@ -199,8 +198,6 @@ private:
|
|||
nsCOMPtr<nsIChannel> mChannel;
|
||||
nsCOMPtr<nsIInterfaceRequestor> mPrevChannelSink;
|
||||
|
||||
nsTObserverArray<imgRequestProxy*> mObservers;
|
||||
|
||||
nsCOMPtr<nsITimedChannel> mTimedChannel;
|
||||
|
||||
nsCString mContentType;
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
#include "ImageLogging.h"
|
||||
#include "RasterImage.h"
|
||||
|
||||
#include "mozilla/Util.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
using namespace mozilla::image;
|
||||
|
||||
static nsresult
|
||||
|
@ -264,6 +267,28 @@ imgStatusTracker::EmulateRequestFinished(imgRequestProxy* aProxy,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
imgStatusTracker::AddConsumer(imgRequestProxy* aConsumer)
|
||||
{
|
||||
mConsumers.AppendElementUnlessExists(aConsumer);
|
||||
}
|
||||
|
||||
// XXX - The last two arguments should go away.
|
||||
bool
|
||||
imgStatusTracker::RemoveConsumer(imgRequestProxy* aConsumer, nsresult aStatus,
|
||||
bool aOnlySendStopRequest)
|
||||
{
|
||||
// Remove the proxy from the list.
|
||||
bool removed = mConsumers.RemoveElement(aConsumer);
|
||||
//MOZ_NONFATAL_ASSERT(removed, "Trying to remove a consumer we don't have");
|
||||
|
||||
// Consumers can get confused if they don't get all the proper teardown
|
||||
// notifications. Part ways on good terms.
|
||||
if (removed)
|
||||
EmulateRequestFinished(aConsumer, aStatus, aOnlySendStopRequest);
|
||||
return removed;
|
||||
}
|
||||
|
||||
void
|
||||
imgStatusTracker::RecordCancel()
|
||||
{
|
||||
|
|
|
@ -21,6 +21,7 @@ class Image;
|
|||
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nscore.h"
|
||||
|
||||
|
@ -85,6 +86,24 @@ public:
|
|||
// OnStopRequest and UnblockOnload, and only if necessary.
|
||||
void EmulateRequestFinished(imgRequestProxy* proxy, nsresult aStatus);
|
||||
|
||||
// We manage a set of consumers that are using an image and thus concerned
|
||||
// with its status. Weak pointers.
|
||||
void AddConsumer(imgRequestProxy* aConsumer);
|
||||
bool RemoveConsumer(imgRequestProxy* aConsumer, nsresult aStatus, bool aOnlySendStopRequest);
|
||||
size_t ConsumerCount() const { return mConsumers.Length(); };
|
||||
|
||||
// This is intentionally non-general because its sole purpose is to support an
|
||||
// some obscure network priority logic in imgRequest. That stuff could probably
|
||||
// be improved, but it's too scary to mess with at the moment.
|
||||
bool FirstConsumerIs(imgRequestProxy* aConsumer) {
|
||||
return mConsumers.SafeElementAt(0, nullptr) == aConsumer;
|
||||
}
|
||||
|
||||
// Temporary hack that goes away in the next patch.
|
||||
const nsTObserverArray<imgRequestProxy*>& GetConsumers() { return mConsumers; };
|
||||
|
||||
void AdoptConsumers(imgStatusTracker* aTracker) { mConsumers = aTracker->mConsumers; }
|
||||
|
||||
// Returns whether we are in the process of loading; that is, whether we have
|
||||
// not received OnStopRequest.
|
||||
bool IsLoading() const;
|
||||
|
@ -160,6 +179,10 @@ private:
|
|||
uint32_t mState;
|
||||
uint32_t mImageStatus;
|
||||
bool mHadLastPart;
|
||||
|
||||
// List of proxies attached to the image. Each proxy represents a consumer
|
||||
// using the image.
|
||||
nsTObserverArray<imgRequestProxy*> mConsumers;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче