From 2d5feee33e3d726f878d77d5987a1b75c2354dc3 Mon Sep 17 00:00:00 2001 From: Jonas Sicking Date: Thu, 7 Oct 2010 09:36:23 -0700 Subject: [PATCH] Bug 599300: Make FileReader work correctly for empty files. r=smaug a=blocker --- content/base/src/nsDOMFileReader.cpp | 21 ++++++++++--------- content/base/src/nsDOMFileReader.h | 4 ++-- content/base/test/test_fileapi.html | 30 ++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/content/base/src/nsDOMFileReader.cpp b/content/base/src/nsDOMFileReader.cpp index 4114bbc5755..12a1b89b9a9 100644 --- a/content/base/src/nsDOMFileReader.cpp +++ b/content/base/src/nsDOMFileReader.cpp @@ -143,7 +143,7 @@ nsDOMFileReader::SetOnloadend(nsIDOMEventListener* aOnloadend) NS_IMETHODIMP nsDOMFileReader::Notify(const char *aCharset, nsDetectionConfident aConf) { - CopyASCIItoUTF16(aCharset, mCharset); + mCharset = aCharset; return NS_OK; } @@ -463,6 +463,8 @@ nsDOMFileReader::OnStopRequest(nsIRequest *aRequest, rv = GetAsDataURL(mFile, mFileData, mDataLen, mResult); break; } + + mResult.SetIsVoid(PR_FALSE); FreeFileData(); @@ -499,7 +501,7 @@ nsDOMFileReader::ReadFileContent(nsIDOMFile* aFile, mFile = aFile; mDataFormat = aDataFormat; - mCharset = aCharset; + CopyUTF16toUTF8(aCharset, mCharset); //Establish a channel with our file { @@ -580,7 +582,7 @@ nsDOMFileReader::DispatchProgressEvent(const nsAString& aType) } nsresult -nsDOMFileReader::GetAsText(const nsAString &aCharset, +nsDOMFileReader::GetAsText(const nsACString &aCharset, const char *aFileData, PRUint32 aDataLen, nsAString& aResult) @@ -588,7 +590,7 @@ nsDOMFileReader::GetAsText(const nsAString &aCharset, nsresult rv; nsCAutoString charsetGuess; if (!aCharset.IsEmpty()) { - CopyUTF16toUTF8(aCharset, charsetGuess); + charsetGuess = aCharset; } else { rv = GuessCharset(aFileData, aDataLen, charsetGuess); NS_ENSURE_SUCCESS(rv, rv); @@ -625,7 +627,7 @@ nsDOMFileReader::GetAsDataURL(nsIDOMFile *aFile, aResult.AppendLiteral(";base64,"); PRUint32 totalRead = 0; - do { + while (aDataLen > totalRead) { PRUint32 numEncode = 4096; PRUint32 amtRemaining = aDataLen - totalRead; if (numEncode > amtRemaining) @@ -643,8 +645,7 @@ nsDOMFileReader::GetAsDataURL(nsIDOMFile *aFile, PR_Free(base64); totalRead += numEncode; - - } while (aDataLen > totalRead); + } return NS_OK; } @@ -700,7 +701,9 @@ nsDOMFileReader::GuessCharset(const char *aFileData, } nsresult rv; - if (detector) { + // The charset detector doesn't work for empty (null) aFileData. Testing + // aDataLen instead of aFileData so that we catch potential errors. + if (detector && aDataLen != 0) { mCharset.Truncate(); detector->Init(this); @@ -712,7 +715,7 @@ nsDOMFileReader::GuessCharset(const char *aFileData, rv = detector->Done(); NS_ENSURE_SUCCESS(rv, rv); - CopyUTF16toUTF8(mCharset, aCharset); + aCharset = mCharset; } else { // no charset detector available, check the BOM unsigned char sniffBuf[4]; diff --git a/content/base/src/nsDOMFileReader.h b/content/base/src/nsDOMFileReader.h index fdd028cac6c..5e161a1faa4 100644 --- a/content/base/src/nsDOMFileReader.h +++ b/content/base/src/nsDOMFileReader.h @@ -118,7 +118,7 @@ protected: }; nsresult ReadFileContent(nsIDOMFile *aFile, const nsAString &aCharset, eDataFormat aDataFormat); - nsresult GetAsText(const nsAString &aCharset, + nsresult GetAsText(const nsACString &aCharset, const char *aFileData, PRUint32 aDataLen, nsAString &aResult); nsresult GetAsDataURL(nsIDOMFile *aFile, const char *aFileData, PRUint32 aDataLen, nsAString &aResult); nsresult GuessCharset(const char *aFileData, PRUint32 aDataLen, nsACString &aCharset); @@ -134,7 +134,7 @@ protected: char *mFileData; nsCOMPtr mFile; - nsString mCharset; + nsCString mCharset; PRUint32 mDataLen; eDataFormat mDataFormat; diff --git a/content/base/test/test_fileapi.html b/content/base/test/test_fileapi.html index 458474c28ef..a439618584c 100644 --- a/content/base/test/test_fileapi.html +++ b/content/base/test/test_fileapi.html @@ -62,6 +62,7 @@ var nonExistingFile = fileList.files[0]; // Test that plain reading works and fires events as expected, both // for text and binary reading + var onloadHasRunText = false; var onloadStartHasRunText = false; r = new FileReader(); @@ -122,6 +123,35 @@ r.readAsText(createFileWithData(convertToUTF32(testTextData)), "UTF-32"); expectedTestCount++; +// Test loading an empty file works (and doesn't crash!) +var emptyFile = createFileWithData(""); +dump("hello nurse"); +r = new FileReader(); +r.onload = getLoadHandler("", 0, "empty no encoding reading"); +r.readAsText(emptyFile, ""); +expectedTestCount++; + +r = new FileReader(); +r.onload = getLoadHandler("", 0, "empty utf8 reading"); +r.readAsText(emptyFile, "utf8"); +expectedTestCount++; + +r = new FileReader(); +r.onload = getLoadHandler("", 0, "empty utf16 reading"); +r.readAsText(emptyFile, "utf-16"); +expectedTestCount++; + +r = new FileReader(); +r.onload = getLoadHandler("", 0, "empty binary string reading"); +r.readAsBinaryString(emptyFile); +expectedTestCount++; + +r = new FileReader(); +r.onload = getLoadHandler(convertToDataURL(""), 0, "empt binary string reading"); +r.readAsDataURL(emptyFile); +expectedTestCount++; + + // Test reusing a FileReader to read multiple times r = new FileReader(); r.onload = getLoadHandler(testASCIIData,