LCOV - app.info - content/base/src/nsDOMFileReader.cpp

LCOV - code coverage report
| Current view: | directory - content/base/src - nsDOMFileReader.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 279 | 114 | 40.9 %
| Date: | 2012-06-02 | Functions: | 46 | 20 | 43.5 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is mozila.org code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Mozilla Foundation
          19                 :  * Portions created by the Initial Developer are Copyright (C) 2007
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *
          24                 :  * Alternatively, the contents of this file may be used under the terms of
          25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          28                 :  * of those above. If you wish to allow use of your version of this file only
          29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          30                 :  * use your version of this file under the terms of the MPL, indicate your
          31                 :  * decision by deleting the provisions above and replace them with the notice
          32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          33                 :  * the provisions above, a recipient may use your version of this file under
          34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          35                 :  *
          36                 :  * ***** END LICENSE BLOCK ***** */
          37                 :
          38                 : #include "nsDOMFileReader.h"
          39                 :
          40                 : #include "nsContentCID.h"
          41                 : #include "nsContentUtils.h"
          42                 : #include "nsDOMClassInfoID.h"
          43                 : #include "nsDOMFile.h"
          44                 : #include "nsDOMError.h"
          45                 : #include "nsCharsetAlias.h"
          46                 : #include "nsICharsetDetector.h"
          47                 : #include "nsICharsetConverterManager.h"
          48                 : #include "nsIConverterInputStream.h"
          49                 : #include "nsIFile.h"
          50                 : #include "nsIFileStreams.h"
          51                 : #include "nsIInputStream.h"
          52                 : #include "nsIMIMEService.h"
          53                 : #include "nsIPlatformCharset.h"
          54                 : #include "nsIUnicodeDecoder.h"
          55                 : #include "nsNetCID.h"
          56                 : #include "nsNetUtil.h"
          57                 :
          58                 : #include "plbase64.h"
          59                 : #include "prmem.h"
          60                 :
          61                 : #include "nsLayoutCID.h"
          62                 : #include "nsXPIDLString.h"
          63                 : #include "nsReadableUtils.h"
          64                 : #include "nsIURI.h"
          65                 : #include "nsStreamUtils.h"
          66                 : #include "nsXPCOM.h"
          67                 : #include "nsIPrivateDOMEvent.h"
          68                 : #include "nsIDOMEventListener.h"
          69                 : #include "nsIJSContextStack.h"
          70                 : #include "nsJSEnvironment.h"
          71                 : #include "nsIScriptGlobalObject.h"
          72                 : #include "nsCExternalHandlerService.h"
          73                 : #include "nsIStreamConverterService.h"
          74                 : #include "nsCycleCollectionParticipant.h"
          75                 : #include "nsLayoutStatics.h"
          76                 : #include "nsIScriptObjectPrincipal.h"
          77                 : #include "nsBlobProtocolHandler.h"
          78                 : #include "mozilla/Preferences.h"
          79                 : #include "xpcpublic.h"
          80                 : #include "nsIScriptSecurityManager.h"
          81                 : #include "nsDOMJSUtils.h"
          82                 : #include "nsDOMEventTargetHelper.h"
          83                 :
          84                 : #include "jstypedarray.h"
          85                 :
          86                 : using namespace mozilla;
          87                 :
          88                 : #define LOAD_STR "load"
          89                 : #define LOADSTART_STR "loadstart"
          90                 : #define LOADEND_STR "loadend"
          91                 :
          92                 : using mozilla::dom::FileIOObject;
          93                 :
          94            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMFileReader)
          95                 :
          96               4 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMFileReader,
          97                 :                                                   FileIOObject)
          98               4 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFile)
          99               4 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrincipal)
         100               4 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannel)
         101               4 :   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(load)
         102               4 :   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(loadstart)
         103               4 :   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(loadend)
         104               4 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
         105                 :
         106               2 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMFileReader,
         107                 :                                                 FileIOObject)
         108               2 :   tmp->mResultArrayBuffer = nsnull;
         109               2 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFile)
         110               2 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPrincipal)
         111               2 :   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(load)
         112               2 :   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(loadstart)
         113               2 :   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(loadend)
         114               2 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
         115                 :
         116                 :
         117              16 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(nsDOMFileReader,
         118                 :                                                nsDOMEventTargetHelper)
         119              16 :   if(tmp->mResultArrayBuffer) {
         120              12 :     NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(tmp->mResultArrayBuffer,
         121                 :                                                "mResultArrayBuffer")
         122                 :   }
         123              16 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
         124                 :
         125                 : DOMCI_DATA(FileReader, nsDOMFileReader)
         126                 :
         127             222 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMFileReader)
         128             140 :   NS_INTERFACE_MAP_ENTRY(nsIDOMFileReader)
         129             130 :   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
         130             130 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
         131             130 :   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
         132             130 :   NS_INTERFACE_MAP_ENTRY(nsICharsetDetectionObserver)
         133             130 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(FileReader)
         134             128 : NS_INTERFACE_MAP_END_INHERITING(FileIOObject)
         135                 :
         136             142 : NS_IMPL_ADDREF_INHERITED(nsDOMFileReader, FileIOObject)
         137             142 : NS_IMPL_RELEASE_INHERITED(nsDOMFileReader, FileIOObject)
         138                 :
         139                 : void
         140               2 : nsDOMFileReader::RootResultArrayBuffer()
         141                 : {
         142                 :   nsContentUtils::PreserveWrapper(
         143                 :     static_cast<nsIDOMEventTarget*>(
         144               2 :       static_cast<nsDOMEventTargetHelper*>(this)), this);
         145               2 : }
         146                 :
         147                 : //nsICharsetDetectionObserver
         148                 :
         149                 : NS_IMETHODIMP
         150               0 : nsDOMFileReader::Notify(const char *aCharset, nsDetectionConfident aConf)
         151                 : {
         152               0 :   mCharset = aCharset;
         153               0 :   return NS_OK;
         154                 : }
         155                 :
         156                 : //nsDOMFileReader constructors/initializers
         157                 :
         158               2 : nsDOMFileReader::nsDOMFileReader()
         159                 :   : mFileData(nsnull),
         160                 :     mDataLen(0), mDataFormat(FILE_AS_BINARY),
         161               2 :     mResultArrayBuffer(nsnull)
         162                 : {
         163               2 :   nsLayoutStatics::AddRef();
         164               2 :   SetDOMStringToNull(mResult);
         165               2 : }
         166                 :
         167               6 : nsDOMFileReader::~nsDOMFileReader()
         168                 : {
         169               2 :   FreeFileData();
         170                 :
         171               2 :   nsLayoutStatics::Release();
         172               8 : }
         173                 :
         174                 : nsresult
         175               2 : nsDOMFileReader::Init()
         176                 : {
         177               2 :   nsDOMEventTargetHelper::Init();
         178                 :
         179               2 :   nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
         180               4 :   nsCOMPtr<nsIPrincipal> subjectPrincipal;
         181               2 :   if (secMan) {
         182               2 :     nsresult rv = secMan->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
         183               2 :     NS_ENSURE_SUCCESS(rv, rv);
         184                 :   }
         185               2 :   NS_ENSURE_STATE(subjectPrincipal);
         186               2 :   mPrincipal.swap(subjectPrincipal);
         187                 :
         188               2 :   return NS_OK;
         189                 : }
         190                 :
         191               0 : NS_IMPL_EVENT_HANDLER(nsDOMFileReader, load)
         192               0 : NS_IMPL_EVENT_HANDLER(nsDOMFileReader, loadstart)
         193               0 : NS_IMPL_EVENT_HANDLER(nsDOMFileReader, loadend)
         194               0 : NS_IMPL_FORWARD_EVENT_HANDLER(nsDOMFileReader, abort, FileIOObject)
         195               0 : NS_IMPL_FORWARD_EVENT_HANDLER(nsDOMFileReader, progress, FileIOObject)
         196               0 : NS_IMPL_FORWARD_EVENT_HANDLER(nsDOMFileReader, error, FileIOObject)
         197                 :
         198                 : NS_IMETHODIMP
         199               0 : nsDOMFileReader::Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
         200                 :                             PRUint32 argc, jsval *argv)
         201                 : {
         202               0 :   nsCOMPtr<nsPIDOMWindow> owner = do_QueryInterface(aOwner);
         203               0 :   if (!owner) {
         204               0 :     NS_WARNING("Unexpected nsIJSNativeInitializer owner");
         205               0 :     return NS_OK;
         206                 :   }
         207                 :
         208               0 :   BindToOwner(owner);
         209                 :
         210                 :   // This object is bound to a |window|,
         211                 :   // so reset the principal.
         212               0 :   nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal = do_QueryInterface(aOwner);
         213               0 :   NS_ENSURE_STATE(scriptPrincipal);
         214               0 :   mPrincipal = scriptPrincipal->GetPrincipal();
         215                 :
         216               0 :   return NS_OK;
         217                 : }
         218                 :
         219                 : // nsIInterfaceRequestor
         220                 :
         221                 : NS_IMETHODIMP
         222               0 : nsDOMFileReader::GetInterface(const nsIID & aIID, void **aResult)
         223                 : {
         224               0 :   return QueryInterface(aIID, aResult);
         225                 : }
         226                 :
         227                 : // nsIDOMFileReader
         228                 :
         229                 : NS_IMETHODIMP
         230               2 : nsDOMFileReader::GetReadyState(PRUint16 *aReadyState)
         231                 : {
         232               2 :   return FileIOObject::GetReadyState(aReadyState);
         233                 : }
         234                 :
         235                 : NS_IMETHODIMP
         236               2 : nsDOMFileReader::GetResult(JSContext* aCx, jsval* aResult)
         237                 : {
         238               2 :   if (mDataFormat == FILE_AS_ARRAYBUFFER) {
         239               2 :     if (mReadyState == nsIDOMFileReader::DONE && mResultArrayBuffer) {
         240               2 :       JSObject* tmp = mResultArrayBuffer;
         241               2 :       *aResult = OBJECT_TO_JSVAL(tmp);
         242                 :     } else {
         243               0 :       *aResult = JSVAL_NULL;
         244                 :     }
         245               2 :     return NS_OK;
         246                 :   }
         247                 :
         248               0 :   nsString tmpResult = mResult;
         249               0 :   if (!xpc::StringToJsval(aCx, tmpResult, aResult)) {
         250               0 :     return NS_ERROR_FAILURE;
         251                 :   }
         252               0 :   return NS_OK;
         253                 : }
         254                 :
         255                 : NS_IMETHODIMP
         256               0 : nsDOMFileReader::GetError(nsIDOMDOMError** aError)
         257                 : {
         258               0 :   return FileIOObject::GetError(aError);
         259                 : }
         260                 :
         261                 : NS_IMETHODIMP
         262               2 : nsDOMFileReader::ReadAsArrayBuffer(nsIDOMBlob* aFile, JSContext* aCx)
         263                 : {
         264               2 :   return ReadFileContent(aCx, aFile, EmptyString(), FILE_AS_ARRAYBUFFER);
         265                 : }
         266                 :
         267                 : NS_IMETHODIMP
         268               0 : nsDOMFileReader::ReadAsBinaryString(nsIDOMBlob* aFile)
         269                 : {
         270               0 :   return ReadFileContent(nsnull, aFile, EmptyString(), FILE_AS_BINARY);
         271                 : }
         272                 :
         273                 : NS_IMETHODIMP
         274               0 : nsDOMFileReader::ReadAsText(nsIDOMBlob* aFile,
         275                 :                             const nsAString &aCharset)
         276                 : {
         277               0 :   return ReadFileContent(nsnull, aFile, aCharset, FILE_AS_TEXT);
         278                 : }
         279                 :
         280                 : NS_IMETHODIMP
         281               0 : nsDOMFileReader::ReadAsDataURL(nsIDOMBlob* aFile)
         282                 : {
         283               0 :   return ReadFileContent(nsnull, aFile, EmptyString(), FILE_AS_DATAURL);
         284                 : }
         285                 :
         286                 : NS_IMETHODIMP
         287               2 : nsDOMFileReader::Abort()
         288                 : {
         289               2 :   return FileIOObject::Abort();
         290                 : }
         291                 :
         292                 : nsresult
         293               0 : nsDOMFileReader::DoAbort(nsAString& aEvent)
         294                 : {
         295                 :   // Revert status and result attributes
         296               0 :   SetDOMStringToNull(mResult);
         297               0 :   mResultArrayBuffer = nsnull;
         298                 :
         299                 :   // Non-null channel indicates a read is currently active
         300               0 :   if (mChannel) {
         301                 :     // Cancel request requires an error status
         302               0 :     mChannel->Cancel(NS_ERROR_FAILURE);
         303               0 :     mChannel = nsnull;
         304                 :   }
         305               0 :   mFile = nsnull;
         306                 :
         307                 :   //Clean up memory buffer
         308               0 :   FreeFileData();
         309                 :
         310                 :   // Tell the base class which event to dispatch
         311               0 :   aEvent = NS_LITERAL_STRING(LOADEND_STR);
         312               0 :   return NS_OK;
         313                 : }
         314                 :
         315                 : static
         316                 : NS_METHOD
         317               0 : ReadFuncBinaryString(nsIInputStream* in,
         318                 :                      void* closure,
         319                 :                      const char* fromRawSegment,
         320                 :                      PRUint32 toOffset,
         321                 :                      PRUint32 count,
         322                 :                      PRUint32 *writeCount)
         323                 : {
         324               0 :   PRUnichar* dest = static_cast<PRUnichar*>(closure) + toOffset;
         325               0 :   PRUnichar* end = dest + count;
         326               0 :   const unsigned char* source = (const unsigned char*)fromRawSegment;
         327               0 :   while (dest != end) {
         328               0 :     *dest = *source;
         329               0 :     ++dest;
         330               0 :     ++source;
         331                 :   }
         332               0 :   *writeCount = count;
         333                 :
         334               0 :   return NS_OK;
         335                 : }
         336                 :
         337                 : nsresult
         338               2 : nsDOMFileReader::DoOnDataAvailable(nsIRequest *aRequest,
         339                 :                                    nsISupports *aContext,
         340                 :                                    nsIInputStream *aInputStream,
         341                 :                                    PRUint32 aOffset,
         342                 :                                    PRUint32 aCount)
         343                 : {
         344               2 :   if (mDataFormat == FILE_AS_BINARY) {
         345                 :     //Continuously update our binary string as data comes in
         346               0 :     NS_ASSERTION(mResult.Length() == aOffset,
         347                 :                  "unexpected mResult length");
         348               0 :     PRUint32 oldLen = mResult.Length();
         349               0 :     PRUnichar *buf = nsnull;
         350               0 :     mResult.GetMutableData(&buf, oldLen + aCount);
         351               0 :     NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
         352                 :
         353               0 :     PRUint32 bytesRead = 0;
         354               0 :     aInputStream->ReadSegments(ReadFuncBinaryString, buf + oldLen, aCount,
         355               0 :                                &bytesRead);
         356               0 :     NS_ASSERTION(bytesRead == aCount, "failed to read data");
         357                 :   }
         358               2 :   else if (mDataFormat == FILE_AS_ARRAYBUFFER) {
         359               2 :     JSObject* abuf = js::ArrayBuffer::getArrayBuffer(mResultArrayBuffer);
         360               2 :     NS_ASSERTION(abuf, "What happened?");
         361                 :
         362               2 :     PRUint32 bytesRead = 0;
         363               2 :     aInputStream->Read((char*)JS_GetArrayBufferData(abuf) + aOffset, aCount, &bytesRead);
         364               2 :     NS_ASSERTION(bytesRead == aCount, "failed to read data");
         365                 :   }
         366                 :   else {
         367                 :     //Update memory buffer to reflect the contents of the file
         368               0 :     mFileData = (char *)PR_Realloc(mFileData, aOffset + aCount);
         369               0 :     NS_ENSURE_TRUE(mFileData, NS_ERROR_OUT_OF_MEMORY);
         370                 :
         371               0 :     PRUint32 bytesRead = 0;
         372               0 :     aInputStream->Read(mFileData + aOffset, aCount, &bytesRead);
         373               0 :     NS_ASSERTION(bytesRead == aCount, "failed to read data");
         374                 :
         375               0 :     mDataLen += aCount;
         376                 :   }
         377                 :
         378               2 :   return NS_OK;
         379                 : }
         380                 :
         381                 : nsresult
         382               2 : nsDOMFileReader::DoOnStopRequest(nsIRequest *aRequest,
         383                 :                                  nsISupports *aContext,
         384                 :                                  nsresult aStatus,
         385                 :                                  nsAString& aSuccessEvent,
         386                 :                                  nsAString& aTerminationEvent)
         387                 : {
         388               2 :   aSuccessEvent = NS_LITERAL_STRING(LOAD_STR);
         389               2 :   aTerminationEvent = NS_LITERAL_STRING(LOADEND_STR);
         390                 :
         391                 :   // Clear out the data if necessary
         392               2 :   if (NS_FAILED(aStatus)) {
         393               0 :     FreeFileData();
         394               0 :     return NS_OK;
         395                 :   }
         396                 :
         397               2 :   nsresult rv = NS_OK;
         398               2 :   switch (mDataFormat) {
         399                 :     case FILE_AS_ARRAYBUFFER:
         400               2 :       break; //Already accumulated mResultArrayBuffer
         401                 :     case FILE_AS_BINARY:
         402               0 :       break; //Already accumulated mResult
         403                 :     case FILE_AS_TEXT:
         404               0 :       rv = GetAsText(mCharset, mFileData, mDataLen, mResult);
         405               0 :       break;
         406                 :     case FILE_AS_DATAURL:
         407               0 :       rv = GetAsDataURL(mFile, mFileData, mDataLen, mResult);
         408               0 :       break;
         409                 :   }
         410                 :
         411               2 :   mResult.SetIsVoid(false);
         412                 :
         413               2 :   FreeFileData();
         414                 :
         415               2 :   return rv;
         416                 : }
         417                 :
         418                 : // Helper methods
         419                 :
         420                 : nsresult
         421               2 : nsDOMFileReader::ReadFileContent(JSContext* aCx,
         422                 :                                  nsIDOMBlob* aFile,
         423                 :                                  const nsAString &aCharset,
         424                 :                                  eDataFormat aDataFormat)
         425                 : {
         426                 :   nsresult rv;
         427               2 :   NS_ENSURE_TRUE(aFile, NS_ERROR_NULL_POINTER);
         428                 :
         429                 :   //Implicit abort to clear any other activity going on
         430               2 :   Abort();
         431               2 :   mError = nsnull;
         432               2 :   SetDOMStringToNull(mResult);
         433               2 :   mTransferred = 0;
         434               2 :   mTotal = 0;
         435               2 :   mReadyState = nsIDOMFileReader::EMPTY;
         436               2 :   FreeFileData();
         437                 :
         438               2 :   mFile = aFile;
         439               2 :   mDataFormat = aDataFormat;
         440               2 :   CopyUTF16toUTF8(aCharset, mCharset);
         441                 :
         442                 :   //Establish a channel with our file
         443                 :   {
         444                 :     // Hold the internal URL alive only as long as necessary
         445                 :     // After the channel is created it will own whatever is backing
         446                 :     // the DOMFile.
         447               4 :     nsDOMFileInternalUrlHolder urlHolder(mFile, mPrincipal);
         448                 :
         449               4 :     nsCOMPtr<nsIURI> uri;
         450               2 :     rv = NS_NewURI(getter_AddRefs(uri), urlHolder.mUrl);
         451               2 :     NS_ENSURE_SUCCESS(rv, rv);
         452                 :
         453               2 :     rv = NS_NewChannel(getter_AddRefs(mChannel), uri);
         454               2 :     NS_ENSURE_SUCCESS(rv, rv);
         455                 :   }
         456                 :
         457                 :   //Obtain the total size of the file before reading
         458               2 :   mTotal = mozilla::dom::kUnknownSize;
         459               2 :   mFile->GetSize(&mTotal);
         460                 :
         461               2 :   rv = mChannel->AsyncOpen(this, nsnull);
         462               2 :   NS_ENSURE_SUCCESS(rv, rv);
         463                 :
         464                 :   //FileReader should be in loading state here
         465               2 :   mReadyState = nsIDOMFileReader::LOADING;
         466               2 :   DispatchProgressEvent(NS_LITERAL_STRING(LOADSTART_STR));
         467                 :
         468               2 :   if (mDataFormat == FILE_AS_ARRAYBUFFER) {
         469               2 :     RootResultArrayBuffer();
         470               2 :     mResultArrayBuffer = js_CreateArrayBuffer(aCx, mTotal);
         471               2 :     if (!mResultArrayBuffer) {
         472               0 :       NS_WARNING("Failed to create JS array buffer");
         473               0 :       return NS_ERROR_FAILURE;
         474                 :     }
         475                 :   }
         476                 :
         477               2 :   return NS_OK;
         478                 : }
         479                 :
         480                 : nsresult
         481               0 : nsDOMFileReader::GetAsText(const nsACString &aCharset,
         482                 :                            const char *aFileData,
         483                 :                            PRUint32 aDataLen,
         484                 :                            nsAString& aResult)
         485                 : {
         486                 :   nsresult rv;
         487               0 :   nsCAutoString charsetGuess;
         488               0 :   if (!aCharset.IsEmpty()) {
         489               0 :     charsetGuess = aCharset;
         490                 :   } else {
         491               0 :     rv = GuessCharset(aFileData, aDataLen, charsetGuess);
         492               0 :     NS_ENSURE_SUCCESS(rv, rv);
         493                 :   }
         494                 :
         495               0 :   nsCAutoString charset;
         496               0 :   rv = nsCharsetAlias::GetPreferred(charsetGuess, charset);
         497               0 :   NS_ENSURE_SUCCESS(rv, rv);
         498                 :
         499               0 :   rv = ConvertStream(aFileData, aDataLen, charset.get(), aResult);
         500                 :
         501               0 :   return NS_OK;
         502                 : }
         503                 :
         504                 : nsresult
         505               0 : nsDOMFileReader::GetAsDataURL(nsIDOMBlob *aFile,
         506                 :                               const char *aFileData,
         507                 :                               PRUint32 aDataLen,
         508                 :                               nsAString& aResult)
         509                 : {
         510               0 :   aResult.AssignLiteral("data:");
         511                 :
         512                 :   nsresult rv;
         513               0 :   nsString contentType;
         514               0 :   rv = aFile->GetType(contentType);
         515               0 :   if (NS_SUCCEEDED(rv) && !contentType.IsEmpty()) {
         516               0 :     aResult.Append(contentType);
         517                 :   } else {
         518               0 :     aResult.AppendLiteral("application/octet-stream");
         519                 :   }
         520               0 :   aResult.AppendLiteral(";base64,");
         521                 :
         522               0 :   PRUint32 totalRead = 0;
         523               0 :   while (aDataLen > totalRead) {
         524               0 :     PRUint32 numEncode = 4096;
         525               0 :     PRUint32 amtRemaining = aDataLen - totalRead;
         526               0 :     if (numEncode > amtRemaining)
         527               0 :       numEncode = amtRemaining;
         528                 :
         529                 :     //Unless this is the end of the file, encode in multiples of 3
         530               0 :     if (numEncode > 3) {
         531               0 :       PRUint32 leftOver = numEncode % 3;
         532               0 :       numEncode -= leftOver;
         533                 :     }
         534                 :
         535                 :     //Out buffer should be at least 4/3rds the read buf, plus a terminator
         536               0 :     char *base64 = PL_Base64Encode(aFileData + totalRead, numEncode, nsnull);
         537               0 :     AppendASCIItoUTF16(nsDependentCString(base64), aResult);
         538               0 :     PR_Free(base64);
         539                 :
         540               0 :     totalRead += numEncode;
         541                 :   }
         542                 :
         543               0 :   return NS_OK;
         544                 : }
         545                 :
         546                 : nsresult
         547               0 : nsDOMFileReader::ConvertStream(const char *aFileData,
         548                 :                                PRUint32 aDataLen,
         549                 :                                const char *aCharset,
         550                 :                                nsAString &aResult)
         551                 : {
         552                 :   nsresult rv;
         553                 :   nsCOMPtr<nsICharsetConverterManager> charsetConverter =
         554               0 :     do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
         555               0 :   NS_ENSURE_SUCCESS(rv, rv);
         556                 :
         557               0 :   nsCOMPtr<nsIUnicodeDecoder> unicodeDecoder;
         558               0 :   rv = charsetConverter->GetUnicodeDecoder(aCharset, getter_AddRefs(unicodeDecoder));
         559               0 :   NS_ENSURE_SUCCESS(rv, rv);
         560                 :
         561                 :   PRInt32 destLength;
         562               0 :   rv = unicodeDecoder->GetMaxLength(aFileData, aDataLen, &destLength);
         563               0 :   NS_ENSURE_SUCCESS(rv, rv);
         564                 :
         565               0 :   aResult.SetLength(destLength);  //Make sure we have enough space for the conversion
         566               0 :   destLength = aResult.Length();
         567                 :
         568               0 :   PRInt32 srcLength = aDataLen;
         569               0 :   rv = unicodeDecoder->Convert(aFileData, &srcLength, aResult.BeginWriting(), &destLength);
         570               0 :   aResult.SetLength(destLength); //Trim down to the correct size
         571                 :
         572               0 :   return rv;
         573                 : }
         574                 :
         575                 : nsresult
         576               0 : nsDOMFileReader::GuessCharset(const char *aFileData,
         577                 :                               PRUint32 aDataLen,
         578                 :                               nsACString &aCharset)
         579                 : {
         580                 :   // First try the universal charset detector
         581                 :   nsCOMPtr<nsICharsetDetector> detector
         582                 :     = do_CreateInstance(NS_CHARSET_DETECTOR_CONTRACTID_BASE
         583               0 :                         "universal_charset_detector");
         584               0 :   if (!detector) {
         585                 :     // No universal charset detector, try the default charset detector
         586                 :     const nsAdoptingCString& detectorName =
         587               0 :       Preferences::GetLocalizedCString("intl.charset.detector");
         588               0 :     if (!detectorName.IsEmpty()) {
         589               0 :       nsCAutoString detectorContractID;
         590               0 :       detectorContractID.AssignLiteral(NS_CHARSET_DETECTOR_CONTRACTID_BASE);
         591               0 :       detectorContractID += detectorName;
         592               0 :       detector = do_CreateInstance(detectorContractID.get());
         593                 :     }
         594                 :   }
         595                 :
         596                 :   nsresult rv;
         597                 :   // The charset detector doesn't work for empty (null) aFileData. Testing
         598                 :   // aDataLen instead of aFileData so that we catch potential errors.
         599               0 :   if (detector && aDataLen != 0) {
         600               0 :     mCharset.Truncate();
         601               0 :     detector->Init(this);
         602                 :
         603                 :     bool done;
         604                 :
         605               0 :     rv = detector->DoIt(aFileData, aDataLen, &done);
         606               0 :     NS_ENSURE_SUCCESS(rv, rv);
         607                 :
         608               0 :     rv = detector->Done();
         609               0 :     NS_ENSURE_SUCCESS(rv, rv);
         610                 :
         611               0 :     aCharset = mCharset;
         612                 :   } else {
         613                 :     // no charset detector available, check the BOM
         614                 :     unsigned char sniffBuf[3];
         615               0 :     PRUint32 numRead = (aDataLen >= sizeof(sniffBuf) ? sizeof(sniffBuf) : aDataLen);
         616               0 :     memcpy(sniffBuf, aFileData, numRead);
         617                 :
         618               0 :     if (numRead >= 2 &&
         619               0 :                sniffBuf[0] == 0xfe &&
         620               0 :                sniffBuf[1] == 0xff) {
         621               0 :       aCharset = "UTF-16BE";
         622               0 :     } else if (numRead >= 2 &&
         623               0 :                sniffBuf[0] == 0xff &&
         624               0 :                sniffBuf[1] == 0xfe) {
         625               0 :       aCharset = "UTF-16LE";
         626               0 :     } else if (numRead >= 3 &&
         627               0 :                sniffBuf[0] == 0xef &&
         628               0 :                sniffBuf[1] == 0xbb &&
         629               0 :                sniffBuf[2] == 0xbf) {
         630               0 :       aCharset = "UTF-8";
         631                 :     }
         632                 :   }
         633                 :
         634               0 :   if (aCharset.IsEmpty()) {
         635                 :     // no charset detected, default to the system charset
         636                 :     nsCOMPtr<nsIPlatformCharset> platformCharset =
         637               0 :       do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
         638               0 :     if (NS_SUCCEEDED(rv)) {
         639               0 :       rv = platformCharset->GetCharset(kPlatformCharsetSel_PlainTextInFile,
         640               0 :                                        aCharset);
         641                 :     }
         642                 :   }
         643                 :
         644               0 :   if (aCharset.IsEmpty()) {
         645                 :     // no sniffed or default charset, try UTF-8
         646               0 :     aCharset.AssignLiteral("UTF-8");
         647                 :   }
         648                 :
         649               0 :   return NS_OK;
         650            4392 : }

Generated by: LCOV version 1.7