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