webengine/osswebengine/WebCore/platform/network/symbian/FileConnection.cpp
changeset 0 dd21522fd290
child 36 0ed94ceaa377
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *
       
    16 */
       
    17 
       
    18 #include <f32file.h>
       
    19 #include <uri8.h>
       
    20 #include <EscapeUtils.h>
       
    21 #include <apmrec.h>
       
    22 #include <apgcli.h>
       
    23 #include "ResourceHandle.h"
       
    24 #include "FileConnection.h"
       
    25 #include "FileReader.h"
       
    26 #include "ResourceHandleManagerSymbian.h"
       
    27 #include "StaticObjectsContainer.h"
       
    28 #include "ResourceRequest.h"
       
    29 #include <BrCtlSpecialLoadObserver.h>
       
    30 #include "brctl.h"
       
    31 #include "DeprecatedString.h"
       
    32 
       
    33 const TInt KFileReadChunkSize = 23920; // bytes
       
    34 _LIT8( KResLoaderUCS2, "iso-10646-ucs-2" );
       
    35 _LIT8( KResLoaderWapWmlc, "application/vnd.wap.wmlc" );
       
    36 
       
    37 
       
    38 static int s_fileTransactionsCount = 0;
       
    39 
       
    40 using namespace WebCore;
       
    41 
       
    42 FileConnection::FileConnection(ResourceHandle* _handle) : MUrlConnection(_handle)
       
    43 {
       
    44     m_fileName = 0;
       
    45     m_fileReader = 0;
       
    46     s_fileTransactionsCount++;
       
    47     m_chunkIndex = 0;
       
    48     m_charset = 0;
       
    49     m_contentType = 0;
       
    50 }
       
    51 
       
    52 FileConnection::~FileConnection()
       
    53 {
       
    54     s_fileTransactionsCount--;
       
    55     delete m_fileName;
       
    56     delete m_fileReader;
       
    57     delete m_charset;
       
    58     delete m_contentType;
       
    59     m_file.Close();
       
    60 }
       
    61 
       
    62 int FileConnection::submit()
       
    63 {
       
    64     TRAPD(error, submitL());
       
    65     return error;
       
    66 }
       
    67 
       
    68 void FileConnection::submitL()
       
    69 {
       
    70     TPtrC8 urlPtr( m_handle->request().url().des() );
       
    71     m_fileName = parseFileNameLC( urlPtr );
       
    72     int submited;
       
    73     if( m_fileName ) {
       
    74         CleanupStack::Pop(); // m_fileName
       
    75         submited = m_file.Open( StaticObjectsContainer::instance()->fsSession(), *m_fileName, EFileRead|EFileShareReadersOnly );
       
    76         if( submited == KErrNone ) {
       
    77             // set content max size info
       
    78             TInt fileSize;
       
    79             // ignore return value
       
    80             m_file.Size( fileSize );
       
    81             m_maxSize = fileSize;
       
    82             // schedule a file read
       
    83             m_fileReader = CFileReader::NewL( m_file, KFileReadChunkSize, this );
       
    84             m_fileReader->StartReading();
       
    85         }
       
    86     }
       
    87     else {
       
    88         submited = KErrArgument;
       
    89     }
       
    90     User::LeaveIfError(submited);
       
    91 }
       
    92 
       
    93 // -----------------------------------------------------------------------------
       
    94 // FileConnection::parseFileNameLC
       
    95 // Translate the file name from a URL to a valid file name in the system.
       
    96 // -----------------------------------------------------------------------------
       
    97 //
       
    98 HBufC* FileConnection::parseFileNameLC(const TDesC8& aUrl )
       
    99 {
       
   100     
       
   101 	//if url has mix of \ and / chars the parser gets confused in extracting the host and the path.
       
   102 	HBufC8* url = HBufC8::New( aUrl.Length() );
       
   103 	url->Des().Copy( aUrl );
       
   104 	TPtr8 urlPtr( url->Des() );
       
   105 	for( TInt i = 0; i < urlPtr.Length(); i++ ) {
       
   106 		if( urlPtr[ i ] == '\\' ) {
       
   107 			urlPtr[ i ] = '/';
       
   108 		}
       
   109 	}
       
   110 	
       
   111 	TInt status;
       
   112     TUriParser8 parser;
       
   113     HBufC8* fileName = NULL;
       
   114 	status = parser.Parse( urlPtr );
       
   115     if( status == KErrNone ) {
       
   116         // this must be the drive letter
       
   117         TPtrC8 host = parser.Extract( EUriHost );
       
   118         TPtrC8 path = parser.Extract( EUriPath );
       
   119         // add missing ":"
       
   120         fileName = HBufC8::NewLC( (host.Length()?host.Length()+1:0) + path.Length() );
       
   121         TPtr8 fileNamePtr( fileName->Des() );
       
   122         if( host.Length() == 1 ) {
       
   123             // fix c to c:
       
   124             fileNamePtr.Copy( host );
       
   125             fileNamePtr.Append( _L(":") );
       
   126         }
       
   127         else {
       
   128             // according to symbian uri parser in case of
       
   129             // file:///c:\foo.html
       
   130             // host: /c:\foo.html
       
   131             // path: /c:\foo.html
       
   132             // remove: / from the begenning of the path
       
   133             if( path.Length() > 2 && path[0] == '/' && path[2] == ':' ) {
       
   134                 // move pointer from "/c:\" to "c:\"
       
   135                 path.Set( path.Mid( 1 ) );
       
   136             }
       
   137         }
       
   138         HBufC8* fileUriPath = NULL;
       
   139         TRAP_IGNORE(fileUriPath = EscapeUtils::EscapeDecodeL(path));    
       
   140         if (fileUriPath) {
       
   141             fileNamePtr.Append(*fileUriPath);    
       
   142         }
       
   143         else {            
       
   144             fileNamePtr.Append( path );
       
   145         }        
       
   146         delete fileUriPath;
       
   147         // fix slashes
       
   148         for( TInt i = 0; i < fileNamePtr.Length(); i++ ) {
       
   149             if( fileNamePtr[ i ] == '/' ) {
       
   150                 fileNamePtr[ i ] = '\\';
       
   151             }
       
   152         }
       
   153     }
       
   154     HBufC* fileName16 = NULL;
       
   155     if( fileName ) {
       
   156         fileName16 = HBufC::NewL( fileName->Length() );
       
   157         fileName16->Des().Copy( *fileName );
       
   158         CleanupStack::PopAndDestroy(); // filename
       
   159         CleanupStack::PushL( fileName16 );
       
   160     }
       
   161 	delete url;
       
   162     return fileName16;
       
   163 }
       
   164 
       
   165 void FileConnection::cancel()
       
   166 {
       
   167     if( m_fileReader ) {
       
   168         m_fileReader->StopReading();
       
   169         complete( KErrCancel ); 
       
   170     }
       
   171 }
       
   172 
       
   173 void FileConnection::download(WebCore::ResourceHandle* handle,
       
   174                               const WebCore::ResourceRequest& request,
       
   175                               const WebCore::ResourceResponse& response)
       
   176 {
       
   177     // stop reading and close the file
       
   178     m_fileReader->StopReading();
       
   179     m_cancelled = true;
       
   180     m_file.Close();
       
   181     // send data to the host application
       
   182     MBrCtlSpecialLoadObserver* loadObserver = StaticObjectsContainer::instance()->brctl()->brCtlSpecialLoadObserver();
       
   183     if(loadObserver) {
       
   184         RArray<TUint> typeArray;
       
   185         CDesCArrayFlat* desArray = new (ELeave) CDesCArrayFlat(4);
       
   186         CleanupStack::PushL(desArray);
       
   187         //
       
   188         HBufC* url = HBufC::NewLC(handle->request().url().url().length());
       
   189         url->Des().Copy(handle->request().url().des());
       
   190         typeArray.Append(EParamRequestUrl);
       
   191         desArray->AppendL(*url);
       
   192 
       
   193         typeArray.Append(EParamCharset);
       
   194         desArray->AppendL(*m_charset);
       
   195 
       
   196         typeArray.Append(EParamReceivedContentType);
       
   197         desArray->AppendL(*m_contentType);
       
   198 
       
   199         typeArray.Append(EParamLocalFileName);
       
   200         desArray->AppendL(*m_fileName);
       
   201         //
       
   202         loadObserver->HandleDownloadL(&typeArray, desArray);
       
   203         //
       
   204         typeArray.Close();
       
   205         desArray->Reset();
       
   206         CleanupStack::PopAndDestroy(2); // desArray, url 
       
   207     }
       
   208 }
       
   209 
       
   210 // -----------------------------------------------------------------------------
       
   211 // FileConnection::contentTypeL
       
   212 // Determine the content type of the file.
       
   213 // -----------------------------------------------------------------------------
       
   214 HBufC8* FileConnection::contentTypeL()
       
   215 {
       
   216     TPtrC8 contentTypePtr;
       
   217     HBufC8* contentType = NULL;
       
   218     TDataRecognitionResult dataType;
       
   219     RApaLsSession apaSession;
       
   220     TInt ret;
       
   221     
       
   222     User::LeaveIfError( apaSession.Connect() );
       
   223     // Ask the application architecture to find the file type
       
   224     TPtrC8 chunkPtr;
       
   225     
       
   226     m_fileReader->GetChunkBuffer( chunkPtr );
       
   227     ret = apaSession.RecognizeData( m_fileName->Des(), chunkPtr, dataType );
       
   228     apaSession.Close();
       
   229     
       
   230     if( ret == KErrNone &&
       
   231         ( dataType.iConfidence == CApaDataRecognizerType::ECertain ) ||
       
   232         ( dataType.iConfidence == CApaDataRecognizerType::EProbable ) ) {
       
   233         // If the file type was found, try to match it to a known file type
       
   234         contentTypePtr.Set( dataType.iDataType.Des8() );
       
   235     }
       
   236     else {
       
   237         // extensions
       
   238         _LIT( KCssExt, ".css" );
       
   239         _LIT(KWbmpExt, ".wbmp");
       
   240         _LIT(KEcmaScriptExt, ".es");
       
   241         _LIT(KJavaScriptExt, ".js");
       
   242         
       
   243         TPtrC extPtr( m_fileName->Right( m_fileName->Length() -  m_fileName->LocateReverse('.') ) );
       
   244         
       
   245         if( extPtr.CompareF( KCssExt() ) == 0 ) {
       
   246             contentTypePtr.Set( _L8( "text/css" ) );
       
   247         }
       
   248         else if( extPtr.CompareF( KWbmpExt() ) == 0 ) {
       
   249             contentTypePtr.Set( _L8( "image/vnd.wap.wbmp" ) );
       
   250         }
       
   251         else if( extPtr.CompareF( KEcmaScriptExt() ) == 0 ||
       
   252             extPtr.CompareF( KJavaScriptExt() ) == 0 ) {
       
   253             contentTypePtr.Set( _L8( "text/ecmascript" ) );
       
   254         }
       
   255 
       
   256         // todo plugin is missing
       
   257         // Check if it is a supported plugin
       
   258         // CPluginHandler* pluginHandler = CPluginHandler::GetSingleton();
       
   259         // TUint16* mimeType16 = pluginHandler->GetPluginMimeTypeL(iFileName);
       
   260     }
       
   261     if( contentTypePtr.Length() ) {
       
   262         contentType = HBufC8::NewL( contentTypePtr.Length() );
       
   263         contentType->Des().Copy( contentTypePtr );
       
   264     }
       
   265     return contentType;
       
   266 }
       
   267 
       
   268 // -----------------------------------------------------------------------------
       
   269 // FileConnection::contentEncoding
       
   270 // Determine the content encoding of the file.
       
   271 // -----------------------------------------------------------------------------
       
   272 //
       
   273 TPtrC8 FileConnection::contentEncoding(const TDesC8& aContentTypeString ) const
       
   274 {
       
   275     // Assume Latin-1 for xhtml and html. ucs2 for any other
       
   276     TPtrC8 charset( KNullDesC8 );
       
   277 
       
   278     TPtrC8 httpAppString( KResLoaderWapWmlc );
       
   279     TPtrC8 contentString( aContentTypeString );
       
   280 
       
   281     // Is the contentType a HTTP_application_vnd_wap_wmlc_string
       
   282     TUint index = contentString.FindF( httpAppString );
       
   283     if( index == 0 ) {
       
   284         // This is a HTTP_application_vnd_wap_wmlc_string
       
   285         charset.Set( KResLoaderUCS2 );
       
   286     }
       
   287     return charset;
       
   288 }
       
   289 
       
   290 void FileConnection::response()
       
   291 {
       
   292     TRAPD(error, responseL());
       
   293     if (error) {
       
   294         complete(error);
       
   295     }        
       
   296 }
       
   297 
       
   298 void FileConnection::responseL()
       
   299 {
       
   300     if (m_chunkIndex == 0 ) {
       
   301         HBufC8* contentType = contentTypeL();
       
   302 
       
   303         if( contentType ) {
       
   304             m_contentType = HBufC::NewL(contentType->Length());
       
   305             m_contentType->Des().Copy(*contentType);
       
   306 
       
   307             TPtrC8 contentEncodingPtr( contentEncoding( contentType->Des() ) );
       
   308             ResourceResponse response(m_handle->request().url().des(), contentType->Des(), m_maxSize, contentEncodingPtr, String() );
       
   309 
       
   310 
       
   311             const TDesC& charset = response.textEncodingName().des();
       
   312             m_charset = charset.AllocL();
       
   313             response.setHTTPStatusCode(200);
       
   314 
       
   315             CResourceHandleManager::self()->receivedResponse(m_handle, response, this);
       
   316         }
       
   317         
       
   318        delete contentType;
       
   319     }
       
   320     // If it is not Browser content, reading the file is canceled in FileConnection::download().
       
   321     if (!m_cancelled) {
       
   322         TPtrC8 chunkPtr;
       
   323         m_fileReader->GetChunkBuffer( chunkPtr );    
       
   324         m_chunkIndex++;
       
   325         CResourceHandleManager::self()->receivedData(m_handle, chunkPtr, m_maxSize, this);
       
   326     }
       
   327 }
       
   328 
       
   329 void FileConnection::complete(int error)
       
   330 {
       
   331     CResourceHandleManager::self()->receivedFinished(m_handle, error, this);
       
   332     derefHandle();
       
   333 }
       
   334 
       
   335 
       
   336 // end of file