gssettingsuis/Gs/GSFramework/src/GSPluginAndViewIdCache.cpp
branchRCL_3
changeset 54 7e0eff37aedb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gssettingsuis/Gs/GSFramework/src/GSPluginAndViewIdCache.cpp	Wed Sep 01 12:20:44 2010 +0100
@@ -0,0 +1,550 @@
+/*
+* Copyright (c) 2002-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*           Plugin and view id caching support
+*
+*/
+
+
+// INCLUDE FILES
+#include "GSPluginAndViewIdCache.h"
+
+// System includes
+#include <bautils.h>
+#include <s32file.h>
+#include <eikappui.h>
+
+// User includes
+#include "GSShimmedView.h"
+#include "GSPlaceholderView.h"
+
+// Constants
+_LIT( KGSCacheFileName, "PluginUidToViewIdCache.dat" );
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::CGSPluginAndViewIdCache
+// C++ constructor.
+//
+// ---------------------------------------------------------------------------
+//
+CGSPluginAndViewIdCache::CGSPluginAndViewIdCache( CEikAppUi& aAppUi )
+:   iAppUi( aAppUi ), iFsSession(CCoeEnv::Static()->FsSession()),iLookupTable( &HashFunction, &HashIdentityRelation )
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::~CGSPluginAndViewIdCache
+// C++ destructor.
+//
+// ---------------------------------------------------------------------------
+//
+CGSPluginAndViewIdCache::~CGSPluginAndViewIdCache()
+    {
+    TRAP_IGNORE( StoreL() );
+    //
+    delete iPlaceholderView;
+    DestroyShims();
+    iLookupTable.Close();
+    //
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::ConstructL
+// 
+//
+// ---------------------------------------------------------------------------
+//
+void CGSPluginAndViewIdCache::ConstructL()
+    {
+    User::LeaveIfError( iFsSession.CreatePrivatePath( EDriveC ) );
+    //
+    iPlaceholderView = CGSPlaceholderView::NewL( iAppUi );
+    //
+    TRAP_IGNORE( RestoreL() );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::NewL
+// 
+//
+// ---------------------------------------------------------------------------
+//
+CGSPluginAndViewIdCache* CGSPluginAndViewIdCache::NewL( CEikAppUi& aAppUi )
+    {
+    CGSPluginAndViewIdCache* self = new(ELeave) CGSPluginAndViewIdCache( aAppUi );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::ActivatePlaceholderViewL
+// 
+//
+// ---------------------------------------------------------------------------
+//
+void CGSPluginAndViewIdCache::ActivatePlaceholderViewL()
+    {
+    iPlaceholderView->ActivateL();
+    }
+
+
+// ----------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::PriorToPlaceholderActiveViewId
+//
+// 
+// ----------------------------------------------------------------------------
+//
+const TVwsViewId& CGSPluginAndViewIdCache::PriorToPlaceholderActiveViewId() const
+    {
+    return iPlaceholderView->PreviouslyActiveViewId();
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::SetPriorToPlaceholderActiveViewId
+// 
+//
+// ---------------------------------------------------------------------------
+//
+void CGSPluginAndViewIdCache::SetPriorToPlaceholderActiveViewId( const TVwsViewId& aViewId )
+    {
+    iPlaceholderView->SetPreviouslyActiveViewId( aViewId );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::RegisterViewAndImplementationAssociationL
+// 
+//
+// ---------------------------------------------------------------------------
+//
+void CGSPluginAndViewIdCache::RegisterViewAndImplementationAssociationL( TUid aViewId, TUid aImplementationUid )
+    {
+    RegisterViewAndImplementationAssociationL( aViewId, aImplementationUid, EFalse );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::PrepareToRegisterPluginInstanceLC
+// 
+//
+// ---------------------------------------------------------------------------
+//
+void CGSPluginAndViewIdCache::PrepareToRegisterPluginInstanceLC( TUid aViewId )
+    {
+    TCacheEntry* value = iLookupTable.Find( aViewId );
+    if  ( value && value->iShim )
+        {
+        // Store cleanup view uid so that we know which shim to re-register
+        // if the cleanup item is invoked.
+        iTransientCleanupViewUid = aViewId;
+
+        // Prepare item
+        TCleanupItem item( ReRegisterShimWithUi, this );
+        CleanupStack::PushL( item );
+
+        // Unregister shim view
+        value->iShim->DeregisterView();
+
+        // If a leave now occurs, the cleanup stack will unwind and will
+        // invoke our cleanup item. This item will then re-add
+        // the specified shim to the view framework. See ReRegisterShimWithUiL
+        // for further details.
+        }
+    else
+        {
+        // Record not found - just push NULL to ensure cleanup stack
+        // remains balanced.
+        CleanupStack::PushL( (CBase*) NULL );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::RegisterPluginInstanceL
+// 
+//
+// ---------------------------------------------------------------------------
+//
+void CGSPluginAndViewIdCache::RegisterPluginInstanceL( TUid aViewId, CGSPluginInterface& aPluginInstance )
+    {
+    TCacheEntry* value = iLookupTable.Find( aViewId );
+    ASSERT( value != NULL );
+    
+    // Can now associate the plugin instance with the cache entry.
+    value->iLoadedPluginImplementation = &aPluginInstance;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::PluginImplementationUidForView
+// 
+//
+// ---------------------------------------------------------------------------
+//
+TBool CGSPluginAndViewIdCache::IsPluginLoaded( TUid aViewId ) const
+    {
+    CGSPluginInterface* instance = PluginInstance( aViewId );
+
+    TBool loaded = EFalse;
+    if ( instance )
+        {
+        loaded = ETrue;
+        }
+    
+    return loaded;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::PluginInstance
+// 
+//
+// ---------------------------------------------------------------------------
+//
+CGSPluginInterface* CGSPluginAndViewIdCache::PluginInstance( TUid aViewId ) const
+    {
+    CGSPluginInterface* ret = NULL;
+    //
+    const TCacheEntry* value = iLookupTable.Find( aViewId );
+    if  ( value )
+        {
+        ret = value->iLoadedPluginImplementation;
+        }
+    //
+    return ret;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::PluginImplementationUidForView
+// 
+//
+// ---------------------------------------------------------------------------
+//
+TUid CGSPluginAndViewIdCache::PluginImplementationUidForView( TUid aViewId ) const
+    {
+    TUid pluginUid = KNullUid;
+    //
+    const TCacheEntry* value = iLookupTable.Find( aViewId );
+    if  ( value )
+        {
+        pluginUid = value->iImplementationUid;
+        }
+    //
+    return pluginUid;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::DestroyShims
+// 
+//
+// ---------------------------------------------------------------------------
+//
+void CGSPluginAndViewIdCache::DestroyShims()
+    {
+	RHashMap< TUid, TCacheEntry >::TIter iterator( iLookupTable );
+    FOREVER
+		{
+		const TUid* key = iterator.NextKey();
+		if  ( key )
+            {
+            TCacheEntry* value = iterator.CurrentValue();
+
+            // Destroy shim instance
+            delete value->iShim;
+            value->iShim = NULL;
+            }
+        else
+            {
+			break;
+            }
+		}
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::RestoreL
+// 
+//
+// ---------------------------------------------------------------------------
+//
+void CGSPluginAndViewIdCache::RestoreL()
+    {
+    TFileName* cacheFile = new(ELeave) TFileName();
+    CleanupStack::PushL( cacheFile );
+    GetCacheFileNameL( *cacheFile );
+    //
+    if  ( BaflUtils::FileExists( iFsSession, *cacheFile ) )
+        {
+        RFileReadStream cacheStream;
+        TInt error = cacheStream.Open( iFsSession, *cacheFile, EFileRead );
+        User::LeaveIfError( error );
+        CleanupClosePushL( cacheStream );
+
+        // Now read in cache hash table
+        TUid key = KNullUid;
+        TUid value = KNullUid;
+        
+        const TInt entryCount = cacheStream.ReadInt32L();
+        for( TInt i=0; i<entryCount; i++ )
+            {
+            key.iUid = cacheStream.ReadUint32L();
+            value.iUid = cacheStream.ReadUint32L();
+            //
+            RegisterViewAndImplementationAssociationL( key, value, ETrue );
+            }
+
+        CleanupStack::PopAndDestroy( &cacheStream );
+        }
+    //
+    CleanupStack::PopAndDestroy( cacheFile );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::StoreL
+// 
+//
+// ---------------------------------------------------------------------------
+//
+void CGSPluginAndViewIdCache::StoreL()
+    {
+    TFileName* intermediateFileName = new(ELeave) TFileName();
+    CleanupStack::PushL( intermediateFileName );
+
+    TFileName* cachePath = new(ELeave) TFileName();
+    CleanupStack::PushL( cachePath );
+    GetCachePathL( *cachePath );
+    
+    // Create a temporary file in the GS private data cage to contain
+    // the cache data. We'll rename this to the real cache file name
+    // once the operation has been completed successfully.
+    RFile intermediateCacheFile;
+    TInt error = intermediateCacheFile.Temp( iFsSession, *cachePath, *intermediateFileName, EFileWrite );
+    User::LeaveIfError( error );
+  
+    // Create a stream from the file. Stream takes ownership of file
+    RFileWriteStream stream( intermediateCacheFile );
+    CleanupClosePushL( stream );
+
+    // Write each entry to the stream
+    stream.WriteUint32L( iLookupTable.Count() );
+
+	RHashMap< TUid, TCacheEntry >::TIter iterator( iLookupTable );
+    FOREVER
+		{
+		const TUid* key = iterator.NextKey();
+		if  ( key )
+            {
+            const TCacheEntry* value = iterator.CurrentValue();
+            stream.WriteUint32L( key->iUid );
+            stream.WriteUint32L( value->iImplementationUid.iUid );
+            }
+        else
+            {
+			break;
+            }
+		}
+	
+    // Finalise the stream
+    stream.CommitL();
+    stream.Close(); // Also closes the file
+    CleanupStack::PopAndDestroy( &stream ); 
+
+    // If we got this far it means we created the cache file successfully.
+    // Now its okay to replace any pre-existing cache file with the
+    // file we just created. We're re-use the cachePath variable for the
+    // ultimate filename since it saves allocating another 1/2kb on the heap.
+    GetCacheFileNameL( *cachePath );
+    if  ( BaflUtils::FileExists( iFsSession, *cachePath ) )
+        {
+        error = iFsSession.Delete( *cachePath );
+        User::LeaveIfError( error );
+        }
+
+    // Now rename intermediate file name to ultimate cache file name.
+    error = iFsSession.Rename( *intermediateFileName, *cachePath );
+    User::LeaveIfError( error );
+
+    CleanupStack::PopAndDestroy( 2, intermediateFileName );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::GetCacheFileNameL
+// 
+//
+// ---------------------------------------------------------------------------
+//
+void CGSPluginAndViewIdCache::GetCacheFileNameL( TDes& aFileName )
+    {
+    GetCachePathL( aFileName );
+    aFileName.Append( KGSCacheFileName );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::GetCachePathL
+// 
+//
+// ---------------------------------------------------------------------------
+//
+void CGSPluginAndViewIdCache::GetCachePathL( TDes& aPath )
+    {
+    aPath.Zero();
+
+    // Get private data cage path
+    TInt err = iFsSession.PrivatePath( aPath );
+    User::LeaveIfError( err );
+
+    // Combine with C: drive
+    const TDriveUnit cDrive( EDriveC );
+    const TDriveName cDriveName( cDrive.Name() );
+    aPath.Insert( 0, cDriveName );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::RegisterViewAndImplementationAssociationL
+// 
+//
+// ---------------------------------------------------------------------------
+//
+void CGSPluginAndViewIdCache::RegisterViewAndImplementationAssociationL( TUid aViewId, TUid aImplementationUid, TBool aCreateShim )
+    {
+    // Check if aViewId is a key within the look up table, so as to avoid
+    // adding duplicate entries...
+    const TCacheEntry* value = iLookupTable.Find( aViewId );
+    if  ( !value )
+        {
+        // No registration for this view yet, so create a new entry
+        TCacheEntry cacheEntry;
+        cacheEntry.iImplementationUid = aImplementationUid;
+        cacheEntry.iLoadedPluginImplementation = NULL;
+
+        if  ( aCreateShim )
+            {
+            // Create a new shim
+            cacheEntry.iShim = CGSShimmedView::NewLC( aViewId, *this, iAppUi );
+            }
+        else
+            {
+            cacheEntry.iShim = NULL;
+            }
+
+        // Add entry to table - the shim ownership is also transferred 
+        // at this point, since the destructor of this class will
+        // destroy all shims.
+        iLookupTable.InsertL( aViewId, cacheEntry );
+        
+        if  ( aCreateShim )
+            {
+            CleanupStack::Pop( cacheEntry.iShim );
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::PrepareForUIDestruction
+// 
+//
+// ---------------------------------------------------------------------------
+//
+void CGSPluginAndViewIdCache::PrepareForUIDestruction()
+    {
+    // Have to remove all UI furniture before the AppUi rug is pulled out
+    // from underneath us...
+    DestroyShims();
+    //
+    delete iPlaceholderView;
+    iPlaceholderView = NULL;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::HandleShimDestruction
+// 
+//
+// ---------------------------------------------------------------------------
+//
+void CGSPluginAndViewIdCache::HandleShimDestruction( TUid aViewId )
+    {
+    TCacheEntry* value = iLookupTable.Find( aViewId );
+    if  ( value && value->iShim )
+        {
+        // The shim has been destroyed.
+        value->iShim = NULL;
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::ReRegisterShimWithUi
+// 
+//
+// ---------------------------------------------------------------------------
+//
+void CGSPluginAndViewIdCache::ReRegisterShimWithUi( TAny* aSelf )
+    {
+    CGSPluginAndViewIdCache* self = reinterpret_cast< CGSPluginAndViewIdCache* >( aSelf );
+    //
+    if  ( self->iTransientCleanupViewUid != KNullUid )
+        {
+        TCacheEntry* value = self->iLookupTable.Find( self->iTransientCleanupViewUid );
+        if  ( value && value->iShim )
+            {
+            TRAP_IGNORE( value->iShim->RegisterViewL() );
+            }
+        }
+    //
+    self->iTransientCleanupViewUid = KNullUid;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::HashFunction
+// 
+//
+// ---------------------------------------------------------------------------
+//
+TUint32 CGSPluginAndViewIdCache::HashFunction( const TUid& aViewId )
+    {
+    const TUint32 hash = DefaultHash::Integer( aViewId.iUid );
+    return hash;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSPluginAndViewIdCache::HashIdentityRelation
+// 
+//
+// ---------------------------------------------------------------------------
+//
+TBool CGSPluginAndViewIdCache::HashIdentityRelation( const TUid& aLeft, const TUid& aRight )
+    {
+    const TBool equal = ( aLeft.iUid == aRight.iUid );
+    return equal;
+    }
+