installationservices/swi/source/sislauncher/server/sislauncherserver.cpp
changeset 0 ba25891c3a9e
child 25 7333d7932ef7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/installationservices/swi/source/sislauncher/server/sislauncherserver.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,558 @@
+/*
+* Copyright (c) 2004-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: 
+* SisLauncher - server implementation
+*
+*/
+
+
+/**
+ @file 
+ @released
+ @internalComponent
+*/
+ 
+#include "sislauncherserver.h"
+#include "sislaunchersession.h"
+#include "sislauncherclientserver.h"
+#include "log.h"
+#include "securitypolicy.h"
+#include <w32std.h>
+
+#include "threadmonitor.h"
+#include "queueprocessor.h"
+
+#ifndef SWI_TEXTSHELL_ROM
+	#include <apmstd.h>
+	#include <apgcli.h>
+	#include <apgwgnam.h>
+	#include <apgtask.h>
+#endif
+
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+const TUint KInstallServerUid = 0x101F7295;
+const TUint KSisRegistryServerUid = 0x10202DCA;
+#endif
+
+using namespace Swi;
+
+CServer2* CSisLauncherServer::NewLC()
+	{
+	CSisLauncherServer* self=new(ELeave) CSisLauncherServer;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+CSisLauncherServer::~CSisLauncherServer()
+	{
+#ifndef SWI_TEXTSHELL_ROM
+	if (iBootMode != KTextShell)
+		{
+		iWsSession.Close();	
+		}
+#endif
+	delete iShutdown;
+	delete iQueueProcessor;
+	CSecurityPolicy::ReleaseResource();
+	}
+
+void CSisLauncherServer::ConstructL()
+	{
+	StartL(KSisLauncherServerName);
+	iShutdown = new (ELeave) CSisLauncherServerShutdown;
+	iShutdown->ConstructL();
+	TInt connectErr = KErrNotFound;
+#ifndef SWI_TEXTSHELL_ROM
+	// Connect to Window Session
+	connectErr = iWsSession.Connect();
+	if (connectErr != KErrNotFound)
+		{
+		User::LeaveIfError(connectErr);
+		}
+#endif
+	if (connectErr == KErrNotFound)
+		{
+		// emulator tests running in textshell or in textshell ROM (#def SWI_TEXTSHELL_ROM)
+		iBootMode = KTextShell;
+		}
+	iQueueProcessor = CQueueProcessor::NewL(*this);
+	}
+
+CSession2* CSisLauncherServer::NewSessionL(const TVersion&,const RMessage2&) const
+	{
+	return new(ELeave) CSisLauncherSession();
+	}
+
+void CSisLauncherServer::AddSession()
+	{
+	++iSessionCount;
+	
+	DEBUG_PRINTF2(_L8("Sis Launcher Server - Adding Session (%d sessions total.)"), iSessionCount);
+	
+	CancelShutdown();	
+	}
+
+void CSisLauncherServer::DropSession()
+	{
+	--iSessionCount;
+	
+	DEBUG_PRINTF2(_L8("Sis Launcher Server - Dropping Session (%d sessions total.)"), iSessionCount);
+	
+	if (0==iSessionCount && iShutdown)
+		{
+		DEBUG_PRINTF(_L8("Sis Launcher Server - Starting shutdown timer."));
+		// ignored if a long timer is active
+		iShutdown->StartShort(EFalse);
+		} 
+	}
+/**
+ * Cancels an existing shutdown timer before renabling with the long timeout. This is used to catch
+ * the case where we need to allow ECOM to work before killing the server. ECOM should finish scanning 
+ * files within a couple of seconds of SWI finishing but just in case we allow ECOM a little longer.
+ * The other reason we have the timer is to handle the case where SWI mistakenly identified a plugin 
+ * resource file, we don't want to hang around forever waiting for an event that never comes.
+ * */
+void CSisLauncherServer::LongServerShutdown()
+	{
+	DEBUG_PRINTF(_L8("Sis Launcher Server - Switching to long shutdown timer"));
+	if (iShutdown)
+		{
+		iShutdown->StartLong();
+		}
+	}
+
+void CSisLauncherServer::CancelShutdown()
+	{
+	DEBUG_PRINTF(_L8("Sis Launcher Server - Cancelling shutdown timer"));
+		
+	if (iShutdown)
+		{
+		iShutdown->Cancel();
+		}	
+	}
+
+void CSisLauncherServer::ShortServerShutdown()
+	{
+	DEBUG_PRINTF(_L8("Sis Launcher Server - Re-enabling short shutdown timer"));
+	if (0==iSessionCount && iShutdown)
+		{
+		DEBUG_PRINTF(_L8("Sis Launcher Server - Starting shutdown timer"));
+		iShutdown->StartShort(ETrue);
+		} 
+	}
+
+	// All functions require TCB capability
+const TInt CSisLauncherServer::iRanges[iRangeCount] = 
+	{
+	0, // All connect attempts
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+	// Range of utility services for Post manufacture management of Layered Execution Environemnts
+	EParseSwTypeRegFile,
+	EUnregisterSifLauncherMimeTypes,
+#endif
+	ESeparatorEndAll,
+	};
+
+const TUint8 CSisLauncherServer::iElementsIndex[iRangeCount] = 
+	{
+	0, // Used by Client which is only swis and TCB is needed.
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+	1, // Utility services used by InstallServer
+	2, // Utility services used by SisRegistryServer
+#endif
+	CPolicyServer::ENotSupported,
+	};
+
+const CPolicyServer::TPolicyElement CSisLauncherServer::iPolicyElements[] = 
+	{
+	{_INIT_SECURITY_POLICY_C1(ECapabilityTCB), CPolicyServer::EFailClient},
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+	{_INIT_SECURITY_POLICY_S0(KInstallServerUid), CPolicyServer::EFailClient},
+	{_INIT_SECURITY_POLICY_S0(KSisRegistryServerUid), CPolicyServer::EFailClient},
+#endif
+	};
+
+const CPolicyServer::TPolicy CSisLauncherServer::iPolicy =
+	{
+	0,					//specifies all connect attempts need TCB
+	iRangeCount,
+	iRanges,
+	iElementsIndex,
+	iPolicyElements,
+	};
+	
+	
+// shutdown timer
+
+CSisLauncherServerShutdown::~CSisLauncherServerShutdown()
+	{
+	Cancel();
+	}
+
+void CSisLauncherServerShutdown::RunL()
+	{
+	CActiveScheduler::Stop();
+	}
+	
+void CSisLauncherServerShutdown::StartShort(TBool aCancelLongTimer)
+	{
+	if (iLongTimerActive & !aCancelLongTimer)
+		{
+		return;
+		}
+	else
+		{
+		Cancel();
+		iLongTimerActive=EFalse;
+		After(KSisLauncherShutdownDelay);
+		}
+	}
+
+inline void CSisLauncherServerShutdown::StartLong()
+	{
+	Cancel();
+	iLongTimerActive=ETrue;
+	After(KSisLauncherLongShutdownDelay);
+	}
+
+
+void CSisLauncherServer::RunExecutableL(const TDesC& aFileName, TBool aWait)
+	{
+	DEBUG_CODE_SECTION(
+		if (aWait)
+			{
+			DEBUG_PRINTF2(_L("Sis Launcher Server - Attempting to run executable by filename ('%S'), waiting for termination."),
+				&aFileName);
+			}
+		else
+			{
+			DEBUG_PRINTF2(_L("Sis Launcher Server - Attempting to run executable by filename ('%S'), not waiting for termination."),
+				&aFileName);
+			}
+	); // DEBUG_CODE_SECTION
+	
+	RProcess process;
+	_LIT(KNullArgs, "");
+	User::LeaveIfError(process.Create(aFileName, KNullArgs));
+	CleanupClosePushL(process);
+	
+	// Get the thread id of the main thread in the process
+	// From CApaExeRecognizer::RunL	
+	TFullName fullName(process.Name());
+	_LIT(KCCMain,"::Main");
+	fullName.Append(KCCMain);
+	TFindThread fT(fullName);
+	User::LeaveIfError(fT.Next(fullName));
+	RThread thread;
+	User::LeaveIfError(thread.Open(fT));
+	TThreadId threadId = thread.Id();
+	thread.Close();
+	process.Resume();
+	
+	CleanupStack::PopAndDestroy(&process);
+	if (aWait)
+		HandleShutdownL(threadId, ETrue);
+	}
+
+
+
+void CSisLauncherServer::ForceShutdownL(TUid aUid)
+	{
+	TBool needToScanFullList;
+	TFullName fullName;
+	do
+		{
+		needToScanFullList = EFalse;
+		TFindProcess findProcess;
+
+		while(findProcess.Next(fullName) == KErrNone)
+			{
+			RProcess process;
+			User::LeaveIfError(process.Open(findProcess));
+			TUid sid(process.SecureId());
+			if (sid == aUid && process.ExitType() == EExitPending)
+				{
+				process.Kill(KErrNone);
+				needToScanFullList = ETrue;
+				}
+			process.Close();
+			}
+		} while (needToScanFullList);
+	}
+
+
+void CSisLauncherServer::HandleShutdownL(TThreadId aThread, TBool aKillOnTimeout)
+	{
+	RWsSession* wsSession = NULL;
+	if (iBootMode == KTextShell) 
+		{
+		// emulator tests running in textshell or in textshell ROM (#def SWI_TEXTSHELL_ROM)
+		DEBUG_PRINTF(_L8("Sis Launcher Server - textshell - skipping shutdown of user applications"));	
+		}
+	else
+		{
+		#ifndef SWI_TEXTSHELL_ROM
+			DEBUG_CODE_SECTION(
+				if (aKillOnTimeout)
+					{
+					DEBUG_PRINTF(_L8("Sis Launcher Server - Awaiting thread shutdown, will forcibly kill process on timeout."));
+					}
+				else
+					{
+					DEBUG_PRINTF(_L8("Sis Launcher Server - Awaiting thread shutdown, will not forcibly kill process on timeout."));
+					}
+				);
+			wsSession = &iWsSession;	
+		#endif
+		}
+	// Read timeout value from software install security
+	// policy.
+	CSecurityPolicy* secPolicy = CSecurityPolicy::GetSecurityPolicyL();
+	TInt runWaitTimeout = secPolicy->RunWaitTimeout();
+	TInt shutdownTimeout = secPolicy->ApplicationShutdownTimeout();
+	// Wait until the thread finishes or a timeout occurs
+	CThreadMonitor* threadMonitor = CThreadMonitor::NewLC(aThread, wsSession);
+	threadMonitor->SyncShutdownL(runWaitTimeout, aKillOnTimeout, shutdownTimeout);
+	CleanupStack::PopAndDestroy(threadMonitor);
+	}
+
+
+#ifndef SWI_TEXTSHELL_ROM
+void CSisLauncherServer::StartDocumentL(RFile& aFile, TBool aWait)
+	{
+	DEBUG_CODE_SECTION(
+	if (aWait)
+		{
+		DEBUG_PRINTF(_L8("Sis Launcher Server - Attempting to start document by filehandle, waiting for termination."));
+		}
+	else
+		{
+		DEBUG_PRINTF(_L8("Sis Launcher Server - Attempting to start document by filehandle, not waiting for termination."));
+		}
+	);
+
+	RApaLsSession apaSession;
+	User::LeaveIfError(apaSession.Connect());
+	CleanupClosePushL(apaSession);
+
+	TThreadId threadId;	
+	User::LeaveIfError(apaSession.StartDocument(aFile, threadId));
+
+	CleanupStack::PopAndDestroy(&apaSession);
+	if (aWait)
+		HandleShutdownL(threadId);
+	}
+
+void CSisLauncherServer::StartByMimeL(RFile& aFile, TDesC8& aMimeType, TBool aWait)
+	{
+	DEBUG_CODE_SECTION(
+	if (aWait)
+		{
+		DEBUG_PRINTF2(_L8("Sis Launcher Server - Attempting to start document by mimetype '%S' (filehandle supplied), waiting for termination."),
+			&aMimeType);
+		}
+	else
+		{
+		DEBUG_PRINTF2(_L8("Sis Launcher Server - Attempting to start document by mimetype '%S' (filehandle supplied), not waiting for termination."),
+			&aMimeType);
+		}
+	);
+
+	RApaLsSession apaSession;
+	User::LeaveIfError(apaSession.Connect());
+	CleanupClosePushL(apaSession);
+
+	TThreadId threadId;
+	TDataType dataType = TDataType(aMimeType);	
+	User::LeaveIfError(apaSession.StartDocument(aFile, dataType, threadId));
+
+	CleanupStack::PopAndDestroy(&apaSession);
+	if (aWait)
+		HandleShutdownL(threadId);
+	}
+	
+void CSisLauncherServer::StartDocumentL(const TDesC& aFileName, TBool aWait)
+	{
+	DEBUG_CODE_SECTION(
+	if (aWait)
+		{
+		DEBUG_PRINTF2(_L("Sis Launcher Server - Attempting to start document by filename '%S', waiting for termination."),
+			&aFileName);
+		}
+	else
+		{
+		DEBUG_PRINTF2(_L("Sis Launcher Server - Attempting to start document by filename '%S', not waiting for termination."),
+			&aFileName);
+		}
+	);
+
+	RApaLsSession apaSession;
+	User::LeaveIfError(apaSession.Connect());
+	CleanupClosePushL(apaSession);
+
+	TThreadId threadId;
+	User::LeaveIfError(apaSession.StartDocument(aFileName, threadId));
+
+	CleanupStack::PopAndDestroy(&apaSession);
+	if (aWait)
+		HandleShutdownL(threadId);
+	}
+
+void CSisLauncherServer::StartByMimeL(const TDesC& aFileName, TDesC8& aMimeType, TBool aWait)
+	{
+	DEBUG_CODE_SECTION(
+	if (aWait)
+		{
+		DEBUG_PRINTF2(_L("Sis Launcher Server - Attempting to start document by filename '%S', waiting for termination."),
+			&aFileName);
+		}
+	else
+		{
+		DEBUG_PRINTF2(_L("Sis Launcher Server - Attempting to start document by filename '%S', not waiting for termination."),
+			&aFileName);
+		}
+	);
+	DEBUG_PRINTF2(_L8("Sis Launcher Server - Supplied MIME type is '%S'."), &aMimeType);	
+
+	RApaLsSession apaSession;
+	User::LeaveIfError(apaSession.Connect());
+	CleanupClosePushL(apaSession);
+
+	TThreadId threadId;
+	TDataType dataType = TDataType(aMimeType);
+	User::LeaveIfError(apaSession.StartDocument(aFileName, dataType, threadId));
+
+	CleanupStack::PopAndDestroy(&apaSession);
+	if (aWait)
+		HandleShutdownL(threadId);
+	}
+
+void CSisLauncherServer::ShutdownL(TUid aUid, TInt aTimeout)
+	{
+	// This method shuts down running exes matching the SID provided in aUid.
+	// It first attempts a graceful shutdown, killing processes if a graceful
+	// shutdown is not supported or fails to work within aTimeout microseconds.
+
+	DEBUG_PRINTF2(_L8("Sis Launcher Server - Attempting to kill process with SID: 0x%08x."),
+		aUid.iUid);
+
+	TInt wgId=0;
+
+	CApaWindowGroupName* wgName = CApaWindowGroupName::NewL(iWsSession);
+	CleanupStack::PushL(wgName);
+	CApaWindowGroupName::FindByAppUid(aUid, iWsSession, wgId);
+	
+	while (wgId != KErrNotFound)
+		{	
+		wgName->ConstructFromWgIdL(wgId);
+		if(wgName->RespondsToShutdownEvent())
+			{
+			TApaTask task(iWsSession);
+			task.SetWgId(wgId);
+
+			RThread thread;
+			User::LeaveIfError(thread.Open(task.ThreadId()));
+			CleanupClosePushL(thread);
+			
+			RProcess process;
+			User::LeaveIfError(thread.Process(process));
+			CleanupClosePushL(process);
+
+			TRequestStatus processStatus;
+			process.Logon(processStatus);
+			
+			task.SendSystemEvent(EApaSystemEventShutdown);
+
+			RTimer timer;
+			CleanupClosePushL(timer);
+			TRequestStatus timerStatus;
+			timer.CreateLocal();
+			timer.After(timerStatus, aTimeout);
+
+			User::WaitForRequest(processStatus,timerStatus);
+
+			if (processStatus==KRequestPending)
+				{
+				// Failed to terminate gracefully, so kill the task.
+				DEBUG_PRINTF(_L8("Sis Launcher Server - Process did not die before timeout. Forcibly killing it."));
+				process.Kill(KErrNone);
+				}
+			else if (timerStatus==KRequestPending)
+				{
+				// Rendezvous completed so cancel timer
+				timer.Cancel();
+				}
+			// Handle second request
+			User::WaitForRequest(processStatus,timerStatus);
+			CleanupStack::PopAndDestroy(3, &thread);
+			}
+
+		// See if there's another instance of this App running.
+		CApaWindowGroupName::FindByAppUid(aUid, iWsSession, wgId);
+		}
+	CleanupStack::PopAndDestroy(wgName);
+	}
+
+void CSisLauncherServer::ShutdownL()
+	{
+	TInt wgId=0;
+    
+	CApaWindowGroupName* wgName = CApaWindowGroupName::NewL(iWsSession);
+	CleanupStack::PushL(wgName);
+	TBuf<1> matchAny;
+	matchAny.Append(KMatchAny);
+	CApaWindowGroupName::FindByCaption(matchAny, iWsSession, wgId);
+	while (wgId != KErrNotFound)
+		{
+		wgName->ConstructFromWgIdL(wgId);
+		//DEF057706 - shut down hidden apps during uninstallation if
+		// SH flag is specified
+		if (!wgName->IsSystem() /* && !wgName->Hidden() */)
+			{
+			// leave if we cannot shutdown the app because its busy
+			if(!wgName->IsBusy())
+				{
+				TApaTask task(iWsSession);
+				task.SetWgId(wgId);
+				// show shutdown dialog for this app?
+				task.SendSystemEvent(EApaSystemEventShutdown);
+				}
+			else
+				{
+				// could not shutdown an app
+				User::Leave(KErrInUse);
+				}
+			}
+	
+		// get next app to shutdown
+		CApaWindowGroupName::FindByCaption(matchAny, iWsSession, wgId);
+		}
+	CleanupStack::PopAndDestroy(wgName);
+	}
+
+void CSisLauncherServer::NotifyNewAppsL(const RPointerArray<TDesC>& aFiles)
+	{
+	RApaLsSession apaSession;
+	User::LeaveIfError(apaSession.Connect());
+	CleanupClosePushL(apaSession);
+
+	// UI frameworks advise ignoring the return code
+	apaSession.ForceRegistration(aFiles);
+
+	CleanupStack::PopAndDestroy();
+	}
+#endif
+
+