os/graphics/windowing/windowserver/nga/SERVER/GRAPHICDRAWER.CPP
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #include "server.h"
    17 #include "WSGRAPHICDRAWERFACTORY.H"
    18 #include "panics.h"
    19 #include <s32mem.h>
    20 #include "wstop.h"
    21 
    22 TInt CWsGraphicDrawerObject::TransientSequence=1;
    23 TBool CWsGraphicDrawerObject::RollOver=EFalse;
    24 
    25 CWsGraphicDrawerObject* CWsGraphicDrawerObject::NewL(CWsClient* aClient,const TWsClCmdUnion &aParams)
    26 	{
    27 	if(!aClient)
    28 		{
    29 		WS_PANIC_DEBUG(EWsPanicWsGraphic);
    30 		User::Leave(KErrGeneral);
    31 		}
    32 	TGraphicDrawerId id;
    33 	id.iId = aParams.CreateGraphic->iId;
    34 	id.iIsUid = !(EWsGraphicIdTransient & aParams.CreateGraphic->iFlags);
    35 	// check for collision
    36 	const CWsGraphicDrawer* dup = CWsTop::WindowServer()->ResolveGraphic(id);
    37 	// request-specific checks
    38 	if(dup)
    39 		{
    40 		// must be exact same session
    41 		if(&(dup->Owner()) != aClient)
    42 			{
    43 			/*	Someone is squatting on someone else's uid, or trying to,
    44 				but there is no good way to know which. */
    45 			__DEBUG_ONLY(aClient->PPanic(EWservPanicPermissionDenied);)
    46 			User::Leave(KErrAlreadyExists);
    47 			}
    48 		// dupping or otherwise must be explicitly intended by the client
    49 		if(!(EWsGraphicReplace & aParams.CreateGraphic->iFlags))
    50 			{
    51 			aClient->PPanic(EWservPanicPermissionDenied);
    52 			}
    53 		}
    54 	else
    55 		{
    56 		// dupping or otherwise must be explicitly intended by the client
    57 		if(EWsGraphicReplace & aParams.CreateGraphic->iFlags)
    58 			{
    59 			aClient->PPanic(EWservPanicPermissionDenied);
    60 			}
    61 		if(id.iIsUid)
    62 			{
    63 			// police creation of artwork with UIDs
    64 			_LIT_SECURITY_POLICY_C1(KSecurityPolicyCreateWithUid,ECapabilityProtServ);
    65 			if(!KSecurityPolicyCreateWithUid.CheckPolicy(aClient->Client()))
    66 				{
    67 				__DEBUG_ONLY(aClient->PPanic(EWservPanicPermissionDenied);)
    68 				User::Leave(KErrPermissionDenied);
    69 				}
    70 			}
    71 		else
    72 			{
    73 			// allocate a new transient id
    74 			// assumption: that there are more values of a TInt than there are possibly Transient objects
    75 			do
    76 				{
    77 				id.iId = TransientSequence++;
    78 				RollOver |= !TransientSequence;
    79 				}
    80 			while(RollOver && CWsTop::WindowServer()->ResolveGraphic(id)); // until no collision
    81 			}
    82 		}
    83 	// create the drawer object
    84 	TPtrC8 data;
    85 	HBufC8* dataBuf = NULL;
    86 	if(aParams.CreateGraphic->iRemoteReadData)
    87 		{
    88 		const TInt len = aParams.CreateGraphic->iDataLen;
    89 		if ((len >= KMaxTInt/4) || (len < 0))
    90 			aClient->PPanic(EWservPanicBuffer);
    91 		dataBuf = HBufC8::NewLC(len);
    92 		TPtr8 des = dataBuf->Des();
    93 		aClient->RemoteRead(des,0);
    94 		if(des.Size() != len)
    95 			{
    96 			aClient->PPanic(EWservPanicBuffer);
    97 			}
    98 		data.Set(des);
    99 		}
   100 	else
   101 		{
   102 		data.Set(CWsClient::BufferTPtr8((TText8*)(aParams.CreateGraphic+1),aParams.CreateGraphic->iDataLen));
   103 		}
   104 
   105 	CWsGraphicDrawerObject* drawer = new(ELeave) CWsGraphicDrawerObject(aClient);
   106 	CleanupStack::PushL(drawer);
   107 	drawer->ConstructL(aParams.CreateGraphic->iType,*CWsTop::WindowServer(),id,data,aParams.CreateGraphic->iClientHandle);
   108 	if(!dup)
   109 		{
   110 		User::LeaveIfError(CWsTop::WindowServer()->AddGraphicDrawer(drawer->Drawer()));
   111 		}
   112 	else
   113 		{
   114 		User::LeaveIfError(CWsTop::WindowServer()->SwapGraphicDrawer(drawer->Drawer()));
   115 		}
   116 	// take off cleanup stack
   117 	CleanupStack::Pop(drawer);
   118 	if(dataBuf)
   119 		{
   120 		CleanupStack::PopAndDestroy(dataBuf);
   121 		}
   122 	// delete dup, which means resolving the object that encapsulates it
   123 	if(dup)
   124 		{
   125 		CWsGraphicDrawerObject* obj = aClient->DrawerObject(dup);
   126 		WS_ASSERT_DEBUG(obj, EWsPanicWsGraphic);
   127 		if(obj)
   128 			{
   129 			obj->CloseObject();
   130 			}
   131 		}
   132 	// trigger redraws if anyone is drawing this graphic before it exists
   133 	if(id.iIsUid)
   134 		{
   135 		CWsTop::WindowServer()->Invalidate(id);
   136 		}
   137 	// done
   138 	return drawer;
   139 	}
   140 
   141 CWsGraphicDrawerObject::CWsGraphicDrawerObject(CWsClient* aOwner):
   142 	CWsObject(aOwner,WS_HANDLE_GRAPHIC_DRAWER)
   143 	{
   144 	}
   145 
   146 CWsGraphicDrawerObject::~CWsGraphicDrawerObject()
   147 	{
   148 	delete iDrawer;
   149 	}
   150 
   151 void CWsGraphicDrawerObject::ConstructL(TUid aType,MWsGraphicDrawerEnvironment& aEnv,const TGraphicDrawerId& aId,const TDesC8& aData,TInt aClientHandle)
   152 	{
   153 	CWsGraphicDrawer* drawer = WsGraphicDrawer::CreateLC(aType,aEnv,aId,*WsOwner(),aData);
   154 	NewObjL();
   155 	iClientHandle = aClientHandle;
   156 	iDrawer=drawer;
   157 	CleanupStack::Pop(iDrawer);
   158 	}
   159 
   160 void CWsGraphicDrawerObject::CommandL(TInt aOpcode, const TAny *aCmdData)
   161 	{
   162 	WS_ASSERT_DEBUG(iDrawer, EWsPanicWsGraphic);
   163 	
   164 	if(iDrawer)
   165 		{
   166 		TWsClCmdUnion pData;
   167 		pData.any = aCmdData;
   168 		switch(aOpcode)
   169 			{
   170 			case EWsGdOpFree:
   171 				// trigger redraws if anyone is drawing this graphic before it exists
   172 				CWsTop::WindowServer()->RemoveGraphicDrawer(iDrawer->Id());
   173 				CloseObject();
   174 				return;
   175 			case EWsGdOpSendMsg:
   176 			case EWsGdOpSendSynchronMsg:
   177 				{
   178 				const TWsClCmdGdSendMessage& cmd = *pData.GraphicSendMessage;
   179 				__ASSERT_DEBUG(cmd.iDataLen,WsOwner()->PPanic(EWservPanicPermissionDenied));
   180 				if(cmd.iDataLen)
   181 					{
   182 					if(cmd.iRemoteReadData)
   183 						{
   184 						HBufC8* wsAlloc = NULL;
   185 						TUint8* drawerAlloc = NULL;
   186 						TPtr8 des(NULL,0);
   187 						// try to get the drawer to allocate for us
   188 						MWsGraphicDrawerMessageAlloc* drawerAllocator = iDrawer->ObjectInterface<MWsGraphicDrawerMessageAlloc>();
   189 						if(drawerAllocator)
   190 							{
   191 							drawerAlloc = reinterpret_cast<TUint8*>(drawerAllocator->Alloc(cmd.iDataLen));
   192 							if(drawerAlloc)
   193 								des.Set(drawerAlloc,0,cmd.iDataLen);
   194 							}
   195 						// else use the normal WSERV default heap
   196 						if(!drawerAlloc)
   197 							{
   198 							wsAlloc = HBufC8::NewLC(cmd.iDataLen);
   199 							des.Set(wsAlloc->Des());
   200 							}
   201 						// fetch
   202    						WsOwner()->RemoteRead(des,0);
   203 						TBool receivedOk = (des.Size() == cmd.iDataLen);
   204 						// dispatch
   205 						if(receivedOk)
   206 							{
   207 							if(aOpcode == EWsGdOpSendMsg)
   208 								{
   209 								iDrawer->HandleMessage(des);
   210 								}
   211 							else
   212 								{
   213 								MWsGraphicHandleSynchronMessage* obj = iDrawer->ObjectInterface<MWsGraphicHandleSynchronMessage>();
   214 
   215 								if(obj)
   216 									SetReply(obj->HandleSynchronMessage(des));
   217 								else
   218 									SetReply(KErrNotSupported);
   219 								}
   220 							}
   221 
   222 						// dealloc
   223 						if(drawerAlloc)
   224 							{
   225 							drawerAllocator->Free(drawerAlloc);
   226 							}
   227 						else
   228 							{
   229 							CleanupStack::PopAndDestroy(wsAlloc);
   230 							}
   231 						// defer panic until after dealloc
   232 						if(!receivedOk)
   233 							{
   234 							WsOwner()->PPanic(EWservPanicBuffer);
   235 							}
   236 						}
   237 					else
   238 						{
   239 						const TPtrC8 data = CWsClient::BufferTPtr8((TText8*)(pData.GraphicSendMessage+1),cmd.iDataLen);
   240 						if(aOpcode == EWsGdOpSendMsg)
   241 							{
   242 							iDrawer->HandleMessage(data);
   243 							}
   244 						else
   245 							{
   246 							MWsGraphicHandleSynchronMessage* obj = iDrawer->ObjectInterface<MWsGraphicHandleSynchronMessage>();
   247 							if(obj)
   248 								SetReply(obj->HandleSynchronMessage(data));
   249 							else
   250 								SetReply(KErrNotSupported);
   251 							}
   252 						}
   253 					}
   254 				}
   255 				break;
   256 			case EWsGdOpGetGraphicId:
   257 				{
   258 				__ASSERT_COMPILE(sizeof(TWsClCmdGdGetId) == sizeof(TGraphicDrawerId));
   259 				const TGraphicDrawerId id = iDrawer->Id();
   260 				CWsClient::ReplyBuf(&id,sizeof(id));
   261 				}
   262 				break;
   263 			case EWsGdOpShareGlobally:
   264 				SetReply(iDrawer->ShareGlobally());
   265 				break;
   266 			case EWsGdOpUnShareGlobally:
   267 				SetReply(iDrawer->UnShareGlobally());
   268 				break;
   269 			case EWsGdOpShare:
   270 				{
   271 				const TSecureId& secid = *reinterpret_cast<const TSecureId*>(aCmdData);
   272 				SetReply(iDrawer->Share(secid));
   273 				break;
   274 				}
   275 			case EWsGdOpUnShare:
   276 				{
   277 				const TSecureId& secid = *reinterpret_cast<const TSecureId*>(aCmdData);
   278 				SetReply(iDrawer->UnShare(secid));
   279 				break;
   280 				}
   281 			default:
   282 				WsOwner()->PPanic(EWservPanicOpcode);
   283 			}
   284 		}
   285 	}
   286 
   287 CWsGraphicDrawer* CWsGraphicDrawerObject::Drawer()
   288 	{
   289 	return iDrawer;
   290 	}
   291 
   292 const CWsGraphicDrawer* CWsGraphicDrawerObject::Drawer() const
   293 	{
   294 	return iDrawer;
   295 	}
   296 
   297 // CWsGraphicMessageQueue \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
   298 
   299 CWsGraphicMessageQueue::CMessage* CWsGraphicMessageQueue::CMessage::New(const TDesC8& aData)
   300    	{
   301 	return new(aData.Size()) CMessage(aData);
   302    	}
   303 
   304 CWsGraphicMessageQueue::CMessage::CMessage(const TDesC8& aData):
   305 	iData((reinterpret_cast<TUint8*>(this)+sizeof(*this)),aData.Size())
   306    	{
   307 	iData = aData;
   308    	}
   309 
   310 TPtrC8 CWsGraphicMessageQueue::CMessage::Data() const
   311 	{
   312 	return iData;
   313    	}
   314 
   315 void CWsGraphicMessageQueue::CMessage::Release()
   316 	{
   317 	delete this;
   318    	}
   319 
   320 CWsGraphicMessageQueue::CMessage::~CMessage()
   321    	{
   322    	}
   323 
   324 CWsGraphicMessageQueue::CWsGraphicMessageQueue(CWsClient *aOwner):
   325 	CEventBase(aOwner)
   326 	{
   327 	}
   328 
   329 CWsGraphicMessageQueue::~CWsGraphicMessageQueue()
   330 	{
   331 	while(iHead)
   332 		{
   333 		CWsMessageData* msg = iHead;
   334 		iHead = iHead->iNext;
   335 		msg->Release();
   336 		}
   337 	}
   338 
   339 TInt CWsGraphicMessageQueue::TopClientHandle() const
   340 	{
   341 	if(iHead)
   342 		return iHead->iClientHandle;
   343 	else
   344 		return KErrNotFound;
   345 	}
   346 
   347 /** 
   348 same functionality as CEventBase::GetData, but this one also inserts the integer header in the reply.
   349 */
   350 void CWsGraphicMessageQueue::GetDataWithHeader(TUint aHeader, const TDesC8& aData, TInt aDataLen)
   351 	{
   352 	TPckgBuf<TUint> hdr = aHeader | (EWsGraphMessageTypeUser & 0x03);
   353 	CWsClient::ReplyBuf(hdr.Ptr(), sizeof(TUint));
   354 	GetData((void*)aData.Ptr(), aDataLen);
   355 	}
   356 
   357 void CWsGraphicMessageQueue::GetGraphicMessage()
   358 	{
   359 	CWsMessageData* top = Pop();
   360 	WS_ASSERT_DEBUG(top && top->Data().Length(), EWsPanicWsGraphic);
   361 	if(top)
   362 		{
   363 		GetDataWithHeader(top->iClientHandle, top->Data(), top->Data().Size());
   364 		CWsGraphicDrawerObject* obj = iWsOwner->DrawerObject(top->iDrawer);
   365 		if(obj)
   366 			{
   367 			MWsGraphicMessageCallback* messageCallback = obj->Drawer()->ObjectInterface<MWsGraphicMessageCallback>();
   368 			if(messageCallback)
   369 				{
   370 				messageCallback->HandleMessageDelivery(top->iId, KErrNone);
   371 				}
   372 			}
   373 
   374 		top->Release();
   375 		}
   376 	}
   377 
   378 void CWsGraphicMessageQueue::AbortMessage(TInt aError)
   379 	{
   380 	CWsMessageData* top = Pop();
   381 	WS_ASSERT_DEBUG(top, EWsPanicWsGraphic);
   382 	if(top)
   383 		{
   384 		CWsGraphicDrawerObject* obj = iWsOwner->DrawerObject(top->iDrawer);
   385 		if(obj)
   386 			{
   387 			MWsGraphicMessageCallback* messageCallback = obj->Drawer()->ObjectInterface<MWsGraphicMessageCallback>();
   388 			if(messageCallback)
   389 				{
   390 				messageCallback->HandleMessageDelivery(top->iId, aError);
   391 				}
   392 			}
   393 		top->Release();
   394 		}
   395 	}
   396 
   397 void CWsGraphicMessageQueue::EventReady(const RMessagePtr2& aEventMsg)
   398 	{
   399 	CEventBase::EventReady(aEventMsg);
   400 	if(iHead)
   401 		{
   402 		SignalEvent(sizeof(TInt) + iHead->Data().Size());
   403 		}
   404 	}
   405 
   406 
   407 void CWsGraphicMessageQueue::Queue(CWsMessageData* aMessage)
   408 	{
   409 	WS_ASSERT_DEBUG(aMessage && !aMessage->iNext, EWsPanicWsGraphic);
   410 	if(aMessage)
   411 		{
   412 		if(iHead)
   413 			{
   414 			iTail->iNext = aMessage;
   415 			iTail = aMessage;
   416 			}
   417 		else
   418 			{
   419 			iHead = iTail = aMessage;
   420 			if(!iEventMsg.IsNull())
   421 				SignalEvent(sizeof(TInt) + iHead->Data().Size());
   422 			}
   423 		}
   424 	}
   425 
   426 CWsMessageData* CWsGraphicMessageQueue::Pop()
   427 	{
   428 	CWsMessageData* ret = NULL;
   429 	if(iHead)
   430 		{
   431 		ret = iHead;
   432 		iHead = iHead->iNext;
   433 		}
   434 	return ret;
   435 	}