webengine/osswebengine/cache/src/HttpCacheHandler.cpp
changeset 0 dd21522fd290
child 1 7c90e6132015
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2006 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:  Implementation of CHttpCacheHandler
       
    15 *
       
    16 */
       
    17 
       
    18 // INCLUDE FILES
       
    19 #include "HttpCacheHandler.h"
       
    20 #include "HttpCacheManager.h"
       
    21 #include "HttpCacheEntry.h"
       
    22 #include "HttpCacheLookupTable.h"
       
    23 #include "HttpCacheStreamHandler.h"
       
    24 #include "HttpCacheUtil.h"
       
    25 #include "HttpCacheEvictionHandler.h"
       
    26 #include "HttpCacheObserver.h"
       
    27 #include <http/RHTTPTransaction.h>
       
    28 #include <http/rhttpsession.h>
       
    29 #include <http/rhttpheaders.h>
       
    30 #include <HttpStringConstants.h>
       
    31 #include <httperr.h>
       
    32 #include <s32file.h>
       
    33 #include <BrCtlDefs.h>
       
    34 
       
    35 // EXTERNAL DATA STRUCTURES
       
    36 
       
    37 // EXTERNAL FUNCTION PROTOTYPES
       
    38 
       
    39 // CONSTANTS
       
    40 
       
    41 // MACROS
       
    42 
       
    43 // LOCAL CONSTANTS AND MACROS
       
    44 
       
    45 // MODULE DATA STRUCTURES
       
    46 
       
    47 // LOCAL FUNCTION PROTOTYPES
       
    48 
       
    49 // FORWARD DECLARATIONS
       
    50 
       
    51 // ============================= LOCAL FUNCTIONS ===============================
       
    52 void PanicCacheHandler(
       
    53     TInt aError)
       
    54     {
       
    55     _LIT(KCachePanic, "cacheHandler Panic");
       
    56 
       
    57     User::Panic( KCachePanic, aError );
       
    58     }
       
    59 
       
    60 // ============================ MEMBER FUNCTIONS ===============================
       
    61 
       
    62 // -----------------------------------------------------------------------------
       
    63 // CHttpCacheHandler::CHttpCacheHandler
       
    64 // C++ default constructor can NOT contain any code, that
       
    65 // might leave.
       
    66 // -----------------------------------------------------------------------------
       
    67 //
       
    68 CHttpCacheHandler::CHttpCacheHandler(
       
    69     TInt aSize ) : iSize( aSize )
       
    70     {
       
    71     }
       
    72 
       
    73 // -----------------------------------------------------------------------------
       
    74 // CHttpCacheHandler::ConstructL
       
    75 // Symbian 2nd phase constructor can leave.
       
    76 // -----------------------------------------------------------------------------
       
    77 //
       
    78 void CHttpCacheHandler::ConstructL(
       
    79     const TDesC& aDirectory,
       
    80     const TDesC& aIndexFile,
       
    81     TInt aCriticalLevel)
       
    82     {
       
    83 	User::LeaveIfError(iRfs.Connect());
       
    84     //
       
    85     iIndexFile = aIndexFile.AllocL();
       
    86     //
       
    87     iDirectory = aDirectory.AllocL();
       
    88     //
       
    89     iEvictionHandler = CHttpCacheEvictionHandler::NewL();
       
    90     //
       
    91     iStreamHandler = CHttpCacheStreamHandler::NewL( iDirectory->Des(), aCriticalLevel );
       
    92     //
       
    93     iLookupTable = CHttpCacheLookupTable::NewL( *iEvictionHandler, *iStreamHandler );
       
    94     //1. Set up top-level cache directory if it doesn't exist. 
       
    95     TEntry entry;
       
    96     TInt err( KErrNone );
       
    97     if (iRfs.Entry(iDirectory->Des(), entry) != KErrNone)
       
    98         {
       
    99         err = iRfs.MkDirAll(iDirectory->Des());
       
   100         }
       
   101 
       
   102     //2. Create subdirectories to store header/body files
       
   103     if ( err == KErrNone || err == KErrAlreadyExists ) { //harmless errors
       
   104     
       
   105         __ASSERT_DEBUG ( (iDirectory->Des().LocateReverse( KPathDelimiter ) == (iDirectory->Des().Length() - 1)),
       
   106                 PanicCacheHandler( KErrCorrupt ) ); // We assume that iDirectory is terminated by a forward slash
       
   107         
       
   108         HBufC* subDir = HBufC::NewL(KMaxPath); // Base cache dir + subdir name + another delimiter
       
   109         _LIT(KFormat,"%S%x%c");
       
   110         for (TUint i = 0; i < KCacheSubdirCount; i++)
       
   111             {
       
   112             TPtrC ptr (iDirectory->Des());
       
   113             subDir->Des().Format(KFormat, &ptr, i, KPathDelimiter); 
       
   114             TInt err2 = iRfs.MkDir(subDir->Des()); 
       
   115             __ASSERT_DEBUG ( (err2 == KErrNone || err2 == KErrAlreadyExists), PanicCacheHandler( err2 ) ); 
       
   116             }
       
   117         delete subDir;
       
   118         //end cache dir + subdir creation
       
   119     } else {
       
   120         User::Leave(err);
       
   121     }
       
   122 
       
   123     OpenLookupTableL();
       
   124     //
       
   125     iHttpCacheObserver = CHttpCacheObserver::NewL(iDirectory, iIndexFile, this);
       
   126     iHttpCacheObserver->StartObserver();
       
   127     }
       
   128 
       
   129 // -----------------------------------------------------------------------------
       
   130 // CHttpCacheHandler::NewL
       
   131 // Two-phased constructor.
       
   132 // -----------------------------------------------------------------------------
       
   133 //
       
   134 CHttpCacheHandler* CHttpCacheHandler::NewL(
       
   135     TInt aSize,
       
   136     const TDesC& aDirectory,
       
   137     const TDesC& aIndexFile,
       
   138     TInt aCriticalLevel)
       
   139     {
       
   140     CHttpCacheHandler* self = new( ELeave ) CHttpCacheHandler( aSize );
       
   141 
       
   142     CleanupStack::PushL( self );
       
   143     self->ConstructL( aDirectory, aIndexFile, aCriticalLevel );
       
   144     CleanupStack::Pop();
       
   145 
       
   146     return self;
       
   147     }
       
   148 
       
   149 // Destructor
       
   150 CHttpCacheHandler::~CHttpCacheHandler()
       
   151     {
       
   152    
       
   153         TRAP_IGNORE( SaveLookupTableL() );
       
   154    
       
   155     //
       
   156     delete iHttpCacheObserver;
       
   157     //
       
   158     if (iEvictionHandler)
       
   159         {
       
   160         iEvictionHandler->RemoveAll();
       
   161         }
       
   162 
       
   163     //
       
   164     delete iLookupTable;
       
   165     //
       
   166     delete iEvictionHandler;
       
   167     //
       
   168     delete iStreamHandler;
       
   169     //
       
   170     delete iDirectory;
       
   171     //
       
   172     delete iIndexFile;
       
   173     //
       
   174     iRfs.Close();
       
   175     }
       
   176 
       
   177 // -----------------------------------------------------------------------------
       
   178 // CHttpCacheHandler::RequestL
       
   179 //
       
   180 // -----------------------------------------------------------------------------
       
   181 //
       
   182 TInt CHttpCacheHandler::RequestL(
       
   183     RHTTPTransaction& aTrans,
       
   184     TBrCtlDefs::TBrCtlCacheMode aCacheMode,
       
   185     THttpCacheEntry& aCacheEntry )
       
   186     {
       
   187     HttpCacheUtil::WriteUrlToLog( 0, _L( "request item" ), aTrans.Request().URI().UriDes() );
       
   188     //
       
   189     TInt status( KErrNotFound );
       
   190     CHttpCacheEntry* entry = NULL;
       
   191     // 0. check if we need to check cache at all (protected vs no cache mode)
       
   192     // 1. check if the url is in the cache
       
   193     // 2. check if it is complete
       
   194     // 3. see if it is useable
       
   195 
       
   196     // use protected item on reload???
       
   197     // currently not
       
   198     // and do not use cache for post
       
   199     if( aCacheMode != TBrCtlDefs::ECacheModeNoCache &&
       
   200         HttpCacheUtil::MethodFromStr( aTrans.Request().Method(), aTrans.Session().StringPool() ) != EMethodPost )
       
   201         {
       
   202         // If the cacheMode is noCache then it must ignore the cached entry.
       
   203         entry = iLookupTable->Find( aTrans.Request().URI().UriDes() );
       
   204         // check if the trailing slash is missing
       
   205         if( !entry )
       
   206             {
       
   207             TUriC8 uri = aTrans.Request().URI();
       
   208 
       
   209             if( uri.Extract( EUriPath ).Length() == 0 )
       
   210                 {
       
   211                 CUri8* fixeduri = CUri8::NewLC( uri );
       
   212                 fixeduri->SetComponentL( _L8("/"), EUriPath );
       
   213                 //
       
   214                 entry = iLookupTable->Find( fixeduri->Uri().UriDes() );
       
   215                 //
       
   216                 CleanupStack::PopAndDestroy(); // fixeduri
       
   217                 }
       
   218             }
       
   219         //
       
   220         if( entry && entry->State() == CHttpCacheEntry::ECacheComplete )
       
   221             {
       
   222 #ifdef __CACHELOG__
       
   223             HttpCacheUtil::WriteLog( 0, _L( "item is in the cache" ) );
       
   224 #endif            
       
   225             //
       
   226             status = CacheNeedsValidationL( *entry, aTrans, aCacheMode ) ? KErrNotReady : KErrNone;
       
   227             // entry could be invalidated at this point. check for status to make sure
       
   228             // the entry is still valid
       
   229             }
       
   230         // prepare stream for request
       
   231         if( status == KErrNone )
       
   232             {
       
   233 #ifdef __CACHELOG__
       
   234             HttpCacheUtil::WriteLog( 0, _L( "prepare item for sending" ) );
       
   235 #endif
       
   236             // attach entry to the stream
       
   237             if( iStreamHandler->AttachL( *entry ) )
       
   238                 {
       
   239                 entry->SetState( CHttpCacheEntry::ECacheRequesting );
       
   240                 entry->Accessed();
       
   241                 }
       
   242             else
       
   243                 {
       
   244                 // cleanup on the corrupt entry
       
   245                 HandleCorruptEntry( *entry );
       
   246                 entry = NULL;
       
   247                 // item is not in cache
       
   248                 status = KErrNotFound;
       
   249                 }
       
   250             }
       
   251         // cleanup
       
   252         if( status == KErrNone && entry )
       
   253             {
       
   254             // save handler and entry so that
       
   255             // on next call we don't have to start a lookup again
       
   256             aCacheEntry.iCacheHandler = this;
       
   257             aCacheEntry.iCacheEntry = entry;
       
   258             }
       
   259         else
       
   260             {
       
   261             // cleanup response headers
       
   262             //
       
   263             // response is not in the cache, so remove all the response header fields
       
   264             // set by cache handler
       
   265             RHTTPHeaders responseHeaders = aTrans.Response().GetHeaderCollection();
       
   266             responseHeaders.RemoveAllFields();
       
   267             }
       
   268         }
       
   269 #ifdef __CACHELOG__
       
   270     else
       
   271         {
       
   272         HttpCacheUtil::WriteLog( 0, _L( "reload: do not use cache" ) );
       
   273         }
       
   274     if( status != KErrNone && entry )
       
   275         {
       
   276         //
       
   277         HttpCacheUtil::WriteLog( 0, _L( "item needs validation" ) );
       
   278         }
       
   279     else
       
   280         {
       
   281         //
       
   282         HttpCacheUtil::WriteLog( 0, _L( "item is not in the cache" ) );
       
   283         }
       
   284 #endif // __CACHELOG__
       
   285 
       
   286     return status;
       
   287     }
       
   288 
       
   289 // -----------------------------------------------------------------------------
       
   290 // CHttpCacheHandler::RequestHeadersL
       
   291 //
       
   292 // -----------------------------------------------------------------------------
       
   293 //
       
   294 TInt CHttpCacheHandler::RequestHeadersL(
       
   295     RHTTPTransaction& aTrans,
       
   296     THttpCacheEntry& aCacheEntry )
       
   297     {
       
   298     HttpCacheUtil::WriteUrlToLog( 0, _L( "request http headers" ), aTrans.Request().URI().UriDes() );
       
   299     //
       
   300     TInt status( KErrNotFound );
       
   301     CHttpCacheEntry* entry = aCacheEntry.iCacheEntry;
       
   302     //
       
   303     if( entry && entry->State() == CHttpCacheEntry::ECacheRequesting )
       
   304         {
       
   305         // response headers should already have all the headers
       
   306         // as RequestL call adds them all.
       
   307         // no need to do much here
       
   308         // get header from file
       
   309         status = KErrNone;
       
   310 #ifdef __CACHELOG__
       
   311         HttpCacheUtil::WriteLog( 0, _L( "sending http headers" ) );
       
   312 #endif        
       
   313         }
       
   314     return status;
       
   315     }
       
   316 
       
   317 // -----------------------------------------------------------------------------
       
   318 // CHttpCacheHandler::RequestNextChunkL
       
   319 //
       
   320 // -----------------------------------------------------------------------------
       
   321 //
       
   322 HBufC8* CHttpCacheHandler::RequestNextChunkL(
       
   323     RHTTPTransaction& aTrans,
       
   324     TBool& aLastChunk,
       
   325     THttpCacheEntry& aCacheEntry )
       
   326     {
       
   327     (void)aTrans; //suppress compiler and PC-lint warnings
       
   328     //
       
   329     HBufC8* bodyStr = NULL;
       
   330     CHttpCacheEntry* entry = aCacheEntry.iCacheEntry;
       
   331     //
       
   332     if( entry && entry->State() == CHttpCacheEntry::ECacheRequesting )
       
   333         {
       
   334         // get next chunk
       
   335         bodyStr = iStreamHandler->NextChunkL( *entry, aLastChunk );
       
   336         }
       
   337     return bodyStr;
       
   338     }
       
   339 
       
   340 // -----------------------------------------------------------------------------
       
   341 // CHttpCacheHandler::RequestClosed
       
   342 //
       
   343 // -----------------------------------------------------------------------------
       
   344 //
       
   345 void CHttpCacheHandler::RequestClosed(
       
   346     RHTTPTransaction* aTrans,
       
   347     THttpCacheEntry& aCacheEntry )
       
   348     {
       
   349     if (aTrans)
       
   350         HttpCacheUtil::WriteUrlToLog( 0, _L( "Request is closed" ), aTrans->Request().URI().UriDes() );
       
   351     // fine
       
   352     // make sure transaction is moved to the complete list
       
   353     CHttpCacheEntry* entry = aCacheEntry.iCacheEntry;
       
   354 
       
   355     if( entry )
       
   356         {
       
   357         // normal close on a request - when the content is loaded from the cache
       
   358         if( entry->State() == CHttpCacheEntry::ECacheRequesting )
       
   359             {
       
   360             entry->SetState( CHttpCacheEntry::ECacheComplete );
       
   361             iStreamHandler->Detach( *entry );
       
   362             }
       
   363         // transaction is closed without being completed
       
   364         else if( entry->State() == CHttpCacheEntry::ECacheResponding ||
       
   365             entry->State() == CHttpCacheEntry::ECacheDestroyed )
       
   366             {
       
   367             // remove uncompleted/destroyed entry
       
   368             iStreamHandler->Detach( *entry );
       
   369             HandleCorruptEntry( *entry );
       
   370             entry = NULL;
       
   371             aCacheEntry.iCacheEntry = NULL;
       
   372 #ifdef __CACHELOG__
       
   373             HttpCacheUtil::WriteLog( 0, _L( "uncompleted entry" ) );
       
   374 #endif
       
   375             }
       
   376         else if( entry->State() == CHttpCacheEntry::ECacheComplete )
       
   377             {
       
   378             // normal close on the request - when the contet is saved to the cache
       
   379             // ResponseComplete has already been called
       
   380             // check if the stream is released
       
   381             __ASSERT_DEBUG( !iStreamHandler->Find( *entry ) , PanicCacheHandler( KErrCorrupt ) );
       
   382             }
       
   383         else
       
   384             {
       
   385             __ASSERT_DEBUG( EFalse , PanicCacheHandler( KErrCorrupt ) );
       
   386             }
       
   387         }
       
   388     }
       
   389 
       
   390 
       
   391 // -----------------------------------------------------------------------------
       
   392 // CHttpCacheHandler::AdjustResponseTime
       
   393 //
       
   394 // -----------------------------------------------------------------------------
       
   395 //
       
   396 
       
   397 void CHttpCacheHandler::AdjustResponseTime(RHTTPTransaction& aTrans)
       
   398     {
       
   399     RStringF fieldName;
       
   400     THTTPHdrVal dateValue;
       
   401     TDateTime date;
       
   402     TTime now;
       
   403     TInt err;
       
   404     TTime serverResponseTime;
       
   405     RHTTPHeaders respHeaders = aTrans.Response().GetHeaderCollection();
       
   406     RStringPool strP = aTrans.Session().StringPool();
       
   407 
       
   408     // Get the current time. All internet dates are GMT
       
   409 
       
   410     now.UniversalTime();
       
   411 
       
   412     // Get the date from the headers. Compare this with the response
       
   413     // GMT time. If the server time is wrong then adjust the time here.
       
   414 
       
   415     fieldName = strP.StringF( HTTP::EDate, RHTTPSession::GetTable() );
       
   416     err = respHeaders.GetField( fieldName, 0, dateValue );
       
   417     if( err == KErrNotFound || dateValue.Type() != THTTPHdrVal::KDateVal )
       
   418         {
       
   419         serverResponseTime = 0;
       
   420         }
       
   421     else
       
   422         {
       
   423         serverResponseTime = TTime( dateValue.DateTime() );
       
   424         }
       
   425 
       
   426 
       
   427     // Implies some thing wrong with with origin server time.
       
   428 
       
   429     if ( now < serverResponseTime )
       
   430         {
       
   431 #ifdef __CACHELOG__
       
   432         HttpCacheUtil::WriteLog( 0, _L( "Response time is less than GMT time" ) );
       
   433 #endif
       
   434         // Remove the field first. It is must otherwise raw field
       
   435         // data is not modified. The cache data is written from the
       
   436         // raw field data.
       
   437         if( respHeaders.RemoveField(fieldName) == KErrNone )
       
   438             {
       
   439             dateValue.SetDateTime( now.DateTime() );
       
   440             TRAP_IGNORE( respHeaders.SetFieldL( fieldName, dateValue ) );
       
   441             }
       
   442         }
       
   443     }
       
   444 
       
   445 
       
   446 // -----------------------------------------------------------------------------
       
   447 // CHttpCacheHandler::ReceivedResponseHeadersL
       
   448 //
       
   449 // -----------------------------------------------------------------------------
       
   450 //
       
   451 void CHttpCacheHandler::ReceivedResponseHeadersL(
       
   452     RHTTPTransaction& aTrans,
       
   453     THttpCacheEntry& aCacheEntry )
       
   454     {
       
   455 #ifdef __CACHELOG__
       
   456     HttpCacheUtil::WriteUrlToLog( 0, _L( "received http headers" ), aTrans.Request().URI().UriDes() );
       
   457 #endif
       
   458     //
       
   459     TBool protectedEntry( EFalse );
       
   460     // check if the item is cacheable
       
   461     // no item should be bigger than the 1/3 of the cache size
       
   462     if( HttpCacheUtil::IsCacheable( aTrans, ( iSize / 3 ), protectedEntry ) )
       
   463         {
       
   464         // check if the entry is already in the cache
       
   465         CHttpCacheEntry* entry = iLookupTable->Find( aTrans.Request().URI().UriDes() );
       
   466         if( entry )
       
   467             {
       
   468 #ifdef __CACHELOG__
       
   469             HttpCacheUtil::WriteUrlToLog( 0, _L( "item is already in the cache" ), entry->Url() );
       
   470 #endif            
       
   471             //
       
   472             if( entry->State() != CHttpCacheEntry::ECacheComplete )
       
   473                 {
       
   474                 // multiple incoming entries? doh.
       
   475 #ifdef __CACHELOG__
       
   476                 HttpCacheUtil::WriteLog( 0, _L( "MULTIPLE REQUEST!!!!!!!!!!!!!!!!!!!!!!!!!" ) );
       
   477 #endif                
       
   478                 // __ASSERT_DEBUG( EFalse, PanicCacheHandler( KErrCorrupt ) );
       
   479                 // ignore this one and the first will proceed.
       
   480                 entry = NULL;
       
   481                 }
       
   482             }
       
   483         else
       
   484             {
       
   485 #ifdef __CACHELOG__
       
   486             HttpCacheUtil::WriteLog( 0, _L( "create new cache item" ) );
       
   487 #endif
       
   488             //Check adjustment of response time is required or not.
       
   489             AdjustResponseTime( aTrans );
       
   490             // hash it
       
   491             entry = iLookupTable->InsertL( aTrans.Request().URI().UriDes() );
       
   492             if( entry )
       
   493                 {
       
   494                 // protect this entry
       
   495                 if( protectedEntry )
       
   496                     {
       
   497 #ifdef __CACHELOG__
       
   498                     HttpCacheUtil::WriteLog( 0, _L( "this item is protected" ) );
       
   499 #endif
       
   500                     //
       
   501                     entry->SetProtected();
       
   502                     RHTTPHeaders responseHeaders = aTrans.Response().GetHeaderCollection();
       
   503                     RStringPool strP = aTrans.Session().StringPool();
       
   504 
       
   505                     // double expiration time
       
   506                     HttpCacheUtil::AdjustExpirationTimeL( responseHeaders, strP );
       
   507                     }
       
   508                 }
       
   509             else
       
   510                 {
       
   511                 // no luck with the lookuptable
       
   512                 __ASSERT_DEBUG( EFalse, PanicCacheHandler( KErrCorrupt ) );
       
   513                 }
       
   514             }
       
   515         // save headers
       
   516         if( entry )
       
   517             {
       
   518             // attach it to the stream handler
       
   519             if( iStreamHandler->AttachL( *entry ) )
       
   520                 {
       
   521                 entry->SetState( CHttpCacheEntry::ECacheResponding );
       
   522                 // 1. handle only 304 and 200
       
   523                 // 2. check if either the header or the body ( or both ) need to be updated
       
   524                 // 3. update the headers anyway in case of notmodified (304)
       
   525                 // 4. remove the old body in case of bodyupdate
       
   526                 TInt httpStatus( aTrans.Response().StatusCode() );
       
   527 #ifdef __CACHELOG__
       
   528                 HttpCacheUtil::WriteLog( 0, _L( "status code: " ), httpStatus );
       
   529 #endif
       
   530                 //
       
   531                 TBool ok( EFalse );
       
   532                 if( httpStatus == HTTPStatus::EOk )
       
   533                     {
       
   534                     ok = HandleResponseOkL( *entry, aTrans );
       
   535                     }
       
   536                 else if( httpStatus == HTTPStatus::ENotModified )
       
   537                     {
       
   538                     ok = HandleResponseNotModifiedL( *entry, aTrans );
       
   539                     }
       
   540                 //
       
   541                 // entry could be corrupted at this point
       
   542                 if( ok )
       
   543                     {
       
   544                     // save handler and entry so that
       
   545                     // on next call we don't have to start a lookup again
       
   546                     aCacheEntry.iCacheHandler = this;
       
   547                     aCacheEntry.iCacheEntry = entry;
       
   548                     }
       
   549                 else
       
   550                     {
       
   551                     iStreamHandler->Detach( *entry );
       
   552                     HandleCorruptEntry( *entry );
       
   553                     entry = NULL;
       
   554                     }
       
   555                 }
       
   556             else
       
   557                 {
       
   558                 HandleCorruptEntry( *entry );
       
   559                 entry = NULL;
       
   560                 }
       
   561             }
       
   562         }
       
   563     }
       
   564 
       
   565 // -----------------------------------------------------------------------------
       
   566 // CHttpCacheHandler::ReceivedResponseBodyDataL
       
   567 //
       
   568 // -----------------------------------------------------------------------------
       
   569 //
       
   570 void CHttpCacheHandler::ReceivedResponseBodyDataL(
       
   571     RHTTPTransaction& aTrans,
       
   572     MHTTPDataSupplier& aBodyDataSupplier,
       
   573     THttpCacheEntry& aCacheEntry )
       
   574     {
       
   575     HttpCacheUtil::WriteUrlToLog( 0, _L( "received body" ), aTrans.Request().URI().UriDes() );
       
   576     // 1. check if we are caching this resource
       
   577     // 2. update the body data
       
   578     CHttpCacheEntry* entry = aCacheEntry.iCacheEntry;
       
   579 
       
   580     if( entry && entry->State() == CHttpCacheEntry::ECacheResponding )
       
   581         {
       
   582         HBufC8* bodyStr = HttpCacheUtil::BodyToBufferL( aBodyDataSupplier );
       
   583         if( bodyStr )
       
   584             {
       
   585             // erase entry if we are unable to save it (low disk space)
       
   586             if( !SaveBuffer( *entry, bodyStr->Des(), ETrue ) )
       
   587                 {
       
   588                 // detach it from the stream and erase it
       
   589                 iStreamHandler->Detach( *entry );
       
   590                 HandleCorruptEntry( *entry );
       
   591 #ifdef __CACHELOG__                
       
   592                 HttpCacheUtil::WriteLog( 0, _L( "body cannot be saved" ) );
       
   593 #endif                
       
   594                 entry = NULL;
       
   595                 // remove entry
       
   596                 aCacheEntry.iCacheEntry = NULL;
       
   597                 }
       
   598 #ifdef __CACHELOG__
       
   599             else
       
   600                 {
       
   601                 HttpCacheUtil::WriteLog( 0, _L( "body is saved" ) );
       
   602                 }
       
   603 #endif // __CACHELOG__
       
   604             //
       
   605             delete bodyStr;
       
   606             }
       
   607         }
       
   608     }
       
   609 
       
   610 // -----------------------------------------------------------------------------
       
   611 // CHttpCacheHandler::ResponseComplete
       
   612 //
       
   613 // -----------------------------------------------------------------------------
       
   614 //
       
   615 void CHttpCacheHandler::ResponseComplete(
       
   616     RHTTPTransaction& aTrans,
       
   617     THttpCacheEntry& aCacheEntry )
       
   618     {
       
   619     HttpCacheUtil::WriteUrlToLog( 0, _L( "response complete" ), aTrans.Request().URI().UriDes() );
       
   620     // 1. check if we are caching this resource
       
   621     // 2. mark the entry as complete
       
   622     CHttpCacheEntry* entry = aCacheEntry.iCacheEntry;
       
   623 
       
   624     if( entry )
       
   625         {
       
   626         if( entry->State() == CHttpCacheEntry::ECacheResponding )
       
   627             {
       
   628             // flush the entry
       
   629             if( !iStreamHandler->Flush( *entry ) )
       
   630                 {
       
   631                 iStreamHandler->Detach( *entry );
       
   632                 HandleCorruptEntry( *entry );
       
   633 #ifdef __CACHELOG__
       
   634                 HttpCacheUtil::WriteLog( 0, _L( "body cannot be saved" ) );
       
   635 #endif
       
   636                 entry = NULL;
       
   637                 // remove entry
       
   638                 aCacheEntry.iCacheEntry = NULL;
       
   639                 }
       
   640             else
       
   641                 {
       
   642                 entry->SetState( CHttpCacheEntry::ECacheComplete );
       
   643                 iStreamHandler->Detach( *entry );
       
   644                 }
       
   645             }
       
   646         else if( entry->State() == CHttpCacheEntry::ECacheDestroyed )
       
   647             {
       
   648             iStreamHandler->Detach( *entry );
       
   649             HandleCorruptEntry( *entry, EFalse );
       
   650             aCacheEntry.iCacheEntry = NULL;
       
   651             }
       
   652         }
       
   653     }
       
   654 
       
   655 // -----------------------------------------------------------------------------
       
   656 // Removes all entries in the Cache lookup table, commits table to disk. 
       
   657 //
       
   658 // -----------------------------------------------------------------------------
       
   659 //
       
   660 TInt CHttpCacheHandler::RemoveAllL()
       
   661     {
       
   662 #ifdef __CACHELOG__
       
   663     HttpCacheUtil::WriteLog( 0, _L( "remove all items" ) );
       
   664 #endif
       
   665     TInt numberOfBytes;
       
   666     // clear all the inactive entries
       
   667     numberOfBytes = iLookupTable->RemoveAll();
       
   668     // and save it. user initiated. no need to do idle save
       
   669     SaveLookupTableL();
       
   670     return numberOfBytes;
       
   671     }
       
   672 
       
   673 // -----------------------------------------------------------------------------
       
   674 // CHttpCacheHandler::ListFiles
       
   675 // Adds all filenames known to this Cache to aFilenameList
       
   676 // -----------------------------------------------------------------------------
       
   677 //
       
   678 TInt CHttpCacheHandler::ListFiles(RPointerArray<TDesC>& aFilenameList)
       
   679     {
       
   680     return iLookupTable->ListFiles(aFilenameList);
       
   681     }
       
   682 
       
   683 // -----------------------------------------------------------------------------
       
   684 // CHttpCacheHandler::RemoveL
       
   685 //
       
   686 // -----------------------------------------------------------------------------
       
   687 //
       
   688 TInt CHttpCacheHandler::RemoveL(
       
   689     const TDesC8& aUrl )
       
   690     {
       
   691     TInt status( KErrNotFound );
       
   692     HttpCacheUtil::WriteUrlToLog( 0, _L( "remove item:" ), aUrl );
       
   693     CHttpCacheEntry* entry = iLookupTable->Find( aUrl );
       
   694 
       
   695     if( entry )
       
   696         {
       
   697         if( entry->State() == CHttpCacheEntry::ECacheComplete )
       
   698             {
       
   699             // delete
       
   700             status = iLookupTable->Remove( aUrl );
       
   701             }
       
   702         else
       
   703             {
       
   704             // mark it as deleted and erase it when the
       
   705             // trans is complete
       
   706             entry->SetState( CHttpCacheEntry::ECacheDestroyed );
       
   707             status = KErrNone;
       
   708             }
       
   709         }
       
   710     return status;
       
   711     }
       
   712 
       
   713 // -----------------------------------------------------------------------------
       
   714 // CHttpCacheHandler::Find
       
   715 //
       
   716 // -----------------------------------------------------------------------------
       
   717 //
       
   718 TBool CHttpCacheHandler::Find(
       
   719     const TDesC8& aUrl )
       
   720     {
       
   721     // find
       
   722     CHttpCacheEntry* entry = iLookupTable->Find( aUrl );
       
   723     return ( entry ? ( entry->State() == CHttpCacheEntry::ECacheComplete ) : EFalse );
       
   724     }
       
   725 
       
   726 // -----------------------------------------------------------------------------
       
   727 // CHttpCacheHandler::SaveL
       
   728 //
       
   729 // -----------------------------------------------------------------------------
       
   730 //
       
   731 TBool CHttpCacheHandler::SaveL(
       
   732     const TDesC8& aUrl,
       
   733     const TDesC8& aHeader,
       
   734     const TDesC8& aContent )
       
   735     {
       
   736     TBool saved( EFalse );
       
   737     // check if entry exist. do not overwrite.
       
   738     CHttpCacheEntry* entry = iLookupTable->Find( aUrl );
       
   739     if( !entry )
       
   740         {
       
   741         entry = iLookupTable->InsertL( aUrl );
       
   742         // prepare for saving
       
   743         if( entry && iStreamHandler->AttachL( *entry ) )
       
   744             {
       
   745             // save header and body
       
   746             saved = SaveBuffer( *entry, aHeader, EFalse ) && SaveBuffer( *entry, aContent, ETrue );
       
   747             if( saved )
       
   748                 {
       
   749                 // flush
       
   750                 saved = iStreamHandler->Flush( *entry );
       
   751                 if( saved )
       
   752                     {
       
   753                     entry->SetState( CHttpCacheEntry::ECacheComplete );
       
   754                     }
       
   755                 }
       
   756             iStreamHandler->Detach( *entry );
       
   757             }
       
   758         // cleanup
       
   759         if( !saved && entry )
       
   760             {
       
   761             HandleCorruptEntry( *entry );
       
   762             }
       
   763         }
       
   764     return saved;
       
   765     }
       
   766 
       
   767 // -----------------------------------------------------------------------------
       
   768 // CHttpCacheHandler::AddHeaderL
       
   769 //
       
   770 // -----------------------------------------------------------------------------
       
   771 //
       
   772 TInt CHttpCacheHandler::AddHeaderL(
       
   773     const TDesC8& aUrl,
       
   774     const TDesC8& aName,
       
   775     const TDesC8& aValue )
       
   776     {
       
   777     TInt status( KErrNotFound );
       
   778     //
       
   779     CHttpCacheEntry* entry = iLookupTable->Find( aUrl );
       
   780     if( entry )
       
   781         {
       
   782         TBool attached;
       
   783         //
       
   784         attached = iStreamHandler->AttachL( *entry );
       
   785         // get headers
       
   786         HBufC8* headersStr = iStreamHandler->HeadersL( *entry );
       
   787         if( headersStr )
       
   788             {
       
   789             CleanupStack::PushL( headersStr );
       
   790             // alter headers and save them
       
   791             HBufC8* newHeaderStr = HttpCacheUtil::AddHeaderLC( aName, aValue, headersStr->Des() );
       
   792             if( newHeaderStr )
       
   793                 {
       
   794                 // remove old headers first
       
   795                 iStreamHandler->RemoveHeaders( *entry );
       
   796                 // save new headers
       
   797                 if( !SaveBuffer( *entry, newHeaderStr->Des(), EFalse ) )
       
   798                     {
       
   799                     status = KErrDirFull;
       
   800                     // failed. should we save the original headers?
       
   801                     TBool saveOk( SaveBuffer( *entry, headersStr->Des(), EFalse ) );
       
   802                     // original save should never fail
       
   803                     __ASSERT_DEBUG( saveOk, PanicCacheHandler( KErrCorrupt ) );
       
   804 
       
   805                     if( !saveOk )
       
   806                         {
       
   807                         // sorry, we made this entry corrupt. remove it
       
   808                         iStreamHandler->Detach( *entry );
       
   809                         HandleCorruptEntry( *entry );
       
   810                         entry = NULL;
       
   811                         }
       
   812                     }
       
   813                 else
       
   814                     {
       
   815                     status = KErrNone;
       
   816                     }
       
   817                 CleanupStack::PopAndDestroy(); // newHeaderStr
       
   818                 }
       
   819             CleanupStack::PopAndDestroy(); // headersStr
       
   820             }
       
   821         // detach
       
   822         if( attached )
       
   823             {
       
   824             iStreamHandler->Detach( *entry );
       
   825             }
       
   826         }
       
   827     return status;
       
   828     }
       
   829 
       
   830 // -----------------------------------------------------------------------------
       
   831 // CHttpCacheHandler::CacheNeedsValidationL
       
   832 //
       
   833 // Note: This function check if cache needs validation
       
   834 //       Delete cache entry from this function is too early, should avoid it
       
   835 // -----------------------------------------------------------------------------
       
   836 //
       
   837 TBool CHttpCacheHandler::CacheNeedsValidationL(
       
   838     CHttpCacheEntry& aCacheEntry,
       
   839     RHTTPTransaction& aTrans,
       
   840     TBrCtlDefs::TBrCtlCacheMode aCacheMode )
       
   841     {
       
   842     // The entry isn't useable unless otherwise stated
       
   843     TBool mustRevalidate( ETrue );
       
   844 
       
   845     // If the cacheMode is PreferCache then it must use it even if it
       
   846     // is expired, etc.  This is typically used during history navigation.
       
   847     //
       
   848     // Note: Cache also set the cacheMode to PreferCache after a resource has
       
   849     //       been validated -- that is when it tries to refetch an entry from
       
   850     //       cache after receiving a 304 response.
       
   851     // get cached headers
       
   852     if( iStreamHandler->AttachL( aCacheEntry ) )
       
   853         {
       
   854         HBufC8* headersStr = iStreamHandler->HeadersL( aCacheEntry );
       
   855         CleanupStack::PushL( headersStr );
       
   856         iStreamHandler->Detach( aCacheEntry );
       
   857         // headersStr == NULL happens if you erase the cache directory
       
   858         // using a file manager
       
   859         if( headersStr )
       
   860             {
       
   861             // use response headers for retreiving cached headers
       
   862             RHTTPHeaders responseHeaders = aTrans.Response().GetHeaderCollection();
       
   863             RHTTPHeaders requestHeaders = aTrans.Request().GetHeaderCollection();
       
   864             RStringPool strP = aTrans.Session().StringPool();
       
   865             // convert the buffer to httpHeader
       
   866             HttpCacheUtil::BufferToHeadersL( headersStr->Des(), responseHeaders, strP );
       
   867 
       
   868             // check if we need to validate the cahce
       
   869             if( aCacheMode == TBrCtlDefs::ECacheModeOnlyCache || aCacheMode == TBrCtlDefs::ECacheModeHistory  )
       
   870                 {
       
   871                 // no validation required
       
   872 #ifdef __CACHELOG__
       
   873                 HttpCacheUtil::WriteLog( 0, _L( "prefer cache mode. no need to revalidate" ), aCacheMode );
       
   874 #endif                
       
   875                 mustRevalidate = EFalse;
       
   876                 }
       
   877             else
       
   878                 {
       
   879                 // Get the pragma no-cache header from the headers
       
   880                 // no-cache on request header means "do not use cache"
       
   881                 if( !HttpCacheUtil::PragmaNoCache( aTrans ) )
       
   882                     {
       
   883                     if( !HttpCacheUtil::CacheTimeIsFresh( requestHeaders, responseHeaders, strP  ) )
       
   884                         {
       
   885 #ifdef __CACHELOG__
       
   886                         HttpCacheUtil::WriteLog( 0, _L( "cache item is not fresh. needs revalidation" ) );
       
   887 #endif
       
   888                         // MKLE-7PRD27: Avoid removing cache entry here 
       
   889                         
       
   890                         mustRevalidate = ETrue;
       
   891                         // add headers like EIfModifiedSince, EETag, EIfNoneMatch
       
   892                         HttpCacheUtil::AddValidationHeaders( responseHeaders, requestHeaders, strP );
       
   893                         }
       
   894                     else
       
   895                         {
       
   896 #ifdef __CACHELOG__
       
   897                         HttpCacheUtil::WriteLog( 0, _L( "cache item is fresh. needs no revalidation" ) );
       
   898 #endif                        
       
   899                         //
       
   900                         mustRevalidate = EFalse;
       
   901                         }
       
   902                     }
       
   903                 else
       
   904                     {
       
   905                     // needs validation
       
   906 #ifdef __CACHELOG__
       
   907                     HttpCacheUtil::WriteLog( 0, _L( "no cache/no store header present. need revalidation" ) );
       
   908 #endif
       
   909                     mustRevalidate = ETrue;
       
   910                     }
       
   911 
       
   912                 }
       
   913             }
       
   914         CleanupStack::PopAndDestroy(); // headersStr
       
   915         }
       
   916     else
       
   917         {
       
   918         HandleCorruptEntry( aCacheEntry );
       
   919         // needs validation
       
   920         mustRevalidate = ETrue;
       
   921         }
       
   922     return mustRevalidate;
       
   923     }
       
   924 
       
   925 // -----------------------------------------------------------------------------
       
   926 // CHttpCacheHandler::CacheNeedsSpaceL
       
   927 //
       
   928 // -----------------------------------------------------------------------------
       
   929 //
       
   930 TBool CHttpCacheHandler::CacheNeedsSpaceL(
       
   931     TInt aSize )
       
   932     {
       
   933     TBool ok( ETrue );
       
   934 #ifdef __CACHELOG__
       
   935     HttpCacheUtil::WriteLog( 0, _L( "the cache is this big" ), iSize );
       
   936     HttpCacheUtil::WriteLog( 0, _L( "we occupy" ), iStreamHandler->SavedContentSize()  );
       
   937     HttpCacheUtil::WriteLog( 0, _L( "this item needs space:" ), aSize );
       
   938 #endif // __CACHELOG__
       
   939 
       
   940     // check if we need extra space
       
   941     if( iStreamHandler->SavedContentSize() + aSize > iSize )
       
   942         {
       
   943 #ifdef __CACHELOG__
       
   944         // items in the cache
       
   945         TInt size( 0 );
       
   946         HttpCacheUtil::WriteLog( 0, _L( "cached items" ) );
       
   947         const CArrayPtrFlat<CHttpCacheEntry>& entries = iLookupTable->Entries();
       
   948         for( TInt i = 0; i < entries.Count(); i++ )
       
   949             {
       
   950             CHttpCacheEntry* entry = entries.At( i );
       
   951             if( entry && entry != (CHttpCacheEntry*)0xffffffff )
       
   952                 {
       
   953                 HttpCacheUtil::WriteUrlToLog( 0, entry->Url(), entry->Size() );
       
   954                 size+=entry->Size();
       
   955                 size+=entry->HeaderSize();
       
   956                 }
       
   957             }
       
   958         HttpCacheUtil::WriteLog( 0, _L( "occupy with headers:" ), size );
       
   959 #endif // __CACHELOG__
       
   960         CArrayPtrFlat<CHttpCacheEntry>* evictedList = iEvictionHandler->EvictL( aSize );
       
   961         if( evictedList && evictedList->Count() )
       
   962             {
       
   963             // destroy items
       
   964             CHttpCacheEntry* entry;
       
   965             for( TInt i = 0; i < evictedList->Count(); i++ )
       
   966                 {
       
   967                 //
       
   968                 entry = evictedList->At( i );
       
   969                 if( entry )
       
   970                     {
       
   971                     // destroy
       
   972                     iLookupTable->Remove( entry->Url() );
       
   973                     }
       
   974                 }
       
   975             // __ASSERT_DEBUG( iStreamHandler->SavedContentSize() + aSize < iSize, PanicCacheHandler( KErrCorrupt ) );
       
   976             // ok = ETrue if there is enough space
       
   977             ok = ( iStreamHandler->SavedContentSize() + aSize < iSize );
       
   978             }
       
   979         else
       
   980             {
       
   981             // interesting...nobody can be evicted...
       
   982             // they are all protected entries?
       
   983             // or the incoming -not yet complete- items take the entire cache?
       
   984 #ifdef __CACHELOG__
       
   985             HttpCacheUtil::WriteLog( 0, _L( "NO SPACE can be released!!!" ) );
       
   986 #endif            
       
   987             ok = EFalse;
       
   988             }
       
   989         delete evictedList;
       
   990         }
       
   991     return ok;
       
   992     }
       
   993 
       
   994 // -----------------------------------------------------------------------------
       
   995 // CHttpCacheHandler::HandleResponseOkL
       
   996 //
       
   997 // -----------------------------------------------------------------------------
       
   998 //
       
   999 TBool CHttpCacheHandler::HandleResponseOkL(
       
  1000     CHttpCacheEntry& aEntry,
       
  1001     RHTTPTransaction& aTrans )
       
  1002     {
       
  1003     TBool saveOk( ETrue );
       
  1004     RHTTPHeaders responseHeader = aTrans.Response().GetHeaderCollection();
       
  1005     RStringPool strP = aTrans.Session().StringPool();
       
  1006     HBufC8* responseHeaderStr = HttpCacheUtil::HeadersToBufferLC( responseHeader, strP );
       
  1007     //
       
  1008     TBool update( ETrue );
       
  1009     // get cached headers to compare
       
  1010     HBufC8* cachedHeaderStr = iStreamHandler->HeadersL( aEntry );
       
  1011     // we've got some headers to update,
       
  1012     // check if we really need to update them
       
  1013     if( cachedHeaderStr )
       
  1014         {
       
  1015         CleanupStack::PushL( cachedHeaderStr );
       
  1016         //
       
  1017         update = HttpCacheUtil::CacheNeedsUpdateL( responseHeader, cachedHeaderStr->Des(), strP );
       
  1018 
       
  1019         CleanupStack::PopAndDestroy(); // cachedHeaderStr
       
  1020         }
       
  1021     //
       
  1022     if( update )
       
  1023         {
       
  1024 #ifdef __CACHELOG__
       
  1025         HttpCacheUtil::WriteLog( 0, _L( "udpate headers" ) );
       
  1026 #endif
       
  1027         if( aEntry.HeaderSize() )
       
  1028             {
       
  1029             // remove it first
       
  1030             iStreamHandler->RemoveHeaders( aEntry );
       
  1031             }
       
  1032         // save
       
  1033         saveOk = SaveBuffer( aEntry, responseHeaderStr->Des() );
       
  1034 
       
  1035         if( aEntry.Size() )
       
  1036             {
       
  1037 #ifdef __CACHELOG__
       
  1038             HttpCacheUtil::WriteLog( 0, _L( "remove body" ) );
       
  1039 #endif            
       
  1040             //
       
  1041             iStreamHandler->RemoveBodyData( aEntry );
       
  1042             }
       
  1043         }
       
  1044     else
       
  1045         {
       
  1046         // if neither the header nor the body need to be updated, then
       
  1047         // detach entry to protect from being updated
       
  1048 #ifdef __CACHELOG__
       
  1049         HttpCacheUtil::WriteLog( 0, _L( "no udpate needed, ignore response" ) );
       
  1050 #endif        
       
  1051         //
       
  1052         aEntry.SetState( CHttpCacheEntry::ECacheComplete );
       
  1053         iStreamHandler->Detach( aEntry );
       
  1054         // pretend that save was ok.
       
  1055         saveOk = ETrue;
       
  1056         }
       
  1057     // destroy corrupt entry by returning EFalse
       
  1058     CleanupStack::PopAndDestroy(); // responseHeaderStr
       
  1059     return saveOk;
       
  1060     }
       
  1061 
       
  1062 // -----------------------------------------------------------------------------
       
  1063 // CHttpCacheHandler::HandleResponseNotModifiedL
       
  1064 //
       
  1065 // -----------------------------------------------------------------------------
       
  1066 //
       
  1067 TBool CHttpCacheHandler::HandleResponseNotModifiedL(
       
  1068     CHttpCacheEntry& aEntry,
       
  1069     RHTTPTransaction& aTrans )
       
  1070     {
       
  1071     // oos? -out of space
       
  1072     TBool saveOk( ETrue );
       
  1073     RHTTPHeaders responseHeader = aTrans.Response().GetHeaderCollection();
       
  1074     RStringPool strP = aTrans.Session().StringPool();
       
  1075     HBufC8* responseHeaderStr = HttpCacheUtil::HeadersToBufferLC( responseHeader, strP );
       
  1076     // If a cache uses a received 304 response to update a cache entry,
       
  1077     // the cache MUST update the entry to reflect any new field values given in the response.
       
  1078     HBufC8* mergedHeadersStr = NULL;
       
  1079     HBufC8* cachedHeaderStr = iStreamHandler->HeadersL( aEntry );
       
  1080     CleanupStack::PushL( cachedHeaderStr );
       
  1081     // don't merge with empty headers
       
  1082     if( cachedHeaderStr )
       
  1083         {
       
  1084         mergedHeadersStr = HttpCacheUtil::MergeHeadersLC( cachedHeaderStr->Des(), responseHeader, strP );
       
  1085         CleanupStack::Pop(); // mergedHeadersStr
       
  1086         }
       
  1087     // don't update empty headers
       
  1088     if( mergedHeadersStr || responseHeaderStr )
       
  1089         {
       
  1090         // remove cached headers first
       
  1091         iStreamHandler->RemoveHeaders( aEntry );
       
  1092         // save merged headers  (reponse + cached)
       
  1093         if( mergedHeadersStr )
       
  1094             {
       
  1095             saveOk = SaveBuffer( aEntry, mergedHeadersStr->Des() );
       
  1096             }
       
  1097         else if( responseHeaderStr )
       
  1098             {
       
  1099             // save responseheader instead
       
  1100             saveOk = SaveBuffer( aEntry, responseHeaderStr->Des() );
       
  1101             }
       
  1102         // if save failed, let's see if we can save old
       
  1103         // headers
       
  1104         if( !saveOk && cachedHeaderStr )
       
  1105             {
       
  1106             saveOk = SaveBuffer( aEntry, cachedHeaderStr->Des() );
       
  1107             }
       
  1108         }
       
  1109     // do not remove the body as it was not modified
       
  1110     delete mergedHeadersStr;
       
  1111     CleanupStack::PopAndDestroy( 2 ); // cachedHeaderStr, responseHeaderStr
       
  1112     // check if save was ok.
       
  1113     // or nothing was not saved at all
       
  1114     if( saveOk )
       
  1115         {
       
  1116         // this item does not need update
       
  1117         aEntry.SetState( CHttpCacheEntry::ECacheComplete );
       
  1118         iStreamHandler->Detach( aEntry );
       
  1119         }
       
  1120     return saveOk;
       
  1121     }
       
  1122 
       
  1123 // -----------------------------------------------------------------------------
       
  1124 // CHttpCacheHandler::OpenLookupTableL
       
  1125 //
       
  1126 // -----------------------------------------------------------------------------
       
  1127 //
       
  1128 void CHttpCacheHandler::OpenLookupTableL()
       
  1129     {
       
  1130     OpenLookupTableL(iLookupTable);
       
  1131     }
       
  1132 
       
  1133 // -----------------------------------------------------------------------------
       
  1134 // CHttpCacheHandler::OpenLookupTableL
       
  1135 // Opens the index*.dat lookup table from file system. 
       
  1136 // -----------------------------------------------------------------------------
       
  1137 //
       
  1138 void CHttpCacheHandler::OpenLookupTableL(CHttpCacheLookupTable* aLookupTable)
       
  1139     {
       
  1140     // read entries from index.dat
       
  1141     RFileReadStream readStream;
       
  1142 
       
  1143         iRfs.SetSessionPath( iDirectory->Des() );
       
  1144 
       
  1145         TInt ret = KErrNone;
       
  1146         TInt tryCount = 0;
       
  1147         for (tryCount = 0; tryCount < 5; tryCount++) 
       
  1148             {
       
  1149             ret = readStream.Open( iRfs, iIndexFile->Des(), EFileRead | EFileShareAny );
       
  1150             if (ret == KErrInUse)
       
  1151                 {
       
  1152                 // When the cache is full, it takes 65 - 85 miliseconds to write the index.
       
  1153                 // So wait 50 miliseconds and try again
       
  1154                 User::After(50000);
       
  1155                 }
       
  1156             else
       
  1157                 {
       
  1158                 break;
       
  1159                 }
       
  1160             }
       
  1161         if( ret == KErrNone )
       
  1162             {
       
  1163             CleanupClosePushL( readStream );
       
  1164             aLookupTable->InternalizeL( readStream, iDirectory->Des() );
       
  1165             CleanupStack::PopAndDestroy(1); // readStream
       
  1166         }
       
  1167     }
       
  1168 
       
  1169 // -----------------------------------------------------------------------------
       
  1170 // CHttpCacheHandler::SaveLookupTableL
       
  1171 //
       
  1172 // -----------------------------------------------------------------------------
       
  1173 //
       
  1174 void CHttpCacheHandler::SaveLookupTableL()
       
  1175     {
       
  1176 #ifdef __CACHELOG__
       
  1177     HttpCacheUtil::WriteLog( 0, _L( "lookup table is saved" ) );
       
  1178 #endif
       
  1179     // save entries to index.dat
       
  1180     RFileWriteStream writeStream;
       
  1181 
       
  1182     // Don't get notified about own changes
       
  1183     iHttpCacheObserver->Cancel();
       
  1184     TInt ret = KErrNone;
       
  1185     TInt tryCount = 0;
       
  1186     for (tryCount = 0; tryCount < 5; tryCount++) 
       
  1187         {
       
  1188         ret = writeStream.Replace( iRfs, iIndexFile->Des(), EFileWrite );
       
  1189         if (ret == KErrInUse)
       
  1190             {
       
  1191             // When the cache is full, it takes 65 - 85 miliseconds to write the index.
       
  1192             // So wait 50 miliseconds and try again
       
  1193             User::After(50000);
       
  1194             }
       
  1195         else
       
  1196             {
       
  1197             break;
       
  1198             }
       
  1199         }
       
  1200     if( ret == KErrNone )
       
  1201         {
       
  1202         CleanupClosePushL( writeStream );
       
  1203         iLookupTable->ExternalizeL( writeStream );
       
  1204         writeStream.CommitL();
       
  1205         CleanupStack::PopAndDestroy(); // writeStream
       
  1206         }
       
  1207     iHttpCacheObserver->StartObserver();
       
  1208     }
       
  1209 
       
  1210 // -----------------------------------------------------------------------------
       
  1211 // CHttpCacheHandler::HandleCorruptEntry
       
  1212 //
       
  1213 // -----------------------------------------------------------------------------
       
  1214 //
       
  1215 void CHttpCacheHandler::HandleCorruptEntry(
       
  1216     CHttpCacheEntry& aStrayEntry,
       
  1217     TBool aUpdate )
       
  1218     {
       
  1219     (void)aUpdate;//suppress compiler and PC-lint warnings
       
  1220 #ifdef __CACHELOG__
       
  1221     HttpCacheUtil::WriteLog( 0, _L( "delete this stray entry" ) );
       
  1222 #endif
       
  1223     // remove from the lookuptable
       
  1224     iLookupTable->EraseCorruptEntry( aStrayEntry.Url() );
       
  1225     }
       
  1226 
       
  1227 // -----------------------------------------------------------------------------
       
  1228 // There used to be a CHttpCacheHandler::FixLookupTableL here. 
       
  1229 // Go back in SVN to re-discover it :)
       
  1230 //
       
  1231 // -----------------------------------------------------------------------------
       
  1232 
       
  1233 // -----------------------------------------------------------------------------
       
  1234 // CHttpCacheHandler::SaveBuffer
       
  1235 //
       
  1236 // -----------------------------------------------------------------------------
       
  1237 //
       
  1238 TBool CHttpCacheHandler::SaveBuffer(
       
  1239     CHttpCacheEntry& aEntry,
       
  1240     const TDesC8& aBuffer,
       
  1241     TBool aBody )
       
  1242     {
       
  1243     TBool ok( EFalse );
       
  1244     TRAPD( err, ok = CacheNeedsSpaceL( aBuffer.Length() ) );
       
  1245     if( err == KErrNone && ok )
       
  1246         {
       
  1247         // safe save
       
  1248         ok = aBody ? iStreamHandler->SaveBodyData( aEntry, aBuffer ) : iStreamHandler->SaveHeaders( aEntry, aBuffer );
       
  1249         }
       
  1250 #ifdef __CACHELOG__
       
  1251     else
       
  1252         {
       
  1253         // stop saving this entry
       
  1254         HttpCacheUtil::WriteUrlToLog( 0, _L( "item cannot be saved. remove it please" ), aEntry.Url() );
       
  1255         }
       
  1256 #endif // __CACHELOG__
       
  1257     return ok;
       
  1258     }
       
  1259 
       
  1260 
       
  1261 // -----------------------------------------------------------------------------
       
  1262 // CHttpCacheHandler::UpdateLookupTable
       
  1263 //
       
  1264 // -----------------------------------------------------------------------------
       
  1265 //
       
  1266 void CHttpCacheHandler::UpdateLookupTable()
       
  1267     {
       
  1268     TRAP_IGNORE(UpdateLookupTableL());
       
  1269     iHttpCacheObserver->StartObserver();
       
  1270     }
       
  1271 
       
  1272 // -----------------------------------------------------------------------------
       
  1273 // CHttpCacheHandler::UpdateLookupTableL
       
  1274 // Slow method due to much file-system interaction. Don't call it from performance critical code. 
       
  1275 // -----------------------------------------------------------------------------
       
  1276 //
       
  1277 void CHttpCacheHandler::UpdateLookupTableL()
       
  1278     {
       
  1279     CHttpCacheEvictionHandler* evictionHandler = CHttpCacheEvictionHandler::NewL();
       
  1280     CleanupStack::PushL(evictionHandler);
       
  1281     CHttpCacheLookupTable* lookupTable = CHttpCacheLookupTable::NewL( *evictionHandler, *iStreamHandler );
       
  1282     CleanupStack::PushL(lookupTable);
       
  1283     OpenLookupTableL(lookupTable);
       
  1284     iLookupTable->MergeL(lookupTable, iRfs);
       
  1285 	CleanupStack::PopAndDestroy(2); // lookupTable, evictionHandler
       
  1286     }
       
  1287 //  End of File