webengine/osswebengine/cache/src/HttpCacheManager.cpp
changeset 0 dd21522fd290
child 1 7c90e6132015
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/cache/src/HttpCacheManager.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,806 @@
+/*
+* Copyright (c) 2006 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:  Implementation of CHttpCacheManager
+*
+*/
+
+// INCLUDE FILES
+#include "HttpCacheManager.h"
+#include "HttpCacheHandler.h"
+#include "HttpCacheUtil.h"
+#include <CenRepNotifyHandler.h>
+#include <HttpCacheManagerInternalCRKeys.h>
+#include <CoreApplicationUIsSDKCRKeys.h>
+#include <centralrepository.h>
+#include <FeatMgr.h>
+#include <http/RHTTPTransaction.h>
+#include <SysUtilDomainCRKeys.h>
+#include <eikenv.h>
+#include <f32file.h>
+#include <e32hashtab.h>
+#include <mmf/common/mmfcontrollerpluginresolver.h>
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES
+
+// CONSTANTS
+
+// kbyte
+const TUint KDefaultCacheSize = 1048576; // 1MB = 1024*1024
+_LIT( KDefaultCacheDir, "c:\\cache\\");
+_LIT( KDefaultIndexFile, "index.dat" );
+_LIT( KDefaultOpIndexFile, "index_op.dat" );
+_LIT( KDefaultVSSIndexFile, "index_vss.dat" );
+_LIT( KIndexFileExtension, ".dat" );
+_LIT8( KVSSHeaderFileldName, "X-Vodafone-Content" );
+_LIT8( KVSSHeaderFileldValue, "Portal" );
+
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::CHttpCacheManager
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CHttpCacheManager::CHttpCacheManager():iCacheFolder( KDefaultCacheDir )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CHttpCacheManager::ConstructL()
+    {
+    CreateCacheHandlersL();
+
+    // read offline mode
+    if( FeatureManager::FeatureSupported( KFeatureIdOfflineMode ) )
+        {
+        // check if connection is not allowed and
+        // come up with a listerner on the offline setting
+        TInt connAllowed( 1 );
+
+        iOfflineRepository = CRepository::NewL( KCRUidCoreApplicationUIs );
+
+        iOfflineRepository->Get( KCoreAppUIsNetworkConnectionAllowed, connAllowed );
+
+        iOfflineMode = !connAllowed;
+
+        iOfflineNotifyHandler = CCenRepNotifyHandler::NewL( *this, *iOfflineRepository,
+            CCenRepNotifyHandler::EIntKey, (TUint32)KCoreAppUIsNetworkConnectionAllowed );
+        iOfflineNotifyHandler->StartListeningL();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CHttpCacheManager* CHttpCacheManager::NewL()
+    {
+    CHttpCacheManager* self = new( ELeave ) CHttpCacheManager();
+
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+
+    return self;
+    }
+
+// Destructor
+CHttpCacheManager::~CHttpCacheManager()
+    {
+    delete iOfflineNotifyHandler;
+    delete iOfflineRepository;
+    delete iCache;
+    delete iOperatorCache;
+    delete iOpDomain;
+    delete iphoneSpecificCache;
+    delete iVSSWhiteList;
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::VSSRequestCheck
+//
+// -----------------------------------------------------------------------------
+//
+TBool CHttpCacheManager::VSSRequestCheck( const RHTTPTransaction& aTrans,
+                                          const RHTTPHeaders& aHttpHeader,
+                                          const TDesC8& aUrl )
+    {
+    TBool VSSTransaction ( EFalse );
+    if( iVSSCacheEnabled && HttpCacheUtil::VSSCacheContent( aUrl, iVSSWhiteList ) )
+        {
+        RStringPool strP = aTrans.Session().StringPool();
+
+#ifdef __CACHELOG__
+        RHTTPHeaders headers ( aHttpHeader );
+        HBufC8* responseHeaderStr8 = HttpCacheUtil::HeadersToBufferLC( headers, strP );
+        HBufC* responseHeaderStr;
+        if( responseHeaderStr8 )
+            {
+            responseHeaderStr = HBufC::NewL( responseHeaderStr8->Length() );
+            responseHeaderStr->Des().Copy( responseHeaderStr8->Des() );
+            CleanupStack::PopAndDestroy(); //  responseHeaderStr8;
+            TPtrC headerStr( responseHeaderStr->Des() );
+            HttpCacheUtil::WriteLog( 0, _L("========== VSS Header Start =========\n") );
+            HttpCacheUtil::WriteLog( 0, responseHeaderStr->Des() );
+            HttpCacheUtil::WriteLog( 0, _L("========== VSS Header End =========\n") );
+            delete responseHeaderStr;
+            }
+#endif
+
+        TPtrC8 nameStr ( KVSSHeaderFileldName() );
+
+        RStringF VSSnameStr = strP.OpenFStringL( nameStr );
+        CleanupClosePushL<RStringF>( VSSnameStr);
+
+        THTTPHdrVal tempVal;
+        if( aHttpHeader.GetField( VSSnameStr, 0, tempVal ) == KErrNone )
+            {
+            TPtrC8 valueStr ( KVSSHeaderFileldValue() );
+            RStringF VSSValueStr = strP.OpenFStringL( valueStr );
+            CleanupClosePushL<RStringF>( VSSValueStr );
+
+            if( tempVal == VSSValueStr )
+                {
+                VSSTransaction      = ETrue;
+                }
+            CleanupStack::PopAndDestroy(); // VSSValueStr
+            }
+        CleanupStack::PopAndDestroy(); // VSSnameStr
+        } //end if( iVSSCacheEnabled && HttpCacheUtil::VSSCacheContent( aUrl, iVSSWhiteList ) )
+    return VSSTransaction;
+    }
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::RequestL
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CHttpCacheManager::RequestL(
+    RHTTPTransaction& aTrans,
+    TBrCtlDefs::TBrCtlCacheMode aCacheMode,
+    THttpCacheEntry& aCacheEntry )
+    {
+    //
+    TInt status( KErrNotFound );
+    if( iCacheEnabled || iVSSCacheEnabled )
+        {
+        CHttpCacheHandler* cache = CacheHandler( aTrans.Request().URI().UriDes(), NULL ) ;
+        __ASSERT_DEBUG( cache, User::Panic( _L("cacheHandler Panic"), KErrCorrupt ) );
+        // adjust cache mode in case of offline operation
+        if( iOfflineMode )
+            {
+            aCacheMode = TBrCtlDefs::ECacheModeOnlyCache;
+            }
+        //
+        if( cache )
+            {
+            status = cache->RequestL( aTrans, aCacheMode, aCacheEntry );
+            // save cache handler even if the entry is not in the cache
+            // so that when the response comes back, we do not need to
+            // check the url
+             if( status == KErrNotFound && iVSSCacheEnabled )
+                {
+                 status = iphoneSpecificCache->RequestL( aTrans, aCacheMode, aCacheEntry );
+                 if( (status  == KErrNotReady) || (status == KErrNone ) )
+                 {
+                 aCacheEntry.iCacheHandler = iphoneSpecificCache; 
+                 }
+                 else
+                 {
+                 // No entry found in any cache. Default to normal cache
+                 aCacheEntry.iCacheHandler = cache;   
+                 }
+                } 
+            else
+            {
+            aCacheEntry.iCacheHandler = cache;  
+            }                
+           } //end if( cache )
+
+        }//end  if( iCacheEnabled || iVSSCacheEnabled )
+    return status;
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::RequestHeadersL
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CHttpCacheManager::RequestHeadersL(
+    RHTTPTransaction& aTrans,
+    THttpCacheEntry& aCacheEntry )
+    {
+    TInt status( KErrNotFound );
+    if( ( iCacheEnabled || iVSSCacheEnabled ) && aCacheEntry.iCacheHandler )
+        {
+        status = aCacheEntry.iCacheHandler->RequestHeadersL( aTrans, aCacheEntry );
+        }
+    return status;
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::RequestNextChunkL
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C HBufC8* CHttpCacheManager::RequestNextChunkL(
+    RHTTPTransaction& aTrans,
+    TBool& aLastChunk,
+    THttpCacheEntry& aCacheEntry )
+    {
+    HBufC8* bodyStr = NULL;
+
+    if( ( iCacheEnabled || iVSSCacheEnabled ) && aCacheEntry.iCacheHandler )
+        {
+        bodyStr = aCacheEntry.iCacheHandler->RequestNextChunkL( aTrans, aLastChunk, aCacheEntry );
+        }
+    return bodyStr;
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::RequestClosed
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpCacheManager::RequestClosed(
+    RHTTPTransaction* aTrans,
+    THttpCacheEntry& aCacheEntry )
+    {
+    if( ( iCacheEnabled || iVSSCacheEnabled ) && aCacheEntry.iCacheHandler )
+        {
+        aCacheEntry.iCacheHandler->RequestClosed( aTrans, aCacheEntry );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::ReceivedResponseHeadersL
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpCacheManager::ReceivedResponseHeadersL(
+  RHTTPTransaction& aTrans,
+    THttpCacheEntry& aCacheEntry )
+    {
+    if( iCacheEnabled || iVSSCacheEnabled )
+        {
+        if( iVSSCacheEnabled && VSSRequestCheck( aTrans, aTrans.Response().GetHeaderCollection(),
+            aTrans.Request().URI().UriDes() ) )
+            {
+            //Modify the cache handler if VSS specific
+            aCacheEntry.iCacheHandler = iphoneSpecificCache;
+            }
+        if( aCacheEntry.iCacheHandler )
+            {
+            aCacheEntry.iCacheHandler->ReceivedResponseHeadersL( aTrans, aCacheEntry );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::ReceivedResponseBodyDataL
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpCacheManager::ReceivedResponseBodyDataL(
+  RHTTPTransaction& aTrans,
+    MHTTPDataSupplier& aBodyDataSupplier,
+    THttpCacheEntry& aCacheEntry )
+    {
+    if( ( iCacheEnabled || iVSSCacheEnabled ) && aCacheEntry.iCacheHandler )
+        {
+        aCacheEntry.iCacheHandler->ReceivedResponseBodyDataL( aTrans, aBodyDataSupplier, aCacheEntry );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::ResponseComplete
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpCacheManager::ResponseComplete(
+    RHTTPTransaction& aTrans,
+    THttpCacheEntry& aCacheEntry )
+    {
+    if( ( iCacheEnabled || iVSSCacheEnabled ) && aCacheEntry.iCacheHandler )
+        {
+        aCacheEntry.iCacheHandler->ResponseComplete( aTrans, aCacheEntry );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::RemoveAllL
+// Removes all files from HTTP cache. Also tries to remove orphaned files, 
+// i.e files found on disk, but not registered in the cache's lookup table
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CHttpCacheManager::RemoveAllL()
+    {
+    TInt numOfBytes( 0 );
+    // do not remove op cache
+    if( iCacheEnabled )
+        {
+        numOfBytes = iCache->RemoveAllL();
+        }
+        
+    //failure here is not mission critical
+    TRAPD( error, RemoveOrphanedFilesL() ); 
+    
+    return numOfBytes;
+    }
+
+
+// Hash function for Symbian file paths: discards case first
+static TUint32 FilepathHash(const TDesC& aDes)
+{
+    //since this function is intensively used by the HashMap, 
+    //keeping (slow) heap allocation out of it. 
+    TBuf<KMaxPath> normalized ( aDes ); 
+     
+    normalized.LowerCase();
+    return DefaultHash::Des16( normalized );
+}
+
+// Comparator for Symbian file paths: Use case-insensitive compare  
+static TBool FilepathIdent(const TDesC& aL, const TDesC& aR)
+{
+    return ( aL.CompareF(aR) == 0 );  
+}
+
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::RemoveOrphanedFilesL 
+// Removes header/body files that exist on the file-system, but are not known to the in-memory Cache lookup table(s)
+// We do this because cache performance degrades substantially if there are too many files in a Symbian FAT32 directory. 
+// Browser crash or out-of-battery situations may cause SaveLookuptable() to be not called, leading to such "orphaned files". 
+// Due to high file-server interaction, don't call this method from performance critical code. 
+// -----------------------------------------------------------------------------
+void CHttpCacheManager::RemoveOrphanedFilesL()
+    {
+
+    //Map that contains pointers to fully-qualified file paths as Keys, and "to be deleted flag" as Value. 
+    RPtrHashMap<TDesC, TInt> onDiskFilesMap(&FilepathHash, &FilepathIdent);
+    CleanupClosePushL( onDiskFilesMap );
+
+    //Pointers to the following TInt are used as VALUES in the HashMap...
+    // so they must be in scope for the lifecycle of the HashMap.
+    const TInt needsDelete( 1 );
+    const TInt noDelete( 0 );
+
+    //collects objects that need to be deleted later on 
+    RPointerArray<HBufC> cleanupList;
+    CleanupResetAndDestroyPushL( cleanupList );
+
+    RFs rfs = CCoeEnv::Static()->FsSession();
+    CDirScan* scanner = CDirScan::NewLC( rfs );
+
+    //Configure CDirScan to tell you all contents of a particular directory hierarchy
+    scanner->SetScanDataL( iCacheFolder, KEntryAttNormal, ESortNone );
+    CDir* matchingFiles( 0 );
+
+    //Step 1. Find out all files on disk: by walking the directory hierarchy, one directory at a time
+    for (;;)
+        {
+        //1a. Get list of files in current directory, NULL if no directory left in tree 
+        scanner->NextL( matchingFiles );
+        if ( !matchingFiles )
+            break;
+
+        TPtrC dir( scanner->FullPath() );       
+        
+        //1b. Add any files found to the HashTable
+        const TInt nMatches = matchingFiles->Count();
+        for ( TInt i = 0; i < nMatches; i++ )
+            {
+            TEntry entry ( (*matchingFiles)[i] ) ; 
+            if (entry.iName.Right( KIndexFileExtension().Length() ).
+                    CompareF( KIndexFileExtension ) != 0) // ignore any .dat index files
+                {
+                HBufC* fullPath = HBufC::NewL( dir.Length() +  entry.iName.Length() );
+                cleanupList.Append( fullPath ); //keep object safe for later destruction
+                fullPath->Des().Append( dir );
+                fullPath->Des().Append( entry.iName ); //a fully qualified file path
+                onDiskFilesMap.Insert( fullPath, &needsDelete ); //add to the hash
+                }
+            }
+            
+
+        delete matchingFiles;
+        } // End of step 1: adding all known files on disk to Map
+
+    CleanupStack::PopAndDestroy( 1, scanner );
+
+#ifdef __CACHELOG__
+    {
+    RDebug::Print(_L("-----------START PRINTING MAP OF SIZE %d---------"), onDiskFilesMap.Count());
+    TPtrHashMapIter<TDesC, TInt> iter(onDiskFilesMap);
+    const TDesC* key;
+    while ((key = iter.NextKey()) != 0)
+        {
+        const TInt val = *(iter.CurrentValue());
+        RDebug::Print(_L("MAP WALK: %S, with value = %d "), key, val);
+        }
+    RDebug::Print(_L("-----------DONE PRINTING MAP-------------"));
+    }
+#endif
+    
+    //Step 2. Get list of known (non-orphaned) files in each Cache's in-memory lookup table. Flag them as DO NOT DELETE
+    RPointerArray<TDesC> knownFiles; 
+    CleanupClosePushL( knownFiles );
+    //Ask CacheHandlers to add their KNOWN files to this array. No ownership transfer occurs. 
+    //Don't go ahead if any of the cache handlers choke to insure correct deletion of files.
+    if (iCache)
+        User::LeaveIfError( iCache->ListFiles( knownFiles ) ); 
+    if (iOperatorCache)
+        User::LeaveIfError( iOperatorCache->ListFiles( knownFiles ) );
+    if (iphoneSpecificCache)
+        User::LeaveIfError( iphoneSpecificCache->ListFiles( knownFiles ) ); 
+
+    //2a. HashTable lookup, and modification of flag
+    for (TInt i = 0; i < knownFiles.Count(); i++)
+        {
+        //lookup filename
+        TInt* ptr = onDiskFilesMap.Find( *(knownFiles[i]) );
+        if (ptr)
+            {
+            // Reinsert into Map, this time with NO DELETE
+            onDiskFilesMap.Insert( knownFiles[i], &noDelete ); 
+            
+            // Add the header file to HashMap
+            HBufC* headerFile = HBufC::NewL( KHttpCacheHeaderExt().Length() +  (*(knownFiles[i])).Length() ); 
+            cleanupList.Append( headerFile ); //keep for later destruction
+            TPtr ptr( headerFile->Des() ); 
+            HttpCacheUtil::GetHeaderFileName( *(knownFiles[i]), ptr );
+            onDiskFilesMap.Insert( headerFile, &noDelete ); // register Header files as NO DELETE
+            }
+        }
+
+    knownFiles.Close(); 
+    CleanupStack::Pop( 1, &knownFiles );
+
+    //Step 3. Delete all files on disk that don't belong to any of the Cache Handlers.
+    CFileMan* fileMan = CFileMan::NewL( rfs );
+    TPtrHashMapIter<TDesC, TInt> iter( onDiskFilesMap );
+    const TDesC* key;
+    while ((key = iter.NextKey()) != 0)
+        {
+        const TInt value ( *(iter.CurrentValue()) );
+        if ( value == 1 ) { // file needs deletion
+            fileMan->Delete( *key );
+        }
+        }
+    delete fileMan;
+
+    CleanupStack::Pop(1, &cleanupList); 
+    cleanupList.ResetAndDestroy(); //should delete all HBufC objects
+    
+    CleanupStack::Pop(1, &onDiskFilesMap);
+    onDiskFilesMap.Close(); // doesn't own any K,V object
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::RemoveL
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CHttpCacheManager::RemoveL(
+    const TDesC8& aUrl )
+    {
+    TInt status( KErrNotFound );
+    if( iCacheEnabled )
+        {
+        // do not remove op cache
+        status = iCache->RemoveL( aUrl );
+        }
+    return status;
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::Find
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CHttpCacheManager::Find(
+    const TDesC8& aUrl )
+    {
+    TBool found( EFalse );
+    //
+    if( iCacheEnabled || iVSSCacheEnabled )
+        {
+        CHttpCacheHandler* cache = CacheHandler( aUrl, NULL );
+
+        __ASSERT_DEBUG( cache, User::Panic( _L("cacheHandler Panic"), KErrCorrupt ) );
+        //
+        if( cache )
+            {
+            found = cache->Find( aUrl );
+            }
+
+        if( !found && iVSSCacheEnabled )
+            {
+            found = iphoneSpecificCache->Find( aUrl );
+            }
+        }
+    return found;
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::VSSHeaderCheck
+//
+// -----------------------------------------------------------------------------
+//
+TBool CHttpCacheManager::VSSHeaderCheck( TDes8*  aHttpHeaderString ) const
+    {
+    TBool found ( EFalse );
+    if( aHttpHeaderString->Size() > 0 )
+        {
+        TPtrC8 nameStr8( KVSSHeaderFileldName() );
+
+        TInt VSSnameLocation = aHttpHeaderString->FindC( nameStr8 ) ;
+
+        if ( VSSnameLocation != KErrNotFound )
+            {
+            TPtrC8 valueStr8( KVSSHeaderFileldValue() );
+            TInt VSSvalueLocation = aHttpHeaderString->FindC( KVSSHeaderFileldValue() );
+
+            if ( (VSSvalueLocation != KErrNotFound ) && ( VSSnameLocation < VSSvalueLocation ) )
+                {
+                found = ETrue;
+                }
+            } //end if ( VSSnameLocation != KErrNotFound )
+        } //end  if( aHttpHeaderString.Size() > 0 )
+
+    return found;
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::SaveL
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CHttpCacheManager::SaveL(
+    const TDesC8& aUrl,
+    const TDesC8& aHeader,
+    const TDesC8& aContent,
+    const TDesC8&  aHttpHeaderString)
+    {
+    TBool saved( EFalse );
+    //
+    if( iCacheEnabled || iVSSCacheEnabled )
+        {
+        HBufC8* headerStr = HBufC8::NewL( aHttpHeaderString.Length() );
+        headerStr->Des().Copy( aHttpHeaderString );
+        TPtr8 headerStrPtr8 ( headerStr->Des() ); //Any Type of TPtrc8
+        CHttpCacheHandler* cache = CacheHandler( aUrl, &headerStrPtr8 );
+        delete headerStr;
+        __ASSERT_DEBUG( cache, User::Panic( _L("cacheHandler Panic"), KErrCorrupt ) );
+        //
+        if( cache )
+            {
+            saved = cache->SaveL( aUrl, aHeader, aContent );
+            }
+        }
+    return saved;
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::AddHeaderL
+// Not supported for Vodafone specific storage.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CHttpCacheManager::AddHeaderL(
+    const TDesC8& aUrl,
+    const TDesC8& aName,
+    const TDesC8& aValue )
+    {
+    TBool status( KErrNotFound );
+    //
+    if( iCacheEnabled || iVSSCacheEnabled )
+        {
+        CHttpCacheHandler* cache = CacheHandler( aUrl, NULL );
+        __ASSERT_DEBUG( cache, User::Panic( _L("cacheHandler Panic"), KErrCorrupt ) );
+        //
+        if( cache )
+            {
+            status = cache->AddHeaderL( aUrl, aName, aValue );
+            }
+        }
+    return status;
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::CreateCacheHandlersL
+//
+// -----------------------------------------------------------------------------
+//
+void CHttpCacheManager::HandleNotifyString(
+    const TUint32 aKeyId,
+    const TDesC& aValue )
+    {
+    // check offline mode
+    if( aKeyId == KCoreAppUIsNetworkConnectionAllowed )
+        {
+        iOfflineMode = ( aValue == _L("1") ? EFalse : ETrue );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::CreateCacheHandlersL
+//
+// -----------------------------------------------------------------------------
+//
+void CHttpCacheManager::CreateCacheHandlersL()
+    {
+    // read cache settings
+    CRepository* repository = CRepository::NewLC( KCRUidCacheManager );
+    CRepository* repositoryDiskLevel = CRepository::NewLC( KCRUidDiskLevel );
+    TInt err;
+
+    // cache on/off
+    TInt cacheEnabled( 0 );
+    err = repository->Get( KCacheManagerHttpCacheEnabled, cacheEnabled );
+
+    iCacheEnabled = cacheEnabled;
+
+        // cache size
+        TInt cacheSize( KDefaultCacheSize );
+        repository->Get( KCacheManagerHttpCacheSize, cacheSize );
+
+         repository->Get( KCacheManagerHttpCacheFolder, iCacheFolder );
+        // fix folder by appending trailing \\ to the end -symbian thing
+        // unless it is already there
+        if( iCacheFolder.LocateReverse( '\\' ) != iCacheFolder.Length() - 1  )
+            {
+            iCacheFolder.Append( _L("\\") );
+            }
+        
+	// get drive letter for sysutil
+	TParsePtrC pathParser( iCacheFolder );
+	TDriveUnit drive = pathParser.Drive();
+	// get critical level
+	// RAM drive can have different critical level
+	TVolumeInfo vinfo;
+	User::LeaveIfError( CCoeEnv::Static()->FsSession().Volume( vinfo, drive ) );
+	//
+	TInt criticalLevel;
+	User::LeaveIfError( repositoryDiskLevel->Get( ( vinfo.iDrive.iType == EMediaRam ? KRamDiskCriticalLevel : KDiskCriticalThreshold ),
+		criticalLevel ) );
+
+    if( (err == KErrNone) && iCacheEnabled )
+        {
+        // create cache handler
+        iCache = CHttpCacheHandler::NewL( cacheSize, iCacheFolder, KDefaultIndexFile(), criticalLevel );
+
+        // create operator cache. same settings
+        if( FeatureManager::FeatureSupported( KFeatureIdOperatorCache ) )
+            {
+            TBuf<512> url;
+            // if domain is missing, then no need to read further
+            if( repository->Get( KOperatorDomainUrl, url ) == KErrNone )
+                {
+
+                HBufC8* opDomain8 = HBufC8::NewL( url.Length() );
+            CleanupStack::PushL(opDomain8);
+            opDomain8->Des().Append( url );
+
+            TInt slashPos = opDomain8->LocateReverse('/');
+            if(slashPos == -1)
+            {
+                slashPos = 0;
+            }
+            TPtrC8 temp = opDomain8->Left(slashPos);
+            iOpDomain = temp.AllocL();
+            CleanupStack::PopAndDestroy(opDomain8);
+
+                // op cache size
+                TInt opCacheSize( KDefaultCacheSize );
+                repository->Get( KOperatorCacheSize, opCacheSize );
+
+                // op cache folder
+                TFileName opCacheFolder( KDefaultCacheDir );
+                repository->Get( KOperatorCacheFolder, opCacheFolder );
+
+                if( opCacheFolder.LocateReverse( '\\' ) != opCacheFolder.Length() - 1  )
+                    {
+                    opCacheFolder.Append( _L("\\") );
+                    }
+
+                // create op cache
+                iOperatorCache = CHttpCacheHandler::NewL( opCacheSize, opCacheFolder, KDefaultOpIndexFile(), criticalLevel );
+        }
+            } //end if( FeatureManager::FeatureSupported( KFeatureIdOperatorCache ) )
+        } //end if( iCacheEnabled )
+
+    TInt VSScacheEnabled( 0 );
+    err = repository->Get( KPhoneSpecificCacheEnabled, VSScacheEnabled );
+
+    iVSSCacheEnabled = VSScacheEnabled;
+ 
+    if( (err == KErrNone) && iVSSCacheEnabled )
+        {
+        // cache size
+        TInt VSScacheSize( KDefaultCacheSize );
+        repository->Get( KPhoneSpecificCacheSize, VSScacheSize );
+
+        // cache folder
+        TFileName VSScacheFolder( KDefaultCacheDir );
+        // ignore cache folder. use c:\ to save memory. (same for operator cache. see below)
+        repository->Get( KPhoneSpecificCacheFolder, VSScacheFolder );
+        // fix folder by appending trailing \\ to the end -symbian thing
+        // unless it is already there
+        if( VSScacheFolder.LocateReverse( '\\' ) != VSScacheFolder.Length() - 1  )
+            {
+            VSScacheFolder.Append( _L("\\") );
+            }
+
+        //Get the white list
+        TBuf<2048> whiteList;
+
+        if( repository->Get( KPhoneSpecificCacheDomainUrl, whiteList ) == KErrNone )
+            {
+            iVSSWhiteList = HBufC8::NewL( whiteList.Length() );
+            iVSSWhiteList->Des().Append( whiteList );
+            }
+        else
+            {
+            iVSSWhiteList = NULL;
+            }
+
+        // create cache handler
+        iphoneSpecificCache = CHttpCacheHandler::NewL( VSScacheSize, VSScacheFolder, KDefaultVSSIndexFile(), criticalLevel );
+        }
+    CleanupStack::PopAndDestroy(2); // repository, , repositoryDiskLevel
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheManager::CacheHandler
+//
+// -----------------------------------------------------------------------------
+//
+CHttpCacheHandler* CHttpCacheManager::CacheHandler(
+    const TDesC8& aUrl,
+    TDes8* aHttpHeaderString ) const
+    {
+    CHttpCacheHandler* cache;
+    if( iVSSCacheEnabled && aHttpHeaderString && VSSHeaderCheck( aHttpHeaderString ) )
+        {
+        cache = iphoneSpecificCache;
+        }
+    else
+        {
+        cache = ( ( iOpDomain && HttpCacheUtil::OperatorCacheContent( iOpDomain->Des(), aUrl ) ) ? iOperatorCache : iCache );
+        }
+    return cache;
+    }
+//  End of File
+