installationservices/swinstallationfw/test/plugins/nonnativeplugin/source/testnonnativeplugin.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 31 Aug 2010 15:21:33 +0300
branchRCL_3
changeset 25 7333d7932ef7
permissions -rw-r--r--
Revision: 201033 Kit: 201035

/*
* Copyright (c) 2008-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 "testnonnativeplugin.h"
#include "usiflog.h"
#include <usif/sif/sif.h>
#include <usif/sif/sifcommon.h>
#include <usif/usiferror.h>
#include <usif/sif/sifplugin.h>
#include <usif/scr/screntries.h>
#include <usif/scr/scr.h>
#include <usif/sts/sts.h>
#include <usif/sif/sifutils.h>

using namespace Usif;

namespace
	{
	const TInt KUserGrantableCapsBitMask = 49152; // ECapabilityReadUserData, ECapabilityWriteUserData
	const TInt KMaxInstalledSize = 1234;
	const TBool KHasExe = EFalse;
	const TBool KDriveSelectionRequired = EFalse;	
	const TAuthenticity KAuthenticity = EAuthenticated;
	_LIT_SECURE_ID(KSifTestSuiteSecureId, 0x10285BCC);
	_LIT_SECURE_ID(KSifRefInstallerServerSecureId, 0x1028634E);
	_LIT_SECURE_ID(KSifLauncherSecureId, 0x10285BD0);
	_LIT(KSifTestComponentVersion, "1.0.0");
	_LIT(KSifTestGlobalComponentId, "test.nonnativepackage.txt");
#ifndef TESTNONNATIVEPLUGIN2
	const TInt KTestNonNativePluginImpId = 0x10285BD2;
	const TComponentId KSifTestComponentId = 12345678;
	_LIT(KSifTestSoftwareType, "plain");
	_LIT(KSifTestComponentName, "Test Component");
	_LIT(KSifTestComponentVendor, "Symbian");
	_LIT(KSifTestInstallPath, "c:\\tusif\\tsif\\nonnativeplugin\\%S\\file%d");
	_LIT(KSifTestOutIntParam, "NonNativePlugin");
#else
	const TInt KTestNonNativePluginImpId = 0x102866EF;
	const TComponentId KSifTestComponentId = 87654321;
	_LIT(KSifTestSoftwareType, "testSoftwareType");
	_LIT(KSifTestComponentName, "Test Layered Execution Environment");
	_LIT(KSifTestComponentVendor, "Test Vendor");
	_LIT(KSifTestInstallPath, "c:\\tusif\\tsif\\nonnativeplugin2\\%S\\file%d");
	_LIT(KSifTestOutIntParam, "NonNativePlugin2");
#endif

	const TImplementationProxy ImplementationTable[] = 
		{
		IMPLEMENTATION_PROXY_ENTRY(KTestNonNativePluginImpId, CTestNonNativePlugin::NewL)
		};

	void UnpackCapabilitySet(TInt aPackedCapSet, TCapabilitySet& aCapSet)
		{
		for (TInt c=0; c<ECapability_Limit; ++c)
			{
			const TInt cap = 1<<c;
			if (aPackedCapSet&cap)
				{
				aCapSet.AddCapability(TCapability(c));
				}
			}
		}

	TComponentId AddComponentToScrL(RSoftwareComponentRegistry& aScr, const TDesC& aComponentName, const TDesC& aVendor)
		{
		// Check if the component is already installed
		RSoftwareComponentRegistryView scrView;
		CComponentFilter* filter = CComponentFilter::NewLC();
		filter->SetNameL(aComponentName);
		filter->SetVendorL(aVendor);

		scrView.OpenViewL(aScr, filter);
		CleanupClosePushL(scrView);

		CComponentEntry* component = scrView.NextComponentL();
		CleanupStack::PopAndDestroy(2, filter);
		if (component != NULL)
			{
			delete component;
			DEBUG_PRINTF2(_L("Non-native component: %S already installed"), &aComponentName);
			User::Leave(KErrSifSameVersionAlreadyInstalled);
			}

		TComponentId componentId = aScr.AddComponentL(aComponentName, aVendor, KSifTestSoftwareType);
		DEBUG_PRINTF2(_L("Added a non-native component with id %d"), componentId);

		return componentId;
		}

	void CreateAndRegisterFilesL(RSoftwareComponentRegistry& aScr, TComponentId aComponentId, const TDesC& aComponentName)
		{
		RStsSession sts;
		sts.CreateTransactionL();
		CleanupClosePushL(sts);

		const TInt numComponentFiles = 3;
		const TInt maxIntDigits = 10;
		
		TInt componentSize = 0;
		
		for (TInt i=0; i<numComponentFiles; ++i)
			{
			// Generate the full path of the i-th file
			const TInt maxPathLen = KSifTestInstallPath.iTypeLength+aComponentName.Length()+maxIntDigits;
			HBufC* filePath = HBufC::NewLC(maxPathLen);
			TPtr filePathPtr = filePath->Des();
			filePathPtr.Format(KSifTestInstallPath, &aComponentName, i);

			// Create the file
			RFile file;
			sts.CreateNewL(*filePath, file, TFileMode(EFileShareExclusive |EFileWrite));
			_LIT8(KNonNativeFootprint, "This file belongs to the Non-Native Test component.");
			User::LeaveIfError(file.Write(KNonNativeFootprint));
			componentSize += KNonNativeFootprint.iTypeLength;
			file.Close();

			// Register the file in the SCR
			aScr.RegisterComponentFileL(aComponentId, *filePath);

			CleanupStack::PopAndDestroy(filePath);
			}

		aScr.SetComponentSizeL(aComponentId, componentSize);

		sts.CommitL();
		CleanupStack::PopAndDestroy(&sts);
		}

	// The literals below are hardcoded because they are used only here so there
	// is no risk of duplication or a typo. Of course, they are also used in the
	// sif.ini file but we cannot reuse them there in any case.

	void ProcessOpaqueParamsL(const COpaqueNamedParams& aInputParams, COpaqueNamedParams& aOutputParams)
		{
		aOutputParams.AddIntL(KSifTestOutIntParam, ETrue);
		TInt silent = ETrue;
		TBool silentFound = aInputParams.GetIntByNameL(_L("DoSilent"), silent);
		if (silentFound)
			{
			aOutputParams.AddIntL(_L("DoneSilently"), silent);
			}
		}

	void InstallL(const TDesC& aComponentName, COpaqueNamedParams& aOutputParams)
		{
		RSoftwareComponentRegistry scr;
		User::LeaveIfError(scr.Connect());
		CleanupClosePushL(scr);
		scr.CreateTransactionL();

		TComponentId componentId = AddComponentToScrL(scr, aComponentName, KSifTestComponentVendor);
		aOutputParams.AddIntL(KSifOutParam_ComponentId, componentId);

		CreateAndRegisterFilesL(scr, componentId, aComponentName);

		scr.CommitTransactionL();
		CleanupStack::PopAndDestroy(&scr);
		}

	void InstallImplL(const TDesC& aFileName, const TSecurityContext& /*aSecurityContext*/,
					const COpaqueNamedParams& aInputParams, COpaqueNamedParams& aOutputParams)
		{
		// The "DummyInstallation" param instructs the installer not to execute any real operation. This dummy installation
		// is needed in order to test the ExcludeOperation mode supported by the SIF APIs. Running multiple concurrent
		// SIF operations may lead to concurrent SCR transactions which are not supported. Hence, this dummy installation
		// is used as a 'safe' installation that may be launched concurrently with a regular native installation.
		TInt dummyInstallation = EFalse;
		if (aInputParams.GetIntByNameL(_L("DummyInstallation"), dummyInstallation) && dummyInstallation)
			{
			return;
			}

		ProcessOpaqueParamsL(aInputParams, aOutputParams);

		TPtrC name;
		const TInt pos = aFileName.LocateReverse('\\');
		if (pos != KErrNotFound)
			{
			name.Set(aFileName.Mid(pos+1));
			}
		else
			{
			name.Set(aFileName);
			}
		
		InstallL(name, aOutputParams);
		}

	void InstallImplL(RFile& aFileHandle, const TSecurityContext& /*aSecurityContext*/,
					const COpaqueNamedParams& aInputParams, COpaqueNamedParams& aOutputParams)
		{
		ProcessOpaqueParamsL(aInputParams, aOutputParams);
		HBufC* name = HBufC::NewLC(KMaxFullName);
		TPtr namePtr = name->Des();
		User::LeaveIfError(aFileHandle.Name(namePtr));
		InstallL(*name, aOutputParams);
		CleanupStack::PopAndDestroy(name);
		}

	void UninstallImplL(TComponentId aComponentId, const TSecurityContext& /*aSecurityContext*/,
						const COpaqueNamedParams& aInputParams, COpaqueNamedParams& aOutputParams)
		{
		ProcessOpaqueParamsL(aInputParams, aOutputParams);

		// Uninstall the component using the SIF Utils Library
		UninstallL(aComponentId);
		}

	void CheckSecurityContextL(const TSecurityContext& aSecurityContext)
		{
		// There are three executables that may issue software management request for TestNonNative packages.
		// These are:
		// (1) TEF test server (KSifTestSuiteSecureId) - all USIF tests
		// (2) the Reference Installer (KSifRefInstallerServerSecureId) - cross installer tests (for embedded packages)
		// (3) the SIF Launcher - for testing integration with AppArc
		// For the first two we also check ReadUserData to ensure coverage in integration tests
		if (aSecurityContext.SecureId() == KSifLauncherSecureId)
			return;
		aSecurityContext.HasCapabilityL(ECapabilityReadUserData);
		if (aSecurityContext.SecureId() != KSifTestSuiteSecureId &&
			aSecurityContext.SecureId() != KSifRefInstallerServerSecureId )
			{
			User::Leave(KErrPermissionDenied);
			}
		}

	TBool CheckSecurityContext(const TSecurityContext& aSecurityContext)
		{
		if (aSecurityContext.SecureId() == KSifLauncherSecureId)
			return ETrue;
		return aSecurityContext.HasCapability(ECapabilityReadUserData) &&
			   (aSecurityContext.SecureId() == KSifTestSuiteSecureId ||
			    aSecurityContext.SecureId() == KSifRefInstallerServerSecureId);
		}

	void GetComponentInfoImplL(CComponentInfo& aComponentInfo, TBool aTestOverflow = EFalse)
		{
		// Prepare capabilities
		TCapabilitySet capSet;
		RPointerArray<Usif::CComponentInfo::CApplicationInfo>* applications = NULL;
		capSet.SetEmpty();
		UnpackCapabilitySet(KUserGrantableCapsBitMask, capSet);
		
		// Create the root node of the CComponentInfo object
		CComponentInfo::CNode* rootNode = CComponentInfo::CNode::NewLC(KSifTestSoftwareType, KSifTestComponentName,
						KSifTestComponentVersion, KSifTestComponentVendor, EDeactivated, ENewComponent,
						KSifTestComponentId, KSifTestGlobalComponentId, KAuthenticity, capSet, KMaxInstalledSize, KHasExe, KDriveSelectionRequired, applications);

		// Create a long string used for overflow tests
		HBufC* longStr = NULL;

		if (aTestOverflow)
			{
			// The CComponentInfo class defines KMaxComponentInfoStreamedSize as:
			// KMaxComponentInfoStreamedSize = 2*KMaxHeapBufLength+6*sizeof(TInt)+sizeof(TInt8), where KMaxHeapBufLength = 2048
			// So, we need a tree of CNode objects in order to cause a KErrOverflow error
			const TInt longStrLen = 256;
			longStr = HBufC::NewLC(longStrLen);
			TPtr longStrPtr(longStr->Des());
			longStrPtr.Fill(TChar(0xadcb), longStrLen);

			const TInt numChildren = 3;
			for (TInt i=0; i<numChildren; ++i)
				{
				CComponentInfo::CNode* childNode = CComponentInfo::CNode::NewLC(KSifTestSoftwareType, *longStr,
						KSifTestComponentVersion, *longStr, EDeactivated, ENewComponent,
						KSifTestComponentId, *longStr, KAuthenticity, capSet, KMaxInstalledSize, KHasExe, KDriveSelectionRequired, applications);
				
				rootNode->AddChildL(childNode);
				CleanupStack::Pop(childNode);
				}
			
			CleanupStack::PopAndDestroy(longStr);
			}

		aComponentInfo.SetRootNodeL(rootNode);
		CleanupStack::Pop(rootNode);

		}
	}

EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
	{
	aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
	return ImplementationTable;
	}

CTestNonNativePlugin* CTestNonNativePlugin::NewL()
	{
	DEBUG_PRINTF(_L8("Constructing CTestNonNativePlugin"));
	CTestNonNativePlugin *self = new (ELeave) CTestNonNativePlugin();
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

void CTestNonNativePlugin::ConstructL()
	{
	}

CTestNonNativePlugin::~CTestNonNativePlugin()
	{
	}

void CTestNonNativePlugin::CancelOperation()
	{
	DEBUG_PRINTF(_L8("Test non-native plugin - Cancel"));
	}

void CTestNonNativePlugin::GetComponentInfo(const TDesC& aFileName, const TSecurityContext& aSecurityContext,
										CComponentInfo& aComponentInfo, TRequestStatus& aStatus)
	{
	DEBUG_PRINTF(_L8("Test non-native plugin - GetComponentInfo by filename"));
	aStatus = KRequestPending;

	TInt err = KErrNone;
	// We test a non-leaving version of TSecurityContext::HasCapability() here
	if (CheckSecurityContext(aSecurityContext))
		{
		_LIT(KTxtTestOverflow, "z:\\tusif\\tsif\\data\\test.overflow.txt");
		TRAP(err, GetComponentInfoImplL(aComponentInfo, aFileName == KTxtTestOverflow));
		}
	else
		{
		err = KErrPermissionDenied;
		}

	TRequestStatus *statusPtr(&aStatus);
	User::RequestComplete(statusPtr, err);
	}

void CTestNonNativePlugin::GetComponentInfo(RFile& /*aFileHandle*/, const TSecurityContext& aSecurityContext,
											CComponentInfo& aComponentInfo, TRequestStatus& aStatus)
	{
	DEBUG_PRINTF(_L8("Test non-native plugin - GetComponentInfo by file handle"));
	aStatus = KRequestPending;

	TRAPD(err, CheckSecurityContextL(aSecurityContext);
			   GetComponentInfoImplL(aComponentInfo));

	TRequestStatus *statusPtr(&aStatus);
	User::RequestComplete(statusPtr, err);
	}

void CTestNonNativePlugin::Install(const TDesC& aFileName, const TSecurityContext& aSecurityContext,
									const COpaqueNamedParams& aInputParams, COpaqueNamedParams& aOutputParams,
									TRequestStatus& aStatus)
	{
	DEBUG_PRINTF2(_L("Test non-native plugin - install for %S"), &aFileName);
	aStatus = KRequestPending;

	TRAPD(err, CheckSecurityContextL(aSecurityContext);
				InstallImplL(aFileName, aSecurityContext, aInputParams, aOutputParams));

	TRequestStatus *statusPtr(&aStatus);
	User::RequestComplete(statusPtr, err);
	}

void CTestNonNativePlugin::Install(RFile& aFileHandle, const TSecurityContext& aSecurityContext,
									const COpaqueNamedParams& aInputParams, COpaqueNamedParams& aOutputParams,
									TRequestStatus& aStatus)
	{
	DEBUG_PRINTF(_L("Test non-native plugin - install by file handle"));
	aStatus = KRequestPending;
	
	TRAPD(err, CheckSecurityContextL(aSecurityContext);
			   InstallImplL(aFileHandle, aSecurityContext, aInputParams, aOutputParams));

	TRequestStatus *statusPtr(&aStatus);
	User::RequestComplete(statusPtr, err);
	}

void CTestNonNativePlugin::Uninstall(TComponentId aComponentId, const TSecurityContext& aSecurityContext,
								const COpaqueNamedParams& aInputParams, COpaqueNamedParams& aOutputParams, TRequestStatus& aStatus)
	{
	DEBUG_PRINTF2(_L8("Test non-native plugin - uninstall for ComponentId =  %d"), aComponentId);
	aStatus = KRequestPending;

	TRAPD(err, CheckSecurityContextL(aSecurityContext);
	 		   UninstallImplL(aComponentId, aSecurityContext, aInputParams, aOutputParams));

	TRequestStatus* statusPtr(&aStatus);
	User::RequestComplete(statusPtr, err);
	}

void CTestNonNativePlugin::Activate(TComponentId /*aComponentId*/, const TSecurityContext& aSecurityContext, TRequestStatus& aStatus)
	{
	DEBUG_PRINTF(_L8("Test non-native plugin - activate"));
	aStatus = KRequestPending;

	TRAPD(err, CheckSecurityContextL(aSecurityContext));

	TRequestStatus* statusPtr(&aStatus);
	User::RequestComplete(statusPtr, err);
	}

void CTestNonNativePlugin::Deactivate(TComponentId /*aComponentId*/, const TSecurityContext& aSecurityContext, TRequestStatus& aStatus)
	{
	DEBUG_PRINTF(_L8("Test non-native plugin - deactivate"));
	aStatus = KRequestPending;

	TRAPD(err, CheckSecurityContextL(aSecurityContext));

	TRequestStatus* statusPtr(&aStatus);
	User::RequestComplete(statusPtr, err);
	}