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