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: * Process RUpsManagement::NotifyPolicyFilesChanged. 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 sl@0: #include sl@0: #include "policycache.h" sl@0: #include "policychangeevaluator.h" sl@0: sl@0: namespace UserPromptService sl@0: { sl@0: inline CUpsSession *CPolicyChangeEvaluator::UpsSession() sl@0: { sl@0: return static_cast(iSession); sl@0: } sl@0: sl@0: inline CUpsServer *CPolicyChangeEvaluator::UpsServer() sl@0: { sl@0: return static_cast( sl@0: &static_cast(iSession)->iServer); sl@0: } sl@0: sl@0: CPolicyChangeEvaluator* CPolicyChangeEvaluator::NewLC(RPolicyCacheCountedHandle &aPolicyCacheHandle, CUpsSession* aSession, const RMessage2& aMessage) sl@0: { sl@0: CPolicyChangeEvaluator* self = new(ELeave) CPolicyChangeEvaluator(aPolicyCacheHandle, aSession, aMessage); sl@0: CleanupStack::PushL(self); sl@0: return self; sl@0: } sl@0: sl@0: CPolicyChangeEvaluator::CPolicyChangeEvaluator(RPolicyCacheCountedHandle &aPolicyCacheHandle, CUpsSession* aSession, const RMessage2& aMessage) sl@0: : CAsyncRequest(aSession, 0, aMessage), sl@0: iPolicyCacheHandle(aPolicyCacheHandle), sl@0: iUpdateDbHandle(UpsServer()->iDbHandle, this) sl@0: { sl@0: } sl@0: sl@0: CPolicyChangeEvaluator::~CPolicyChangeEvaluator() sl@0: /** sl@0: Normally cleanup should be done when DoCleanup function is called by the framework. sl@0: Sometime later, possibly after our parent CUpsSession has been deleted, this sl@0: destructor will be run. In this case the framework will have cleared our iSession variable sl@0: and we must do NOTHING. sl@0: sl@0: Unfortunately there is a special case where this object fails inside ConstructL, when we must do sl@0: some cleanup. We can detect this be seeing iSession (and hence UpsServer()) is non-NULL. sl@0: */ sl@0: { sl@0: CUpsSession *session = UpsSession(); sl@0: if(session) sl@0: { sl@0: /*lint -save -e1506*/ // ignore warning about calling a virtual function in a destructor sl@0: DoCleanup(); sl@0: /*lint -restore*/ sl@0: } sl@0: } sl@0: sl@0: sl@0: void CPolicyChangeEvaluator::StartUpdate() sl@0: /// Starts evaluating the database view sl@0: { sl@0: iPolicyCacheHandle.NotifyOnRef1(iStatus); sl@0: SetActive(); sl@0: } sl@0: sl@0: void CPolicyChangeEvaluator::ProcessEventL(TPolicyChangeEvent aEvent) sl@0: /** sl@0: Process either a DoCancel call or a request completing through RunL sl@0: */ sl@0: { sl@0: switch(iState) sl@0: { sl@0: case EWaitForPolicyCacheIdle: sl@0: WaitForPolicyCacheIdleStateL(aEvent); sl@0: return; sl@0: sl@0: case EScanDatabase: sl@0: ScanDatabaseStateL(aEvent); sl@0: return; sl@0: BULLSEYE_OFF sl@0: } sl@0: BULLSEYE_RESTORE sl@0: sl@0: // Should not get here sl@0: _LIT(KServerPanicState, "UPS-CPolicyChangeEvaluator"); sl@0: User::Panic(KServerPanicState, iState); sl@0: } sl@0: sl@0: void CPolicyChangeEvaluator::DoCleanup() sl@0: /// implement CAsyncRequest sl@0: { sl@0: Cancel(); sl@0: sl@0: iSSPVarray.Close(); sl@0: sl@0: delete iUpdateView; sl@0: iUpdateView = 0; sl@0: sl@0: iUpdateDbHandle.Close(); sl@0: sl@0: iPolicyCacheHandle.Release(); sl@0: } sl@0: sl@0: void CPolicyChangeEvaluator::DoCancel() sl@0: /// implement CActive - Cancel sl@0: { sl@0: TRAP_IGNORE(ProcessEventL(ECancel)); sl@0: } sl@0: sl@0: sl@0: void CPolicyChangeEvaluator::RunL() sl@0: /// implement CActive, override CAsyncRequset sl@0: { sl@0: User::LeaveIfError(iStatus.Int()); sl@0: sl@0: ProcessEventL(EInternalRequestComplete); sl@0: } sl@0: sl@0: TInt CPolicyChangeEvaluator::RunError(TInt aError) sl@0: { sl@0: iUpdateDbHandle.CloseMaster(); sl@0: return CAsyncRequest::RunError(aError); sl@0: } sl@0: sl@0: void CPolicyChangeEvaluator::DbHandleAboutToBeDeleted() sl@0: /** sl@0: Called just before the master database handle is shut. sl@0: Need to cancel and cleanup/delete our view and fail the client request. sl@0: */ sl@0: { sl@0: // Make sure our request is cancelled sl@0: Cancel(); sl@0: sl@0: // Cleanup/delete our view object sl@0: DoCleanup(); sl@0: sl@0: // Abort the client view request. sl@0: CompleteAndMarkForDeletion(KErrAbort); sl@0: } sl@0: sl@0: void CPolicyChangeEvaluator::WaitForPolicyCacheIdleStateL(TPolicyChangeEvent aEvent) sl@0: { sl@0: switch(aEvent) sl@0: { sl@0: case EInternalRequestComplete: sl@0: { sl@0: // Cache is idle so now create the view and walk the database sl@0: CDecisionFilter *filter= CDecisionFilter::NewLC(); sl@0: iUpdateView = iUpdateDbHandle->CreateViewL(*filter); sl@0: CleanupStack::PopAndDestroy(filter); sl@0: sl@0: // Update state and start evaluating the view sl@0: iState = EScanDatabase; sl@0: iUpdateView->EvaluateView(iStatus); sl@0: SetActive(); sl@0: break; sl@0: } sl@0: case ECancel: sl@0: iPolicyCacheHandle.CancelNotifyOnRef1(); sl@0: break; sl@0: BULLSEYE_OFF sl@0: } sl@0: BULLSEYE_RESTORE sl@0: sl@0: } sl@0: sl@0: void CPolicyChangeEvaluator::ScanDatabaseStateL(TPolicyChangeEvent aEvent) sl@0: { sl@0: switch(aEvent) sl@0: { sl@0: case EInternalRequestComplete: sl@0: { sl@0: // Finished evaluating the view sl@0: BuildServerServicePolicyVersionTableL(); sl@0: sl@0: // If the server policy cache handle has not already been sl@0: // re-opened, open it. sl@0: if(!UpsServer()->iPolicyCache.IsOpen()) sl@0: { sl@0: UpsServer()->iPolicyCache.OpenL(); sl@0: } sl@0: // Assign the server handle to ours - this will increment the reference count. sl@0: iPolicyCacheHandle = UpsServer()->iPolicyCache; sl@0: sl@0: // Set the property, the value does not matter. sl@0: // We do not need to change the value, setting to the same value still notifies all clients of sl@0: // an update. sl@0: User::LeaveIfError(RProperty::Set(KUpsServerUid, KUpsServiceConfigProperty, 42)); sl@0: sl@0: // Process the iSSPVarray and delete uneeded database entries sl@0: DeleteUnneededEntriesL(); sl@0: sl@0: // All done. sl@0: CompleteAndMarkForDeletion(KErrNone); sl@0: break; sl@0: } sl@0: case ECancel: sl@0: iUpdateView->Cancel(); sl@0: break; sl@0: BULLSEYE_OFF sl@0: } sl@0: BULLSEYE_RESTORE sl@0: } sl@0: sl@0: sl@0: sl@0: TInt CPolicyChangeEvaluator::OrderServerServicePolicyVersion(const TServerServicePolicyVersion &aLhs, sl@0: const TServerServicePolicyVersion &aRhs) sl@0: { sl@0: TInt t = aLhs.iServerId - aRhs.iServerId; sl@0: if(t) return t; sl@0: t = aLhs.iServiceId - aRhs.iServiceId; sl@0: if(t) return t; sl@0: t = aLhs.iMajorVersion - aRhs.iMajorVersion; sl@0: return t; sl@0: } sl@0: sl@0: void CPolicyChangeEvaluator::BuildServerServicePolicyVersionTableL() sl@0: { sl@0: TLinearOrder linearOrder(OrderServerServicePolicyVersion); sl@0: sl@0: while(CDecisionRecord *record = iUpdateView->NextDecisionL()) sl@0: { sl@0: TServerServicePolicyVersion ent = { record->iServerSid.iId, sl@0: record->iServiceId.iUid, sl@0: record->iMajorPolicyVersion }; sl@0: delete record; sl@0: record = 0; sl@0: TInt r = iSSPVarray.InsertInOrder(ent, linearOrder); sl@0: if((r != KErrNone) && (r != KErrAlreadyExists)) sl@0: { sl@0: User::Leave(r); sl@0: } sl@0: } sl@0: sl@0: sl@0: } sl@0: sl@0: static TBool CompareServiceId(const TServiceId* k, const TServiceConfig& t) sl@0: { sl@0: return TUint(k->iUid) == t.iServiceId; sl@0: } sl@0: sl@0: void CPolicyChangeEvaluator::DeleteUnneededEntriesL() sl@0: { sl@0: TInt count = iSSPVarray.Count(); sl@0: sl@0: if(count == 0) return; // No database entries! sl@0: sl@0: TSecureId serverSid(0); // ID of server currently being processed. 0 is illegal sl@0: RArray serviceConfigArray; sl@0: CleanupClosePushL(serviceConfigArray); sl@0: for(TInt i=0; iServiceConfigL(serverSid, serviceConfigArray); sl@0: } sl@0: sl@0: CDecisionFilter *filter = CDecisionFilter::NewLC(); sl@0: filter->SetServerSid(serverSid, EEqual); sl@0: filter->SetServiceId(serviceId, EEqual); sl@0: sl@0: // Now attempt to lookup the current ServiceId in the serviceconfig for sl@0: // the current server. sl@0: TInt serviceIndex = serviceConfigArray.Find(serviceId, CompareServiceId); sl@0: if(serviceIndex != KErrNotFound) sl@0: { sl@0: DEBUG_PRINTF5(_L8("i=%d Found server %x service %x at index %d\n"), sl@0: i, sspv.iServerId, sspv.iServiceId, serviceIndex); sl@0: TServiceConfig &serviceConfig = serviceConfigArray[serviceIndex]; sl@0: filter->SetMajorPolicyVersion(serviceConfig.iMajorVersion, ENotEqual); sl@0: DEBUG_PRINTF4(_L8("Deleting OLD decisions where server=0x%x service=0x%x MajorVersion!=%d\n"), sl@0: serverSid.iId, serviceId.iUid, serviceConfig.iMajorVersion); sl@0: } sl@0: else sl@0: { sl@0: DEBUG_PRINTF3(_L8("Deleting ALL decisions where server=0x%x service=0x%x MajorVersion==*\n"), sl@0: serverSid.iId, serviceId.iUid); sl@0: } sl@0: sl@0: TRAP_IGNORE(iUpdateDbHandle->RemoveDecisionsL(*filter)); sl@0: CleanupStack::PopAndDestroy(filter); sl@0: sl@0: }; sl@0: CleanupStack::PopAndDestroy(&serviceConfigArray); sl@0: sl@0: } sl@0: sl@0: } // End of namespace UserPromptServer sl@0: // End of file sl@0: sl@0: