Bug 846852 - Preallocate the RasterImage source data array when loading from file://. r=seth

--HG--
extra : rebase_source : 9bf2cc014d97f245ae063f65ab4aa6743c3194f2
This commit is contained in:
Joe Drew 2013-03-01 14:21:06 -05:00
parent 02aba3c77d
commit 6e66049758

View File

@ -10,6 +10,8 @@
#include "mozilla/Likely.h"
#include "nsIHttpChannel.h"
#include "nsIFileChannel.h"
#include "nsIFile.h"
#include "nsSimpleURI.h"
#include "nsMimeTypes.h"
#include "nsIURI.h"
@ -128,6 +130,49 @@ ImageFactory::CreateAnonymousImage(const nsCString& aMimeType)
return newImage.forget();
}
int32_t
SaturateToInt32(int64_t val)
{
if (val > INT_MAX)
return INT_MAX;
if (val < INT_MIN)
return INT_MIN;
return static_cast<int32_t>(val);
}
uint32_t
GetContentSize(nsIRequest* aRequest)
{
// Use content-length as a size hint for http channels.
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest));
if (httpChannel) {
nsAutoCString contentLength;
nsresult rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-length"),
contentLength);
if (NS_SUCCEEDED(rv)) {
return std::max(contentLength.ToInteger(&rv), 0);
}
}
// Use the file size as a size hint for file channels.
nsCOMPtr<nsIFileChannel> fileChannel(do_QueryInterface(aRequest));
if (fileChannel) {
nsCOMPtr<nsIFile> file;
nsresult rv = fileChannel->GetFile(getter_AddRefs(file));
if (NS_SUCCEEDED(rv)) {
int64_t filesize;
rv = file->GetFileSize(&filesize);
if (NS_SUCCEEDED(rv)) {
return std::max(SaturateToInt32(filesize), 0);
}
}
}
// Fallback - neither http nor file. We'll use dynamic allocation.
return 0;
}
/* static */ already_AddRefed<Image>
ImageFactory::CreateRasterImage(nsIRequest* aRequest,
imgStatusTracker* aStatusTracker,
@ -145,20 +190,12 @@ ImageFactory::CreateRasterImage(nsIRequest* aRequest,
newImage->SetInnerWindowID(aInnerWindowId);
// Use content-length as a size hint for http channels.
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest));
if (httpChannel) {
nsAutoCString contentLength;
rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-length"),
contentLength);
if (NS_SUCCEEDED(rv)) {
int32_t len = contentLength.ToInteger(&rv);
uint32_t len = GetContentSize(aRequest);
// Pass anything usable on so that the RasterImage can preallocate
// its source buffer.
if (len > 0) {
uint32_t sizeHint = (uint32_t) len;
sizeHint = std::min<uint32_t>(sizeHint, 20000000); // Bound by something reasonable
uint32_t sizeHint = std::min<uint32_t>(len, 20000000); // Bound by something reasonable
rv = newImage->SetSourceSizeHint(sizeHint);
if (NS_FAILED(rv)) {
// Flush memory, try to get some back, and try again.
@ -170,8 +207,6 @@ ImageFactory::CreateRasterImage(nsIRequest* aRequest,
}
}
}
}
}
return newImage.forget();
}