diff -r e8c1ea2c6496 -r 8758140453c0 localisation/apparchitecture/apserv/apsnnapps.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/localisation/apparchitecture/apserv/apsnnapps.cpp Thu Jan 21 12:53:44 2010 +0000 @@ -0,0 +1,733 @@ +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Symbian Foundation License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Non-Native application registration functionality for the AppArc server session +// +// + + +#include "apsnnapps.h" + +#include +#include +#include + +#include "APSCLSV.H" +#include "APSSERV.H" +#include "APSSTD.H" +#include "../apgrfx/apprivate.h" +#include "apsnnappupdates.h" + +/** +KNonNativeApplicationsUpdateLog +@internalComponent +*/ +_LIT(KNonNativeApplicationsUpdateLog, ":\\private\\10003a3f\\UpdatedAppsList.bin"); + +/************************************************************************************************************** + * CApsNonNativeApplicationsUpdateList + **************************************************************************************************************/ + +CApsNonNativeApplicationsUpdateList* CApsNonNativeApplicationsUpdateList::NewL(RFs& aFs) + { + CApsNonNativeApplicationsUpdateList* self = new(ELeave) CApsNonNativeApplicationsUpdateList(aFs); + return self; + } + +void CApsNonNativeApplicationsUpdateList::RecoverFromUpdateLogL(RFs& aFs, RFile& aFile) + { + CleanupClosePushL(aFile); + CApsNonNativeApplicationsUpdateList* self = new(ELeave) CApsNonNativeApplicationsUpdateList(aFs); + CleanupStack::PushL(self); + self->RecoverFromUpdateLogL(aFile); // consumes aFile + CleanupStack::PopAndDestroy(self); + CleanupStack::Pop(&aFile); + } + + +CApsNonNativeApplicationsUpdateList::CApsNonNativeApplicationsUpdateList(RFs& aFs) : + iFs(aFs) + { + } + +CApsNonNativeApplicationsUpdateList::~CApsNonNativeApplicationsUpdateList() + { + CApsNonNativeApplicationsUpdate* update = iUpdateListHead; + while(update != NULL) + { + CApsNonNativeApplicationsUpdate* next = update->Next(); + delete update; + update = next; + } + } + +void CApsNonNativeApplicationsUpdateList::RecoverFromUpdateLogL(RFile& aFile) + { + RFileReadStream readStream; + CleanupClosePushL(readStream); + RFile logFileDupe; + User::LeaveIfError(logFileDupe.Duplicate(aFile)); + readStream.Attach(logFileDupe); // Attach takes ownership of & Nulls the handle passed to it + TInt pos = 0; + InternalizeL(readStream,pos); + CleanupStack::PopAndDestroy(&readStream); + + /* Great, we've read in all our performed updates and deleted all the ones that were fully + rolled back. + The next step is to roll back the rest of the updates. We'll need to create an + update log as it was before the reboot, so that further rollbacks we successfully perform + can also be logged in it */ + + // pos should point to the end of the last compelte action recorded in the file + // remove any invalid or half-written actions by truncating to pos + User::LeaveIfError(aFile.SetSize(pos)); + RApsUpdateLog updateLog(iFs); + updateLog.Open(aFile,pos); // consumes aFile + CleanupClosePushL(updateLog); + + if(iEEndOfUpdateRequiredToFixLog) + { + updateLog.LogWriteStream().WriteInt8L(CApsNonNativeApplicationsUpdate::EEndOfUpdate); + updateLog.LogWriteStream().CommitL(); // puts us back to an alpha stopping point + } + + if(iLogReplayCurrentUpdate != NULL) + { + switch(iLogReplayCurrentUpdate->iState) + { + case CApsNonNativeApplicationsUpdate::ENew: + /* current update was never performed. Start rollback at the previous one, + which will be in EPerformed */ + iLogReplayCurrentUpdate = iLogReplayCurrentUpdate->Previous(); + ASSERT(iLogReplayCurrentUpdate == NULL || iLogReplayCurrentUpdate->iState == CApsNonNativeApplicationsUpdate::EPerformed); + break; + case CApsNonNativeApplicationsUpdate::EPerforming: + case CApsNonNativeApplicationsUpdate::EPerformed: + case CApsNonNativeApplicationsUpdate::ERollingBack: + break; + case CApsNonNativeApplicationsUpdate::ERolledBack: + User::Leave(KErrCorrupt); + break; + } + Rollback(iLogReplayCurrentUpdate, updateLog); + } + CleanupStack::PopAndDestroy(&updateLog); + } + +void CApsNonNativeApplicationsUpdateList::InternalizeL(RReadStream& aStream, TInt& aPosition) + { + TInt err = KErrNone; + while(err == KErrNone) + { + TRAP(err,InternalizeActionL(aStream,aPosition)); + if(err == KErrNone || err == KErrCorrupt || err == KErrEof) + { + // We anticipate that the last update we try to read may be incomplete or corrupt. + // if we get either of these, jsut stop reading in the list of updates. + } + else + { + // something really unexpected, e.g. KErrNoMemory + User::Leave(err); + } + } + CApsNonNativeApplicationsUpdate* update = iUpdateListHead; + while(update) + { + update->PostInternalizeL(); + update = update->Next(); + } + } + +void CApsNonNativeApplicationsUpdateList::InternalizeActionL(RReadStream& aStream, TInt& aPosition) + { + TInt pos = aPosition; + + CApsNonNativeApplicationsUpdate::TLogActionType action = + static_cast(aStream.ReadInt8L()); + CApsNonNativeApplicationsUpdate::TLogUpdateType type = + static_cast(aStream.ReadInt8L()); + TUid appUid; + appUid.iUid = aStream.ReadInt32L(); + pos += sizeof(TInt8) + sizeof(TInt8) + sizeof(TUint32); + + switch(action) + { + case CApsNonNativeApplicationsUpdate::ENewUpdate: + // for ENewUpdate, this is not a valid stopping point, + // so we don't want to change aPosition unless it completes successfully. + InternalizeNewUpdateL(aStream, pos, type, appUid); + aPosition = pos; + break; + case CApsNonNativeApplicationsUpdate::EPerformUpdate: + // for EPerformUpdate, this is a beta stopping point, and + // InternalizePerformUpdateL will only ever update aPosition to + // another stopping point, so we can give it the real aPosition. + // Since it's a beta stopping point, we need to set iEEndofUpdateRequiredToFixLog + iEEndOfUpdateRequiredToFixLog = ETrue; + aPosition = pos; + InternalizePerformUpdateL(aStream, aPosition, type, appUid); + iEEndOfUpdateRequiredToFixLog = EFalse; + break; + case CApsNonNativeApplicationsUpdate::ERollbackUpdate: + // this action has the same behaviour as EPerformUpdate + iEEndOfUpdateRequiredToFixLog = ETrue; + aPosition = pos; + InternalizeRollbackUpdateL(aStream, aPosition, type, appUid); + iEEndOfUpdateRequiredToFixLog = EFalse; + break; + default: + User::Leave(KErrCorrupt); + break; + } + } + +void CApsNonNativeApplicationsUpdateList::InternalizeNewUpdateL(RReadStream& aStream, TInt& aPosition, CApsNonNativeApplicationsUpdate::TLogUpdateType aType, TUid aUid) + { + // check that this is the first update or the previous update was performed completely + if(iLogReplayCurrentUpdate != NULL && (iLogReplayCurrentUpdate->iState != CApsNonNativeApplicationsUpdate::EPerformed || iLogReplayCurrentUpdate->Next() != NULL)) + { + User::Leave(KErrCorrupt); + } + + /* + create the update object, depending on type + */ + CApsNonNativeApplicationsUpdate* update = NULL; + switch(aType) + { + case CApsNonNativeApplicationsUpdate::ERegisterApplication: + update = CApsRegisterNonNativeApplication::NewL(iFs, aUid, TDriveName(), CApsNonNativeApplicationsUpdate::ENeedsInternalizing); + break; + case CApsNonNativeApplicationsUpdate::EDeregisterApplication: + update = CApsDeregisterNonNativeApplication::NewL(iFs, *CApaAppListServer::Self(), aUid, CApsNonNativeApplicationsUpdate::ENeedsInternalizing); + break; +#ifdef _DEBUG + case CApsNonNativeApplicationsUpdate::EFail: + update = new(ELeave) CApsAlwaysFailUpdate(iFs, CApsNonNativeApplicationsUpdate::ENeedsInternalizing); + break; + case CApsNonNativeApplicationsUpdate::EPanic: + update = new(ELeave) CApsAlwaysPanicUpdate(iFs, CApsNonNativeApplicationsUpdate::ENeedsInternalizing); + break; + case CApsNonNativeApplicationsUpdate::ERollbackPanic: + update = new(ELeave) CApsAlwaysPanicOnRollbackUpdate(iFs, CApsNonNativeApplicationsUpdate::ENeedsInternalizing); + break; +#endif + default: + User::Leave(KErrCorrupt); + break; + } + CleanupStack::PushL(update); + update->InternalizeNewUpdateL(aStream, aPosition); + CleanupStack::Pop(update); + /* alpha stopping point. + update->iState should be ENew now. + */ + Append(update); + iLogReplayCurrentUpdate = update; + } + +void CApsNonNativeApplicationsUpdateList::InternalizePerformUpdateL(RReadStream& aStream, TInt& aPosition, CApsNonNativeApplicationsUpdate::TLogUpdateType aType, TUid aUid) + { + if(iLogReplayCurrentUpdate == NULL || iLogReplayCurrentUpdate->iState != CApsNonNativeApplicationsUpdate::ENew) + { + User::Leave(KErrCorrupt); + } + if(iLogReplayCurrentUpdate->Uid() != aUid || iLogReplayCurrentUpdate->iType != aType) + { + User::Leave(KErrCorrupt); + } + /* + tell the update to read in its log + */ + iLogReplayCurrentUpdate->InternalizePerformUpdateL(aStream, aPosition); + // the function above will return iff EEndOfUpdate is reached + } + + +void CApsNonNativeApplicationsUpdateList::InternalizeRollbackUpdateL(RReadStream& aStream, TInt& aPosition, CApsNonNativeApplicationsUpdate::TLogUpdateType aType, TUid aUid) + { + if(iLogReplayCurrentUpdate == NULL) + { + User::Leave(KErrCorrupt); + } + if( iLogReplayCurrentUpdate->iState != CApsNonNativeApplicationsUpdate::EPerforming + && iLogReplayCurrentUpdate->iState != CApsNonNativeApplicationsUpdate::EPerformed + && iLogReplayCurrentUpdate->iState != CApsNonNativeApplicationsUpdate::ERollingBack) + { + User::Leave(KErrCorrupt); + } + if(iLogReplayCurrentUpdate->iType != aType || iLogReplayCurrentUpdate->Uid() != aUid) + { + User::Leave(KErrCorrupt); + } + + iLogReplayCurrentUpdate->InternalizeRollbackUpdateL(aStream, aPosition); + // the function above will return iff EEndOfUpdate is reached + + if(iLogReplayCurrentUpdate->iState == CApsNonNativeApplicationsUpdate::ERolledBack) + { + iLogReplayCurrentUpdate = iLogReplayCurrentUpdate->Previous(); + } + } + +void CApsNonNativeApplicationsUpdateList::Append(CApsNonNativeApplicationsUpdate* aUpdate) + { + if(iUpdateListHead == NULL) + { + iUpdateListHead = aUpdate; + return; + } + + CApsNonNativeApplicationsUpdate* update = iUpdateListHead; + while(update->iNext != NULL) + { + update = update->iNext; + } + update->iNext = aUpdate; + aUpdate->iPrevious = update; + } + +void CApsNonNativeApplicationsUpdateList::ExecuteL() + { + RApsUpdateLog updateLog(iFs); + updateLog.OpenL(); + CleanupClosePushL(updateLog); + CApsNonNativeApplicationsUpdate* update = iUpdateListHead; + while(update != NULL) + { + TRAPD(err,update->PerformUpdateL(updateLog)); + if(err == KErrNone) + { + update = update->Next(); + } + else + { + // call rollback on everything, including the one that failed + // since it may have to clean up half-finished stuff + Rollback(update, updateLog); + User::Leave(err); + } + } + CleanupStack::PopAndDestroy(&updateLog); + } + +void CApsNonNativeApplicationsUpdateList::Rollback(CApsNonNativeApplicationsUpdate* aStartPoint, RApsUpdateLog& aUpdateLog) + { + CApsNonNativeApplicationsUpdate* update = aStartPoint; + + while(update != NULL) + { + TRAP_IGNORE(update->RollbackUpdateL(aUpdateLog)); + update = update->Previous(); + } + } + +/** +@internalComponent +*/ +RApsUpdateLog::RApsUpdateLog(RFs& aFs) : + iFs(aFs) + { + TChar drive = RFs::GetSystemDriveChar(); + iLogFileName.Append(drive); + iLogFileName.Append(KNonNativeApplicationsUpdateLog); + } + +/** +RApsUpdateLog::OpenL + +Opens a write stream to a log file that keeps track of what updates have been performed. + +@internalComponent +*/ +void RApsUpdateLog::OpenL() + { + User::LeaveIfError(iLogWriteStream.Replace(iFs,iLogFileName,EFileShareExclusive|EFileStream|EFileWrite)); + } + +/** +RApsUpdateLog::Open + +Opens a write stream to a log file that keeps track of what updates have been performed. + +@internalComponent +*/ +void RApsUpdateLog::Open(RFile& aFile, TUint aSeekPos) + { + iLogWriteStream.Attach(aFile, aSeekPos); + } + +/** +RApsUpdateLog::Close + +Cleans up the list of new Registration files created during this set of updates +and deletes the log files created. + +@internalComponent +*/ +void RApsUpdateLog::Close() + { + _LIT(KLitPathForTemporaryFiles, "\\private\\10003a3f\\temp\\"); + const TInt count = iDrivesAffected.Count(); + CFileMan* fileman = NULL; + TRAPD(err, fileman = CFileMan::NewL(iFs)); + if (err == KErrNone) + { + for(TInt i = 0; i < count; ++i) + { + TFileName dir(*(iDrivesAffected[i])); + dir.Append(KLitPathForTemporaryNonNativeResourceAndIconFiles); + fileman->RmDir(dir); // recursive + iFs.RmDir(KLitPathForTemporaryFiles); // non-recursive + } + delete fileman; + } + + iFilesRegistered.ResetAndDestroy(); + iDrivesAffected.ResetAndDestroy(); + iLogWriteStream.Close(); + iFs.Delete(iLogFileName); + } + + +/** +CApsNonNativeApplicationsUpdateList::RApsUpdateLog holds a list of registration files that have +been written during this transaction. This list is used by the Deregistration +command as the forced-updates list. + +This stops them from being incorrectly hidden from the scan performed to find +the registration file to delete. + +@internalComponent +*/ +RPointerArray& RApsUpdateLog::NewRegistrationFiles() + { + return iFilesRegistered; + } + + +/** +CApsNonNativeApplicationsUpdateList::RApsUpdateLog holds a list of drives that have been used +in the transaction. This is then used to clean up the temporary file directories + +@internalComponent +*/ +RPointerArray& RApsUpdateLog::DrivesAffected() + { + return iDrivesAffected; + } + +/** +Returns the stream that updates should write their recovery log data to +@internalComponent +*/ +RWriteStream& RApsUpdateLog::LogWriteStream() + { + return iLogWriteStream; + } + +/************************************************************************************************************** + * CApsNonNativeApplicationsManager + **************************************************************************************************************/ + +void CApsNonNativeApplicationsManager::NotifyScanComplete() + { + //See if the session is intrested in scan complete notification. + if (!iNotifyOnScanCompleteMsg.IsNull()) + { + iNotifyOnScanCompleteMsg.Complete(KErrNone); + } + } //lint !e1762 Suppress member function could be made const + + +CApsNonNativeApplicationsManager* CApsNonNativeApplicationsManager::NewL(CApaAppListServer& aServ, RFs& aFs) + { + CApsNonNativeApplicationsManager* self = new(ELeave)CApsNonNativeApplicationsManager(aServ, aFs); + return self; + } + +CApsNonNativeApplicationsManager::~CApsNonNativeApplicationsManager() + { + delete iUpdateList; + } + +CApsNonNativeApplicationsManager::CApsNonNativeApplicationsManager(CApaAppListServer& aServ, RFs& aFs) : + iServ(aServ), + iFs(aFs) + { + } + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CApsNonNativeApplicationsManager::PrepareNonNativeApplicationsUpdatesL() + { + if (iServ.AppList().AppScanInProgress()) + { + iServ.AppList().StopScan(ETrue); //Stop updating applist now, we anyways have to update it when we are commiting these changes + } + if (iNonNativeApplicationsUpdateAppsLock) + { + User::Leave(KErrInUse); + } + + ASSERT(iUpdateList == NULL); + + iUpdateList = CApsNonNativeApplicationsUpdateList::NewL(iFs); + iNonNativeApplicationsUpdateAppsLock = ETrue; + } + + +void CApsNonNativeApplicationsManager::CheckForUpdateAppsLockL() + { + if (!iNonNativeApplicationsUpdateAppsLock) + { + // PrepareNonNativeApplicationsUpdatesL hasn't been called successfully + User::Leave(KErrNotReady); + } + } + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void CApsNonNativeApplicationsManager::RegisterNonNativeApplicationL(const RMessage2& aMessage) + { + CheckForUpdateAppsLockL(); + CleanupStack::PushL(TCleanupItem(&StaticAbortNonNativeApplicationsUpdates,this)); + DoRegisterNonNativeApplicationL(aMessage); + CleanupStack::Pop(this); + } + + +void CApsNonNativeApplicationsManager::DoRegisterNonNativeApplicationL(const RMessage2& aMessage) + { + // an RBuf for creating the file names in. + // create it here so it's below ipcParameter0 on the cleanup stack + RBuf target; + CleanupClosePushL(target); + + // read in the resource file from aMessage + RBuf8 ipcParameter0(HBufC8::NewL(aMessage.GetDesLengthL(0))); + CleanupClosePushL(ipcParameter0); + aMessage.ReadL(0, ipcParameter0); + if (ipcParameter0.Length()<=sizeof(SNonNativeApplicationInfo)+sizeof(TCheckedUid)) + { + User::Leave(KErrArgument); + } + + // get drivename + const SNonNativeApplicationInfo nonNativeApplicationInfo = *reinterpret_cast(ipcParameter0.Ptr()); + TDriveName driveName = TDriveUnit(nonNativeApplicationInfo.iDrive).Name(); + + // get uid + const TUid applicationUid(TCheckedUid(ipcParameter0.Mid(sizeof(SNonNativeApplicationInfo), sizeof(TCheckedUid))).UidType()[2]); + if (applicationUid==TUid::Null()) + { + User::Leave(KErrArgument); + } + + // construct resource file name + target.CreateL(driveName, KMaxFileName); + target.Append(KLitPathForNonNativeResourceAndIconFiles); + const TInt startOfFileName=target.Length(); // take note of this so we can chop off the file name later + target.AppendFormat(KLitFormatForRegistrationResourceFile, applicationUid.iUid); + + // prepare registrationResourceFileDataPrefix + const TUidType uidPrefix(TUid::Uid(KUidPrefixedNonNativeRegistrationResourceFile), nonNativeApplicationInfo.iApplicationType, applicationUid); + const TBufC8 registrationResourceFileDataPrefix(TCheckedUid(uidPrefix).Des()); + + // create the object that will actually perform the update + CApsRegisterNonNativeApplication* updateObject = CApsRegisterNonNativeApplication::NewL(iFs, applicationUid, driveName); + CleanupStack::PushL(updateObject); + + // write resource file to temp location + updateObject->SetResourceFileTargetLocation(target); + updateObject->WriteResourceFileL(ipcParameter0.Mid(sizeof(SNonNativeApplicationInfo)), ®istrationResourceFileDataPrefix); + + if (aMessage.Int1()!=0) // if there is a localisable resource-file + { + RBuf8 ipcParameter1(HBufC8::NewL(User::LeaveIfError(aMessage.GetDesLength(1)))); + CleanupClosePushL(ipcParameter1); + aMessage.ReadL(1, ipcParameter1); + + // construct localisable resoure file name + target.SetLength(startOfFileName); + target.AppendFormat(KLitFormatForLocalisableResourceFile, applicationUid.iUid); + + updateObject->SetLocalisableResourceFileTargetLocation(target); + // write localisable resource file to temp location + updateObject->WriteLocalisableResourceFileL(ipcParameter1, NULL); + CleanupStack::PopAndDestroy(&ipcParameter1); + + if (aMessage.Int2()!=0) // if there is an icon-file + { + RFile iconFile; + CleanupClosePushL(iconFile); + User::LeaveIfError(iconFile.AdoptFromClient(aMessage, 2, 3)); + RBuf iconFileName; + CleanupClosePushL(iconFileName); + iconFileName.CreateL(KMaxFileName); + User::LeaveIfError(iconFile.Name(iconFileName)); + + if (startOfFileName+iconFileName.Length()>KMaxFileName) + { + User::Leave(KErrArgument); + } + target.SetLength(startOfFileName); + target.Append(iconFileName); + updateObject->SetIconFileTargetLocation(target); + updateObject->CopyIconFileL(iconFile); + + CleanupStack::PopAndDestroy(2, &iconFile); // iconFileName, iconFile + } + } + + CleanupStack::Pop(updateObject); + iUpdateList->Append(updateObject); + + CleanupStack::PopAndDestroy(2, &target); // ipcParameter0, target + } + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CApsNonNativeApplicationsManager::DeregisterNonNativeApplicationL(const RMessage2& aMessage) + { + CheckForUpdateAppsLockL(); + CleanupStack::PushL(TCleanupItem(&StaticAbortNonNativeApplicationsUpdates,this)); + const TUid applicationUid(TUid::Uid(aMessage.Int0())); + iUpdateList->Append(CApsDeregisterNonNativeApplication::NewL(iFs, iServ, applicationUid)); + CleanupStack::Pop(this); + } + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef _DEBUG +void CApsNonNativeApplicationsManager::ForceFailInNonNativeApplicationsUpdatesL() + { + CheckForUpdateAppsLockL(); + CleanupStack::PushL(TCleanupItem(&StaticAbortNonNativeApplicationsUpdates,this)); + iUpdateList->Append(new(ELeave) CApsAlwaysFailUpdate(iFs)); + CleanupStack::Pop(this); + } + +void CApsNonNativeApplicationsManager::ForcePanicInNonNativeApplicationsUpdatesL() + { + CheckForUpdateAppsLockL(); + CleanupStack::PushL(TCleanupItem(&StaticAbortNonNativeApplicationsUpdates,this)); + iUpdateList->Append(new(ELeave) CApsAlwaysPanicUpdate(iFs)); + CleanupStack::Pop(this); + } + +void CApsNonNativeApplicationsManager::ForcePanicInNonNativeApplicationsRollbackL() + { + CheckForUpdateAppsLockL(); + CleanupStack::PushL(TCleanupItem(&StaticAbortNonNativeApplicationsUpdates,this)); + iUpdateList->Append(new(ELeave) CApsAlwaysPanicOnRollbackUpdate(iFs)); + CleanupStack::Pop(this); + } + +#endif // _DEBUG + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CApsNonNativeApplicationsManager::CommitNonNativeApplicationsUpdatesL(const RMessage2& aMessage) + { + CheckForUpdateAppsLockL(); + + TRAPD(err,iUpdateList->ExecuteL()); + + // Failure or success, we can't be hanging on to the lock after this function completes + delete iUpdateList; + iUpdateList = NULL; + iNonNativeApplicationsUpdateAppsLock = EFalse; + + if (KErrNone != err) + { + if(iServ.AppList().AppListUpdatePending()) + { + // Trigger a rescan + iServ.UpdateApps(); + } + User::Leave(err); // bail out at this point if things didn't go to plan + } + + if(aMessage.Int0()==(TInt) ETrue) + //The request is completed without waiting till completion application list preparation. + aMessage.Complete(KErrNone); + else + //The request is not completed till completion application list preparation. + iNotifyOnScanCompleteMsg=aMessage; + + // Trigger a rescan + iServ.UpdateApps(); + } + +/** +This function has the word "Rollback" in it because it used to actually roll back the +updates that had been preformed but whose effects were hidden from the public APIs until commit. + +The real updates no longer happen until commit-time, so there's no real rolling back to be done here. +The real rolling back is done automatically by iUpdateList, during the commit call, if neccessary. +*/ +void CApsNonNativeApplicationsManager::RollbackNonNativeApplicationsUpdates() + { + AbortNonNativeApplicationsUpdates(); + } + +void CApsNonNativeApplicationsManager::AbortNonNativeApplicationsUpdates() + { + if (!iNonNativeApplicationsUpdateAppsLock) + { + // It is always ok to call this function but if we haven't called PrepareNonNativeApplicationsUpdatesL() + // there isn't anything to do + return; + } + if(iServ.AppList().AppListUpdatePending()) + { + // Trigger a rescan + iServ.UpdateApps(); + } + delete iUpdateList; + iUpdateList = NULL; + iNonNativeApplicationsUpdateAppsLock = EFalse; + } + +void CApsNonNativeApplicationsManager::StaticAbortNonNativeApplicationsUpdates(TAny* aSelf) + { + static_cast(aSelf)->AbortNonNativeApplicationsUpdates(); + } + +void CApsNonNativeApplicationsManager::RecoverFromUpdateLogL(RFs& aFs) + { + TChar drive = RFs::GetSystemDriveChar(); + TFileName logPath; + logPath.Append(drive); + logPath.Append(KNonNativeApplicationsUpdateLog); + RFile logFile; + TInt err = logFile.Open(aFs,logPath,EFileShareExclusive|EFileStream|EFileWrite); + if(err == KErrNotFound || err == KErrPathNotFound) + { + // no log file, nothing to do. + return; + } + User::LeaveIfError(err); + // this function takes over ownership of logFile + TRAP(err,CApsNonNativeApplicationsUpdateList::RecoverFromUpdateLogL(aFs, logFile)); + if(err != KErrNone) + { + // there's nothing we can do, just delete it and move on + aFs.Delete(logPath); + } + + }