--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/menucontentsrv/srvsrc/mcssuitehandler.cpp Thu Dec 17 08:54:17 2009 +0200
@@ -0,0 +1,699 @@
+/*
+* Copyright (c) 2008 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:
+*
+*/
+
+// INCLUDE FILES
+#include <badesca.h>
+#include <sacls.h>
+
+#include "mcssuitehandler.h"
+#include "menueng.h"
+#include "mcsinstallnotifier.h"
+#include "mcssuiteparser.h"
+#include "mcssuiteobject.h"
+#include "menusrvengutils.h"
+#include "mcsmenuitem.h"
+
+// ================= LOCAL FUNCTIONS =======================
+
+/**
+* Cleanup support method. Call ResetAndDestroy() on the array.
+* @param RMenuItemArray* as TAny*
+*/
+LOCAL_C void ResetAndDestroy( TAny* aArray )
+ {
+ ((RPointerArray<CSuiteObject>*)aArray)->ResetAndDestroy();
+ }
+
+// ---------------------------------------------------------
+// CleanupResetAndDestroyPushL
+// ---------------------------------------------------------
+//
+LOCAL_C void CleanupResetAndDestroyPushL( RPointerArray<CSuiteObject>& aArray )
+ {
+ CleanupStack::PushL( TCleanupItem( ResetAndDestroy, &aArray ) );
+ }
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::NewL
+// ---------------------------------------------------------
+//
+CMcsSuiteHandler* CMcsSuiteHandler::NewL( CMenuEng& aEng, const TDesC& aDirName )
+ {
+ CMcsSuiteHandler* self = new( ELeave ) CMcsSuiteHandler( aEng );
+ CleanupStack::PushL( self );
+ self->ConstructL(aDirName);
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::~CMcsSuiteHandler
+// ---------------------------------------------------------
+//
+CMcsSuiteHandler::~CMcsSuiteHandler()
+ {
+ iSuites.ResetAndDestroy();
+ delete iMmcObserver;
+ delete iFreeSpaceObserver;
+ delete iInstallNotifier;
+ iTimestamps.Close();
+ iNewTimestamps.Close();
+ iEng.DequeueOperation( *this );
+ delete iInstalledFileList;
+ delete iFileNewList;
+ iDirPath.Close();
+ iFs.Close();
+ }
+
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::HaveSuite
+// ---------------------------------------------------------
+//
+TBool CMcsSuiteHandler::HaveSuite(const TDesC& aSuiteName)
+ {
+ return iSuites.Exist(aSuiteName);
+ }
+
+void CMcsSuiteHandler::GetAttribute( const TDesC& aSuiteName, const TDesC& aAttrName,
+ TBool& aAttrExists, TDes& aAttrVal )
+ {
+ TInt suitePos = iSuites.FindLastSuite(aSuiteName);
+ if (suitePos != KErrNotFound)
+ {
+ iSuites[suitePos]->GetAttribute(aAttrName, aAttrExists, aAttrVal);
+ }
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::CMcsSuiteHandler
+// ---------------------------------------------------------
+//
+CMcsSuiteHandler::CMcsSuiteHandler( CMenuEng& aEng ) :
+ iEng(aEng)
+ {
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::ConstructL
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::ConstructL(const TDesC& aDirName)
+ {
+ User::LeaveIfError( iFs.Connect( ) );
+ iDirPath.CreateL( KMaxPath );
+ User::LeaveIfError( iFs.PrivatePath( iDirPath ) );
+ iDirPath.Append(KImportDir);
+ iDirPath.Append(KBackSlash);
+ iDirPath.Append(aDirName);
+ iDirPath.Append(KBackSlash);
+ iFileNewList = new (ELeave) CDesCArrayFlat(KDefaultGranularity);
+ iInstalledFileList = new (ELeave) CDesCArrayFlat(KDefaultGranularity);
+ iInstallNotifier = CMcsInstallNotifier::NewL(*this, KSAUidSoftwareInstallKeyValue);
+ iMmcObserver = CMcsMmcObserver::NewL( *this );
+ iFreeSpaceObserver = CMcsFreeSpaceObserver::NewL( *this );
+ // Import suites form suite dir
+ CheckSuiteDirL();
+ iEvent = EInstOpRestore;
+ iEng.QueueOperationL( *this );
+ }
+
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::HandleInstallNotifyL
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::HandleInstallNotifyL(TInt aEvent)
+ {
+ // Look for new files
+ CheckSuiteDirL();
+ iEvent = aEvent;
+ iEng.QueueOperationL( *this );
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::HandleMmcEventL
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::HandleMmcEventL(TInt aEvent)
+ {
+ CheckSuiteDirL();
+ if (aEvent == EMmcInsert)
+ {
+ iEvent = EInstOpInstall;
+ }
+ else if (aEvent == EMmcRemove)
+ {
+ iEvent = EInstOpUninstall;
+ }
+ iEng.QueueOperationL( *this );
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::HandleFreeSpaceEventL
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::HandleFreeSpaceEventL()
+ {
+ CheckSuiteDirL();
+ iEvent = EInstOpUninstall;
+ iEng.QueueOperationL( *this );
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::CheckSuiteDirL
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::CheckSuiteDirL()
+ {
+ // Get file list
+ iFileNewList->Reset();
+ iNewTimestamps.Reset();
+
+ TDriveList driveList;
+ TChar driveLetter;
+ User::LeaveIfError(iFs.DriveList(driveList));
+ for (TInt driveNumber = EDriveA; driveNumber <= EDriveZ; driveNumber++)
+ {
+ if (driveList[driveNumber])
+ {
+ User::LeaveIfError(iFs.DriveToChar(driveNumber, driveLetter));
+ RBuf filePath;
+ filePath.CreateL(KMaxPath);
+ CleanupClosePushL(filePath);
+ filePath.Append(driveLetter);
+ filePath.Append(KColen);
+ filePath.Append(iDirPath);
+ CDir* fileList;
+
+ iFs.GetDir(filePath, KEntryAttMaskSupported,
+ ESortByName, fileList);
+
+ CleanupStack::PopAndDestroy(&filePath);
+ if (fileList)
+ {
+ CleanupStack::PushL(fileList);
+ for (TInt i = 0; i < fileList->Count(); i++)
+ {
+ // Not dir, xml file
+ if (!(*fileList)[i].IsDir() && ValidExtansion(
+ (*fileList)[i].iName))
+ {
+ // Don't add same file names more then once
+ // Or else it will case trouble during update
+ TInt dummy;
+ if ( iFileNewList->Find((*fileList)[i].iName, dummy) )
+ {
+ iFileNewList->AppendL((*fileList)[i].iName);
+ iNewTimestamps.AppendL((*fileList)[i].iModified);
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy(fileList);
+ }
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::AddNewL
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::AddNew()
+ {
+ for ( TInt i = 0; i < iFileNewList->Count(); i++ )
+ {
+ TPtrC fileNewName = (*iFileNewList)[i];
+ TTime fileTimestamp = iNewTimestamps[i];
+
+ if ( !FileInstalled(fileNewName) )
+ {
+ // Not yet installed, install it
+ TRAP_IGNORE( InstallFileL(fileNewName, fileTimestamp) );
+ }
+ else if (FileNeedUpdate(fileNewName, fileTimestamp) )
+ {
+ //Installed, but needs update
+ TRAP_IGNORE( UpdateFileL( fileNewName, fileTimestamp) );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::RemoveOldL
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::RemoveOld()
+ {
+ for ( TInt i = 0; i < iInstalledFileList->Count(); i++ )
+ {
+ TPtrC fileNewName = (*iInstalledFileList)[i];
+
+ // File was removed, unistall it
+ if ( FileUninstalled(fileNewName) )
+ {
+ TRAP_IGNORE( UninstallFileL(fileNewName) );
+ }
+ }
+ iInstalledFileList->Compress();
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::ScanSuitesL
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::ScanSuitesL()
+ {
+ RArray<TMenuItem> suiteItems;
+ CleanupClosePushL( suiteItems );
+ GetMenuSuitesL( suiteItems, KMenuAttSuiteAdded(), KMenuTrue() );
+
+ for ( TInt i = 0; i < suiteItems.Count(); i++ )
+ {
+ TBool dummy(EFalse);
+ TPtrC suiteName(KNullDesC);
+ iEng.ObjectL( suiteItems[i].Id() ).
+ FindAttribute( KMenuAttSuiteName, suiteName, dummy );
+
+ if ( !HaveSuite( suiteName ) )
+ {
+ iEng.RemoveL( suiteItems[i].Id() );
+ }
+ }
+ CleanupStack::PopAndDestroy(&suiteItems);
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::FileExistL
+// ---------------------------------------------------------
+//
+TBool CMcsSuiteHandler::FileInstalled(const TDesC& aFileName)
+ {
+ TInt posInArray;
+ // uses Folded Comparing
+ if (iInstalledFileList->Find(aFileName, posInArray) == KErrNone)
+ {
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::FileUninstalled
+// ---------------------------------------------------------
+//
+TBool CMcsSuiteHandler::FileUninstalled(const TDesC& aFileName)
+ {
+ for (TInt j = 0 ; j < iFileNewList->Count(); j++)
+ {
+ if ( !(*iFileNewList)[j].Compare( aFileName ) )
+ {
+ // Wasn't removed but maybe needs to be updated (rom case)
+ return FileNeedUpdate(aFileName, iNewTimestamps[j]);
+ }
+ }
+ return ETrue;
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::FileNeedUpdate
+// ---------------------------------------------------------
+//
+TBool CMcsSuiteHandler::FileNeedUpdate(const TDesC& aFileName, const TTime& aTimestamp)
+ {
+ TInt posInArray;
+ // uses Folded Comparing
+ if (iInstalledFileList->Find(aFileName, posInArray) == KErrNone)
+ {
+ // If timestamps mach then it's the same file
+ return (iTimestamps[posInArray] != aTimestamp);
+ }
+ return EFalse;
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::ValidExtansion
+// ---------------------------------------------------------
+//
+TBool CMcsSuiteHandler::ValidExtansion(const TDesC& aFileName)
+ {
+ TPtrC fileExt =
+ aFileName.Mid( aFileName.LocateReverse( KDot ) + 1 );
+
+ return ( fileExt.CompareF(KXmlExt) == 0 );
+ }
+
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::InstallFile
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::InstallFileL(const TDesC& aFileName, const TTime& aTimestam)
+ {
+ RPointerArray<CSuiteObject> suiteArray;
+ CleanupResetAndDestroyPushL(suiteArray);
+
+ // Get suite from suite file
+ GetSuitesL(aFileName, suiteArray);
+
+ //Add filename to installed suites files array
+ //If Leave occured during GetSuitesL filename wont be added
+ iInstalledFileList->AppendL(aFileName);
+ iTimestamps.AppendL(aTimestam);
+
+ // Take the ownership of suite items
+ for (TInt i = 0; i < suiteArray.Count(); i++ )
+ {
+ User::LeaveIfError( iSuites.Append( suiteArray[i] ) );
+ TRAPD( err, AddSuiteL( suiteArray[i]->SuiteName() ) );
+ if( err!=KErrNone )
+ {
+ if( i==0 )
+ {
+ iInstalledFileList->Delete( iInstalledFileList->Count()-1 );
+ iTimestamps.Remove( iTimestamps.Count()-1 );
+ }
+ iSuites.Remove( iSuites.Count()-1 );
+ User::Leave( err );
+ }
+ suiteArray[i] = NULL;
+ }
+ CleanupStack::Pop(&suiteArray);
+ suiteArray.Close();
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::UninstallFile
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::UninstallFileL(const TDesC& aFileName)
+ {
+ TInt pos(KErrNotFound);
+ if ( !iInstalledFileList->Find(aFileName, pos))
+ {
+
+ // Need to know what suites are beeing removed
+ CDesCArrayFlat* removedSuites =
+ new (ELeave) CDesCArrayFlat(KDefaultGranularity);
+ CleanupStack::PushL(removedSuites);
+ for (TInt i = 0; i < iSuites.Count(); i++)
+ {
+ if ( aFileName.Compare( iSuites[i]->FileName() ) == KErrNone )
+ {
+ removedSuites->AppendL( iSuites[i]->SuiteName() );
+ }
+ }
+
+ // We know what suites are beeing removed, we can remove those safly
+ iSuites.RemoveByFileName(aFileName);
+
+ // Remove uninstalled file from our list
+ iInstalledFileList->Delete(pos);
+ iTimestamps.Remove(pos);
+
+ // And reopen removed suites defined in other files
+ for (TInt i = 0; i < removedSuites->Count(); i++)
+ {
+ TInt suitePos = iSuites.FindLastSuite( (*removedSuites)[i] );
+ if (suitePos != KErrNotFound)
+ {
+ ReopenSuiteL(suitePos);
+ }
+ else
+ {
+ RemoveSuiteFromXmlL( (*removedSuites)[i] );
+ }
+ }
+
+ CleanupStack::PopAndDestroy(removedSuites);
+ }
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::UpdateFileL
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::UpdateFileL(const TDesC& aFileName, const TTime& aTimestam)
+ {
+ TInt pos;
+ if (iInstalledFileList->Find(aFileName, pos) == KErrNone)
+ {
+ // Get rid of out of date suites
+ iSuites.RemoveByFileName(aFileName);
+ iInstalledFileList->Delete(pos);
+ //iInstalledFileList->Compress();
+ iTimestamps.Remove(pos);
+
+ // Instal suites form file name
+ InstallFileL(aFileName, aTimestam);
+ }
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::GetSuites
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::GetSuitesL(const TDesC& aFileName,
+ RPointerArray<CSuiteObject>& aSuiteArray)
+ {
+ TDriveList driveList;
+ TChar driveLetter;
+ User::LeaveIfError( iFs.DriveList( driveList ) );
+ for ( TInt driveNumber = EDriveZ; driveNumber >= EDriveA; driveNumber-- )
+ {
+ if ( driveList[driveNumber] )
+ {
+ User::LeaveIfError( iFs.DriveToChar( driveNumber, driveLetter ) );
+ RBuf file;
+ file.CleanupClosePushL();
+ file.CreateL( KMaxPath );
+ file.Append( driveLetter );
+ file.Append( KColen );
+ file.Append( iDirPath );
+ file.Append( aFileName );
+ CSuiteParser* suiteParser = CSuiteParser::NewL(file);
+ CleanupStack::PushL(suiteParser);
+ TRAP_IGNORE( suiteParser->GetSuitsArrayL( aSuiteArray ) );
+ CleanupStack::PopAndDestroy(suiteParser);
+ CleanupStack::PopAndDestroy( &file );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::ReopenSuite
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::ReopenSuiteL(TInt aSuiteArrayPos)
+ {
+ RPointerArray<CSuiteObject> suiteArray;
+ CleanupResetAndDestroyPushL(suiteArray);
+
+ TPtrC suiteName = iSuites[aSuiteArrayPos]->SuiteName();
+ TPtrC fileName = iSuites[aSuiteArrayPos]->FileName();
+
+ // Get suite from suite file
+ GetSuitesL(fileName, suiteArray);
+
+ // Find our suite in suites from specified file
+ CSuiteObject* neededSuite = NULL;
+ for (TInt j = 0; j < suiteArray.Count(); j++)
+ {
+ if (suiteArray[j]->SuiteName().Compare(suiteName) == KErrNone)
+ {
+ // Take ownership of Suite Object
+ neededSuite = suiteArray[j];
+ suiteArray.Remove(j);
+ break;
+ }
+ }
+
+ if ( neededSuite )
+ {
+ // Replace Suite Object in suiteArray
+ delete iSuites[aSuiteArrayPos];
+ iSuites[aSuiteArrayPos] = neededSuite;
+ }
+ else
+ {
+ // Must be some error, delete that suite
+ delete iSuites[aSuiteArrayPos];
+ iSuites.Remove( aSuiteArrayPos );
+ }
+
+ CleanupStack::PopAndDestroy(&suiteArray);
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::GetMenuSuitesL
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::GetMenuSuitesL(
+ RArray<TMenuItem>& aItemArray,
+ const TDesC& aAttrName,
+ const TDesC& aAttrValue )
+ {
+ TInt root( 0 );
+ iEng.RootFolderL( root );
+ TMenuSrvTypeAttrFilter suiteFilter;
+ suiteFilter.SetType( KMenuTypeSuite() );
+ suiteFilter.SetAttr( aAttrName, aAttrValue );
+ iEng.GetItemsL( aItemArray, root, &suiteFilter, ETrue );
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::AddSuiteL
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::AddSuiteL( const TPtrC& aSuiteName )
+ {
+ RArray<TMenuItem> mcsItems;
+ CleanupClosePushL( mcsItems );
+ GetMenuSuitesL( mcsItems, KMenuAttSuiteName(), aSuiteName );
+
+ if( mcsItems.Count() == KErrNone )
+ {
+ AddSuiteToXmlL( aSuiteName );
+ }
+ else
+ {
+ UpdateItemsL( mcsItems );
+ }
+ CleanupStack::PopAndDestroy(&mcsItems);
+ }
+
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::AddSuiteL
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::RemoveSuiteFromXmlL( const TPtrC& aSuiteName )
+ {
+ RArray<TMenuItem> mcsItems;
+ CleanupClosePushL( mcsItems );
+ GetMenuSuitesL( mcsItems, KMenuAttSuiteName(), aSuiteName );
+
+ for( TInt i( 0 ); i < mcsItems.Count(); i++ )
+ {
+ UpdateSuiteInXmlL( mcsItems, i );
+ }
+
+ CleanupStack::PopAndDestroy(&mcsItems);
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::UpdateSuiteInXmlL
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::UpdateSuiteInXmlL(
+ RArray<TMenuItem> & aMcsItems, TInt aIndex )
+ {
+ TBool dummy(EFalse);
+ TPtrC val(KNullDesC);
+ if( iEng.ObjectL(aMcsItems[aIndex].Id()).
+ FindAttribute( KMenuAttSuiteAdded, val, dummy ) )
+ {
+ if ( val.Compare(KMenuTrue) == KErrNone )
+ {
+ iEng.RemoveL(aMcsItems[aIndex].Id());
+ }
+ else if ( val.Compare(KMenuFalse) == KErrNone )
+ {
+ iEng.ModifiableObjectL(aMcsItems[aIndex].Id()).
+ RemoveAttribute( KMenuAttSuiteAdded );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::RunMenuEngOperationL
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::RunMenuEngOperationL()
+ {
+ if ( iEvent & EInstOpInstall )
+ {
+ // Add new suites
+ AddNew();
+ }
+ else if ( ( iEvent & EInstOpUninstall ) )
+ {
+ // Remove old suites, andd new if needed (stub sis case)
+ RemoveOld();
+ AddNew();
+ }
+ else if( ( iEvent & EInstOpRestore ) )
+ {
+ AddNew();
+ ScanSuitesL();
+ }
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::CompletedMenuEngOperation
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::CompletedMenuEngOperation( TInt /*aErr*/ )
+ {
+
+ }
+// ---------------------------------------------------------
+// CMcsSuiteHandler::AddSuiteToXmlL
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::AddSuiteToXmlL( const TPtrC& aSuiteName )
+ {
+ TInt root( 0 );
+ iEng.RootFolderL( root );
+
+ CMenuEngObject* obj = iEng.NewObjectL( KMenuTypeSuite );
+ CleanupStack::PushL( obj );
+ obj->SetAttributeL( KMenuAttSuiteName, aSuiteName, EFalse );
+ obj->SetAttributeL( KMenuAttSuiteAdded, KMenuTrue, EFalse );
+ iEng.AddL( *obj, root, 0 );
+ CleanupStack::Pop( obj );
+ }
+
+// ---------------------------------------------------------
+// CMcsSuiteHandler::UpdateItemsL
+// ---------------------------------------------------------
+//
+void CMcsSuiteHandler::UpdateItemsL(
+ const RArray<TMenuItem>& aItemArray )
+ {
+ for( TInt i( 0 ); i < aItemArray.Count(); ++i )
+ {
+ TPtrC val(KNullDesC);
+ TBool dummy( EFalse );
+ iEng.ObjectL( aItemArray[i].Id() ).
+ FindAttribute( KMenuAttSuiteAdded, val, dummy );
+ if( val.Compare( KMenuTrue ) != KErrNone )
+ {
+ iEng.ModifiableObjectL( aItemArray[i].Id() ).
+ SetAttributeL( KMenuAttSuiteAdded, KMenuFalse, EFalse);
+ }
+ else
+ {
+ iEng.ModifiableObjectL( aItemArray[i].Id() ).
+ SetAttributeL( KMenuAttSuiteAdded, KMenuTrue, EFalse);
+ }
+ }
+ }
+