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