--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/installationservices/refswinstallationplugin/source/sifrefinstallertask.cpp Fri Mar 19 09:33:35 2010 +0200
@@ -0,0 +1,1015 @@
+/*
+* Copyright (c) 2008-2009 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:
+* This file implements Reference Install tasks for getting ComponentInfo, installation, uninstallation and activation/deactivation.
+*
+*/
+
+
+#include "sifrefinstallertask.h"
+#include "sifrefbinpkgextractor.h"
+#include "usiflog.h"
+#include <usif/usiferror.h>
+
+using namespace Usif;
+
+_LIT(KRefInstPrivateDir, "c:\\private\\1028634e\\");
+
+/**
+A set of helper functions for Reference Installer tasks.
+*/
+namespace InstallHelper
+ {
+ _LIT(KSifReferenceSoftwareType, "reference");
+ _LIT(KUiConfirmationQuestion, "Are you sure you want to %S component: %S, vendor: %S");
+ _LIT(KParamNameErrDesc, "Error Description");
+ _LIT(KErrFileAlreadyExists, "File already exists: ");
+ _LIT(KUiConfirmationTypeInstall, "install");
+ _LIT(KUiConfirmationTypeUpgrade, "upgrade");
+ _LIT(KUiConfirmationTypeUninstall, "uninstall");
+ _LIT(KUiParserErrorDesc, "Installer encountered a problem when parsing a package file.");
+ const TInt KMaxConfirmationTypeLengh = KUiConfirmationTypeUninstall.iTypeLength;
+
+ // This Reference Installer uses Component Name and Vendor Name in order to
+ // identify a component in the SCR database. This identification scheme doesn't provide
+ // unique ids and its results depend on the current language. Hence, a real installer
+ // must use the Unique Id mechanism provided by the SCR.
+ void FindComponentL(RSoftwareComponentRegistry& aScr, TComponentSearchData& aCompSearchData, const CSifRefPkgParser& aParser)
+ {
+ DEBUG_PRINTF(_L8("InstallHelper::FindComponentL()"));
+
+ // Get the index of the current language
+ const TLanguage curLang = User::Language();
+ TInt langIndex = aParser.GetLanguageIndex(curLang);
+ if (langIndex == KErrNotFound)
+ {
+ ASSERT(aParser.Languages().Count() > 0); // The parser should have already rejected packages without languages
+ langIndex = 0;
+ }
+
+ // Data for CComponentInfo
+ aCompSearchData.iName = aParser.ComponentNames()[langIndex];
+ aCompSearchData.iVersion = aParser.Version().Name();
+ aCompSearchData.iVendor = aParser.VendorNames()[langIndex];
+ aCompSearchData.iScomoState = EDeactivated;
+ aCompSearchData.iInstallStatus = ENewComponent;
+ aCompSearchData.iComponentId = 0;
+
+ RSoftwareComponentRegistryView scrView;
+ CComponentFilter* filter = CComponentFilter::NewLC();
+ filter->SetNameL(*aCompSearchData.iName);
+ filter->SetVendorL(*aCompSearchData.iVendor);
+ filter->SetSoftwareTypeL(KSifReferenceSoftwareType);
+
+ scrView.OpenViewL(aScr, filter);
+ CleanupClosePushL(scrView);
+
+ // Iterate over matching components in order to determine the status of the package being processed.
+ CComponentEntry* component = NULL;
+ while ((component = scrView.NextComponentL()) != NULL)
+ {
+ const TDesC& installedVersion = component->Version();
+ const TInt cmp = RSoftwareComponentRegistry::CompareVersionsL(installedVersion, aCompSearchData.iVersion);
+ if (cmp > 0)
+ {
+ aCompSearchData.iInstallStatus = ENewerVersionAlreadyInstalled;
+ aCompSearchData.iScomoState = component->ScomoState();
+ aCompSearchData.iComponentId = component->ComponentId();
+ delete component;
+ break;
+ }
+ else if (cmp == 0 && aCompSearchData.iInstallStatus < EAlreadyInstalled)
+ {
+ aCompSearchData.iInstallStatus = EAlreadyInstalled;
+ aCompSearchData.iScomoState = component->ScomoState();
+ aCompSearchData.iComponentId = component->ComponentId();
+ }
+ else if (cmp < 0 && aCompSearchData.iInstallStatus < EUpgrade)
+ {
+ aCompSearchData.iInstallStatus = EUpgrade;
+ aCompSearchData.iScomoState = component->ScomoState();
+ aCompSearchData.iComponentId = component->ComponentId();
+ }
+ delete component;
+ }
+ CleanupStack::PopAndDestroy(2, filter);
+ }
+
+ TBool UnregisterAndDeleteFileL(RSoftwareComponentRegistry& aScr, RSoftwareComponentRegistryFilesList& aFileList, RStsSession& aSts, TComponentId aComponentId)
+ {
+ DEBUG_PRINTF(_L8("InstallHelper::UnregisterAndDeleteFileL()"));
+
+ // Get next file
+ HBufC* file = aFileList.NextFileL();
+ if (file != NULL)
+ {
+ // and remove it from the file system
+ CleanupStack::PushL(file);
+ aSts.RemoveL(*file);
+ CleanupStack::PopAndDestroy(file);
+ }
+ else
+ {
+ // Remove the component from the SCR if there are no files left
+ aFileList.Close();
+ aScr.DeleteComponentL(aComponentId);
+
+ // Copying complete
+ return ETrue;
+ }
+
+ // Copying in progress
+ return EFalse;
+ }
+
+ MInstallerUIHandler* CreateUiHandlerL(const COpaqueNamedParams* aCustomArguments, TInstallerUIHandlerFactory aUiHandlerFactory)
+ {
+ DEBUG_PRINTF(_L8("InstallHelper::CreateUiHandlerL()"));
+
+ // Instantiate a UI handler for non-silent requests
+ if (aCustomArguments != NULL)
+ {
+ TInt silent = EFalse;
+ aCustomArguments->GetIntByNameL(_L("Silent"), silent);
+ if (silent)
+ {
+ return NULL;
+ }
+ }
+
+ return aUiHandlerFactory();
+ }
+
+ enum TConfirmationType
+ {
+ EConfirmationInstall,
+ EConfirmationUpgrade,
+ EConfirmationUninstall
+ };
+
+ void userConfirmationL(TConfirmationType aType, MInstallerUIHandler& uiHandler, const TDesC& aComponent, const TDesC& aVendor)
+ {
+ DEBUG_PRINTF(_L8("InstallHelper::userConfirmationL()"));
+
+ const TInt maxLen = KUiConfirmationQuestion.iTypeLength + KMaxConfirmationTypeLengh + aComponent.Length() + aVendor.Length();
+ HBufC* info = HBufC::NewLC(maxLen);
+ TPtr bufInfo(info->Des());
+
+ switch (aType)
+ {
+ case EConfirmationInstall:
+ bufInfo.Format(KUiConfirmationQuestion, &KUiConfirmationTypeInstall, &aComponent, &aVendor);
+ break;
+
+ case EConfirmationUpgrade:
+ bufInfo.Format(KUiConfirmationQuestion, &KUiConfirmationTypeUpgrade, &aComponent, &aVendor);
+ break;
+
+ case EConfirmationUninstall:
+ bufInfo.Format(KUiConfirmationQuestion, &KUiConfirmationTypeUninstall, &aComponent, &aVendor);
+ break;
+
+ default:
+ User::Leave(KErrArgument);
+ }
+
+ if (!uiHandler.ConfirmationUIHandler(*info))
+ {
+ User::Leave(KErrCancel);
+ }
+
+ CleanupStack::PopAndDestroy(info);
+ }
+ }
+
+// =============================================================================================================
+
+CSifRefGetComponentInfoTask* CSifRefGetComponentInfoTask::NewL(TTransportTaskParams& aParams)
+ {
+ DEBUG_PRINTF(_L8("CSifRefGetComponentInfoTask::NewL()"));
+
+ // Validate the arguments first.
+ if ((aParams.iFileName == NULL && aParams.iFileHandle == NULL) || aParams.iComponentInfo == NULL)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ CSifRefGetComponentInfoTask* self = new (ELeave) CSifRefGetComponentInfoTask(aParams);
+ return self;
+ }
+
+CSifRefGetComponentInfoTask::CSifRefGetComponentInfoTask(TTransportTaskParams& aParams)
+: CSifTransportTask(aParams, EFalse), iStep(EExtractEmbeddedPkgs)
+ {
+ }
+
+CSifRefGetComponentInfoTask::~CSifRefGetComponentInfoTask()
+ {
+ DEBUG_PRINTF(_L8("CSifRefGetComponentInfoTask::~CSifRefGetComponentInfoTask()"));
+
+ iFile.Close();
+ iFs.Close();
+ iScr.Close();
+ iSts.Close();
+ iEmbeddedComponents.Close();
+ if (iSifRequestInProgress)
+ {
+ iSif.CancelOperation();
+ }
+ iSif.Close();
+ delete iParser;
+ delete iComponentInfo;
+ }
+
+TBool CSifRefGetComponentInfoTask::ExecuteImplL()
+ {
+ DEBUG_PRINTF2(_L8("Exiting from CSifRefGetComponentInfoTask::ExecuteImplL(), iStep = %d"), iStep);
+
+ TBool done = EFalse;
+
+ switch (iStep)
+ {
+ case EExtractEmbeddedPkgs:
+ ExtractEmbeddedPkgsL();
+ ++iStep;
+ break;
+
+ case EParsePkgFile:
+ iStep = ParsePkgFileL();
+ break;
+
+ case EFindComponent:
+ InstallHelper::FindComponentL(iScr, iCompSearchData, *iParser);
+ ++iStep;
+ break;
+
+ case ECreateComponentInfoNode:
+ iStep = CreateComponentInfoNodeL();
+ break;
+
+ case ESetComponentInfo:
+ SetComponentInfoL();
+ done = ETrue;
+ break;
+
+ default:
+ User::Leave(KErrGeneral);
+ }
+
+ if (!iSifRequestInProgress)
+ {
+ TRequestStatus* status(RequestStatus());
+ User::RequestComplete(status, KErrNone);
+ }
+
+ DEBUG_PRINTF3(_L8("Exiting from CSifRefGetComponentInfoTask::ExecuteImplL(), done = %d, iStep = %d"), done, iStep);
+
+ return done;
+ }
+
+void CSifRefGetComponentInfoTask::ExtractEmbeddedPkgsL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefGetComponentInfoTask::ExtractEmbeddedPkgsL()"));
+
+ // Start an STS transaction. The extraction of a package requires creation of temporary
+ // files that must be deleted when the GetComponentInfo requiest is complete. This is why
+ // we need this STS transaction here.
+ iSts.CreateTransactionL();
+
+ if (FileName())
+ {
+ SifRefBinPkgExtractor::BuildPkgTreeL(iSts, *FileName(), KRefInstPrivateDir, iEmbeddedComponents);
+ }
+ else if (FileHandle())
+ {
+ SifRefBinPkgExtractor::BuildPkgTreeL(iSts, *FileHandle(), KRefInstPrivateDir, iEmbeddedComponents);
+ }
+ else
+ {
+ ASSERT(0);
+ }
+
+ // Connect to the SCR. The installer needs this session to check if a component being queried
+ // is already installed and, if yes, obtain its detials.
+ User::LeaveIfError(iScr.Connect());
+ }
+
+TInt CSifRefGetComponentInfoTask::ParsePkgFileL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefGetComponentInfoTask::ParsePkgFileL()"));
+
+ delete iParser;
+ iParser = NULL;
+
+ // Check if the next component is of the type our installer supports. If yes, add it to the list of
+ // the components to be processed. If not, use the SIF API to obtain its details.
+ const SifRefBinPkgExtractor::CAuxNode& node = *iEmbeddedComponents[iCurrentComponent];
+ if (node.Foreign())
+ {
+ // Connect to the SIF server
+ iComponentInfo = CComponentInfo::NewL();
+ User::LeaveIfError(iSif.Connect());
+
+ // Our installer keeps temporary files under its private folder and therefore we have to
+ // pass a file handle to the SIF API.
+ User::LeaveIfError(iFs.Connect());
+ iFs.ShareProtected();
+ User::LeaveIfError(iFile.Open(iFs, node.FileNameL(), EFileShareReadersOnly));
+
+ // Submit a SIF request
+ iSif.GetComponentInfo(iFile, *iComponentInfo, *RequestStatus());
+
+ iSifRequestInProgress = ETrue;
+
+ return ECreateComponentInfoNode;
+ }
+ else
+ {
+ iParser = CSifRefPkgParser::NewL(node.FileNameL());
+ return EFindComponent;
+ }
+ }
+
+TInt CSifRefGetComponentInfoTask::CreateComponentInfoNodeL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefGetComponentInfoTask::CreateComponentInfoNodeL()"));
+
+ SifRefBinPkgExtractor::CAuxNode& auxNode = *iEmbeddedComponents[iCurrentComponent];
+
+ if (iSifRequestInProgress)
+ {
+ iSif.Close();
+ iFile.Close();
+ iFs.Close();
+
+ iSifRequestInProgress = EFalse;
+
+ // Add the root node of iComponentInfo to the tree
+ User::LeaveIfError(RequestStatus()->Int());
+ auxNode.SetCompInfoL(iComponentInfo);
+ iComponentInfo = NULL;
+ }
+ else
+ {
+ // This reference installer uses the KExampleFileSize const value to calculate the maximum size of the installed
+ // component on a phone. This is because the reference package file carries only the list of the files to be installed
+ // without the files themselves. A real installer should use the size of the files to be installed.
+ const TInt KExampleFileSize = 1024;
+ const TInt maxInstalledSize = iParser->Files().Count() * KExampleFileSize;
+ const TBool hasExe = EFalse;
+ // The example capabilities below are hardcoded due to the same reason. The reference package file doesn't contain
+ // user grantable capabilities but a real package file should provide them.
+ TCapabilitySet userGrantableCaps(ECapabilityReadUserData, ECapabilityWriteUserData);
+
+ // Create a ComponentInfo node and set it as a root node.
+ CComponentInfo::CNode* compInfoNode = CComponentInfo::CNode::NewLC(InstallHelper::KSifReferenceSoftwareType,
+ *iCompSearchData.iName, iCompSearchData.iVersion, *iCompSearchData.iVendor,
+ iCompSearchData.iScomoState, iCompSearchData.iInstallStatus, iCompSearchData.iComponentId,
+ *iCompSearchData.iName, ENotAuthenticated, userGrantableCaps, maxInstalledSize, hasExe);
+
+ auxNode.SetNodeL(compInfoNode);
+ CleanupStack::Pop(compInfoNode);
+ }
+
+ return (++iCurrentComponent < iEmbeddedComponents.Count()) ? EParsePkgFile : ESetComponentInfo;
+ }
+
+void CSifRefGetComponentInfoTask::SetComponentInfoL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefGetComponentInfoTask::SetComponentInfoL()"));
+
+ // At least one node must exist, otherwise we can't reach this point.
+ ASSERT (iEmbeddedComponents.Count() > 0);
+
+ // Build a real tree of the nodes from iEmbeddedComponents which is a flat list
+ for (TInt i=iEmbeddedComponents.Count()-1; i>=1; --i)
+ {
+ iEmbeddedComponents[i]->RegisterChildToParentL();
+ }
+
+ // Set the tree built above as the root node of ComponentInfo().
+ iEmbeddedComponents[0]->SetAsRootNodeL(*ComponentInfo());
+ }
+
+// =============================================================================================================
+
+CSifRefInstallTask* CSifRefInstallTask::NewL(TTransportTaskParams& aParams, TInstallerUIHandlerFactory aUiHandlerFactory)
+ {
+ DEBUG_PRINTF(_L8("CSifRefInstallTask::NewL()"));
+
+ CSifRefInstallTask* self = new (ELeave) CSifRefInstallTask(aParams);
+ CleanupStack::PushL(self);
+ self->ConstructL(aUiHandlerFactory);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CSifRefInstallTask::CSifRefInstallTask(TTransportTaskParams& aParams)
+: CSifTransportTask(aParams, EFalse), iStep(EExtractEmbeddedPkgs)
+ {
+ }
+
+CSifRefInstallTask::~CSifRefInstallTask()
+ {
+ DEBUG_PRINTF(_L8("CSifRefInstallTask::~CSifRefInstallTask()"));
+
+ iFileList.Close();
+ iFile.Close();
+ iFs.Close();
+ iScr.Close();
+ iSts.Close();
+ iEmbeddedComponents.Close();
+ if (iSifRequestInProgress)
+ {
+ iSif.CancelOperation();
+ }
+ iSif.Close();
+ delete iParser;
+ delete iUiHandler;
+ delete iOpaqueArguments;
+ delete iOpaqueResults;
+ }
+
+void CSifRefInstallTask::ConstructL(TInstallerUIHandlerFactory aUiHandlerFactory)
+ {
+ if ((FileName() == NULL && FileHandle() == NULL) ||
+ CustomArguments() == NULL ||
+ CustomResults() == NULL)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ iUiHandler = InstallHelper::CreateUiHandlerL(CustomArguments(), aUiHandlerFactory);
+ }
+
+TBool CSifRefInstallTask::ExecuteImplL()
+ {
+ DEBUG_PRINTF2(_L8("Exiting from CSifRefInstallTask::ExecuteImplL(), iStep = %d"), iStep);
+
+ TBool done = EFalse;
+
+ switch (iStep)
+ {
+ case EExtractEmbeddedPkgs:
+ ExtractEmbeddedPkgsL();
+ ++iStep;
+ break;
+
+ case EParsePkgFile:
+ iStep = ParsePkgFileL();
+ break;
+
+ case ELaunchForeignInstall:
+ LaunchForeignInstallL();
+ ++iStep;
+ break;
+
+ case EFinishForeignInstall:
+ FinishForeignInstallL();
+ iStep = EParsePkgFile;
+ break;
+
+ case EFindAndCheckComponent:
+ // Next step differs for ENewComponent and EUpgrade
+ iStep = FindAndCheckComponentL();
+ break;
+
+ case EGetInstalledFileList:
+ GetInstalledFileListL();
+ ++iStep;
+ break;
+
+ case EUnregisterAndDeleteFile:
+ if (UnregisterAndDeleteFileL())
+ {
+ ++iStep;
+ }
+ break;
+
+ case ERegisterComponent:
+ RegisterComponentL();
+ ++iStep;
+ break;
+
+ case ECopyFile:
+ if (CopyFileL())
+ {
+ ++iStep;
+ }
+ break;
+
+ case ESetScomoState:
+ iStep = SetScomoStateL();
+ break;
+
+ case ECommit:
+ CommitL();
+ done = ETrue;
+ break;
+
+ default:
+ User::Leave(KErrGeneral);
+ }
+
+ if (!iSifRequestInProgress)
+ {
+ TRequestStatus* status(RequestStatus());
+ User::RequestComplete(status, KErrNone);
+ }
+
+ DEBUG_PRINTF3(_L8("Exiting from CSifRefInstallTask::ExecuteImplL(), done = %d, iStep = %d"), done, iStep);
+
+ return done;
+ }
+
+namespace
+ {
+ TInt AuxNodeSorter(const SifRefBinPkgExtractor::CAuxNode& aLeft, const SifRefBinPkgExtractor::CAuxNode& aRight)
+ {
+ const TBool l = aLeft.Foreign();
+ const TBool r = aRight.Foreign();
+ if (l == r)
+ {
+ return 0;
+ }
+ else if (!l && r)
+ {
+ return 1;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ }
+
+void CSifRefInstallTask::ExtractEmbeddedPkgsL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefInstallTask::ExtractEmbeddedPkgsL()"));
+
+ // Start an STS transaction
+ iSts.CreateTransactionL();
+
+ if (FileName())
+ {
+ SifRefBinPkgExtractor::BuildPkgTreeL(iSts, *FileName(), KRefInstPrivateDir, iEmbeddedComponents);
+ }
+ else if (FileHandle())
+ {
+ SifRefBinPkgExtractor::BuildPkgTreeL(iSts, *FileHandle(), KRefInstPrivateDir, iEmbeddedComponents);
+ }
+ else
+ {
+ ASSERT(0);
+ }
+
+ // Sort the list of the embedded components in order to install foreign packages first
+ const TLinearOrder<SifRefBinPkgExtractor::CAuxNode> sortOrder(AuxNodeSorter);
+ iEmbeddedComponents.Sort(sortOrder);
+ }
+
+TInt CSifRefInstallTask::ParsePkgFileL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefInstallTask::ParsePkgFileL()"));
+
+ TInt nextStep = -1;
+ TRAPD(err, nextStep = ParsePkgFileImplL());
+ if (err != KErrNone)
+ {
+ if (iUiHandler)
+ {
+ iUiHandler->ErrorDescriptionUIHandler(InstallHelper::KUiParserErrorDesc);
+ }
+ User::Leave(err);
+ }
+
+ return nextStep;
+ }
+
+TInt CSifRefInstallTask::ParsePkgFileImplL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefInstallTask::ParsePkgFileImplL()"));
+
+ delete iParser;
+ iParser = NULL;
+
+ // Check if the next component is of the type our installer supports. If yes, add it to the list of
+ // the components to be processed. If not, use the SIF API to install it.
+ const SifRefBinPkgExtractor::CAuxNode& node = *iEmbeddedComponents[iCurrentComponent];
+ if (node.Foreign())
+ {
+ return ELaunchForeignInstall;
+ }
+ else
+ {
+ iParser = CSifRefPkgParser::NewL(node.FileNameL());
+ return EFindAndCheckComponent;
+ }
+ }
+
+void CSifRefInstallTask::LaunchForeignInstallL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefInstallTask::LaunchForeignInstallL()"));
+
+ const SifRefBinPkgExtractor::CAuxNode& node = *iEmbeddedComponents[iCurrentComponent];
+
+ // Connect to the SIF server
+ User::LeaveIfError(iSif.Connect());
+
+ // Our installer keeps temporary files under its private folder and therefore we have to
+ // pass a file handle to the SIF API.
+ User::LeaveIfError(iFs.Connect());
+ iFs.ShareProtected();
+ User::LeaveIfError(iFile.Open(iFs, node.FileNameL(), EFileShareReadersOnly));
+
+ // Submit a SIF request
+ iOpaqueArguments = COpaqueNamedParams::NewL();
+ iOpaqueResults = COpaqueNamedParams::NewL();
+ iSif.Install(iFile, *iOpaqueArguments, *iOpaqueResults, *RequestStatus(), EFalse);
+
+ iSifRequestInProgress = ETrue;
+ }
+
+void CSifRefInstallTask::FinishForeignInstallL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefInstallTask::FinishForeignInstallL()"));
+
+ iSif.Close();
+ iFile.Close();
+ iFs.Close();
+ delete iOpaqueArguments;
+ iOpaqueArguments = NULL;
+ delete iOpaqueResults;
+ iOpaqueResults = NULL;
+
+ // Check the result of the concurrent installation
+ iSifRequestInProgress = EFalse;
+ User::LeaveIfError(RequestStatus()->Int());
+
+ // There must be at least one component left because we install foreign components first
+ ++iCurrentComponent;
+ }
+
+TInt CSifRefInstallTask::FindAndCheckComponentL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefInstallTask::FindAndCheckComponentL()"));
+
+ // Connect to the SCR and create a new transaction to continue the installation of our own type
+ if (!iScrTransaction)
+ {
+ User::LeaveIfError(iScr.Connect());
+ iScr.CreateTransactionL();
+ iScrTransaction = ETrue;
+ }
+
+ // Exit code
+ TInt nextStep = ERegisterComponent;
+
+ // Check if already installed
+ InstallHelper::FindComponentL(iScr, iCompSearchData, *iParser);
+ switch (iCompSearchData.iInstallStatus)
+ {
+ case ENewComponent:
+ // nextStep already set to ERegisterComponent
+ break;
+
+ case EUpgrade:
+ // Uninstall the previous version
+ nextStep = EGetInstalledFileList;
+ break;
+
+ case EAlreadyInstalled:
+ User::Leave(KErrSifSameVersionAlreadyInstalled);
+ break;
+
+ case ENewerVersionAlreadyInstalled:
+ User::Leave(KErrSifNewerVersionAlreadyInstalled);
+ break;
+
+ default:
+ ASSERT(0);
+ }
+
+ // Ask the user for the confirmation
+ if (iUiHandler != NULL)
+ {
+ userConfirmationL(iCompSearchData.iInstallStatus == ENewComponent ? InstallHelper::EConfirmationInstall : InstallHelper::EConfirmationUpgrade, *iUiHandler, *iCompSearchData.iName, *iCompSearchData.iVendor);
+ }
+
+ return nextStep;
+ }
+
+void CSifRefInstallTask::GetInstalledFileListL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefInstallTask::GetInstalledFileListL()"));
+
+ // Get a list of files to be deleted
+ iFileList.OpenListL(iScr, iCompSearchData.iComponentId);
+ }
+
+TBool CSifRefInstallTask::UnregisterAndDeleteFileL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefInstallTask::UnregisterAndDeleteFileL()"));
+
+ return InstallHelper::UnregisterAndDeleteFileL(iScr, iFileList, iSts, iCompSearchData.iComponentId);
+ }
+
+void CSifRefInstallTask::RegisterComponentL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefInstallTask::RegisterComponentL()"));
+
+ // Register a new component in the SCR
+ RCPointerArray<CLocalizableComponentInfo> componentInfoArray;
+ CleanupClosePushL(componentInfoArray);
+
+ // ...for each language
+ const RLanguageArray& languages = iParser->Languages();
+ const TInt langCount = languages.Count();
+ for (TInt i=0; i<langCount; ++i)
+ {
+ const TDesC& locName = *iParser->ComponentNames()[i];
+ const TDesC& locVendor = *iParser->VendorNames()[i];
+ CLocalizableComponentInfo* componentInfo = CLocalizableComponentInfo::NewLC(locName, locVendor, languages[i]);
+ componentInfoArray.AppendL(componentInfo);
+ CleanupStack::Pop(componentInfo);
+ }
+ iCompSearchData.iComponentId = iScr.AddComponentL(componentInfoArray, InstallHelper::KSifReferenceSoftwareType);
+
+ // Set the version of a new component
+ iScr.SetComponentVersionL(iCompSearchData.iComponentId, iCompSearchData.iVersion);
+
+ CleanupStack::PopAndDestroy(&componentInfoArray);
+
+ iCopyFileIndex = 0;
+ iComponentSize = 0;
+
+ // Send the id if the installed component to the client. If this is a compound package we send the id of the root component only.
+ if (iEmbeddedComponents[iCurrentComponent]->Root())
+ {
+ CustomResults()->AddIntL(KSifOutParam_ComponentId, iCompSearchData.iComponentId);
+ }
+ }
+
+namespace
+ {
+ TBool CheckPathExistenceL(const TDesC& filePath)
+ {
+ TBool exists = EFalse;
+
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs);
+ TEntry entry;
+ TInt error = fs.Entry(filePath, entry);
+ if (error == KErrNone)
+ {
+ exists = ETrue;
+ }
+ else if (error != KErrPathNotFound && error != KErrNotFound)
+ {
+ User::Leave(error);
+ }
+
+ CleanupStack::PopAndDestroy(&fs);
+
+ return exists;
+ }
+ }
+
+TBool CSifRefInstallTask::CopyFileL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefInstallTask::CopyFileL()"));
+
+ // List of files to be copied from a package file
+ const RCHBufCArray& files = iParser->Files();
+
+ // Register and copy a file if any left
+ if (iCopyFileIndex < files.Count())
+ {
+ // The name of the current file
+ const TDesC& filePath = *files[iCopyFileIndex];
+
+ // Check if filePath already exists
+ if (CheckPathExistenceL(filePath))
+ {
+ // Add a custom result describing the error
+ HBufC* desc = HBufC::NewLC(InstallHelper::KErrFileAlreadyExists.iTypeLength + filePath.Length());
+ TPtr bufDesc = desc->Des();
+ bufDesc.Copy(InstallHelper::KErrFileAlreadyExists);
+ bufDesc.Copy(filePath);
+ CustomResults()->AddStringL(InstallHelper::KParamNameErrDesc, *desc);
+ CleanupStack::PopAndDestroy(desc);
+ }
+
+ // Register the file in the SCR
+ iScr.RegisterComponentFileL(iCompSearchData.iComponentId, filePath);
+
+ // Copy the current file
+ RFile file;
+ iSts.CreateNewL(filePath, file, TFileMode(EFileShareExclusive |EFileWrite));
+ _LIT8(KReferenceFootprint, "This file belongs to the SIF reference component.\n");
+ const TInt numLines = 100; // The operation must take a while to simulate real copying
+ for (TInt i=0; i<numLines; ++i)
+ {
+ User::LeaveIfError(file.Write(KReferenceFootprint));
+ }
+ iComponentSize += KReferenceFootprint.iTypeLength*numLines;
+ file.Close();
+
+ ++iCopyFileIndex;
+ }
+ else
+ {
+ // Set the size of the component in the SCR
+ iScr.SetComponentSizeL(iCompSearchData.iComponentId, iComponentSize);
+
+ // Step complete, all the files have been copied
+ return ETrue;
+ }
+
+ // Step not complete, there are still files left
+
+ DEBUG_PRINTF(_L8("Exiting from CSifRefInstallTask::CopyFileL()"));
+
+ return EFalse;
+ }
+
+TInt CSifRefInstallTask::SetScomoStateL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefInstallTask::SetScomoStateL()"));
+
+ // Activate the newly added component
+ TInt inactive = EFalse;
+ if (!CustomArguments()->GetIntByNameL(_L("InstallInactive"), inactive) || !inactive)
+ {
+ iScr.SetScomoStateL(iCompSearchData.iComponentId, EActivated);
+ }
+
+ // Check if there are any components to be installed left
+ return (++iCurrentComponent < iEmbeddedComponents.Count()) ? EParsePkgFile : ECommit;
+ }
+
+void CSifRefInstallTask::CommitL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefInstallTask::CommitL()"));
+
+ // Commit the STS & SCR transactions
+ iSts.CommitL();
+ iScr.CommitTransactionL();
+ }
+
+// =============================================================================================================
+
+CSifRefUninstallTask* CSifRefUninstallTask::NewL(TTransportTaskParams& aParams, TInstallerUIHandlerFactory aUiHandlerFactory)
+ {
+ DEBUG_PRINTF(_L8("CSifRefUninstallTask::NewL()"));
+
+ CSifRefUninstallTask* self = new (ELeave) CSifRefUninstallTask(aParams);
+ CleanupStack::PushL(self);
+ self->ConstructL(aUiHandlerFactory);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CSifRefUninstallTask::CSifRefUninstallTask(TTransportTaskParams& aParams)
+: CSifTransportTask(aParams), iStep(EGetFileList)
+ {
+ }
+
+void CSifRefUninstallTask::ConstructL(TInstallerUIHandlerFactory aUiHandlerFactory)
+ {
+ if (ComponentId() == NULL || CustomArguments() == NULL || CustomResults() == NULL)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ iUiHandler = InstallHelper::CreateUiHandlerL(CustomArguments(), aUiHandlerFactory);
+ }
+
+CSifRefUninstallTask::~CSifRefUninstallTask()
+ {
+ DEBUG_PRINTF(_L8("CSifRefUninstallTask::~CSifRefUninstallTask()"));
+
+ // Make sure to close sub-session before the session
+ iFileList.Close();
+ iScr.Close();
+ iSts.Close();
+ delete iUiHandler;
+ }
+
+TBool CSifRefUninstallTask::ExecuteImplL()
+ {
+ DEBUG_PRINTF2(_L8("CSifRefInstallTask::ExecuteImplL(), iStep = %d"), iStep);
+
+ switch (iStep)
+ {
+ case EGetFileList:
+ GetFileListL();
+ break;
+
+ case EUnregisterAndDeleteFile:
+ if (!UnregisterAndDeleteFileL())
+ {
+ return EFalse;
+ }
+ break;
+
+ case ECommit:
+ CommitL();
+ return ETrue;
+
+ default:
+ User::Leave(KErrGeneral);
+ }
+
+ ++iStep;
+
+ DEBUG_PRINTF2(_L8("Exiting from CSifRefInstallTask::ExecuteImplL(), iStep = %d"), iStep);
+
+ return EFalse;
+ }
+
+void CSifRefUninstallTask::GetFileListL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefUninstallTask::GetFileListL()"));
+
+ // Connect to the SCR and start a transaction
+ User::LeaveIfError(iScr.Connect());
+ iScr.CreateTransactionL();
+
+ // Ask the user for confirmation
+ if (iUiHandler != NULL)
+ {
+ CComponentEntry* entry = CComponentEntry::NewLC();
+ if (!iScr.GetComponentL(ComponentId(), *entry))
+ {
+ User::Leave(KErrNotFound);
+ }
+ userConfirmationL(InstallHelper::EConfirmationUninstall, *iUiHandler, entry->Name(), entry->Vendor());
+ CleanupStack::PopAndDestroy(entry);
+ }
+
+ // Get a list of files to be deleted
+ iFileList.OpenListL(iScr, ComponentId());
+
+ // Start an STS transaction
+ iSts.CreateTransactionL();
+ }
+
+TBool CSifRefUninstallTask::UnregisterAndDeleteFileL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefUninstallTask::UnregisterAndDeleteFileL()"));
+
+ return InstallHelper::UnregisterAndDeleteFileL(iScr, iFileList, iSts, ComponentId());
+ }
+
+void CSifRefUninstallTask::CommitL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefUninstallTask::CommitL()"));
+
+ // Commit the STS & SCR transactions
+ iSts.CommitL();
+ iScr.CommitTransactionL();
+ }
+
+// =============================================================================================================
+
+CSifRefActivateDeactivateTask::CSifRefActivateDeactivateTask(TTransportTaskParams& aParams, TScomoState aScomoState)
+: CSifTransportTask(aParams), iScomoState(aScomoState)
+ {
+ DEBUG_PRINTF(_L8("CSifRefActivateDeactivateTask::CSifRefActivateDeactivateTask()"));
+ }
+
+CSifRefActivateDeactivateTask::~CSifRefActivateDeactivateTask()
+ {
+ DEBUG_PRINTF(_L8("CSifRefActivateDeactivateTask::~CSifRefActivateDeactivateTask()"));
+
+ iScr.Close();
+ }
+
+TBool CSifRefActivateDeactivateTask::ExecuteImplL()
+ {
+ DEBUG_PRINTF(_L8("CSifRefActivateDeactivateTask::ExecuteImplL()"));
+
+ if (ComponentId() == NULL)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ // Connect to SCR and activate/deactivate component
+ User::LeaveIfError(iScr.Connect());
+ iScr.SetScomoStateL(ComponentId(), iScomoState);
+
+ return ETrue;
+ }