1 /* |
|
2 * Copyright (c) 2002-2007 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: Recogniser wrapper |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 // INCLUDE FILES |
|
21 #include "CGflmFileRecognizer.h" |
|
22 #include "CGflmDriveResolver.h" |
|
23 #include "CGflmDriveItem.h" |
|
24 #include "GflmUtils.h" |
|
25 #include "GFLMConsts.h" |
|
26 #include <e32svr.h> |
|
27 #include <barsread.h> |
|
28 #include <gflmfileextensionmimetypes.rsg> |
|
29 #include <data_caging_path_literals.hrh> |
|
30 |
|
31 |
|
32 // CONSTANTS |
|
33 _LIT( KFileExtensionResourceFile, "gflmfileextensionmimetypes.rsc" ); |
|
34 const TInt KMimeTypeGranularity = 10; |
|
35 const TUint KPerCentToDrop = 30; |
|
36 const TUint KHundredPerCent = 100; |
|
37 |
|
38 |
|
39 // ============================ MEMBER FUNCTIONS =============================== |
|
40 |
|
41 // ----------------------------------------------------------------------------- |
|
42 // CGflmFileRecognizer::CGflmFileRecognizer |
|
43 // C++ default constructor can NOT contain any code, that |
|
44 // might leave. |
|
45 // ----------------------------------------------------------------------------- |
|
46 // |
|
47 CGflmFileRecognizer::CGflmFileRecognizer( |
|
48 CGflmDriveResolver* aDriveResolver, |
|
49 RFs& aFs ) : |
|
50 iCache( _FOFF( CPathTypePair, iLink ) ), |
|
51 iDriveResolver( aDriveResolver ), |
|
52 iFs( aFs ) |
|
53 { |
|
54 } |
|
55 |
|
56 // ----------------------------------------------------------------------------- |
|
57 // CGflmFileRecognizer::ConstructL |
|
58 // Symbian 2nd phase constructor can leave. |
|
59 // ----------------------------------------------------------------------------- |
|
60 // |
|
61 void CGflmFileRecognizer::ConstructL( TInt aMemoryConsumption ) |
|
62 { |
|
63 User::LeaveIfError( iApaSession.Connect() ); |
|
64 iMimeTypes = new( ELeave ) CDesCArraySeg( KMimeTypeGranularity ); |
|
65 iCacheMaxMemoryUsage = aMemoryConsumption; |
|
66 |
|
67 // Get resource drive from dll location |
|
68 TFileName dllFileName; |
|
69 Dll::FileName( dllFileName ); |
|
70 TParsePtrC dllParse( dllFileName ); |
|
71 |
|
72 TFileName resFileName; |
|
73 resFileName.Copy( dllParse.Drive() ); |
|
74 resFileName.Append( KDC_RESOURCE_FILES_DIR ); |
|
75 GflmUtils::EnsureFinalBackslash( resFileName ); |
|
76 resFileName.Append( KFileExtensionResourceFile ); |
|
77 |
|
78 RResourceFile resFile; |
|
79 resFile.OpenL( iFs, resFileName ); |
|
80 CleanupClosePushL( resFile ); |
|
81 resFile.ConfirmSignatureL(); |
|
82 |
|
83 ConstructExtMimePairsL( resFile, R_EXT_MIME_PAIRS, iExtMimePairs ); |
|
84 ConstructExtMimePairsL( |
|
85 resFile, R_REMOTE_EXT_MIME_PAIRS, iRemoteExtMimePairs ); |
|
86 |
|
87 CleanupStack::PopAndDestroy( &resFile ); |
|
88 } |
|
89 |
|
90 // ----------------------------------------------------------------------------- |
|
91 // CGflmFileRecognizer::ConstructExtMimePairsL |
|
92 // |
|
93 // ----------------------------------------------------------------------------- |
|
94 // |
|
95 void CGflmFileRecognizer::ConstructExtMimePairsL( |
|
96 RResourceFile& aResFile, |
|
97 TInt aResId, |
|
98 RPointerArray< CExtMimePair >& aPairs ) |
|
99 { |
|
100 TCleanupItem cleanupItem( ResetAndDestroyExtMimePairs, &aPairs ); |
|
101 CleanupStack::PushL( cleanupItem ); |
|
102 // read the pairs |
|
103 HBufC8* resData = aResFile.AllocReadLC( aResId ); |
|
104 TResourceReader reader; |
|
105 reader.SetBuffer( resData ); |
|
106 TInt count( reader.ReadInt16() ); |
|
107 aPairs.ReserveL( count ); |
|
108 for ( TInt i( 0 ); i < count; i++ ) |
|
109 { |
|
110 TPtrC ext( reader.ReadTPtrC() ); |
|
111 TPtrC mime( reader.ReadTPtrC() ); |
|
112 CExtMimePair* pair = new (ELeave) CExtMimePair(); |
|
113 CleanupStack::PushL( pair ); |
|
114 pair->iExt = ext.AllocL(); |
|
115 pair->iMime = mime.AllocL(); |
|
116 aPairs.AppendL( pair ); |
|
117 CleanupStack::Pop( pair ); |
|
118 } |
|
119 CleanupStack::PopAndDestroy( resData ); |
|
120 CleanupStack::Pop( &aPairs ); |
|
121 } |
|
122 |
|
123 // ----------------------------------------------------------------------------- |
|
124 // CGflmFileRecognizer::FindMimeFromExt |
|
125 // |
|
126 // ----------------------------------------------------------------------------- |
|
127 // |
|
128 TPtrC CGflmFileRecognizer::FindMimeFromExt( |
|
129 const TDesC& aExt, |
|
130 RPointerArray< CExtMimePair >& aPairs ) |
|
131 { |
|
132 TInt count( aPairs.Count() ); |
|
133 |
|
134 for( TInt i( 0 ); i < count; i++) |
|
135 { |
|
136 CExtMimePair* pair = aPairs[ i ]; |
|
137 if( !aExt.CompareF( *pair->iExt ) ) |
|
138 { |
|
139 return TPtrC( *pair->iMime ); |
|
140 } |
|
141 } |
|
142 return TPtrC( KNullDesC ); |
|
143 } |
|
144 |
|
145 // ----------------------------------------------------------------------------- |
|
146 // CGflmFileRecognizer::NewL |
|
147 // Two-phased constructor. |
|
148 // ----------------------------------------------------------------------------- |
|
149 // |
|
150 CGflmFileRecognizer* CGflmFileRecognizer::NewL( |
|
151 RFs& aFs, |
|
152 TInt aMemoryConsumption, |
|
153 CGflmDriveResolver* aDriveResolver ) |
|
154 { |
|
155 CGflmFileRecognizer* self = |
|
156 new( ELeave ) CGflmFileRecognizer( aDriveResolver, aFs ); |
|
157 |
|
158 CleanupStack::PushL( self ); |
|
159 self->ConstructL( aMemoryConsumption ); |
|
160 CleanupStack::Pop( self ); |
|
161 |
|
162 return self; |
|
163 } |
|
164 |
|
165 // ----------------------------------------------------------------------------- |
|
166 // CGflmFileRecognizer::~CGflmFileRecognizer |
|
167 // |
|
168 // ----------------------------------------------------------------------------- |
|
169 // |
|
170 CGflmFileRecognizer::~CGflmFileRecognizer() |
|
171 { |
|
172 iApaSession.Close(); |
|
173 |
|
174 FlushCache(); |
|
175 |
|
176 delete iMimeTypes; |
|
177 |
|
178 iExtMimePairs.ResetAndDestroy(); |
|
179 iExtMimePairs.Close(); |
|
180 |
|
181 iRemoteExtMimePairs.ResetAndDestroy(); |
|
182 iRemoteExtMimePairs.Close(); |
|
183 } |
|
184 |
|
185 // ----------------------------------------------------------------------------- |
|
186 // CGflmFileRecognizer::RecognizeL( const TDesC& aFilename ) |
|
187 // (other items were commented in a header). |
|
188 // ----------------------------------------------------------------------------- |
|
189 // |
|
190 TPtrC CGflmFileRecognizer::RecognizeL( const TDesC& aFilename ) |
|
191 { |
|
192 TPtrC mimeType; |
|
193 TRAPD( err, mimeType.Set( DoRecognizeL( aFilename ) ) ); |
|
194 if ( err == KErrNoMemory ) |
|
195 { |
|
196 FlushCache(); |
|
197 return DoRecognizeL( aFilename ); |
|
198 } |
|
199 User::LeaveIfError( err ); |
|
200 return mimeType; |
|
201 } |
|
202 |
|
203 // ----------------------------------------------------------------------------- |
|
204 // CGflmFileRecognizer::DoRecognizeL( const TDesC& aFilename ) |
|
205 // (other items were commented in a header). |
|
206 // ----------------------------------------------------------------------------- |
|
207 // |
|
208 TPtrC CGflmFileRecognizer::DoRecognizeL( const TDesC& aFilename ) |
|
209 { |
|
210 // Search the cache for a hit |
|
211 TInt cropPoint( aFilename.LocateReverse( KGFLMDot()[ 0 ] ) ); |
|
212 TBool isRemoteDrive( EFalse ); |
|
213 |
|
214 if ( iDriveResolver && iDriveResolver->IsRemoteDrive( aFilename ) ) |
|
215 { |
|
216 isRemoteDrive = ETrue; |
|
217 } |
|
218 |
|
219 if( cropPoint != KErrNotFound ) |
|
220 { |
|
221 TPtrC ext( aFilename.Mid( cropPoint ) ); |
|
222 TPtrC mime( FindMimeFromExt( ext, iExtMimePairs ) ); |
|
223 if ( mime.Length() ) |
|
224 { |
|
225 return mime; |
|
226 } |
|
227 |
|
228 // Use remote drive specific extension mime pairs and skip |
|
229 // content recognition because it is so slow for remote drives. |
|
230 // Mime types are resolved from extension by remote storage framework |
|
231 // anyway. |
|
232 if ( isRemoteDrive) |
|
233 { |
|
234 return FindMimeFromExt( ext, iRemoteExtMimePairs ); |
|
235 } |
|
236 } |
|
237 else if ( isRemoteDrive) |
|
238 { |
|
239 // Skip content recognition for remote drives because it is so slow |
|
240 return TPtrC( KNullDesC ); |
|
241 } |
|
242 |
|
243 TDblQueIter< CPathTypePair > pairIt( iCache ); |
|
244 pairIt.SetToFirst(); |
|
245 CPathTypePair* pair = NULL; |
|
246 while ( ( pair = pairIt++ ) != NULL ) |
|
247 { |
|
248 TPtrC ptr( *( pair->iFilename ) ); |
|
249 if( ptr.Length() == aFilename.Length() && |
|
250 !aFilename.CompareF( ptr ) ) |
|
251 { |
|
252 // Cache hit |
|
253 // Move item to the first position if not already. |
|
254 // When clearing cache, oldest items can be dropped easily. |
|
255 pair->iLink.Deque(); |
|
256 iCache.AddFirst( *pair ); |
|
257 |
|
258 if ( pair->iTypeIndex != KErrNotFound ) |
|
259 { |
|
260 return iMimeTypes->MdcaPoint( pair->iTypeIndex ); |
|
261 } |
|
262 return TPtrC( KNullDesC ); |
|
263 } |
|
264 } |
|
265 |
|
266 // Cache miss |
|
267 TUid uid( KNullUid ); |
|
268 TDataType datatype; |
|
269 |
|
270 TIMESTAMP( "GFLM AppForDocument started: " ) |
|
271 |
|
272 // Acquire the mime-type of the file |
|
273 TInt err( iApaSession.AppForDocument( aFilename, uid, datatype ) ); |
|
274 |
|
275 TIMESTAMP( "GFLM AppForDocument ended: " ) |
|
276 |
|
277 if ( err != KErrNone ) |
|
278 { |
|
279 // If recognition returns error, handle as unrecognized file |
|
280 ERROR_LOG1( |
|
281 "CGflmFileRecognizer::DoRecognizeL-AppForDocument=%d", |
|
282 err ) |
|
283 return TPtrC( KNullDesC ); |
|
284 } |
|
285 |
|
286 CPathTypePair* newPair = CPathTypePair::NewLC( aFilename ); |
|
287 TPtrC mimeType( datatype.Des() ); |
|
288 |
|
289 INFO_LOG2( "GFLM AppForDocument:file=%S,mime=%S", &aFilename, &mimeType ) |
|
290 |
|
291 // Run through the mime-type list to find the correct index |
|
292 if ( mimeType.Length() ) |
|
293 { |
|
294 TBool isMimeFound( EFalse ); |
|
295 TInt mimeCount( iMimeTypes->MdcaCount() ); |
|
296 for ( TInt j( 0 ); j < mimeCount; j++ ) |
|
297 { |
|
298 if( !mimeType.CompareF( iMimeTypes->MdcaPoint( j ) ) ) |
|
299 { |
|
300 newPair->iTypeIndex = j; |
|
301 isMimeFound = ETrue; |
|
302 break; |
|
303 } |
|
304 } |
|
305 // Add mime type to list if not already added |
|
306 if ( !isMimeFound ) |
|
307 { |
|
308 iMimeTypes->AppendL( mimeType ); |
|
309 newPair->iTypeIndex = mimeCount; |
|
310 } |
|
311 } |
|
312 |
|
313 // Cleanup cache and add new pair |
|
314 CleanupStack::Pop( newPair ); |
|
315 CleanupCache(); |
|
316 iCacheMemoryUsage += newPair->Size(); |
|
317 iCache.AddFirst( *newPair ); |
|
318 |
|
319 if ( newPair->iTypeIndex != KErrNotFound ) |
|
320 { |
|
321 return iMimeTypes->MdcaPoint( newPair->iTypeIndex ); |
|
322 } |
|
323 return TPtrC( KNullDesC ); |
|
324 } |
|
325 |
|
326 |
|
327 // ----------------------------------------------------------------------------- |
|
328 // CGflmFileRecognizer::ResetAndDestroyExtMimePairs( ) |
|
329 // |
|
330 // ----------------------------------------------------------------------------- |
|
331 // |
|
332 void CGflmFileRecognizer::ResetAndDestroyExtMimePairs( TAny* aPtr ) |
|
333 { |
|
334 RPointerArray< CExtMimePair >* extMimePairs = |
|
335 static_cast< RPointerArray< CExtMimePair >* >( aPtr ); |
|
336 extMimePairs->ResetAndDestroy(); |
|
337 extMimePairs->Close(); |
|
338 } |
|
339 |
|
340 |
|
341 // ----------------------------------------------------------------------------- |
|
342 // CGflmFileRecognizer::FlushCache( ) |
|
343 // |
|
344 // ----------------------------------------------------------------------------- |
|
345 // |
|
346 void CGflmFileRecognizer::FlushCache() |
|
347 { |
|
348 TDblQueIter< CPathTypePair > pairIt( iCache ); |
|
349 pairIt.SetToFirst(); |
|
350 CPathTypePair* pair = NULL; |
|
351 while ( ( pair = pairIt++ ) != NULL ) |
|
352 { |
|
353 pair->iLink.Deque(); |
|
354 delete pair; |
|
355 } |
|
356 iCacheMemoryUsage = 0; |
|
357 } |
|
358 |
|
359 // ----------------------------------------------------------------------------- |
|
360 // CGflmFileRecognizer::CleanupCache( ) |
|
361 // |
|
362 // ----------------------------------------------------------------------------- |
|
363 // |
|
364 void CGflmFileRecognizer::CleanupCache( ) |
|
365 { |
|
366 if( iCacheMemoryUsage > iCacheMaxMemoryUsage ) |
|
367 { |
|
368 TInt dropThreshold = ( TInt ) ( ( ( ( TUint ) iCacheMaxMemoryUsage ) * |
|
369 KPerCentToDrop ) / KHundredPerCent ); |
|
370 TInt droppedSize( 0 ); |
|
371 |
|
372 TDblQueIter< CPathTypePair > pairIt( iCache ); |
|
373 pairIt.SetToLast(); |
|
374 CPathTypePair* pair = NULL; |
|
375 while ( ( pair = pairIt-- ) != NULL ) |
|
376 { |
|
377 droppedSize += pair->Size(); |
|
378 pair->iLink.Deque(); |
|
379 delete pair; |
|
380 if ( droppedSize >= dropThreshold ) |
|
381 { |
|
382 break; |
|
383 } |
|
384 } |
|
385 iCacheMemoryUsage -= droppedSize; |
|
386 } |
|
387 } |
|
388 |
|
389 // ----------------------------------------------------------------------------- |
|
390 // CGflmFileRecognizer::CPathTypePair::NewLC() |
|
391 // |
|
392 // ----------------------------------------------------------------------------- |
|
393 // |
|
394 CGflmFileRecognizer::CPathTypePair* |
|
395 CGflmFileRecognizer::CPathTypePair::NewLC( const TDesC& aFilename ) |
|
396 { |
|
397 CPathTypePair* self = new ( ELeave ) CPathTypePair(); |
|
398 CleanupStack::PushL( self ); |
|
399 self->ConstructL( aFilename ); |
|
400 return self; |
|
401 } |
|
402 |
|
403 // ----------------------------------------------------------------------------- |
|
404 // CGflmFileRecognizer::CPathTypePair::ConstructL() |
|
405 // |
|
406 // ----------------------------------------------------------------------------- |
|
407 // |
|
408 void CGflmFileRecognizer::CPathTypePair::ConstructL( const TDesC& aFilename ) |
|
409 { |
|
410 iFilename = aFilename.AllocL(); |
|
411 } |
|
412 |
|
413 // ----------------------------------------------------------------------------- |
|
414 // CGflmFileRecognizer::CPathTypePair::CPathTypePair() |
|
415 // |
|
416 // ----------------------------------------------------------------------------- |
|
417 // |
|
418 CGflmFileRecognizer::CPathTypePair::CPathTypePair() : |
|
419 iTypeIndex( KErrNotFound ) |
|
420 { |
|
421 } |
|
422 |
|
423 // ----------------------------------------------------------------------------- |
|
424 // CGflmFileRecognizer::CPathTypePair::~CPathTypePair() |
|
425 // |
|
426 // ----------------------------------------------------------------------------- |
|
427 // |
|
428 CGflmFileRecognizer::CPathTypePair::~CPathTypePair() |
|
429 { |
|
430 delete iFilename; |
|
431 } |
|
432 |
|
433 // ----------------------------------------------------------------------------- |
|
434 // CGflmFileRecognizer::CPathTypePair::Size() |
|
435 // |
|
436 // ----------------------------------------------------------------------------- |
|
437 // |
|
438 TInt CGflmFileRecognizer::CPathTypePair::Size() const |
|
439 { |
|
440 return ( sizeof( TInt ) + iFilename->Size() + sizeof( TDblQueLink ) ); |
|
441 } |
|
442 |
|
443 // ----------------------------------------------------------------------------- |
|
444 // CGflmFileRecognizer::CExtMimePair::~CExtMimePair() |
|
445 // |
|
446 // ----------------------------------------------------------------------------- |
|
447 // |
|
448 CGflmFileRecognizer::CExtMimePair::~CExtMimePair() |
|
449 { |
|
450 delete iExt; |
|
451 delete iMime; |
|
452 } |
|
453 |
|
454 // End of File |
|