appfw/apparchitecture/apserv/apsnnapps.cpp
changeset 0 2e3d3ce01487
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Non-Native application registration functionality for the AppArc server session
       
    15 // 
       
    16 // apsnnapps.cpp
       
    17 //
       
    18 
       
    19 
       
    20 #include "apsnnapps.h"
       
    21 
       
    22 #include <bautils.h>
       
    23 #include <f32file.h>
       
    24 #include <s32file.h>
       
    25 
       
    26 #include "APSCLSV.H"
       
    27 #include "apsserv.h"
       
    28 #include "APSSTD.H"
       
    29 #include "../apgrfx/apprivate.h"
       
    30 #include "apsnnappupdates.h"
       
    31 
       
    32 /**
       
    33 KNonNativeApplicationsUpdateLog
       
    34 @internalComponent
       
    35 */
       
    36 _LIT(KNonNativeApplicationsUpdateLog, ":\\private\\10003a3f\\UpdatedAppsList.bin");
       
    37 
       
    38 /**************************************************************************************************************
       
    39  * CApsNonNativeApplicationsUpdateList
       
    40  **************************************************************************************************************/
       
    41 
       
    42 CApsNonNativeApplicationsUpdateList* CApsNonNativeApplicationsUpdateList::NewL(RFs& aFs)
       
    43 	{
       
    44 	CApsNonNativeApplicationsUpdateList* self = new(ELeave) CApsNonNativeApplicationsUpdateList(aFs);
       
    45 	return self;
       
    46 	}
       
    47 
       
    48 void CApsNonNativeApplicationsUpdateList::RecoverFromUpdateLogL(RFs& aFs, RFile& aFile)
       
    49 	{
       
    50 	CleanupClosePushL(aFile);
       
    51 	CApsNonNativeApplicationsUpdateList* self = new(ELeave) CApsNonNativeApplicationsUpdateList(aFs);
       
    52 	CleanupStack::PushL(self);
       
    53 	self->RecoverFromUpdateLogL(aFile); // consumes aFile
       
    54 	CleanupStack::PopAndDestroy(self);
       
    55 	CleanupStack::Pop(&aFile);
       
    56 	}
       
    57 
       
    58 
       
    59 CApsNonNativeApplicationsUpdateList::CApsNonNativeApplicationsUpdateList(RFs& aFs) :
       
    60 		iFs(aFs)
       
    61 	{
       
    62 	}
       
    63 
       
    64 CApsNonNativeApplicationsUpdateList::~CApsNonNativeApplicationsUpdateList()
       
    65 	{
       
    66 	CApsNonNativeApplicationsUpdate* update = iUpdateListHead;
       
    67 	while(update != NULL)
       
    68 		{
       
    69 		CApsNonNativeApplicationsUpdate* next = update->Next();
       
    70 		delete update;
       
    71 		update = next;
       
    72 		}
       
    73 	}
       
    74 
       
    75 void CApsNonNativeApplicationsUpdateList::RecoverFromUpdateLogL(RFile& aFile)
       
    76 	{
       
    77 	RFileReadStream readStream;
       
    78 	CleanupClosePushL(readStream);
       
    79 	RFile logFileDupe;
       
    80 	User::LeaveIfError(logFileDupe.Duplicate(aFile));
       
    81 	readStream.Attach(logFileDupe); // Attach takes ownership of & Nulls the handle passed to it
       
    82 	TInt pos = 0;
       
    83 	InternalizeL(readStream,pos);
       
    84 	CleanupStack::PopAndDestroy(&readStream);
       
    85 
       
    86 	/* Great, we've read in all our performed updates and deleted all the ones that were fully
       
    87 	   rolled back.
       
    88 	   The next step is to roll back the rest of the updates. We'll need to create an
       
    89 	   update log as it was before the reboot, so that further rollbacks we successfully perform
       
    90 	   can also be logged in it */
       
    91 	
       
    92 	// pos should point to the end of the last compelte action recorded in the file
       
    93 	// remove any invalid or half-written actions by truncating to pos
       
    94 	User::LeaveIfError(aFile.SetSize(pos));
       
    95 	RApsUpdateLog updateLog(iFs);
       
    96 	updateLog.Open(aFile,pos); // consumes aFile
       
    97 	CleanupClosePushL(updateLog);
       
    98 
       
    99 	if(iEEndOfUpdateRequiredToFixLog)
       
   100 		{
       
   101 		updateLog.LogWriteStream().WriteInt8L(CApsNonNativeApplicationsUpdate::EEndOfUpdate);
       
   102 		updateLog.LogWriteStream().CommitL(); // puts us back to an alpha stopping point
       
   103 		}
       
   104 
       
   105 	if(iLogReplayCurrentUpdate != NULL)
       
   106 		{
       
   107 		switch(iLogReplayCurrentUpdate->iState)
       
   108 			{
       
   109 		case CApsNonNativeApplicationsUpdate::ENew:
       
   110 			/* current update was never performed. Start rollback at the previous one,
       
   111 			   which will be in EPerformed */
       
   112 			iLogReplayCurrentUpdate = iLogReplayCurrentUpdate->Previous();
       
   113 			ASSERT(iLogReplayCurrentUpdate == NULL || iLogReplayCurrentUpdate->iState == CApsNonNativeApplicationsUpdate::EPerformed);
       
   114 			break;
       
   115 		case CApsNonNativeApplicationsUpdate::EPerforming:
       
   116 		case CApsNonNativeApplicationsUpdate::EPerformed:
       
   117 		case CApsNonNativeApplicationsUpdate::ERollingBack:
       
   118 			break;
       
   119 		case CApsNonNativeApplicationsUpdate::ERolledBack:
       
   120 			User::Leave(KErrCorrupt);
       
   121 			break;
       
   122 			}
       
   123 		Rollback(iLogReplayCurrentUpdate, updateLog);
       
   124 		}
       
   125 	CleanupStack::PopAndDestroy(&updateLog);
       
   126 	}
       
   127 
       
   128 void CApsNonNativeApplicationsUpdateList::InternalizeL(RReadStream& aStream, TInt& aPosition)
       
   129 	{
       
   130 	TInt err = KErrNone;
       
   131 	while(err == KErrNone)
       
   132 		{
       
   133 		TRAP(err,InternalizeActionL(aStream,aPosition));
       
   134 		if(err == KErrNone || err == KErrCorrupt || err == KErrEof)
       
   135 			{
       
   136 			// We anticipate that the last update we try to read may be not complete or corrupt.
       
   137 			// if we get either of these, jsut stop reading in the list of updates.
       
   138 			}
       
   139 		else
       
   140 			{
       
   141 			// something really unexpected, e.g. KErrNoMemory
       
   142 			User::Leave(err);
       
   143 			}
       
   144 		}
       
   145 	CApsNonNativeApplicationsUpdate* update = iUpdateListHead;
       
   146 	while(update) 
       
   147 		{
       
   148 		update->PostInternalizeL();
       
   149 		update = update->Next();
       
   150 		}
       
   151 	}
       
   152 
       
   153 void CApsNonNativeApplicationsUpdateList::InternalizeActionL(RReadStream& aStream, TInt& aPosition)
       
   154 	{
       
   155 	TInt pos = aPosition;
       
   156 
       
   157 	CApsNonNativeApplicationsUpdate::TLogActionType action =
       
   158 		static_cast<CApsNonNativeApplicationsUpdate::TLogActionType>(aStream.ReadInt8L());
       
   159 	CApsNonNativeApplicationsUpdate::TLogUpdateType type =
       
   160 		static_cast<CApsNonNativeApplicationsUpdate::TLogUpdateType>(aStream.ReadInt8L());
       
   161 	TUid appUid;
       
   162 	appUid.iUid = aStream.ReadInt32L();
       
   163 	pos += sizeof(TInt8) + sizeof(TInt8) + sizeof(TUint32);
       
   164 
       
   165 	switch(action)
       
   166 		{
       
   167 	case CApsNonNativeApplicationsUpdate::ENewUpdate:
       
   168 		// for ENewUpdate, this is not a valid stopping point,
       
   169 		// so we don't want to change aPosition unless it completes successfully.
       
   170 		InternalizeNewUpdateL(aStream, pos, type, appUid);
       
   171 		aPosition = pos;
       
   172 		break;
       
   173 	case CApsNonNativeApplicationsUpdate::EPerformUpdate:
       
   174 		// for EPerformUpdate, this is a beta stopping point, and
       
   175 		// InternalizePerformUpdateL will only ever update aPosition to
       
   176 		// another stopping point, so we can give it the real aPosition.
       
   177 		// Since it's a beta stopping point, we need to set iEEndofUpdateRequiredToFixLog
       
   178 		iEEndOfUpdateRequiredToFixLog = ETrue;
       
   179 		aPosition = pos;
       
   180 		InternalizePerformUpdateL(aStream, aPosition, type, appUid);
       
   181 		iEEndOfUpdateRequiredToFixLog = EFalse;
       
   182 		break;
       
   183 	case CApsNonNativeApplicationsUpdate::ERollbackUpdate:
       
   184 		// this action has the same behaviour as EPerformUpdate
       
   185 		iEEndOfUpdateRequiredToFixLog = ETrue;
       
   186 		aPosition = pos;
       
   187 		InternalizeRollbackUpdateL(aStream, aPosition, type, appUid);
       
   188 		iEEndOfUpdateRequiredToFixLog = EFalse;
       
   189 		break;
       
   190 	default:
       
   191 		User::Leave(KErrCorrupt);
       
   192 		break;
       
   193 		}
       
   194 	}
       
   195 
       
   196 void CApsNonNativeApplicationsUpdateList::InternalizeNewUpdateL(RReadStream& aStream, TInt& aPosition, CApsNonNativeApplicationsUpdate::TLogUpdateType aType, TUid aUid)
       
   197 	{
       
   198 	// check that this is the first update or the previous update was performed completely
       
   199 	if(iLogReplayCurrentUpdate !=  NULL && (iLogReplayCurrentUpdate->iState != CApsNonNativeApplicationsUpdate::EPerformed || iLogReplayCurrentUpdate->Next() != NULL))
       
   200 		{
       
   201 		User::Leave(KErrCorrupt);
       
   202 		}
       
   203 
       
   204 	/*
       
   205 	 create the update object, depending on type
       
   206 	 */
       
   207 	CApsNonNativeApplicationsUpdate* update = NULL;
       
   208 	switch(aType) 
       
   209 		{
       
   210 	case CApsNonNativeApplicationsUpdate::ERegisterApplication:
       
   211 		update = CApsRegisterNonNativeApplication::NewL(iFs, aUid, TDriveName(), CApsNonNativeApplicationsUpdate::ENeedsInternalizing);
       
   212 		break;
       
   213 	case CApsNonNativeApplicationsUpdate::EDeregisterApplication:
       
   214 		update = CApsDeregisterNonNativeApplication::NewL(iFs, *CApaAppArcServer::Self(), aUid, CApsNonNativeApplicationsUpdate::ENeedsInternalizing);
       
   215 		break;
       
   216 #ifdef _DEBUG
       
   217 	case CApsNonNativeApplicationsUpdate::EFail:
       
   218 		update = new(ELeave) CApsAlwaysFailUpdate(iFs, CApsNonNativeApplicationsUpdate::ENeedsInternalizing);
       
   219 		break;
       
   220 	case CApsNonNativeApplicationsUpdate::EPanic:
       
   221 		update = new(ELeave) CApsAlwaysPanicUpdate(iFs, CApsNonNativeApplicationsUpdate::ENeedsInternalizing);
       
   222 		break;
       
   223 	case CApsNonNativeApplicationsUpdate::ERollbackPanic:
       
   224 		update = new(ELeave) CApsAlwaysPanicOnRollbackUpdate(iFs, CApsNonNativeApplicationsUpdate::ENeedsInternalizing);
       
   225 		break;
       
   226 #endif
       
   227 	default:
       
   228 		User::Leave(KErrCorrupt);
       
   229 		break;
       
   230 		}
       
   231 	CleanupStack::PushL(update);
       
   232 	update->InternalizeNewUpdateL(aStream, aPosition);
       
   233 	CleanupStack::Pop(update);
       
   234 	/* alpha stopping point.
       
   235 	   update->iState should be ENew now.
       
   236 	 */
       
   237 	Append(update);
       
   238 	iLogReplayCurrentUpdate = update;
       
   239 	}
       
   240 
       
   241 void CApsNonNativeApplicationsUpdateList::InternalizePerformUpdateL(RReadStream& aStream, TInt& aPosition, CApsNonNativeApplicationsUpdate::TLogUpdateType aType, TUid aUid)
       
   242 	{
       
   243 	if(iLogReplayCurrentUpdate == NULL || iLogReplayCurrentUpdate->iState != CApsNonNativeApplicationsUpdate::ENew)
       
   244 		{
       
   245 		User::Leave(KErrCorrupt);
       
   246 		}
       
   247 	if(iLogReplayCurrentUpdate->Uid() != aUid || iLogReplayCurrentUpdate->iType != aType)
       
   248 		{
       
   249 		User::Leave(KErrCorrupt);
       
   250 		}
       
   251 	/*
       
   252 	 tell the update to read in its log
       
   253 	 */
       
   254 	iLogReplayCurrentUpdate->InternalizePerformUpdateL(aStream, aPosition);
       
   255 	// the function above will return iff EEndOfUpdate is reached
       
   256 	}
       
   257 
       
   258 
       
   259 void CApsNonNativeApplicationsUpdateList::InternalizeRollbackUpdateL(RReadStream& aStream, TInt& aPosition, CApsNonNativeApplicationsUpdate::TLogUpdateType aType, TUid aUid)
       
   260 	{
       
   261 	if(iLogReplayCurrentUpdate == NULL)
       
   262 		{
       
   263 		User::Leave(KErrCorrupt);
       
   264 		}
       
   265 	if( iLogReplayCurrentUpdate->iState != CApsNonNativeApplicationsUpdate::EPerforming
       
   266 	 && iLogReplayCurrentUpdate->iState != CApsNonNativeApplicationsUpdate::EPerformed
       
   267 	 && iLogReplayCurrentUpdate->iState != CApsNonNativeApplicationsUpdate::ERollingBack)
       
   268 		{
       
   269 		User::Leave(KErrCorrupt);
       
   270 		}
       
   271 	if(iLogReplayCurrentUpdate->iType != aType || iLogReplayCurrentUpdate->Uid() != aUid)
       
   272 		{
       
   273 		User::Leave(KErrCorrupt);
       
   274 		}
       
   275 	
       
   276 	iLogReplayCurrentUpdate->InternalizeRollbackUpdateL(aStream, aPosition);
       
   277 	// the function above will return iff EEndOfUpdate is reached
       
   278 
       
   279 	if(iLogReplayCurrentUpdate->iState == CApsNonNativeApplicationsUpdate::ERolledBack)
       
   280 		{
       
   281 		iLogReplayCurrentUpdate = iLogReplayCurrentUpdate->Previous();
       
   282 		}
       
   283 	}
       
   284 
       
   285 void CApsNonNativeApplicationsUpdateList::Append(CApsNonNativeApplicationsUpdate* aUpdate)
       
   286 	{
       
   287 	if(iUpdateListHead == NULL)
       
   288 		{
       
   289 		iUpdateListHead = aUpdate;
       
   290 		return;
       
   291 		}
       
   292 
       
   293 	CApsNonNativeApplicationsUpdate* update = iUpdateListHead;
       
   294 	while(update->iNext != NULL)
       
   295 		{
       
   296 		update = update->iNext;
       
   297 		}
       
   298 	update->iNext = aUpdate;
       
   299 	aUpdate->iPrevious = update;
       
   300 	}
       
   301 
       
   302 void CApsNonNativeApplicationsUpdateList::ExecuteL()
       
   303 	{
       
   304 	RApsUpdateLog updateLog(iFs);
       
   305 	updateLog.OpenL();
       
   306 	CleanupClosePushL(updateLog);
       
   307 	CApsNonNativeApplicationsUpdate* update = iUpdateListHead;
       
   308 	while(update != NULL)
       
   309 		{
       
   310 		TRAPD(err,update->PerformUpdateL(updateLog));
       
   311 		if(err == KErrNone)
       
   312 			{
       
   313 			update = update->Next();
       
   314 			}
       
   315 		else
       
   316 			{
       
   317 			// call rollback on everything, including the one that failed
       
   318 			// since it may have to clean up half-finished stuff
       
   319 			Rollback(update, updateLog);
       
   320 			User::Leave(err);
       
   321 			}
       
   322 		}
       
   323 	CleanupStack::PopAndDestroy(&updateLog);
       
   324 	}
       
   325 
       
   326 void CApsNonNativeApplicationsUpdateList::Rollback(CApsNonNativeApplicationsUpdate* aStartPoint, RApsUpdateLog& aUpdateLog)
       
   327 	{
       
   328 	CApsNonNativeApplicationsUpdate* update = aStartPoint;
       
   329 
       
   330 	while(update != NULL)
       
   331 		{
       
   332 		TRAP_IGNORE(update->RollbackUpdateL(aUpdateLog));
       
   333 		update = update->Previous();
       
   334 		}
       
   335 	}
       
   336 
       
   337 /**
       
   338 @internalComponent
       
   339 */
       
   340 RApsUpdateLog::RApsUpdateLog(RFs& aFs) :
       
   341 	iFs(aFs), iFilesRegistered(NULL), iDrivesAffected(NULL)
       
   342 	{
       
   343 	TChar drive = RFs::GetSystemDriveChar();
       
   344 	iLogFileName.Append(drive);
       
   345 	iLogFileName.Append(KNonNativeApplicationsUpdateLog);
       
   346 	}
       
   347 
       
   348 /**
       
   349 RApsUpdateLog::OpenL
       
   350 
       
   351 Opens a write stream to a log file that keeps track of what updates have been performed.
       
   352 
       
   353 @internalComponent
       
   354 */
       
   355 void RApsUpdateLog::OpenL()
       
   356 	{
       
   357 	ASSERT(!iFilesRegistered && !iDrivesAffected);
       
   358 	const TInt KArrayGranularity = 128;
       
   359 	iFilesRegistered = new (ELeave) CDesCArraySeg(KArrayGranularity);
       
   360 	iDrivesAffected = new (ELeave) CDesCArraySeg(KArrayGranularity);
       
   361 	User::LeaveIfError(iLogWriteStream.Replace(iFs,iLogFileName,EFileShareExclusive|EFileStream|EFileWrite));
       
   362 	}
       
   363 
       
   364 /**
       
   365 RApsUpdateLog::Open
       
   366 
       
   367 Opens a write stream to a log file that keeps track of what updates have been performed.
       
   368 
       
   369 @internalComponent
       
   370 */
       
   371 void RApsUpdateLog::Open(RFile& aFile, TUint aSeekPos)
       
   372 	{
       
   373 	iLogWriteStream.Attach(aFile, aSeekPos);
       
   374 	}
       
   375 
       
   376 /**
       
   377 RApsUpdateLog::Close
       
   378 
       
   379 Cleans up the list of new Registration files created during this set of updates
       
   380 and deletes the log files created.
       
   381 
       
   382 @internalComponent
       
   383 */
       
   384 void RApsUpdateLog::Close()
       
   385 	{
       
   386 	_LIT(KLitPathForTemporaryFiles, "\\private\\10003a3f\\temp\\");
       
   387 	const TInt count = (iDrivesAffected ? iDrivesAffected->Count() : 0);
       
   388 	CFileMan* fileman = NULL;
       
   389 	TRAPD(err, fileman = CFileMan::NewL(iFs));
       
   390 	if (err == KErrNone) 
       
   391 		{
       
   392 		for(TInt i = 0; i < count; ++i)
       
   393 			{
       
   394 			TFileName dir((*iDrivesAffected)[i]);
       
   395 			dir.Append(KLitPathForTemporaryNonNativeResourceAndIconFiles);
       
   396 			fileman->RmDir(dir); // recursive
       
   397 			iFs.RmDir(KLitPathForTemporaryFiles); // non-recursive
       
   398 			}
       
   399 		delete fileman;
       
   400 		}
       
   401 	
       
   402 	delete iFilesRegistered;
       
   403 	iFilesRegistered = NULL;
       
   404 	
       
   405 	delete iDrivesAffected;
       
   406 	iDrivesAffected = NULL;
       
   407 	
       
   408 	iLogWriteStream.Close();
       
   409 	iFs.Delete(iLogFileName);
       
   410 	}
       
   411 
       
   412 
       
   413 /**
       
   414 CApsNonNativeApplicationsUpdateList::RApsUpdateLog holds a list of registration files that have
       
   415 been written during this transaction. This list is used by the Deregistration
       
   416 command as the forced-updates list.
       
   417 
       
   418 This stops them from being incorrectly hidden from the scan performed to find
       
   419 the registration file to delete.
       
   420 
       
   421 @internalComponent
       
   422 */
       
   423 CDesCArray& RApsUpdateLog::NewRegistrationFiles()
       
   424 	{
       
   425 	return *iFilesRegistered;
       
   426 	}
       
   427 
       
   428 
       
   429 /**
       
   430 CApsNonNativeApplicationsUpdateList::RApsUpdateLog holds a list of drives that have been used
       
   431 in the transaction. This is then used to clean up the temporary file directories
       
   432 
       
   433 @internalComponent
       
   434 */
       
   435 CDesCArray& RApsUpdateLog::DrivesAffected()
       
   436 	{
       
   437 	return *iDrivesAffected;
       
   438 	}
       
   439 
       
   440 /**
       
   441 Returns the stream that updates should write their recovery log data to
       
   442 @internalComponent
       
   443 */
       
   444 RWriteStream& RApsUpdateLog::LogWriteStream()
       
   445 	{
       
   446 	return iLogWriteStream;
       
   447 	}
       
   448 
       
   449 /**************************************************************************************************************
       
   450  * CApsNonNativeApplicationsManager
       
   451  **************************************************************************************************************/
       
   452 
       
   453 void CApsNonNativeApplicationsManager::NotifyScanComplete()
       
   454 	{
       
   455 	//See if the session is intrested in scan complete notification.
       
   456 	if (!iNotifyOnScanCompleteMsg.IsNull())
       
   457 		{
       
   458 		iNotifyOnScanCompleteMsg.Complete(KErrNone);
       
   459 		}
       
   460 	} //lint !e1762 Suppress member function could be made const
       
   461 
       
   462 
       
   463 CApsNonNativeApplicationsManager* CApsNonNativeApplicationsManager::NewL(CApaAppArcServer& aServ, RFs& aFs)
       
   464 	{
       
   465 	CApsNonNativeApplicationsManager* self = new(ELeave)CApsNonNativeApplicationsManager(aServ, aFs);
       
   466 	return self;
       
   467 	}
       
   468 
       
   469 CApsNonNativeApplicationsManager::~CApsNonNativeApplicationsManager()
       
   470 	{
       
   471 	delete iUpdateList;
       
   472 	}
       
   473 
       
   474 CApsNonNativeApplicationsManager::CApsNonNativeApplicationsManager(CApaAppArcServer& aServ, RFs& aFs) :
       
   475 		iServ(aServ),
       
   476 		iFs(aFs)
       
   477 	{
       
   478 	}
       
   479 
       
   480 //
       
   481 
       
   482 void CApsNonNativeApplicationsManager::PrepareNonNativeApplicationsUpdatesL()
       
   483 	{
       
   484 	if (iServ.AppList().AppScanInProgress())
       
   485 		{
       
   486 		iServ.AppList().StopScan(ETrue); //Stop updating applist now, we anyways have to update it when we are commiting these changes
       
   487 		}
       
   488 	if (iNonNativeApplicationsUpdateAppsLock) 
       
   489 		{
       
   490 		User::Leave(KErrInUse);
       
   491 		}
       
   492 
       
   493 	ASSERT(iUpdateList == NULL);
       
   494 	
       
   495 	iUpdateList = CApsNonNativeApplicationsUpdateList::NewL(iFs);
       
   496 	iNonNativeApplicationsUpdateAppsLock = ETrue;
       
   497 	}
       
   498 
       
   499 
       
   500 void CApsNonNativeApplicationsManager::CheckForUpdateAppsLockL()
       
   501 	{
       
   502 	if (!iNonNativeApplicationsUpdateAppsLock)
       
   503 		{
       
   504 		// PrepareNonNativeApplicationsUpdatesL hasn't been called successfully
       
   505 		User::Leave(KErrNotReady);
       
   506 		}	
       
   507 	}
       
   508 
       
   509 
       
   510 //
       
   511  
       
   512  void CApsNonNativeApplicationsManager::RegisterNonNativeApplicationL(const RMessage2& aMessage)
       
   513 	{
       
   514 	CheckForUpdateAppsLockL();
       
   515 	CleanupStack::PushL(TCleanupItem(&StaticAbortNonNativeApplicationsUpdates,this));
       
   516 	DoRegisterNonNativeApplicationL(aMessage);
       
   517 	CleanupStack::Pop(this);
       
   518 	}
       
   519 
       
   520 
       
   521 void CApsNonNativeApplicationsManager::DoRegisterNonNativeApplicationL(const RMessage2& aMessage)
       
   522 	{
       
   523 	// an RBuf for creating the file names in.
       
   524 	// create it here so it's below ipcParameter0 on the cleanup stack
       
   525 	RBuf target;
       
   526 	CleanupClosePushL(target);
       
   527 
       
   528 	// read in the resource file from aMessage
       
   529 	RBuf8 ipcParameter0(HBufC8::NewL(aMessage.GetDesLengthL(0)));
       
   530 	CleanupClosePushL(ipcParameter0);
       
   531 	aMessage.ReadL(0, ipcParameter0);
       
   532 	if (ipcParameter0.Length()<=sizeof(SNonNativeApplicationInfo)+sizeof(TCheckedUid))
       
   533 		{
       
   534 		User::Leave(KErrArgument);
       
   535 		}
       
   536 
       
   537 	// get drivename
       
   538 	const SNonNativeApplicationInfo nonNativeApplicationInfo = *reinterpret_cast<const SNonNativeApplicationInfo*>(ipcParameter0.Ptr());
       
   539 	TDriveName driveName = TDriveUnit(nonNativeApplicationInfo.iDrive).Name();
       
   540 
       
   541 	// get uid
       
   542 	const TUid applicationUid(TCheckedUid(ipcParameter0.Mid(sizeof(SNonNativeApplicationInfo), sizeof(TCheckedUid))).UidType()[2]);
       
   543 	if (applicationUid==TUid::Null())
       
   544 		{
       
   545 		User::Leave(KErrArgument);
       
   546 		}
       
   547 
       
   548 	// construct resource file name
       
   549 	target.CreateL(driveName, KMaxFileName);
       
   550 	target.Append(KLitPathForNonNativeResourceAndIconFiles);
       
   551 	const TInt startOfFileName=target.Length(); // take note of this so we can chop off the file name later
       
   552 	target.AppendFormat(KLitFormatForRegistrationResourceFile, applicationUid.iUid);
       
   553 
       
   554 	// prepare registrationResourceFileDataPrefix
       
   555 	const TUidType uidPrefix(TUid::Uid(KUidPrefixedNonNativeRegistrationResourceFile), nonNativeApplicationInfo.iApplicationType, applicationUid);
       
   556 	const TBufC8<sizeof(TCheckedUid)> registrationResourceFileDataPrefix(TCheckedUid(uidPrefix).Des());
       
   557 
       
   558 	// create the object that will actually perform the update
       
   559 	CApsRegisterNonNativeApplication* updateObject = CApsRegisterNonNativeApplication::NewL(iFs, applicationUid, driveName);
       
   560 	CleanupStack::PushL(updateObject);
       
   561 
       
   562 	// write resource file to temp location
       
   563 	updateObject->SetResourceFileTargetLocation(target);
       
   564 	updateObject->WriteResourceFileL(ipcParameter0.Mid(sizeof(SNonNativeApplicationInfo)), &registrationResourceFileDataPrefix);
       
   565 	
       
   566 	if (aMessage.Int1()!=0) // if there is a localisable resource-file
       
   567 		{
       
   568 		RBuf8 ipcParameter1(HBufC8::NewL(User::LeaveIfError(aMessage.GetDesLength(1))));
       
   569 		CleanupClosePushL(ipcParameter1);
       
   570 		aMessage.ReadL(1, ipcParameter1);
       
   571 		
       
   572 		// construct localisable resoure file name
       
   573 		target.SetLength(startOfFileName);
       
   574 		target.AppendFormat(KLitFormatForLocalisableResourceFile, applicationUid.iUid);
       
   575 
       
   576 		updateObject->SetLocalisableResourceFileTargetLocation(target);
       
   577 		// write localisable resource file to temp location
       
   578 		updateObject->WriteLocalisableResourceFileL(ipcParameter1, NULL);
       
   579 		CleanupStack::PopAndDestroy(&ipcParameter1);
       
   580 
       
   581 		if (aMessage.Int2()!=0) // if there is an icon-file
       
   582 			{
       
   583 			RFile iconFile;
       
   584 			CleanupClosePushL(iconFile);
       
   585 			User::LeaveIfError(iconFile.AdoptFromClient(aMessage, 2, 3));
       
   586 			RBuf iconFileName;
       
   587 			CleanupClosePushL(iconFileName);
       
   588 			iconFileName.CreateL(KMaxFileName);
       
   589 			User::LeaveIfError(iconFile.Name(iconFileName));
       
   590 
       
   591 			if (startOfFileName+iconFileName.Length()>KMaxFileName)
       
   592 				{
       
   593 				User::Leave(KErrArgument);
       
   594 				}
       
   595 			target.SetLength(startOfFileName);
       
   596 			target.Append(iconFileName);
       
   597 			updateObject->SetIconFileTargetLocation(target);
       
   598 			updateObject->CopyIconFileL(iconFile);
       
   599 
       
   600 			CleanupStack::PopAndDestroy(2, &iconFile); // iconFileName, iconFile
       
   601 			}
       
   602 		}
       
   603 
       
   604 	CleanupStack::Pop(updateObject);
       
   605 	iUpdateList->Append(updateObject);
       
   606 
       
   607 	CleanupStack::PopAndDestroy(2, &target); // ipcParameter0, target
       
   608 	}
       
   609 
       
   610 
       
   611 //
       
   612  
       
   613 void CApsNonNativeApplicationsManager::DeregisterNonNativeApplicationL(const RMessage2& aMessage)
       
   614 	{
       
   615 	CheckForUpdateAppsLockL();
       
   616 	CleanupStack::PushL(TCleanupItem(&StaticAbortNonNativeApplicationsUpdates,this));
       
   617 	const TUid applicationUid(TUid::Uid(aMessage.Int0()));
       
   618 	iUpdateList->Append(CApsDeregisterNonNativeApplication::NewL(iFs, iServ, applicationUid));
       
   619 	CleanupStack::Pop(this);
       
   620 	}
       
   621 
       
   622 //
       
   623 
       
   624 #ifdef _DEBUG
       
   625 void CApsNonNativeApplicationsManager::ForceFailInNonNativeApplicationsUpdatesL()
       
   626 	{
       
   627 	CheckForUpdateAppsLockL();
       
   628 	CleanupStack::PushL(TCleanupItem(&StaticAbortNonNativeApplicationsUpdates,this));
       
   629 	iUpdateList->Append(new(ELeave) CApsAlwaysFailUpdate(iFs));
       
   630 	CleanupStack::Pop(this);
       
   631 	}
       
   632 
       
   633 void CApsNonNativeApplicationsManager::ForcePanicInNonNativeApplicationsUpdatesL()
       
   634 	{
       
   635 	CheckForUpdateAppsLockL();
       
   636 	CleanupStack::PushL(TCleanupItem(&StaticAbortNonNativeApplicationsUpdates,this));
       
   637 	iUpdateList->Append(new(ELeave) CApsAlwaysPanicUpdate(iFs));
       
   638 	CleanupStack::Pop(this);
       
   639 	}
       
   640 
       
   641 void CApsNonNativeApplicationsManager::ForcePanicInNonNativeApplicationsRollbackL()
       
   642 	{
       
   643 	CheckForUpdateAppsLockL();
       
   644 	CleanupStack::PushL(TCleanupItem(&StaticAbortNonNativeApplicationsUpdates,this));
       
   645 	iUpdateList->Append(new(ELeave) CApsAlwaysPanicOnRollbackUpdate(iFs));
       
   646 	CleanupStack::Pop(this);
       
   647 	}
       
   648 
       
   649 #endif // _DEBUG
       
   650 
       
   651 //
       
   652 
       
   653 void CApsNonNativeApplicationsManager::CommitNonNativeApplicationsUpdatesL(const RMessage2& aMessage)
       
   654 	{
       
   655 	CheckForUpdateAppsLockL();
       
   656 
       
   657 	TRAPD(err,iUpdateList->ExecuteL());
       
   658 
       
   659 	// Failure or success, we can't be hanging on to the lock after this function completes
       
   660 	delete iUpdateList;
       
   661 	iUpdateList = NULL;
       
   662 	iNonNativeApplicationsUpdateAppsLock = EFalse;
       
   663 	
       
   664 	if (KErrNone != err)
       
   665 		{
       
   666 		if(iServ.AppList().AppListUpdatePending())
       
   667 			{
       
   668 			// Trigger a rescan
       
   669 			iServ.UpdateApps();	
       
   670 			}
       
   671 		User::Leave(err); // bail out at this point if things didn't go to plan
       
   672 		}
       
   673 	
       
   674 	if(aMessage.Int0()==(TInt) ETrue)	
       
   675 		//The request is completed without waiting till completion application list preparation. 
       
   676 		aMessage.Complete(KErrNone); 
       
   677 	else	
       
   678 		//The request is not completed till completion application list preparation.		
       
   679 		iNotifyOnScanCompleteMsg=aMessage;
       
   680 
       
   681 	// Trigger a rescan
       
   682 	iServ.UpdateApps();
       
   683 	}
       
   684 
       
   685 /**
       
   686 This function has the word "Rollback" in it because it used to actually roll back the
       
   687 updates that had been preformed but whose effects were hidden from the public APIs until commit.
       
   688 
       
   689 The real updates no longer happen until commit-time, so there's no real rolling back to be done here.
       
   690 The real rolling back is done automatically by iUpdateList, during the commit call, if neccessary.
       
   691 */
       
   692 void CApsNonNativeApplicationsManager::RollbackNonNativeApplicationsUpdates()
       
   693 	{
       
   694 	AbortNonNativeApplicationsUpdates();
       
   695 	}
       
   696 
       
   697 void CApsNonNativeApplicationsManager::AbortNonNativeApplicationsUpdates()
       
   698 	{
       
   699 	if (!iNonNativeApplicationsUpdateAppsLock)
       
   700 		{
       
   701 		// It is always ok to call this function but if we haven't called PrepareNonNativeApplicationsUpdatesL()
       
   702 		// there isn't anything to do
       
   703 		return;
       
   704 		}
       
   705 	if(iServ.AppList().AppListUpdatePending())
       
   706 		{
       
   707 		// Trigger a rescan
       
   708 		iServ.UpdateApps();	
       
   709 		}
       
   710 	delete iUpdateList;
       
   711 	iUpdateList = NULL;
       
   712 	iNonNativeApplicationsUpdateAppsLock = EFalse;
       
   713 	}
       
   714 
       
   715 void CApsNonNativeApplicationsManager::StaticAbortNonNativeApplicationsUpdates(TAny* aSelf)
       
   716 	{
       
   717 	static_cast<CApsNonNativeApplicationsManager*>(aSelf)->AbortNonNativeApplicationsUpdates();
       
   718 	}
       
   719 
       
   720 void CApsNonNativeApplicationsManager::RecoverFromUpdateLogL(RFs& aFs)
       
   721 	{
       
   722 	TChar drive = RFs::GetSystemDriveChar();
       
   723 	TFileName logPath;
       
   724 	logPath.Append(drive);
       
   725 	logPath.Append(KNonNativeApplicationsUpdateLog);
       
   726 	RFile logFile;
       
   727 	TInt err = logFile.Open(aFs,logPath,EFileShareExclusive|EFileStream|EFileWrite);
       
   728 	if(err == KErrNotFound || err == KErrPathNotFound)
       
   729 		{
       
   730 		// no log file, nothing to do.
       
   731 		return;
       
   732 		}
       
   733 	User::LeaveIfError(err);
       
   734 	// this function takes over ownership of logFile
       
   735 	TRAP(err,CApsNonNativeApplicationsUpdateList::RecoverFromUpdateLogL(aFs, logFile));
       
   736 	if(err != KErrNone)
       
   737 		{
       
   738 		// there's nothing we can do, just delete it and move on
       
   739 		aFs.Delete(logPath);
       
   740 		}
       
   741 	
       
   742 	}