os/persistentdata/persistentstorage/centralrepository/cenrepnotifierhandler/src/cenrepnotifyhandler.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/centralrepository/cenrepnotifierhandler/src/cenrepnotifyhandler.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,481 @@
1.4 +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// INCLUDE FILES
1.18 +//
1.19 +
1.20 +
1.21 +
1.22 +#include <e32std.h>
1.23 +#include <e32svr.h>
1.24 +#include <centralrepository.h>
1.25 +#include "cenrepnotifyhandler.h"
1.26 +
1.27 +// ============================ MEMBER FUNCTIONS ===============================
1.28 +
1.29 +/**
1.30 +* Constructor used for single key listening.
1.31 +*
1.32 +* @param aCallback Reference to a callback instance.
1.33 +* @param aSession Reference to an existing repository session.
1.34 +* @param aKeyType Type of the key identified by aId parameter.
1.35 +* @param aId Id of the key that change notifications are needed for.
1.36 +* @capability None
1.37 +*/
1.38 +CCenRepNotifyHandler::CCenRepNotifyHandler(
1.39 + MCenRepNotifyHandlerCallback& aCallback,
1.40 + CRepository& aSession,
1.41 + TCenRepKeyType aKeyType,
1.42 + TUint32 aId)
1.43 + : CActive(EPriorityStandard), iSession(aSession),
1.44 + iCallback(aCallback), iKeyType(aKeyType), iId(aId), iWholeRepository(EFalse)
1.45 + {
1.46 + CActiveScheduler::Add(this);
1.47 + }
1.48 +
1.49 +/**
1.50 +* Constructor used for whole repository listening.
1.51 +*
1.52 +* @param aCallback Reference to a callback instance.
1.53 +* @param aSession Reference to an existing repository session.
1.54 +* @capability None
1.55 +*/
1.56 +CCenRepNotifyHandler::CCenRepNotifyHandler(
1.57 + MCenRepNotifyHandlerCallback& aCallback,
1.58 + CRepository& aSession)
1.59 + : CActive(EPriorityStandard), iSession(aSession), iCallback(aCallback),
1.60 + iKeyType(EIntKey), iId(0), iWholeRepository(ETrue)
1.61 + {
1.62 + CActiveScheduler::Add(this);
1.63 + }
1.64 +
1.65 +/**
1.66 +* This is a two-phase constructor method that is used to
1.67 +* create a new instance for listening to the changes in a single key.
1.68 +*
1.69 +* @param aCallback Reference to a callback instance.
1.70 +* @param aSession Reference to an existing repository session.
1.71 +* Do not close this session until all CCenRepNotifyHandler
1.72 +* instances referring to it have been deleted.
1.73 +* @param aKeyType Type of the key identified by aId parameter.
1.74 +* @param aId Id of the key that change notifications are needed for.
1.75 +* @return A pointer to a new instance of the CCenRepNotifyHandler class.
1.76 +*
1.77 +* @leave KErrArgument if invalid key type is passed as a parameter.
1.78 +* @capability None
1.79 +*/
1.80 +EXPORT_C CCenRepNotifyHandler* CCenRepNotifyHandler::NewL(
1.81 + MCenRepNotifyHandlerCallback& aCallback,
1.82 + CRepository& aSession,
1.83 + TCenRepKeyType aKeyType,
1.84 + TUint32 aId)
1.85 + {
1.86 + CCenRepNotifyHandler* newInstance = NewLC(aCallback, aSession, aKeyType, aId);
1.87 + CleanupStack::Pop();
1.88 + return newInstance;
1.89 + }
1.90 +
1.91 +/**
1.92 +* This is a two-phase constructor method that is used to create a new
1.93 +* instance for listening to the changes in all keys in the repository.
1.94 +*
1.95 +* Type specific callback methods of MCenRepNotifyHandlerCallback will not
1.96 +* be used when notifying about changes in this case,
1.97 +* only HandleNotifyGeneric() is used.
1.98 +*
1.99 +* @param aCallback Reference to a callback instance.
1.100 +* @param aSession Reference to an existing repository session.
1.101 +* Do not close this session until all CCenRepNotifyHandler
1.102 +* instances referring to it have been deleted.
1.103 +* @return A pointer to a new instance of the CCenRepNotifyHandler class.
1.104 +* @capability None
1.105 +*/
1.106 +EXPORT_C CCenRepNotifyHandler* CCenRepNotifyHandler::NewL(
1.107 + MCenRepNotifyHandlerCallback& aCallback,
1.108 + CRepository& aSession)
1.109 + {
1.110 + CCenRepNotifyHandler* newInstance = NewLC(aCallback, aSession);
1.111 + CleanupStack::Pop();
1.112 + return newInstance;
1.113 + }
1.114 +
1.115 +/**
1.116 +* This is a two-phase constructor method that is used to create a new
1.117 +* instance for listening to the changes in a single key.
1.118 +* Leaves the constructed instance to cleanup stack.
1.119 +*
1.120 +* @param aCallback Reference to a callback instance.
1.121 +* @param aSession Reference to an existing repository session.
1.122 +* Do not close this session until all CCenRepNotifyHandler
1.123 +* instances referring to it have been deleted.
1.124 +* @param aKeyType Type of the key identified by aId parameter.
1.125 +* @param aId Id of the key that change notifications are needed for.
1.126 +* @return A pointer to a new instance of the CCenRepNotifyHandler class.
1.127 +*
1.128 +* @leave KErrArgument if invalid key type is passed as a parameter.
1.129 +* @capability None
1.130 +*/
1.131 +EXPORT_C CCenRepNotifyHandler* CCenRepNotifyHandler::NewLC(
1.132 + MCenRepNotifyHandlerCallback& aCallback,
1.133 + CRepository& aSession,
1.134 + TCenRepKeyType aKeyType,
1.135 + TUint32 aId)
1.136 + {
1.137 + if ( aKeyType != EIntKey &&
1.138 + aKeyType != ERealKey &&
1.139 + aKeyType != EStringKey &&
1.140 + aKeyType != EBinaryKey )
1.141 + {
1.142 + User::Leave( KErrArgument );
1.143 + }
1.144 +
1.145 + CCenRepNotifyHandler* newInstance = new (ELeave) CCenRepNotifyHandler( aCallback, aSession,
1.146 + aKeyType, aId);
1.147 + CleanupStack::PushL( newInstance );
1.148 + return newInstance;
1.149 + }
1.150 +
1.151 +/**
1.152 +* This is a two-phase constructor method that is used to create a new
1.153 +* instance for listening to the changes in all keys in the repository.
1.154 +* Leaves the constructed instance to cleanup stack.
1.155 +*
1.156 +* Type specific callback methods of MCenRepNotifyHandlerCallback will
1.157 +* not be used when notifying about changes in this case,
1.158 +* only HandleNotifyGeneric() is used.
1.159 +*
1.160 +* @param aCallback Reference to a callback instance.
1.161 +* @param aSession Reference to an existing repository session.
1.162 +* Do not close this session until all CCenRepNotifyHandler
1.163 +* instances referring to it have been deleted.
1.164 +* @return A pointer to a new instance of the CCenRepNotifyHandler class.
1.165 +* @capability None
1.166 +*/
1.167 +EXPORT_C CCenRepNotifyHandler* CCenRepNotifyHandler::NewLC(
1.168 + MCenRepNotifyHandlerCallback& aCallback,
1.169 + CRepository& aSession)
1.170 + {
1.171 + CCenRepNotifyHandler* newInstance = new (ELeave) CCenRepNotifyHandler(aCallback, aSession);
1.172 + CleanupStack::PushL( newInstance );
1.173 +
1.174 + return newInstance;
1.175 + }
1.176 +
1.177 +// Destructor
1.178 +EXPORT_C CCenRepNotifyHandler::~CCenRepNotifyHandler()
1.179 + {
1.180 + Cancel();
1.181 + }
1.182 +
1.183 +/**
1.184 +* When this method is called, the CCenRepNotifyHandler starts
1.185 +* listening for notifications. If it is already listening, nothing happens.
1.186 +*
1.187 +* For single setting handler when there is already an existing notification
1.188 +* on the same setting and session,the HandleNotifyError will be trigerred with
1.189 +* KErrAlreadyExists error
1.190 +* @leave KErrNotFound if setting does not exist
1.191 +* KErrPermissionDenied if client does not have the necessary capability
1.192 +* plus other system-wide error codes.
1.193 +* For whole settings handler, the HandleNotifyError will be trigerred with the
1.194 +* error code
1.195 +* @capability Dependent Capability required depends on platform security of keyspace.
1.196 +*/
1.197 +EXPORT_C void CCenRepNotifyHandler::StartListeningL()
1.198 + {
1.199 + if(IsActive())
1.200 + {
1.201 + return;
1.202 + }
1.203 + User::LeaveIfError(OrderNotification());
1.204 +
1.205 + SetActive();
1.206 + }
1.207 +
1.208 +/**
1.209 +* When this method is called, the CCenRepNotifyHandler stops
1.210 +* listening for notifications. If it is already stopped, nothing happens.
1.211 +* @capability None
1.212 +*/
1.213 +EXPORT_C void CCenRepNotifyHandler::StopListening()
1.214 + {
1.215 + if(IsActive())
1.216 + {
1.217 + Cancel();
1.218 + }
1.219 + }
1.220 +
1.221 +/**
1.222 +* Implements CActive
1.223 +*/
1.224 +void CCenRepNotifyHandler::RunL()
1.225 + {
1.226 + // Check that notification was for correct ID or it was caused by
1.227 + // a repository wide reset (KInvalidNotificationId).
1.228 + TUint32 status = static_cast<TUint32>(iStatus.Int());
1.229 + if( !iWholeRepository && status != iId &&
1.230 + status != NCentralRepositoryConstants::KInvalidNotificationId )
1.231 + {
1.232 +#ifdef _DEBUG
1.233 + RDebug::Print(_L("CCenRepNotifyHandler::RunL(): Received notif about unknown key: %d"),
1.234 + status);
1.235 + RDebug::Print(_L("CCenRepNotifyHandler::RunL(): Notification not renewed."));
1.236 +#endif
1.237 + // We are not listening to key notified for us. Do not reorder notification
1.238 + // as there is clearly some problems in central repository.
1.239 + iCallback.HandleNotifyError(status, KErrArgument, this);
1.240 + return;
1.241 + }
1.242 +
1.243 + if (iWholeRepository && iStatus.Int() == KErrPermissionDenied)
1.244 + {
1.245 +
1.246 + RArray<TUint32> allKeyList;
1.247 + //check every single settings that we have read permission
1.248 + TRAPD(err,iSession.FindL(0x00000000,0x00000000,allKeyList));
1.249 + if (err==KErrNone)
1.250 + {
1.251 + TInt arrayCount=allKeyList.Count();
1.252 + for (TInt i=0;i<arrayCount;i++)
1.253 + {
1.254 + TUint32 dummyMeta;
1.255 + err=iSession.GetMeta(allKeyList[i],dummyMeta);
1.256 + //potential error at this stage likely to include only
1.257 + //KErrPermissionDenied plus other resource allocation
1.258 + //error such as KErrNoMemory
1.259 + if (err!=KErrNone)
1.260 + {
1.261 + TInt errorkey=allKeyList[i];
1.262 + allKeyList.Close();
1.263 + iCallback.HandleNotifyError(errorkey, err, this);
1.264 + return;
1.265 + }
1.266 + }
1.267 + }
1.268 + else
1.269 + {
1.270 + iCallback.HandleNotifyError( NCentralRepositoryConstants::KUnspecifiedKey , err, this );
1.271 + return;
1.272 + }
1.273 + }
1.274 +
1.275 + // Reorder notification
1.276 + TInt err = OrderNotification();
1.277 +
1.278 + // Handle notification
1.279 + if ( err == KErrNone )
1.280 + {
1.281 + SetActive();
1.282 + if ( iWholeRepository )
1.283 + {
1.284 + iCallback.HandleNotifyGeneric(status);
1.285 + }
1.286 + else
1.287 + {
1.288 + switch (iKeyType)
1.289 + {
1.290 + case EIntKey:
1.291 + {
1.292 + TInt newValue;
1.293 + err=iSession.Get(iId, newValue);
1.294 + if (err==KErrNone)
1.295 + {
1.296 + iCallback.HandleNotifyInt(iId, newValue);
1.297 + }
1.298 + }
1.299 + break;
1.300 + case ERealKey:
1.301 + {
1.302 + TReal newValue;
1.303 + err=iSession.Get(iId, newValue);
1.304 + if (err==KErrNone)
1.305 + {
1.306 + iCallback.HandleNotifyReal(iId, newValue);
1.307 + }
1.308 + }
1.309 + break;
1.310 + case EStringKey:
1.311 + {
1.312 + TBuf16<NCentralRepositoryConstants::KMaxUnicodeStringLength> newValue;
1.313 + err=iSession.Get(iId, newValue);
1.314 + if (err==KErrNone)
1.315 + {
1.316 + iCallback.HandleNotifyString(iId, newValue);
1.317 + }
1.318 + }
1.319 + break;
1.320 + case EBinaryKey:
1.321 + {
1.322 + TBuf8<NCentralRepositoryConstants::KMaxBinaryLength> newValue;
1.323 + err=iSession.Get(iId, newValue);
1.324 + if (err==KErrNone)
1.325 + {
1.326 + iCallback.HandleNotifyBinary(iId, newValue);
1.327 + }
1.328 + }
1.329 + break;
1.330 + default:
1.331 + break;
1.332 + }
1.333 + if (err!=KErrNone)
1.334 + {
1.335 + iCallback.HandleNotifyError(iId,err,this);
1.336 + }
1.337 + }
1.338 + }
1.339 + else
1.340 + {
1.341 + iCallback.HandleNotifyError(status, err, this);
1.342 + }
1.343 + }
1.344 +
1.345 +/**
1.346 +* Implements CActive
1.347 +* @param aError the error returned
1.348 +* @return error
1.349 +*/
1.350 +TInt CCenRepNotifyHandler::RunError(TInt aError)
1.351 + {
1.352 + if ( iWholeRepository )
1.353 + {
1.354 + iCallback.HandleNotifyError(NCentralRepositoryConstants::KInvalidNotificationId,
1.355 + aError, this);
1.356 + }
1.357 + else
1.358 + {
1.359 + iCallback.HandleNotifyError(iId, aError, this);
1.360 + }
1.361 +
1.362 + return KErrNone;
1.363 + }
1.364 +
1.365 +/**
1.366 +* Implements CActive
1.367 +*/
1.368 +void CCenRepNotifyHandler::DoCancel()
1.369 + {
1.370 + if ( iWholeRepository )
1.371 + {
1.372 + iSession.NotifyCancelAll();
1.373 + }
1.374 + else
1.375 + {
1.376 + iSession.NotifyCancel(iId);
1.377 + }
1.378 + }
1.379 +
1.380 +/*
1.381 +* Order notification
1.382 +* @return error code from CenRep
1.383 +*/
1.384 +TInt CCenRepNotifyHandler::OrderNotification()
1.385 + {
1.386 + if ( iWholeRepository )
1.387 + {
1.388 + // order notification for all keys in repository
1.389 + return iSession.NotifyRequest(0x00000000, 0x00000000, iStatus);
1.390 + }
1.391 + else
1.392 + {
1.393 + return iSession.NotifyRequest(iId, iStatus);
1.394 + }
1.395 + }
1.396 +
1.397 +// -----------------------------------------------------------------------------
1.398 +// MCenRepNotifyHandlerCallback::HandleNotifyXXX
1.399 +// Default implementations for callback interface.
1.400 +// In debug build these methods print trace.
1.401 +// In release build they do nothing.
1.402 +//
1.403 +// These methods are documented in cenrepnotifierhandler.h. Don't redocument
1.404 +// here.
1.405 +// -----------------------------------------------------------------------------
1.406 +//
1.407 +#ifdef _DEBUG
1.408 +EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyInt(TUint32 aId, TInt aNewValue)
1.409 + {
1.410 + RDebug::Print(_L("MCenRepNotifyHandlerCallback: Integer key %d changed, new value: %d"),
1.411 + aId, aNewValue);
1.412 + }
1.413 +
1.414 +EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyReal(TUint32 aId, TReal aNewValue)
1.415 + {
1.416 + RDebug::Print(_L("MCenRepNotifyHandlerCallback: Real key %d changed, new value: %e"),
1.417 + aId, aNewValue);
1.418 + }
1.419 +
1.420 +EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyString(TUint32 aId,
1.421 + const TDesC16& aNewValue)
1.422 + {
1.423 + RDebug::Print(_L("MCenRepNotifyHandlerCallback: String key %d changed, new value: %S"),
1.424 + aId, &aNewValue);
1.425 + }
1.426 +
1.427 +EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyBinary(TUint32 aId,
1.428 + const TDesC8& aNewValue)
1.429 + {
1.430 + RDebug::Print(_L("MCenRepNotifyHandlerCallback: Binary key %d changed, new value: %s"),
1.431 + aId, aNewValue.Ptr());
1.432 + }
1.433 +
1.434 +EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyGeneric(TUint32 aId)
1.435 + {
1.436 + if ( aId == NCentralRepositoryConstants::KInvalidNotificationId )
1.437 + {
1.438 + RDebug::Print(_L("MCenRepNotifyHandlerCallback: "));
1.439 + RDebug::Print(_L("Repository wide reset caused generic notification"));
1.440 + }
1.441 + else
1.442 + {
1.443 + RDebug::Print(_L("MCenRepNotifyHandlerCallback: Generic key %d changed"), aId);
1.444 + }
1.445 + }
1.446 +
1.447 +EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyError(TUint32 aId, TInt aError,
1.448 + CCenRepNotifyHandler* aHandler)
1.449 + {
1.450 + RDebug::Print(_L("MCenRepNotifyHandlerCallback %d notifies error for id: %d, error: %d"),
1.451 + aHandler, aId, aError);
1.452 + }
1.453 +
1.454 +#else
1.455 +
1.456 +EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyInt(TUint32 /*aId*/, TInt /*aNewValue*/)
1.457 + {
1.458 + }
1.459 +
1.460 +EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyReal(TUint32 /*aId*/, TReal /*aNewValue*/)
1.461 + {
1.462 + }
1.463 +
1.464 +EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyString(TUint32 /*aId*/,
1.465 + const TDesC16& /*aNewValue*/)
1.466 + {
1.467 + }
1.468 +
1.469 +EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyBinary(TUint32 /*aId*/,
1.470 + const TDesC8& /*aNewValue*/)
1.471 + {
1.472 + }
1.473 +
1.474 +EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyGeneric(TUint32 /*aId*/)
1.475 + {
1.476 + }
1.477 +
1.478 +EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyError(TUint32 /*aId*/, TInt /*aError*/,
1.479 + CCenRepNotifyHandler* /*aHandler*/)
1.480 + {
1.481 + }
1.482 +#endif // _DEBUG
1.483 +
1.484 +// End of File