os/security/authorisation/userpromptservice/server/source/upsserver/authoriser.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/security/authorisation/userpromptservice/server/source/upsserver/authoriser.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,844 @@
     1.4 +/*
     1.5 +* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.6 +* All rights reserved.
     1.7 +* This component and the accompanying materials are made available
     1.8 +* under the terms of the License "Eclipse Public License v1.0"
     1.9 +* which accompanies this distribution, and is available
    1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.11 +*
    1.12 +* Initial Contributors:
    1.13 +* Nokia Corporation - initial contribution.
    1.14 +*
    1.15 +* Contributors:
    1.16 +*
    1.17 +* Description: 
    1.18 +* Implements CAuthoriser.	 See class and function definitions for
    1.19 +* more information.
    1.20 +*
    1.21 +*/
    1.22 +
    1.23 +
    1.24 +/**
    1.25 + @file
    1.26 +*/
    1.27 +
    1.28 +#include "upsserver.h"
    1.29 +#include "policycache.h"
    1.30 +#include "authoriser.h"
    1.31 +#include <ups/upsdbw.h>
    1.32 +#include "upslog.h"
    1.33 +#include <ups/dialogcreator.h>
    1.34 +#include <ups/policyevaluator.h>
    1.35 +
    1.36 +namespace UserPromptService
    1.37 +{
    1.38 +
    1.39 +CAuthoriser* CAuthoriser::NewL(RPolicyCacheCountedHandle &aPolicyCache,
    1.40 +								   CUpsSession* aSession, CUpsSubsession* aSubsession, TBool aServerCheckOk,
    1.41 +								   TThreadId &aClientTid, TProcessId &aClientPId,
    1.42 +								   const RMessage2& aMessage, const TServiceId& aServiceId,
    1.43 +								   RBuf &aDestination, RBuf8 &aOpaqueData)
    1.44 +	/**
    1.45 +	   Factory function allocates a new, initialized instance of CAuthoriser,
    1.46 +	   registered for the supplied session and subsession.
    1.47 +	   
    1.48 +	   If construction is successful, the caller should pass ownership to
    1.49 +	   the SCS framework (TransferToScsFrameworkL), and pop the
    1.50 +	   CAuthoriser from the cleanupstack. From this point onwards the
    1.51 +	   request should be completed by the CAuthoriser/CAsyncRequst code,
    1.52 +	   so the caller must not return or leave with any code except
    1.53 +	   KErrScsSetupAsync. This is why the StartProcessingRequest function
    1.54 +	   is defined as non-leaving.
    1.55 +
    1.56 +	   @param	aPolicyCache	The server policy cache manager.
    1.57 +	   @param	aSession		Session on which this request was launched.
    1.58 +	   @param	aSubsession		Subsession on which this request was launched.
    1.59 +	   @param	aServerCheckOk	Did the system server checks pass?
    1.60 +	   @param	aClientThread	Handle to the user client thread.
    1.61 +	   @param	aMessage		Standard server-side handle to message.
    1.62 +	   @param	aDestination	We take ownership of the RBuf and close the callers handle
    1.63 +	   @param	aOpaqueData		We take ownership of the RBuf and close the callers handle
    1.64 +	   @return					New, initialized instance of CAuthoriser, which
    1.65 +	   is owned by the server's collection of outstanding
    1.66 +	   requests.
    1.67 +	*/
    1.68 +	{
    1.69 +	CAuthoriser* self = new(ELeave) CAuthoriser(aPolicyCache, aSession, aSubsession, aMessage);
    1.70 +	CleanupStack::PushL(self);
    1.71 +	self->ConstructL(aServerCheckOk, aClientTid, aClientPId, aServiceId, aDestination, aOpaqueData);
    1.72 +	CleanupStack::Pop(self);
    1.73 +	return self;
    1.74 +	}
    1.75 +
    1.76 +CAuthoriser::CAuthoriser(RPolicyCacheCountedHandle &aPolicyCache,
    1.77 +						   CUpsSession* aSession, CUpsSubsession* aSubsession,
    1.78 +						   const RMessage2& aMessage)
    1.79 +	/**
    1.80 +	   This private constructor initializes the superclass and prevents direct instantiation.
    1.81 +
    1.82 +	   @param	aPolicyCache		The server policy cache manager.
    1.83 +	   @param	aSession			Session on which this request was launched.
    1.84 +	   @param	aSubsession		Subsession on which this request was launched.
    1.85 +	   @param	aMessage		Standard server-side handle to message.
    1.86 +	   @param	aDestination	HBufC description, takes ownership.
    1.87 +	   @param	aOpaqueData		0 or HBufC opaqueData, takes ownership.
    1.88 +	*/
    1.89 +	:	CAsyncRequest(aSession, aSubsession, aMessage),
    1.90 +		iPolicyCache(aPolicyCache)
    1.91 +	{
    1.92 +	// empty.
    1.93 +	}
    1.94 +
    1.95 +void CAuthoriser::ConstructL(TBool aServerCheckOk, TThreadId &aClientTid, TProcessId &aClientPid, const TServiceId& aServiceId, RBuf &aDestination, RBuf8 &aOpaqueData)
    1.96 +	/**
    1.97 +	   Second-phase constructor allocates the timer which is used to generate
    1.98 +	   a delay, and adds this object to the server's collection of outstanding
    1.99 +	   requests.
   1.100 +	*/
   1.101 +	{
   1.102 +	iState = ECheckPolicy;
   1.103 +
   1.104 +	RProcess clientProcess;
   1.105 +	TInt r = clientProcess.Open(aClientPid);
   1.106 +	if(r != KErrNone)
   1.107 +		{
   1.108 +		User::Leave(KErrUpsBadClientProcessId);
   1.109 +		}
   1.110 +	CleanupClosePushL(clientProcess);
   1.111 +	
   1.112 +	// Create a CPromptReqest for the policy lookup
   1.113 +	iPromptRequest = CPromptRequest::NewL(clientProcess.SecureId(), // Client details
   1.114 +										  clientProcess.VendorId(),
   1.115 +										  aClientTid,
   1.116 +										  aClientPid,
   1.117 +										  iMessagePtr2.SecureId(), // Server SID
   1.118 +										  aServiceId, // Server service ID
   1.119 +										  aDestination, // Request detail, takes ownership
   1.120 +										  aOpaqueData,	//				   takes ownership
   1.121 +										  aServerCheckOk); 
   1.122 +	
   1.123 +	CleanupStack::PopAndDestroy(&clientProcess);
   1.124 +	}
   1.125 +
   1.126 +void CAuthoriser::ProcessEventL(TAuthoriserEvent aEvent)
   1.127 +	{
   1.128 +	//	DEBUG_PRINTF4(_L8("0x%x CAuthoriser::ProcessEventL state %d, event %d\n"), this, iState, aEvent);
   1.129 +	_LIT(KServerPanicState, "UPS-ProcessEventL");
   1.130 +	switch(iState)
   1.131 +		{
   1.132 +		case ECheckPolicy:
   1.133 +			CheckPolicyStateL(aEvent);
   1.134 +			return;
   1.135 +		case ECreatingFingerprints:
   1.136 +			CreatingFingerprintsStateL(aEvent);
   1.137 +			return;
   1.138 +		case ECheckDatabase:
   1.139 +			CheckDatabaseStateL(aEvent);
   1.140 +			return;
   1.141 +		case EPreparingDialog:
   1.142 +			PreparingDialogStateL(aEvent);
   1.143 +			return;
   1.144 +		case EExecutingDialog:
   1.145 +			ExecutingDialogStateL(aEvent);
   1.146 +			return;
   1.147 +BULLSEYE_OFF
   1.148 +		}
   1.149 +	
   1.150 +	// Should not get here
   1.151 +	User::Panic(KServerPanicState, iState);
   1.152 +BULLSEYE_RESTORE
   1.153 +	}
   1.154 +
   1.155 +
   1.156 +void CAuthoriser::CheckPolicyStateL(TAuthoriserEvent aEvent)
   1.157 +	{
   1.158 +	switch(aEvent)
   1.159 +		{
   1.160 +		case EInternalRequestComplete:
   1.161 +			// Caused by the ups sub session code calling Wakeup
   1.162 +			// to start the request processing. We are now within the
   1.163 +			// active scheduler error handling framework.
   1.164 +
   1.165 +			// This call will lookup the policy and move to the next
   1.166 +			// state, or leave.
   1.167 +			LookupPolicyL();
   1.168 +			break;
   1.169 +
   1.170 +			BULLSEYE_OFF
   1.171 +		case EClearedToDisplayDialog:
   1.172 +			ASSERT(EFalse);
   1.173 +			break;
   1.174 +			BULLSEYE_RESTORE
   1.175 +
   1.176 +		case ECancel:
   1.177 +			// This WILL happen if am authorise request is made and immediately cancelled (before CAuthoriser::Runl has
   1.178 +			// the chance to run). We should complete our "fake" internal request so we do not block
   1.179 +			// when we return to the DoCancel/CActive::Cancel which caused this event.
   1.180 +			CompleteSelf();
   1.181 +			break;
   1.182 +BULLSEYE_OFF
   1.183 +		}
   1.184 +BULLSEYE_RESTORE
   1.185 +	}
   1.186 +
   1.187 +void CAuthoriser::CreatingFingerprintsStateL(TAuthoriserEvent aEvent)
   1.188 +	{
   1.189 +	switch(aEvent)
   1.190 +		{
   1.191 +		case EInternalRequestComplete:
   1.192 +			// This will move to the next state and lookup the fingerprints, or leave.
   1.193 +			LookupFingerprintsL();
   1.194 +			break;
   1.195 +
   1.196 +			BULLSEYE_OFF
   1.197 +		case EClearedToDisplayDialog:
   1.198 +			ASSERT(EFalse);
   1.199 +			break;
   1.200 +			BULLSEYE_RESTORE
   1.201 +
   1.202 +		case ECancel:
   1.203 +			// Cancel the request to create the fingerprints
   1.204 +			iPolicyEvaluator->Imp().Cancel();
   1.205 +			break;
   1.206 +BULLSEYE_OFF
   1.207 +		}
   1.208 +BULLSEYE_RESTORE
   1.209 +	}
   1.210 +
   1.211 +void CAuthoriser::CheckDatabaseStateL(TAuthoriserEvent aEvent)
   1.212 +	{
   1.213 +	switch(aEvent)
   1.214 +		{
   1.215 +		case EInternalRequestComplete:
   1.216 +			// Normally the create fingerprints state code will call
   1.217 +			// LookupFingerprintsL to move to this state and do the
   1.218 +			// lookup, but if we need to re-lookup the fingerprints a
   1.219 +			// "fake" request will be issued and this code will be
   1.220 +			// used.
   1.221 +			LookupFingerprintsL();
   1.222 +			break;
   1.223 +		case EClearedToDisplayDialog:
   1.224 +			// Change state and ask the dialog creator to start creating
   1.225 +			// the dialog, or leave.
   1.226 +			PrepareDialogL();
   1.227 +			break;
   1.228 +		case ECancel:
   1.229 +			// Complete the fake request which was issued to try and
   1.230 +			// get us to redo the fingerprint lookup.
   1.231 +			CompleteSelf();
   1.232 +			break;
   1.233 +BULLSEYE_OFF
   1.234 +		}
   1.235 +BULLSEYE_RESTORE
   1.236 +	}
   1.237 +
   1.238 +void CAuthoriser::PreparingDialogStateL(TAuthoriserEvent aEvent)
   1.239 +	{
   1.240 +	switch(aEvent)
   1.241 +		{
   1.242 +		case EInternalRequestComplete:
   1.243 +			// Created dialog, now change state to execute and display
   1.244 +			// it.
   1.245 +			ExecuteDialogL();
   1.246 +			break;
   1.247 +
   1.248 +			BULLSEYE_OFF
   1.249 +		case EClearedToDisplayDialog:
   1.250 +			ASSERT(EFalse);
   1.251 +			break;
   1.252 +			BULLSEYE_RESTORE
   1.253 +
   1.254 +		case ECancel:
   1.255 +			// Cancel the request to create the dialog
   1.256 +			iDialogCreator->Imp().Cancel();
   1.257 +			break;
   1.258 +BULLSEYE_OFF
   1.259 +		}
   1.260 +BULLSEYE_RESTORE
   1.261 +	}
   1.262 +
   1.263 +void CAuthoriser::ExecutingDialogStateL(TAuthoriserEvent aEvent)
   1.264 +	{
   1.265 +	switch(aEvent)
   1.266 +		{
   1.267 +		case EInternalRequestComplete:
   1.268 +			// Dialog complete, process the result and complete the
   1.269 +			// client request.
   1.270 +			ProcessDialogResultL();
   1.271 +			break;
   1.272 +
   1.273 +			BULLSEYE_OFF
   1.274 +		case EClearedToDisplayDialog:
   1.275 +			ASSERT(EFalse);
   1.276 +			break;
   1.277 +			BULLSEYE_RESTORE
   1.278 +
   1.279 +		case ECancel:
   1.280 +			// Cancel the request to execute the dialog
   1.281 +			iDialogCreator->Imp().Cancel();
   1.282 +			break;
   1.283 +BULLSEYE_OFF
   1.284 +		}
   1.285 +BULLSEYE_RESTORE
   1.286 +	}
   1.287 +
   1.288 +void CAuthoriser::Wakeup()
   1.289 +	/**
   1.290 +	   Raise and complete a request against self. Will cause RunL to
   1.291 +	   be run within the active scheduler.
   1.292 +	*/
   1.293 +	{
   1.294 +	iStatus = KRequestPending;
   1.295 +	SetActive();
   1.296 +	CompleteSelf();
   1.297 +	}
   1.298 +
   1.299 +void CAuthoriser::CompleteSelf()
   1.300 +	{
   1.301 +	_LIT(KServerPanicState, "UPS-CompleteSelf");
   1.302 +	switch(iState)
   1.303 +		{
   1.304 +		case ECheckPolicy:
   1.305 +		case ECheckDatabase:
   1.306 +			break;
   1.307 +
   1.308 +	BULLSEYE_OFF
   1.309 +		case ECreatingFingerprints:
   1.310 +		case EPreparingDialog:
   1.311 +		case EExecutingDialog:
   1.312 +			User::Panic(KServerPanicState, iState);
   1.313 +			/*lint -unreachable */
   1.314 +			return; // Not legal in these states
   1.315 +		}
   1.316 +	BULLSEYE_RESTORE
   1.317 +		
   1.318 +	if(iStatus == KRequestPending)
   1.319 +		{
   1.320 +		TRequestStatus *status = &iStatus;
   1.321 +		User::RequestComplete(status, KErrNone);
   1.322 +		}
   1.323 +	}
   1.324 +
   1.325 +
   1.326 +
   1.327 +void CAuthoriser::ClearedToDisplayL()
   1.328 +	/**
   1.329 +	   The UPS server GateKeeper has granted us permission to proceed
   1.330 +	   with dialog generation and display.
   1.331 +	*/
   1.332 +	{
   1.333 +	ProcessEventL(EClearedToDisplayDialog);
   1.334 +	}
   1.335 +
   1.336 +
   1.337 +
   1.338 +
   1.339 +
   1.340 +
   1.341 +CAuthoriser::~CAuthoriser()
   1.342 +	/**
   1.343 +	   Close the timer which was initialized in ConstructL.
   1.344 +	*/
   1.345 +	{
   1.346 +	iDialogFingerprint = 0; // MUST not delete, owned by CDialogCreator
   1.347 +	
   1.348 +	delete iDialogCreator;
   1.349 +	iDialogCreator = 0;
   1.350 +	
   1.351 +	iDialogCreatorParams = 0; // MUST not delete, owned by evaluator
   1.352 +	
   1.353 +	iClientEntity = 0;	// MUST not delete, owned by evaluator
   1.354 +	
   1.355 +	iFingerprints.ResetAndDestroy();
   1.356 +	
   1.357 +	delete iPolicyEvaluator;
   1.358 +	iPolicyEvaluator = 0;	
   1.359 +
   1.360 +	iPolicyCache.Release();
   1.361 +	iPolicy = 0; // MUST not delete, ownded by policy cache
   1.362 +	
   1.363 +	delete iPromptRequest;
   1.364 +	iPromptRequest = 0;
   1.365 +	}
   1.366 +
   1.367 +void CAuthoriser::RunL()
   1.368 +	{
   1.369 +	// Wake up the next pending request now (if any), to make sure it
   1.370 +	// will be processed ahead of any incoming requests.
   1.371 +	UpsServer()->WakeupNextPendingL();
   1.372 +	
   1.373 +	// Reset our priority to standard
   1.374 +	if(Priority() != CActive::EPriorityStandard)
   1.375 +		{
   1.376 +		SetPriority(CActive::EPriorityStandard);
   1.377 +		}
   1.378 +	User::LeaveIfError(iStatus.Int());
   1.379 +	
   1.380 +	ProcessEventL(EInternalRequestComplete);
   1.381 +	}
   1.382 +
   1.383 +
   1.384 +void CAuthoriser::DoCleanup()
   1.385 +	{
   1.386 +	if(iPromptForced)
   1.387 +		{
   1.388 +		// Have previously called ForcePromptL on a database record and it told us to 
   1.389 +		// prompt,  so have previously marked the record as disputed.
   1.390 +		TRAP_IGNORE(UpsServer()->UnDisputeRecordIdL(iPromptForcedRecordId));
   1.391 +		iPromptForced = EFalse;
   1.392 +		}
   1.393 +
   1.394 +	// Cancel current internal operation
   1.395 +	Cancel();
   1.396 +	
   1.397 +	// Let the server know we are done
   1.398 +	UpsServer()->AuthoriserDone(this);
   1.399 +
   1.400 +	// The framework will complete the client request and schedule us
   1.401 +	// for deletion.
   1.402 +	}
   1.403 +
   1.404 +
   1.405 +
   1.406 +
   1.407 +void CAuthoriser::DoCancel()
   1.408 +	/**
   1.409 +	   Cancel the current operation.  This does not complete the client
   1.410 +	   request or mark this object for deletion.
   1.411 +	*/
   1.412 +	{
   1.413 +	TRAP_IGNORE(
   1.414 +		// Wake up the next pending request now (if any), to make sure it
   1.415 +		// will be processed ahead of any incoming requests.
   1.416 +		UpsServer()->WakeupNextPendingL();
   1.417 +		ProcessEventL(ECancel);
   1.418 +		);
   1.419 +	}
   1.420 +
   1.421 +void CAuthoriser::LookupPolicyL()
   1.422 +	{
   1.423 +	// This returns a ptr into the cache, so we have to be careful not to use it after the cache is deleted.
   1.424 +	// This is why we wrap the cache in a RPolicyCacheCountedHandle.
   1.425 +	iPolicy = iPolicyCache->MatchL(*iPromptRequest);
   1.426 +	
   1.427 +	ASSERT(iPolicy);
   1.428 +	
   1.429 +	if(iPolicy->PromptRequired())
   1.430 +		{
   1.431 +		// Policy contains both yes and no responses...
   1.432 +		// Start creating the fingerprints
   1.433 +		CreateFingerprintsL();
   1.434 +		return;
   1.435 +		}
   1.436 +	
   1.437 +	// Return result to system server
   1.438 +	TUpsDecisionPckgBuf decisionBuf;
   1.439 +	decisionBuf() = MapCPolicyTOptions2TUpsDecision(iPolicy->Options());
   1.440 +	iMessagePtr2.WriteL(0, decisionBuf);
   1.441 +	
   1.442 +	CompleteAndMarkForDeletion(KErrNone);
   1.443 +	}
   1.444 +
   1.445 +
   1.446 +void CAuthoriser::CreateFingerprintsL()
   1.447 +	/**
   1.448 +	   Load Policy Evaluator and tell it to start generating the fingerprints
   1.449 +	*/
   1.450 +	{
   1.451 +	iState = ECreatingFingerprints;
   1.452 +
   1.453 +	iPolicyEvaluator = UpsServer()->iPluginManager->CreateEvaluatorL(iPolicy->PolicyEvaluator());
   1.454 +	
   1.455 +	iPolicyEvaluator->Imp().GenerateFingerprints(*iPromptRequest, *iPolicy, 
   1.456 +												 iFingerprints, iClientEntity, iDialogCreatorParams, iStatus);
   1.457 +	
   1.458 +	SetActive();
   1.459 +	}
   1.460 +
   1.461 +_LIT8(KDefaultFingerprint,"*");
   1.462 +//_LIT(KServerPanicDb, "UPS-BadDB");
   1.463 +static const char * const KCorruptDb = "UPS-BadDB error=%d line=%d\n";
   1.464 +
   1.465 +void CAuthoriser::LookupFingerprintsL()
   1.466 +	{
   1.467 +	// Lookup in DB
   1.468 +	iState = ECheckDatabase;
   1.469 +
   1.470 +	TPtrC8 clientEntityName(KNullDesC8());
   1.471 +	if(iClientEntity)
   1.472 +		{
   1.473 +		clientEntityName.Set(iClientEntity->Name());
   1.474 +		}
   1.475 +	
   1.476 +	CDecisionFilter *filter = CDecisionFilter::NewLC(iPromptRequest->ClientSid(),
   1.477 +													 iPolicy->PolicyEvaluator(),
   1.478 +													 iPromptRequest->ServiceId(),
   1.479 +													 iPromptRequest->ServerSid(),
   1.480 +													 KDefaultFingerprint(),
   1.481 +													 clientEntityName,
   1.482 +													 iPolicy->MajorVersion());
   1.483 +	//
   1.484 +	// Lookup the fingerprints in the DB and return the first match
   1.485 +	//
   1.486 +	CDecisionRecord *record = 0;
   1.487 +	TInt fingerprintCount = iFingerprints.Count();
   1.488 +	for(TInt i=0; i<fingerprintCount; ++i)
   1.489 +		{
   1.490 +		filter->SetFingerprintL(iFingerprints[i]->Fingerprint(), EEqual);
   1.491 +		record = 0;
   1.492 +		TRAPD(err, record = UpsServer()->iDbHandle->GetDecisionL(*filter));
   1.493 +		if(err != KErrNone)
   1.494 +			{
   1.495 +			HandleDbErrorL(err);
   1.496 +			}
   1.497 +		
   1.498 +		if(record)
   1.499 +			{
   1.500 +			break;
   1.501 +			}
   1.502 +		}
   1.503 +	
   1.504 +	if(record)
   1.505 +		{
   1.506 +		// Found record
   1.507 +		CleanupStack::PushL(record);
   1.508 +		// Read current eval info value from record.
   1.509 +		iDialogEvaluatorInfo = record->iEvaluatorInfo;
   1.510 +
   1.511 +		if(UpsServer()->IsRecordIdDisputed(record->iRecordId))
   1.512 +			{
   1.513 +			// Matching record is under dispute so a dialog must be in progress.
   1.514 +			// Queue for later re-evaluation.
   1.515 +			UpsServer()->GateKeeperL(this);
   1.516 +			return;
   1.517 +			}
   1.518 +
   1.519 +		if(iPromptForced && (record->iRecordId != iPromptForcedRecordId))
   1.520 +			{
   1.521 +			// Have previously called ForcePromptL on a database record and it told us to 
   1.522 +			// prompt, BUT we have now matched a different record ID! Presumably
   1.523 +			// someone else overwrote or deleted our record....
   1.524 +			//
   1.525 +			// We need to undispute the old record id and continue as if ForcePromptL had
   1.526 +			// never been called/returned yes. 
   1.527 +			iPromptForced = EFalse;
   1.528 +			UpsServer()->UnDisputeRecordIdL(iPromptForcedRecordId);
   1.529 +			}
   1.530 +		
   1.531 +		// Call ForcePrompt to see if we need to prompt anyway
   1.532 +		TUint newDialogEvaluatorInfo = iDialogEvaluatorInfo;
   1.533 +		TBool forcePrompt = iPolicyEvaluator->Imp().ForcePromptL(*record, newDialogEvaluatorInfo);
   1.534 +		if(forcePrompt)
   1.535 +			{
   1.536 +			iPromptForced = ETrue;
   1.537 +			iPromptForcedRecordId = record->iRecordId;
   1.538 +			UpsServer()->DisputeRecordIdL(iPromptForcedRecordId);
   1.539 +			}
   1.540 +		
   1.541 +		if(newDialogEvaluatorInfo != iDialogEvaluatorInfo)
   1.542 +			{
   1.543 +			// Eavluator info changes, update our member variable copy
   1.544 +			// so it is used in the dialog
   1.545 +			iDialogEvaluatorInfo = newDialogEvaluatorInfo;
   1.546 +			// If we ARE displaying a prompt, then when it completes,
   1.547 +			// we will delete the existing record. If the user choice
   1.548 +			// requires a new record we will use the evaluator value
   1.549 +			// from our member variable
   1.550 +			if(!forcePrompt)
   1.551 +				{
   1.552 +				// Not forcing a prompt, so update the DB now.
   1.553 +				record->iEvaluatorInfo = newDialogEvaluatorInfo;
   1.554 +				// If the update fails, we carry on anyway...
   1.555 +				TRAPD(err, UpsServer()->iDbHandle->UpdateDecisionL(*filter, *record));
   1.556 +				if(err != KErrNone)
   1.557 +					{
   1.558 +					HandleDbErrorL(err);
   1.559 +					}				
   1.560 +				}
   1.561 +			}
   1.562 +		
   1.563 +		if(!forcePrompt)
   1.564 +			{
   1.565 +			// Return the result found in the DB to the system server
   1.566 +			TUpsDecisionPckgBuf decisionBuf;
   1.567 +			decisionBuf() = MapCPolicyTOptions2TUpsDecision((record->iResult) ? (CPolicy::EAlways) : (CPolicy::ENever));
   1.568 +			iMessagePtr2.WriteL(0, decisionBuf);
   1.569 +			
   1.570 +			CleanupStack::PopAndDestroy(record);
   1.571 +			CleanupStack::PopAndDestroy(filter);
   1.572 +			CompleteAndMarkForDeletion(KErrNone);
   1.573 +			return;
   1.574 +			}
   1.575 +		
   1.576 +		// Prompt is being forced, so fall through
   1.577 +		CleanupStack::PopAndDestroy(record);
   1.578 +		}
   1.579 +	
   1.580 +	// Record not found, or prompt forced
   1.581 +	CleanupStack::PopAndDestroy(filter);
   1.582 +	
   1.583 +	// Queue for clearence to display a dialog
   1.584 +	UpsServer()->GateKeeperL(this);
   1.585 +	}
   1.586 +
   1.587 +void CAuthoriser::PrepareDialogL()
   1.588 +	{
   1.589 +	iState = EPreparingDialog;
   1.590 +	
   1.591 +	iDialogCreator = UpsServer()->iPluginManager->CreateDialogCreatorL(iPolicy->DialogCreator());
   1.592 +	
   1.593 +	iDialogCreator->Imp().PrepareDialog(*iPromptRequest, *iPolicy, iFingerprints, 
   1.594 +										iClientEntity, iDialogCreatorParams, iStatus);
   1.595 +	SetActive();
   1.596 +	}
   1.597 +
   1.598 +
   1.599 +
   1.600 +
   1.601 +void CAuthoriser::ExecuteDialogL()
   1.602 +	{
   1.603 +	iState = EExecutingDialog;
   1.604 +	iDialogCreator->Imp().DisplayDialog(iDialogSelectedOption, iDialogFingerprint, iDialogEvaluatorInfo, iStatus);
   1.605 +	SetActive();
   1.606 +	}
   1.607 +
   1.608 +void CAuthoriser::ProcessDialogResultL()
   1.609 +	{
   1.610 +	if(iPromptForced)
   1.611 +		{
   1.612 +		// Pormpt was forced therefore we must have matched an existing record in the
   1.613 +		// database.
   1.614 +		// Delete the old decision.
   1.615 +		CDecisionFilter *filter = CDecisionFilter::NewLC();
   1.616 +		filter->SetRecordId(iPromptForcedRecordId, EEqual);
   1.617 +		TRAPD(err, UpsServer()->iDbHandle->RemoveDecisionsL(*filter));
   1.618 +		CleanupStack::PopAndDestroy(filter);
   1.619 +		if(err != KErrNone)
   1.620 +			{
   1.621 +			HandleDbErrorL(err);
   1.622 +			}
   1.623 +
   1.624 +		// No longer disputing the record ID because we have a new decision
   1.625 +		iPromptForced = EFalse;
   1.626 +		UpsServer()->UnDisputeRecordIdL(iPromptForcedRecordId);
   1.627 +		}
   1.628 +	
   1.629 +	TUpsDecisionPckgBuf decisionBuf;
   1.630 +	// Mask out any illegal responses - ie buttons which we did not
   1.631 +	// ask to be displayed...
   1.632 +	iDialogSelectedOption = CPolicy::TOptions(TUint(iDialogSelectedOption) & TUint(iPolicy->Options()));
   1.633 +	
   1.634 +	decisionBuf() = MapCPolicyTOptions2TUpsDecision(iDialogSelectedOption);
   1.635 +	
   1.636 +	if((iDialogSelectedOption & CPolicy::EAlways) || (iDialogSelectedOption & CPolicy::ENever))
   1.637 +		{
   1.638 +
   1.639 +		__ASSERT_ALWAYS(NULL != iDialogFingerprint,
   1.640 +						User::Panic(KUpsServerName,
   1.641 +								KErrUpsBadFingerprintLength));	
   1.642 +	
   1.643 +		// Save yes/no result to database
   1.644 +		TPtrC8 clientEntityName(KNullDesC8());
   1.645 +		if(iClientEntity)
   1.646 +			{
   1.647 +			clientEntityName.Set(iClientEntity->Name());
   1.648 +			}
   1.649 +		
   1.650 +		CDecisionRecord *record = CDecisionRecord::NewLC(iPromptRequest->ClientSid(),
   1.651 +														 iPolicy->PolicyEvaluator(),
   1.652 +														 iPromptRequest->ServiceId(),
   1.653 +														 iPromptRequest->ServerSid(),
   1.654 +														 iDialogFingerprint->Fingerprint(),
   1.655 +														 clientEntityName,
   1.656 +														 iDialogFingerprint->Description(),
   1.657 +														 ((iDialogSelectedOption & CPolicy::EAlways) != 0),
   1.658 +														 iPolicy->MajorVersion(),
   1.659 +														 iDialogEvaluatorInfo);
   1.660 +		
   1.661 +		// Create new record - Failure is not fatal...
   1.662 +		TRAPD(err, UpsServer()->iDbHandle->CreateDecisionL(*record));
   1.663 +		if(err == KErrAlreadyExists)
   1.664 +			{
   1.665 +			/// You might think this will never happen, but under OOM conditions it can/does. The original database query can fail,
   1.666 +			/// even though there is a matching record in the database, we then choose to display a prompt, then the above code attempts to
   1.667 +			/// insert a "new" record and fails.... We recover by just updating the existing record.
   1.668 +			CDecisionFilter *filter = CDecisionFilter::NewLC(iPromptRequest->ClientSid(),
   1.669 +															 iPolicy->PolicyEvaluator(),
   1.670 +															 iPromptRequest->ServiceId(),
   1.671 +															 iPromptRequest->ServerSid(),
   1.672 +															 iDialogFingerprint->Fingerprint(),
   1.673 +													 		 clientEntityName,
   1.674 +													 		 iPolicy->MajorVersion());
   1.675 +
   1.676 +			TRAP(err, UpsServer()->iDbHandle->UpdateDecisionL(*filter, *record));
   1.677 +			CleanupStack::PopAndDestroy(filter);
   1.678 +			}
   1.679 +		if(err != KErrNone)
   1.680 +			{
   1.681 +			HandleDbErrorL(err);
   1.682 +			}
   1.683 +		
   1.684 +		CleanupStack::PopAndDestroy(record);
   1.685 +		}
   1.686 +
   1.687 +	iMessagePtr2.WriteL(0, decisionBuf);
   1.688 +	
   1.689 +	CompleteAndMarkForDeletion(KErrNone);
   1.690 +	}
   1.691 +
   1.692 +TUpsDecision CAuthoriser::MapCPolicyTOptions2TUpsDecision(CPolicy::TOptions aOptions)
   1.693 +/**
   1.694 +	Map the specified policy option bitmap (normally only a single bit should be set) into 
   1.695 +	a TUpsDecision.
   1.696 +
   1.697 +	If the server supports session decisions, then return never/always as EUpsDecSessionNo/EUpsDecSessionYes.
   1.698 +
   1.699 +	Usually a single option should be specified, but we consider the options in the order which
   1.700 +	minimises UPS traffic...
   1.701 +*/
   1.702 +	{
   1.703 +	if( (aOptions & (CPolicy::ENever | CPolicy::ESessionNo)) != 0)
   1.704 +		{
   1.705 +		// A Never - If the session supports "session no" then return it to cut down on UPS traffic
   1.706 +		if(iPolicy->Options() & CPolicy::ESessionNo)
   1.707 +			{
   1.708 +			return EUpsDecSessionNo;
   1.709 +			}
   1.710 +		// Otherwise return "single shot no" so the server will re-query us later (we may silently answer).
   1.711 +		return EUpsDecNo;
   1.712 +		}
   1.713 +
   1.714 +	if( (aOptions & (CPolicy::EAlways| CPolicy::ESessionYes)) != 0)
   1.715 +		{
   1.716 +		// An Always - If the session supports "session yes" then return it to cut down on UPS traffic
   1.717 +		if(iPolicy->Options() & CPolicy::ESessionYes)
   1.718 +			{
   1.719 +			return EUpsDecSessionYes;
   1.720 +			}
   1.721 +		// Otherwise return "single shot yes" so the server will re-query us later (so force prompt handling works).
   1.722 +		return EUpsDecYes;
   1.723 +		}
   1.724 +
   1.725 +	if( (aOptions & CPolicy::ENo) != 0)
   1.726 +		{
   1.727 +		// A "single shot no"
   1.728 +		return EUpsDecNo;
   1.729 +		}
   1.730 +
   1.731 +	// Only possibility left is a single shot yes
   1.732 +	// If it is not one, then map to no
   1.733 +	BULLSEYE_OFF
   1.734 +	if( (aOptions & CPolicy::EYes) == 0)
   1.735 +		{
   1.736 +		return EUpsDecNo; // No option set!
   1.737 +		}
   1.738 +	BULLSEYE_RESTORE
   1.739 +
   1.740 +	// A "single shot yes"
   1.741 +	return EUpsDecYes;
   1.742 +	}
   1.743 +
   1.744 +void CAuthoriser::HandleDbErrorL(TInt aError)
   1.745 +	{
   1.746 +	if((aError != KErrNoMemory) && (aError != KErrDiskFull))
   1.747 +		{
   1.748 +		RDebug::Printf(KCorruptDb, aError, __LINE__);
   1.749 +		UpsServer()->iDbHandle->DeleteDatabaseL(UpsServer()->iFs);
   1.750 +		UpsServer()->iDbHandle.Close(); // Will auto-reopen when next used
   1.751 +		User::Leave(aError);
   1.752 +		}
   1.753 +	UpsServer()->iDbHandle.Close(); // Will auto-reopen when next used
   1.754 +	}
   1.755 +
   1.756 +CAuthoriserFifo* CAuthoriserFifo::NewL()
   1.757 +	/**
   1.758 +	   Create a new CAuthoriserFifo instance
   1.759 +	*/
   1.760 +	{
   1.761 +	CAuthoriserFifo *self = new(ELeave) CAuthoriserFifo;
   1.762 +	return self;
   1.763 +	}
   1.764 +
   1.765 +CAuthoriserFifo::~CAuthoriserFifo()
   1.766 +	/**
   1.767 +	   Does not delete CAuthoriser objects in the FIFO, just frees
   1.768 +	   storage used by the FIFO itself.
   1.769 +	*/
   1.770 +	{
   1.771 +	iPtrArray.Close();
   1.772 +	}
   1.773 +
   1.774 +
   1.775 +
   1.776 +void CAuthoriserFifo::PushL(CAuthoriser *aAuthoriser)
   1.777 +	/**
   1.778 +	   @param aAuthoriser The CAuthoriser to be pushed onto the FIFO.
   1.779 +	   
   1.780 +	   This class does NOT take ownership.
   1.781 +	*/
   1.782 +	{
   1.783 +	iPtrArray.AppendL(aAuthoriser);
   1.784 +	}
   1.785 +
   1.786 +CAuthoriser *CAuthoriserFifo::PopL()
   1.787 +	{
   1.788 +	/**
   1.789 +	   @return A CAuthoriser ptr, or Leaves KErrUnderflow if FIFO is empty.
   1.790 +	*/
   1.791 +	TInt count = iPtrArray.Count();
   1.792 +	BULLSEYE_OFF
   1.793 +	if(count == 0)
   1.794 +		{
   1.795 +		User::Leave(KErrUnderflow);
   1.796 +		}
   1.797 +	BULLSEYE_RESTORE
   1.798 +	
   1.799 +	CAuthoriser *ret = iPtrArray[0];
   1.800 +	iPtrArray.Remove(0);
   1.801 +	return ret;
   1.802 +	}
   1.803 +
   1.804 +void CAuthoriserFifo::RemoveL(CAuthoriser *aAuthoriser)
   1.805 +	/**
   1.806 +	   Remove the specified object from the FIFO.
   1.807 +	   
   1.808 +	   It is not considered to be an error if the object is not in the
   1.809 +	   FIFO.
   1.810 +	   
   1.811 +	   @param aAuthoriser The CAuthoriser to be removed from the FIFO.
   1.812 +	*/
   1.813 +	{
   1.814 +	TInt i = iPtrArray.Find(aAuthoriser);
   1.815 +	BULLSEYE_OFF
   1.816 +	if( i == KErrNotFound)
   1.817 +		{
   1.818 +		return; // Not found is not considered an error.
   1.819 +		}
   1.820 +	BULLSEYE_RESTORE
   1.821 +	
   1.822 +	User::LeaveIfError(i);
   1.823 +	iPtrArray.Remove(i);
   1.824 +	}
   1.825 +
   1.826 +
   1.827 +TBool CAuthoriserFifo::IsEmpty() const
   1.828 +	/**
   1.829 +		@return ETrue if empty
   1.830 +	 */
   1.831 +	{
   1.832 +	return (iPtrArray.Count() == 0);
   1.833 +	}
   1.834 +
   1.835 +void CAuthoriserFifo::Compress()
   1.836 +	/**
   1.837 +	Reduce memory usage as much as possible. Typically used during OOM testing.
   1.838 +	*/
   1.839 +{
   1.840 +	iPtrArray.Compress();
   1.841 +}
   1.842 +
   1.843 +
   1.844 +
   1.845 +
   1.846 +} // End of namespace UserPromptService
   1.847 +// End of file