--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/centralrepository/cenrepnotifierhandler/src/cenrepnotifyhandler.cpp Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,481 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// INCLUDE FILES
+//
+
+
+
+#include <e32std.h>
+#include <e32svr.h>
+#include <centralrepository.h>
+#include "cenrepnotifyhandler.h"
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+/**
+* Constructor used for single key listening.
+*
+* @param aCallback Reference to a callback instance.
+* @param aSession Reference to an existing repository session.
+* @param aKeyType Type of the key identified by aId parameter.
+* @param aId Id of the key that change notifications are needed for.
+* @capability None
+*/
+CCenRepNotifyHandler::CCenRepNotifyHandler(
+ MCenRepNotifyHandlerCallback& aCallback,
+ CRepository& aSession,
+ TCenRepKeyType aKeyType,
+ TUint32 aId)
+ : CActive(EPriorityStandard), iSession(aSession),
+ iCallback(aCallback), iKeyType(aKeyType), iId(aId), iWholeRepository(EFalse)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+/**
+* Constructor used for whole repository listening.
+*
+* @param aCallback Reference to a callback instance.
+* @param aSession Reference to an existing repository session.
+* @capability None
+*/
+CCenRepNotifyHandler::CCenRepNotifyHandler(
+ MCenRepNotifyHandlerCallback& aCallback,
+ CRepository& aSession)
+ : CActive(EPriorityStandard), iSession(aSession), iCallback(aCallback),
+ iKeyType(EIntKey), iId(0), iWholeRepository(ETrue)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+/**
+* This is a two-phase constructor method that is used to
+* create a new instance for listening to the changes in a single key.
+*
+* @param aCallback Reference to a callback instance.
+* @param aSession Reference to an existing repository session.
+* Do not close this session until all CCenRepNotifyHandler
+* instances referring to it have been deleted.
+* @param aKeyType Type of the key identified by aId parameter.
+* @param aId Id of the key that change notifications are needed for.
+* @return A pointer to a new instance of the CCenRepNotifyHandler class.
+*
+* @leave KErrArgument if invalid key type is passed as a parameter.
+* @capability None
+*/
+EXPORT_C CCenRepNotifyHandler* CCenRepNotifyHandler::NewL(
+ MCenRepNotifyHandlerCallback& aCallback,
+ CRepository& aSession,
+ TCenRepKeyType aKeyType,
+ TUint32 aId)
+ {
+ CCenRepNotifyHandler* newInstance = NewLC(aCallback, aSession, aKeyType, aId);
+ CleanupStack::Pop();
+ return newInstance;
+ }
+
+/**
+* This is a two-phase constructor method that is used to create a new
+* instance for listening to the changes in all keys in the repository.
+*
+* Type specific callback methods of MCenRepNotifyHandlerCallback will not
+* be used when notifying about changes in this case,
+* only HandleNotifyGeneric() is used.
+*
+* @param aCallback Reference to a callback instance.
+* @param aSession Reference to an existing repository session.
+* Do not close this session until all CCenRepNotifyHandler
+* instances referring to it have been deleted.
+* @return A pointer to a new instance of the CCenRepNotifyHandler class.
+* @capability None
+*/
+EXPORT_C CCenRepNotifyHandler* CCenRepNotifyHandler::NewL(
+ MCenRepNotifyHandlerCallback& aCallback,
+ CRepository& aSession)
+ {
+ CCenRepNotifyHandler* newInstance = NewLC(aCallback, aSession);
+ CleanupStack::Pop();
+ return newInstance;
+ }
+
+/**
+* This is a two-phase constructor method that is used to create a new
+* instance for listening to the changes in a single key.
+* Leaves the constructed instance to cleanup stack.
+*
+* @param aCallback Reference to a callback instance.
+* @param aSession Reference to an existing repository session.
+* Do not close this session until all CCenRepNotifyHandler
+* instances referring to it have been deleted.
+* @param aKeyType Type of the key identified by aId parameter.
+* @param aId Id of the key that change notifications are needed for.
+* @return A pointer to a new instance of the CCenRepNotifyHandler class.
+*
+* @leave KErrArgument if invalid key type is passed as a parameter.
+* @capability None
+*/
+EXPORT_C CCenRepNotifyHandler* CCenRepNotifyHandler::NewLC(
+ MCenRepNotifyHandlerCallback& aCallback,
+ CRepository& aSession,
+ TCenRepKeyType aKeyType,
+ TUint32 aId)
+ {
+ if ( aKeyType != EIntKey &&
+ aKeyType != ERealKey &&
+ aKeyType != EStringKey &&
+ aKeyType != EBinaryKey )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ CCenRepNotifyHandler* newInstance = new (ELeave) CCenRepNotifyHandler( aCallback, aSession,
+ aKeyType, aId);
+ CleanupStack::PushL( newInstance );
+ return newInstance;
+ }
+
+/**
+* This is a two-phase constructor method that is used to create a new
+* instance for listening to the changes in all keys in the repository.
+* Leaves the constructed instance to cleanup stack.
+*
+* Type specific callback methods of MCenRepNotifyHandlerCallback will
+* not be used when notifying about changes in this case,
+* only HandleNotifyGeneric() is used.
+*
+* @param aCallback Reference to a callback instance.
+* @param aSession Reference to an existing repository session.
+* Do not close this session until all CCenRepNotifyHandler
+* instances referring to it have been deleted.
+* @return A pointer to a new instance of the CCenRepNotifyHandler class.
+* @capability None
+*/
+EXPORT_C CCenRepNotifyHandler* CCenRepNotifyHandler::NewLC(
+ MCenRepNotifyHandlerCallback& aCallback,
+ CRepository& aSession)
+ {
+ CCenRepNotifyHandler* newInstance = new (ELeave) CCenRepNotifyHandler(aCallback, aSession);
+ CleanupStack::PushL( newInstance );
+
+ return newInstance;
+ }
+
+// Destructor
+EXPORT_C CCenRepNotifyHandler::~CCenRepNotifyHandler()
+ {
+ Cancel();
+ }
+
+/**
+* When this method is called, the CCenRepNotifyHandler starts
+* listening for notifications. If it is already listening, nothing happens.
+*
+* For single setting handler when there is already an existing notification
+* on the same setting and session,the HandleNotifyError will be trigerred with
+* KErrAlreadyExists error
+* @leave KErrNotFound if setting does not exist
+* KErrPermissionDenied if client does not have the necessary capability
+* plus other system-wide error codes.
+* For whole settings handler, the HandleNotifyError will be trigerred with the
+* error code
+* @capability Dependent Capability required depends on platform security of keyspace.
+*/
+EXPORT_C void CCenRepNotifyHandler::StartListeningL()
+ {
+ if(IsActive())
+ {
+ return;
+ }
+ User::LeaveIfError(OrderNotification());
+
+ SetActive();
+ }
+
+/**
+* When this method is called, the CCenRepNotifyHandler stops
+* listening for notifications. If it is already stopped, nothing happens.
+* @capability None
+*/
+EXPORT_C void CCenRepNotifyHandler::StopListening()
+ {
+ if(IsActive())
+ {
+ Cancel();
+ }
+ }
+
+/**
+* Implements CActive
+*/
+void CCenRepNotifyHandler::RunL()
+ {
+ // Check that notification was for correct ID or it was caused by
+ // a repository wide reset (KInvalidNotificationId).
+ TUint32 status = static_cast<TUint32>(iStatus.Int());
+ if( !iWholeRepository && status != iId &&
+ status != NCentralRepositoryConstants::KInvalidNotificationId )
+ {
+#ifdef _DEBUG
+ RDebug::Print(_L("CCenRepNotifyHandler::RunL(): Received notif about unknown key: %d"),
+ status);
+ RDebug::Print(_L("CCenRepNotifyHandler::RunL(): Notification not renewed."));
+#endif
+ // We are not listening to key notified for us. Do not reorder notification
+ // as there is clearly some problems in central repository.
+ iCallback.HandleNotifyError(status, KErrArgument, this);
+ return;
+ }
+
+ if (iWholeRepository && iStatus.Int() == KErrPermissionDenied)
+ {
+
+ RArray<TUint32> allKeyList;
+ //check every single settings that we have read permission
+ TRAPD(err,iSession.FindL(0x00000000,0x00000000,allKeyList));
+ if (err==KErrNone)
+ {
+ TInt arrayCount=allKeyList.Count();
+ for (TInt i=0;i<arrayCount;i++)
+ {
+ TUint32 dummyMeta;
+ err=iSession.GetMeta(allKeyList[i],dummyMeta);
+ //potential error at this stage likely to include only
+ //KErrPermissionDenied plus other resource allocation
+ //error such as KErrNoMemory
+ if (err!=KErrNone)
+ {
+ TInt errorkey=allKeyList[i];
+ allKeyList.Close();
+ iCallback.HandleNotifyError(errorkey, err, this);
+ return;
+ }
+ }
+ }
+ else
+ {
+ iCallback.HandleNotifyError( NCentralRepositoryConstants::KUnspecifiedKey , err, this );
+ return;
+ }
+ }
+
+ // Reorder notification
+ TInt err = OrderNotification();
+
+ // Handle notification
+ if ( err == KErrNone )
+ {
+ SetActive();
+ if ( iWholeRepository )
+ {
+ iCallback.HandleNotifyGeneric(status);
+ }
+ else
+ {
+ switch (iKeyType)
+ {
+ case EIntKey:
+ {
+ TInt newValue;
+ err=iSession.Get(iId, newValue);
+ if (err==KErrNone)
+ {
+ iCallback.HandleNotifyInt(iId, newValue);
+ }
+ }
+ break;
+ case ERealKey:
+ {
+ TReal newValue;
+ err=iSession.Get(iId, newValue);
+ if (err==KErrNone)
+ {
+ iCallback.HandleNotifyReal(iId, newValue);
+ }
+ }
+ break;
+ case EStringKey:
+ {
+ TBuf16<NCentralRepositoryConstants::KMaxUnicodeStringLength> newValue;
+ err=iSession.Get(iId, newValue);
+ if (err==KErrNone)
+ {
+ iCallback.HandleNotifyString(iId, newValue);
+ }
+ }
+ break;
+ case EBinaryKey:
+ {
+ TBuf8<NCentralRepositoryConstants::KMaxBinaryLength> newValue;
+ err=iSession.Get(iId, newValue);
+ if (err==KErrNone)
+ {
+ iCallback.HandleNotifyBinary(iId, newValue);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ if (err!=KErrNone)
+ {
+ iCallback.HandleNotifyError(iId,err,this);
+ }
+ }
+ }
+ else
+ {
+ iCallback.HandleNotifyError(status, err, this);
+ }
+ }
+
+/**
+* Implements CActive
+* @param aError the error returned
+* @return error
+*/
+TInt CCenRepNotifyHandler::RunError(TInt aError)
+ {
+ if ( iWholeRepository )
+ {
+ iCallback.HandleNotifyError(NCentralRepositoryConstants::KInvalidNotificationId,
+ aError, this);
+ }
+ else
+ {
+ iCallback.HandleNotifyError(iId, aError, this);
+ }
+
+ return KErrNone;
+ }
+
+/**
+* Implements CActive
+*/
+void CCenRepNotifyHandler::DoCancel()
+ {
+ if ( iWholeRepository )
+ {
+ iSession.NotifyCancelAll();
+ }
+ else
+ {
+ iSession.NotifyCancel(iId);
+ }
+ }
+
+/*
+* Order notification
+* @return error code from CenRep
+*/
+TInt CCenRepNotifyHandler::OrderNotification()
+ {
+ if ( iWholeRepository )
+ {
+ // order notification for all keys in repository
+ return iSession.NotifyRequest(0x00000000, 0x00000000, iStatus);
+ }
+ else
+ {
+ return iSession.NotifyRequest(iId, iStatus);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// MCenRepNotifyHandlerCallback::HandleNotifyXXX
+// Default implementations for callback interface.
+// In debug build these methods print trace.
+// In release build they do nothing.
+//
+// These methods are documented in cenrepnotifierhandler.h. Don't redocument
+// here.
+// -----------------------------------------------------------------------------
+//
+#ifdef _DEBUG
+EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyInt(TUint32 aId, TInt aNewValue)
+ {
+ RDebug::Print(_L("MCenRepNotifyHandlerCallback: Integer key %d changed, new value: %d"),
+ aId, aNewValue);
+ }
+
+EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyReal(TUint32 aId, TReal aNewValue)
+ {
+ RDebug::Print(_L("MCenRepNotifyHandlerCallback: Real key %d changed, new value: %e"),
+ aId, aNewValue);
+ }
+
+EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyString(TUint32 aId,
+ const TDesC16& aNewValue)
+ {
+ RDebug::Print(_L("MCenRepNotifyHandlerCallback: String key %d changed, new value: %S"),
+ aId, &aNewValue);
+ }
+
+EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyBinary(TUint32 aId,
+ const TDesC8& aNewValue)
+ {
+ RDebug::Print(_L("MCenRepNotifyHandlerCallback: Binary key %d changed, new value: %s"),
+ aId, aNewValue.Ptr());
+ }
+
+EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyGeneric(TUint32 aId)
+ {
+ if ( aId == NCentralRepositoryConstants::KInvalidNotificationId )
+ {
+ RDebug::Print(_L("MCenRepNotifyHandlerCallback: "));
+ RDebug::Print(_L("Repository wide reset caused generic notification"));
+ }
+ else
+ {
+ RDebug::Print(_L("MCenRepNotifyHandlerCallback: Generic key %d changed"), aId);
+ }
+ }
+
+EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyError(TUint32 aId, TInt aError,
+ CCenRepNotifyHandler* aHandler)
+ {
+ RDebug::Print(_L("MCenRepNotifyHandlerCallback %d notifies error for id: %d, error: %d"),
+ aHandler, aId, aError);
+ }
+
+#else
+
+EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyInt(TUint32 /*aId*/, TInt /*aNewValue*/)
+ {
+ }
+
+EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyReal(TUint32 /*aId*/, TReal /*aNewValue*/)
+ {
+ }
+
+EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyString(TUint32 /*aId*/,
+ const TDesC16& /*aNewValue*/)
+ {
+ }
+
+EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyBinary(TUint32 /*aId*/,
+ const TDesC8& /*aNewValue*/)
+ {
+ }
+
+EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyGeneric(TUint32 /*aId*/)
+ {
+ }
+
+EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyError(TUint32 /*aId*/, TInt /*aError*/,
+ CCenRepNotifyHandler* /*aHandler*/)
+ {
+ }
+#endif // _DEBUG
+
+// End of File