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