layouts/cdl/CdlServer/src/CdlSession.cpp
changeset 0 05e9090e2422
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/layouts/cdl/CdlServer/src/CdlSession.cpp	Thu Dec 17 09:14:12 2009 +0200
@@ -0,0 +1,390 @@
+/*
+* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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 "CdlServer.h"
+
+const TInt KCdlSessionMaxBuf = 0x100000; // 1 megabyte limit on IPC transfers
+
+CCdlSession::CCdlSession()
+	{
+	}
+
+CCdlServer& CCdlSession::Server()
+	{
+	return *static_cast<CCdlServer*>(const_cast<CServer2*>(CSession2::Server()));
+	}
+
+TBool CCdlSession::NotifyPending() const
+	{
+	return !iNotify.IsNull();
+	}
+
+void CCdlSession::CreateL()
+//
+// 2nd phase construct for sessions - called by the CServer2 framework
+//
+	{
+	Server().AddSession();
+	}
+
+CCdlSession::~CCdlSession()
+	{
+	delete iTempBuf;
+	delete iSendingBuf;
+	delete iSendingState;
+	Server().DropSession();
+	}
+
+void CCdlSession::ServiceL(const RMessage2& aMessage)
+//
+// Handle a client request.
+// Leaving is handled by CCdlServer::RunError() which reports the error code
+// to the client
+//
+	{
+	switch (aMessage.Function())
+		{
+		case ECdlServCmdRequestGetCust:
+			RequestGetCustL(aMessage);
+			break;
+
+		case ECdlServCmdGetCust:
+			GetCustL(aMessage);
+			break;
+
+		case ECdlServCmdSetUidsToNotify:
+			SetUidsToNotifyL(aMessage);
+			break;
+
+		case ECdlServCmdNotifyChange:
+			NotifyChangeL(aMessage);
+			break;
+
+		case ECdlServCmdCancelNotifyChange:
+			CancelNotifyChangeL(aMessage);
+			break;
+
+		case ECdlServCmdSetCust:
+			SetCustL(aMessage);
+			break;
+
+		case ECdlServCmdGetRefsSize:
+			GetRefsSizeL(aMessage);
+			break;
+
+		case ECdlServCmdGetNamesSize:
+			GetNamesSizeL(aMessage);
+			break;
+
+		case ECdlServCmdGetTempBuf:
+			GetTempBufL(aMessage);
+			break;
+
+		case ECdlServCmdGetAllRefsSize:
+			GetAllRefsSizeL(aMessage);
+			break;
+
+		case ECdlServCmdIsPluginInRom:
+			IsPluginInRomL(aMessage);
+			break;
+
+		case ECdlServCmdPluginDrive:
+			PluginDriveL(aMessage);
+			break;
+
+		default:
+			PanicClient(aMessage,EPanicIllegalFunction);
+			break;
+		}
+	}
+
+void CCdlSession::RequestGetCustL(const RMessage2& aMessage)
+	{
+	if (iSendingBuf)
+		{
+		aMessage.Complete(KErrNotReady);
+		return;
+		}
+
+	// get the uids from the client
+	CCdlUids* uids = CCdlUids::NewLC();
+	HBufC8* buf = HBufC8::NewMaxLC(ValidIntL(aMessage.Int2(), 0, KCdlSessionMaxBuf));
+	TPtr8 ptr = buf->Des();
+	aMessage.ReadL(1, ptr);
+	uids->ImportL(*buf);
+	CleanupStack::PopAndDestroy(buf);
+
+	// get the size of the requested customisation
+	delete iSendingState;
+	iSendingState = 0;
+	delete iSendingBuf;
+	iSendingBuf = 0;
+	CCdlRefs* sendingState = Server().GetStateLC(*uids);
+	iSendingBuf = sendingState->ExportL();
+	iSendingState = sendingState;
+	TInt size=iSendingBuf->Size();
+	CleanupStack::Pop(sendingState);
+	CleanupStack::PopAndDestroy(uids);
+
+	// send the size to the client
+	TPckg<TInt> sizePckg(size);
+	WriteAndComplete(aMessage, 0, sizePckg);
+	}
+
+void CCdlSession::GetCustL(const RMessage2& aMessage)
+	{
+	if (!iSendingBuf)
+		{
+		PanicClient(aMessage, EPanicNoCustomisationRequested);
+		return;
+		}
+
+	if (iSendingBuf->Size() > aMessage.Int1())
+		{
+		TInt size=iSendingBuf->Size();
+		TPckg<TInt> sizePckg(size);
+		WriteAndComplete(aMessage, 2, sizePckg, KCdlRefsSizeChanged);
+		return;
+		}
+
+	WriteAndComplete(aMessage, 0, *iSendingBuf);
+	delete iSendingBuf;
+	iSendingBuf = 0;
+	delete iSendingState;
+	iSendingState = 0;
+	iQueuedCustChange = EFalse;
+	}
+
+void CCdlSession::SetUidsToNotifyL(const RMessage2& aMessage)
+	{
+	HBufC8* buf = HBufC8::NewMaxLC(ValidIntL(aMessage.Int1(), 0, KCdlSessionMaxBuf));
+	TPtr8 ptr = buf->Des();
+	aMessage.ReadL(0, ptr);
+	iUids.ImportL(*buf);
+	CleanupStack::PopAndDestroy(buf);
+	aMessage.Complete(KErrNone);
+	}
+
+void CCdlSession::NotifyChangeL(const RMessage2& aMessage)
+	{
+	if (NotifyPending())
+		PanicClient(aMessage,EPanicNotifyActive);
+	else
+		iNotify=aMessage;
+
+	if (iQueuedCustChange)
+		{
+		NotifyCustChangeL();
+		}
+	else if (iQueuedRefsChange)
+		{
+		HandleRefsChangeL();
+		}
+	}
+
+void CCdlSession::CancelNotifyChangeL(const RMessage2& aMessage)
+	{
+	if (NotifyPending())
+		iNotify.Complete(KErrCancel);
+	aMessage.Complete(KErrNone);
+	}
+
+void CCdlSession::SetCustL(const RMessage2& aMessage)
+	{
+	CCdlRefs* state = CCdlRefs::NewLC();
+	HBufC8* buf = HBufC8::NewMaxLC(ValidIntL(aMessage.Int1(), 0, KCdlSessionMaxBuf));
+	TPtr8 ptr = buf->Des();
+	aMessage.ReadL(0, ptr);
+	state->ImportL(*buf);
+	CleanupStack::PopAndDestroy(buf);
+	Server().SetStateL(state);
+	CleanupStack::PopAndDestroy(state);
+	aMessage.Complete(KErrNone);
+	}
+
+void CCdlSession::NotifyCustChangeL()
+	{
+	if (NotifyPending())
+		{
+		TPckgBuf<SCdlServerChange> change;
+		change().iType = SCdlServerChange::EGlobalCustomisation;
+		change().iSize = iSendingBuf->Size();
+		WriteAndComplete(iNotify, 0, change);
+		iQueuedCustChange = EFalse;
+		}
+	else
+		{
+		iQueuedCustChange = ETrue;
+		}
+	}
+
+void CCdlSession::WriteAndComplete(const RMessagePtr2& aMessage, TInt aParam, const TDesC8& aDes, TInt aCode)
+	{
+	TRAPD(r,aMessage.WriteL(aParam, aDes));
+	if (r==KErrNone)
+		aMessage.Complete(aCode);
+	else
+		PanicClient(aMessage, EPanicBadDescriptor);
+	}
+
+void CCdlSession::HandleCustChangeL(const CCdlUids& aUids)
+	{
+	CCdlUids* change = iUids.IntersectionLC(aUids);
+	if (change->Count())
+		{
+		if (iSendingBuf == NULL)
+			{
+			iSendingState = Server().GetStateLC(*change);
+			CleanupStack::Pop(iSendingState);
+			iSendingBuf = iSendingState->ExportL();
+			NotifyCustChangeL();
+			}
+		else
+			{
+			iSendingState->MergeAndReplaceL(*Server().GetStateLC(*change));
+			CleanupStack::PopAndDestroy(); // change in state;
+			delete iSendingBuf;
+			iSendingBuf = 0;
+			iSendingBuf = iSendingState->ExportL();
+			// don't notify change in state for ongoing transaction
+			}
+		}
+
+	CleanupStack::PopAndDestroy(change);
+	}
+
+void CCdlSession::HandleRefsChangeL()
+	{
+	if (NotifyPending())
+		{
+		TPckgBuf<SCdlServerChange> change;
+		change().iType = SCdlServerChange::EAvailableRefs;
+		WriteAndComplete(iNotify, 0, change);
+		iQueuedRefsChange = EFalse;
+		}
+	else
+		{
+		iQueuedRefsChange = ETrue;
+		}
+	}
+
+void CCdlSession::GetRefsSizeL(const RMessage2& aMessage)
+	{
+	delete iTempBuf;
+	iTempBuf = 0;
+
+	if (aMessage.Int1())	// Get by name
+		{
+		HBufC* buf = HBufC::NewMaxLC(ValidIntL(aMessage.Int2(), 0, KMaxFileName));
+		TPtr ptr = buf->Des();
+		aMessage.ReadL(1, ptr);
+		CCdlRefs* refs = Server().AllRefs().SubsetByNameLC(*buf);
+		if (refs->CountRefs() == 0)	// library not found in server, perhaps not scanned yet.
+			{
+			CCdlRefCollection* contents = Server().FileContentsLC(*buf);
+			refs->AppendL(*contents);
+			CleanupStack::PopAndDestroy(contents);
+			}
+		iTempBuf = refs->ExportL();
+		CleanupStack::PopAndDestroy(refs);
+		CleanupStack::PopAndDestroy(buf);
+		}
+	else					// Get by UID
+		{
+		iTempBuf = Server().AllRefs().SubsetByUidLC(TUid::Uid(aMessage.Int3()))->ExportL();
+		CleanupStack::PopAndDestroy();		// unnamed CCdlRefs
+		}
+
+	// send the size to the client
+	TPckgBuf<TInt> sizePckg(iTempBuf->Size());
+	WriteAndComplete(aMessage, 0, sizePckg);
+	}
+
+void CCdlSession::GetAllRefsSizeL(const RMessage2& aMessage)
+	{
+	delete iTempBuf;
+	iTempBuf = 0;
+	iTempBuf = Server().AllRefs().ExportL();
+
+	// send the size to the client
+	TPckgBuf<TInt> sizePckg(iTempBuf->Size());
+	WriteAndComplete(aMessage, 0, sizePckg);
+	}
+
+void CCdlSession::GetNamesSizeL(const RMessage2& aMessage)
+	{
+	delete iTempBuf;
+	iTempBuf = 0;
+	iTempBuf = Server().AllRefs().Names().ExportL();
+
+	// send the size to the client
+	TPckgBuf<TInt> sizePckg(iTempBuf->Size());
+	WriteAndComplete(aMessage, 0, sizePckg);
+	}
+
+void CCdlSession::GetTempBufL(const RMessage2& aMessage)
+	{
+	if (iTempBuf)
+		{
+		WriteAndComplete(aMessage, 0, *iTempBuf);
+		delete iTempBuf;
+		iTempBuf = 0;
+		}
+	else
+		{
+		// This message can only be used after one of the messages that
+		// set up iTempBuf
+		PanicClient(aMessage, EPanicBufRequestedWithoutSetup);
+		}
+	}
+
+void CCdlSession::IsPluginInRomL(const RMessage2& aMessage)
+	{
+	HBufC* fileBuf = HBufC::NewMaxLC(ValidIntL(aMessage.Int1(), 0, KMaxFileName));
+	TPtr filePtr = fileBuf->Des();
+	aMessage.ReadL(0, filePtr);
+
+	TPckgBuf<TBool> isInRomPckg(EFalse);
+	TInt err = Server().IsPluginInRom(*fileBuf, isInRomPckg());
+	CleanupStack::PopAndDestroy(fileBuf);
+	
+	WriteAndComplete(aMessage, 2, isInRomPckg, err);
+	}
+
+void CCdlSession::PluginDriveL(const RMessage2& aMessage)
+	{
+	HBufC* fileBuf = HBufC::NewMaxLC(ValidIntL(aMessage.Int1(), 0, KMaxFileName));
+	TPtr filePtr = fileBuf->Des();
+	aMessage.ReadL(0, filePtr);
+
+	TDriveUnit drive;
+	TInt err = Server().PluginDrive(*fileBuf, drive);
+	CleanupStack::PopAndDestroy(fileBuf);
+
+	aMessage.Complete(err ? err : static_cast<TInt>(drive));
+	}
+
+TInt CCdlSession::ValidIntL(TInt aVal, TInt aMin, TInt aMax) const
+	{
+	if (aVal < aMin || aMax < aVal)
+		{
+		User::Leave(KErrArgument);
+		}
+	return aVal;
+	}
+