smartinstaller/adm/src/ADMStateMachine.cpp
branchADM
changeset 48 364021cecc90
equal deleted inserted replaced
47:3f419852be07 48:364021cecc90
       
     1 /*
       
     2 * Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *     State machine implementation
       
    16 *
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 #include <ADM.rsg>
       
    22 #include "ADMApplication.h" // KUidADMApp
       
    23 #include "ADMStateMachine.h"
       
    24 #include "ADMStateMachineDebug.h"
       
    25 #include "globals.h"
       
    26 #include "config.h"
       
    27 
       
    28 #include <e32std.h>
       
    29 #include <sysutil.h>        // SysUtil::DiskSpaceBelowCriticalLevel()
       
    30 #include <BAUTILS.H>
       
    31 #include <apgcli.h>
       
    32 
       
    33 // Use Char 0xFF to indicate no drive is selected
       
    34 const TChar KNoDriveSelected = 0xFF;
       
    35 
       
    36 // Used to force the progress bar to finish
       
    37 const TInt KProgressBarFullValue = 100;
       
    38 
       
    39 TInt CompareVersions(TVersion& version1, TVersion& version2);
       
    40 
       
    41 // ---------------------------------------------------------------------------
       
    42 // Panic
       
    43 //
       
    44 // Raises a panic with specific panic code.
       
    45 // ---------------------------------------------------------------------------
       
    46 //
       
    47 LOCAL_C inline void Panic(TInt aPanicCode)
       
    48 	{
       
    49 	_LIT(KPanic, "SmartInst-SM");
       
    50 	User::Panic( KPanic, aPanicCode );
       
    51 	}
       
    52 
       
    53 LOCAL_C inline void Panic(TInt aPanicCode, TInt aState)
       
    54 	{
       
    55 	_LIT(KPanic, "SmartInst-SM");
       
    56 	const TInt reason = aState*100 + aPanicCode;
       
    57 	User::Panic( KPanic, reason );
       
    58 	}
       
    59 
       
    60 // -----------------------------------------------------------------------------
       
    61 // Default constructor
       
    62 // -----------------------------------------------------------------------------
       
    63 //
       
    64 CStateMachine::CStateMachine(CADMAppUi& aAppUi) :
       
    65 	CActive(EPriorityNormal),
       
    66 	iAppUi(aAppUi),
       
    67 	iFailedState( CStateFactory::EStateLast )
       
    68 	{
       
    69 	CActiveScheduler::Add(this);
       
    70 	}
       
    71 
       
    72 // -----------------------------------------------------------------------------
       
    73 // NewL()
       
    74 // -----------------------------------------------------------------------------
       
    75 //
       
    76 CStateMachine* CStateMachine::NewL(CADMAppUi& aAppUi, const TDesC& aDownloadPath)
       
    77 	{
       
    78 	CStateMachine* self = new (ELeave) CStateMachine(aAppUi);
       
    79 	CleanupStack::PushL(self);
       
    80 	self->ConstructL(aDownloadPath);
       
    81 	CleanupStack::Pop();
       
    82 	return self;
       
    83 	}
       
    84 
       
    85 // -----------------------------------------------------------------------------
       
    86 // ConstructL()
       
    87 // -----------------------------------------------------------------------------
       
    88 //
       
    89 void CStateMachine::ConstructL(const TDesC& aDownloadPath)
       
    90 	{
       
    91 	// Create a local semaphore for handling the download deleting
       
    92 	// This must be the first to be created and last to be destroyed.
       
    93 	iDlDeletingSemaphore.CreateLocal(0);
       
    94 
       
    95 	iXmlParser = CXmlParser::NewL();
       
    96 	iSisParser = CSisParser::NewL();
       
    97 
       
    98 #ifdef USE_LOGFILE
       
    99 	iInstallManager = CInstallManager::NewL(this, iAppUi.iLog);
       
   100 	iDepTree = CDepTree::NewL(iAppUi.iLog, aDownloadPath);
       
   101 	iDownloadHandler = CDownloadHandler::NewL(this, iAppUi.iLog, !(iAppUi.EikonEnv()->StartedAsServerApp()));
       
   102 #else
       
   103 	iInstallManager = CInstallManager::NewL(this);
       
   104 	iDepTree = CDepTree::NewL(aDownloadPath);
       
   105 	iDownloadHandler = CDownloadHandler::NewL(this, !(iAppUi.EikonEnv()->StartedAsServerApp()));
       
   106 #endif
       
   107 
       
   108 	iStateFactory = CStateFactory::NewL(*this);
       
   109 	}
       
   110 
       
   111 // -----------------------------------------------------------------------------
       
   112 // Destructor
       
   113 // -----------------------------------------------------------------------------
       
   114 //
       
   115 CStateMachine::~CStateMachine()
       
   116 	{
       
   117 	if (IsActive())
       
   118 		{
       
   119 		Cancel();
       
   120 		}
       
   121 	delete iStateFactory;
       
   122 	delete iDownloadHandler;
       
   123 	delete iInstallManager;
       
   124 	delete iDepTree;
       
   125 	delete iSisParser;
       
   126 	delete iXmlParser;
       
   127 	delete iDownloadedFile;
       
   128 
       
   129 	iDlDeletingSemaphore.Close();
       
   130 	}
       
   131 
       
   132 // -----------------------------------------------------------------------------
       
   133 // Updates the displayed progress bar
       
   134 // -----------------------------------------------------------------------------
       
   135 //
       
   136 void CStateMachine::UpdateProgressBar(TInt aStartValue, TInt aEndValue)
       
   137 	{
       
   138 	iAppUi.iProgress->Update(aStartValue, aEndValue);
       
   139 	}
       
   140 
       
   141 // -----------------------------------------------------------------------------
       
   142 // Removes the displayed progress bar
       
   143 // -----------------------------------------------------------------------------
       
   144 //
       
   145 void CStateMachine::StopProgressBar() const
       
   146 	{
       
   147 	iAppUi.iProgress->Cancel();
       
   148 	}
       
   149 
       
   150 // -----------------------------------------------------------------------------
       
   151 // Sets the failure state and reason for exit
       
   152 // -----------------------------------------------------------------------------
       
   153 //
       
   154 void CStateMachine::SetFailureReason(TExitReason aReason)
       
   155 	{
       
   156 	iAppUi.iExitReason = aReason;
       
   157 	iFailedState = (CStateFactory::TAppState)StateIndex();
       
   158 	// If the device is not supported, don't create resume info
       
   159 	if (aReason == EDeviceNotSupported)
       
   160 		{
       
   161 		iAppUi.iIsResumeRequired = EFalse;
       
   162 		}
       
   163 	}
       
   164 
       
   165 // -----------------------------------------------------------------------------
       
   166 // Shows the download query dialog with a specified text.
       
   167 // @param aResourceId Resource ID for the text to be shown.
       
   168 // @param aInfoResourceId Resource ID for additional information text.
       
   169 // -----------------------------------------------------------------------------
       
   170 //
       
   171 void CStateMachine::ShowDownloadQueryL(const TInt aResourceId, const TInt aInfoResourceId)
       
   172 	{
       
   173 	iAppUi.ShowDownloadQueryL( aResourceId, aInfoResourceId );
       
   174 	}
       
   175 
       
   176 // -----------------------------------------------------------------------------
       
   177 // Shows wait note
       
   178 // -----------------------------------------------------------------------------
       
   179 //
       
   180 void CStateMachine::ShowWaitNoteL(const TInt aResourceId)
       
   181 	{
       
   182 	iAppUi.ShowWaitNoteL( aResourceId, ETrue );
       
   183 	}
       
   184 
       
   185 // -----------------------------------------------------------------------------
       
   186 // Shows wait note with the specified values
       
   187 // -----------------------------------------------------------------------------
       
   188 //
       
   189 void CStateMachine::ShowInstallingWaitNoteL(const TInt aCurrent, const TInt aLast)
       
   190 	{
       
   191 	iAppUi.ShowWaitNoteNumL( R_ADM_INSTALLING_TEXT, aCurrent, aLast );
       
   192 	}
       
   193 
       
   194 // -----------------------------------------------------------------------------
       
   195 // Shows the progress bar with the specified values
       
   196 // -----------------------------------------------------------------------------
       
   197 //
       
   198 void CStateMachine::ShowProgressBarL(const TInt aStartValue, const TInt aEndValue, const TInt aCurrent, const TInt aLast)
       
   199 	{
       
   200 	iAppUi.ShowGlobalProgressL( R_ADM_DOWNLOADING_TEXT,
       
   201 			aStartValue, aEndValue,
       
   202 			aCurrent, aLast );
       
   203 	}
       
   204 
       
   205 // -----------------------------------------------------------------------------
       
   206 // Stops the wait note
       
   207 // -----------------------------------------------------------------------------
       
   208 //
       
   209 void CStateMachine::StopWaitNote()
       
   210 	{
       
   211 	iAppUi.CancelWaitNote();
       
   212 	}
       
   213 
       
   214 // -----------------------------------------------------------------------------
       
   215 // Starts the state machine from the initial state.
       
   216 // -----------------------------------------------------------------------------
       
   217 //
       
   218 void CStateMachine::Start()
       
   219 	{
       
   220 	LOG( "+ CStateMachine::Start()" );
       
   221 
       
   222 	// If the initial state has been set, don't change it here
       
   223 	if (!iState)
       
   224 		{
       
   225 		iState = &iStateFactory->GetState( CStateFactory::EStateSetup );
       
   226 		}
       
   227 
       
   228 	iStatus = KRequestPending;
       
   229 	SetActive();
       
   230 	// send signal that this request has completed
       
   231 	TRequestStatus* status = &iStatus;
       
   232 	User::RequestComplete(status, KErrNone);
       
   233 	}
       
   234 
       
   235 // -----------------------------------------------------------------------------
       
   236 // Stops the state machine
       
   237 // -----------------------------------------------------------------------------
       
   238 //
       
   239 void CStateMachine::Stop()
       
   240 	{
       
   241 	LOG( "+ CStateMachine::Stop()" );
       
   242 	Cancel();
       
   243 	iDepTree->RemoveDownloadedFiles( FsSession() );
       
   244 	// Log statistics. Prevent divide-by-zero.
       
   245 	if (iDownloadTime == 0)
       
   246 		iDownloadTime = 1;
       
   247 	LOG4( "Total %d kB in %.1f s, avg %.2f kB/s",
       
   248 			iCumulativeDownloaded/1024,
       
   249 			iDownloadTime/1000000.0,
       
   250 			iCumulativeDownloaded*1000000.0 / iDownloadTime / 1024.0);
       
   251 	}
       
   252 
       
   253 // -----------------------------------------------------------------------------
       
   254 // Returns current state ID
       
   255 // -----------------------------------------------------------------------------
       
   256 //
       
   257 TInt CStateMachine::StateIndex() const
       
   258 	{
       
   259 	return iStateFactory->StateIndex(iState);
       
   260 	}
       
   261 
       
   262 // -----------------------------------------------------------------------------
       
   263 // Request the next state we want the application to go to
       
   264 // -----------------------------------------------------------------------------
       
   265 //
       
   266 void CStateMachine::SetState(const CStateFactory::TAppState aState)
       
   267 	{
       
   268 	SetState( iStateFactory->GetState(aState) );
       
   269 	}
       
   270 
       
   271 // -----------------------------------------------------------------------------
       
   272 // Set the starting state of the state machine, but do not invoke state change
       
   273 // -----------------------------------------------------------------------------
       
   274 //
       
   275 void CStateMachine::SetStartState(const CStateFactory::TAppState aState)
       
   276 	{
       
   277 	iState = &iStateFactory->GetState( aState );
       
   278 	}
       
   279 
       
   280 // -----------------------------------------------------------------------------
       
   281 // Request the next state we want the application to go to
       
   282 // -----------------------------------------------------------------------------
       
   283 //
       
   284 void CStateMachine::SetState(TState& aState)
       
   285 	{
       
   286 	LOG3( "+ SetState(): %d -> %d", iStateFactory->StateIndex(iState), iStateFactory->StateIndex(&aState) );
       
   287 
       
   288 	iState->Exit();
       
   289 	iState = &aState;
       
   290 	SetActive();
       
   291 	// send signal that this request has completed
       
   292 	TRequestStatus* status = &iStatus;
       
   293 	User::RequestComplete(status, KErrNone);
       
   294 
       
   295 	//LOG2( "- SetState(): now in %d", iStateFactory->StateIndex(iState) );
       
   296 	}
       
   297 
       
   298 // -----------------------------------------------------------------------------
       
   299 // Active object heart
       
   300 // -----------------------------------------------------------------------------
       
   301 //
       
   302 void CStateMachine::RunL()
       
   303 	{
       
   304 	//LOG2( "+ CStateEngine::RunL(): state=%d", iStateFactory->StateIndex(iState) );
       
   305 	iState->Enter();
       
   306 	//LOG2( "- CStateEngine::RunL(): %d", iStateFactory->StateIndex(iState) );
       
   307 	}
       
   308 
       
   309 // -----------------------------------------------------------------------------
       
   310 // Handles the leaves from RunL().
       
   311 //
       
   312 // SPECIFIC CASES NOT DONE YET:
       
   313 // -
       
   314 // -----------------------------------------------------------------------------
       
   315 //
       
   316 TInt CStateMachine::RunError(const TInt aError)
       
   317 	{
       
   318 	LOG3("+ SM::RunError(): %d, %d", StateIndex(), aError );
       
   319 
       
   320 	TExitReason err = EInstallationFailed;
       
   321 
       
   322 	switch ( aError )
       
   323 		{
       
   324 		case KLeaveExit:
       
   325 			{
       
   326 			// TODO: Ugly hack: we need to return KLeaveExit as RunError()
       
   327 			// gets called when application exit is called within RunL().
       
   328 			//LOG( "Exit() left" );
       
   329 			return KLeaveExit;
       
   330 			}
       
   331 		case SwiUI::KSWInstErrUserCancel:
       
   332 			{
       
   333 			LOG( "User cancelled installation" );
       
   334 			// User cancelled the installation
       
   335 			err = EUserCancelled;
       
   336 			}
       
   337 			break;
       
   338 		case SwiUI::KSWInstErrInsufficientMemory:
       
   339 			{
       
   340 			LOG( "Installer left: not enough space" );
       
   341 			err = EInsufficientMemory;
       
   342 			}
       
   343 			break;
       
   344 		case SwiUI::KSWInstErrMissingDependency:
       
   345 			{
       
   346 			LOG( "Installer left: missing dependency." );
       
   347 			//err = EInstallationFailed;
       
   348 			}
       
   349 			break;
       
   350 		case SwiUI::KSWInstErrFileCorrupted:
       
   351 		case SwiUI::KSWInstErrPackageNotSupported:
       
   352 		case SwiUI::KSWInstErrGeneralError:
       
   353 		case SwiUI::KSWInstErrNoRights:
       
   354 		case SwiUI::KSWInstErrNetworkFailure:
       
   355 		case SwiUI::KSWInstErrAccessDenied:
       
   356 		case SwiUI::KSWInstUpgradeError:
       
   357 			{
       
   358 			LOG2( "Installer left, err=%d", aError );
       
   359 			//err = EInstallationFailed;
       
   360 			}
       
   361 			break;
       
   362 		case KErrServerTerminated:
       
   363 			{
       
   364 			LOG( "Server process terminated, cannot continue." );
       
   365 			}
       
   366 			break;
       
   367 		case EUnsupportedDevice:
       
   368 			{
       
   369 			LOG( "MachineId not present in supported devices list" );
       
   370 			err = EDeviceNotSupported;
       
   371 			}
       
   372 			break;
       
   373 		case KErrAlreadyExists:
       
   374 			{
       
   375 			// Download already exists
       
   376 			LOG( "Existing download" );
       
   377 			err = EDownloadFailed;
       
   378 			}
       
   379 			break;
       
   380 		default:
       
   381 			{
       
   382 			LOG2( "Uncategorized leave %d, exiting", aError );
       
   383 			}
       
   384 			break;
       
   385 		}
       
   386 
       
   387 	LOG2( "Exiting due to failure %d", err );
       
   388 	SetFailureReason( err );
       
   389 	SetState( CStateFactory::EStatePrepareExitWithError );
       
   390 
       
   391 	return KErrNone;
       
   392 	}
       
   393 
       
   394 // -----------------------------------------------------------------------------
       
   395 //
       
   396 // -----------------------------------------------------------------------------
       
   397 //
       
   398 void CStateMachine::DoCancel()
       
   399 	{
       
   400 	LOG( "CStateMachine::DoCancel()" );
       
   401 	iDownloadHandler->CancelAllDownloads();
       
   402 	iInstallManager->CancelAll();
       
   403 	}
       
   404 
       
   405 // -----------------------------------------------------------------------------
       
   406 // Sets the internet access point identifier for download handler
       
   407 // -----------------------------------------------------------------------------
       
   408 //
       
   409 void CStateMachine::SetIAP(TUint32 aIAP)
       
   410 	{
       
   411 	iDownloadHandler->SetIAP(aIAP);
       
   412 	}
       
   413 
       
   414 // -----------------------------------------------------------------------------
       
   415 // Handles the UI event from AppUi, filters it and passes it to states.
       
   416 // -----------------------------------------------------------------------------
       
   417 //
       
   418 void CStateMachine::HandleUserResponse(TInt aStatus)
       
   419 	{
       
   420 	switch (aStatus)
       
   421 		{
       
   422 		case EAknSoftkeyYes:
       
   423 			iState->UserAccepted();
       
   424 			break;
       
   425 		case EAknSoftkeyNo:
       
   426 			iState->UserRejected();
       
   427 			break;
       
   428 		case EAknSoftkeyCancel:
       
   429 		case EKeyPhoneEnd:
       
   430 			// fall-through
       
   431 		default:
       
   432 			iState->UserCancelled();
       
   433 			break;
       
   434 		}
       
   435 	}
       
   436 
       
   437 // -----------------------------------------------------------------------------
       
   438 //
       
   439 // -----------------------------------------------------------------------------
       
   440 //
       
   441 void CStateMachine::HandleInstallCompletedL(TInt aStatus)
       
   442 	{
       
   443 	LOG4( "HandleInstallCompletedL(%d): %d. '%S'", aStatus, StateIndex(), iCurrentPackage->GetSisPackageName() );
       
   444 	// TODO: Can iCurrentPackage ever be null? In case of root package installation??
       
   445 
       
   446 	iState->InstallCompleted( aStatus );
       
   447 	}
       
   448 
       
   449 // -----------------------------------------------------------------------------
       
   450 // Called, if IAP has changed
       
   451 // -----------------------------------------------------------------------------
       
   452 //
       
   453 void CStateMachine::HandleIapChanged(const TUint32 aIAP)
       
   454 	{
       
   455 	iAppUi.iIAP = aIAP;
       
   456 	SetIAP(aIAP);
       
   457 	}
       
   458 
       
   459 // -----------------------------------------------------------------------------
       
   460 // Called when download has finished.
       
   461 // -----------------------------------------------------------------------------
       
   462 //
       
   463 void CStateMachine::HandleHttpFetchCompleted(
       
   464 		const TDesC& aDlFilename,
       
   465 		const TInt /* aDownloadType */,
       
   466 		const TInt32 aBytesDownloaded,
       
   467 		const TReal32 aAvgDlSpeed, // bytes/second
       
   468 		const TInt64 aDlTime       // microseconds
       
   469 		)
       
   470 	{
       
   471 	delete iDownloadedFile;
       
   472 	iDownloadedFile = NULL;
       
   473 	iDownloadedFile = aDlFilename.Alloc();
       
   474 	iDownloadSize = aBytesDownloaded;
       
   475 	// Indicate that we've downloaded this amount already to keep progress bar happy
       
   476 	iCumulativeDownloaded += aBytesDownloaded;
       
   477 	// Calculate cumulative average download speed
       
   478 	iDownloadTime += aDlTime;
       
   479 
       
   480 #ifdef DEBUG_ADM
       
   481 	TReal32 avgDlSpeed = iCumulativeDownloaded*1000000.0 / iDownloadTime;
       
   482 
       
   483 #ifdef _DEBUG
       
   484 	TBuf<32> buf;
       
   485 	TReal r = avgDlSpeed;
       
   486 	TRealFormat fmt(3, 2);
       
   487 	fmt.iType = KRealFormatFixed; // | KDoNotUseTriads;
       
   488 	buf.AppendNum(r/1024.0, fmt);
       
   489 	buf.Append(' ');
       
   490 	buf.Append(iAppUi.iPrefixKb);
       
   491 	buf.Append('/');
       
   492 	buf.Append('s');
       
   493 	iAppUi.EikonEnv()->InfoMsg(buf);
       
   494 #endif
       
   495 
       
   496 	LOG8( "DL %7d/%7d (%.1f s, %3.02f kB/s) (total: %d kB, %.1f s, avg %.02f kB/s) OK",
       
   497 			aBytesDownloaded, aBytesDownloaded, aDlTime/1000000.0, aAvgDlSpeed/1024.0,
       
   498 			iCumulativeDownloaded/1024, iDownloadTime/1000000.0, avgDlSpeed/1024.0 );
       
   499 #endif
       
   500 	iState->DownloadCompleted(aBytesDownloaded);
       
   501 	}
       
   502 
       
   503 // -----------------------------------------------------------------------------
       
   504 // Called when download manager has retrieved a packet from the network.
       
   505 // Required for updating the progress bar.
       
   506 // -----------------------------------------------------------------------------
       
   507 //
       
   508 void CStateMachine::HandleHttpFetchInProgress(const TInt32 aAlreadyDownloaded, const TInt32 aDownloadSize, const TReal32 aAvgDlSpeed)
       
   509 	{
       
   510 	iState->DownloadInProgress(aAlreadyDownloaded, aDownloadSize, aAvgDlSpeed);
       
   511 	}
       
   512 
       
   513 // -----------------------------------------------------------------------------
       
   514 // Called when download manager encounters a problem while downloading
       
   515 // -----------------------------------------------------------------------------
       
   516 //
       
   517 void CStateMachine::HandleHttpFetchFailure(
       
   518 		const TDesC& aDlFilename,
       
   519 		const TInt aGlobalErrorId,
       
   520 		const TInt aErrorId,
       
   521 		const TInt aFetchType
       
   522 		)
       
   523 	{
       
   524 	if (aFetchType)
       
   525 		{
       
   526 		LOG5( "+ HandleHttpFetchFailure(): %d. %d, %d '%S'", StateIndex(), aGlobalErrorId, aErrorId, &aDlFilename );
       
   527 		}
       
   528 	delete iDownloadedFile;
       
   529 	iDownloadedFile = NULL;
       
   530 	iDownloadedFile = aDlFilename.Alloc();
       
   531 	// TODO: Filter the errors here and invoke proper callbacks in states
       
   532 	iState->DownloadFailed();
       
   533 	LOG( "- HandleHttpFetchFailure()" );
       
   534 	}
       
   535 
       
   536 // -----------------------------------------------------------------------------
       
   537 // Signals the semaphore that download deleting is in progress (and the installation
       
   538 // can safely continue).
       
   539 // -----------------------------------------------------------------------------
       
   540 //
       
   541 void CStateMachine::HandleDownloadDeleting()
       
   542 	{
       
   543 	iDlDeletingSemaphore.Signal();
       
   544 	}
       
   545 
       
   546 // =============================================================================
       
   547 
       
   548 // -----------------------------------------------------------------------------
       
   549 //
       
   550 // -----------------------------------------------------------------------------
       
   551 //
       
   552 TState& CStateFactory::GetState(const TAppState aState) const
       
   553 	{
       
   554 	__ASSERT_DEBUG( aState < EStateLast, Panic(EPanicStateIndexOutOfBounds) );
       
   555 	return *iStates[aState];
       
   556 	}
       
   557 
       
   558 // -----------------------------------------------------------------------------
       
   559 //
       
   560 // -----------------------------------------------------------------------------
       
   561 //
       
   562 TInt CStateFactory::StateIndex(const TState* aState) const
       
   563 	{
       
   564 	TInt state;
       
   565 	for (state = 0; state < EStateLast; state++)
       
   566 		{
       
   567 		if (iStates[state] == aState)
       
   568 			{
       
   569 			return state;
       
   570 			}
       
   571 		}
       
   572 	// We end up here, if the state is not set, which may happen, if this
       
   573 	// is called before CStateMachine::Start() or CStateMachine::SetState().
       
   574 	return KUnknownState;
       
   575 	}
       
   576 
       
   577 // -----------------------------------------------------------------------------
       
   578 // Creates a new CStateFactory.
       
   579 // @return Newly created CStateFactory.
       
   580 // -----------------------------------------------------------------------------
       
   581 //
       
   582 CStateFactory* CStateFactory::NewL(CStateMachine& aStateMachine)
       
   583 	{
       
   584 	CStateFactory* self = new (ELeave) CStateFactory(aStateMachine);
       
   585 	CleanupStack::PushL(self);
       
   586 
       
   587 	// Create the states
       
   588 	self->iStates[EStateSetup]                      = new (ELeave) TStateSetup(*self);
       
   589 	self->iStates[EStateSetupParsing]               = new (ELeave) TStateSetupParsing(*self);
       
   590 	self->iStates[EStateBuildDepTree]               = new (ELeave) TStateBuildDepTree(*self);
       
   591 	self->iStates[EStateDownloadDepFile]            = new (ELeave) TStateDownloadDepFile(*self);
       
   592 	self->iStates[EStateParseDepFile]               = new (ELeave) TStateParseDepFile(*self);
       
   593 	self->iStates[EStateDownloadChangesFile]        = new (ELeave) TStateDownloadChangesFile(*self);
       
   594 	self->iStates[EStateParseChangesFile]           = new (ELeave) TStateParseChangesFile(*self);
       
   595 	self->iStates[EStateBuildFetchList]             = new (ELeave) TStateBuildFetchList(*self);
       
   596 	self->iStates[EStateVerifyAvailableDiskSpace]   = new (ELeave) TStateVerifyAvailableDiskSpace(*self);
       
   597 	self->iStates[EStateConfirmDownload]            = new (ELeave) TStateConfirmDownload(*self);
       
   598 	self->iStates[EStateConfirmRoamingDownload]     = new (ELeave) TStateConfirmRoamingDownload(*self);
       
   599 	self->iStates[EStateStartDependencyDownload]    = new (ELeave) TStateStartDependencyDownload(*self);
       
   600 	self->iStates[EStateDownloadDependency]         = new (ELeave) TStateDownloadDependency(*self);
       
   601 	self->iStates[EStateInstallDependency]          = new (ELeave) TStateInstallDependency(*self);
       
   602 	self->iStates[EStateInstallAppSis]              = new (ELeave) TStateInstallAppSis(*self);
       
   603 	self->iStates[EStateUninstallDependency]        = new (ELeave) TStateUninstallDependency(*self);
       
   604 	self->iStates[EStatePrepareExitWithError]       = new (ELeave) TStatePrepareExitWithError(*self);
       
   605 	self->iStates[EStateLaunchApp]                  = new (ELeave) TStateLaunchApp(*self);
       
   606 	self->iStates[EStateExit]                       = new (ELeave) TStateExit(*self);
       
   607 
       
   608 	CleanupStack::Pop();
       
   609 
       
   610 	return self;
       
   611 	}
       
   612 
       
   613 // -----------------------------------------------------------------------------
       
   614 // Default constructor
       
   615 // -----------------------------------------------------------------------------
       
   616 //
       
   617 CStateFactory::CStateFactory(CStateMachine& aStateMachine) :
       
   618 	iStateMachine(aStateMachine)
       
   619 	{
       
   620 	}
       
   621 
       
   622 // -----------------------------------------------------------------------------
       
   623 // Default destructor
       
   624 // -----------------------------------------------------------------------------
       
   625 //
       
   626 CStateFactory::~CStateFactory()
       
   627 	{
       
   628 	// Deletes all state objects
       
   629 	iStates.DeleteAll();
       
   630 	}
       
   631 
       
   632 // =============================================================================
       
   633 
       
   634 TState::TState(const CStateFactory& aFactory) :
       
   635 	iFactory(aFactory),
       
   636 	iStateMachine(aFactory.StateMachine())
       
   637 	{
       
   638 	}
       
   639 
       
   640 void TState::PanicInState(TStatePanic aPanic) const
       
   641 	{
       
   642 	Panic(aPanic, iFactory.StateIndex(this));
       
   643 	}
       
   644 
       
   645 // Change of states
       
   646 void TState::Enter() const
       
   647 	{
       
   648 	}
       
   649 
       
   650 void TState::Exit() const
       
   651 	{
       
   652 	}
       
   653 
       
   654 // Events from UI
       
   655 void TState::UserAccepted()
       
   656 	{
       
   657 	LOG_FUNC
       
   658 	}
       
   659 
       
   660 // -----------------------------------------------------------------------------
       
   661 // Implements the default user cancel behaviour. If needed, overwrite in the
       
   662 // state implementation.
       
   663 // -----------------------------------------------------------------------------
       
   664 //
       
   665 void TState::UserCancelled()
       
   666 	{
       
   667 	LOG_FUNC
       
   668 	iStateMachine.SetFailureReason(EUserCancelled);
       
   669 	iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError );
       
   670 	}
       
   671 
       
   672 // -----------------------------------------------------------------------------
       
   673 // Implements the default user reject behaviour. If needed, overwrite in the
       
   674 // state implementation.
       
   675 // -----------------------------------------------------------------------------
       
   676 //
       
   677 void TState::UserRejected()
       
   678 	{
       
   679 	UserCancelled();
       
   680 	}
       
   681 
       
   682 // Events from DownloadManager
       
   683 void TState::DownloadInProgress(const TInt /* aAlreadyDownloaded */, const TInt /* aDownloadSize */, const TReal32 /* aAvgDlSpeed */)
       
   684 	{
       
   685 	//LOG_FUNC
       
   686 	}
       
   687 
       
   688 void TState::DownloadCompleted(const TInt /* aBytesDownloaded */)
       
   689 	{
       
   690 	LOG_FUNC
       
   691 	}
       
   692 
       
   693  void TState::DownloadFailed()
       
   694 	{
       
   695 	LOG_FUNC
       
   696 	}
       
   697 
       
   698 void TState::DownloadFailed(const CStateFactory::TAppState aState)
       
   699 	{
       
   700 	const EDownloadError errId = iStateMachine.iDownloadHandler->GetDownloadError();
       
   701 	SLOG3( "+ DownloadFailed(): %d. err=%d", iStateMachine.StateIndex(), errId );
       
   702 
       
   703 	if ( (errId == EDlErrDownloadFailure ) && ( iStateMachine.iRestartAttempt < KDownloadRestartRetries) )
       
   704 		{
       
   705 		iStateMachine.iRestartAttempt++;
       
   706 		SLOG2( "Download restart, attempt %d", iStateMachine.iRestartAttempt );
       
   707 		iStateMachine.SetState( aState );
       
   708 		}
       
   709 	else
       
   710 		{
       
   711 		SLOG3( "Aborting download. (%d; %d)", iStateMachine.iRestartAttempt, errId );
       
   712 //      iStateMachine.iRestartAttempt = 0;
       
   713 		iStateMachine.SetFailureReason(EDownloadFailed);
       
   714 		iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError );
       
   715 		}
       
   716 	}
       
   717 
       
   718 void TState::DownloadCancelled()
       
   719 	{
       
   720 	LOG_FUNC
       
   721 	iStateMachine.SetFailureReason(EUserCancelled);
       
   722 	iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError );
       
   723 	}
       
   724 
       
   725 // Events from InstallManager
       
   726 void TState::InstallInProgress()
       
   727 	{
       
   728 	LOG_FUNC
       
   729 	}
       
   730 
       
   731 void TState::InstallCompleted(TInt /* aStatus */)
       
   732 	{
       
   733 	LOG_FUNC
       
   734 	}
       
   735 
       
   736 void TState::InstallationCancelled()
       
   737 	{
       
   738 	LOG_FUNC
       
   739 	}
       
   740 
       
   741 // =============================================================================
       
   742 TStateSetup::TStateSetup(const CStateFactory& aFactory) :
       
   743 	TState(aFactory)
       
   744 	{
       
   745 	LOG_FUNC
       
   746 	}
       
   747 
       
   748 void TStateSetup::Enter() const
       
   749 	{
       
   750 	LOG_FUNC
       
   751 
       
   752 	// TODO: Check if we are roaming and proceed according to that
       
   753 
       
   754 	iStateMachine.SetState( CStateFactory::EStateSetupParsing );
       
   755 	}
       
   756 
       
   757 TStateSetupParsing::TStateSetupParsing(const CStateFactory& aFactory) :
       
   758 	TState(aFactory)
       
   759 	{
       
   760 	}
       
   761 
       
   762 void TStateSetupParsing::Enter() const
       
   763 	{
       
   764 	const TInt mUid = iStateMachine.MachineUid();
       
   765 	if ( mUid )
       
   766 		{
       
   767 		iStateMachine.iDepTree->SetMachineId( mUid );
       
   768 		}
       
   769 	else
       
   770 		{
       
   771 		PanicInState( EPanicStateInvalidMachineUid );
       
   772 		}
       
   773 
       
   774 	// Get the drive where wrapper package was installed to
       
   775 	const TBool driveStatus = iStateMachine.iInstallManager->GetPackageInstalledDriveL(
       
   776 			iStateMachine.WrapperPackageUid(),
       
   777 			iStateMachine.iWrapperInstalledDrive);
       
   778 
       
   779 
       
   780 #ifdef __WINS__
       
   781 	iStateMachine.iWrapperInstalledDrive = 'C';
       
   782 #else
       
   783 	if ( !driveStatus )
       
   784 		{
       
   785 		// Read the wrapper installed drive from resume info file.
       
   786 		// TODO: What if user has tried to install on a removable drive and it's not available during the menu launch?
       
   787 		}
       
   788 #endif
       
   789 
       
   790 	SLOG3( "Installer pkg on %c: (%d)", (char)iStateMachine.iWrapperInstalledDrive, driveStatus );
       
   791 
       
   792 	// Cannot combine this with drive status. User might be trying to reinstall an app, already present in the device!
       
   793 	TVersion version, minVersion = KMinBootstrapSisVersion;
       
   794 	if ( iStateMachine.iInstallManager->GetPackageVersionInfoL(KUidBootstrap, version) )
       
   795 		{
       
   796 		// Compare installed and min required Bootstrap versions
       
   797 		if ( CompareVersions(minVersion, version) == EGreaterFirstVersion )
       
   798 			{
       
   799 			iStateMachine.SetFailureReason( EInvalidBootstrapVersion );
       
   800 			iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError );
       
   801 			return;
       
   802 			}
       
   803 		}
       
   804 	else
       
   805 		{
       
   806 		// Launched from the menu grid
       
   807 		}
       
   808 
       
   809 	switch ( iStateMachine.BootstrapVersion() )
       
   810 		{
       
   811 		case 1:
       
   812 		case 2:
       
   813 		case 3:
       
   814 			{
       
   815 			// Parses the dependency file included withing the wrapper package.
       
   816 			SLOG2( "* Parsing '%S'", iStateMachine.DepFilename() );
       
   817 			iStateMachine.iXmlParser->GetDepContentsL(
       
   818 					*iStateMachine.DepFilename(),
       
   819 					iStateMachine.iCurrentPackage,
       
   820 					iStateMachine.iDepTree
       
   821 				);
       
   822 			iStateMachine.SetState( CStateFactory::EStateBuildDepTree );
       
   823 			}
       
   824 			break;
       
   825 		case 4:
       
   826 			{
       
   827 			// Parses the application.sis file included in the wrapper package.
       
   828 			SLOG2( "* Parsing '%S'", iStateMachine.SisFilename() );
       
   829 			iStateMachine.iSisParser->GetDepContentsL(
       
   830 					*iStateMachine.SisFilename(),
       
   831 					iStateMachine.iCurrentPackage,
       
   832 					iStateMachine.iDepTree
       
   833 				);
       
   834 			iStateMachine.SetState( CStateFactory::EStateBuildDepTree );
       
   835 			}
       
   836 			break;
       
   837 		default:
       
   838 			{
       
   839 			SLOG2( "Invalid bootstrap v%d", iStateMachine.BootstrapVersion() );
       
   840 			iStateMachine.SetFailureReason( EInvalidBootstrapVersion );
       
   841 			iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError );
       
   842 			}
       
   843 			break;
       
   844 		}
       
   845 	}
       
   846 
       
   847 // -----------------------------------------------------------------------------
       
   848 //
       
   849 // -----------------------------------------------------------------------------
       
   850 //
       
   851 TStateParseDepFile::TStateParseDepFile(const CStateFactory& aFactory) :
       
   852 	TState(aFactory)
       
   853 	{
       
   854 	}
       
   855 
       
   856 void TStateParseDepFile::Enter() const
       
   857 	{
       
   858 	SLOG2( "+ ParseDepFileL(): '%S'", iStateMachine.iDownloadedFile );
       
   859 	iStateMachine.iXmlParser->GetDepContentsL(
       
   860 			*iStateMachine.iDownloadedFile,
       
   861 			iStateMachine.iCurrentPackage,
       
   862 			iStateMachine.iDepTree
       
   863 		);
       
   864 	iStateMachine.SetState( CStateFactory::EStateBuildDepTree );
       
   865 	SLOG2( "- ParseDepFileL(): '%S'", iStateMachine.iDownloadedFile );
       
   866 	}
       
   867 
       
   868 // -----------------------------------------------------------------------------
       
   869 //
       
   870 // -----------------------------------------------------------------------------
       
   871 //
       
   872 TStateParseChangesFile::TStateParseChangesFile(const CStateFactory& aFactory) :
       
   873 	TState(aFactory)
       
   874 	{
       
   875 	}
       
   876 
       
   877 void TStateParseChangesFile::Enter() const
       
   878 	{
       
   879 	SLOG2("+ ParseChangesFileL(): '%S'", iStateMachine.iDownloadedFile);
       
   880 	// Parse the provided changes file.
       
   881 	// the parameter aChangesFileName will be invalid after the call
       
   882 	iStateMachine.iXmlParser->GetChangesInfoL(
       
   883 			*iStateMachine.iDownloadedFile,
       
   884 			iStateMachine.iCurrentPackage,
       
   885 			iStateMachine.iDepTree
       
   886 		);
       
   887 	iStateMachine.SetState( CStateFactory::EStateDownloadDepFile );
       
   888 	SLOG2( "- ParseChangesFileL(): '%S'", iStateMachine.iDownloadedFile );
       
   889 	}
       
   890 
       
   891 // -----------------------------------------------------------------------------
       
   892 //
       
   893 // -----------------------------------------------------------------------------
       
   894 //
       
   895 TStateBuildFetchList::TStateBuildFetchList(const CStateFactory& aFactory) :
       
   896 	TState(aFactory)
       
   897 	{
       
   898 	}
       
   899 
       
   900 void TStateBuildFetchList::Enter() const
       
   901 	{
       
   902 	// Construct the list of dependent packages
       
   903 	SLOG( "Building dependency list" );
       
   904 	iStateMachine.iDepTree->ConstructFetchListL();
       
   905 
       
   906 	// Remove all downloaded dep files
       
   907 	SLOG( "Removing downloaded files" );
       
   908 	iStateMachine.iDepTree->RemoveDownloadedFiles( iStateMachine.FsSession() );
       
   909 
       
   910 	// Check if cycle exists
       
   911 	if ( iStateMachine.iDepTree->IsCyclePresent() )
       
   912 		{
       
   913 		// TODO: Inform user about configuration failure, exit gracefully
       
   914 		SLOG( "! Failure: cycle exists in the graph." );
       
   915 		iStateMachine.SetFailureReason( EInstallationFailed );
       
   916 		iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError );
       
   917 		}
       
   918 	iStateMachine.SetState( CStateFactory::EStateVerifyAvailableDiskSpace );
       
   919 	}
       
   920 
       
   921 // -----------------------------------------------------------------------------
       
   922 //
       
   923 // -----------------------------------------------------------------------------
       
   924 //
       
   925 TStateVerifyAvailableDiskSpace::TStateVerifyAvailableDiskSpace(const CStateFactory& aFactory) :
       
   926 	TState(aFactory)
       
   927 	{
       
   928 	}
       
   929 
       
   930 void TStateVerifyAvailableDiskSpace::Enter() const
       
   931 	{
       
   932 	// MaxDownloadSize is subtracted from available System drive space.
       
   933 
       
   934 	// In case of silent installation of main app, if there is no space available in the drive selected by the user for wrapper,
       
   935 	// normal installation to follow.
       
   936 
       
   937 	// Set the drive info
       
   938 	if ( iStateMachine.iDepTree->SetDriveInfo() )
       
   939 		{
       
   940 		// With Ovi Store prompt always
       
   941 		const TInt dlThreshold = iStateMachine.OviStoreRunning()
       
   942 				? 0
       
   943 				: KDownloadPromptThreshold;
       
   944 		const TInt dlSize = iStateMachine.iDepTree->GetTotalDownloadSize();
       
   945 
       
   946 		SLOG3( "Download size %d (%d)", dlSize, dlThreshold );
       
   947 
       
   948 #ifdef DEBUG_ADM
       
   949 		// Print all the drives set. To be removed after testing.
       
   950 		CPackageInfo *node = NULL;
       
   951 		while( (node = iStateMachine.iDepTree->GetNextSortedNode()) != NULL )
       
   952 			{
       
   953 			SLOG5( "PkgUid 0x%08X: InstDrive %c:, prio %d, size %d",
       
   954 					node->GetPackageUid(), (char)node->GetInstallDrive(),
       
   955 					node->GetDrivePriority(), node->GetInstallSize() );
       
   956 			}
       
   957 #endif
       
   958 		// Show user how much to download and confirm, if he/she wants to do that
       
   959 		// if we have dependencies to download at all
       
   960 		if ( dlSize > 0 )
       
   961 			{
       
   962 			// Finalize the progress bar
       
   963 			iStateMachine.UpdateProgressBar( KProgressBarFullValue, KProgressBarFullValue );
       
   964 
       
   965 			// We need to download dependencies
       
   966 			if ( iStateMachine.UsingWLAN() && !iStateMachine.OviStoreRunning() )
       
   967 				{
       
   968 				// If using WLAN, start the dependency download immediately without prompting the user
       
   969 				iStateMachine.SetState( CStateFactory::EStateStartDependencyDownload );
       
   970 				}
       
   971 			else if ( iStateMachine.RegisteredRoaming() )
       
   972 				{
       
   973 				// If the device is roaming, always prompt the user
       
   974 				iStateMachine.SetState( CStateFactory::EStateConfirmRoamingDownload );
       
   975 				}
       
   976 			else if ( dlSize > dlThreshold )
       
   977 				{
       
   978 				// If not using WLAN and the download threshold has exceeded, prompt the user
       
   979 				iStateMachine.SetState( CStateFactory::EStateConfirmDownload );
       
   980 				}
       
   981 			else
       
   982 				{
       
   983 				// Otherwise, continue the download automatically without prompting the user
       
   984 				iStateMachine.SetState( CStateFactory::EStateStartDependencyDownload );
       
   985 				}
       
   986 			}
       
   987 		else
       
   988 			{
       
   989 			SLOG( "Nothing to download, dependencies OK." );
       
   990 			// Keep the next progress bar update happy
       
   991 			iStateMachine.iProgressMaxValue = KProgressBarFullValue;
       
   992 			// Finalize the progress bar
       
   993 			iStateMachine.UpdateProgressBar( KProgressBarFullValue*95/100, KProgressBarFullValue );
       
   994 			iStateMachine.SetState( CStateFactory::EStateInstallAppSis );
       
   995 			}
       
   996 		}
       
   997 	else
       
   998 		{
       
   999 		iStateMachine.SetFailureReason( EInsufficientMemory );
       
  1000 		iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError );
       
  1001 		}
       
  1002 	}
       
  1003 
       
  1004 // -----------------------------------------------------------------------------
       
  1005 // Builds the dependency tree. This function controls the state machine.
       
  1006 // -----------------------------------------------------------------------------
       
  1007 //
       
  1008 TStateBuildDepTree::TStateBuildDepTree(const CStateFactory& aFactory) :
       
  1009 	TState(aFactory)
       
  1010 	{
       
  1011 	}
       
  1012 
       
  1013 void TStateBuildDepTree::Enter() const
       
  1014 	{
       
  1015 	SLOG2( "+ BuildDepTreeL(%d)", iStateMachine.iNodesProcessed );
       
  1016 
       
  1017 	// Update progress bar
       
  1018 	iStateMachine.iNodesProcessed++;
       
  1019 
       
  1020 	iStateMachine.iCurrentPackage = iStateMachine.iDepTree->GetNextNode();
       
  1021 	CPackageInfo* package = iStateMachine.iCurrentPackage;
       
  1022 
       
  1023 	if ( package == NULL )
       
  1024 		{
       
  1025 		SLOG( "Last package processed" );
       
  1026 		// Do the final progress bar update
       
  1027 		iStateMachine.UpdateProgressBar( KProgressBarFullValue*95/100, KProgressBarFullValue );
       
  1028 
       
  1029 		iStateMachine.SetState( CStateFactory::EStateBuildFetchList );
       
  1030 		}
       
  1031 	else
       
  1032 		{
       
  1033 		SLOG3( "* Processing 0x%08X (%d)", package->GetPackageUid(), package->GetPackageStatus() );
       
  1034 
       
  1035 		iStateMachine.UpdateProgressBar( iStateMachine.iNodesProcessed,
       
  1036 				iStateMachine.iNodesProcessed+2 );
       
  1037 
       
  1038 		// Call the install class api to validate and set the package status
       
  1039 		TUid uid = TUid::Uid( package->GetPackageUid() );
       
  1040 		TVersion version, test;
       
  1041 
       
  1042 		test = package->GetPackageVersion();
       
  1043 
       
  1044 		if (iStateMachine.iInstallManager->GetPackageVersionInfoL(uid, version))
       
  1045 			{
       
  1046 			// Compare installed and required verions
       
  1047 			// to find if upgrade is required.
       
  1048 			if ( (CompareVersions(test, version) ) == EGreaterFirstVersion)
       
  1049 				{
       
  1050 				SLOG8( "Package 0x%08X: upgrade %d.%02d.%d -> %d.%02d.%d",
       
  1051 						uid.iUid,
       
  1052 						version.iMajor, version.iMinor, version.iBuild,
       
  1053 						test.iMajor, test.iMinor, test.iBuild
       
  1054 						);
       
  1055 				package->SetPackageStatus(EPackageToBeUpgraded);
       
  1056 				}
       
  1057 			else
       
  1058 				{
       
  1059 				SLOG5( "Package 0x%08X: v%d.%02d.%d already installed", uid.iUid,
       
  1060 						version.iMajor, version.iMinor, version.iBuild
       
  1061 						);
       
  1062 				package->SetPackageStatus(EPackageInstalled);
       
  1063 				}
       
  1064 			}
       
  1065 		else
       
  1066 			{
       
  1067 			SLOG5( "Package 0x%08X: v%d.%02d.%d to be downloaded", uid.iUid,
       
  1068 					test.iMajor, test.iMinor, test.iBuild
       
  1069 					);
       
  1070 			package->SetPackageStatus(EPackageToBeFetched);
       
  1071 			}
       
  1072 
       
  1073 		iStateMachine.SetState( CStateFactory::EStateDownloadChangesFile );
       
  1074 		}
       
  1075 	SLOG2( "- BuildDepTreeL(%d)", iStateMachine.iNodesProcessed );
       
  1076 	}
       
  1077 
       
  1078 // -----------------------------------------------------------------------------
       
  1079 // Requests a download for the dependecy sis package _dep.xml file.
       
  1080 // -----------------------------------------------------------------------------
       
  1081 //
       
  1082 TStateDownloadDepFile::TStateDownloadDepFile(const CStateFactory& aFactory) :
       
  1083 	TState(aFactory)
       
  1084 	{
       
  1085 	}
       
  1086 
       
  1087 void TStateDownloadDepFile::Enter() const
       
  1088 	{
       
  1089 	//Here fetch the dep file of the current package.
       
  1090 	SLOG2( "+ FetchDepFileL(): 0x%08X", iStateMachine.iCurrentPackage->GetPackageUid() );
       
  1091 
       
  1092 	// TODO:Here the download Url should never be null]
       
  1093 	// as its mandatory to specify the Url in changes file.
       
  1094 	TPtrC8 urlPtr(NULL, 0);
       
  1095 	if (iStateMachine.iCurrentPackage->GetDownloadUrlL() != NULL)
       
  1096 		{
       
  1097 		SLOG8_2( "DepPkg URL: '%S'", iStateMachine.iCurrentPackage->GetDownloadUrlL() );
       
  1098 		urlPtr.Set(iStateMachine.iCurrentPackage->GetDownloadUrlL()->Des() );
       
  1099 		}
       
  1100 	else
       
  1101 		{
       
  1102 		SLOG8_2( "DepPkg URL: '%S' (default)", iStateMachine.ConfigUrl() );
       
  1103 		urlPtr.Set( *iStateMachine.ConfigUrl() );
       
  1104 		}
       
  1105 
       
  1106 	User::LeaveIfNull( iStateMachine.iCurrentPackage->GetDepFileName() );
       
  1107 
       
  1108 	SLOG2( "Downloading DEP: '%S'", iStateMachine.iCurrentPackage->GetDepFileName() );
       
  1109 
       
  1110 	iStateMachine.iDownloadHandler->StartDownloadL(
       
  1111 		urlPtr,
       
  1112 		*iStateMachine.iCurrentPackage->GetDepFileName(),
       
  1113 		iStateMachine.iDepTree->GetDownloadPath(),
       
  1114 		1);
       
  1115 	// We don't request a new state after this. When download completes
       
  1116 	// succesfully, a new state change will be requested.
       
  1117 	}
       
  1118 
       
  1119 void TStateDownloadDepFile::DownloadCompleted(const TInt /* aBytesDownloaded */)
       
  1120 	{
       
  1121 	iStateMachine.iRestartAttempt = 0;
       
  1122 	iStateMachine.SetState( CStateFactory::EStateParseDepFile );
       
  1123 	}
       
  1124 
       
  1125 void TStateDownloadDepFile::DownloadFailed()
       
  1126 	{
       
  1127 	LOG_FUNC
       
  1128 	TState::DownloadFailed( CStateFactory::EStateDownloadDepFile );
       
  1129 	}
       
  1130 
       
  1131 // -----------------------------------------------------------------------------
       
  1132 // Requests a download for the _changes.xml file.
       
  1133 // -----------------------------------------------------------------------------
       
  1134 //
       
  1135 TStateDownloadChangesFile::TStateDownloadChangesFile(const CStateFactory& aFactory) :
       
  1136 	TState(aFactory)
       
  1137 	{
       
  1138 	}
       
  1139 
       
  1140 void TStateDownloadChangesFile::Enter() const
       
  1141 	{
       
  1142 	// See if the URL is provided as part of the
       
  1143 	// dep file, otherwise use the default one.
       
  1144 	TPtrC8 urlPtr(NULL, 0);
       
  1145 	if ( iStateMachine.iCurrentPackage->GetURL() != NULL )
       
  1146 		{
       
  1147 		SLOG8_2( "Changes URL: '%S'", iStateMachine.iCurrentPackage->GetURL() );
       
  1148 		urlPtr.Set(iStateMachine.iCurrentPackage->GetURL()->Des());
       
  1149 		}
       
  1150 	else
       
  1151 		{
       
  1152 		SLOG8_2( "Changes URL: '%S' (default)", iStateMachine.ConfigUrl() );
       
  1153 		urlPtr.Set( *iStateMachine.ConfigUrl() );
       
  1154 		}
       
  1155 
       
  1156 		//TODO: The only reason why this is back here :
       
  1157 		//Changes file name for Root is not set when root is parsed. Fix it.
       
  1158 		iStateMachine.iCurrentPackage->SetChangesFileNameL();
       
  1159 	SLOG2( "Downloading CHANGES: '%S'", iStateMachine.iCurrentPackage->GetChangesFileName() );
       
  1160 
       
  1161 	// Download the changes file
       
  1162 	iStateMachine.iDownloadHandler->StartDownloadL(
       
  1163 		urlPtr,
       
  1164 		*iStateMachine.iCurrentPackage->GetChangesFileName(),
       
  1165 		iStateMachine.iDepTree->GetDownloadPath(),
       
  1166 		0);
       
  1167 	// We don't request a new state after this. When download completes
       
  1168 	// succesfully, a new state change will be requested by DownloadCompleted()
       
  1169 	}
       
  1170 
       
  1171 void TStateDownloadChangesFile::DownloadCompleted(const TInt /*aBytesDownloaded*/)
       
  1172 	{
       
  1173 	LOG_FUNC
       
  1174 
       
  1175 	iStateMachine.iNodesProcessed++;
       
  1176 	iStateMachine.UpdateProgressBar( iStateMachine.iNodesProcessed, iStateMachine.iNodesProcessed+2 );
       
  1177 
       
  1178 	iStateMachine.iRestartAttempt = 0;
       
  1179 	iStateMachine.SetState( CStateFactory::EStateParseChangesFile );
       
  1180 	}
       
  1181 
       
  1182 void TStateDownloadChangesFile::DownloadFailed()
       
  1183 	{
       
  1184 	LOG_FUNC
       
  1185 	TState::DownloadFailed( CStateFactory::EStateDownloadChangesFile );
       
  1186 	}
       
  1187 
       
  1188 // -----------------------------------------------------------------------------
       
  1189 //
       
  1190 // -----------------------------------------------------------------------------
       
  1191 //
       
  1192 TStateStartDependencyDownload::TStateStartDependencyDownload(const CStateFactory& aFactory) :
       
  1193 	TState(aFactory)
       
  1194 	{
       
  1195 	}
       
  1196 
       
  1197 void TStateStartDependencyDownload::Enter() const
       
  1198 	{
       
  1199 	const TUint32 totalDlSize = iStateMachine.iDepTree->GetTotalDownloadSize();
       
  1200 	SLOG2( "Starting to download %d bytes", totalDlSize );
       
  1201 
       
  1202 	// Remove all downloads before proceeding
       
  1203 	iStateMachine.iDownloadHandler->CancelAllDownloads();
       
  1204 
       
  1205 	// Start progress bar from beginning
       
  1206 	iStateMachine.iCounterCurrent = 1;
       
  1207 	iStateMachine.iCounterMax = iStateMachine.iDepTree->CountDownloadNodes();
       
  1208 
       
  1209 	// reset to zero for download and install of packages.
       
  1210 	iStateMachine.iDownloadSize = 0;
       
  1211 	iStateMachine.iNodesProcessed = 0;
       
  1212 
       
  1213 	// Start the dependency download!
       
  1214 	iStateMachine.SetState( CStateFactory::EStateDownloadDependency );
       
  1215 	}
       
  1216 
       
  1217 // -----------------------------------------------------------------------------
       
  1218 //
       
  1219 // -----------------------------------------------------------------------------
       
  1220 //
       
  1221 TStateDownloadDependency::TStateDownloadDependency(const CStateFactory& aFactory) :
       
  1222 	TState(aFactory),
       
  1223 	iRetryDownload(EFalse)
       
  1224 	{
       
  1225 	}
       
  1226 
       
  1227 void TStateDownloadDependency::Enter() const
       
  1228 	{
       
  1229 	SLOG3( "+ FetchPackageL(%d): retry=%d", iStateMachine.iNodesProcessed, iRetryDownload );
       
  1230 
       
  1231 	CPackageInfo* fetchPackage = NULL;
       
  1232 
       
  1233 	if ( iRetryDownload )
       
  1234 		{
       
  1235 		fetchPackage = iStateMachine.iDepTree->GetCurrentFetchNode();
       
  1236 		}
       
  1237 	else
       
  1238 		{
       
  1239 		iStateMachine.iNodesProcessed++;
       
  1240 		// always ensure that iCurrentPackage points to the correct one
       
  1241 		fetchPackage = iStateMachine.iDepTree->GetNextFetchNode();
       
  1242 		}
       
  1243 	iStateMachine.iCurrentPackage = fetchPackage;
       
  1244 
       
  1245 	if ( !fetchPackage )
       
  1246 		{
       
  1247 /*
       
  1248 		//end of list - we're finished
       
  1249 		SLOG2( "Uninstalling wrapper 0x%08X", iStateMachine.WrapperPackageUid().iUid );
       
  1250 		TInt err = iStateMachine.iInstallManager->SilentUnInstallPackage(
       
  1251 			iStateMachine.WrapperPackageUid() );
       
  1252 		SLOG2( "Uninstall status: %d", err);
       
  1253 */
       
  1254 		// Wrapper has been uninstalled, ready to exit/launch
       
  1255 		iStateMachine.SetState( CStateFactory::EStateExit );
       
  1256 		return;
       
  1257 		}
       
  1258 /*
       
  1259 	// Attempting to fix 'Network connection lost!' errors on 3G. Does not help.
       
  1260 	SLOG( "Deleting all downloads" );
       
  1261 	iStateMachine.iDownloadHandler->CancelAllDownloads();
       
  1262 */
       
  1263 	switch ( fetchPackage->GetPackageStatus() )
       
  1264 		{
       
  1265 		case EPackageRootToBeInstalled:
       
  1266 			{
       
  1267 			//SLOG( "* Installing AppSis" );
       
  1268 
       
  1269 			iStateMachine.SetState( CStateFactory::EStateInstallAppSis );
       
  1270 			}
       
  1271 			break;
       
  1272 		case EPackageToBeFetched:
       
  1273 		case EPackageToBeUpgraded:
       
  1274 			{
       
  1275 			SLOG2( "* Package 0x%08X to be Fetched/Upgraded", fetchPackage->GetPackageUid() );
       
  1276 
       
  1277 			// Initialize progress bar
       
  1278 			//ShowGlobalProgressL(R_ADM_DOWNLOAD_WAIT_TEXT, 0, KMaxTInt);
       
  1279 
       
  1280 			if ( iStateMachine.iCounterMax > 0 )
       
  1281 				{
       
  1282 				iStateMachine.StopWaitNote();
       
  1283 				// prevent progress bar from starting from previous dl size
       
  1284 				iStateMachine.iProgressCurrentValue = 0;
       
  1285 				iStateMachine.iCumulativeDepDownloaded = 0;
       
  1286 				iStateMachine.iProgressMaxValue = fetchPackage->GetDownloadSize();
       
  1287 				iStateMachine.ShowProgressBarL(
       
  1288 						0,
       
  1289 						iStateMachine.iProgressMaxValue,
       
  1290 						iStateMachine.iCounterCurrent,
       
  1291 						iStateMachine.iCounterMax
       
  1292 						);
       
  1293 				}
       
  1294 
       
  1295 			// TODO:Here the download Url should never be null,
       
  1296 			// as its mandatory to specify the Url in changes file.
       
  1297 			TPtrC8 urlPtr(NULL, 0);
       
  1298 			if (fetchPackage->GetDownloadUrlL() != NULL )
       
  1299 				{
       
  1300 				SLOG8_2( "Package URL: '%S'", fetchPackage->GetDownloadUrlL());
       
  1301 				urlPtr.Set(fetchPackage->GetDownloadUrlL()->Des());
       
  1302 				}
       
  1303 			else
       
  1304 				{
       
  1305 				SLOG8_2( "Package URL: '%S' (default)", iStateMachine.ConfigUrl() );
       
  1306 				urlPtr.Set(*iStateMachine.ConfigUrl());
       
  1307 				}
       
  1308 
       
  1309 			User::LeaveIfNull( fetchPackage->GetSisPackageName() );
       
  1310 
       
  1311 			SLOG2( "Downloading: '%S'", fetchPackage->GetSisPackageName() );
       
  1312 			iStateMachine.iDownloadHandler->StartDownloadL(
       
  1313 				urlPtr,
       
  1314 				*fetchPackage->GetSisPackageName(),
       
  1315 				iStateMachine.iDepTree->GetDownloadPath(),
       
  1316 				2);
       
  1317 			}
       
  1318 			break;
       
  1319 		case EPackageInstalled:
       
  1320 			{
       
  1321 			SLOG2( "* Package 0x%08X installed", fetchPackage->GetPackageUid());
       
  1322 			//FetchPackageL();
       
  1323 			iStateMachine.SetState( CStateFactory::EStateDownloadDependency );
       
  1324 			}
       
  1325 			break;
       
  1326 		default:
       
  1327 			{
       
  1328 			// TODO: Better error handling
       
  1329 			Panic( EPanicStateFetchStatus );
       
  1330 			}
       
  1331 			break;
       
  1332 		} // switch
       
  1333 	SLOG2( "- FetchPackageL(%d)", iStateMachine.iNodesProcessed );
       
  1334 	}
       
  1335 
       
  1336 void TStateDownloadDependency::DownloadCompleted(const TInt aBytesDownloaded)
       
  1337 	{
       
  1338 	iRetryDownload = EFalse;
       
  1339 	// Indicate that we've downloaded this amount already to keep progress bar happy
       
  1340 	iStateMachine.iCumulativeDepDownloaded += aBytesDownloaded;
       
  1341 	iStateMachine.iDownloadSize = iStateMachine.iCumulativeDepDownloaded;
       
  1342 	iStateMachine.SetState( CStateFactory::EStateInstallDependency );
       
  1343 	}
       
  1344 
       
  1345 void TStateDownloadDependency::DownloadInProgress(const TInt aAlreadyDownloaded, const TInt aDownloadSize, const TReal32 aAvgDlSpeed)
       
  1346 	{
       
  1347 	static TInt32 prevAlready = 0;
       
  1348 	// Prevents log and event flooding
       
  1349 	if (aAlreadyDownloaded != prevAlready)
       
  1350 		{
       
  1351 		prevAlready = aAlreadyDownloaded;
       
  1352 
       
  1353 		iStateMachine.iDownloadSize = aAlreadyDownloaded + iStateMachine.iCumulativeDepDownloaded;
       
  1354 		iStateMachine.iProgressCurrentValue =
       
  1355 				iStateMachine.iCumulativeDepDownloaded + aAlreadyDownloaded;
       
  1356 		if (aAvgDlSpeed > 0)
       
  1357 			{
       
  1358 			SLOG4( "DL %7d/%7d (%3.02f kB/s)", aAlreadyDownloaded, aDownloadSize, aAvgDlSpeed/1024 );
       
  1359 			}
       
  1360 		else
       
  1361 			{
       
  1362 			SLOG3( "DL %7d/%7d", aAlreadyDownloaded, aDownloadSize );
       
  1363 			}
       
  1364 		// Update the progress bar
       
  1365 		iStateMachine.UpdateProgressBar( iStateMachine.iProgressCurrentValue,
       
  1366 				iStateMachine.iProgressMaxValue );
       
  1367 		}
       
  1368 	}
       
  1369 
       
  1370 void TStateDownloadDependency::DownloadFailed()
       
  1371 	{
       
  1372 	LOG_FUNC
       
  1373 	iRetryDownload = ETrue;
       
  1374 	TState::DownloadFailed( CStateFactory::EStateDownloadDependency );
       
  1375 	}
       
  1376 
       
  1377 // -----------------------------------------------------------------------------
       
  1378 // Uninstalls installed dependencies one at the time
       
  1379 // -----------------------------------------------------------------------------
       
  1380 //
       
  1381 TStateUninstallDependency::TStateUninstallDependency(const CStateFactory& aFactory) :
       
  1382 	TState(aFactory)
       
  1383 	{
       
  1384 	}
       
  1385 
       
  1386 void TStateUninstallDependency::Enter() const
       
  1387 	{
       
  1388 	CPackageInfo* node = iStateMachine.iDepTree->GetPreviousFetchNode();
       
  1389 	// Uninstall all the fetched and installed dependencies
       
  1390 	if (node)
       
  1391 		{
       
  1392 		// TODO: Can the package present check be moved to Install handler?. Below is an async function though.
       
  1393 		if ( (node->GetPackageStatus() == EPackageFetchedInstalled) &&
       
  1394 			( iStateMachine.iInstallManager->IsPackagePresentL(TUid::Uid(node->GetPackageUid())) ) )
       
  1395 			{
       
  1396 			SLOG2( "Uninstalling: 0x%x", node->GetPackageUid() );
       
  1397 
       
  1398 			iStateMachine.iInstallManager->
       
  1399 				SilentUninstallPackageAsync( TUid::Uid(node->GetPackageUid()) );
       
  1400 			// the next event will be triggered by InstallCompleted() below
       
  1401 			}
       
  1402 		else
       
  1403 			{
       
  1404 			SLOG2( "Skipping: 0x%x", node->GetPackageUid() );
       
  1405 			// Process the next package
       
  1406 			iStateMachine.SetState( CStateFactory::EStateUninstallDependency );
       
  1407 			}
       
  1408 		}
       
  1409 	else
       
  1410 		{
       
  1411 		SLOG( "About to uninstall wrapper" );
       
  1412 		// We've processed the dependency tree, uninstall the wrapper
       
  1413 		// Failure reason is set before calling EPrepareForExitWithError
       
  1414 		iStateMachine.SetState( CStateFactory::EStateExit );
       
  1415 		}
       
  1416 	}
       
  1417 
       
  1418 // This is actually handling the UNinstallation completed event
       
  1419 void TStateUninstallDependency::InstallCompleted(TInt aStatus)
       
  1420 	{
       
  1421 	SLOG2( "UninstallDependencyCompleted(): %d", aStatus );
       
  1422 	// Try to uninstall next dependency, without minding the status code
       
  1423 	iStateMachine.SetState( CStateFactory::EStateUninstallDependency );
       
  1424 	}
       
  1425 
       
  1426 // -----------------------------------------------------------------------------
       
  1427 //
       
  1428 // -----------------------------------------------------------------------------
       
  1429 //
       
  1430 TStateLaunchApp::TStateLaunchApp(const CStateFactory& aFactory) :
       
  1431 	TState(aFactory)
       
  1432 	{
       
  1433 	}
       
  1434 
       
  1435 void TStateLaunchApp::Enter() const
       
  1436 	{
       
  1437 	RArray<TUid> appSids;
       
  1438 	TBool launchStatus = ETrue;
       
  1439 	// Get the SID list from installer
       
  1440 	TUid uid = TUid::Uid( iStateMachine.iCurrentPackage->GetPackageUid() );
       
  1441 	const TBool status = iStateMachine.iInstallManager->GetPackageSidsL(uid, appSids);
       
  1442 
       
  1443 	if ( status )
       
  1444 		{
       
  1445 #ifdef DEBUG_ADM
       
  1446 		for (TInt i = 0; i < appSids.Count(); i++)
       
  1447 			{
       
  1448 			SLOG3( "SID[%d]=0x%08X", i, appSids[i] );
       
  1449 			}
       
  1450 #endif
       
  1451 		TApaAppInfo appInfo;
       
  1452 		RApaLsSession lsSession;
       
  1453 
       
  1454 		// Connect to Apparc
       
  1455 		if ( !lsSession.Connect() )
       
  1456 			{
       
  1457 			CleanupClosePushL( lsSession );
       
  1458 
       
  1459 			for (TInt i = 0; i < appSids.Count(); i++)
       
  1460 				{
       
  1461 				TInt ret = lsSession.GetAppInfo( appInfo, appSids[i] );
       
  1462 				// Get the app Info of the Sid.
       
  1463 				if ( ret == KErrNone )
       
  1464 					{
       
  1465 					HBufC* iconFilename = NULL;
       
  1466 					// Get the application icon, if any. It's used in the launch dialog.
       
  1467 					ret = lsSession.GetAppIcon( appSids[i], iconFilename );
       
  1468 					if (ret == KErrNone)
       
  1469 						{
       
  1470 						// We have a launchable exe and icon: get the executable name and caption
       
  1471 						iStateMachine.iLaunchName = appInfo.iFullName;
       
  1472 						iStateMachine.iLaunchCaption = appInfo.iCaption;
       
  1473 						iStateMachine.iLaunchIconFilename.Copy( *iconFilename );
       
  1474 						SLOG5( "LaunchExe %d '%S' '%S' '%S'", i, &iStateMachine.iLaunchName, &iStateMachine.iLaunchCaption, &iStateMachine.iLaunchIconFilename );
       
  1475 
       
  1476 						delete iconFilename;
       
  1477 						break;
       
  1478 						}
       
  1479 					// The .exe didn't have an icon, try next .exe.
       
  1480 					// We're assuming that only exe's having an icon are the ones we should launch
       
  1481 					} // if
       
  1482 				} // for
       
  1483 			CleanupStack::PopAndDestroy( &lsSession );
       
  1484 			} //if ( !lsSession.Connect() )
       
  1485 		else
       
  1486 			{
       
  1487 			launchStatus = EFalse;
       
  1488 			}
       
  1489 		} // if( status )
       
  1490 	else
       
  1491 		{
       
  1492 		launchStatus = EFalse;
       
  1493 		}
       
  1494 
       
  1495 	appSids.Close();
       
  1496 
       
  1497 	if ( launchStatus && iStateMachine.iLaunchName.Length() )
       
  1498 		{
       
  1499 		iStateMachine.SetAppLaunch(ETrue);
       
  1500 		iStateMachine.iAppUi.ShowLaunchPromptL( iStateMachine.iLaunchCaption, iStateMachine.iLaunchIconFilename );
       
  1501 		}
       
  1502 	else
       
  1503 		{
       
  1504 		// No executable to launch!
       
  1505 		iStateMachine.SetState( CStateFactory::EStateExit );
       
  1506 		}
       
  1507 	}
       
  1508 
       
  1509 // -----------------------------------------------------------------------------
       
  1510 //
       
  1511 // -----------------------------------------------------------------------------
       
  1512 //
       
  1513 void TStateLaunchApp::UserAccepted()
       
  1514 	{
       
  1515 	RApaLsSession lsSession;
       
  1516 
       
  1517 	// Connect to Apparc
       
  1518 	User::LeaveIfError( lsSession.Connect() );
       
  1519 	CleanupClosePushL( lsSession );
       
  1520 
       
  1521 	CApaCommandLine* cmdLine = CApaCommandLine::NewLC();
       
  1522 	cmdLine->SetExecutableNameL( iStateMachine.iLaunchName );
       
  1523 	cmdLine->SetCommandL( EApaCommandRun );
       
  1524 
       
  1525 	SLOG3( "Launching %S '%S'", &iStateMachine.iLaunchCaption, &iStateMachine.iLaunchName );
       
  1526 	// Launch the application
       
  1527 	// TODO: Better error handling
       
  1528 	User::LeaveIfError( lsSession.StartApp( *cmdLine ) );
       
  1529 
       
  1530 	CleanupStack::PopAndDestroy( 2, &lsSession ); // cmdLine, lsSession
       
  1531 
       
  1532 	iStateMachine.SetState( CStateFactory::EStateExit );
       
  1533 	}
       
  1534 
       
  1535 // -----------------------------------------------------------------------------
       
  1536 //
       
  1537 // -----------------------------------------------------------------------------
       
  1538 //
       
  1539 void TStateLaunchApp::UserRejected()
       
  1540 	{
       
  1541 	SLOG( "User denied application launch" );
       
  1542 	iStateMachine.SetAppLaunch(EFalse);
       
  1543 	iStateMachine.SetState( CStateFactory::EStateExit );
       
  1544 	}
       
  1545 
       
  1546 // -----------------------------------------------------------------------------
       
  1547 //
       
  1548 // -----------------------------------------------------------------------------
       
  1549 //
       
  1550 TStateExit::TStateExit(const CStateFactory& aFactory) :
       
  1551 	TState(aFactory)
       
  1552 	{
       
  1553 	}
       
  1554 
       
  1555 void TStateExit::Enter() const
       
  1556 	{
       
  1557 	SLOG2( "Exit (%d)", iStateMachine.FailedState() );
       
  1558 
       
  1559 #ifdef FEATURE_INSTALL_RESUME
       
  1560 	// FailedState is checked to differentiate a completion of successful menu launch from failure cases.
       
  1561 	// Also uninstall the wrapper, when the resume information file is not required
       
  1562 	// (in case of Bootstrap failure mode - KCmdLineCancelAdmNoResume)
       
  1563 	if ( ( iStateMachine.FailedState() == CStateFactory::EStateLast ) ||
       
  1564 			 ( iStateMachine.FailedState() == KUnknownState ) ||
       
  1565 			 ( !iStateMachine.ResumeRequired() )
       
  1566 			)
       
  1567 		{
       
  1568 		// Do the final cleanup here: remove the wrapper package, which
       
  1569 		// will also remove the bootstrap
       
  1570 		SLOG2( "Uninstalling wrapper 0x%08X", iStateMachine.WrapperPackageUid().iUid );
       
  1571 		const TInt err = iStateMachine.iInstallManager->SilentUnInstallPackage(
       
  1572 				iStateMachine.WrapperPackageUid() );
       
  1573 		if (err != KErrNone)
       
  1574 			{
       
  1575 			SLOG2( "! Uninstall failed (%d)", err );
       
  1576 			}
       
  1577 
       
  1578 		// Remove resume info files
       
  1579 		RemoveResumeFiles();
       
  1580 		}
       
  1581 	else
       
  1582 		{
       
  1583 		// Remove only the bootstrap.
       
  1584 		// Wrapper is retained for Menu launch.
       
  1585 		// It is possible that bootstrap is already removed in previous unsuccessful menu launch
       
  1586 		if ( iStateMachine.iInstallManager->IsPackagePresentL( KUidBootstrap ) )
       
  1587 			{
       
  1588 			SLOG2( "Uninstalling bootstrap 0x%08X", KUidBootstrap );
       
  1589 			const TInt err = iStateMachine.iInstallManager->SilentUnInstallPackage( KUidBootstrap );
       
  1590 			// ignore any errors
       
  1591 			if (err != KErrNone)
       
  1592 				{
       
  1593 				SLOG2( "! Uninstall failed (%d)", err );
       
  1594 				}
       
  1595 			}
       
  1596 		}
       
  1597 #else
       
  1598 	// Do the final cleanup here: remove the wrapper package
       
  1599 	SLOG2( "Uninstalling wrapper 0x%08X", iStateMachine.WrapperPackageUid().iUid );
       
  1600 	const TInt err = iStateMachine.iInstallManager->SilentUnInstallPackage(
       
  1601 			iStateMachine.WrapperPackageUid() );
       
  1602 	if (err != KErrNone)
       
  1603 		{
       
  1604 		SLOG2( "! Uninstall failed (%d)", err );
       
  1605 		}
       
  1606 #endif // FEATURE_INSTALL_RESUME
       
  1607 
       
  1608 #ifdef FEATURE_REPORTING
       
  1609 	// Report only the specified cases
       
  1610 	switch ( iStateMachine.ExitReason() )
       
  1611 		{
       
  1612 	case EExitNoError:
       
  1613 	case EUserCancelled:
       
  1614 //	case EDownloadFailed:
       
  1615 	case EInsufficientMemory:
       
  1616 	case EDeviceNotSupported:
       
  1617 	case EInstallationFailed:
       
  1618 	case EInvalidBootstrapVersion:
       
  1619 	case ERootInstallationFailed:
       
  1620 		Report();
       
  1621 		break;
       
  1622 	default:
       
  1623 		break;
       
  1624 		}
       
  1625 #else
       
  1626 	// We can exit the application
       
  1627 	// The default failure reason is "No Error"
       
  1628 	iStateMachine.iAppUi.ExitApp();
       
  1629 
       
  1630 	// Above call does not return
       
  1631 #endif
       
  1632 	}
       
  1633 
       
  1634 // -----------------------------------------------------------------------------
       
  1635 // RemoveResumeFiles()
       
  1636 // On successful completion of the installation process, remove the resume info file.
       
  1637 // -----------------------------------------------------------------------------
       
  1638 //
       
  1639 void TStateExit::RemoveResumeFiles() const
       
  1640 	{
       
  1641 	if ( BaflUtils::FileExists(iStateMachine.FsSession(), KADMResumeInfoFile) )
       
  1642 		{
       
  1643 		RArray< TPtrC > lineBuffer;
       
  1644 		TInt ret = 0;
       
  1645 		HBufC* buffer = ReadConfigFile( iStateMachine.FsSession(), KADMResumeInfoFile, lineBuffer, ret );
       
  1646 
       
  1647 		if ( buffer && ret == KErrNone )
       
  1648 			{
       
  1649 			// Get AppFileName from the config file
       
  1650 			TPtrC appFileNameLine = GetConfigValue( KRFieldAppFileName, lineBuffer, ret );
       
  1651 			if ( ret == KErrNone )
       
  1652 				{
       
  1653 				SLOG2( "AppFileName = '%S'", &appFileNameLine );
       
  1654 
       
  1655 				if ( BaflUtils::FileExists(iStateMachine.FsSession(), appFileNameLine) )
       
  1656 					{
       
  1657 					const TInt err = iStateMachine.FsSession().Delete( appFileNameLine );
       
  1658 					SLOG2( "AppFile has been deleted (%d)", err);
       
  1659 					}
       
  1660 				}
       
  1661 			else
       
  1662 				{
       
  1663 				SLOG2( "Failed to read value from resume info (%d)", ret );
       
  1664 				}
       
  1665 			delete buffer;
       
  1666 			}
       
  1667 		ret = iStateMachine.FsSession().Delete( KADMResumeInfoFile );
       
  1668 		SLOG2( "Resume info has been deleted (%d)", ret );
       
  1669 
       
  1670 		// TODO: Need to remove the copied dep file as well
       
  1671 		}
       
  1672 	}
       
  1673 #ifdef FEATURE_REPORTING
       
  1674 // -----------------------------------------------------------------------------
       
  1675 // Creates a report about the installation and sends that to the server
       
  1676 // -----------------------------------------------------------------------------
       
  1677 //
       
  1678 void TStateExit::Report() const
       
  1679 	{
       
  1680 	_LIT8(KFmtVersion, "%d.%02d.%d");
       
  1681 	_LIT(KOK, "OK");
       
  1682 	TBuf8<KMaxFileName> url;
       
  1683 	url.Copy( *iStateMachine.ConfigUrl() );
       
  1684 
       
  1685 	// -----------------------------------------------------------------------------
       
  1686 	// The base report URL is:
       
  1687 	// http://server/root/x.yy.z/reason/flags/OK
       
  1688 	//
       
  1689 	// where
       
  1690 	//
       
  1691 	// http://server/root/     ConfigUrl()
       
  1692 	// x.yy.z                  ADM version formatted as %d.%02d.%d
       
  1693 	// reason                  iExitReason
       
  1694 	// flags                   Flags defined below in Report Version 1
       
  1695 	// OK                      Non-existing file
       
  1696 	//
       
  1697 	// -----------------------------------------------------------------------------
       
  1698 	// Report Version 1
       
  1699 	//
       
  1700 	//31        11 10  9  8  7  6  5  4  3  2  1  0
       
  1701 	// +-------+--+--+--+--+--+--+--+--+--+--+--+--+
       
  1702 	// |reservd|  |  |                 |           |
       
  1703 	// +-------+--+--+--+--+--+--+--+--+--+--+--+--+
       
  1704 	//
       
  1705 	//      value
       
  1706 	// bits range  description
       
  1707 	//  0-3  0-15  Report version
       
  1708 	//
       
  1709 	// Other bits for version 1
       
  1710 	//
       
  1711 	//      value
       
  1712 	// bits range  description
       
  1713 	//  4-9  0-63  Number of packages downloaded
       
  1714 	//   10   1    Ovi Store running
       
  1715 	//   11   1    Application launched
       
  1716 	// -----------------------------------------------------------------------------
       
  1717 	//
       
  1718 
       
  1719 	// Get the ADM version
       
  1720 	TVersion version;
       
  1721 	iStateMachine.iInstallManager->GetPackageVersionInfoL(KUidADMApp, version);
       
  1722 
       
  1723 #if 0
       
  1724 	const TUint32 KReportVersion = 1;
       
  1725 	TUint32 flags;
       
  1726 	flags  = KReportVersion                                        << 0;  // 4 bits (0-15)
       
  1727 	flags |= (iStateMachine.iDepTree->CountDownloadNodes() & 0x3f) << 4;  // 6 bits (0-63)
       
  1728 	flags |= iStateMachine.OviStoreRunning()                       << 10; // 1 bit
       
  1729 	flags |= iStateMachine.AppLaunch()                             << 11; // 1 bit
       
  1730 	SLOG2( "Exit: 0x%08x", flags );
       
  1731 #endif
       
  1732 
       
  1733 	url.AppendFormat(KFmtVersion, version.iMajor, version.iMinor, version.iBuild);
       
  1734 	url.Append('/');
       
  1735 	url.AppendNum( iStateMachine.ExitReason() );
       
  1736 	url.Append('/');
       
  1737 	url.AppendNum( iStateMachine.OviStoreRunning() );
       
  1738 	url.Append('/');
       
  1739 	url.AppendNum( iStateMachine.ResumingInstallation() );
       
  1740 	url.Append('/');
       
  1741 #if 0
       
  1742 	url.AppendNumFixedWidthUC(flags, EHex, 8);
       
  1743 	url.Append('/');
       
  1744 	url.AppendNum( iStateMachine.OviStoreRunning() );
       
  1745 	url.Append('/');
       
  1746 	url.AppendNum( iStateMachine.AppLaunch() );
       
  1747 	url.Append('/');
       
  1748 #endif
       
  1749 	iStateMachine.iDownloadHandler->StartDownloadL(
       
  1750 		url,
       
  1751 		KOK,
       
  1752 		iStateMachine.iDepTree->GetDownloadPath(),
       
  1753 		0);
       
  1754 	}
       
  1755 
       
  1756 // -----------------------------------------------------------------------------
       
  1757 // Ignore "in progress" event calls.
       
  1758 // -----------------------------------------------------------------------------
       
  1759 //
       
  1760 void TStateExit::DownloadInProgress(const TInt /* aAlreadyDownloaded */, const TInt /* aDownloadSize */, const TReal32 /* aAvgDlSpeed */)
       
  1761 	{
       
  1762 	}
       
  1763 
       
  1764 // -----------------------------------------------------------------------------
       
  1765 // Transfer control to ExitApp().
       
  1766 // -----------------------------------------------------------------------------
       
  1767 //
       
  1768 void TStateExit::DownloadCompleted(const TInt /* aBytesDownloaded */)
       
  1769 	{
       
  1770 	iStateMachine.iAppUi.ExitApp();
       
  1771 	}
       
  1772 
       
  1773 // -----------------------------------------------------------------------------
       
  1774 // Transfer control to ExitApp().
       
  1775 // -----------------------------------------------------------------------------
       
  1776 //
       
  1777 void TStateExit::DownloadFailed()
       
  1778 	{
       
  1779 	iStateMachine.iAppUi.ExitApp();
       
  1780 	}
       
  1781 
       
  1782 // -----------------------------------------------------------------------------
       
  1783 // Transfer control to ExitApp().
       
  1784 // -----------------------------------------------------------------------------
       
  1785 //
       
  1786 void TStateExit::DownloadCancelled()
       
  1787 	{
       
  1788 	iStateMachine.iAppUi.ExitApp();
       
  1789 	}
       
  1790 #endif
       
  1791 
       
  1792 // -----------------------------------------------------------------------------
       
  1793 //
       
  1794 // -----------------------------------------------------------------------------
       
  1795 //
       
  1796 TStatePrepareExitWithError::TStatePrepareExitWithError(const CStateFactory& aFactory) :
       
  1797 	TState(aFactory)
       
  1798 	{
       
  1799 	}
       
  1800 
       
  1801 void TStatePrepareExitWithError::Enter() const
       
  1802 	{
       
  1803 	// Show the user a wait note, if needed
       
  1804 	iStateMachine.iAppUi.HandleFailure();
       
  1805 
       
  1806 	// TODO: FIX THIS! DlMgr requires some time for its AOs to do the cleanup.
       
  1807 	User::After(1000000);
       
  1808 	iStateMachine.iDownloadHandler->CancelAllDownloads();
       
  1809 	iStateMachine.iDepTree->RemoveDownloadedFiles( iStateMachine.FsSession() );
       
  1810 
       
  1811 #ifdef FEATURE_INSTALL_RESUME
       
  1812 	// Backup the resume info for future launch
       
  1813 	if ( iStateMachine.ResumeRequired() )
       
  1814 		{
       
  1815 		// Create the resume information
       
  1816 		if ( CreateInstallationResumeInfo() == KErrNone )
       
  1817 			{
       
  1818 			// Dependencies are not uninstalled if launched from Menu
       
  1819 			iStateMachine.SetState( CStateFactory::EStateExit );
       
  1820 			return;
       
  1821 			}
       
  1822 		}
       
  1823 	// If no resume info required or CreateInstallationResumeInfo fails.
       
  1824 	iStateMachine.SetState( CStateFactory::EStateUninstallDependency );
       
  1825 #else
       
  1826 	// Trigger the dependency uninstallation
       
  1827 	iStateMachine.SetState( CStateFactory::EStateUninstallDependency );
       
  1828 #endif // FEATURE_INSTALL_RESUME
       
  1829 	}
       
  1830 
       
  1831 // -----------------------------------------------------------------------------
       
  1832 // CreateInstallationResumeInfo
       
  1833 // Backup the necessary information to continue the installation later i.e.
       
  1834 // from the application menu grid.
       
  1835 // -----------------------------------------------------------------------------
       
  1836 //
       
  1837 #define CHECK(a) {    \
       
  1838 	if (a != KErrNone) \
       
  1839 		goto failed;   \
       
  1840 	pos++;             \
       
  1841 	}
       
  1842 
       
  1843 TInt TStatePrepareExitWithError::CreateInstallationResumeInfo() const
       
  1844 	{
       
  1845 	SLOG( "+ CreateInstallationResumeInfo()" );
       
  1846 
       
  1847 	// This is increment in each CHECK() macro
       
  1848 	TInt pos = 0;
       
  1849 
       
  1850 	// Step 0: Backup the required files to ADM Private folder.
       
  1851 	// (Also the names are written to resume info file)
       
  1852 	TRAPD( err, BackupFilesL() );
       
  1853 	CHECK(err);
       
  1854 
       
  1855 	RFile outFile;
       
  1856 	CPackageInfo* node = NULL;
       
  1857 
       
  1858 	TInt numberOfNodes = iStateMachine.iDepTree->NodesCount();
       
  1859 	// Skip the main application
       
  1860 	if (numberOfNodes > 0)
       
  1861 		{
       
  1862 		numberOfNodes--;
       
  1863 		}
       
  1864 
       
  1865 	err = outFile.Open( iStateMachine.FsSession(), KADMResumeInfoFile, EFileWrite | EFileStreamText | EFileShareAny );
       
  1866 	CHECK(err);
       
  1867 
       
  1868 	// Step 1: Write the application name
       
  1869 	node = iStateMachine.iDepTree->GetRootNode();
       
  1870 	SLOG3( "Saving state for '%S' (%d)", node->GetPackageName(), numberOfNodes );
       
  1871 	err = WriteToConfigFile( outFile, KRFieldAppName, *node->GetPackageName() );
       
  1872 	CHECK(err);
       
  1873 
       
  1874 	// Step 2: Write the depPkg UIDs to resume info file.
       
  1875 	// A new resume info file is already created as part of the "BackupFilesL()"
       
  1876 	// If user presses cancel before the fetchlist is constructed, then this loop will not execute.
       
  1877 	for (TInt i = 0; i < numberOfNodes; i++)
       
  1878 		{
       
  1879 		node =  iStateMachine.iDepTree->GetFetchNode( i );
       
  1880 		SLOG2( "Adding info: 0x%08X", node->GetPackageUid() );
       
  1881 
       
  1882 		err = WriteIntToConfigFile( outFile, KRFieldDepPkgUid, node->GetPackageUid() );
       
  1883 		CHECK(err);
       
  1884 		}
       
  1885 
       
  1886 #if 0
       
  1887 	node = iStateMachine.iDepTree->GetRootNode();
       
  1888 	SLOG2( "Adding main: 0x%08X", node->GetPackageUid() );
       
  1889 
       
  1890 	// Step 3: Write the Root pkg UID to resume info file.
       
  1891 	// TODO: Check whether this is really needed.
       
  1892 	err = WriteIntToConfigFile( outFile, KRootPkgUid, node->GetPackageUid() );
       
  1893 	CHECK(err);
       
  1894 #endif
       
  1895 
       
  1896 	// Step 4: Write the BootstrapVersion to resume info file.
       
  1897 	err = WriteIntToConfigFile( outFile, KRFieldBootstrap, iStateMachine.BootstrapVersion() );
       
  1898 	CHECK(err);
       
  1899 
       
  1900 	// Step 5: Write the Wrapper installed drive to resume info file.
       
  1901 	err = WriteIntToConfigFile( outFile, KRFieldWrapperDrive, iStateMachine.iWrapperInstalledDrive );
       
  1902 	CHECK(err);
       
  1903 
       
  1904 	// Step 6: Write the Wrapper Package UID.
       
  1905 	err = WriteIntToConfigFile( outFile, KRFieldWrapperPkgUid, iStateMachine.WrapperPackageUid().iUid );
       
  1906 
       
  1907 	if (err != KErrNone)
       
  1908 		{
       
  1909 failed:
       
  1910 		SLOG3( "Resume info creation failed (%d: %d)", pos, err );
       
  1911 		// Remove the resume info file in error situation as it might not contain
       
  1912 		// all the information needed to continue the installation
       
  1913 		const TInt deleteStatus = iStateMachine.FsSession().Delete(KADMResumeInfoFile);
       
  1914 		SLOG2( "Resume info has been removed (%d)", deleteStatus );
       
  1915 		}
       
  1916 
       
  1917 	if (pos)
       
  1918 		{
       
  1919 		outFile.Close();
       
  1920 		}
       
  1921 
       
  1922 	SLOG2( "- CreateInstallationResumeInfo(): %d", err );
       
  1923 
       
  1924 	return err;
       
  1925 	}
       
  1926 
       
  1927 // -----------------------------------------------------------------------------
       
  1928 // BackupFiles
       
  1929 // In case of failure during the complete installation process,
       
  1930 // backup the required files for future launch.
       
  1931 // -----------------------------------------------------------------------------
       
  1932 //
       
  1933 void TStatePrepareExitWithError::BackupFilesL() const
       
  1934 	{
       
  1935 #if 0
       
  1936 	HBufC* destFileName = NULL;
       
  1937 	TInt err = KErrNone, pos = 0;
       
  1938 
       
  1939 	// Backup the main application sis file to a folder. - Copy to ADM Private folder?!
       
  1940 	TParsePtrC appFileName( *iStateMachine.SisFilename() );
       
  1941 
       
  1942 	destFileName = HBufC::NewLC( appFileName.NameAndExt().Length() + KADMPrivatePath().Length() );
       
  1943 	TPtr nameBufPtr = destFileName->Des();
       
  1944 
       
  1945 	nameBufPtr.Append( KADMPrivatePath );
       
  1946 	nameBufPtr.Append( appFileName.NameAndExt() );
       
  1947 
       
  1948 	// TODO: Do the file copying in AO
       
  1949 	CFileMan* fileMan = CFileMan::NewL( iStateMachine.FsSession() );
       
  1950 	CleanupStack::PushL(fileMan);
       
  1951 	err = fileMan->Copy( *iStateMachine.SisFilename(), *destFileName );
       
  1952 	CleanupStack::PopAndDestroy(fileMan);
       
  1953 
       
  1954 	if (err != KErrNone)
       
  1955 		{
       
  1956 failed:
       
  1957 		CleanupStack::PopAndDestroy(destFileName);
       
  1958 		SLOG3( "Failed to create backup (%d: %d)", pos, err );
       
  1959 		User::Leave(err);
       
  1960 		}
       
  1961 
       
  1962 	// Backup the info. The file is not present yet.
       
  1963 	RFile outFile;
       
  1964 	err = outFile.Replace( iStateMachine.FsSession(), KADMResumeInfoFile, EFileWrite | EFileStreamText | EFileShareAny );
       
  1965 	CHECK(err);
       
  1966 
       
  1967 	// TODO: Backup the depfile in case of Bootstrap version 2 and save the name as well.
       
  1968 
       
  1969 	// Write the AppFilename to resume info file.
       
  1970 	err = WriteToConfigFile( outFile, KAppFileName, destFileName->Des() );
       
  1971 	CHECK(err);
       
  1972 	CleanupStack::PopAndDestroy(); // destFileName
       
  1973 #endif
       
  1974 	// Backup the info. The file is not present yet.
       
  1975 	RFile outFile;
       
  1976 
       
  1977 	// If no resume info file exists, create a new one.
       
  1978 	// In case a resume info file exists, replace the file with a new one.
       
  1979 	// (One resume information file supported at any point of time)
       
  1980 	TInt err = outFile.Replace( iStateMachine.FsSession(), KADMResumeInfoFile, EFileWrite | EFileStreamText | EFileShareAny );
       
  1981 
       
  1982 	if (err != KErrNone)
       
  1983 		{
       
  1984 		goto failed;
       
  1985 		}
       
  1986 
       
  1987 	// TODO: Backup the depfile in case of Bootstrap version 2 and save the name as well.
       
  1988 
       
  1989 	// Write the AppFilename to resume info file.
       
  1990 	err = WriteToConfigFile( outFile, KRFieldAppFileName, iStateMachine.SisFilename()->Des() );
       
  1991 
       
  1992 	if (err != KErrNone)
       
  1993 		{
       
  1994 failed:
       
  1995 		SLOG2( "- BackupFiles(): LEAVE %d", err );
       
  1996 		outFile.Close();
       
  1997 		User::Leave(err);
       
  1998 		}
       
  1999 
       
  2000 	outFile.Close();
       
  2001 	}
       
  2002 
       
  2003 // -----------------------------------------------------------------------------
       
  2004 //
       
  2005 // -----------------------------------------------------------------------------
       
  2006 //
       
  2007 TStateInstallDependency::TStateInstallDependency(const CStateFactory& aFactory) :
       
  2008 	TState(aFactory)
       
  2009 	{
       
  2010 	}
       
  2011 
       
  2012 void TStateInstallDependency::Enter() const
       
  2013 	{
       
  2014 	SLOG3( "Installing '%S' to %c:", iStateMachine.iDownloadedFile, (char)iStateMachine.iCurrentPackage->GetInstallDrive() );
       
  2015 	// Replace the downloading note with installing note
       
  2016 	iStateMachine.ShowInstallingWaitNoteL( iStateMachine.iCounterCurrent, iStateMachine.iCounterMax );
       
  2017 	iStateMachine.StopProgressBar();
       
  2018 
       
  2019 	// TODO: FIX THIS! This is an ugly hack to give time for S60 DlMgr AOs to
       
  2020 	// finish their cleanups. To fix this properly, we need to wait till we get
       
  2021 	// "EHttpDlDeleting" event before starting the installation. This has to be
       
  2022 	// called before CancelAllDownloads(), otherwise DlMgrServer will die in
       
  2023 	// CBase91 PANIC.
       
  2024 	User::After(1000000);
       
  2025 	// We need to remove the download(s) before starting the installation.
       
  2026 	// Otherwise we might get KErrInUse error while installing. This happens
       
  2027 	// quite often when using E: / F: drive as the download drive.
       
  2028 	iStateMachine.iDownloadHandler->CancelAllDownloads();
       
  2029 
       
  2030 	// Wait for the "DlDeleting" event
       
  2031 	iStateMachine.iDlDeletingSemaphore.Wait(KDlDeletingTimeout);
       
  2032 
       
  2033 	iStateMachine.iInstallManager->SilentInstallPackageL(
       
  2034 			*iStateMachine.iDownloadedFile,
       
  2035 			iStateMachine.iCurrentPackage->GetInstallDrive()
       
  2036 		 );
       
  2037 
       
  2038 	iStateMachine.UpdateProgressBar(iStateMachine.iCumulativeDepDownloaded,
       
  2039 			iStateMachine.iProgressMaxValue );
       
  2040 	}
       
  2041 
       
  2042 void TStateInstallDependency::Exit() const
       
  2043 	{
       
  2044 	// Remove the wait note
       
  2045 #if 0
       
  2046 	if ( !iStateMachine.OviStoreRunning() )
       
  2047 		{
       
  2048 		iStateMachine.StopWaitNote();
       
  2049 		}
       
  2050 #endif
       
  2051 	}
       
  2052 
       
  2053 void TStateInstallDependency::InstallCompleted(TInt aStatus)
       
  2054 	{
       
  2055 	LOG_FUNC
       
  2056 
       
  2057 	CPackageInfo *curr = iStateMachine.iDepTree->GetCurrentFetchNode();
       
  2058 	User::LeaveIfNull(curr);
       
  2059 	SLOG3( "Removing '%S%S'", &iStateMachine.iDepTree->GetDownloadPath(), curr->GetSisPackageName() );
       
  2060 
       
  2061 	// Delete the .sis file as its no longer required.
       
  2062 	iStateMachine.iDepTree->DeleteFile( iStateMachine.FsSession(),
       
  2063 					*curr->GetSisPackageName(),
       
  2064 					iStateMachine.iDepTree->GetDownloadPath()
       
  2065 					);
       
  2066 	if (aStatus == KErrNone)
       
  2067 		{
       
  2068 		if (curr->GetPackageStatus() == EPackageToBeFetched )
       
  2069 			{
       
  2070 			curr->SetPackageStatus(EPackageFetchedInstalled);
       
  2071 			}
       
  2072 		else if (curr->GetPackageStatus() == EPackageRootToBeInstalled )
       
  2073 			{
       
  2074 			curr->SetPackageStatus(EPackageRootInstalled);
       
  2075 			}
       
  2076 		else
       
  2077 			{
       
  2078 			SLOG2( "Unexpected package status %d", curr->GetPackageStatus() );
       
  2079 			}
       
  2080 
       
  2081 		// Dependency package succesfully installed, update the counter to keep UI happy
       
  2082 		iStateMachine.iCounterCurrent++;
       
  2083 		// Download the next dependency
       
  2084 		iStateMachine.SetState( CStateFactory::EStateDownloadDependency );
       
  2085 		}
       
  2086 	else
       
  2087 		{
       
  2088 		SLOG2( "Dependency installation failed %d", aStatus );
       
  2089 		iStateMachine.SetFailureReason( EInstallationFailed );
       
  2090 		iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError );
       
  2091 		}
       
  2092 	}
       
  2093 
       
  2094 // -----------------------------------------------------------------------------
       
  2095 //
       
  2096 // -----------------------------------------------------------------------------
       
  2097 //
       
  2098 TStateInstallAppSis::TStateInstallAppSis(const CStateFactory& aFactory) :
       
  2099 	TState(aFactory)
       
  2100 	{
       
  2101 	}
       
  2102 
       
  2103 void TStateInstallAppSis::Enter() const
       
  2104 	{
       
  2105 	// We need to find the root package
       
  2106 	if (iStateMachine.iCurrentPackage == NULL)
       
  2107 		{
       
  2108 		SLOG( "Finding root package" );
       
  2109 		CPackageInfo* package = NULL;
       
  2110 		while ( (package = iStateMachine.iDepTree->GetNextFetchNode()) != NULL )
       
  2111 			{
       
  2112 			if (package->GetPackageStatus() == EPackageRootToBeInstalled)
       
  2113 				{
       
  2114 				SLOG3( "Root: UID 0x%08X, '%S'", package->GetPackageUid(), package->GetPackageName() );
       
  2115 				break;
       
  2116 				}
       
  2117 			}
       
  2118 		iStateMachine.iCurrentPackage = package;
       
  2119 		}
       
  2120 	// iStateMachine.iCurrentPackage should now point to a correct packege,
       
  2121 	// the application.sis, in this case. Just make sure, it really does that.
       
  2122 	// Do we have a package set?
       
  2123 	if ( iStateMachine.iCurrentPackage )
       
  2124 		{
       
  2125 		if ( iStateMachine.BootstrapVersion() == 3 )
       
  2126 			{
       
  2127 /*
       
  2128 			SLOG( "Uninstalling smartinstaller (bootstrap)" );
       
  2129 			TInt err = iStateMachine.iInstallManager->SilentUnInstallPackage(
       
  2130 					iStateMachine.WrapperPackageUid() );
       
  2131 			SLOG2( "Uninstall status: %d", err);
       
  2132 */
       
  2133 			// Delete the dependency file that was provided with the wrapper
       
  2134 			// TODO: Remove if(), DeleteFile() copes with NULL filenames.
       
  2135 			if ( iStateMachine.DepFilename() )
       
  2136 				{
       
  2137 				iStateMachine.iAppUi.DeleteFile( *iStateMachine.DepFilename() );
       
  2138 				}
       
  2139 
       
  2140 #ifdef FEATURE_LAUNCH_INSTALLED_APP
       
  2141 			SLOG( "Dependencies and application are installed, ready to launch!" );
       
  2142 			iStateMachine.SetState( CStateFactory::EStateLaunchApp );
       
  2143 #else
       
  2144 			SLOG( "Dependencies and application are installed, ready to exit!" );
       
  2145 			iStateMachine.SetState( CStateFactory::EStateExit );
       
  2146 #endif
       
  2147 			}
       
  2148 		else
       
  2149 			{
       
  2150 			SLOG3( "* Installing AppSis 0x%08x '%S'", iStateMachine.iCurrentPackage->GetPackageUid(), iStateMachine.SisFilename() );
       
  2151 
       
  2152 			// TODO: Leave or not to leave?
       
  2153 			//User::LeaveIfNull( iStateMachine.SisFilename() );
       
  2154 
       
  2155 			// Update the progress bar
       
  2156 			iStateMachine.UpdateProgressBar( iStateMachine.iProgressMaxValue,
       
  2157 				iStateMachine.iProgressMaxValue );
       
  2158 
       
  2159 			//First try silent install - if package is self-signed, this will fail
       
  2160 			//according to policy, so retry with a normal install.
       
  2161 
       
  2162 			//User might not have been prompted for drive selection.
       
  2163 			//In that case, it is ok to prompt for drive selection as part of the Wrapper Package Installation.
       
  2164 			//This will be the case when files are injected into the Bootstrap import folder and not in a common "?:/ADM" drive.
       
  2165 
       
  2166 			TChar installDrive = iStateMachine.SisFilename()->Des()[0];
       
  2167 			installDrive.UpperCase();
       
  2168 			if (installDrive < 'A' || installDrive > 'Z')
       
  2169 				{
       
  2170 				installDrive = KNoDriveSelected;
       
  2171 				}
       
  2172 
       
  2173 			// If the wrapper installed drive is not selected, use the application.sis
       
  2174 			// destination drive as the installed drive. This way the developer can
       
  2175 			// control, if he/she wants to prompt the installation drive or force it
       
  2176 			// already in the wrapper/installer .pkg file. This can be controlled
       
  2177 			// by using '!' as the destination drive (=prompt) or by using a fixed
       
  2178 			// drive letter A->Z (=don't prompt).
       
  2179 			if ( iStateMachine.iWrapperInstalledDrive == KNoDriveSelected )
       
  2180 				{
       
  2181 				iStateMachine.iWrapperInstalledDrive = installDrive;
       
  2182 				}
       
  2183 
       
  2184 			if ( iStateMachine.iWrapperInstalledDrive != KNoDriveSelected )
       
  2185 				{
       
  2186 				SLOG3( "Installing AppSis '%S' to %c:", iStateMachine.SisFilename(), (char)iStateMachine.iWrapperInstalledDrive );
       
  2187 
       
  2188 				// First show the wait note and then remove progress bar.
       
  2189 				// MUCH less flicker this way.
       
  2190 				iStateMachine.ShowWaitNoteL( R_ADM_FINALIZING_INSTALLATION_WAIT_TEXT );
       
  2191 				iStateMachine.StopProgressBar();
       
  2192 				iStateMachine.iInstallManager->SilentInstallPackageL( *iStateMachine.SisFilename(), iStateMachine.iWrapperInstalledDrive );
       
  2193 				}
       
  2194 			else
       
  2195 				{
       
  2196 				SLOG( "! No installation drive selected, prompting" );
       
  2197 				// User will be prompted for the drive.
       
  2198 
       
  2199 				//TODO: This is a hack. Change the Installcompleted logic to accomodate this.
       
  2200 				iStateMachine.StopWaitNote();
       
  2201 				iStateMachine.StopProgressBar();
       
  2202 				TInt aStatus = iStateMachine.iInstallManager->
       
  2203 						InstallPackage( *iStateMachine.SisFilename() );
       
  2204 				iStateMachine.SetNonSilentInstallation(ETrue);
       
  2205 				iStateMachine.HandleInstallCompletedL( aStatus );
       
  2206 				}
       
  2207 			} // if
       
  2208 		}
       
  2209 	else
       
  2210 		{
       
  2211 		// Hmm. We should've had a root package, but apparently we didn't. Odd.
       
  2212 		SLOG( "! Unexpected root package. PANIC" );
       
  2213 		PanicInState(EPanicStateUnexpectedRootPackage);
       
  2214 		}
       
  2215 	}
       
  2216 
       
  2217 void TStateInstallAppSis::InstallCompleted(TInt aStatus)
       
  2218 	{
       
  2219 	LOG_FUNC
       
  2220 
       
  2221 	//It is possible for silent installation of the main app to fail due to insufficient memory
       
  2222 	//TODO: would it be wise to move the below conditions to InstallManager and have some different error returned to statemachine?
       
  2223 
       
  2224 	if ( ( aStatus == SwiUI::KSWInstErrSecurityFailure ) || ( aStatus == SwiUI::KSWInstErrInsufficientMemory ) )
       
  2225 		{
       
  2226 		// We have a wait note displayed. If silent install failed,
       
  2227 		// it needs to be removed so the installer UI won't be affected.
       
  2228 		iStateMachine.StopWaitNote();
       
  2229 
       
  2230 		//SwiUI collapses the real error, Swi::ESignatureSelfSigned is what we should
       
  2231 		//be checking here. SwiUI::GetLastErrorL is not implemented
       
  2232 		//If the silent install fails, because of a self signed package, try again
       
  2233 		//with interactive install.
       
  2234 		// This is a synchronous call which returns the control here after
       
  2235 		// installation is finished (or cancelled, or an error occurs or..)
       
  2236 		aStatus = iStateMachine.iInstallManager->InstallPackage(
       
  2237 				*iStateMachine.SisFilename() );
       
  2238 		iStateMachine.SetNonSilentInstallation(ETrue);
       
  2239 		}
       
  2240 	else if ( aStatus == KErrNone )
       
  2241 		{
       
  2242 		// We end up here, if the silent installation completes succesfully
       
  2243 		iStateMachine.SetSilentInstallationOk(ETrue);
       
  2244 		}
       
  2245 	// Was installation succesful?
       
  2246 	if (aStatus == KErrNone)
       
  2247 		{
       
  2248 		CPackageInfo *curr = iStateMachine.iDepTree->GetCurrentFetchNode();
       
  2249 		User::LeaveIfNull(curr);
       
  2250 		//TODO: What if root package is set in HandleInstallComplete!!!
       
  2251 		// The next if should _always_ be true here
       
  2252 		if ( curr->GetPackageStatus() == EPackageRootToBeInstalled )
       
  2253 			{
       
  2254 			curr->SetPackageStatus(EPackageRootInstalled);
       
  2255 			}
       
  2256 		else if ( curr->GetPackageStatus() != EPackageRootInstalled )
       
  2257 			{
       
  2258 			SLOG2( "! Invalid root package status %d", curr->GetPackageStatus() );
       
  2259 			}
       
  2260 
       
  2261 		CPackageInfo* fetchPackage = iStateMachine.iDepTree->GetNextFetchNode();
       
  2262 
       
  2263 		// TODO: This is duplicated code from TStateDownloadDependency
       
  2264 		if ( !fetchPackage )
       
  2265 			{
       
  2266 /*
       
  2267 			//end of list - we're finished
       
  2268 			SLOG( "Uninstalling wrapper" );
       
  2269 			TInt err = iStateMachine.iInstallManager->SilentUnInstallPackage(
       
  2270 					iStateMachine.WrapperPackageUid() );
       
  2271 			SLOG2( "Uninstall status: %d", err);
       
  2272 			// Wrapper has been uninstalled, ready to exit
       
  2273 */
       
  2274 #ifdef FEATURE_LAUNCH_INSTALLED_APP
       
  2275 			iStateMachine.SetState( CStateFactory::EStateLaunchApp );
       
  2276 #else
       
  2277 			iStateMachine.SetState( CStateFactory::EStateExit );
       
  2278 #endif
       
  2279 			return;
       
  2280 			}
       
  2281 		else
       
  2282 			{
       
  2283 			// We should be at the end of the list, but seems that we're not.
       
  2284 			SLOG2( "! Unexpected package 0x%08X. PANIC", fetchPackage->GetPackageUid() );
       
  2285 			PanicInState(EPanicStateUnexpectedPackage);
       
  2286 			}
       
  2287 		}
       
  2288 	else
       
  2289 		{
       
  2290 		const TExitReason reason = (aStatus == SwiUI::KSWInstErrUserCancel)
       
  2291 				? EUserCancelled
       
  2292 				: EInstallationFailed;
       
  2293 		iStateMachine.SetFailureReason( reason );
       
  2294 		iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError );
       
  2295 		}
       
  2296 	}
       
  2297 
       
  2298 // -----------------------------------------------------------------------------
       
  2299 // Confirms the user to continue the download when download threshold is exceeded
       
  2300 // -----------------------------------------------------------------------------
       
  2301 //
       
  2302 TStateConfirmDownload::TStateConfirmDownload(const CStateFactory& aFactory) :
       
  2303 	TState(aFactory)
       
  2304 	{
       
  2305 	}
       
  2306 
       
  2307 void TStateConfirmDownload::Enter() const
       
  2308 	{
       
  2309 	// Show download query as we are roaming
       
  2310 	iStateMachine.ShowDownloadQueryL( R_ADM_DL_PROMPT_TEXT );
       
  2311 	// the next state will get invoked by the user reply to the query
       
  2312 	}
       
  2313 
       
  2314 void TStateConfirmDownload::UserAccepted()
       
  2315 	{
       
  2316 	// This is called when the user has selected "Yes" in the confirmation query
       
  2317 	iStateMachine.SetState( CStateFactory::EStateStartDependencyDownload );
       
  2318 	}
       
  2319 
       
  2320 // -----------------------------------------------------------------------------
       
  2321 // Confirms the user to continue the download if device is roaming
       
  2322 // -----------------------------------------------------------------------------
       
  2323 //
       
  2324 TStateConfirmRoamingDownload::TStateConfirmRoamingDownload(const CStateFactory& aFactory) :
       
  2325 	TState(aFactory)
       
  2326 	{
       
  2327 	}
       
  2328 
       
  2329 void TStateConfirmRoamingDownload::Enter() const
       
  2330 	{
       
  2331 	// Show download query as we are roaming
       
  2332 	iStateMachine.ShowDownloadQueryL( R_ADM_DL_PROMPT_TEXT, R_ADM_ROAMING_TEXT );
       
  2333 	// the next state will get invoked by the user reply to the query
       
  2334 	}
       
  2335 
       
  2336 void TStateConfirmRoamingDownload::UserAccepted()
       
  2337 	{
       
  2338 	// This is called when the user has selected "Yes" in the confirmation query
       
  2339 	iStateMachine.SetState( CStateFactory::EStateStartDependencyDownload );
       
  2340 	}