--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/appfw/apparchitecture/apserv/apsnnapps.cpp Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,742 @@
+// 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 "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:
+// Non-Native application registration functionality for the AppArc server session
+//
+// apsnnapps.cpp
+//
+
+
+#include "apsnnapps.h"
+
+#include <bautils.h>
+#include <f32file.h>
+#include <s32file.h>
+
+#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 not complete 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<CApsNonNativeApplicationsUpdate::TLogActionType>(aStream.ReadInt8L());
+ CApsNonNativeApplicationsUpdate::TLogUpdateType type =
+ static_cast<CApsNonNativeApplicationsUpdate::TLogUpdateType>(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, *CApaAppArcServer::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), iFilesRegistered(NULL), iDrivesAffected(NULL)
+ {
+ 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()
+ {
+ ASSERT(!iFilesRegistered && !iDrivesAffected);
+ const TInt KArrayGranularity = 128;
+ iFilesRegistered = new (ELeave) CDesCArraySeg(KArrayGranularity);
+ iDrivesAffected = new (ELeave) CDesCArraySeg(KArrayGranularity);
+ 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 ? iDrivesAffected->Count() : 0);
+ 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;
+ }
+
+ delete iFilesRegistered;
+ iFilesRegistered = NULL;
+
+ delete iDrivesAffected;
+ iDrivesAffected = NULL;
+
+ 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
+*/
+CDesCArray& 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
+*/
+CDesCArray& 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(CApaAppArcServer& aServ, RFs& aFs)
+ {
+ CApsNonNativeApplicationsManager* self = new(ELeave)CApsNonNativeApplicationsManager(aServ, aFs);
+ return self;
+ }
+
+CApsNonNativeApplicationsManager::~CApsNonNativeApplicationsManager()
+ {
+ delete iUpdateList;
+ }
+
+CApsNonNativeApplicationsManager::CApsNonNativeApplicationsManager(CApaAppArcServer& 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<const SNonNativeApplicationInfo*>(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<sizeof(TCheckedUid)> 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<CApsNonNativeApplicationsManager*>(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);
+ }
+
+ }