/*
* Copyright (c) 2004-2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
#include "uninstallmachine.h"
#include "uninstallationplanner.h"
#include "uninstallationprocessor.h"
#include "log.h"
#include "sisregistrypackage.h"
#include "sisregistryentry.h"
#include "sisregistrysession.h"
#include "plan.h"
#include "swispubsubdefs.h"
#include <s32mem.h>
using namespace Swi;
//
// TUninstallState
//
CUninstallMachine::TUninstallState::TUninstallState(CUninstallMachine& aUninstallMachine)
: iUninstallMachine(aUninstallMachine)
{
}
//
// TRegistrationState
//
CUninstallMachine::TRegistrationState::TRegistrationState(
CUninstallMachine& aUninstallMachine)
/**
Constructor.
*/
: CUninstallMachine::TUninstallState(aUninstallMachine)
{
}
void CUninstallMachine::TRegistrationState::EnterL()
/**
Send registration request to the SWI Observer and then activate the
installation machine.
*/
{
DEBUG_PRINTF(_L8("Uninstall Machine - Entering Registration State"));
//connect to the SWI Observer
User::LeaveIfError(iUninstallMachine.Observer().Connect());
//Register to the SWI Observer; which completes this request
//when the SWI Observer Processor is idle.
iUninstallMachine.Observer().Register(iUninstallMachine.iStatus);
iUninstallMachine.SetActive();
}
CUninstallMachine::TState* CUninstallMachine::TRegistrationState::CompleteL()
/**
Obtains the log file handle and its name from the SWI Observer.
Adds the log file to the transaction
*/
{
DEBUG_PRINTF(_L8("Uninstall Machine - Registration State complete"));
RBuf logFileName;
logFileName.CreateL(KMaxFileName);
logFileName.CleanupClosePushL();
//Get created a log file and obtains its full name.
iUninstallMachine.Observer().GetFileHandleL(logFileName);
//Add the log file to the transaction
#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
iUninstallMachine.TransactionSession().RegisterNewL(logFileName);
#else
iUninstallMachine.IntegrityServicesL().AddL(logFileName);
#endif
CleanupStack::PopAndDestroy(&logFileName);
// Get Controllers.
return static_cast<TState*>(&iUninstallMachine.iConfirmationState);
}
CUninstallMachine::TState* CUninstallMachine::TRegistrationState::ErrorL(TInt aCode)
/**
If there is any error, closes the SWI Observer connection.
*/
{
DEBUG_PRINTF2(_L8("Uninstall Machine - Registration State failed with code '%d'"), aCode);
User::Leave(aCode);
return NULL;
}
void CUninstallMachine::TRegistrationState::Cancel()
/**
Cancels the registration request.
*/
{
DEBUG_PRINTF(_L8("Uninstall Machine - Registration State cancelled!"));
iUninstallMachine.Observer().CancelRegistration();
}
//
// TConfirmationState
//
CUninstallMachine::TConfirmationState::TConfirmationState(
CUninstallMachine& aUninstallMachine)
: CUninstallMachine::TUninstallState(aUninstallMachine)
{
}
// Calls Uninstall dialog.
void CUninstallMachine::TConfirmationState::EnterL()
{
DEBUG_PRINTF(_L8("Uninstall Machine - Entering Confirmation State"));
// Construct a TAppInfo object for the dialog. For that we need app name,
// vendor name, and version. The first two are already supplied in the
// \e iPackage member which is a pointer to CSisRegistryPackage object.
// Getting package version involves more work.
#ifndef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
RSisRegistrySession regSession;
User::LeaveIfError(regSession.Connect());
CleanupClosePushL(regSession);
#endif
RSisRegistryEntry regEntry;
#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
User::LeaveIfError(regEntry.OpenL(iUninstallMachine.RegistryWrapper().RegistrySession(), *iUninstallMachine.iPackage));
#else
User::LeaveIfError(regEntry.OpenL(regSession, *iUninstallMachine.iPackage));
#endif
CleanupClosePushL(regEntry);
TVersion ver=regEntry.VersionL();
HBufC* localizedVendorName=regEntry.LocalizedVendorNameL();
CleanupStack::PushL(localizedVendorName);
// At last we have everything to construct TAppInfo object.
TAppInfo appInfo(iUninstallMachine.iPackage->Name(),
*localizedVendorName,ver);
// Construct and execute uninstall dialog command.
CDisplayUninstall* cmd=CDisplayUninstall::NewLC(appInfo);
iUninstallMachine.UiHandler().ExecuteL(*cmd);
TBool rv=cmd->ReturnResult();
CleanupStack::PopAndDestroy(cmd);
#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
CleanupStack::PopAndDestroy(2, ®Entry); // regEntry, localizedVendorName
#else
CleanupStack::PopAndDestroy(3, ®Session); // regEntry, localizedVendorName
#endif
// Make the decision and leave if the user cancelled uninstallation.
if (!rv)
User::Leave(KErrCancel);
// Continue uninstallation.
iUninstallMachine.CompleteSelf();
iUninstallMachine.SetActive();
}
// The next state will be planning uninstallation.
CUninstallMachine::TState* CUninstallMachine::TConfirmationState::CompleteL()
{
DEBUG_PRINTF(_L8("Uninstall Machine - Completed Confirmation State"));
return static_cast<TState*>(&iUninstallMachine.iPlanUninstallationState);
}
CUninstallMachine::TState* CUninstallMachine::TConfirmationState::ErrorL(
TInt aCode)
{
DEBUG_PRINTF2(_L8("Uninstall Machine - Confimation State failed with code %d"), aCode);
User::Leave(aCode);
return NULL;
}
void CUninstallMachine::TConfirmationState::Cancel()
{
}
//
// TPlanUninstallationState
//
CUninstallMachine::TPlanUninstallationState::TPlanUninstallationState(CUninstallMachine& aUninstallMachine)
: CUninstallMachine::TUninstallState(aUninstallMachine)
{
}
void CUninstallMachine::TPlanUninstallationState::EnterL()
{
DEBUG_PRINTF(_L8("Uninstall Machine - Entering Uninstallation Planning State"));
// Create result.
iUninstallMachine.iResult=CInstallationResult::NewL();
// Call uninstallation planner and plan the uninstallation
iUninstallMachine.iPlanner=CUninstallationPlanner::NewL(
iUninstallMachine.UiHandler(), *iUninstallMachine.iResult);
// The following function may leave either because of an error or because
// the user cancelled uninstallation (a dialog), in which case it notifies
// the UI sothat we don't need to display anything (cancellation is not an
// error). See RunError() for more details.
iUninstallMachine.iPlanner->PlanUninstallationL(*iUninstallMachine.iPackage);
TInt finalProgressBarValue = iUninstallMachine.iPlanner->FinalProgressBarValue();
iUninstallMachine.SetFinalProgressBarValue(finalProgressBarValue);
iUninstallMachine.iPlan=iUninstallMachine.iPlanner->TransferPlanOwnership();
iUninstallMachine.CompleteSelf();
iUninstallMachine.SetActive();
}
// The next state will be interfacing with transaction support
CUninstallMachine::TState* CUninstallMachine::TPlanUninstallationState::CompleteL()
{
DEBUG_PRINTF(_L8("Uninstall Machine - Completed Uninstallation Planning State"));
// The user hasn't cancelled so mark the un-installation as confirmed. This
// will allow the registry cache to be regenerated further on during the
// un-installation process.
iUninstallMachine.iOperationConfirmed = ETrue;
return static_cast<TState*>(&iUninstallMachine.iIntegritySupportState);
}
CUninstallMachine::TState* CUninstallMachine::TPlanUninstallationState::ErrorL(TInt aCode)
{
DEBUG_PRINTF2(_L8("Uninstall Machine - Uninstallation Planning State failed with code %d"), aCode);
User::Leave(aCode);
return NULL;
}
void CUninstallMachine::TPlanUninstallationState::Cancel()
{
}
//
// TIntegritySupportState
//
CUninstallMachine::TIntegritySupportState::TIntegritySupportState(
CUninstallMachine& aUninstallMachine)
: CUninstallMachine::TUninstallState(aUninstallMachine)
{
}
void CUninstallMachine::TIntegritySupportState::EnterL()
{
DEBUG_PRINTF(_L8("Uninstall Machine - Entering Integrity Support State"));
// create a processor
iUninstallMachine.iProcessor = CUninstallationProcessor::NewL(
*iUninstallMachine.iPlan, iUninstallMachine.UiHandler(),
#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
iUninstallMachine.TransactionSession(), iUninstallMachine.RegistryWrapper(),
#else
iUninstallMachine.IntegrityServicesL(),
#endif
iUninstallMachine.Observer());
// execute the plan install files, update registry, all in one step
iUninstallMachine.iProcessor->ProcessPlanL(iUninstallMachine.iStatus);
//run the RBS executables , before entering the processor state.
iUninstallMachine.iProcessor->RunBeforeShutdown();
iUninstallMachine.SetActive();
}
CUninstallMachine::TState*
CUninstallMachine::TIntegritySupportState::CompleteL()
{
DEBUG_PRINTF(_L8("Uninstall Machine - Completed Integrity Support State"));
return static_cast<TState*>(&iUninstallMachine.iFinalState);
}
CUninstallMachine::TState* CUninstallMachine::TIntegritySupportState::ErrorL(
TInt aCode)
{
DEBUG_PRINTF2(_L8("Uninstall Machine - Integrity Support State failed with code %d"), aCode);
User::Leave(aCode);
return NULL;
}
void CUninstallMachine::TIntegritySupportState::Cancel()
{
}
//
// TFinalState
//
CUninstallMachine::TFinalState::TFinalState(
CUninstallMachine& aUninstallMachine)
: CUninstallMachine::TUninstallState(aUninstallMachine)
{
}
void CUninstallMachine::TFinalState::EnterL()
{
DEBUG_PRINTF(_L8("Uninstall Machine - Entering Final State"));
TUid pubsubCategory;
pubsubCategory.iUid = KUidSystemCategoryValue;
TInt err = RProperty::Set(pubsubCategory, KUidSoftwareInstallKey, ESwisStatusSuccess | ESwisUninstall);
User::LeaveIfError(err);
iUninstallMachine.CompleteSelf();
iUninstallMachine.SetActive();
}
CUninstallMachine::TState* CUninstallMachine::TFinalState::CompleteL()
{
DEBUG_PRINTF(_L8("Uninstall Machine - Completed Final State"));
return NULL;
}
CUninstallMachine::TState* CUninstallMachine::TFinalState::ErrorL(
TInt aCode)
{
DEBUG_PRINTF2(_L8("Uninstall Machine - Final State failed with code %d"), aCode);
User::Leave(aCode);
return NULL;
}
void CUninstallMachine::TFinalState::Cancel()
{
}
//
// CUninstallMachine
//
// Constructor, sets this pointer into the state objects
CUninstallMachine::CUninstallMachine(const RMessage2& aMessage)
: CSwisStateMachine(aMessage),
iRegistrationState(*this),
iConfirmationState(*this),
iPlanUninstallationState(*this),
iIntegritySupportState(*this),
iFinalState(*this)
{
}
void CUninstallMachine::ConstructL()
{
DEBUG_PRINTF(_L8("Constructing new Uninstall Machine"));
// Call base class' ConstructL() which inits transaction service
CSwisStateMachine::ConstructL();
TInt length=Message().GetDesLengthL(0);
HBufC8* packageBuffer=HBufC8::NewMaxLC(length);
TPtr8 p=packageBuffer->Des();
Message().ReadL(0, p);
RMemReadStream readStream;
readStream.Open(p.Ptr(), length);
CleanupClosePushL(readStream);
iPackage=CSisRegistryPackage::NewL(readStream);
CleanupStack::PopAndDestroy(2, packageBuffer);
}
/*static*/ CUninstallMachine* CUninstallMachine::NewL(const RMessage2& aMessage)
{
CUninstallMachine* self=new(ELeave) CUninstallMachine(aMessage);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self);
return self;
}
TInt CUninstallMachine::Start()
{
DEBUG_PRINTF(_L8("Starting Uninstall"));
return CSwisStateMachine::Start();
}
// Delete objects, close connection to the servers
CUninstallMachine::~CUninstallMachine()
{
DEBUG_PRINTF(_L8("Destroying Uninstall Machine"));
delete iPlan;
delete iPlanner;
delete iResult;
delete iProcessor;
delete iPackage;
}
CUninstallMachine::TState* CUninstallMachine::FirstState()
{
return &iRegistrationState;
}
// This is called from RunL() whenever a state leaves
CUninstallMachine::TState* CUninstallMachine::ErrorOnStateEntryL(TInt aError)
{
return CurrentState()->ErrorL(aError);
}
void CUninstallMachine::SignalCompletedL()
{
HandleInstallationEventL(iPlan, EEventCompletedUnInstall);
}