os/security/authorisation/userpromptservice/server/source/upsserver/policychangeevaluator.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of the License "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: 
    15 * Process RUpsManagement::NotifyPolicyFilesChanged.
    16 *
    17 */
    18 
    19 
    20 /**
    21  @file
    22 */
    23 
    24 #include "upsserver.h"
    25 #include <ups/upsdbw.h>
    26 #include <e32property.h>
    27 #include "policycache.h"
    28 #include "policychangeevaluator.h"
    29 
    30 namespace UserPromptService
    31 {
    32 inline CUpsSession *CPolicyChangeEvaluator::UpsSession()
    33 	{
    34 	return static_cast<CUpsSession*>(iSession);
    35 	}
    36 
    37 inline CUpsServer *CPolicyChangeEvaluator::UpsServer()
    38 	{
    39 	return static_cast<CUpsServer *>(
    40 		&static_cast<CUpsSession*>(iSession)->iServer);
    41 	}
    42 
    43 CPolicyChangeEvaluator* CPolicyChangeEvaluator::NewLC(RPolicyCacheCountedHandle &aPolicyCacheHandle, CUpsSession* aSession, const RMessage2& aMessage)
    44 	{
    45 	CPolicyChangeEvaluator* self = new(ELeave) CPolicyChangeEvaluator(aPolicyCacheHandle, aSession, aMessage);
    46 	CleanupStack::PushL(self);
    47 	return self;
    48 	}
    49 
    50 CPolicyChangeEvaluator::CPolicyChangeEvaluator(RPolicyCacheCountedHandle &aPolicyCacheHandle, CUpsSession* aSession, const RMessage2& aMessage)
    51 	:	CAsyncRequest(aSession, 0, aMessage),
    52 		iPolicyCacheHandle(aPolicyCacheHandle),
    53 		iUpdateDbHandle(UpsServer()->iDbHandle, this)
    54 	{
    55 	}
    56 
    57 CPolicyChangeEvaluator::~CPolicyChangeEvaluator()
    58 /**
    59 	Normally cleanup should be done when DoCleanup function is called by the framework.
    60 	Sometime later, possibly after our parent CUpsSession has been deleted, this
    61 	destructor will be run. In this case the framework will have cleared our iSession variable
    62 	and we must do NOTHING.
    63 
    64 	Unfortunately there is a special case where this object fails inside ConstructL, when we must do 
    65 	some cleanup. We can detect this be seeing iSession (and hence UpsServer()) is non-NULL.
    66 */
    67 	{
    68 	CUpsSession *session = UpsSession();
    69 	if(session)
    70 		{
    71 		/*lint -save -e1506*/ // ignore warning about calling a virtual function in a destructor
    72 		DoCleanup();
    73 		/*lint -restore*/
    74 		}
    75 	}
    76 
    77 
    78 void CPolicyChangeEvaluator::StartUpdate()
    79 	/// Starts evaluating the database view
    80 	{
    81 	iPolicyCacheHandle.NotifyOnRef1(iStatus);
    82 	SetActive();
    83 	}
    84 
    85 void CPolicyChangeEvaluator::ProcessEventL(TPolicyChangeEvent aEvent)
    86 /**
    87 	Process either a DoCancel call or a request completing through RunL
    88 */
    89 	{
    90 	switch(iState)
    91 		{
    92 		case EWaitForPolicyCacheIdle:
    93 			WaitForPolicyCacheIdleStateL(aEvent);
    94 			return;
    95 			
    96 		case EScanDatabase:
    97 			ScanDatabaseStateL(aEvent);
    98 			return;
    99 BULLSEYE_OFF
   100 		}
   101 BULLSEYE_RESTORE
   102 	
   103 	// Should not get here
   104 	_LIT(KServerPanicState, "UPS-CPolicyChangeEvaluator");
   105 	User::Panic(KServerPanicState, iState);
   106 	}
   107 
   108 void CPolicyChangeEvaluator::DoCleanup()
   109 /// implement CAsyncRequest
   110 	{
   111 	Cancel();
   112 
   113 	iSSPVarray.Close();
   114 	
   115 	delete iUpdateView;
   116 	iUpdateView = 0;
   117 
   118 	iUpdateDbHandle.Close();
   119 
   120 	iPolicyCacheHandle.Release();
   121 	}
   122 
   123 void CPolicyChangeEvaluator::DoCancel()
   124 	/// implement CActive - Cancel
   125 	{
   126 	TRAP_IGNORE(ProcessEventL(ECancel));
   127 	}
   128 
   129 	
   130 void CPolicyChangeEvaluator::RunL()
   131 	/// implement CActive, override CAsyncRequset
   132 	{
   133 	User::LeaveIfError(iStatus.Int());
   134 
   135 	ProcessEventL(EInternalRequestComplete);
   136 	}
   137 
   138 TInt CPolicyChangeEvaluator::RunError(TInt aError)
   139 	{
   140 	iUpdateDbHandle.CloseMaster();
   141 	return CAsyncRequest::RunError(aError);
   142 	}
   143 
   144 void CPolicyChangeEvaluator::DbHandleAboutToBeDeleted()
   145 /**
   146 	Called just before the master database handle is shut.
   147 	Need to cancel and cleanup/delete our view and fail the client request.
   148 */
   149 	{
   150 	// Make sure our request is cancelled
   151 	Cancel();
   152 
   153 	// Cleanup/delete our view object
   154 	DoCleanup();
   155 	
   156 	// Abort the client view request.
   157 	CompleteAndMarkForDeletion(KErrAbort);
   158 	}
   159 
   160 void CPolicyChangeEvaluator::WaitForPolicyCacheIdleStateL(TPolicyChangeEvent aEvent)
   161 	{
   162 	switch(aEvent)
   163 		{
   164 		case EInternalRequestComplete:
   165 			{
   166 			// Cache is idle so now create the view and walk the database
   167 			CDecisionFilter *filter= CDecisionFilter::NewLC();
   168 			iUpdateView = iUpdateDbHandle->CreateViewL(*filter);
   169 			CleanupStack::PopAndDestroy(filter);
   170 
   171 			// Update state and start evaluating the view
   172 			iState = EScanDatabase;
   173 			iUpdateView->EvaluateView(iStatus);
   174 			SetActive();
   175 			break;
   176 			}
   177 		case ECancel:
   178 			iPolicyCacheHandle.CancelNotifyOnRef1();
   179 			break;
   180 BULLSEYE_OFF
   181 		}
   182 BULLSEYE_RESTORE
   183 
   184 	}
   185 
   186 void CPolicyChangeEvaluator::ScanDatabaseStateL(TPolicyChangeEvent aEvent)
   187 	{
   188 	switch(aEvent)
   189 		{
   190 		case EInternalRequestComplete:
   191 			{
   192 			// Finished evaluating the view
   193 			BuildServerServicePolicyVersionTableL();
   194 			
   195 			// If the server policy cache handle has not already been
   196 			// re-opened, open it.
   197 			if(!UpsServer()->iPolicyCache.IsOpen())
   198 				{
   199 				UpsServer()->iPolicyCache.OpenL();
   200 				}
   201 			// Assign the server handle to ours - this will increment the reference count.
   202 			iPolicyCacheHandle = UpsServer()->iPolicyCache;
   203 
   204 			// Set the property, the value does not matter.
   205 			// We do not need to change the value, setting to the same value still notifies all clients of
   206 			// an update.
   207 			User::LeaveIfError(RProperty::Set(KUpsServerUid, KUpsServiceConfigProperty, 42));
   208 
   209 			// Process the iSSPVarray and delete uneeded database entries
   210 			DeleteUnneededEntriesL();
   211 
   212 			// All done.
   213 			CompleteAndMarkForDeletion(KErrNone);
   214 			break;
   215 			}
   216 		case ECancel:
   217 			iUpdateView->Cancel();
   218 			break;
   219 BULLSEYE_OFF
   220 		}
   221 BULLSEYE_RESTORE
   222 	}
   223 
   224 
   225 
   226 TInt CPolicyChangeEvaluator::OrderServerServicePolicyVersion(const TServerServicePolicyVersion &aLhs,
   227 									 			 						 const TServerServicePolicyVersion &aRhs)
   228 {
   229 	TInt t = aLhs.iServerId - aRhs.iServerId;
   230 	if(t) return t;
   231 	t = aLhs.iServiceId - aRhs.iServiceId;
   232 	if(t) return t;
   233 	t = aLhs.iMajorVersion - aRhs.iMajorVersion;
   234 	return t;
   235 }
   236 
   237 void CPolicyChangeEvaluator::BuildServerServicePolicyVersionTableL()
   238 	{
   239 	TLinearOrder<TServerServicePolicyVersion> linearOrder(OrderServerServicePolicyVersion);
   240 
   241 	while(CDecisionRecord *record = iUpdateView->NextDecisionL())
   242 		{
   243 		TServerServicePolicyVersion ent = { record->iServerSid.iId, 
   244 											record->iServiceId.iUid,
   245 											record->iMajorPolicyVersion };
   246 		delete record;
   247 		record = 0;
   248 		TInt r = iSSPVarray.InsertInOrder(ent, linearOrder);
   249 		if((r != KErrNone) && (r != KErrAlreadyExists))
   250 			{
   251 			User::Leave(r);
   252 			}
   253 		}
   254 
   255 
   256 	}
   257 
   258 static TBool CompareServiceId(const TServiceId* k, const TServiceConfig& t)
   259 	{
   260 	return TUint(k->iUid) == t.iServiceId;
   261 	}
   262 
   263 void CPolicyChangeEvaluator::DeleteUnneededEntriesL()
   264 	{
   265 	TInt count = iSSPVarray.Count();
   266 
   267 	if(count == 0) return; // No database entries!
   268 
   269 	TSecureId serverSid(0); // ID of server currently being processed. 0 is illegal
   270 	RArray<TServiceConfig> serviceConfigArray;
   271 	CleanupClosePushL(serviceConfigArray);
   272 	for(TInt i=0; i<count; ++i)
   273 		{
   274 		const TServerServicePolicyVersion &sspv = iSSPVarray[i];
   275 		TServiceId serviceId = {sspv.iServiceId};
   276 
   277 		// The iSSPVarray is sorted by server/service/version. This means
   278 		// all entries for a single server will be adjacent to each other
   279 		if(serverSid != sspv.iServerId)
   280 			{
   281 			// 0 is not a valid server SID, so this will always run the first time
   282 			// through the loop.
   283 			serviceConfigArray.Close();
   284 			serverSid = sspv.iServerId;
   285 			iPolicyCacheHandle->ServiceConfigL(serverSid, serviceConfigArray);
   286 			}
   287 
   288 		CDecisionFilter *filter = CDecisionFilter::NewLC();
   289 		filter->SetServerSid(serverSid, EEqual);
   290 		filter->SetServiceId(serviceId, EEqual);
   291 
   292 		// Now attempt to lookup the current ServiceId in the serviceconfig for 
   293 		// the current server.
   294 		TInt serviceIndex = serviceConfigArray.Find(serviceId, CompareServiceId);
   295 		if(serviceIndex != KErrNotFound)
   296 			{
   297 			DEBUG_PRINTF5(_L8("i=%d Found server %x service %x at index %d\n"),
   298 							i, sspv.iServerId, sspv.iServiceId, serviceIndex);
   299 			TServiceConfig &serviceConfig = serviceConfigArray[serviceIndex];
   300 			filter->SetMajorPolicyVersion(serviceConfig.iMajorVersion, ENotEqual);
   301 			DEBUG_PRINTF4(_L8("Deleting OLD decisions where server=0x%x service=0x%x MajorVersion!=%d\n"),
   302 							serverSid.iId, serviceId.iUid, serviceConfig.iMajorVersion);
   303 			}
   304 		else
   305 			{
   306 			DEBUG_PRINTF3(_L8("Deleting ALL decisions where server=0x%x service=0x%x MajorVersion==*\n"),
   307 							serverSid.iId, serviceId.iUid);
   308 			}
   309 
   310 		TRAP_IGNORE(iUpdateDbHandle->RemoveDecisionsL(*filter));
   311 		CleanupStack::PopAndDestroy(filter);
   312 			
   313 		};
   314 	CleanupStack::PopAndDestroy(&serviceConfigArray);
   315 
   316 	}
   317 
   318 } // End of namespace UserPromptServer
   319 // End of file
   320 
   321