|
1 // Copyright (c) 1997-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 // |
|
15 |
|
16 |
|
17 #include <ecom/ecom.h> |
|
18 #include <ecom/ecomerrorcodes.h> |
|
19 #include <ecom/implementationinformation.h> |
|
20 |
|
21 #include "ImageConversionResolver.h" |
|
22 #include "ImageConvResolvrUtils.h" |
|
23 |
|
24 _LIT(KIclResolverPanicCategory, "ImageConversionResolver"); |
|
25 |
|
26 //Current version of plugin framework. |
|
27 //Plugin will be ignored if the version from opaque data doesn't |
|
28 //match the current framework version. |
|
29 //const TInt KPluginFrameworkVersion = 0; |
|
30 |
|
31 GLDEF_C void Panic(TInt aReason) |
|
32 { |
|
33 User::Panic(KIclResolverPanicCategory, aReason); |
|
34 } |
|
35 |
|
36 /** |
|
37 * Constructs and initialises a new instance of CImageConversionResolver. |
|
38 * |
|
39 * @param "MPublicRegistry& aRegistry" |
|
40 * A reference to the registry on which it will operate |
|
41 * @return "CImageConversionResolver*" |
|
42 * A pointer to the newly constructed resolver |
|
43 */ |
|
44 CImageConversionResolver* CImageConversionResolver::NewL(MPublicRegistry& aRegistry) |
|
45 { |
|
46 return new(ELeave) CImageConversionResolver(aRegistry); |
|
47 } |
|
48 |
|
49 /** |
|
50 * |
|
51 * Default destructor |
|
52 * |
|
53 */ |
|
54 CImageConversionResolver::~CImageConversionResolver() |
|
55 { |
|
56 } |
|
57 |
|
58 /** |
|
59 * |
|
60 * Default constructor |
|
61 * |
|
62 * @param "MPublicRegistry& aRegistry" |
|
63 * A reference to the registry on which it will operate |
|
64 */ |
|
65 CImageConversionResolver::CImageConversionResolver(MPublicRegistry& aRegistry) |
|
66 : CResolver(aRegistry) |
|
67 { |
|
68 } |
|
69 |
|
70 /** |
|
71 * |
|
72 * Request that the resolver identify the most appropriate interface |
|
73 * implementation. |
|
74 * |
|
75 * @param "TUid aInterfaceUid" |
|
76 * The Uid of the interface you want to match against |
|
77 * @param "const TEComResolverParams& aAdditionalParameters" |
|
78 * A passed in reference to the parameters on which to match |
|
79 * @return "TUid" |
|
80 * The implementation Uid of the single best match found |
|
81 */ |
|
82 TUid CImageConversionResolver::IdentifyImplementationL(TUid aInterfaceUid, const TEComResolverParams& aAdditionalParameters) const |
|
83 { |
|
84 RImplInfoArray& implementationsInfo = iRegistry.ListImplementationsL(aInterfaceUid); |
|
85 TUid found = KNullUid; |
|
86 if (implementationsInfo.Count()) |
|
87 found = ResolveL(implementationsInfo, aAdditionalParameters); |
|
88 |
|
89 return found; |
|
90 } |
|
91 |
|
92 /** |
|
93 * |
|
94 * Called by IdentifyImplementationL to select an implementation from the |
|
95 * supplied implementation uid, ignoring any implementations that have their |
|
96 * Disabled flag set or are not of the current framework version. |
|
97 * The image type and sub type is verified to ensure the implementation is of |
|
98 * expected type. |
|
99 * |
|
100 * @param "const RImplInfoArray& aImplementationsInfo" |
|
101 * The list of plugins you want to match against |
|
102 * @param "const TEComResolverParams& aAdditionalParameters" |
|
103 * A passed in reference to the parameters on which to match |
|
104 * @return "TUid" |
|
105 * The implementation Uid of plugin |
|
106 */ |
|
107 TUid CImageConversionResolver::ResolveL(const RImplInfoArray& aImplementationsInfo, const TEComResolverParams& aAdditionalParameters) const |
|
108 { |
|
109 // Retrieve the match data from the descriptor |
|
110 CCustomMatchData* customMatch = CCustomMatchData::NewLC(aAdditionalParameters.DataType()); |
|
111 |
|
112 TResolverMatchType matchType = customMatch->MatchType(); |
|
113 TUint requiredExtensions = customMatch->ExtensionOptions(); |
|
114 TUint requiredOptions = customMatch->Options(); |
|
115 TUid baseType = customMatch->BaseType(); |
|
116 TUid subType = customMatch->SubType(); |
|
117 TUid implementationUid = customMatch->ImplementationType(); |
|
118 |
|
119 RUidDataArray requiredOptionsUids; |
|
120 if (requiredOptions) |
|
121 { |
|
122 CleanupClosePushL(requiredOptionsUids); |
|
123 customMatch->GetOptionsUidsL(requiredOptionsUids); |
|
124 } |
|
125 |
|
126 // Select plugin on implementation uid |
|
127 if((matchType != EMatchUids) || (implementationUid == KNullUid)) |
|
128 User::Leave(KErrArgument); |
|
129 |
|
130 TUid bestMatch = KNullUid; |
|
131 TInt version = 0; |
|
132 TBool requiredOptionsFound = EFalse; |
|
133 |
|
134 // Loop through the implementations searching for the implementation uid |
|
135 const TInt count = aImplementationsInfo.Count(); |
|
136 for(TInt index = 0; index < count; index++) |
|
137 { |
|
138 const CImplementationInformation& impData = *aImplementationsInfo[index]; |
|
139 COpaqueDataParse* parse = NULL; |
|
140 TRAPD(error, parse = COpaqueDataParse::NewL(impData.OpaqueData())); |
|
141 if (error!=KErrNone) |
|
142 { |
|
143 if (error==KErrNotSupported) |
|
144 { |
|
145 // means that the resource entry was not valid |
|
146 continue; |
|
147 } |
|
148 else |
|
149 User::Leave(error); |
|
150 } |
|
151 |
|
152 CleanupStack::PushL(parse); |
|
153 |
|
154 // we can assume the version is valid as it is checked in |
|
155 // COpaqueDataParse::ConstructL() which leaves if not valid |
|
156 ASSERT(parse->Version() <= KIclPluginFrameworkVersionMax); |
|
157 |
|
158 if (!impData.Disabled()) |
|
159 { |
|
160 if (implementationUid == impData.ImplementationUid()) |
|
161 { // Got a match |
|
162 // Moved here to optimize iteration through implementations |
|
163 // Check if extension options are required. |
|
164 if (requiredExtensions) |
|
165 { |
|
166 if (!parse->SupportsExtensionsL(requiredExtensions)) |
|
167 { |
|
168 CleanupStack::PopAndDestroy(parse); |
|
169 continue; |
|
170 } |
|
171 } |
|
172 |
|
173 if ((baseType == parse->ImageTypeUid()) && (subType == parse->ImageSubTypeUid())) |
|
174 {// ImageType and SubType match |
|
175 if (requiredOptions) |
|
176 { |
|
177 parse->EnsureBinaryPropertiesReadL(); |
|
178 if(parse->CheckOptionsUids(requiredOptionsUids)) |
|
179 { |
|
180 if (!requiredOptionsFound) |
|
181 { |
|
182 bestMatch = impData.ImplementationUid(); |
|
183 version = impData.Version(); |
|
184 requiredOptionsFound = ETrue; |
|
185 CleanupStack::PopAndDestroy(parse); |
|
186 continue; |
|
187 } |
|
188 } |
|
189 else |
|
190 { |
|
191 if (requiredOptionsFound) |
|
192 { |
|
193 CleanupStack::PopAndDestroy(parse); |
|
194 continue; |
|
195 } |
|
196 } |
|
197 } |
|
198 |
|
199 if (version < impData.Version()) |
|
200 { // Higher version match |
|
201 bestMatch = impData.ImplementationUid(); |
|
202 version = impData.Version(); |
|
203 } |
|
204 } |
|
205 } |
|
206 } |
|
207 CleanupStack::PopAndDestroy(parse); |
|
208 } |
|
209 |
|
210 if (requiredOptions) |
|
211 { |
|
212 CleanupStack::PopAndDestroy();//requiredOptionsUids |
|
213 } |
|
214 CleanupStack::PopAndDestroy(customMatch); |
|
215 |
|
216 return bestMatch; |
|
217 } |
|
218 |
|
219 /* |
|
220 * |
|
221 * List all the implementations which satisfy the specified interface, ignoring |
|
222 * any implementations that have their Disabled flag set or are not of the |
|
223 * current framework version. |
|
224 * |
|
225 * The list is sorted: |
|
226 * 1) For EMatchString in desending order of number of bytes matched and version number. |
|
227 * 2) For EMatchMIMEType in asending order of the MIME position that matched and |
|
228 * desending version number. |
|
229 * 3) All others - desending version numbers. |
|
230 * |
|
231 * @param "TUid aInterfaceUid" |
|
232 * The Uid of the interface you want to match against |
|
233 * @param "const TEComResolverParams& aAdditionalParameters" |
|
234 * A passed in reference to the parameters on which to match |
|
235 * @return "RImplInfoArray*" |
|
236 * The list of matches found |
|
237 */ |
|
238 RImplInfoArray* CImageConversionResolver::ListAllL(TUid aInterfaceUid, const TEComResolverParams& aAdditionalParameters) const |
|
239 { |
|
240 // Retrieve the match data from the descriptor |
|
241 CCustomMatchData* customMatch = CCustomMatchData::NewLC(aAdditionalParameters.DataType()); |
|
242 |
|
243 TResolverMatchType matchType = customMatch->MatchType(); |
|
244 TUint requiredExtensions = customMatch->ExtensionOptions(); |
|
245 TUint requiredOptions = customMatch->Options(); |
|
246 TUid baseType = customMatch->BaseType(); |
|
247 TUid subType = customMatch->SubType(); |
|
248 TUid implementationUid = customMatch->ImplementationType(); |
|
249 HBufC8* matchString = customMatch->MatchString().AllocLC(); |
|
250 HBufC* fileSuffix = customMatch->FileSuffix().AllocLC(); |
|
251 |
|
252 RUidDataArray requiredUids; |
|
253 CleanupClosePushL(requiredUids); |
|
254 customMatch->GetMatchReqUidsL(requiredUids); |
|
255 |
|
256 RUidDataArray requiredOptionsUids; |
|
257 CleanupClosePushL(requiredOptionsUids); |
|
258 customMatch->GetOptionsUidsL(requiredOptionsUids); |
|
259 |
|
260 // Use the member var to create the array so that we get proper cleanup behaviour |
|
261 RImplInfoArray& fullList = iRegistry.ListImplementationsL(aInterfaceUid); |
|
262 |
|
263 RArray<TSortImplInfo> sortList; |
|
264 CleanupClosePushL(sortList); |
|
265 |
|
266 TInt matchLevel = 0; |
|
267 TInt optionsMatchLevel = 0; |
|
268 |
|
269 // Loop through the implementations matching on appropriate info |
|
270 const TInt count = fullList.Count(); |
|
271 TInt index; |
|
272 |
|
273 for(index = 0; index < count; index++) |
|
274 { |
|
275 const CImplementationInformation& impData = *(fullList[index]); |
|
276 COpaqueDataParse* parse = NULL; |
|
277 TRAPD(error, parse = COpaqueDataParse::NewL(impData.OpaqueData())); |
|
278 if (error!=KErrNone) |
|
279 { |
|
280 if (error==KErrNotSupported) |
|
281 { |
|
282 // means that the resource entry was not valid |
|
283 continue; |
|
284 } |
|
285 else |
|
286 User::Leave(error); |
|
287 } |
|
288 |
|
289 CleanupStack::PushL(parse); |
|
290 |
|
291 // we can assume the version is valid as it is checked in |
|
292 // COpaqueDataParse::ConstructL() which leaves if not valid |
|
293 ASSERT(parse->Version() <= KIclPluginFrameworkVersionMax); |
|
294 |
|
295 if (!impData.Disabled()) |
|
296 { |
|
297 |
|
298 TBool matchFound = EFalse; |
|
299 switch(matchType) |
|
300 { |
|
301 case EListImageTypes: |
|
302 { |
|
303 if (baseType == KNullUid) |
|
304 { // Looking for base image types |
|
305 if (parse->ImageSubTypeUid() == KNullUid) |
|
306 matchFound = ETrue; |
|
307 } |
|
308 else |
|
309 { // Looking for sub-types of a particular base image type |
|
310 if ((baseType == parse->ImageTypeUid()) && (parse->ImageSubTypeUid() != KNullUid)) |
|
311 matchFound = ETrue; |
|
312 } |
|
313 break; |
|
314 } |
|
315 |
|
316 case EListFileTypes: |
|
317 { // Looking for entries with file extensions and/or MIME types |
|
318 if(!parse->OnlyUidsAvail() && !parse->IsSubCodec()) |
|
319 matchFound = ETrue; |
|
320 break; |
|
321 } |
|
322 |
|
323 case EMatchMIMEType: |
|
324 { |
|
325 if(!parse->OnlyUidsAvail() && !parse->IsSubCodec()) |
|
326 { //If codec has no MIME types ignore it |
|
327 parse->EnsureMIMETypesReadL(); |
|
328 const TInt numMimeTypes = parse->MIMETypesCount(); |
|
329 for (TInt index2 = 0; index2 < numMimeTypes; index2++) |
|
330 { |
|
331 const TDesC8& mimeType = parse->MIMEType(index2); |
|
332 if (COpaqueDataParse::CompareMIMETypes(*matchString, mimeType)) |
|
333 { |
|
334 matchFound = ETrue; |
|
335 matchLevel = index2; |
|
336 break; |
|
337 } |
|
338 } |
|
339 } |
|
340 |
|
341 break; |
|
342 } |
|
343 |
|
344 case EMatchString: |
|
345 { // Match the match strings |
|
346 if (CImageConversionResolverUtils::Match(*matchString, impData.DataType(), matchLevel)) |
|
347 matchFound = ETrue; |
|
348 break; |
|
349 } |
|
350 |
|
351 case EMatchUids: |
|
352 { // match on UIDs |
|
353 if (implementationUid != KNullUid) |
|
354 {// We're matching on codec implementation uid |
|
355 if (implementationUid == impData.ImplementationUid()) |
|
356 { |
|
357 matchFound = ETrue; |
|
358 } |
|
359 else |
|
360 { |
|
361 matchFound = (implementationUid == parse->PluginClassUid()); |
|
362 } |
|
363 } |
|
364 else |
|
365 { // We're matching on image type (and sub-type) |
|
366 if (parse->CompareUids(baseType, subType)) |
|
367 matchFound = ETrue; |
|
368 } |
|
369 break; |
|
370 } |
|
371 |
|
372 case EMatchFileSuffix: |
|
373 { |
|
374 if(!parse->OnlyUidsAvail() && parse->IsOpenAgainstSuffix()) |
|
375 { //If codec has file extensions and allow matching on them |
|
376 parse->EnsureExtnsReadL(); |
|
377 const TInt numExtns = parse->ExtnsCount(); |
|
378 for (TInt index2 = 0; index2 < numExtns; index2++) |
|
379 { |
|
380 const TDesC8& extn = parse->Extn(index2); |
|
381 if (COpaqueDataParse::CompareFileSuffixL(*fileSuffix, extn)) |
|
382 { |
|
383 matchFound = ETrue; |
|
384 matchLevel = index2; |
|
385 break; |
|
386 } |
|
387 } |
|
388 } |
|
389 |
|
390 break; |
|
391 } |
|
392 |
|
393 case EMatchReqUids: |
|
394 { |
|
395 if(!parse->OnlyUidsAvail()) |
|
396 { |
|
397 parse->EnsureBinaryPropertiesReadL(); |
|
398 if(parse->CheckRequiredUids(requiredUids)) |
|
399 { |
|
400 matchFound = ETrue; |
|
401 if(parse->IsDefaultCodec()) |
|
402 { |
|
403 matchLevel = 1; |
|
404 } |
|
405 else |
|
406 { |
|
407 matchLevel = 0; |
|
408 } |
|
409 } |
|
410 } |
|
411 break; |
|
412 } |
|
413 |
|
414 default: |
|
415 {//unknown match type |
|
416 Panic(KErrArgument); |
|
417 } |
|
418 } |
|
419 |
|
420 if (matchFound) |
|
421 { |
|
422 // Moved here to reduce timing required to list all codecs plugins. |
|
423 // Check if certain extensions are required. |
|
424 if (requiredExtensions) |
|
425 { |
|
426 if (!parse->SupportsExtensionsL(requiredExtensions)) |
|
427 { |
|
428 CleanupStack::PopAndDestroy(parse); |
|
429 continue; |
|
430 } |
|
431 } |
|
432 |
|
433 // Check if certain options are required |
|
434 if(requiredOptions) |
|
435 { |
|
436 optionsMatchLevel = 0; |
|
437 parse->EnsureBinaryPropertiesReadL(); |
|
438 if(parse->CheckOptionsUids(requiredOptionsUids)) |
|
439 { |
|
440 optionsMatchLevel = 1;// one for having required options |
|
441 if(parse->IsDefaultCodec()) |
|
442 { |
|
443 optionsMatchLevel = 2; // two for being default codec and having required options |
|
444 } |
|
445 } |
|
446 } |
|
447 |
|
448 TSortImplInfo sortInfo(fullList[index],matchLevel,optionsMatchLevel); |
|
449 User::LeaveIfError(sortList.Append(sortInfo)); |
|
450 } |
|
451 } |
|
452 CleanupStack::PopAndDestroy(parse); |
|
453 } |
|
454 |
|
455 TLinearOrder<TSortImplInfo>* sortFunction = NULL; |
|
456 if(matchType==EMatchMIMEType) |
|
457 sortFunction = new (ELeave) TLinearOrder<TSortImplInfo>(SortAsending); |
|
458 else |
|
459 sortFunction = new (ELeave) TLinearOrder<TSortImplInfo>(SortDesending); |
|
460 |
|
461 sortList.Sort(*sortFunction); |
|
462 delete sortFunction; |
|
463 |
|
464 RImplInfoArray* retList = new (ELeave) RImplInfoArray; |
|
465 CleanupStack::PushL(retList); |
|
466 // coverity[double_push] |
|
467 CleanupClosePushL(*retList); // note the double PushL - will Close and delete on PopAndDestroy(2) |
|
468 |
|
469 TInt noEntries = sortList.Count(); |
|
470 for(index = 0; index < noEntries; index++) |
|
471 User::LeaveIfError(retList->Append(sortList[index].iImplInfo)); |
|
472 |
|
473 if ((matchType == EMatchString) && (noEntries > 1)) |
|
474 { |
|
475 // check that there is no ambiguity due to a short match string |
|
476 TBool matchStringIsTooShort = EFalse; |
|
477 for (TInt i = 0; i < noEntries; i++) |
|
478 { |
|
479 const CImplementationInformation& implementationInfo = *((*retList)[i]); |
|
480 TInt implementationStringLength = implementationInfo.DataType().Length(); |
|
481 while ((implementationStringLength > 0) && (implementationInfo.DataType()[implementationStringLength - 1] == '?')) |
|
482 { // Clip extraneous '?' wildcards off the end of the plugin match string |
|
483 implementationStringLength--; |
|
484 } |
|
485 if (matchString->Length() < implementationStringLength) |
|
486 { |
|
487 matchStringIsTooShort = ETrue; |
|
488 break; |
|
489 } |
|
490 } |
|
491 |
|
492 if (matchStringIsTooShort) |
|
493 { |
|
494 User::Leave(KErrUnderflow); |
|
495 } |
|
496 } |
|
497 |
|
498 |
|
499 |
|
500 CleanupStack::Pop(2, retList); // retList x2 |
|
501 |
|
502 CleanupStack::PopAndDestroy(6, customMatch); // sortList, requiredOptionsUids, requiredUids, fileSuffix, matchString, customMatch |
|
503 |
|
504 return retList; |
|
505 } |
|
506 |
|
507 /** |
|
508 * Function to sort an array of TSortImplInfo in asending order of the match level, options match level and |
|
509 * then in desending order of version numbers. |
|
510 * |
|
511 * @param "const TSortImplInfo& aImpInfo1" |
|
512 * First element. |
|
513 * @param "const TSortImplInfo& aImpInfo2" |
|
514 * Second element. |
|
515 * @return "TInt" |
|
516 * Indication of element swapping order. |
|
517 */ |
|
518 TInt CImageConversionResolver::SortAsending(const TSortImplInfo& aImpInfo1, const TSortImplInfo& aImpInfo2) |
|
519 { |
|
520 TInt result = aImpInfo1.iMatchLevel - aImpInfo2.iMatchLevel; |
|
521 |
|
522 if(result == 0) |
|
523 result = aImpInfo1.iOptionsMatchLevel - aImpInfo2.iOptionsMatchLevel; |
|
524 |
|
525 if(result == 0) |
|
526 result = aImpInfo2.iImplInfo->Version() - aImpInfo1.iImplInfo->Version(); |
|
527 |
|
528 return result; |
|
529 } |
|
530 |
|
531 /** |
|
532 * Function to sort an array of TSortImplInfo in desending order of the match level, options match level |
|
533 * and version numbers. |
|
534 * |
|
535 * @param "const TSortImplInfo& aImpInfo1" |
|
536 * First element. |
|
537 * @param "const TSortImplInfo& aImpInfo2" |
|
538 * Second element. |
|
539 * @return "TInt" |
|
540 * Indication of element swapping order. |
|
541 */ |
|
542 TInt CImageConversionResolver::SortDesending(const TSortImplInfo& aImpInfo1, const TSortImplInfo& aImpInfo2) |
|
543 { |
|
544 TInt result = aImpInfo2.iMatchLevel - aImpInfo1.iMatchLevel; |
|
545 |
|
546 if(result == 0) |
|
547 result = aImpInfo2.iOptionsMatchLevel - aImpInfo1.iOptionsMatchLevel; |
|
548 |
|
549 if(result == 0) |
|
550 result = aImpInfo2.iImplInfo->Version() - aImpInfo1.iImplInfo->Version(); |
|
551 |
|
552 return result; |
|
553 } |
|
554 |
|
555 /** |
|
556 * Construtor for the TSortImplInfo class |
|
557 * |
|
558 * @param "CImplementationInformation *const aImplInfo" |
|
559 * A implementation information element to be sorted. |
|
560 * @param "TInt aMatchLevel" |
|
561 * The matching level of the entry |
|
562 */ |
|
563 TSortImplInfo::TSortImplInfo(CImplementationInformation *const aImplInfo, TInt aMatchLevel): |
|
564 iImplInfo(aImplInfo), |
|
565 iMatchLevel(aMatchLevel), |
|
566 iOptionsMatchLevel(0) |
|
567 { |
|
568 } |
|
569 |
|
570 /** |
|
571 * Construtor for the TSortImplInfo class |
|
572 * |
|
573 * @param "CImplementationInformation *const aImplInfo" |
|
574 * A implementation information element to be sorted. |
|
575 * @param "TInt aMatchLevel" |
|
576 * The matching level of the entry |
|
577 * @param "TInt aOptionsMatchLevel" |
|
578 * The options matching level of the entry |
|
579 */ |
|
580 TSortImplInfo::TSortImplInfo(CImplementationInformation *const aImplInfo, TInt aMatchLevel, TInt aOptionsMatchLevel): |
|
581 iImplInfo(aImplInfo), |
|
582 iMatchLevel(aMatchLevel), |
|
583 iOptionsMatchLevel(aOptionsMatchLevel) |
|
584 { |
|
585 } |
|
586 |