diff -r a359256acfc6 -r c8a366e56285 webengine/osswebengine/cache/src/HttpCacheManager.cpp --- a/webengine/osswebengine/cache/src/HttpCacheManager.cpp Thu Aug 27 07:44:59 2009 +0300 +++ b/webengine/osswebengine/cache/src/HttpCacheManager.cpp Thu Sep 24 12:53:48 2009 +0300 @@ -40,19 +40,28 @@ // kbyte const TUint KDefaultCacheSize = 1048576; // 1MB = 1024*1024 -_LIT( KDefaultCacheDir, "c:\\cache\\"); -_LIT( KDefaultOperatorCacheDir, "c:\\cache\\op\\"); -_LIT( KDefaultVssCacheDir, "c:\\cache\\vss\\"); +const TUint KDefaultOperatorCacheSize = 300*1024; // 300KB +_LIT( KDefaultCacheDrive, "c"); +_LIT( KDefaultCacheDir, "c:\\system\\cache\\"); +_LIT( KDefaultOperatorCacheDir, "c:\\system\\cache\\"); +_LIT( KDefaultVssCacheDir, "c:\\system\\cache\\vss\\"); _LIT( KDefaultIndexFile, "index.dat" ); _LIT( KDefaultOpIndexFile, "index_op.dat" ); _LIT( KDefaultVSSIndexFile, "index_vss.dat" ); _LIT( KIndexFileExtension, ".dat" ); +_LIT( KCrashCheck, "browser.val"); _LIT( KValidationFileExtension, ".val" ); -_LIT8( KVSSHeaderFileldName, "X-Vodafone-Content" ); -_LIT8( KVSSHeaderFileldValue, "Portal" ); - +_LIT8( KVSSHeaderFieldName, "X-Vodafone-Content" ); +_LIT8( KVSSHeaderFieldValue, "Portal" ); +// default override string, browser gets 2MB, widgetUI gets 1MB, OVI Store gets 1MB : max 4MB. +_LIT( KDefaultOverrideString, "10008D39;1;2048;C;10282822;1;1024;C;102829A0;1;1024;C" ); // MACROS +#define KUIDBROWSERNG 0x10008D39 +#define KUIDWIDGETUI 0x10282822 +#define KUIDBROWSERCACHECLEANER 0x20026777 +#define KUIDOPERATORMENU 0x100039CE +#define KUIDOVISTORE 0x102829A0 // LOCAL CONSTANTS AND MACROS @@ -62,6 +71,15 @@ // FORWARD DECLARATIONS +TBool IsBrowser() + { + RProcess process; + TSecureId secId = process.SecureId(); + TUint32 secIdInt = secId; + + return ( secIdInt == KUIDBROWSERNG ); + } + // ============================ MEMBER FUNCTIONS =============================== @@ -82,7 +100,16 @@ // void CHttpCacheManager::ConstructL() { +#ifdef __CACHELOG__ + HttpCacheUtil::WriteLog( 0, _L("-------------------------------------------")); + HttpCacheUtil::WriteLog( 0, _L("| Creating new CHttpCacheManager Instance |"), (TInt)this); + HttpCacheUtil::WriteLog( 0, _L("-------------------------------------------")); +#endif + CreateCacheHandlersL(); +#ifdef __CACHELOG__ + HttpCacheUtil::WriteLog( 0, _L("Created cache handlers"), (TInt)this); +#endif // read offline mode if( FeatureManager::FeatureSupported( KFeatureIdOfflineMode ) ) @@ -124,6 +151,22 @@ // ----------------------------------------------------------------------------- CHttpCacheManager::~CHttpCacheManager() { +#ifdef __CACHELOG__ + HttpCacheUtil::WriteLog( 0, _L("-----------------------------------------")); + HttpCacheUtil::WriteLog( 0, _L("| Destroying CHttpCacheManager Instance | "), (TInt)this); + HttpCacheUtil::WriteLog( 0, _L("-----------------------------------------")); +#endif + + if( IsBrowser() ) // only enabled in browser + { + // delete crashcheck.dat file + RFs rfs; + rfs.Connect(); + rfs.SetSessionPath( iCacheFolder ); + rfs.Delete(KCrashCheck()); + rfs.Close(); + } + delete iOfflineNotifyHandler; delete iOfflineRepository; delete iCache; @@ -165,7 +208,7 @@ } #endif - TPtrC8 nameStr ( KVSSHeaderFileldName() ); + TPtrC8 nameStr ( KVSSHeaderFieldName() ); RStringF VSSnameStr = strP.OpenFStringL( nameStr ); CleanupClosePushL( VSSnameStr); @@ -173,7 +216,7 @@ THTTPHdrVal tempVal; if ( aHttpHeader.GetField( VSSnameStr, 0, tempVal ) == KErrNone ) { - TPtrC8 valueStr ( KVSSHeaderFileldValue() ); + TPtrC8 valueStr ( KVSSHeaderFieldValue() ); RStringF VSSValueStr = strP.OpenFStringL( valueStr ); CleanupClosePushL( VSSValueStr ); @@ -203,7 +246,6 @@ 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 ) { @@ -368,29 +410,6 @@ } // ----------------------------------------------------------------------------- -// FilePathHash -// 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 normalized ( aDes ); - - normalized.LowerCase(); - return DefaultHash::Des16( normalized ); -} - -// ----------------------------------------------------------------------------- -// FilepathIdent -// 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. @@ -399,127 +418,125 @@ // ----------------------------------------------------------------------------- void CHttpCacheManager::RemoveOrphanedFilesL() { - //Map that contains pointers to fully-qualified file paths as Keys, and "to be deleted flag" as Value. - RPtrHashMap 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 cleanupList; - CleanupResetAndDestroyPushL( cleanupList ); + // Only proceed if we are running the browser configuration, otherwise we will accidentally + // remove content we shouldn't. + // get our SID. + if( !IsBrowser() ) + return; + + // Step 1. Get map of disk content + RFs rfs; + User::LeaveIfError( rfs.Connect() ); + CleanupClosePushL( rfs ); + + // Map that contains pointers to fully-qualified file paths as Keys, and "to be deleted flag" as Value. + // Initially we mark everything as a candidate for deletion. + CHttpCacheFileHash *onDiskFilesMap = NULL; + HttpCacheUtil::GenerateCacheContentHashMapL( onDiskFilesMap, rfs, iCacheFolder, KCacheFileNeedsDelete ); + CleanupStack::PushL( onDiskFilesMap ); + + // mark everything in the cache as no delete needed. + MarkAllCacheContentAsNoDelete( onDiskFilesMap ); - 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 ); + // tell any other clients that we are about to remove their cached content + WipeAllOtherIndexFilesL( onDiskFilesMap, rfs ); + + // delete any remaining marked files + DeleteMarkedFilesL( onDiskFilesMap, rfs ); - //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; + CleanupStack::PopAndDestroy(1, onDiskFilesMap ); + CleanupStack::PopAndDestroy(1, &rfs ); + } - TPtrC dir( scanner->FullPath() ); +void CHttpCacheManager::MarkAllCacheContentAsNoDelete( CHttpCacheFileHash* aOnDiskFilesMap ) + { + //Step 2. Get list of known (non-orphaned) files in each Cache's in-memory lookup table. Flag them as DO NOT DELETE + //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 ) + iCache->ValidateCacheEntriesL(aOnDiskFilesMap); + if( iOperatorCache ) + iOperatorCache->ValidateCacheEntriesL(aOnDiskFilesMap); + if( iphoneSpecificCache ) + iphoneSpecificCache->ValidateCacheEntriesL(aOnDiskFilesMap); + } - //1b. Add any files found to the HashTable - const TInt nMatches = matchingFiles->Count(); - for ( TInt i = 0; i < nMatches; i++ ) - { - TEntry entry ( (*matchingFiles)[i] ) ; - TPtrC ext( entry.iName.Right( KIndexFileExtension().Length() )); +void CHttpCacheManager::GenerateEmptyIndexFileL(const TDesC& aIndexFile, RFs& aRfs ) + { + // Going to remove non-web client cache files in OrphanedFilesL call, + // Signal to these clients by emptying (or creating) an 'empty' index file + // do this before we start cleaning up files, to lessen the chances that any + // of the files are in use when we're trying to delete them. + + // 'adopt' code from httpcachelookuptable for dealing with indexes. + // save entries to index.dat + RFileWriteStream writeStream; - if ( ext.CompareF( KIndexFileExtension ) != 0 && // ignore any .dat index files - ext.CompareF( KValidationFileExtension ) != 0 ) // ignore any .val 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 - } + TInt ret = KErrNone; + TInt tryCount = 0; + for (tryCount = 0; tryCount < 5; tryCount++) + { + ret = writeStream.Replace( aRfs, aIndexFile, EFileWrite ); + if (ret == KErrInUse) + { + // When the cache is full, it takes 65 - 85 miliseconds to write the index. + // So wait 50 miliseconds and try again + User::After(50000); + } + else + { + break; } - - delete matchingFiles; - } // End of step 1: adding all known files on disk to Map + } + if( ret == KErrNone ) + { + CleanupClosePushL( writeStream ); + writeStream.WriteInt32L( KCacheVersionNumber ); + writeStream.WriteInt32L( 0 ); // no entries in the index. + writeStream.CommitL(); + CleanupStack::PopAndDestroy(); // writeStream + } + } - CleanupStack::PopAndDestroy( 1, scanner ); - -#ifdef __CACHELOG__ +void CHttpCacheManager::WipeAllOtherIndexFilesL( CHttpCacheFileHash* aOnDiskFilesMap, RFs& aRfs ) { - HttpCacheUtil::WriteFormatLog(0, _L("-----------START PRINTING MAP OF SIZE %d---------"), onDiskFilesMap.Count()); - TPtrHashMapIter iter(onDiskFilesMap); + // look through hashmap for any .dat files which don't belong to the instantiated caches and overwrite them with blank ones. + THttpCacheFileHashIter iter( aOnDiskFilesMap->HashMap() ); const TDesC* key; while ((key = iter.NextKey()) != 0) { - const TInt val = *(iter.CurrentValue()); - HttpCacheUtil::WriteFormatLog(0, _L("MAP WALK: %S, with value = %d "), key, val); - } - HttpCacheUtil::WriteFormatLog(0, _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 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) + const TFileInfo* value ( (iter.CurrentValue()) ); + if( value->iUserInt == KCacheFileNeedsDelete ) { - // Reinsert into Map, this time with NO DELETE - onDiskFilesMap.Insert( knownFiles[i], &noDelete ); -#if 0 // no header files any more. - // 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 -#endif + TPtrC ext( key->Right(KIndexFileExtension().Length()) ); + if ( ext.CompareF( KIndexFileExtension ) == 0 ) // find any .dat index files + { + GenerateEmptyIndexFileL( *key , aRfs ); + } } } - - knownFiles.Close(); - CleanupStack::Pop( 1, &knownFiles ); + } +void CHttpCacheManager::DeleteMarkedFilesL( CHttpCacheFileHash* aOnDiskFilesMap, RFs& aRfs ) + { //Step 3. Delete all files on disk that don't belong to any of the Cache Handlers. - CFileMan* fileMan = CFileMan::NewL( rfs ); - TPtrHashMapIter iter( onDiskFilesMap ); + CFileMan* fileMan = CFileMan::NewL( aRfs ); + THttpCacheFileHashIter iter( aOnDiskFilesMap->HashMap() ); const TDesC* key; while ((key = iter.NextKey()) != 0) { - const TInt value ( *(iter.CurrentValue()) ); - if ( value == 1 ) { // file needs deletion - fileMan->Delete( *key ); - } + const TFileInfo* value ( (iter.CurrentValue()) ); + if( value->iUserInt == KCacheFileNeedsDelete ) + { + TPtrC ext( key->Right(KIndexFileExtension().Length()) ); + if ( ext.CompareF( KIndexFileExtension ) != 0 && // ignore any .dat index files + ext.CompareF( KValidationFileExtension ) != 0 ) // ignore any .val files + { + 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 - } // ----------------------------------------------------------------------------- @@ -552,8 +569,6 @@ if( iCacheEnabled || iVSSCacheEnabled ) { CHttpCacheHandler* cache = CacheHandler( aUrl, NULL ); - - __ASSERT_DEBUG( cache, User::Panic( _L("cacheHandler Panic"), KErrCorrupt ) ); // if( cache ) { @@ -578,14 +593,14 @@ TBool found ( EFalse ); if( aHttpHeaderString->Size() > 0 ) { - TPtrC8 nameStr8( KVSSHeaderFileldName() ); + TPtrC8 nameStr8( KVSSHeaderFieldName() ); TInt VSSnameLocation = aHttpHeaderString->FindC( nameStr8 ) ; if ( VSSnameLocation != KErrNotFound ) { - TPtrC8 valueStr8( KVSSHeaderFileldValue() ); - TInt VSSvalueLocation = aHttpHeaderString->FindC( KVSSHeaderFileldValue() ); + TPtrC8 valueStr8( KVSSHeaderFieldValue() ); + TInt VSSvalueLocation = aHttpHeaderString->FindC( KVSSHeaderFieldValue() ); if ( (VSSvalueLocation != KErrNotFound ) && ( VSSnameLocation < VSSvalueLocation ) ) { @@ -617,7 +632,6 @@ 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 ) { @@ -642,7 +656,6 @@ if( iCacheEnabled || iVSSCacheEnabled ) { CHttpCacheHandler* cache = CacheHandler( aUrl, NULL ); - __ASSERT_DEBUG( cache, User::Panic( _L("cacheHandler Panic"), KErrCorrupt ) ); // if( cache ) { @@ -675,138 +688,147 @@ // void CHttpCacheManager::CreateCacheHandlersL() { - // read cache settings - CRepository* repository = CRepository::NewLC( KCRUidCacheManager ); - CRepository* repositoryDiskLevel = CRepository::NewLC( KCRUidDiskLevel ); - TInt err; + // get our SID. + RProcess process; + TSecureId secId = process.SecureId(); + TUint32 secIdInt = secId; + + CRepository* repository = CRepository::NewLC(KCRUidCacheManager); + CRepository* repositoryDiskLevel = CRepository::NewLC(KCRUidDiskLevel); // Get Cache Postpone Parameters. - // THttpCachePostponeParameters postpone; + TBool newCentrepPresent; + GetPostponeParamsL( newCentrepPresent, postpone, repository ); + + // apply default cache configuration - no cache for anyone, sizes set to default. + iCacheEnabled = EFalse; + TInt cacheSize( KDefaultCacheSize ); + iCacheFolder.Copy( KDefaultCacheDir ); + + TBool opCacheEnabled( EFalse ); + iOperatorCache = 0; + TInt opCacheSize = KDefaultOperatorCacheSize; + TFileName opCacheFolder( KDefaultOperatorCacheDir ); + + iVSSCacheEnabled = EFalse; + TInt vssCacheSize = KDefaultOperatorCacheSize; + TFileName vssCacheFolder( KDefaultVssCacheDir ); - if (KErrNone == repository->Get(KCacheWritePostponeEnabled, postpone.iEnabled) ) + if(newCentrepPresent) { - User::LeaveIfError( repository->Get( KCacheWritePostponeFreeRAMThreshold, postpone.iFreeRamThreshold ) ); - User::LeaveIfError( repository->Get( KCacheWritePostponeImmediateWriteThreshold, postpone.iImmediateWriteThreshold ) ); - User::LeaveIfError( repository->Get( KCacheWritePostponeWriteTimeout, postpone.iWriteTimeout ) ); + // if the new Centrep file is present, we trust it's configured properly. + GetHttpCacheConfigL( *repository, iCacheEnabled, cacheSize, iCacheFolder ); + GetOperatorCacheConfigL( *repository, opCacheEnabled, opCacheSize, opCacheFolder ); + GetVSSCacheConfigL( *repository, iVSSCacheEnabled, vssCacheSize, vssCacheFolder ); + } + + // look for per-process overrides in central repository. Do this before we get drive critical levels so we're on the right + // drive. + // This has a default string which applies the new per-client default configuration + ApplyCacheOverridesL(*repository, secIdInt, iCacheEnabled, cacheSize, opCacheEnabled, iVSSCacheEnabled, iCacheFolder, KDefaultCacheDrive()); + + TInt criticalLevel = 0; + GetCriticalDriveLevelsL( *repositoryDiskLevel, iCacheFolder, criticalLevel ); + + // Create any caches we should be using. + if (iCacheEnabled) + { + CreateHttpCacheL( secIdInt, cacheSize, criticalLevel, postpone ); + + if (opCacheEnabled) + { + CreateOperatorCacheL( *repository, opCacheFolder, opCacheSize, criticalLevel, postpone ); + } + } //end if( iCacheEnabled ) + + if ( iVSSCacheEnabled ) + { + CreateVssCacheL( *repository, vssCacheFolder, vssCacheSize, criticalLevel, postpone ); } - // 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, postpone); - - // 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); + CleanupStack::PopAndDestroy(2); // repository, repositoryDiskLevel + CrashCheckL( secIdInt ); + } - // op cache size - TInt opCacheSize( KDefaultCacheSize ); - repository->Get( KOperatorCacheSize, opCacheSize ); - - // op cache folder - TFileName opCacheFolder( KDefaultOperatorCacheDir ); - repository->Get( KOperatorCacheFolder, opCacheFolder ); - - if ( opCacheFolder.LocateReverse( '\\' ) != opCacheFolder.Length() - 1 ) - { - opCacheFolder.Append( _L("\\") ); - } - - // create op cache - iOperatorCache = CHttpCacheHandler::NewL( opCacheSize, opCacheFolder, KDefaultOpIndexFile(), criticalLevel, postpone); - } - } //end if( FeatureManager::FeatureSupported( KFeatureIdOperatorCache ) ) - } //end if( iCacheEnabled ) - - TInt VSScacheEnabled( 0 ); - err = repository->Get( KPhoneSpecificCacheEnabled, VSScacheEnabled ); - - iVSSCacheEnabled = VSScacheEnabled; - - if ( (err == KErrNone) && iVSSCacheEnabled ) +void CHttpCacheManager::ApplyCacheOverridesL(CRepository& aRepository, const TUint32& aSecIdInt, TBool& aCacheEnabled, TInt& aCacheSize, TBool& aOpCacheEnabled, TBool& aVssCacheEnabled, TDes& aPath, const TDesC& aDefaultDrive) + { + TDriveUnit drive(aDefaultDrive); + + // set defaults + if(aSecIdInt == KUIDBROWSERNG) // for the browser, force use of Operator and VSS caches + { + aOpCacheEnabled = ETrue; + aVssCacheEnabled = ETrue; + } + + // read override string from centrep + HBufC16 *overrideBuf = HBufC16::NewLC(64); + TPtr overrideStr(overrideBuf->Des()); + TInt strLen; + TInt err = aRepository.Get(KCacheManagerHttpCacheProcessOverride, overrideStr, strLen); + if(strLen > overrideBuf->Length()) + { + overrideBuf = overrideBuf->ReAllocL(strLen); + // make sure cleanup stack contains correct pointer since ReAllocL always allocates a new des for larger space. + CleanupStack::Pop(); + CleanupStack::PushL(overrideBuf); + // reassign the TPtr + overrideStr.Set(overrideBuf->Des()); + // pull in the whole string + aRepository.Get(KCacheManagerHttpCacheProcessOverride, overrideStr, strLen); + } + // if we failed to load an override string, use the default. + if( overrideStr.Length() == 0 ) { - // cache size - TInt VSScacheSize( KDefaultCacheSize ); - repository->Get( KPhoneSpecificCacheSize, VSScacheSize ); + CleanupStack::PopAndDestroy( overrideBuf ); + overrideBuf = KDefaultOverrideString().AllocLC(); + overrideStr.Set( overrideBuf->Des() ); + } + // Built in Lex likes white space to separate strings, but easier to enter with ; separators. Replace all ; with spaces. + TInt pos=0; + do{ + if(overrideStr[pos] == ';') + { + overrideStr[pos] = ' '; + } + pos++; + }while(pos < overrideStr.Length()); + + TLex overrideLex(overrideStr); + do{ + TUint32 tempId; + User::LeaveIfError(overrideLex.BoundedVal(tempId,EHex,KMaxTUint32)); + if(overrideLex.TokenLength() != 8) // if we're not pointing at an SID in the string, we are incorrect and the override is broken. + User::Leave(KErrCorrupt); + overrideLex.SkipSpace(); + TInt32 tempCacheEnabled; + User::LeaveIfError(overrideLex.BoundedVal(tempCacheEnabled,KMaxTInt32)); + overrideLex.SkipSpace(); + TInt32 tempCacheSize; + User::LeaveIfError(overrideLex.BoundedVal(tempCacheSize,KMaxTInt32)); + overrideLex.SkipSpace(); + TDriveUnit tempDrive(overrideLex.NextToken()); + overrideLex.SkipSpaceAndMark(); + // found a hex SID matching ours, use the parameters. + if(tempId == aSecIdInt) + { + aCacheEnabled = tempCacheEnabled; + aCacheSize = tempCacheSize * 1024; // conf is in KB + drive = tempDrive; + break; + } + }while(!overrideLex.Eos()); - // cache folder - TFileName VSScacheFolder( KDefaultVssCacheDir ); - // 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, postpone); - } - - CleanupStack::PopAndDestroy(2); // repository, , repositoryDiskLevel + // Modify drive letter on aPath to match + TParsePtr parsePath(aPath); + TPtrC pathStr(parsePath.Path()); + TPath tempPath; + tempPath.Format(_L("%c:%S"), TInt(drive)+'A', &pathStr); + aPath.Copy(tempPath); + HttpCacheUtil::EnsureTrailingSlash( aPath ); + + CleanupStack::PopAndDestroy(overrideBuf); } // ----------------------------------------------------------------------------- @@ -829,4 +851,184 @@ } return cache; } + +void CHttpCacheManager::GetPostponeParamsL( TBool& aNewCentrepPresent, THttpCachePostponeParameters& aParams, CRepository* aRepo ) + { + aNewCentrepPresent = EFalse; + if (KErrNone == aRepo->Get(KCacheWritePostponeEnabled, + aParams.iEnabled)) + { + User::LeaveIfError(aRepo->Get( + KCacheWritePostponeFreeRAMThreshold, + aParams.iFreeRamThreshold)); + User::LeaveIfError(aRepo->Get( + KCacheWritePostponeImmediateWriteThreshold, + aParams.iImmediateWriteThreshold)); + User::LeaveIfError(aRepo->Get(KCacheWritePostponeWriteTimeout, + aParams.iWriteTimeout)); + + aNewCentrepPresent = ETrue; + } + } + +void CHttpCacheManager::GetHttpCacheConfigL( CRepository& aRepository, TBool& aCacheEnabled, TInt& aCacheSize, TDes& aCacheFolder ) + { + // General HTTP Cache + TBool cacheEnabled( EFalse ); + aCacheFolder.Copy( KDefaultCacheDir ); + + TInt err = aRepository.Get(KCacheManagerHttpCacheEnabled, cacheEnabled); + aCacheEnabled = cacheEnabled; + if( err == KErrNone ) + { + // cache size + TInt tempCacheSize; + if( aRepository.Get(KCacheManagerHttpCacheSize, tempCacheSize) == KErrNone ) + aCacheSize = tempCacheSize; + + // cache location + TFileName tempCacheLocation; + if( aRepository.Get(KCacheManagerHttpCacheFolder, tempCacheLocation) == KErrNone ) + aCacheFolder.Copy( tempCacheLocation ); + } + HttpCacheUtil::EnsureTrailingSlash( aCacheFolder ); + } + +void CHttpCacheManager::GetOperatorCacheConfigL( CRepository& aRepository, TBool& aOpCacheEnabled, TInt& aOpCacheSize, TDes& aOpCacheFolder ) + { + // Operator Cache + aOpCacheEnabled = FeatureManager::FeatureSupported(KFeatureIdOperatorCache); + if( aOpCacheEnabled ) + { + TInt tempOpCacheSize; + if( aRepository.Get(KOperatorCacheSize, tempOpCacheSize) == KErrNone ) + aOpCacheSize = tempOpCacheSize; + + // op cache folder + TFileName tempOpCacheFolder; + if( aRepository.Get(KOperatorCacheFolder, tempOpCacheFolder) == KErrNone ) + aOpCacheFolder.Copy( tempOpCacheFolder ); + } + HttpCacheUtil::EnsureTrailingSlash( aOpCacheFolder ); + } + +void CHttpCacheManager::GetVSSCacheConfigL( CRepository& aRepository, TBool& aVSSCacheEnabled, TInt& aVssCacheSize, TDes& aVssCacheFolder ) + { + // VSS Cache + TInt VSScacheEnabled(0); + TInt err = aRepository.Get(KPhoneSpecificCacheEnabled, VSScacheEnabled); + aVSSCacheEnabled = VSScacheEnabled; + + if ( err == KErrNone && aVSSCacheEnabled ) + { + TInt tempVSSCacheSize; + if( aRepository.Get(KPhoneSpecificCacheSize, tempVSSCacheSize) == KErrNone ) + aVssCacheSize = tempVSSCacheSize; + + TFileName tempVSScacheFolder; + if( aRepository.Get(KPhoneSpecificCacheFolder, tempVSScacheFolder) == KErrNone ) + aVssCacheFolder.Copy( tempVSScacheFolder ); + } + HttpCacheUtil::EnsureTrailingSlash( aVssCacheFolder ); + } + +void CHttpCacheManager::GetCriticalDriveLevelsL( CRepository& aRepository, const TDesC& aCacheFolder, TInt& aCriticalLevel ) + { + // get drive letter for sysutil + TParsePtrC pathParser( aCacheFolder ); + TDriveUnit drive = pathParser.Drive(); + + // get critical level + // RAM drive can have different critical level + TVolumeInfo vinfo; + User::LeaveIfError(CCoeEnv::Static()->FsSession().Volume(vinfo, drive)); + // + User::LeaveIfError(aRepository.Get((vinfo.iDrive.iType == EMediaRam ? KRamDiskCriticalLevel : KDiskCriticalThreshold), aCriticalLevel)); + } + +void CHttpCacheManager::CreateHttpCacheL( const TInt& aSecIdInt, const TInt& aCacheSize, const TInt& aCriticalLevel, const THttpCachePostponeParameters& aPostpone ) + { + // browser gets the normal index.dat name, other clients get .dat + TFileName indexFile( KDefaultIndexFile() ); + if( aSecIdInt != KUIDBROWSERNG ) + { + indexFile.Format(_L("%08x.dat"), aSecIdInt); + } + // create cache handler + iCache = CHttpCacheHandler::NewL( aCacheSize, iCacheFolder, indexFile, aCriticalLevel, aPostpone); + } + +void CHttpCacheManager::CreateOperatorCacheL( CRepository& aRepository, const TDesC& aOpCacheFolder, const TInt& aOpCacheSize, const TInt& aCriticalLevel, const THttpCachePostponeParameters& aPostpone ) + { + TBuf<512> url; + // if domain is missing, then no need to read further + if (aRepository.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); + + // create op cache + iOperatorCache = CHttpCacheHandler::NewL( aOpCacheSize, aOpCacheFolder, KDefaultOpIndexFile(), aCriticalLevel, aPostpone); + } + } + +void CHttpCacheManager::CreateVssCacheL( CRepository& aRepository, const TDesC& aVssCacheFolder, const TInt& aVssCacheSize, const TInt& aCriticalLevel, const THttpCachePostponeParameters& aPostpone ) + { + //Get the white list + TBuf<2048> whiteList; + + if (aRepository.Get(KPhoneSpecificCacheDomainUrl, whiteList) == KErrNone) + { + iVSSWhiteList = HBufC8::NewL(whiteList.Length()); + iVSSWhiteList->Des().Append(whiteList); + } + else + { + iVSSWhiteList = NULL; + } + + // create cache handler + iphoneSpecificCache = CHttpCacheHandler::NewL(aVssCacheSize, aVssCacheFolder, KDefaultVSSIndexFile(), aCriticalLevel, aPostpone); + } + +void CHttpCacheManager::CrashCheckL( const TInt& aSecIdInt ) + { + if( aSecIdInt == KUIDBROWSERNG ) + { + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // Remove orphan files if browser didn't close cache properly - should only happen very occasionally + // + // We leave a file on the drive when we are in use and remove it when we close properly + // If the file is already there we expect files in the cache which have not been added to the index. + // + ////////////////////////////////////////////////////////////////////////////////////////////////////// + RFs rfs; + User::LeaveIfError( rfs.Connect() ); + CleanupClosePushL( rfs ); + rfs.SetSessionPath( iCacheFolder ); + RFile crashTest; + TInt err = crashTest.Create(rfs,KCrashCheck(),EFileRead); + crashTest.Close(); + if ( err == KErrAlreadyExists ) + { + #ifdef __CACHELOG__ + HttpCacheUtil::WriteLog(0, _L("Crash detected - removing orphan files")); + #endif + RemoveOrphanedFilesL(); + } + CleanupStack::PopAndDestroy( &rfs ); + } + } + // End of File