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 // read the pairs |
|
101 HBufC8* resData = aResFile.AllocReadLC( aResId ); |
|
102 TResourceReader reader; |
|
103 reader.SetBuffer( resData ); |
|
104 TInt count( reader.ReadInt16() ); |
|
105 aPairs.ReserveL( count ); |
|
106 for ( TInt i( 0 ); i < count; i++ ) |
|
107 { |
|
108 TPtrC ext( reader.ReadTPtrC() ); |
|
109 TPtrC mime( reader.ReadTPtrC() ); |
|
110 CExtMimePair* pair = new (ELeave) CExtMimePair(); |
|
111 CleanupStack::PushL( pair ); |
|
112 pair->iExt = ext.AllocL(); |
|
113 pair->iMime = mime.AllocL(); |
|
114 aPairs.AppendL( pair ); |
|
115 CleanupStack::Pop( pair ); |
|
116 } |
|
117 CleanupStack::PopAndDestroy( resData ); |
|
118 } |
|
119 |
|
120 // ----------------------------------------------------------------------------- |
|
121 // CGflmFileRecognizer::FindMimeFromExt |
|
122 // |
|
123 // ----------------------------------------------------------------------------- |
|
124 // |
|
125 TPtrC CGflmFileRecognizer::FindMimeFromExt( |
|
126 const TDesC& aExt, |
|
127 RPointerArray< CExtMimePair >& aPairs ) |
|
128 { |
|
129 TInt count( aPairs.Count() ); |
|
130 |
|
131 for( TInt i( 0 ); i < count; i++) |
|
132 { |
|
133 CExtMimePair* pair = aPairs[ i ]; |
|
134 if( !aExt.CompareF( *pair->iExt ) ) |
|
135 { |
|
136 return TPtrC( *pair->iMime ); |
|
137 } |
|
138 } |
|
139 return TPtrC( KNullDesC ); |
|
140 } |
|
141 |
|
142 // ----------------------------------------------------------------------------- |
|
143 // CGflmFileRecognizer::NewL |
|
144 // Two-phased constructor. |
|
145 // ----------------------------------------------------------------------------- |
|
146 // |
|
147 CGflmFileRecognizer* CGflmFileRecognizer::NewL( |
|
148 RFs& aFs, |
|
149 TInt aMemoryConsumption, |
|
150 CGflmDriveResolver* aDriveResolver ) |
|
151 { |
|
152 CGflmFileRecognizer* self = |
|
153 new( ELeave ) CGflmFileRecognizer( aDriveResolver, aFs ); |
|
154 |
|
155 CleanupStack::PushL( self ); |
|
156 self->ConstructL( aMemoryConsumption ); |
|
157 CleanupStack::Pop( self ); |
|
158 |
|
159 return self; |
|
160 } |
|
161 |
|
162 // ----------------------------------------------------------------------------- |
|
163 // CGflmFileRecognizer::~CGflmFileRecognizer |
|
164 // |
|
165 // ----------------------------------------------------------------------------- |
|
166 // |
|
167 CGflmFileRecognizer::~CGflmFileRecognizer() |
|
168 { |
|
169 iApaSession.Close(); |
|
170 |
|
171 FlushCache(); |
|
172 |
|
173 delete iMimeTypes; |
|
174 |
|
175 iExtMimePairs.ResetAndDestroy(); |
|
176 iExtMimePairs.Close(); |
|
177 |
|
178 iRemoteExtMimePairs.ResetAndDestroy(); |
|
179 iRemoteExtMimePairs.Close(); |
|
180 } |
|
181 |
|
182 // ----------------------------------------------------------------------------- |
|
183 // CGflmFileRecognizer::RecognizeL( const TDesC& aFilename ) |
|
184 // (other items were commented in a header). |
|
185 // ----------------------------------------------------------------------------- |
|
186 // |
|
187 TPtrC CGflmFileRecognizer::RecognizeL( const TDesC& aFilename ) |
|
188 { |
|
189 TPtrC mimeType; |
|
190 TRAPD( err, mimeType.Set( DoRecognizeL( aFilename ) ) ); |
|
191 if ( err == KErrNoMemory ) |
|
192 { |
|
193 FlushCache(); |
|
194 return DoRecognizeL( aFilename ); |
|
195 } |
|
196 User::LeaveIfError( err ); |
|
197 return mimeType; |
|
198 } |
|
199 |
|
200 // ----------------------------------------------------------------------------- |
|
201 // CGflmFileRecognizer::DoRecognizeL( const TDesC& aFilename ) |
|
202 // (other items were commented in a header). |
|
203 // ----------------------------------------------------------------------------- |
|
204 // |
|
205 TPtrC CGflmFileRecognizer::DoRecognizeL( const TDesC& aFilename ) |
|
206 { |
|
207 // Search the cache for a hit |
|
208 TInt cropPoint( aFilename.LocateReverse( KGFLMDot()[ 0 ] ) ); |
|
209 TBool isRemoteDrive( EFalse ); |
|
210 |
|
211 if ( iDriveResolver && iDriveResolver->IsRemoteDrive( aFilename ) ) |
|
212 { |
|
213 isRemoteDrive = ETrue; |
|
214 } |
|
215 |
|
216 if( cropPoint != KErrNotFound ) |
|
217 { |
|
218 TPtrC ext( aFilename.Mid( cropPoint ) ); |
|
219 TPtrC mime( FindMimeFromExt( ext, iExtMimePairs ) ); |
|
220 if ( mime.Length() ) |
|
221 { |
|
222 return mime; |
|
223 } |
|
224 |
|
225 // Use remote drive specific extension mime pairs and skip |
|
226 // content recognition because it is so slow for remote drives. |
|
227 // Mime types are resolved from extension by remote storage framework |
|
228 // anyway. |
|
229 if ( isRemoteDrive) |
|
230 { |
|
231 return FindMimeFromExt( ext, iRemoteExtMimePairs ); |
|
232 } |
|
233 } |
|
234 else if ( isRemoteDrive) |
|
235 { |
|
236 // Skip content recognition for remote drives because it is so slow |
|
237 return TPtrC( KNullDesC ); |
|
238 } |
|
239 |
|
240 TDblQueIter< CPathTypePair > pairIt( iCache ); |
|
241 pairIt.SetToFirst(); |
|
242 CPathTypePair* pair = NULL; |
|
243 while ( ( pair = pairIt++ ) != NULL ) |
|
244 { |
|
245 TPtrC ptr( *( pair->iFilename ) ); |
|
246 if( ptr.Length() == aFilename.Length() && |
|
247 !aFilename.CompareF( ptr ) ) |
|
248 { |
|
249 // Cache hit |
|
250 // Move item to the first position if not already. |
|
251 // When clearing cache, oldest items can be dropped easily. |
|
252 pair->iLink.Deque(); |
|
253 iCache.AddFirst( *pair ); |
|
254 |
|
255 if ( pair->iTypeIndex != KErrNotFound ) |
|
256 { |
|
257 return iMimeTypes->MdcaPoint( pair->iTypeIndex ); |
|
258 } |
|
259 return TPtrC( KNullDesC ); |
|
260 } |
|
261 } |
|
262 |
|
263 // Cache miss |
|
264 TUid uid( KNullUid ); |
|
265 TDataType datatype; |
|
266 |
|
267 TIMESTAMP( "GFLM AppForDocument started: " ) |
|
268 |
|
269 // Acquire the mime-type of the file |
|
270 TInt err( iApaSession.AppForDocument( aFilename, uid, datatype ) ); |
|
271 |
|
272 TIMESTAMP( "GFLM AppForDocument ended: " ) |
|
273 |
|
274 if ( err != KErrNone ) |
|
275 { |
|
276 // If recognition returns error, handle as unrecognized file |
|
277 ERROR_LOG1( |
|
278 "CGflmFileRecognizer::DoRecognizeL-AppForDocument=%d", |
|
279 err ) |
|
280 return TPtrC( KNullDesC ); |
|
281 } |
|
282 |
|
283 CPathTypePair* newPair = CPathTypePair::NewLC( aFilename ); |
|
284 TPtrC mimeType( datatype.Des() ); |
|
285 |
|
286 INFO_LOG2( "GFLM AppForDocument:file=%S,mime=%S", &aFilename, &mimeType ) |
|
287 |
|
288 // Run through the mime-type list to find the correct index |
|
289 if ( mimeType.Length() ) |
|
290 { |
|
291 TBool isMimeFound( EFalse ); |
|
292 TInt mimeCount( iMimeTypes->MdcaCount() ); |
|
293 for ( TInt j( 0 ); j < mimeCount; j++ ) |
|
294 { |
|
295 if( !mimeType.CompareF( iMimeTypes->MdcaPoint( j ) ) ) |
|
296 { |
|
297 newPair->iTypeIndex = j; |
|
298 isMimeFound = ETrue; |
|
299 break; |
|
300 } |
|
301 } |
|
302 // Add mime type to list if not already added |
|
303 if ( !isMimeFound ) |
|
304 { |
|
305 iMimeTypes->AppendL( mimeType ); |
|
306 newPair->iTypeIndex = mimeCount; |
|
307 } |
|
308 } |
|
309 |
|
310 // Cleanup cache and add new pair |
|
311 CleanupStack::Pop( newPair ); |
|
312 CleanupCache(); |
|
313 iCacheMemoryUsage += newPair->Size(); |
|
314 iCache.AddFirst( *newPair ); |
|
315 |
|
316 if ( newPair->iTypeIndex != KErrNotFound ) |
|
317 { |
|
318 return iMimeTypes->MdcaPoint( newPair->iTypeIndex ); |
|
319 } |
|
320 return TPtrC( KNullDesC ); |
|
321 } |
|
322 |
|
323 // ----------------------------------------------------------------------------- |
|
324 // CGflmFileRecognizer::FlushCache( ) |
|
325 // |
|
326 // ----------------------------------------------------------------------------- |
|
327 // |
|
328 void CGflmFileRecognizer::FlushCache() |
|
329 { |
|
330 TDblQueIter< CPathTypePair > pairIt( iCache ); |
|
331 pairIt.SetToFirst(); |
|
332 CPathTypePair* pair = NULL; |
|
333 while ( ( pair = pairIt++ ) != NULL ) |
|
334 { |
|
335 pair->iLink.Deque(); |
|
336 delete pair; |
|
337 } |
|
338 iCacheMemoryUsage = 0; |
|
339 } |
|
340 |
|
341 // ----------------------------------------------------------------------------- |
|
342 // CGflmFileRecognizer::CleanupCache( ) |
|
343 // |
|
344 // ----------------------------------------------------------------------------- |
|
345 // |
|
346 void CGflmFileRecognizer::CleanupCache( ) |
|
347 { |
|
348 if( iCacheMemoryUsage > iCacheMaxMemoryUsage ) |
|
349 { |
|
350 TInt dropThreshold = ( TInt ) ( ( ( ( TUint ) iCacheMaxMemoryUsage ) * |
|
351 KPerCentToDrop ) / KHundredPerCent ); |
|
352 TInt droppedSize( 0 ); |
|
353 |
|
354 TDblQueIter< CPathTypePair > pairIt( iCache ); |
|
355 pairIt.SetToLast(); |
|
356 CPathTypePair* pair = NULL; |
|
357 while ( ( pair = pairIt-- ) != NULL ) |
|
358 { |
|
359 droppedSize += pair->Size(); |
|
360 pair->iLink.Deque(); |
|
361 delete pair; |
|
362 if ( droppedSize >= dropThreshold ) |
|
363 { |
|
364 break; |
|
365 } |
|
366 } |
|
367 iCacheMemoryUsage -= droppedSize; |
|
368 } |
|
369 } |
|
370 |
|
371 // ----------------------------------------------------------------------------- |
|
372 // CGflmFileRecognizer::CPathTypePair::NewLC() |
|
373 // |
|
374 // ----------------------------------------------------------------------------- |
|
375 // |
|
376 CGflmFileRecognizer::CPathTypePair* |
|
377 CGflmFileRecognizer::CPathTypePair::NewLC( const TDesC& aFilename ) |
|
378 { |
|
379 CPathTypePair* self = new ( ELeave ) CPathTypePair(); |
|
380 CleanupStack::PushL( self ); |
|
381 self->ConstructL( aFilename ); |
|
382 return self; |
|
383 } |
|
384 |
|
385 // ----------------------------------------------------------------------------- |
|
386 // CGflmFileRecognizer::CPathTypePair::ConstructL() |
|
387 // |
|
388 // ----------------------------------------------------------------------------- |
|
389 // |
|
390 void CGflmFileRecognizer::CPathTypePair::ConstructL( const TDesC& aFilename ) |
|
391 { |
|
392 iFilename = aFilename.AllocL(); |
|
393 } |
|
394 |
|
395 // ----------------------------------------------------------------------------- |
|
396 // CGflmFileRecognizer::CPathTypePair::CPathTypePair() |
|
397 // |
|
398 // ----------------------------------------------------------------------------- |
|
399 // |
|
400 CGflmFileRecognizer::CPathTypePair::CPathTypePair() : |
|
401 iTypeIndex( KErrNotFound ) |
|
402 { |
|
403 } |
|
404 |
|
405 // ----------------------------------------------------------------------------- |
|
406 // CGflmFileRecognizer::CPathTypePair::~CPathTypePair() |
|
407 // |
|
408 // ----------------------------------------------------------------------------- |
|
409 // |
|
410 CGflmFileRecognizer::CPathTypePair::~CPathTypePair() |
|
411 { |
|
412 delete iFilename; |
|
413 } |
|
414 |
|
415 // ----------------------------------------------------------------------------- |
|
416 // CGflmFileRecognizer::CPathTypePair::Size() |
|
417 // |
|
418 // ----------------------------------------------------------------------------- |
|
419 // |
|
420 TInt CGflmFileRecognizer::CPathTypePair::Size() const |
|
421 { |
|
422 return ( sizeof( TInt ) + iFilename->Size() + sizeof( TDblQueLink ) ); |
|
423 } |
|
424 |
|
425 // ----------------------------------------------------------------------------- |
|
426 // CGflmFileRecognizer::CExtMimePair::~CExtMimePair() |
|
427 // |
|
428 // ----------------------------------------------------------------------------- |
|
429 // |
|
430 CGflmFileRecognizer::CExtMimePair::~CExtMimePair() |
|
431 { |
|
432 delete iExt; |
|
433 delete iMime; |
|
434 } |
|
435 |
|
436 // End of File |
|