Bug 704059 - Part 2: Let images call imgStatusTracker::OnStopRequest. r=joe

This commit is contained in:
Seth Fowler 2013-02-13 18:41:10 -08:00
parent 2c5dbc3666
commit 275786c6bf
7 changed files with 92 additions and 16 deletions

View File

@ -106,13 +106,16 @@ public:
/**
* Called from OnStopRequest when the image's underlying request completes.
* The arguments are the same as OnStopRequest's, but by separating this
* functionality into a different method we don't interfere with subclasses
* which wish to implement nsIStreamListener.
*
* @param aRequest The completed request.
* @param aContext Context from Necko's OnStopRequest.
* @param aStatus A success or failure code.
* @param aLastPart Whether this is the final part of the underlying request.
*/
virtual nsresult OnImageDataComplete(nsIRequest* aRequest,
nsISupports* aContext,
nsresult status) = 0;
nsresult aStatus,
bool aLastPart) = 0;
/**
* Called for multipart images to allow for any necessary reinitialization

View File

@ -1813,7 +1813,7 @@ get_header_str (char *buf, char *data, size_t data_len)
}
nsresult
RasterImage::OnImageDataComplete(nsIRequest*, nsISupports*, nsresult)
RasterImage::DoImageDataComplete()
{
if (mError)
return NS_ERROR_FAILURE;
@ -1874,6 +1874,19 @@ RasterImage::OnImageDataComplete(nsIRequest*, nsISupports*, nsresult)
return NS_OK;
}
nsresult
RasterImage::OnImageDataComplete(nsIRequest*, nsISupports*, nsresult aStatus, bool aLastPart)
{
nsresult finalStatus = DoImageDataComplete();
// Give precedence to Necko failure codes.
if (NS_FAILED(aStatus))
finalStatus = aStatus;
GetStatusTracker().OnStopRequest(aLastPart, finalStatus);
return finalStatus;
}
nsresult
RasterImage::OnImageDataAvailable(nsIRequest*,
nsISupports*,

View File

@ -251,7 +251,8 @@ public:
uint32_t aCount) MOZ_OVERRIDE;
virtual nsresult OnImageDataComplete(nsIRequest* aRequest,
nsISupports* aContext,
nsresult aResult) MOZ_OVERRIDE;
nsresult aStatus,
bool aLastPart) MOZ_OVERRIDE;
virtual nsresult OnNewSourceData() MOZ_OVERRIDE;
/**
@ -599,6 +600,8 @@ private:
uint8_t **imageData, uint32_t *imageLength,
uint32_t **paletteData, uint32_t *paletteLength);
nsresult DoImageDataComplete();
bool ApplyDecodeFlags(uint32_t aNewFlags);
already_AddRefed<layers::Image> GetCurrentImage();

View File

@ -361,9 +361,32 @@ VectorImage::OutOfProcessSizeOfDecoded() const
nsresult
VectorImage::OnImageDataComplete(nsIRequest* aRequest,
nsISupports* aContext,
nsresult aStatus)
nsresult aStatus,
bool aLastPart)
{
return OnStopRequest(aRequest, aContext, aStatus);
NS_ABORT_IF_FALSE(mStopRequest.empty(), "Duplicate call to OnImageDataComplete?");
// Call our internal OnStopRequest method, which only talks to our embedded
// SVG document. This won't have any effect on our imgStatusTracker.
nsresult finalStatus = OnStopRequest(aRequest, aContext, aStatus);
// Give precedence to Necko failure codes.
if (NS_FAILED(aStatus))
finalStatus = aStatus;
// If there's an error already, we need to fire OnStopRequest on our
// imgStatusTracker immediately. We might not get another chance.
if (mError || NS_FAILED(finalStatus)) {
GetStatusTracker().OnStopRequest(aLastPart, finalStatus);
return finalStatus;
}
// Otherwise, we record the parameters we'll use to call OnStopRequest, and
// return. We'll actually call it in OnSVGDocumentLoaded or
// OnSVGDocumentError.
mStopRequest.construct(aLastPart, finalStatus);
return finalStatus;
}
nsresult
@ -883,6 +906,13 @@ VectorImage::OnSVGDocumentLoaded()
observer->OnStartContainer(); // Signal that width/height are available.
observer->FrameChanged(&nsIntRect::GetMaxSizedIntRect());
observer->OnStopFrame();
if (!mStopRequest.empty()) {
GetStatusTracker().OnStopRequest(mStopRequest.ref().lastPart,
mStopRequest.ref().status);
mStopRequest.destroy();
}
observer->OnStopDecode(NS_OK); // Unblock page load.
}
@ -900,6 +930,14 @@ VectorImage::OnSVGDocumentError()
mError = true;
if (mStatusTracker) {
if (!mStopRequest.empty()) {
nsresult status = NS_FAILED(mStopRequest.ref().status)
? mStopRequest.ref().status
: NS_ERROR_FAILURE;
GetStatusTracker().OnStopRequest(mStopRequest.ref().lastPart, status);
mStopRequest.destroy();
}
// Unblock page load.
mStatusTracker->GetDecoderObserver()->OnStopDecode(NS_ERROR_FAILURE);
}

View File

@ -55,7 +55,8 @@ public:
uint32_t aCount) MOZ_OVERRIDE;
virtual nsresult OnImageDataComplete(nsIRequest* aRequest,
nsISupports* aContext,
nsresult status) MOZ_OVERRIDE;
nsresult aResult,
bool aLastPart) MOZ_OVERRIDE;
virtual nsresult OnNewSourceData() MOZ_OVERRIDE;
// Callback for SVGRootRenderingObserver.
@ -78,11 +79,28 @@ protected:
private:
void CancelAllListeners();
// A private structure used for storing the arguments to
// imgStatusTracker::OnStopRequest until we're ready to call it.
struct StopRequest
{
StopRequest(bool aLastPart = true, nsresult aStatus = NS_OK)
: lastPart(aLastPart)
, status(aStatus)
{ }
bool lastPart;
nsresult status;
};
nsRefPtr<SVGDocumentWrapper> mSVGDocumentWrapper;
nsRefPtr<SVGRootRenderingObserver> mRenderingObserver;
nsRefPtr<SVGLoadEventListener> mLoadEventListener;
nsRefPtr<SVGParseCompleteListener> mParseCompleteListener;
// If we need to fire OnStopRequest, this stores the parameters we got when
// OnImageDataComplete was called.
Maybe<StopRequest> mStopRequest;
nsIntRect mRestrictedRegion; // If we were created by
// ExtractFrame, this is the region
// that we're restricted to using.

View File

@ -628,7 +628,7 @@ NS_IMETHODIMP imgRequest::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt,
// trigger a failure, since the image might be waiting for more non-optional
// data and this is the point where we break the news that it's not coming.
if (mImage) {
nsresult rv = mImage->OnImageDataComplete(aRequest, ctxt, status);
nsresult rv = mImage->OnImageDataComplete(aRequest, ctxt, status, lastPart);
// If we got an error in the OnImageDataComplete() call, we don't want to
// proceed as if nothing bad happened. However, we also want to give
@ -636,11 +636,14 @@ NS_IMETHODIMP imgRequest::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt,
// more meaningful.
if (NS_FAILED(rv) && NS_SUCCEEDED(status))
status = rv;
} else {
// We have to fire imgStatusTracker::OnStopRequest ourselves because there's
// no image capable of doing so.
imgStatusTracker& statusTracker = GetStatusTracker();
statusTracker.RecordCancel(); // No image indicates an error!
statusTracker.OnStopRequest(lastPart, status);
}
imgStatusTracker& statusTracker = GetStatusTracker();
statusTracker.RecordStopRequest(lastPart, status);
// If the request went through, update the cache entry size. Otherwise,
// cancel the request, which removes us from the cache.
if (mImage && NS_SUCCEEDED(status)) {
@ -653,8 +656,6 @@ NS_IMETHODIMP imgRequest::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt,
this->Cancel(status);
}
GetStatusTracker().OnStopRequest(lastPart, status);
mTimedChannel = nullptr;
return NS_OK;
}

View File

@ -91,7 +91,7 @@ NS_IMETHODIMP imgTools::DecodeImage(nsIInputStream* aInStr,
rv = image->OnImageDataAvailable(nullptr, nullptr, inStream, 0, uint32_t(length));
NS_ENSURE_SUCCESS(rv, rv);
// Let the Image know we've sent all the data.
rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK);
rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true);
NS_ENSURE_SUCCESS(rv, rv);
// All done.