os/persistentdata/persistentstorage/centralrepository/cenrepnotifierhandler/src/cenrepnotifyhandler.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// INCLUDE FILES
sl@0
    15
//
sl@0
    16
sl@0
    17
sl@0
    18
sl@0
    19
#include <e32std.h>
sl@0
    20
#include <e32svr.h>
sl@0
    21
#include <centralrepository.h>
sl@0
    22
#include "cenrepnotifyhandler.h"
sl@0
    23
sl@0
    24
// ============================ MEMBER FUNCTIONS ===============================
sl@0
    25
sl@0
    26
/**
sl@0
    27
* Constructor used for single key listening.
sl@0
    28
*
sl@0
    29
* @param aCallback Reference to a callback instance.
sl@0
    30
* @param aSession Reference to an existing repository session.
sl@0
    31
* @param aKeyType  Type of the key identified by aId parameter.
sl@0
    32
* @param aId       Id of the key that change notifications are needed for.
sl@0
    33
* @capability      None
sl@0
    34
*/
sl@0
    35
CCenRepNotifyHandler::CCenRepNotifyHandler(
sl@0
    36
    MCenRepNotifyHandlerCallback& aCallback, 
sl@0
    37
    CRepository& aSession, 
sl@0
    38
    TCenRepKeyType aKeyType, 
sl@0
    39
    TUint32 aId)
sl@0
    40
    : CActive(EPriorityStandard), iSession(aSession), 
sl@0
    41
    iCallback(aCallback), iKeyType(aKeyType), iId(aId), iWholeRepository(EFalse)
sl@0
    42
    {
sl@0
    43
    CActiveScheduler::Add(this);
sl@0
    44
    }
sl@0
    45
sl@0
    46
/**
sl@0
    47
* Constructor used for whole repository listening.
sl@0
    48
*
sl@0
    49
* @param aCallback Reference to a callback instance.
sl@0
    50
* @param aSession Reference to an existing repository session.
sl@0
    51
* @capability None
sl@0
    52
*/
sl@0
    53
CCenRepNotifyHandler::CCenRepNotifyHandler(
sl@0
    54
    MCenRepNotifyHandlerCallback& aCallback, 
sl@0
    55
    CRepository& aSession)
sl@0
    56
    : CActive(EPriorityStandard), iSession(aSession), iCallback(aCallback), 
sl@0
    57
    iKeyType(EIntKey), iId(0), iWholeRepository(ETrue)
sl@0
    58
    {
sl@0
    59
    CActiveScheduler::Add(this);
sl@0
    60
    }
sl@0
    61
sl@0
    62
/**
sl@0
    63
* This is a two-phase constructor method that is used to
sl@0
    64
* create a new instance for listening to the changes in a single key.
sl@0
    65
*
sl@0
    66
* @param aCallback Reference to a callback instance.
sl@0
    67
* @param aSession  Reference to an existing repository session.
sl@0
    68
*                  Do not close this session until all CCenRepNotifyHandler
sl@0
    69
*                  instances referring to it have been deleted.
sl@0
    70
* @param aKeyType  Type of the key identified by aId parameter. 
sl@0
    71
* @param aId       Id of the key that change notifications are needed for.
sl@0
    72
* @return          A pointer to a new instance of the CCenRepNotifyHandler class.
sl@0
    73
* 
sl@0
    74
* @leave           KErrArgument if invalid key type is passed as a parameter.
sl@0
    75
* @capability      None
sl@0
    76
*/
sl@0
    77
EXPORT_C CCenRepNotifyHandler* CCenRepNotifyHandler::NewL(
sl@0
    78
    MCenRepNotifyHandlerCallback& aCallback, 
sl@0
    79
    CRepository& aSession, 
sl@0
    80
    TCenRepKeyType aKeyType, 
sl@0
    81
    TUint32 aId)
sl@0
    82
    {
sl@0
    83
    CCenRepNotifyHandler* newInstance = NewLC(aCallback, aSession, aKeyType, aId);
sl@0
    84
    CleanupStack::Pop();
sl@0
    85
    return newInstance;
sl@0
    86
    }
sl@0
    87
sl@0
    88
/**
sl@0
    89
* This is a two-phase constructor method that is used to create a new
sl@0
    90
* instance for listening to the changes in all keys in the repository. 
sl@0
    91
*
sl@0
    92
* Type specific callback methods of MCenRepNotifyHandlerCallback will not
sl@0
    93
* be used when notifying about changes in this case,
sl@0
    94
* only HandleNotifyGeneric() is used.
sl@0
    95
*
sl@0
    96
* @param aCallback Reference to a callback instance.
sl@0
    97
* @param aSession  Reference to an existing repository session.
sl@0
    98
*                  Do not close this session until all CCenRepNotifyHandler
sl@0
    99
*                  instances referring to it have been deleted.
sl@0
   100
* @return          A pointer to a new instance of the CCenRepNotifyHandler class.
sl@0
   101
* @capability      None
sl@0
   102
*/
sl@0
   103
EXPORT_C CCenRepNotifyHandler* CCenRepNotifyHandler::NewL(
sl@0
   104
    MCenRepNotifyHandlerCallback& aCallback, 
sl@0
   105
    CRepository& aSession)
sl@0
   106
    {
sl@0
   107
    CCenRepNotifyHandler* newInstance = NewLC(aCallback, aSession);
sl@0
   108
    CleanupStack::Pop();
sl@0
   109
    return newInstance;
sl@0
   110
    }
sl@0
   111
sl@0
   112
/**
sl@0
   113
* This is a two-phase constructor method that is used to create a new
sl@0
   114
* instance for listening to the changes in a single key.
sl@0
   115
* Leaves the constructed instance to cleanup stack.
sl@0
   116
*
sl@0
   117
* @param aCallback Reference to a callback instance.
sl@0
   118
* @param aSession  Reference to an existing repository session.
sl@0
   119
*                  Do not close this session until all CCenRepNotifyHandler
sl@0
   120
*                  instances referring to it have been deleted.
sl@0
   121
* @param aKeyType  Type of the key identified by aId parameter.
sl@0
   122
* @param aId       Id of the key that change notifications are needed for.
sl@0
   123
* @return          A pointer to a new instance of the CCenRepNotifyHandler class.
sl@0
   124
* 
sl@0
   125
* @leave           KErrArgument if invalid key type is passed as a parameter.
sl@0
   126
* @capability      None
sl@0
   127
*/
sl@0
   128
EXPORT_C CCenRepNotifyHandler* CCenRepNotifyHandler::NewLC(
sl@0
   129
    MCenRepNotifyHandlerCallback& aCallback, 
sl@0
   130
    CRepository& aSession, 
sl@0
   131
    TCenRepKeyType aKeyType, 
sl@0
   132
    TUint32 aId)
sl@0
   133
    {
sl@0
   134
    if ( aKeyType != EIntKey && 
sl@0
   135
         aKeyType != ERealKey && 
sl@0
   136
         aKeyType != EStringKey  && 
sl@0
   137
         aKeyType != EBinaryKey ) 
sl@0
   138
        { 
sl@0
   139
        User::Leave( KErrArgument ); 
sl@0
   140
        } 
sl@0
   141
sl@0
   142
    CCenRepNotifyHandler* newInstance = new (ELeave) CCenRepNotifyHandler( aCallback, aSession, 
sl@0
   143
                                                                           aKeyType, aId);
sl@0
   144
    CleanupStack::PushL( newInstance );
sl@0
   145
    return newInstance;
sl@0
   146
    }
sl@0
   147
sl@0
   148
/**
sl@0
   149
* This is a two-phase constructor method that is used to create a new
sl@0
   150
* instance for listening to the changes in all keys in the repository.
sl@0
   151
* Leaves the constructed instance to cleanup stack. 
sl@0
   152
*
sl@0
   153
* Type specific callback methods of MCenRepNotifyHandlerCallback will
sl@0
   154
* not be used when notifying about changes in this case,
sl@0
   155
* only HandleNotifyGeneric() is used.
sl@0
   156
*
sl@0
   157
* @param aCallback Reference to a callback instance.
sl@0
   158
* @param aSession  Reference to an existing repository session.
sl@0
   159
*                  Do not close this session until all CCenRepNotifyHandler
sl@0
   160
*                  instances referring to it have been deleted.
sl@0
   161
* @return          A pointer to a new instance of the CCenRepNotifyHandler class.
sl@0
   162
* @capability      None
sl@0
   163
*/
sl@0
   164
EXPORT_C CCenRepNotifyHandler* CCenRepNotifyHandler::NewLC(
sl@0
   165
    MCenRepNotifyHandlerCallback& aCallback, 
sl@0
   166
    CRepository& aSession)
sl@0
   167
    {
sl@0
   168
    CCenRepNotifyHandler* newInstance = new (ELeave) CCenRepNotifyHandler(aCallback, aSession);
sl@0
   169
    CleanupStack::PushL( newInstance );
sl@0
   170
sl@0
   171
    return newInstance;
sl@0
   172
    }
sl@0
   173
sl@0
   174
// Destructor
sl@0
   175
EXPORT_C CCenRepNotifyHandler::~CCenRepNotifyHandler()
sl@0
   176
    {
sl@0
   177
    Cancel();
sl@0
   178
    }
sl@0
   179
sl@0
   180
/**
sl@0
   181
* When this method is called, the CCenRepNotifyHandler starts
sl@0
   182
* listening for notifications. If it is already listening, nothing happens.
sl@0
   183
*
sl@0
   184
* For single setting handler when there is already an existing notification
sl@0
   185
* on the same setting and session,the HandleNotifyError will be trigerred with
sl@0
   186
* KErrAlreadyExists error
sl@0
   187
* @leave KErrNotFound if setting does not exist
sl@0
   188
* 		 KErrPermissionDenied if client does not have the necessary capability
sl@0
   189
* plus other system-wide error codes.
sl@0
   190
* For whole settings handler, the HandleNotifyError will be trigerred with the 
sl@0
   191
* error code
sl@0
   192
* @capability Dependent Capability required depends on platform security of keyspace.
sl@0
   193
*/
sl@0
   194
EXPORT_C void CCenRepNotifyHandler::StartListeningL()
sl@0
   195
    {
sl@0
   196
    if(IsActive())
sl@0
   197
        {
sl@0
   198
        return;
sl@0
   199
        }
sl@0
   200
    User::LeaveIfError(OrderNotification());
sl@0
   201
sl@0
   202
    SetActive();
sl@0
   203
    }
sl@0
   204
sl@0
   205
/**
sl@0
   206
* When this method is called, the CCenRepNotifyHandler stops
sl@0
   207
* listening for notifications. If it is already stopped, nothing happens.
sl@0
   208
* @capability      None
sl@0
   209
*/
sl@0
   210
EXPORT_C void CCenRepNotifyHandler::StopListening()
sl@0
   211
    {
sl@0
   212
    if(IsActive())
sl@0
   213
        {
sl@0
   214
        Cancel();
sl@0
   215
        }
sl@0
   216
    }
sl@0
   217
sl@0
   218
/**
sl@0
   219
* Implements CActive
sl@0
   220
*/    
sl@0
   221
void CCenRepNotifyHandler::RunL()
sl@0
   222
    {
sl@0
   223
    // Check that notification was for correct ID or it was caused by
sl@0
   224
    // a repository wide reset (KInvalidNotificationId).
sl@0
   225
    TUint32 status = static_cast<TUint32>(iStatus.Int());
sl@0
   226
    if( !iWholeRepository && status != iId && 
sl@0
   227
        status != NCentralRepositoryConstants::KInvalidNotificationId )
sl@0
   228
        {
sl@0
   229
#ifdef _DEBUG
sl@0
   230
        RDebug::Print(_L("CCenRepNotifyHandler::RunL(): Received notif about unknown key: %d"), 
sl@0
   231
        status);
sl@0
   232
        RDebug::Print(_L("CCenRepNotifyHandler::RunL(): Notification not renewed."));
sl@0
   233
#endif
sl@0
   234
        // We are not listening to key notified for us. Do not reorder notification 
sl@0
   235
        // as there is clearly some problems in central repository.
sl@0
   236
        iCallback.HandleNotifyError(status, KErrArgument, this);
sl@0
   237
        return;
sl@0
   238
        }
sl@0
   239
sl@0
   240
    if (iWholeRepository && iStatus.Int() == KErrPermissionDenied)
sl@0
   241
    	{
sl@0
   242
sl@0
   243
        RArray<TUint32> allKeyList;
sl@0
   244
        //check every single settings that we have read permission
sl@0
   245
        TRAPD(err,iSession.FindL(0x00000000,0x00000000,allKeyList));
sl@0
   246
        if (err==KErrNone)
sl@0
   247
        	{
sl@0
   248
        	TInt arrayCount=allKeyList.Count();
sl@0
   249
        	for (TInt i=0;i<arrayCount;i++)
sl@0
   250
        		{
sl@0
   251
        		TUint32 dummyMeta;
sl@0
   252
        		err=iSession.GetMeta(allKeyList[i],dummyMeta);
sl@0
   253
        		//potential error at this stage likely to include only
sl@0
   254
        		//KErrPermissionDenied plus other resource allocation
sl@0
   255
        		//error such as KErrNoMemory
sl@0
   256
        		if (err!=KErrNone)
sl@0
   257
        			{
sl@0
   258
        			TInt errorkey=allKeyList[i];
sl@0
   259
        			allKeyList.Close();
sl@0
   260
        			iCallback.HandleNotifyError(errorkey, err, this);
sl@0
   261
					return;
sl@0
   262
        			}
sl@0
   263
                }
sl@0
   264
        	}
sl@0
   265
        else
sl@0
   266
            {
sl@0
   267
            iCallback.HandleNotifyError( NCentralRepositoryConstants::KUnspecifiedKey , err, this );
sl@0
   268
            return;
sl@0
   269
            }
sl@0
   270
    	}
sl@0
   271
sl@0
   272
    // Reorder notification
sl@0
   273
    TInt err = OrderNotification();
sl@0
   274
    
sl@0
   275
    // Handle notification
sl@0
   276
    if ( err == KErrNone )
sl@0
   277
        {
sl@0
   278
        SetActive();
sl@0
   279
        if ( iWholeRepository )
sl@0
   280
            {
sl@0
   281
            iCallback.HandleNotifyGeneric(status);
sl@0
   282
            }
sl@0
   283
        else
sl@0
   284
            {
sl@0
   285
            switch (iKeyType)
sl@0
   286
                {
sl@0
   287
                case EIntKey:
sl@0
   288
                    {
sl@0
   289
                    TInt newValue;
sl@0
   290
                    err=iSession.Get(iId, newValue);
sl@0
   291
                    if (err==KErrNone)
sl@0
   292
                    	{
sl@0
   293
                    	iCallback.HandleNotifyInt(iId, newValue);
sl@0
   294
                    	}
sl@0
   295
                    }
sl@0
   296
                    break;
sl@0
   297
                case ERealKey:            
sl@0
   298
                    {
sl@0
   299
                    TReal newValue;
sl@0
   300
                    err=iSession.Get(iId, newValue);
sl@0
   301
                    if (err==KErrNone)
sl@0
   302
                    	{
sl@0
   303
                    	iCallback.HandleNotifyReal(iId, newValue);
sl@0
   304
                    	}
sl@0
   305
                    }
sl@0
   306
                    break;
sl@0
   307
                case EStringKey:
sl@0
   308
                    {
sl@0
   309
                    TBuf16<NCentralRepositoryConstants::KMaxUnicodeStringLength> newValue;
sl@0
   310
                    err=iSession.Get(iId, newValue);
sl@0
   311
                    if (err==KErrNone)
sl@0
   312
                    	{
sl@0
   313
                    	iCallback.HandleNotifyString(iId, newValue);
sl@0
   314
                    	}
sl@0
   315
                    }
sl@0
   316
                    break;
sl@0
   317
                case EBinaryKey:
sl@0
   318
                    {
sl@0
   319
                    TBuf8<NCentralRepositoryConstants::KMaxBinaryLength> newValue;
sl@0
   320
                    err=iSession.Get(iId, newValue);
sl@0
   321
                    if (err==KErrNone)
sl@0
   322
                    	{
sl@0
   323
                    	iCallback.HandleNotifyBinary(iId, newValue);
sl@0
   324
                    	}
sl@0
   325
                    }
sl@0
   326
                    break;
sl@0
   327
                default:
sl@0
   328
                    break;
sl@0
   329
                }
sl@0
   330
            if (err!=KErrNone)
sl@0
   331
            	{           	
sl@0
   332
            	iCallback.HandleNotifyError(iId,err,this);
sl@0
   333
            	}
sl@0
   334
            }
sl@0
   335
        }
sl@0
   336
    else
sl@0
   337
        {
sl@0
   338
        iCallback.HandleNotifyError(status, err, this);
sl@0
   339
        }
sl@0
   340
    }
sl@0
   341
    
sl@0
   342
/**
sl@0
   343
* Implements CActive
sl@0
   344
* @param aError the error returned
sl@0
   345
* @return error
sl@0
   346
*/
sl@0
   347
TInt CCenRepNotifyHandler::RunError(TInt aError)
sl@0
   348
    {
sl@0
   349
    if ( iWholeRepository )
sl@0
   350
        {
sl@0
   351
        iCallback.HandleNotifyError(NCentralRepositoryConstants::KInvalidNotificationId, 
sl@0
   352
                                    aError, this);    
sl@0
   353
        }
sl@0
   354
    else
sl@0
   355
        {
sl@0
   356
        iCallback.HandleNotifyError(iId, aError, this);    
sl@0
   357
        }
sl@0
   358
    
sl@0
   359
    return KErrNone;
sl@0
   360
    }
sl@0
   361
sl@0
   362
/**
sl@0
   363
* Implements CActive
sl@0
   364
*/    
sl@0
   365
void CCenRepNotifyHandler::DoCancel()
sl@0
   366
    {
sl@0
   367
    if ( iWholeRepository )
sl@0
   368
        {
sl@0
   369
        iSession.NotifyCancelAll();
sl@0
   370
        }
sl@0
   371
    else
sl@0
   372
        {
sl@0
   373
        iSession.NotifyCancel(iId);
sl@0
   374
        }
sl@0
   375
    }
sl@0
   376
sl@0
   377
/* 
sl@0
   378
* Order notification
sl@0
   379
* @return error code from CenRep
sl@0
   380
*/
sl@0
   381
TInt CCenRepNotifyHandler::OrderNotification()
sl@0
   382
    {
sl@0
   383
    if ( iWholeRepository )
sl@0
   384
        {
sl@0
   385
        // order notification for all keys in repository
sl@0
   386
        return iSession.NotifyRequest(0x00000000, 0x00000000, iStatus);
sl@0
   387
        }
sl@0
   388
    else
sl@0
   389
        {
sl@0
   390
        return iSession.NotifyRequest(iId, iStatus);
sl@0
   391
        }
sl@0
   392
    }
sl@0
   393
sl@0
   394
// -----------------------------------------------------------------------------
sl@0
   395
// MCenRepNotifyHandlerCallback::HandleNotifyXXX
sl@0
   396
// Default implementations for callback interface. 
sl@0
   397
// In debug build these methods print trace. 
sl@0
   398
// In release build they do nothing.
sl@0
   399
//
sl@0
   400
// These methods are documented in cenrepnotifierhandler.h. Don't redocument
sl@0
   401
// here.
sl@0
   402
// -----------------------------------------------------------------------------
sl@0
   403
// 
sl@0
   404
#ifdef _DEBUG
sl@0
   405
EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyInt(TUint32 aId, TInt aNewValue)
sl@0
   406
    {
sl@0
   407
    RDebug::Print(_L("MCenRepNotifyHandlerCallback: Integer key %d changed, new value: %d"), 
sl@0
   408
    aId, aNewValue);
sl@0
   409
    }
sl@0
   410
sl@0
   411
EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyReal(TUint32 aId, TReal aNewValue)
sl@0
   412
    {
sl@0
   413
    RDebug::Print(_L("MCenRepNotifyHandlerCallback: Real key %d changed, new value: %e"), 
sl@0
   414
    aId, aNewValue);
sl@0
   415
    }
sl@0
   416
sl@0
   417
EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyString(TUint32 aId, 
sl@0
   418
                                                               const TDesC16&  aNewValue)
sl@0
   419
    {
sl@0
   420
    RDebug::Print(_L("MCenRepNotifyHandlerCallback: String key %d changed, new value: %S"), 
sl@0
   421
    aId, &aNewValue);
sl@0
   422
    }
sl@0
   423
sl@0
   424
EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyBinary(TUint32 aId, 
sl@0
   425
                                                               const TDesC8&  aNewValue)
sl@0
   426
    {
sl@0
   427
    RDebug::Print(_L("MCenRepNotifyHandlerCallback: Binary key %d changed, new value: %s"), 
sl@0
   428
    aId, aNewValue.Ptr());
sl@0
   429
    }
sl@0
   430
sl@0
   431
EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyGeneric(TUint32 aId)
sl@0
   432
    {
sl@0
   433
    if ( aId == NCentralRepositoryConstants::KInvalidNotificationId )
sl@0
   434
        {
sl@0
   435
        RDebug::Print(_L("MCenRepNotifyHandlerCallback: "));
sl@0
   436
        RDebug::Print(_L("Repository wide reset caused generic notification"));
sl@0
   437
        }
sl@0
   438
    else
sl@0
   439
        {
sl@0
   440
        RDebug::Print(_L("MCenRepNotifyHandlerCallback: Generic key %d changed"), aId);
sl@0
   441
        }
sl@0
   442
    }
sl@0
   443
sl@0
   444
EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyError(TUint32 aId, TInt aError, 
sl@0
   445
                                                              CCenRepNotifyHandler* aHandler)
sl@0
   446
    {
sl@0
   447
    RDebug::Print(_L("MCenRepNotifyHandlerCallback %d notifies error for id: %d, error: %d"), 
sl@0
   448
    aHandler, aId, aError);
sl@0
   449
    }
sl@0
   450
sl@0
   451
#else
sl@0
   452
sl@0
   453
EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyInt(TUint32 /*aId*/, TInt /*aNewValue*/)
sl@0
   454
    {
sl@0
   455
    }
sl@0
   456
sl@0
   457
EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyReal(TUint32 /*aId*/, TReal /*aNewValue*/)
sl@0
   458
    {
sl@0
   459
    }
sl@0
   460
sl@0
   461
EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyString(TUint32 /*aId*/, 
sl@0
   462
    const TDesC16&  /*aNewValue*/)
sl@0
   463
    {
sl@0
   464
    }
sl@0
   465
sl@0
   466
EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyBinary(TUint32 /*aId*/, 
sl@0
   467
    const TDesC8&  /*aNewValue*/)
sl@0
   468
    {
sl@0
   469
    }
sl@0
   470
sl@0
   471
EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyGeneric(TUint32 /*aId*/)
sl@0
   472
    {
sl@0
   473
    }
sl@0
   474
sl@0
   475
EXPORT_C void MCenRepNotifyHandlerCallback::HandleNotifyError(TUint32 /*aId*/, TInt /*aError*/, 
sl@0
   476
    CCenRepNotifyHandler* /*aHandler*/)
sl@0
   477
    {
sl@0
   478
    }
sl@0
   479
#endif // _DEBUG
sl@0
   480
sl@0
   481
// End of File