sl@0: /* sl@0: * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * Implements CAuthoriser. See class and function definitions for sl@0: * more information. sl@0: * sl@0: */ sl@0: sl@0: sl@0: /** sl@0: @file sl@0: */ sl@0: sl@0: #include "upsserver.h" sl@0: #include "policycache.h" sl@0: #include "authoriser.h" sl@0: #include sl@0: #include "upslog.h" sl@0: #include sl@0: #include sl@0: sl@0: namespace UserPromptService sl@0: { sl@0: sl@0: CAuthoriser* CAuthoriser::NewL(RPolicyCacheCountedHandle &aPolicyCache, sl@0: CUpsSession* aSession, CUpsSubsession* aSubsession, TBool aServerCheckOk, sl@0: TThreadId &aClientTid, TProcessId &aClientPId, sl@0: const RMessage2& aMessage, const TServiceId& aServiceId, sl@0: RBuf &aDestination, RBuf8 &aOpaqueData) sl@0: /** sl@0: Factory function allocates a new, initialized instance of CAuthoriser, sl@0: registered for the supplied session and subsession. sl@0: sl@0: If construction is successful, the caller should pass ownership to sl@0: the SCS framework (TransferToScsFrameworkL), and pop the sl@0: CAuthoriser from the cleanupstack. From this point onwards the sl@0: request should be completed by the CAuthoriser/CAsyncRequst code, sl@0: so the caller must not return or leave with any code except sl@0: KErrScsSetupAsync. This is why the StartProcessingRequest function sl@0: is defined as non-leaving. sl@0: sl@0: @param aPolicyCache The server policy cache manager. sl@0: @param aSession Session on which this request was launched. sl@0: @param aSubsession Subsession on which this request was launched. sl@0: @param aServerCheckOk Did the system server checks pass? sl@0: @param aClientThread Handle to the user client thread. sl@0: @param aMessage Standard server-side handle to message. sl@0: @param aDestination We take ownership of the RBuf and close the callers handle sl@0: @param aOpaqueData We take ownership of the RBuf and close the callers handle sl@0: @return New, initialized instance of CAuthoriser, which sl@0: is owned by the server's collection of outstanding sl@0: requests. sl@0: */ sl@0: { sl@0: CAuthoriser* self = new(ELeave) CAuthoriser(aPolicyCache, aSession, aSubsession, aMessage); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aServerCheckOk, aClientTid, aClientPId, aServiceId, aDestination, aOpaqueData); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: CAuthoriser::CAuthoriser(RPolicyCacheCountedHandle &aPolicyCache, sl@0: CUpsSession* aSession, CUpsSubsession* aSubsession, sl@0: const RMessage2& aMessage) sl@0: /** sl@0: This private constructor initializes the superclass and prevents direct instantiation. sl@0: sl@0: @param aPolicyCache The server policy cache manager. sl@0: @param aSession Session on which this request was launched. sl@0: @param aSubsession Subsession on which this request was launched. sl@0: @param aMessage Standard server-side handle to message. sl@0: @param aDestination HBufC description, takes ownership. sl@0: @param aOpaqueData 0 or HBufC opaqueData, takes ownership. sl@0: */ sl@0: : CAsyncRequest(aSession, aSubsession, aMessage), sl@0: iPolicyCache(aPolicyCache) sl@0: { sl@0: // empty. sl@0: } sl@0: sl@0: void CAuthoriser::ConstructL(TBool aServerCheckOk, TThreadId &aClientTid, TProcessId &aClientPid, const TServiceId& aServiceId, RBuf &aDestination, RBuf8 &aOpaqueData) sl@0: /** sl@0: Second-phase constructor allocates the timer which is used to generate sl@0: a delay, and adds this object to the server's collection of outstanding sl@0: requests. sl@0: */ sl@0: { sl@0: iState = ECheckPolicy; sl@0: sl@0: RProcess clientProcess; sl@0: TInt r = clientProcess.Open(aClientPid); sl@0: if(r != KErrNone) sl@0: { sl@0: User::Leave(KErrUpsBadClientProcessId); sl@0: } sl@0: CleanupClosePushL(clientProcess); sl@0: sl@0: // Create a CPromptReqest for the policy lookup sl@0: iPromptRequest = CPromptRequest::NewL(clientProcess.SecureId(), // Client details sl@0: clientProcess.VendorId(), sl@0: aClientTid, sl@0: aClientPid, sl@0: iMessagePtr2.SecureId(), // Server SID sl@0: aServiceId, // Server service ID sl@0: aDestination, // Request detail, takes ownership sl@0: aOpaqueData, // takes ownership sl@0: aServerCheckOk); sl@0: sl@0: CleanupStack::PopAndDestroy(&clientProcess); sl@0: } sl@0: sl@0: void CAuthoriser::ProcessEventL(TAuthoriserEvent aEvent) sl@0: { sl@0: // DEBUG_PRINTF4(_L8("0x%x CAuthoriser::ProcessEventL state %d, event %d\n"), this, iState, aEvent); sl@0: _LIT(KServerPanicState, "UPS-ProcessEventL"); sl@0: switch(iState) sl@0: { sl@0: case ECheckPolicy: sl@0: CheckPolicyStateL(aEvent); sl@0: return; sl@0: case ECreatingFingerprints: sl@0: CreatingFingerprintsStateL(aEvent); sl@0: return; sl@0: case ECheckDatabase: sl@0: CheckDatabaseStateL(aEvent); sl@0: return; sl@0: case EPreparingDialog: sl@0: PreparingDialogStateL(aEvent); sl@0: return; sl@0: case EExecutingDialog: sl@0: ExecutingDialogStateL(aEvent); sl@0: return; sl@0: BULLSEYE_OFF sl@0: } sl@0: sl@0: // Should not get here sl@0: User::Panic(KServerPanicState, iState); sl@0: BULLSEYE_RESTORE sl@0: } sl@0: sl@0: sl@0: void CAuthoriser::CheckPolicyStateL(TAuthoriserEvent aEvent) sl@0: { sl@0: switch(aEvent) sl@0: { sl@0: case EInternalRequestComplete: sl@0: // Caused by the ups sub session code calling Wakeup sl@0: // to start the request processing. We are now within the sl@0: // active scheduler error handling framework. sl@0: sl@0: // This call will lookup the policy and move to the next sl@0: // state, or leave. sl@0: LookupPolicyL(); sl@0: break; sl@0: sl@0: BULLSEYE_OFF sl@0: case EClearedToDisplayDialog: sl@0: ASSERT(EFalse); sl@0: break; sl@0: BULLSEYE_RESTORE sl@0: sl@0: case ECancel: sl@0: // This WILL happen if am authorise request is made and immediately cancelled (before CAuthoriser::Runl has sl@0: // the chance to run). We should complete our "fake" internal request so we do not block sl@0: // when we return to the DoCancel/CActive::Cancel which caused this event. sl@0: CompleteSelf(); sl@0: break; sl@0: BULLSEYE_OFF sl@0: } sl@0: BULLSEYE_RESTORE sl@0: } sl@0: sl@0: void CAuthoriser::CreatingFingerprintsStateL(TAuthoriserEvent aEvent) sl@0: { sl@0: switch(aEvent) sl@0: { sl@0: case EInternalRequestComplete: sl@0: // This will move to the next state and lookup the fingerprints, or leave. sl@0: LookupFingerprintsL(); sl@0: break; sl@0: sl@0: BULLSEYE_OFF sl@0: case EClearedToDisplayDialog: sl@0: ASSERT(EFalse); sl@0: break; sl@0: BULLSEYE_RESTORE sl@0: sl@0: case ECancel: sl@0: // Cancel the request to create the fingerprints sl@0: iPolicyEvaluator->Imp().Cancel(); sl@0: break; sl@0: BULLSEYE_OFF sl@0: } sl@0: BULLSEYE_RESTORE sl@0: } sl@0: sl@0: void CAuthoriser::CheckDatabaseStateL(TAuthoriserEvent aEvent) sl@0: { sl@0: switch(aEvent) sl@0: { sl@0: case EInternalRequestComplete: sl@0: // Normally the create fingerprints state code will call sl@0: // LookupFingerprintsL to move to this state and do the sl@0: // lookup, but if we need to re-lookup the fingerprints a sl@0: // "fake" request will be issued and this code will be sl@0: // used. sl@0: LookupFingerprintsL(); sl@0: break; sl@0: case EClearedToDisplayDialog: sl@0: // Change state and ask the dialog creator to start creating sl@0: // the dialog, or leave. sl@0: PrepareDialogL(); sl@0: break; sl@0: case ECancel: sl@0: // Complete the fake request which was issued to try and sl@0: // get us to redo the fingerprint lookup. sl@0: CompleteSelf(); sl@0: break; sl@0: BULLSEYE_OFF sl@0: } sl@0: BULLSEYE_RESTORE sl@0: } sl@0: sl@0: void CAuthoriser::PreparingDialogStateL(TAuthoriserEvent aEvent) sl@0: { sl@0: switch(aEvent) sl@0: { sl@0: case EInternalRequestComplete: sl@0: // Created dialog, now change state to execute and display sl@0: // it. sl@0: ExecuteDialogL(); sl@0: break; sl@0: sl@0: BULLSEYE_OFF sl@0: case EClearedToDisplayDialog: sl@0: ASSERT(EFalse); sl@0: break; sl@0: BULLSEYE_RESTORE sl@0: sl@0: case ECancel: sl@0: // Cancel the request to create the dialog sl@0: iDialogCreator->Imp().Cancel(); sl@0: break; sl@0: BULLSEYE_OFF sl@0: } sl@0: BULLSEYE_RESTORE sl@0: } sl@0: sl@0: void CAuthoriser::ExecutingDialogStateL(TAuthoriserEvent aEvent) sl@0: { sl@0: switch(aEvent) sl@0: { sl@0: case EInternalRequestComplete: sl@0: // Dialog complete, process the result and complete the sl@0: // client request. sl@0: ProcessDialogResultL(); sl@0: break; sl@0: sl@0: BULLSEYE_OFF sl@0: case EClearedToDisplayDialog: sl@0: ASSERT(EFalse); sl@0: break; sl@0: BULLSEYE_RESTORE sl@0: sl@0: case ECancel: sl@0: // Cancel the request to execute the dialog sl@0: iDialogCreator->Imp().Cancel(); sl@0: break; sl@0: BULLSEYE_OFF sl@0: } sl@0: BULLSEYE_RESTORE sl@0: } sl@0: sl@0: void CAuthoriser::Wakeup() sl@0: /** sl@0: Raise and complete a request against self. Will cause RunL to sl@0: be run within the active scheduler. sl@0: */ sl@0: { sl@0: iStatus = KRequestPending; sl@0: SetActive(); sl@0: CompleteSelf(); sl@0: } sl@0: sl@0: void CAuthoriser::CompleteSelf() sl@0: { sl@0: _LIT(KServerPanicState, "UPS-CompleteSelf"); sl@0: switch(iState) sl@0: { sl@0: case ECheckPolicy: sl@0: case ECheckDatabase: sl@0: break; sl@0: sl@0: BULLSEYE_OFF sl@0: case ECreatingFingerprints: sl@0: case EPreparingDialog: sl@0: case EExecutingDialog: sl@0: User::Panic(KServerPanicState, iState); sl@0: /*lint -unreachable */ sl@0: return; // Not legal in these states sl@0: } sl@0: BULLSEYE_RESTORE sl@0: sl@0: if(iStatus == KRequestPending) sl@0: { sl@0: TRequestStatus *status = &iStatus; sl@0: User::RequestComplete(status, KErrNone); sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: void CAuthoriser::ClearedToDisplayL() sl@0: /** sl@0: The UPS server GateKeeper has granted us permission to proceed sl@0: with dialog generation and display. sl@0: */ sl@0: { sl@0: ProcessEventL(EClearedToDisplayDialog); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: CAuthoriser::~CAuthoriser() sl@0: /** sl@0: Close the timer which was initialized in ConstructL. sl@0: */ sl@0: { sl@0: iDialogFingerprint = 0; // MUST not delete, owned by CDialogCreator sl@0: sl@0: delete iDialogCreator; sl@0: iDialogCreator = 0; sl@0: sl@0: iDialogCreatorParams = 0; // MUST not delete, owned by evaluator sl@0: sl@0: iClientEntity = 0; // MUST not delete, owned by evaluator sl@0: sl@0: iFingerprints.ResetAndDestroy(); sl@0: sl@0: delete iPolicyEvaluator; sl@0: iPolicyEvaluator = 0; sl@0: sl@0: iPolicyCache.Release(); sl@0: iPolicy = 0; // MUST not delete, ownded by policy cache sl@0: sl@0: delete iPromptRequest; sl@0: iPromptRequest = 0; sl@0: } sl@0: sl@0: void CAuthoriser::RunL() sl@0: { sl@0: // Wake up the next pending request now (if any), to make sure it sl@0: // will be processed ahead of any incoming requests. sl@0: UpsServer()->WakeupNextPendingL(); sl@0: sl@0: // Reset our priority to standard sl@0: if(Priority() != CActive::EPriorityStandard) sl@0: { sl@0: SetPriority(CActive::EPriorityStandard); sl@0: } sl@0: User::LeaveIfError(iStatus.Int()); sl@0: sl@0: ProcessEventL(EInternalRequestComplete); sl@0: } sl@0: sl@0: sl@0: void CAuthoriser::DoCleanup() sl@0: { sl@0: if(iPromptForced) sl@0: { sl@0: // Have previously called ForcePromptL on a database record and it told us to sl@0: // prompt, so have previously marked the record as disputed. sl@0: TRAP_IGNORE(UpsServer()->UnDisputeRecordIdL(iPromptForcedRecordId)); sl@0: iPromptForced = EFalse; sl@0: } sl@0: sl@0: // Cancel current internal operation sl@0: Cancel(); sl@0: sl@0: // Let the server know we are done sl@0: UpsServer()->AuthoriserDone(this); sl@0: sl@0: // The framework will complete the client request and schedule us sl@0: // for deletion. sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: void CAuthoriser::DoCancel() sl@0: /** sl@0: Cancel the current operation. This does not complete the client sl@0: request or mark this object for deletion. sl@0: */ sl@0: { sl@0: TRAP_IGNORE( sl@0: // Wake up the next pending request now (if any), to make sure it sl@0: // will be processed ahead of any incoming requests. sl@0: UpsServer()->WakeupNextPendingL(); sl@0: ProcessEventL(ECancel); sl@0: ); sl@0: } sl@0: sl@0: void CAuthoriser::LookupPolicyL() sl@0: { sl@0: // This returns a ptr into the cache, so we have to be careful not to use it after the cache is deleted. sl@0: // This is why we wrap the cache in a RPolicyCacheCountedHandle. sl@0: iPolicy = iPolicyCache->MatchL(*iPromptRequest); sl@0: sl@0: ASSERT(iPolicy); sl@0: sl@0: if(iPolicy->PromptRequired()) sl@0: { sl@0: // Policy contains both yes and no responses... sl@0: // Start creating the fingerprints sl@0: CreateFingerprintsL(); sl@0: return; sl@0: } sl@0: sl@0: // Return result to system server sl@0: TUpsDecisionPckgBuf decisionBuf; sl@0: decisionBuf() = MapCPolicyTOptions2TUpsDecision(iPolicy->Options()); sl@0: iMessagePtr2.WriteL(0, decisionBuf); sl@0: sl@0: CompleteAndMarkForDeletion(KErrNone); sl@0: } sl@0: sl@0: sl@0: void CAuthoriser::CreateFingerprintsL() sl@0: /** sl@0: Load Policy Evaluator and tell it to start generating the fingerprints sl@0: */ sl@0: { sl@0: iState = ECreatingFingerprints; sl@0: sl@0: iPolicyEvaluator = UpsServer()->iPluginManager->CreateEvaluatorL(iPolicy->PolicyEvaluator()); sl@0: sl@0: iPolicyEvaluator->Imp().GenerateFingerprints(*iPromptRequest, *iPolicy, sl@0: iFingerprints, iClientEntity, iDialogCreatorParams, iStatus); sl@0: sl@0: SetActive(); sl@0: } sl@0: sl@0: _LIT8(KDefaultFingerprint,"*"); sl@0: //_LIT(KServerPanicDb, "UPS-BadDB"); sl@0: static const char * const KCorruptDb = "UPS-BadDB error=%d line=%d\n"; sl@0: sl@0: void CAuthoriser::LookupFingerprintsL() sl@0: { sl@0: // Lookup in DB sl@0: iState = ECheckDatabase; sl@0: sl@0: TPtrC8 clientEntityName(KNullDesC8()); sl@0: if(iClientEntity) sl@0: { sl@0: clientEntityName.Set(iClientEntity->Name()); sl@0: } sl@0: sl@0: CDecisionFilter *filter = CDecisionFilter::NewLC(iPromptRequest->ClientSid(), sl@0: iPolicy->PolicyEvaluator(), sl@0: iPromptRequest->ServiceId(), sl@0: iPromptRequest->ServerSid(), sl@0: KDefaultFingerprint(), sl@0: clientEntityName, sl@0: iPolicy->MajorVersion()); sl@0: // sl@0: // Lookup the fingerprints in the DB and return the first match sl@0: // sl@0: CDecisionRecord *record = 0; sl@0: TInt fingerprintCount = iFingerprints.Count(); sl@0: for(TInt i=0; iSetFingerprintL(iFingerprints[i]->Fingerprint(), EEqual); sl@0: record = 0; sl@0: TRAPD(err, record = UpsServer()->iDbHandle->GetDecisionL(*filter)); sl@0: if(err != KErrNone) sl@0: { sl@0: HandleDbErrorL(err); sl@0: } sl@0: sl@0: if(record) sl@0: { sl@0: break; sl@0: } sl@0: } sl@0: sl@0: if(record) sl@0: { sl@0: // Found record sl@0: CleanupStack::PushL(record); sl@0: // Read current eval info value from record. sl@0: iDialogEvaluatorInfo = record->iEvaluatorInfo; sl@0: sl@0: if(UpsServer()->IsRecordIdDisputed(record->iRecordId)) sl@0: { sl@0: // Matching record is under dispute so a dialog must be in progress. sl@0: // Queue for later re-evaluation. sl@0: UpsServer()->GateKeeperL(this); sl@0: return; sl@0: } sl@0: sl@0: if(iPromptForced && (record->iRecordId != iPromptForcedRecordId)) sl@0: { sl@0: // Have previously called ForcePromptL on a database record and it told us to sl@0: // prompt, BUT we have now matched a different record ID! Presumably sl@0: // someone else overwrote or deleted our record.... sl@0: // sl@0: // We need to undispute the old record id and continue as if ForcePromptL had sl@0: // never been called/returned yes. sl@0: iPromptForced = EFalse; sl@0: UpsServer()->UnDisputeRecordIdL(iPromptForcedRecordId); sl@0: } sl@0: sl@0: // Call ForcePrompt to see if we need to prompt anyway sl@0: TUint newDialogEvaluatorInfo = iDialogEvaluatorInfo; sl@0: TBool forcePrompt = iPolicyEvaluator->Imp().ForcePromptL(*record, newDialogEvaluatorInfo); sl@0: if(forcePrompt) sl@0: { sl@0: iPromptForced = ETrue; sl@0: iPromptForcedRecordId = record->iRecordId; sl@0: UpsServer()->DisputeRecordIdL(iPromptForcedRecordId); sl@0: } sl@0: sl@0: if(newDialogEvaluatorInfo != iDialogEvaluatorInfo) sl@0: { sl@0: // Eavluator info changes, update our member variable copy sl@0: // so it is used in the dialog sl@0: iDialogEvaluatorInfo = newDialogEvaluatorInfo; sl@0: // If we ARE displaying a prompt, then when it completes, sl@0: // we will delete the existing record. If the user choice sl@0: // requires a new record we will use the evaluator value sl@0: // from our member variable sl@0: if(!forcePrompt) sl@0: { sl@0: // Not forcing a prompt, so update the DB now. sl@0: record->iEvaluatorInfo = newDialogEvaluatorInfo; sl@0: // If the update fails, we carry on anyway... sl@0: TRAPD(err, UpsServer()->iDbHandle->UpdateDecisionL(*filter, *record)); sl@0: if(err != KErrNone) sl@0: { sl@0: HandleDbErrorL(err); sl@0: } sl@0: } sl@0: } sl@0: sl@0: if(!forcePrompt) sl@0: { sl@0: // Return the result found in the DB to the system server sl@0: TUpsDecisionPckgBuf decisionBuf; sl@0: decisionBuf() = MapCPolicyTOptions2TUpsDecision((record->iResult) ? (CPolicy::EAlways) : (CPolicy::ENever)); sl@0: iMessagePtr2.WriteL(0, decisionBuf); sl@0: sl@0: CleanupStack::PopAndDestroy(record); sl@0: CleanupStack::PopAndDestroy(filter); sl@0: CompleteAndMarkForDeletion(KErrNone); sl@0: return; sl@0: } sl@0: sl@0: // Prompt is being forced, so fall through sl@0: CleanupStack::PopAndDestroy(record); sl@0: } sl@0: sl@0: // Record not found, or prompt forced sl@0: CleanupStack::PopAndDestroy(filter); sl@0: sl@0: // Queue for clearence to display a dialog sl@0: UpsServer()->GateKeeperL(this); sl@0: } sl@0: sl@0: void CAuthoriser::PrepareDialogL() sl@0: { sl@0: iState = EPreparingDialog; sl@0: sl@0: iDialogCreator = UpsServer()->iPluginManager->CreateDialogCreatorL(iPolicy->DialogCreator()); sl@0: sl@0: iDialogCreator->Imp().PrepareDialog(*iPromptRequest, *iPolicy, iFingerprints, sl@0: iClientEntity, iDialogCreatorParams, iStatus); sl@0: SetActive(); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: void CAuthoriser::ExecuteDialogL() sl@0: { sl@0: iState = EExecutingDialog; sl@0: iDialogCreator->Imp().DisplayDialog(iDialogSelectedOption, iDialogFingerprint, iDialogEvaluatorInfo, iStatus); sl@0: SetActive(); sl@0: } sl@0: sl@0: void CAuthoriser::ProcessDialogResultL() sl@0: { sl@0: if(iPromptForced) sl@0: { sl@0: // Pormpt was forced therefore we must have matched an existing record in the sl@0: // database. sl@0: // Delete the old decision. sl@0: CDecisionFilter *filter = CDecisionFilter::NewLC(); sl@0: filter->SetRecordId(iPromptForcedRecordId, EEqual); sl@0: TRAPD(err, UpsServer()->iDbHandle->RemoveDecisionsL(*filter)); sl@0: CleanupStack::PopAndDestroy(filter); sl@0: if(err != KErrNone) sl@0: { sl@0: HandleDbErrorL(err); sl@0: } sl@0: sl@0: // No longer disputing the record ID because we have a new decision sl@0: iPromptForced = EFalse; sl@0: UpsServer()->UnDisputeRecordIdL(iPromptForcedRecordId); sl@0: } sl@0: sl@0: TUpsDecisionPckgBuf decisionBuf; sl@0: // Mask out any illegal responses - ie buttons which we did not sl@0: // ask to be displayed... sl@0: iDialogSelectedOption = CPolicy::TOptions(TUint(iDialogSelectedOption) & TUint(iPolicy->Options())); sl@0: sl@0: decisionBuf() = MapCPolicyTOptions2TUpsDecision(iDialogSelectedOption); sl@0: sl@0: if((iDialogSelectedOption & CPolicy::EAlways) || (iDialogSelectedOption & CPolicy::ENever)) sl@0: { sl@0: sl@0: __ASSERT_ALWAYS(NULL != iDialogFingerprint, sl@0: User::Panic(KUpsServerName, sl@0: KErrUpsBadFingerprintLength)); sl@0: sl@0: // Save yes/no result to database sl@0: TPtrC8 clientEntityName(KNullDesC8()); sl@0: if(iClientEntity) sl@0: { sl@0: clientEntityName.Set(iClientEntity->Name()); sl@0: } sl@0: sl@0: CDecisionRecord *record = CDecisionRecord::NewLC(iPromptRequest->ClientSid(), sl@0: iPolicy->PolicyEvaluator(), sl@0: iPromptRequest->ServiceId(), sl@0: iPromptRequest->ServerSid(), sl@0: iDialogFingerprint->Fingerprint(), sl@0: clientEntityName, sl@0: iDialogFingerprint->Description(), sl@0: ((iDialogSelectedOption & CPolicy::EAlways) != 0), sl@0: iPolicy->MajorVersion(), sl@0: iDialogEvaluatorInfo); sl@0: sl@0: // Create new record - Failure is not fatal... sl@0: TRAPD(err, UpsServer()->iDbHandle->CreateDecisionL(*record)); sl@0: if(err == KErrAlreadyExists) sl@0: { sl@0: /// You might think this will never happen, but under OOM conditions it can/does. The original database query can fail, sl@0: /// even though there is a matching record in the database, we then choose to display a prompt, then the above code attempts to sl@0: /// insert a "new" record and fails.... We recover by just updating the existing record. sl@0: CDecisionFilter *filter = CDecisionFilter::NewLC(iPromptRequest->ClientSid(), sl@0: iPolicy->PolicyEvaluator(), sl@0: iPromptRequest->ServiceId(), sl@0: iPromptRequest->ServerSid(), sl@0: iDialogFingerprint->Fingerprint(), sl@0: clientEntityName, sl@0: iPolicy->MajorVersion()); sl@0: sl@0: TRAP(err, UpsServer()->iDbHandle->UpdateDecisionL(*filter, *record)); sl@0: CleanupStack::PopAndDestroy(filter); sl@0: } sl@0: if(err != KErrNone) sl@0: { sl@0: HandleDbErrorL(err); sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(record); sl@0: } sl@0: sl@0: iMessagePtr2.WriteL(0, decisionBuf); sl@0: sl@0: CompleteAndMarkForDeletion(KErrNone); sl@0: } sl@0: sl@0: TUpsDecision CAuthoriser::MapCPolicyTOptions2TUpsDecision(CPolicy::TOptions aOptions) sl@0: /** sl@0: Map the specified policy option bitmap (normally only a single bit should be set) into sl@0: a TUpsDecision. sl@0: sl@0: If the server supports session decisions, then return never/always as EUpsDecSessionNo/EUpsDecSessionYes. sl@0: sl@0: Usually a single option should be specified, but we consider the options in the order which sl@0: minimises UPS traffic... sl@0: */ sl@0: { sl@0: if( (aOptions & (CPolicy::ENever | CPolicy::ESessionNo)) != 0) sl@0: { sl@0: // A Never - If the session supports "session no" then return it to cut down on UPS traffic sl@0: if(iPolicy->Options() & CPolicy::ESessionNo) sl@0: { sl@0: return EUpsDecSessionNo; sl@0: } sl@0: // Otherwise return "single shot no" so the server will re-query us later (we may silently answer). sl@0: return EUpsDecNo; sl@0: } sl@0: sl@0: if( (aOptions & (CPolicy::EAlways| CPolicy::ESessionYes)) != 0) sl@0: { sl@0: // An Always - If the session supports "session yes" then return it to cut down on UPS traffic sl@0: if(iPolicy->Options() & CPolicy::ESessionYes) sl@0: { sl@0: return EUpsDecSessionYes; sl@0: } sl@0: // Otherwise return "single shot yes" so the server will re-query us later (so force prompt handling works). sl@0: return EUpsDecYes; sl@0: } sl@0: sl@0: if( (aOptions & CPolicy::ENo) != 0) sl@0: { sl@0: // A "single shot no" sl@0: return EUpsDecNo; sl@0: } sl@0: sl@0: // Only possibility left is a single shot yes sl@0: // If it is not one, then map to no sl@0: BULLSEYE_OFF sl@0: if( (aOptions & CPolicy::EYes) == 0) sl@0: { sl@0: return EUpsDecNo; // No option set! sl@0: } sl@0: BULLSEYE_RESTORE sl@0: sl@0: // A "single shot yes" sl@0: return EUpsDecYes; sl@0: } sl@0: sl@0: void CAuthoriser::HandleDbErrorL(TInt aError) sl@0: { sl@0: if((aError != KErrNoMemory) && (aError != KErrDiskFull)) sl@0: { sl@0: RDebug::Printf(KCorruptDb, aError, __LINE__); sl@0: UpsServer()->iDbHandle->DeleteDatabaseL(UpsServer()->iFs); sl@0: UpsServer()->iDbHandle.Close(); // Will auto-reopen when next used sl@0: User::Leave(aError); sl@0: } sl@0: UpsServer()->iDbHandle.Close(); // Will auto-reopen when next used sl@0: } sl@0: sl@0: CAuthoriserFifo* CAuthoriserFifo::NewL() sl@0: /** sl@0: Create a new CAuthoriserFifo instance sl@0: */ sl@0: { sl@0: CAuthoriserFifo *self = new(ELeave) CAuthoriserFifo; sl@0: return self; sl@0: } sl@0: sl@0: CAuthoriserFifo::~CAuthoriserFifo() sl@0: /** sl@0: Does not delete CAuthoriser objects in the FIFO, just frees sl@0: storage used by the FIFO itself. sl@0: */ sl@0: { sl@0: iPtrArray.Close(); sl@0: } sl@0: sl@0: sl@0: sl@0: void CAuthoriserFifo::PushL(CAuthoriser *aAuthoriser) sl@0: /** sl@0: @param aAuthoriser The CAuthoriser to be pushed onto the FIFO. sl@0: sl@0: This class does NOT take ownership. sl@0: */ sl@0: { sl@0: iPtrArray.AppendL(aAuthoriser); sl@0: } sl@0: sl@0: CAuthoriser *CAuthoriserFifo::PopL() sl@0: { sl@0: /** sl@0: @return A CAuthoriser ptr, or Leaves KErrUnderflow if FIFO is empty. sl@0: */ sl@0: TInt count = iPtrArray.Count(); sl@0: BULLSEYE_OFF sl@0: if(count == 0) sl@0: { sl@0: User::Leave(KErrUnderflow); sl@0: } sl@0: BULLSEYE_RESTORE sl@0: sl@0: CAuthoriser *ret = iPtrArray[0]; sl@0: iPtrArray.Remove(0); sl@0: return ret; sl@0: } sl@0: sl@0: void CAuthoriserFifo::RemoveL(CAuthoriser *aAuthoriser) sl@0: /** sl@0: Remove the specified object from the FIFO. sl@0: sl@0: It is not considered to be an error if the object is not in the sl@0: FIFO. sl@0: sl@0: @param aAuthoriser The CAuthoriser to be removed from the FIFO. sl@0: */ sl@0: { sl@0: TInt i = iPtrArray.Find(aAuthoriser); sl@0: BULLSEYE_OFF sl@0: if( i == KErrNotFound) sl@0: { sl@0: return; // Not found is not considered an error. sl@0: } sl@0: BULLSEYE_RESTORE sl@0: sl@0: User::LeaveIfError(i); sl@0: iPtrArray.Remove(i); sl@0: } sl@0: sl@0: sl@0: TBool CAuthoriserFifo::IsEmpty() const sl@0: /** sl@0: @return ETrue if empty sl@0: */ sl@0: { sl@0: return (iPtrArray.Count() == 0); sl@0: } sl@0: sl@0: void CAuthoriserFifo::Compress() sl@0: /** sl@0: Reduce memory usage as much as possible. Typically used during OOM testing. sl@0: */ sl@0: { sl@0: iPtrArray.Compress(); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: } // End of namespace UserPromptService sl@0: // End of file