|
1 /* |
|
2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: This file implements class CEmailClientApi. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS |
|
21 #include <viewclipartner.h> |
|
22 #include <vwsdefpartner.h> |
|
23 #else |
|
24 #include <viewcli.h> |
|
25 #include <vwsdef.h> |
|
26 #endif // SYMBIAN_ENABLE_SPLIT_HEADERS |
|
27 #include <centralrepository.h> |
|
28 #include "emailclientapiimpl.h" |
|
29 #include "emailapiutils.h" |
|
30 #include "emailmailbox.h" |
|
31 #include <memailaddress.h> |
|
32 #include "cfsmailplugin.h" |
|
33 #include "cfsmailclient.h" |
|
34 #include "emailclientapiimpldefs.h" |
|
35 #include "emailmailboxcache.h" |
|
36 #include "emailclientapi.hrh" |
|
37 |
|
38 // --------------------------------------------------------------------------- |
|
39 // |
|
40 // --------------------------------------------------------------------------- |
|
41 MEmailMailbox* CEmailClientApi::MailboxL( const TMailboxId& aId ) |
|
42 { |
|
43 UpdateMailboxInfoCacheL(); |
|
44 CPluginData* pluginData = MailboxInfoCacheL().PluginDataL( aId ); |
|
45 MEmailMailbox* mailbox = NULL; |
|
46 if ( pluginData ) |
|
47 { |
|
48 mailbox = CEmailMailbox::NewL( *pluginData, aId ); |
|
49 } |
|
50 return mailbox; |
|
51 } |
|
52 |
|
53 // ----------------------------------------------------------------------------- |
|
54 // |
|
55 // ----------------------------------------------------------------------------- |
|
56 MEmailMailbox* CEmailClientApi::MailboxL( const TPtrC& aAddress ) |
|
57 { |
|
58 MEmailMailbox* mailbox = NULL; |
|
59 REmailMailboxIdArray mailboxes; |
|
60 CleanupClosePushL( mailboxes ); |
|
61 TInt count( GetMailboxIdsL( mailboxes ) ); |
|
62 while ( count-- ) |
|
63 { |
|
64 const TMailboxId mailboxId = mailboxes[count]; |
|
65 MEmailMailbox* refMailbox = MailboxL( mailboxId ); |
|
66 if ( refMailbox ) |
|
67 { |
|
68 TPtrC address( refMailbox->AddressL()->Address() ); |
|
69 if ( !address.Compare( aAddress ) ) |
|
70 { |
|
71 mailbox = refMailbox; // addresses match |
|
72 count = 0; |
|
73 } |
|
74 else |
|
75 { |
|
76 refMailbox->Release(); |
|
77 } |
|
78 } |
|
79 } |
|
80 CleanupStack::PopAndDestroy( &mailboxes ); |
|
81 // find mailbox or leave KErrNotFound |
|
82 if ( !mailbox ) |
|
83 { |
|
84 User::Leave( KErrNotFound ); |
|
85 } |
|
86 return mailbox; |
|
87 } |
|
88 |
|
89 // ----------------------------------------------------------------------------- |
|
90 // |
|
91 // ----------------------------------------------------------------------------- |
|
92 TInt CEmailClientApi::GetMailboxIdsL( |
|
93 REmailMailboxIdArray& aMailboxes ) |
|
94 { |
|
95 UpdateMailboxInfoCacheL(); |
|
96 |
|
97 aMailboxes.Reset(); |
|
98 CEmailMailboxCache& mbcache = MailboxInfoCacheL(); |
|
99 mbcache.GetIdsL( aMailboxes ); |
|
100 |
|
101 const TInt mailboxesFound( aMailboxes.Count() ); |
|
102 return mailboxesFound; |
|
103 } |
|
104 |
|
105 // ----------------------------------------------------------------------------- |
|
106 // |
|
107 // ----------------------------------------------------------------------------- |
|
108 TInt CEmailClientApi::GetMailboxesL( RMailboxPtrArray& aMailboxes ) |
|
109 { |
|
110 REmailMailboxIdArray mailboxIdArray; |
|
111 CleanupClosePushL( mailboxIdArray ); |
|
112 |
|
113 // GetMailboxIdsL loads plugin and keeps loaded if it contains at |
|
114 // least one mailbox |
|
115 TInt count = GetMailboxIdsL( mailboxIdArray ); |
|
116 while ( count-- ) |
|
117 { |
|
118 // mailbox creation increases plugin ref count by one |
|
119 MEmailMailbox* mailbox = MailboxL( mailboxIdArray[count] ); |
|
120 CleanupReleasePushL( *mailbox ); |
|
121 aMailboxes.AppendL( mailbox ); |
|
122 CleanupStack::Pop( mailbox ); |
|
123 } |
|
124 // Created mailboxes still hold plugin references so we can decrease |
|
125 // ref count. |
|
126 ReleaseAllPlugins(); |
|
127 |
|
128 CleanupStack::PopAndDestroy( &mailboxIdArray ); |
|
129 return aMailboxes.Count(); |
|
130 } |
|
131 |
|
132 // ----------------------------------------------------------------------------- |
|
133 // |
|
134 // ----------------------------------------------------------------------------- |
|
135 void CEmailClientApi::LaunchEmailL( const TLaunchPolicy /*aPolicy*/ ) |
|
136 { |
|
137 User::Leave(KErrNotSupported); |
|
138 } |
|
139 |
|
140 // ----------------------------------------------------------------------------- |
|
141 // |
|
142 // ----------------------------------------------------------------------------- |
|
143 CPluginData* CEmailClientApi::TPluginIterator::Next() |
|
144 { |
|
145 CPluginData* item = NULL; |
|
146 if ( iIndex < iArray.Count() ) |
|
147 { |
|
148 item = iArray[ iIndex++ ]; |
|
149 } |
|
150 return item; |
|
151 } |
|
152 |
|
153 // ----------------------------------------------------------------------------- |
|
154 // |
|
155 // ----------------------------------------------------------------------------- |
|
156 CEmailClientApi* CEmailClientApi::NewL() |
|
157 { |
|
158 CEmailClientApi* instance = static_cast<CEmailClientApi*>( Dll::Tls() ); |
|
159 |
|
160 if ( !instance ) |
|
161 { |
|
162 instance = new ( ELeave ) CEmailClientApi(); |
|
163 CleanupStack::PushL( instance ); |
|
164 instance->ConstructL(); |
|
165 User::LeaveIfError( Dll::SetTls( instance ) ); |
|
166 CleanupStack::Pop( instance ); |
|
167 } |
|
168 |
|
169 instance->iInstanceCounter++; |
|
170 |
|
171 return instance; |
|
172 } |
|
173 |
|
174 // ----------------------------------------------------------------------------- |
|
175 // |
|
176 // ----------------------------------------------------------------------------- |
|
177 CEmailClientApi::~CEmailClientApi() |
|
178 { |
|
179 // ensure this doesn't held plugin references |
|
180 ReleaseAllPlugins(); |
|
181 |
|
182 // ResetAndDestroy doesn't work because ~CPluginData is private |
|
183 TInt count( iPluginDataArray.Count() ); |
|
184 while ( count-- ) |
|
185 { |
|
186 delete iPluginDataArray[count]; |
|
187 } |
|
188 iPluginDataArray.Close(); |
|
189 iLoadedPluginsArray.Close(); |
|
190 delete iMailboxCache; |
|
191 |
|
192 Dll::FreeTls(); |
|
193 } |
|
194 |
|
195 // ----------------------------------------------------------------------------- |
|
196 // |
|
197 // ----------------------------------------------------------------------------- |
|
198 CEmailClientApi::CEmailClientApi() : iInstanceCounter( 0 ) |
|
199 { |
|
200 } |
|
201 |
|
202 // ----------------------------------------------------------------------------- |
|
203 // |
|
204 // ----------------------------------------------------------------------------- |
|
205 void CEmailClientApi::CleanupImplInfoPushL( RPointerArray<CImplementationInformation>& aArray ) |
|
206 { |
|
207 TCleanupItem item( &CEmailClientApi::CleanupImplInfo, &aArray ); |
|
208 CleanupStack::PushL( item ); |
|
209 } |
|
210 |
|
211 // ----------------------------------------------------------------------------- |
|
212 // |
|
213 // ----------------------------------------------------------------------------- |
|
214 void CEmailClientApi::CleanupImplInfo( TAny* aAny ) |
|
215 { |
|
216 RPointerArray<CImplementationInformation>* array = |
|
217 reinterpret_cast<RPointerArray<CImplementationInformation>*>( aAny ); |
|
218 array->ResetAndDestroy(); |
|
219 } |
|
220 |
|
221 // ----------------------------------------------------------------------------- |
|
222 // |
|
223 // ----------------------------------------------------------------------------- |
|
224 void CEmailClientApi::ConstructL() |
|
225 { |
|
226 RPointerArray<CImplementationInformation> implInfoArray; |
|
227 REComSession::ListImplementationsL( KFSMailPluginInterface, implInfoArray ); |
|
228 CleanupImplInfoPushL( implInfoArray ); |
|
229 TInt err = KErrNone; |
|
230 TInt count( implInfoArray.Count() ); |
|
231 // add implementation UIDs to plugin info array, no instantiation at this |
|
232 // phase |
|
233 while ( count-- ) |
|
234 { |
|
235 const CImplementationInformation* info = implInfoArray[count]; |
|
236 CPluginData* pluginData = new ( ELeave ) CPluginData( info->ImplementationUid() ); |
|
237 err = iPluginDataArray.Append( pluginData ); |
|
238 if ( err != KErrNone ) |
|
239 { |
|
240 // failed to append, give up |
|
241 delete pluginData; |
|
242 count = 0; |
|
243 } |
|
244 } |
|
245 iMailClient = CFSMailClient::NewL(); |
|
246 CleanupStack::PopAndDestroy( &implInfoArray ); |
|
247 User::LeaveIfError( err ); |
|
248 } |
|
249 |
|
250 // ----------------------------------------------------------------------------- |
|
251 // |
|
252 // ----------------------------------------------------------------------------- |
|
253 TEmailTypeId CEmailClientApi::InterfaceId() const |
|
254 { |
|
255 return KEmailClientApiInterface; |
|
256 } |
|
257 |
|
258 // ----------------------------------------------------------------------------- |
|
259 // |
|
260 // ----------------------------------------------------------------------------- |
|
261 void CEmailClientApi::Release() |
|
262 { |
|
263 if( this->iInstanceCounter == 1 ) |
|
264 { |
|
265 delete this; |
|
266 } |
|
267 else |
|
268 { |
|
269 this->iInstanceCounter--; |
|
270 } |
|
271 } |
|
272 |
|
273 // ----------------------------------------------------------------------------- |
|
274 // Returns plugin instance from plugin data. If we already have "claimed" |
|
275 // instance once, prevent increment of reference count |
|
276 // ----------------------------------------------------------------------------- |
|
277 CFSMailPlugin* CEmailClientApi::UsePlugin( CPluginData& aPluginData ) |
|
278 { |
|
279 // use 'data' as search key for IndexOfLoadedPluginData() |
|
280 TPluginData data( aPluginData.Uid() ); |
|
281 TPluginData* pluginDataPtr = &data; |
|
282 // check if we have plugin already "in use". |
|
283 const TInt index( IndexOfLoadedPluginData( data ) ); |
|
284 if ( index == KErrNotFound ) |
|
285 { // we don't have plugin instance so take it and add to loaded plugins |
|
286 data.iPlugin = aPluginData.ClaimInstance(); |
|
287 if ( data.iPlugin && iLoadedPluginsArray.Append( data ) != KErrNone ) |
|
288 { |
|
289 aPluginData.ReleaseInstance(); // failed to append, don't proceed.. |
|
290 data.iPlugin = NULL; // but return null |
|
291 } |
|
292 } |
|
293 else |
|
294 { |
|
295 // already in use, obtain plugin pointer from the array |
|
296 pluginDataPtr = &iLoadedPluginsArray[index]; |
|
297 } |
|
298 return pluginDataPtr->iPlugin; |
|
299 } |
|
300 |
|
301 // ----------------------------------------------------------------------------- |
|
302 // |
|
303 // ----------------------------------------------------------------------------- |
|
304 void CEmailClientApi::ReleasePlugin( CPluginData& aPluginData ) |
|
305 { |
|
306 // release plugin but only if it is not already claimed |
|
307 TPluginData data( aPluginData.Uid() ); |
|
308 const TInt index( IndexOfLoadedPluginData( data ) ); |
|
309 if ( index != KErrNotFound ) |
|
310 { |
|
311 aPluginData.ReleaseInstance(); |
|
312 iLoadedPluginsArray.Remove( index ); |
|
313 } |
|
314 } |
|
315 |
|
316 // ----------------------------------------------------------------------------- |
|
317 // |
|
318 // ----------------------------------------------------------------------------- |
|
319 void CEmailClientApi::ReleaseAllPlugins() |
|
320 { |
|
321 for ( TInt i = 0; i < iPluginDataArray.Count(); i++ ) |
|
322 { |
|
323 CPluginData* pdata = iPluginDataArray[i]; |
|
324 ReleasePlugin( *pdata ); |
|
325 } |
|
326 } |
|
327 |
|
328 // ----------------------------------------------------------------------------- |
|
329 // |
|
330 // ----------------------------------------------------------------------------- |
|
331 CEmailMailboxCache& CEmailClientApi::MailboxInfoCacheL() |
|
332 { |
|
333 if ( !iMailboxCache) |
|
334 { |
|
335 iMailboxCache = CEmailMailboxCache::NewL(); |
|
336 } |
|
337 return *iMailboxCache; |
|
338 } |
|
339 |
|
340 // ----------------------------------------------------------------------------- |
|
341 // Lists all mailboxes in protocol plugins and adds them to cache. Plugins may |
|
342 // not be loaded so loading is done. The plugin is kept in memory if it contains |
|
343 // at least one mailbox to avoid loading again later as typical use case is |
|
344 // creation of a mailbox object => the plugin is again needed |
|
345 //( see ::GetMailboxesL which calls ReleaseAllPlugins() |
|
346 // ----------------------------------------------------------------------------- |
|
347 void CEmailClientApi::UpdateMailboxInfoCacheL() |
|
348 { |
|
349 CEmailMailboxCache& mbcache = MailboxInfoCacheL(); |
|
350 if ( !mbcache.IsCached() ) |
|
351 { |
|
352 // cache update needed |
|
353 mbcache.StartCachingPushL(); |
|
354 TPluginIterator iter( iPluginDataArray ); |
|
355 CPluginData* pluginData = iter.Next(); |
|
356 while ( pluginData ) |
|
357 { |
|
358 TBool containsMailbox( EFalse ); |
|
359 // loads plugin if needed |
|
360 CFSMailPlugin* plugin = UsePlugin( *pluginData ); |
|
361 if ( plugin ) |
|
362 { |
|
363 // if one plugin fails, it should not block other plugins |
|
364 // ==> trap it |
|
365 |
|
366 TRAPD( err, containsMailbox = CachePluginMailboxesL( |
|
367 *pluginData, |
|
368 *plugin ) ); |
|
369 if ( !containsMailbox || err ) |
|
370 { |
|
371 // plugins with no mailboxes (or failed to cache) is |
|
372 // released (unloaded) to optimize RAM usage. |
|
373 ReleasePlugin( *pluginData ); |
|
374 } |
|
375 } |
|
376 else if ( pluginData->iPluginLoadError == KErrNoMemory ) |
|
377 { |
|
378 // don't continue if OOM |
|
379 User::Leave( KErrNoMemory ); |
|
380 } |
|
381 pluginData = iter.Next(); |
|
382 } |
|
383 mbcache.EndCachingPop(); |
|
384 } |
|
385 } |
|
386 |
|
387 // ----------------------------------------------------------------------------- |
|
388 // |
|
389 // ----------------------------------------------------------------------------- |
|
390 TBool CEmailClientApi::CachePluginMailboxesL( CPluginData& aPluginData, CFSMailPlugin& aPlugin ) |
|
391 { |
|
392 TBool containsMailbox( EFalse ); |
|
393 RArray<TFSMailMsgId> pluginMailboxes; |
|
394 CleanupClosePushL( pluginMailboxes ); |
|
395 aPlugin.ListMailBoxesL( pluginMailboxes ); |
|
396 TInt mailboxCount = pluginMailboxes.Count(); |
|
397 while ( mailboxCount-- ) |
|
398 { |
|
399 const TFSMailMsgId& mailboxId = pluginMailboxes[mailboxCount]; |
|
400 TMailboxId id( mailboxId.Id() ); |
|
401 MailboxInfoCacheL().AddMailboxL( aPluginData, id ); |
|
402 containsMailbox = ETrue; |
|
403 } |
|
404 CleanupStack::PopAndDestroy( &pluginMailboxes ); |
|
405 return containsMailbox; |
|
406 } |
|
407 |
|
408 // ----------------------------------------------------------------------------- |
|
409 // |
|
410 // ----------------------------------------------------------------------------- |
|
411 TInt CEmailClientApi::IndexOfLoadedPluginData( const TPluginData& aPluginData ) const |
|
412 { |
|
413 TIdentityRelation<TPluginData> relation( CEmailClientApi::PluginDataEquals ); |
|
414 return iLoadedPluginsArray.Find( aPluginData, relation ); |
|
415 } |
|
416 |
|
417 // ----------------------------------------------------------------------------- |
|
418 // |
|
419 // ----------------------------------------------------------------------------- |
|
420 TBool CEmailClientApi::PluginDataEquals( const TPluginData& a1, const TPluginData& a2 ) |
|
421 { |
|
422 return ( a1.iUid == a2.iUid ); |
|
423 } |
|
424 |
|
425 // End of file |