webengine/osswebengine/WebCore/platform/network/symbian/FileConnection.cpp
changeset 0 dd21522fd290
child 25 0ed94ceaa377
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/WebCore/platform/network/symbian/FileConnection.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,336 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*
+*/
+
+#include <f32file.h>
+#include <uri8.h>
+#include <EscapeUtils.h>
+#include <apmrec.h>
+#include <apgcli.h>
+#include "ResourceHandle.h"
+#include "FileConnection.h"
+#include "FileReader.h"
+#include "ResourceHandleManagerSymbian.h"
+#include "StaticObjectsContainer.h"
+#include "ResourceRequest.h"
+#include <BrCtlSpecialLoadObserver.h>
+#include "brctl.h"
+#include "DeprecatedString.h"
+
+const TInt KFileReadChunkSize = 23920; // bytes
+_LIT8( KResLoaderUCS2, "iso-10646-ucs-2" );
+_LIT8( KResLoaderWapWmlc, "application/vnd.wap.wmlc" );
+
+
+static int s_fileTransactionsCount = 0;
+
+using namespace WebCore;
+
+FileConnection::FileConnection(ResourceHandle* _handle) : MUrlConnection(_handle)
+{
+    m_fileName = 0;
+    m_fileReader = 0;
+    s_fileTransactionsCount++;
+    m_chunkIndex = 0;
+    m_charset = 0;
+    m_contentType = 0;
+}
+
+FileConnection::~FileConnection()
+{
+    s_fileTransactionsCount--;
+    delete m_fileName;
+    delete m_fileReader;
+    delete m_charset;
+    delete m_contentType;
+    m_file.Close();
+}
+
+int FileConnection::submit()
+{
+    TRAPD(error, submitL());
+    return error;
+}
+
+void FileConnection::submitL()
+{
+    TPtrC8 urlPtr( m_handle->request().url().des() );
+    m_fileName = parseFileNameLC( urlPtr );
+    int submited;
+    if( m_fileName ) {
+        CleanupStack::Pop(); // m_fileName
+        submited = m_file.Open( StaticObjectsContainer::instance()->fsSession(), *m_fileName, EFileRead|EFileShareReadersOnly );
+        if( submited == KErrNone ) {
+            // set content max size info
+            TInt fileSize;
+            // ignore return value
+            m_file.Size( fileSize );
+            m_maxSize = fileSize;
+            // schedule a file read
+            m_fileReader = CFileReader::NewL( m_file, KFileReadChunkSize, this );
+            m_fileReader->StartReading();
+        }
+    }
+    else {
+        submited = KErrArgument;
+    }
+    User::LeaveIfError(submited);
+}
+
+// -----------------------------------------------------------------------------
+// FileConnection::parseFileNameLC
+// Translate the file name from a URL to a valid file name in the system.
+// -----------------------------------------------------------------------------
+//
+HBufC* FileConnection::parseFileNameLC(const TDesC8& aUrl )
+{
+    
+	//if url has mix of \ and / chars the parser gets confused in extracting the host and the path.
+	HBufC8* url = HBufC8::New( aUrl.Length() );
+	url->Des().Copy( aUrl );
+	TPtr8 urlPtr( url->Des() );
+	for( TInt i = 0; i < urlPtr.Length(); i++ ) {
+		if( urlPtr[ i ] == '\\' ) {
+			urlPtr[ i ] = '/';
+		}
+	}
+	
+	TInt status;
+    TUriParser8 parser;
+    HBufC8* fileName = NULL;
+	status = parser.Parse( urlPtr );
+    if( status == KErrNone ) {
+        // this must be the drive letter
+        TPtrC8 host = parser.Extract( EUriHost );
+        TPtrC8 path = parser.Extract( EUriPath );
+        // add missing ":"
+        fileName = HBufC8::NewLC( (host.Length()?host.Length()+1:0) + path.Length() );
+        TPtr8 fileNamePtr( fileName->Des() );
+        if( host.Length() == 1 ) {
+            // fix c to c:
+            fileNamePtr.Copy( host );
+            fileNamePtr.Append( _L(":") );
+        }
+        else {
+            // according to symbian uri parser in case of
+            // file:///c:\foo.html
+            // host: /c:\foo.html
+            // path: /c:\foo.html
+            // remove: / from the begenning of the path
+            if( path.Length() > 2 && path[0] == '/' && path[2] == ':' ) {
+                // move pointer from "/c:\" to "c:\"
+                path.Set( path.Mid( 1 ) );
+            }
+        }
+        HBufC8* fileUriPath = NULL;
+        TRAP_IGNORE(fileUriPath = EscapeUtils::EscapeDecodeL(path));    
+        if (fileUriPath) {
+            fileNamePtr.Append(*fileUriPath);    
+        }
+        else {            
+            fileNamePtr.Append( path );
+        }        
+        delete fileUriPath;
+        // fix slashes
+        for( TInt i = 0; i < fileNamePtr.Length(); i++ ) {
+            if( fileNamePtr[ i ] == '/' ) {
+                fileNamePtr[ i ] = '\\';
+            }
+        }
+    }
+    HBufC* fileName16 = NULL;
+    if( fileName ) {
+        fileName16 = HBufC::NewL( fileName->Length() );
+        fileName16->Des().Copy( *fileName );
+        CleanupStack::PopAndDestroy(); // filename
+        CleanupStack::PushL( fileName16 );
+    }
+	delete url;
+    return fileName16;
+}
+
+void FileConnection::cancel()
+{
+    if( m_fileReader ) {
+        m_fileReader->StopReading();
+        complete( KErrCancel ); 
+    }
+}
+
+void FileConnection::download(WebCore::ResourceHandle* handle,
+                              const WebCore::ResourceRequest& request,
+                              const WebCore::ResourceResponse& response)
+{
+    // stop reading and close the file
+    m_fileReader->StopReading();
+    m_cancelled = true;
+    m_file.Close();
+    // send data to the host application
+    MBrCtlSpecialLoadObserver* loadObserver = StaticObjectsContainer::instance()->brctl()->brCtlSpecialLoadObserver();
+    if(loadObserver) {
+        RArray<TUint> typeArray;
+        CDesCArrayFlat* desArray = new (ELeave) CDesCArrayFlat(4);
+        CleanupStack::PushL(desArray);
+        //
+        HBufC* url = HBufC::NewLC(handle->request().url().url().length());
+        url->Des().Copy(handle->request().url().des());
+        typeArray.Append(EParamRequestUrl);
+        desArray->AppendL(*url);
+
+        typeArray.Append(EParamCharset);
+        desArray->AppendL(*m_charset);
+
+        typeArray.Append(EParamReceivedContentType);
+        desArray->AppendL(*m_contentType);
+
+        typeArray.Append(EParamLocalFileName);
+        desArray->AppendL(*m_fileName);
+        //
+        loadObserver->HandleDownloadL(&typeArray, desArray);
+        //
+        typeArray.Close();
+        desArray->Reset();
+        CleanupStack::PopAndDestroy(2); // desArray, url 
+    }
+}
+
+// -----------------------------------------------------------------------------
+// FileConnection::contentTypeL
+// Determine the content type of the file.
+// -----------------------------------------------------------------------------
+HBufC8* FileConnection::contentTypeL()
+{
+    TPtrC8 contentTypePtr;
+    HBufC8* contentType = NULL;
+    TDataRecognitionResult dataType;
+    RApaLsSession apaSession;
+    TInt ret;
+    
+    User::LeaveIfError( apaSession.Connect() );
+    // Ask the application architecture to find the file type
+    TPtrC8 chunkPtr;
+    
+    m_fileReader->GetChunkBuffer( chunkPtr );
+    ret = apaSession.RecognizeData( m_fileName->Des(), chunkPtr, dataType );
+    apaSession.Close();
+    
+    if( ret == KErrNone &&
+        ( dataType.iConfidence == CApaDataRecognizerType::ECertain ) ||
+        ( dataType.iConfidence == CApaDataRecognizerType::EProbable ) ) {
+        // If the file type was found, try to match it to a known file type
+        contentTypePtr.Set( dataType.iDataType.Des8() );
+    }
+    else {
+        // extensions
+        _LIT( KCssExt, ".css" );
+        _LIT(KWbmpExt, ".wbmp");
+        _LIT(KEcmaScriptExt, ".es");
+        _LIT(KJavaScriptExt, ".js");
+        
+        TPtrC extPtr( m_fileName->Right( m_fileName->Length() -  m_fileName->LocateReverse('.') ) );
+        
+        if( extPtr.CompareF( KCssExt() ) == 0 ) {
+            contentTypePtr.Set( _L8( "text/css" ) );
+        }
+        else if( extPtr.CompareF( KWbmpExt() ) == 0 ) {
+            contentTypePtr.Set( _L8( "image/vnd.wap.wbmp" ) );
+        }
+        else if( extPtr.CompareF( KEcmaScriptExt() ) == 0 ||
+            extPtr.CompareF( KJavaScriptExt() ) == 0 ) {
+            contentTypePtr.Set( _L8( "text/ecmascript" ) );
+        }
+
+        // todo plugin is missing
+        // Check if it is a supported plugin
+        // CPluginHandler* pluginHandler = CPluginHandler::GetSingleton();
+        // TUint16* mimeType16 = pluginHandler->GetPluginMimeTypeL(iFileName);
+    }
+    if( contentTypePtr.Length() ) {
+        contentType = HBufC8::NewL( contentTypePtr.Length() );
+        contentType->Des().Copy( contentTypePtr );
+    }
+    return contentType;
+}
+
+// -----------------------------------------------------------------------------
+// FileConnection::contentEncoding
+// Determine the content encoding of the file.
+// -----------------------------------------------------------------------------
+//
+TPtrC8 FileConnection::contentEncoding(const TDesC8& aContentTypeString ) const
+{
+    // Assume Latin-1 for xhtml and html. ucs2 for any other
+    TPtrC8 charset( KNullDesC8 );
+
+    TPtrC8 httpAppString( KResLoaderWapWmlc );
+    TPtrC8 contentString( aContentTypeString );
+
+    // Is the contentType a HTTP_application_vnd_wap_wmlc_string
+    TUint index = contentString.FindF( httpAppString );
+    if( index == 0 ) {
+        // This is a HTTP_application_vnd_wap_wmlc_string
+        charset.Set( KResLoaderUCS2 );
+    }
+    return charset;
+}
+
+void FileConnection::response()
+{
+    TRAPD(error, responseL());
+    if (error) {
+        complete(error);
+    }        
+}
+
+void FileConnection::responseL()
+{
+    if (m_chunkIndex == 0 ) {
+        HBufC8* contentType = contentTypeL();
+
+        if( contentType ) {
+            m_contentType = HBufC::NewL(contentType->Length());
+            m_contentType->Des().Copy(*contentType);
+
+            TPtrC8 contentEncodingPtr( contentEncoding( contentType->Des() ) );
+            ResourceResponse response(m_handle->request().url().des(), contentType->Des(), m_maxSize, contentEncodingPtr, String() );
+
+
+            const TDesC& charset = response.textEncodingName().des();
+            m_charset = charset.AllocL();
+            response.setHTTPStatusCode(200);
+
+            CResourceHandleManager::self()->receivedResponse(m_handle, response, this);
+        }
+        
+       delete contentType;
+    }
+    // If it is not Browser content, reading the file is canceled in FileConnection::download().
+    if (!m_cancelled) {
+        TPtrC8 chunkPtr;
+        m_fileReader->GetChunkBuffer( chunkPtr );    
+        m_chunkIndex++;
+        CResourceHandleManager::self()->receivedData(m_handle, chunkPtr, m_maxSize, this);
+    }
+}
+
+void FileConnection::complete(int error)
+{
+    CResourceHandleManager::self()->receivedFinished(m_handle, error, this);
+    derefHandle();
+}
+
+
+// end of file