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 the License "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 #include "APGAIR.H" |
|
17 #include <apgaplst.h> |
|
18 #include <bautils.h> |
|
19 #include "APGICNFL.H" |
|
20 #include "APFDEF.H" |
|
21 #include "apprivate.h" |
|
22 #include <barsc2.h> |
|
23 #include <barsread2.h> |
|
24 #include <e32uid.h> |
|
25 #include "APGSTD.H" |
|
26 |
|
27 #include "apsecutils.h" |
|
28 |
|
29 const TUint KResourceOffsetMask = 0xFFFFF000; |
|
30 |
|
31 |
|
32 _LIT(KAppBinaryPathAndExtension,"\\sys\\bin\\.exe"); |
|
33 _LIT(KV1AppPathAndExtension, "\\system\\apps\\.app"); |
|
34 const TInt KAppRegistrationInfoResourceId = 1; |
|
35 |
|
36 #ifndef SYMBIAN_APPARC_APPINFO_CACHE |
|
37 CApaAppInfoReaderV2* CApaAppInfoReaderV2::NewL(RFs& aFs, const TDesC& aRegistrationFileName, const TUid aAppUid,const TDesC& aDefaultAppIconFileName) |
|
38 { |
|
39 CApaAppInfoReaderV2* self = new(ELeave) CApaAppInfoReaderV2(aFs, aRegistrationFileName, aAppUid,aDefaultAppIconFileName); |
|
40 CleanupStack::PushL(self); |
|
41 self->ConstructL(); |
|
42 CleanupStack::Pop(self); |
|
43 return self; |
|
44 } |
|
45 |
|
46 CApaAppInfoReaderV2::CApaAppInfoReaderV2(RFs& aFs, const TDesC& aRegistrationFileName, const TUid aAppUid,const TDesC& aDefaultAppIconFileName) |
|
47 : CApaAppInfoReader(aFs, aAppUid), |
|
48 iRegistrationFileName(aRegistrationFileName),iDefaultAppIconFileName(aDefaultAppIconFileName) |
|
49 { |
|
50 } |
|
51 #else |
|
52 CApaAppInfoReaderV2* CApaAppInfoReaderV2::NewL(RFs& aFs, const TDesC& aRegistrationFileName, const TUid aAppUid) |
|
53 { |
|
54 CApaAppInfoReaderV2* self = new(ELeave) CApaAppInfoReaderV2(aFs, aRegistrationFileName, aAppUid); |
|
55 CleanupStack::PushL(self); |
|
56 self->ConstructL(); |
|
57 CleanupStack::Pop(self); |
|
58 return self; |
|
59 } |
|
60 |
|
61 CApaAppInfoReaderV2::CApaAppInfoReaderV2(RFs& aFs, const TDesC& aRegistrationFileName, const TUid aAppUid) |
|
62 : CApaAppInfoReader(aFs, aAppUid), |
|
63 iRegistrationFileName(aRegistrationFileName) |
|
64 { |
|
65 } |
|
66 #endif // SYMBIAN_APPARC_APPINFO_CACHE |
|
67 |
|
68 void CApaAppInfoReaderV2::ConstructL() |
|
69 { |
|
70 iIconLoader = CApaIconLoader::NewL(iFs); |
|
71 } |
|
72 |
|
73 CApaAppInfoReaderV2::~CApaAppInfoReaderV2() |
|
74 { |
|
75 delete iIconLoader; |
|
76 } |
|
77 |
|
78 #ifdef SYMBIAN_APPARC_APPINFO_CACHE |
|
79 // The behaviour of the following function is a little non-standard, as it |
|
80 // transfers ownership of the pointer owned by a CApaAppInfoReaderV2 object |
|
81 // to the caller. This means that this function is only designed to be called once. |
|
82 // Doing things this way provides a small performance optimisation by enabling the caller |
|
83 // to delete it's stored pointer, and replace it with one returned by this function, |
|
84 // instead of having to copy the object (copying could be expensive for the methods |
|
85 // of this class that need to return arrays). |
|
86 CApaIconLoader* CApaAppInfoReaderV2::IconLoader() |
|
87 { |
|
88 CApaIconLoader* iconLoader = iIconLoader; |
|
89 iIconLoader = NULL; // ownership transferred to caller |
|
90 return iconLoader; |
|
91 } |
|
92 #endif // SYMBIAN_APPARC_APPINFO_CACHE |
|
93 |
|
94 // this method reads the minimum information required to register an app |
|
95 // if this fails (Leaves), we say the read has been unsuccessful |
|
96 void CApaAppInfoReaderV2::ReadMandatoryInfoL(CResourceFile*& aRegistrationFile, RResourceReader& aResourceReader) |
|
97 { |
|
98 TEntry entry; |
|
99 User::LeaveIfError(iFs.Entry(iRegistrationFileName, entry)); |
|
100 iTimeStamp = entry.iModified; |
|
101 |
|
102 TUint fileOffset = 0; |
|
103 TInt fileLength = 0; |
|
104 TUid middleUid(KUidApp); |
|
105 |
|
106 // in the case of a non-native application, the resource file |
|
107 // has been padded with the application type uid |
|
108 |
|
109 if (TParsePtrC(iRegistrationFileName).Path().CompareF(KLitPathForNonNativeResourceAndIconFiles)==0) |
|
110 { |
|
111 fileOffset=sizeof(TCheckedUid); |
|
112 fileLength=entry.iSize-fileOffset; |
|
113 middleUid=entry[1]; |
|
114 if (middleUid.iUid==KNullUid.iUid) |
|
115 { |
|
116 User::Leave(KErrCorrupt); |
|
117 } |
|
118 } |
|
119 |
|
120 aRegistrationFile = CResourceFile::NewL(iFs, iRegistrationFileName, fileOffset, fileLength); |
|
121 aResourceReader.OpenL(aRegistrationFile, KAppRegistrationInfoResourceId); |
|
122 |
|
123 aResourceReader.ReadUint32L(); // skip over LONG reserved_long |
|
124 aResourceReader.ReadUint32L(); // skip over LLINK reserved_llink |
|
125 |
|
126 // read LTEXT app_file |
|
127 const TPtrC appFile(aResourceReader.ReadTPtrCL()); |
|
128 TParse parse; // this object gets used for 2 purposes: first to check that a TParsePtrC can be created over "appFile" without it panicking, and second to construct iAppBinaryFullName |
|
129 User::LeaveIfError(parse.SetNoWild(appFile, NULL, NULL)); // do this before creating a TParsePtrC, since TParsePtrC's constructor panics if it fails (which would provide an easy way for malware to kill the Apparc server) |
|
130 const TParsePtrC appFileParser(appFile); |
|
131 |
|
132 // read LONG attributes |
|
133 iCapability.iAttributes = aResourceReader.ReadUint32L(); |
|
134 |
|
135 if (!appFileParser.NamePresent()) |
|
136 { |
|
137 User::Leave(KErrCorrupt); |
|
138 } |
|
139 const TPtrC appNameWithoutExtension(appFileParser.Name()); |
|
140 const TPtrC registrationFileDrive(TParsePtrC(iRegistrationFileName).Drive()); |
|
141 TUid firstUid(TUid::Null()); |
|
142 if (iCapability.iAttributes & TApaAppCapability::ENonNative) |
|
143 { |
|
144 if (!appFileParser.PathPresent() || !appFileParser.ExtPresent()) |
|
145 { |
|
146 User::Leave(KErrCorrupt); |
|
147 } |
|
148 const TPtrC appFilePath(appFileParser.Path()); |
|
149 const TPtrC appFileNameAndExt(appFileParser.NameAndExt()); |
|
150 TPtrC appFileDrive(registrationFileDrive); |
|
151 if (appFileParser.DrivePresent()) |
|
152 { |
|
153 appFileDrive.Set(appFileParser.Drive()); |
|
154 } |
|
155 User::LeaveIfError(parse.SetNoWild(appFileDrive, &appFilePath, &appFileNameAndExt)); |
|
156 // keep firstUid as TUid::Null() |
|
157 } |
|
158 else if (iCapability.iAttributes & TApaAppCapability::EBuiltAsDll) |
|
159 { |
|
160 // legacy dll-style app |
|
161 User::LeaveIfError(parse.SetNoWild(registrationFileDrive, &KV1AppPathAndExtension, &appNameWithoutExtension)); |
|
162 User::LeaveIfError(parse.AddDir(appNameWithoutExtension)); |
|
163 firstUid = KDynamicLibraryUid; |
|
164 } |
|
165 else |
|
166 { |
|
167 // exe-style app |
|
168 User::LeaveIfError(parse.SetNoWild(registrationFileDrive, &KAppBinaryPathAndExtension, &appNameWithoutExtension)); |
|
169 firstUid = KExecutableImageUid; |
|
170 } |
|
171 iAppBinaryFullName = parse.FullName().AllocL(); |
|
172 |
|
173 // set the TUidType for the app binary |
|
174 // cannot read the TEntry info from the app binary because it's in \sys\bin |
|
175 iAppBinaryUidType = TUidType(firstUid, middleUid, iAppUid); |
|
176 } |
|
177 |
|
178 // reads as much info as it can |
|
179 // at least captions and icons must be setup on return from this method (using defaults if necessary) |
|
180 TBool CApaAppInfoReaderV2::Read() |
|
181 { |
|
182 CResourceFile* registrationFile = NULL; |
|
183 RResourceReader resourceReader; |
|
184 TRAPD(ret, ReadMandatoryInfoL(registrationFile, resourceReader)); |
|
185 if (ret != KErrNone) |
|
186 { |
|
187 resourceReader.Close(); |
|
188 delete registrationFile; |
|
189 return EFalse; // might have read something, but failed to setup enough info to make it worthwhile trying to read any more |
|
190 } |
|
191 |
|
192 CResourceFile* localisableFile = NULL; |
|
193 TUint localisableResourceId = 1; // only initialising this here to keep the compiler happy, as it's concerned that the variable might be used without having been initialised. The variable should be initialised later, before it's used |
|
194 TRAP(ret, ReadNonLocalisableInfoL(resourceReader, localisableFile, localisableResourceId)); |
|
195 |
|
196 if (ret == KErrNone) |
|
197 { |
|
198 TRAP(ret, ReadNonLocalisableOptionalInfoL(resourceReader, registrationFile, localisableFile)); |
|
199 } |
|
200 |
|
201 TBool useDefaultIcons=ETrue; |
|
202 |
|
203 if (ret == KErrNone && localisableFile) |
|
204 { |
|
205 TRAP(ret, ReadLocalisableInfoL(localisableFile, localisableResourceId, useDefaultIcons)); |
|
206 } |
|
207 delete localisableFile; |
|
208 resourceReader.Close(); |
|
209 delete registrationFile; |
|
210 |
|
211 // if anything went wrong, we tell the caller that the read was unsuccessful. Some |
|
212 // of the members of this class may not contain complete data, but this doesn't matter |
|
213 // because the caller shouldn't try to access the data if the read was unsuccessful |
|
214 TBool readSuccessful = (ret == KErrNone); |
|
215 |
|
216 if (useDefaultIcons) |
|
217 { |
|
218 delete iIcons; |
|
219 iIcons = NULL; |
|
220 TRAP_IGNORE(iIcons = CApaAppIconArray::NewDefaultIconsL()); |
|
221 } |
|
222 |
|
223 return readSuccessful; |
|
224 } |
|
225 |
|
226 HBufC* CApaAppInfoReaderV2::FullIconFileNameL(const TDesC& aIconFileName) const |
|
227 { |
|
228 HBufC* filename = NULL; |
|
229 if (aIconFileName.Length() == 0) |
|
230 { |
|
231 return NULL; |
|
232 } |
|
233 /* |
|
234 * aIconFileName may contain a valid string in some format (for eg. URI format) other than path to a regular file on disk |
|
235 * and that can be a mbm or non-mbm file. Such a filename will be reported as invalid filename by iFs.IsValidName() method. |
|
236 * aIconFileName will be returned since it is a valid string. |
|
237 */ |
|
238 if(!iFs.IsValidName(aIconFileName)) |
|
239 { |
|
240 filename = aIconFileName.AllocL(); |
|
241 return filename; |
|
242 } |
|
243 |
|
244 TParsePtrC parsePtr(aIconFileName); |
|
245 if (parsePtr.IsWild() |
|
246 || !parsePtr.PathPresent() |
|
247 || !parsePtr.NamePresent()) |
|
248 { |
|
249 return NULL; |
|
250 } |
|
251 // check for fully qualified icon filename |
|
252 if (parsePtr.DrivePresent() && BaflUtils::FileExists(iFs, aIconFileName)) |
|
253 { |
|
254 filename = aIconFileName.AllocL(); |
|
255 } |
|
256 else |
|
257 { |
|
258 // check for icon file on same drive as localisable resource file |
|
259 TParse parse; |
|
260 TPtrC localisableResourceFileDrive = TParsePtrC(*iLocalisableResourceFileName).Drive(); |
|
261 TInt ret = parse.SetNoWild(localisableResourceFileDrive, &aIconFileName, NULL); |
|
262 if (ret == KErrNone && BaflUtils::FileExists(iFs, parse.FullName())) |
|
263 { |
|
264 filename = parse.FullName().AllocL(); |
|
265 } |
|
266 else |
|
267 { |
|
268 TPtrC registrationFileDrive = TParsePtrC(iRegistrationFileName).Drive(); |
|
269 if (TInt(TDriveUnit(registrationFileDrive)) != TInt(TDriveUnit(localisableResourceFileDrive))) |
|
270 { |
|
271 // check for icon file on same drive as registration file |
|
272 ret = parse.SetNoWild(registrationFileDrive, &aIconFileName, NULL); |
|
273 if (ret == KErrNone && BaflUtils::FileExists(iFs, parse.FullName())) |
|
274 { |
|
275 filename = parse.FullName().AllocL(); |
|
276 } |
|
277 } |
|
278 } |
|
279 } |
|
280 return filename; |
|
281 } |
|
282 |
|
283 void CApaAppInfoReaderV2::ReadLocalisableInfoL(const CResourceFile* aResourceFile, TUint aResourceId, TBool& aUseDefaultIcons) |
|
284 { |
|
285 RResourceReader resourceReader; |
|
286 resourceReader.OpenLC(aResourceFile, aResourceId); |
|
287 |
|
288 resourceReader.ReadUint32L(); // skip over LONG reserved_long |
|
289 resourceReader.ReadUint32L(); // skip over LLINK reserved_llink |
|
290 |
|
291 // read LTEXT short_caption |
|
292 iShortCaption = resourceReader.ReadHBufCL(); |
|
293 |
|
294 resourceReader.ReadUint32L(); // skip over LONG reserved_long |
|
295 resourceReader.ReadUint32L(); // skip over LLINK reserved_llink |
|
296 |
|
297 // read LTEXT caption |
|
298 iCaption = resourceReader.ReadHBufCL(); |
|
299 |
|
300 // read WORD number_of_icons |
|
301 const TInt numOfIcons = resourceReader.ReadInt16L(); |
|
302 #ifdef SYMBIAN_APPARC_APPINFO_CACHE |
|
303 iNumOfAppIcons = numOfIcons; |
|
304 #endif // SYMBIAN_APPARC_APPINFO_CACHE |
|
305 |
|
306 // read LTEXT icon_file |
|
307 TPtrC iconFile = resourceReader.ReadTPtrCL(); |
|
308 |
|
309 iIconFileName = FullIconFileNameL(iconFile); |
|
310 if (iIconFileName) |
|
311 { |
|
312 TEntry entry; |
|
313 TInt ret = iFs.Entry(*iIconFileName, entry); |
|
314 if (KErrNone == ret) |
|
315 { |
|
316 iIconFileTimeStamp = entry.iModified; |
|
317 } |
|
318 |
|
319 aUseDefaultIcons = EFalse; |
|
320 if (iFs.IsValidName(*iIconFileName)) |
|
321 { |
|
322 if(FileIsMbmWithGenericExtensionL(*iIconFileName)) |
|
323 { |
|
324 if (numOfIcons > 0) |
|
325 { |
|
326 CApaAppIconArray* iconArray = CApaAppIconArray::NewAppIconsL(numOfIcons, *iIconFileName, *iIconLoader); |
|
327 delete iIcons; |
|
328 iIcons = iconArray; |
|
329 } |
|
330 else |
|
331 { |
|
332 aUseDefaultIcons = ETrue; |
|
333 } |
|
334 } |
|
335 else |
|
336 { |
|
337 iNonMbmIconFile = ETrue; |
|
338 } |
|
339 } |
|
340 //If the filename is not a valid name then the file is treated as a non-mbm file. |
|
341 else |
|
342 { |
|
343 iNonMbmIconFile = ETrue; |
|
344 } |
|
345 } |
|
346 // read LEN WORD STRUCT view_list[] |
|
347 const TInt numOfViews = resourceReader.ReadInt16L(); |
|
348 if (numOfViews > 0) |
|
349 { |
|
350 iViewDataArray = new(ELeave) CArrayPtrFlat<CApaAppViewData>(1); |
|
351 } |
|
352 for(TInt view = 0; view < numOfViews; ++view) |
|
353 { |
|
354 CApaAppViewData* viewData=CApaAppViewData::NewLC(); |
|
355 resourceReader.ReadUint32L(); // skip over LONG reserved_long |
|
356 resourceReader.ReadUint32L(); // skip over LLINK reserved_llink |
|
357 |
|
358 // read LONG uid |
|
359 const TUid viewUid = {resourceReader.ReadInt32L()}; |
|
360 viewData->SetUid(viewUid); |
|
361 // read LONG screen_mode |
|
362 const TInt screenMode = {resourceReader.ReadInt32L()}; |
|
363 viewData->SetScreenMode(screenMode); |
|
364 |
|
365 resourceReader.ReadUint32L(); // skip over LONG reserved_long |
|
366 resourceReader.ReadUint32L(); // skip over LLINK reserved_llink |
|
367 |
|
368 // read LTEXT caption |
|
369 TPtrC viewCaption = resourceReader.ReadTPtrCL(); |
|
370 viewData->SetCaptionL(viewCaption); |
|
371 // read WORD number_of_icons |
|
372 const TInt numOfViewIcons = resourceReader.ReadInt16L(); |
|
373 #ifdef SYMBIAN_APPARC_APPINFO_CACHE |
|
374 viewData->SetNumOfViewIcons(numOfViewIcons); |
|
375 #endif // SYMBIAN_APPARC_APPINFO_CACHE |
|
376 // read LTEXT icon_file |
|
377 TPtrC viewIconFile = resourceReader.ReadTPtrCL(); |
|
378 HBufC* const fullViewIconFileName = FullIconFileNameL(viewIconFile); |
|
379 if (fullViewIconFileName) |
|
380 { |
|
381 CleanupStack::PushL(fullViewIconFileName); |
|
382 viewIconFile.Set(*fullViewIconFileName); |
|
383 viewData->SetIconFileNameL(viewIconFile); |
|
384 |
|
385 if (iFs.IsValidName(viewIconFile)) |
|
386 { |
|
387 if(!FileIsMbmWithGenericExtensionL(viewIconFile)) |
|
388 { |
|
389 viewData->SetNonMbmIconFile(ETrue); |
|
390 } |
|
391 } |
|
392 //If the filename is not a valid name then the file is treated as a non-mbm file. |
|
393 else |
|
394 { |
|
395 viewData->SetNonMbmIconFile(ETrue); |
|
396 } |
|
397 } |
|
398 else |
|
399 { |
|
400 viewIconFile.Set(KNullDesC); |
|
401 if (numOfViewIcons > 0 && iIconFileName) |
|
402 { |
|
403 viewIconFile.Set(*iIconFileName); // default to app icon filename |
|
404 } |
|
405 } |
|
406 if (numOfViewIcons > 0 && iFs.IsValidName(viewIconFile) && (FileIsMbmWithGenericExtensionL(viewIconFile))) |
|
407 { |
|
408 CApaAppIconArray* iconArray = CApaAppIconArray::NewViewIconsL(numOfViewIcons, viewIconFile, *iIconLoader); |
|
409 viewData->SetIconArray(iconArray); |
|
410 iconArray = NULL; |
|
411 } |
|
412 if (fullViewIconFileName) |
|
413 { |
|
414 CleanupStack::PopAndDestroy(fullViewIconFileName); |
|
415 } |
|
416 iViewDataArray->AppendL(viewData); |
|
417 CleanupStack::Pop(viewData); |
|
418 } |
|
419 #ifndef SYMBIAN_APPARC_APPINFO_CACHE |
|
420 iIconLoader->LoadAllIconsL(); |
|
421 #endif // SYMBIAN_APPARC_APPINFO_CACHE |
|
422 // Read LTEXT group_name |
|
423 // If a localised group name has been specified, it overrides |
|
424 // The group name (if any), specified by APP_REGISTRATION_INFO |
|
425 |
|
426 TApaAppGroupName groupName; |
|
427 TRAPD(ret, (groupName = resourceReader.ReadTPtrCL())); |
|
428 if (ret != KErrNone) |
|
429 { |
|
430 if (ret != KErrEof) |
|
431 { |
|
432 User::Leave(ret); |
|
433 } |
|
434 } |
|
435 else |
|
436 { |
|
437 if (groupName.Length() > 0) |
|
438 { |
|
439 iCapability.iGroupName = groupName; |
|
440 } |
|
441 } |
|
442 |
|
443 CleanupStack::PopAndDestroy(&resourceReader); |
|
444 } |
|
445 |
|
446 |
|
447 TBool CApaAppInfoReaderV2::FileIsMbm(const TDesC& aFileName) |
|
448 { // static |
|
449 if (aFileName.Length() > 0) |
|
450 { |
|
451 TParsePtrC parsePtr(aFileName); |
|
452 _LIT(KFileExtensionMBM, ".MBM"); |
|
453 if (parsePtr.Ext().CompareF(KFileExtensionMBM) == 0) |
|
454 { |
|
455 return ETrue; |
|
456 } |
|
457 } |
|
458 return EFalse; |
|
459 } |
|
460 |
|
461 |
|
462 |
|
463 |
|
464 /*An MBM file may have a generic icon extension. In this case, as a way to check whether the file is an MBM one, |
|
465 it is necessary to read the content of the fist four 32bit words of it and find out whether these words correspond to |
|
466 KWriteonceFileStoreUid, KMultiBitmapFileImageUid, zero and KMultiBitmapFileImageChecksum respectively (defined in graphics/gditools/bmconv/bmconv.h). |
|
467 So the file is opened and the first 4 32 bit words are extracted and compared with the header information of standard MBM file. |
|
468 If they match, the function returns ETrue, else it returns EFalse */ |
|
469 TBool CApaAppInfoReaderV2::FileIsMbmWithGenericExtensionL(const TDesC& aFileName) const |
|
470 { |
|
471 if (aFileName.Length() > 0) |
|
472 { |
|
473 //open a file in Share mode - this will allow other methods to access it too |
|
474 RFile file; |
|
475 User::LeaveIfError(file.Open(iFs,aFileName,EFileShareReadersOnly)); |
|
476 //this is done beacuse the file can also be accessed by applist at the same time |
|
477 //buffer stores the 16 bytes of the file |
|
478 CleanupClosePushL(file); |
|
479 TBuf8<16> buffer; |
|
480 User::LeaveIfError(file.Read(buffer,16)); |
|
481 CleanupStack::PopAndDestroy();//file |
|
482 //we use a constant pointer to the buffer to read header info |
|
483 TPtrC8 filePointer(buffer); |
|
484 |
|
485 /*The first 16 bytes of an MBM file are the same for any generic MBM file. |
|
486 These are : |
|
487 KWriteOnceFileStoreUid = 0x10000037(Emulator MBM file) 0x10000041(ROM image) |
|
488 KMultiBitMapFileImageUid = 0x10000042(Emulator MBM file) 0x00000001(ROM image) |
|
489 Zero = 0x00000000(Emulator MBM file) 0x0000000C(ROM image) |
|
490 checksum = 0x47396439(Emulator MBM file) 0x10000040(ROM image) |
|
491 The first 16 bytes of the given file is compared with these standard values to ascertain it is MBM file*/ |
|
492 if((filePointer[3]==0x10)&&(filePointer[2]==0x00)&&(filePointer[1]==0x00)&&(filePointer[0]==0x37)) |
|
493 {//KWriteOnceFileStoreUid = 0x10000037 |
|
494 if((filePointer[7]==0x10)&&(filePointer[6]==0x00)&&(filePointer[5]==0x00)&&(filePointer[4]==0x42)) |
|
495 {//KMultiBitMapFileImageUid = 0x10000042 |
|
496 if((filePointer[11]==0x00)&&(filePointer[10]==0x00)&&(filePointer[9]==0x00)&&(filePointer[8]==0x00)) |
|
497 {//Zero = 0x00000000) |
|
498 if((filePointer[15]==0x47)&&(filePointer[14]==0x39)&&(filePointer[13]==0x64)&&(filePointer[12]==0x39)) |
|
499 {//checksum = 0x47396439 |
|
500 return ETrue; |
|
501 } |
|
502 } |
|
503 } |
|
504 } |
|
505 //Else Check for ROM Image MBM file's header |
|
506 else if((filePointer[3]==0x10)&&(filePointer[2]==0x00)&&(filePointer[1]==0x00)&&(filePointer[0]==0x41)) |
|
507 {//KWriteOnceFileStoreUid = 0x10000041 |
|
508 if((filePointer[7]==0x00)&&(filePointer[6]==0x00)&&(filePointer[5]==0x00)&&(filePointer[4]==0x01)) |
|
509 {//KMultiBitMapFileImageUid = 0x00000001 |
|
510 if((filePointer[11]==0x00)&&(filePointer[10]==0x00)&&(filePointer[9]==0x00)&&(filePointer[8]==0x0C)) |
|
511 {//Zero = 0x0000000C) |
|
512 if((filePointer[15]==0x10)&&(filePointer[14]==0x00)&&(filePointer[13]==0x00)&&(filePointer[12]==0x40)) |
|
513 {//checksum = 0x10000040 |
|
514 return ETrue; |
|
515 } |
|
516 } |
|
517 } |
|
518 } |
|
519 } |
|
520 return EFalse; |
|
521 } |
|
522 |
|
523 HBufC8* CApaAppInfoReaderV2::ReadOpaqueDataL(TUint aResourceId, const CResourceFile* aRegistrationFile, CResourceFile* aLocalisableResourceFile) |
|
524 { // static |
|
525 HBufC8* opaqueData = NULL; |
|
526 if (aResourceId == 0) |
|
527 { |
|
528 opaqueData = HBufC8::NewL(0); |
|
529 } |
|
530 else |
|
531 { |
|
532 if (aResourceId & KResourceOffsetMask) |
|
533 { |
|
534 // expecting opaque data to be in the localisable resource file |
|
535 if (aLocalisableResourceFile) |
|
536 { |
|
537 aLocalisableResourceFile->ConfirmSignatureL(); |
|
538 opaqueData = aLocalisableResourceFile->AllocReadLC(aResourceId); |
|
539 CleanupStack::Pop(opaqueData); |
|
540 } |
|
541 else |
|
542 { |
|
543 opaqueData = HBufC8::NewL(0); |
|
544 } |
|
545 } |
|
546 else |
|
547 { |
|
548 // expecting opaque data to be in the registration file |
|
549 __ASSERT_ALWAYS(aRegistrationFile, Panic(EPanicNullPointer)); |
|
550 opaqueData = aRegistrationFile->AllocReadLC(aResourceId); //lint !e613 Suppress ossible use of null pointer |
|
551 CleanupStack::Pop(opaqueData); |
|
552 } |
|
553 } |
|
554 return opaqueData; |
|
555 } |
|
556 |
|
557 void CApaAppInfoReaderV2::ReadNonLocalisableOptionalInfoL(RResourceReader& aResourceReader, const CResourceFile* aRegistrationFile, CResourceFile* aLocalisableResourceFile) |
|
558 { |
|
559 // read LEN WORD STRUCT service_list[] |
|
560 TInt serviceCount = 0; |
|
561 // service information was not present in the first release of the registration file |
|
562 // APP_REGISTRATION_INFO resource struct |
|
563 // this method must not leave if the registration file doesn't contain service information, so the |
|
564 // following call to ReadInt16L is trapped to ensure this method doesn't leave just because |
|
565 // there is no more information in the resource to read (KErrEof) |
|
566 TRAPD(err, serviceCount = aResourceReader.ReadInt16L()); |
|
567 if (err != KErrNone) |
|
568 { |
|
569 if (err != KErrEof) |
|
570 { |
|
571 User::Leave(err); |
|
572 } |
|
573 return; // end of resource reached |
|
574 } |
|
575 else |
|
576 { |
|
577 if ((!iServiceArray) && (serviceCount > 0)) |
|
578 { |
|
579 iServiceArray = new(ELeave) CArrayFixFlat<TApaAppServiceInfo>(4); |
|
580 } |
|
581 while (serviceCount--) |
|
582 { |
|
583 const TUid serviceUid = {aResourceReader.ReadUint32L()}; |
|
584 |
|
585 if ((serviceUid == KOpenServiceUid) && (iOpenServiceIsLegacy)) |
|
586 { |
|
587 __ASSERT_DEBUG(iIndexOfFirstOpenService == 0, User::Invariant()); |
|
588 // If we found an Open service in the SERVICE_INFO declaration |
|
589 // then we must ignore the legacy one |
|
590 (*iServiceArray)[0].Release(); |
|
591 iServiceArray->Delete(0); |
|
592 iOpenServiceIsLegacy = EFalse; |
|
593 iIndexOfFirstOpenService = -1; |
|
594 } |
|
595 |
|
596 CArrayFixFlat<TDataTypeWithPriority>* datatypes = new(ELeave) CArrayFixFlat<TDataTypeWithPriority>(5); |
|
597 CleanupStack::PushL(datatypes); |
|
598 ReadDataTypesL(aResourceReader, *datatypes); |
|
599 |
|
600 const TUint resourceId = aResourceReader.ReadUint32L(); |
|
601 HBufC8* opaqueData = NULL; |
|
602 opaqueData = ReadOpaqueDataL(resourceId, aRegistrationFile, aLocalisableResourceFile); |
|
603 CleanupStack::PushL(opaqueData); |
|
604 |
|
605 TApaAppServiceInfo serviceInfo(serviceUid, datatypes, opaqueData); // takes ownership of opaqueData |
|
606 iServiceArray->AppendL(serviceInfo); |
|
607 CleanupStack::Pop(opaqueData); |
|
608 CleanupStack::Pop(datatypes); |
|
609 if ((serviceUid == KOpenServiceUid) && (iIndexOfFirstOpenService < 0)) |
|
610 { |
|
611 iIndexOfFirstOpenService = iServiceArray->Count() - 1; |
|
612 } |
|
613 } |
|
614 // read LLINK opaque_data |
|
615 const TUint resourceId = aResourceReader.ReadUint32L(); |
|
616 delete iOpaqueData; |
|
617 iOpaqueData = NULL; |
|
618 iOpaqueData = ReadOpaqueDataL(resourceId, aRegistrationFile, aLocalisableResourceFile); |
|
619 } |
|
620 } |
|
621 |
|
622 void CApaAppInfoReaderV2::ReadNonLocalisableInfoL(RResourceReader& aResourceReader, CResourceFile*& aLocalisableResourceFile, TUint& aLocalisableResourceId) |
|
623 { |
|
624 __ASSERT_DEBUG(aLocalisableResourceFile == NULL, User::Invariant()); |
|
625 |
|
626 // read LTEXT localisable_resource_file |
|
627 TPtrC localisableResourceFileName(aResourceReader.ReadTPtrCL()); |
|
628 if (localisableResourceFileName.Length() > 0 && iFs.IsValidName(localisableResourceFileName)) |
|
629 { |
|
630 // determine the language specific name of the localisable resource file |
|
631 TParse parse; |
|
632 TParsePtrC parsePtr(iRegistrationFileName); |
|
633 User::LeaveIfError(parse.SetNoWild(parsePtr.Drive(), &KAppResourceFileExtension, &localisableResourceFileName)); |
|
634 TFileName resourceFileName(parse.FullName()); |
|
635 BaflUtils::NearestLanguageFile(iFs, resourceFileName, iApplicationLanguage); |
|
636 iLocalisableResourceFileName = resourceFileName.AllocL(); |
|
637 |
|
638 TEntry entry; |
|
639 User::LeaveIfError(iFs.Entry(*iLocalisableResourceFileName, entry)); |
|
640 iLocalisableResourceFileTimeStamp = entry.iModified; |
|
641 |
|
642 |
|
643 // open the localisable resource file |
|
644 aLocalisableResourceFile = CResourceFile::NewL(iFs, resourceFileName, 0, 0); |
|
645 } |
|
646 |
|
647 // read LONG localisable_resource_id |
|
648 aLocalisableResourceId = aResourceReader.ReadUint32L(); |
|
649 if (aLocalisableResourceFile && (aLocalisableResourceId & KResourceOffsetMask)) |
|
650 { |
|
651 aLocalisableResourceFile->ConfirmSignatureL(); |
|
652 } |
|
653 |
|
654 iCapability.iAppIsHidden=aResourceReader.ReadInt8L(); |
|
655 iCapability.iEmbeddability = static_cast<TApaAppCapability::TEmbeddability>(aResourceReader.ReadInt8L()); |
|
656 iCapability.iSupportsNewFile=aResourceReader.ReadInt8L(); |
|
657 iCapability.iLaunchInBackground = aResourceReader.ReadInt8L(); |
|
658 iCapability.iGroupName = aResourceReader.ReadTPtrCL(); |
|
659 |
|
660 // read BYTE default_screen_number |
|
661 iDefaultScreenNumber = aResourceReader.ReadUint8L(); |
|
662 |
|
663 //read the datatypes |
|
664 CArrayFixFlat<TDataTypeWithPriority>* datatypes = new(ELeave) CArrayFixFlat<TDataTypeWithPriority>(5); |
|
665 CleanupStack::PushL(datatypes); |
|
666 ReadDataTypesL(aResourceReader, *datatypes); |
|
667 //dataTypes is deleted if |
|
668 // A. There are no legacy datatypes |
|
669 // B. Control panel plugin apps are not allowed to register MIME types.If they happen to have any, these datatypes should be ignored. |
|
670 if ((iCapability.iAttributes & TApaAppCapability::EControlPanelItem) || (datatypes->Count() == 0)) |
|
671 { |
|
672 CleanupStack::PopAndDestroy(datatypes); |
|
673 } |
|
674 else |
|
675 { |
|
676 __ASSERT_DEBUG(!iServiceArray, User::Invariant()); |
|
677 iServiceArray = new(ELeave) CArrayFixFlat<TApaAppServiceInfo>(4); |
|
678 HBufC8* opaqueData = HBufC8::NewL(0); |
|
679 CleanupStack::PushL(opaqueData); |
|
680 TApaAppServiceInfo serviceInfo(KOpenServiceUid, datatypes, opaqueData); |
|
681 iServiceArray->AppendL(serviceInfo); |
|
682 CleanupStack::Pop(opaqueData); |
|
683 CleanupStack::Pop(datatypes); |
|
684 iIndexOfFirstOpenService = 0; |
|
685 iOpenServiceIsLegacy = ETrue; |
|
686 } |
|
687 |
|
688 // read LEN WORD STRUCT file_ownership_list[] |
|
689 const TInt fileOwnershipArraySize = aResourceReader.ReadInt16L(); |
|
690 if (fileOwnershipArraySize > 0) |
|
691 { |
|
692 iOwnedFileArray = new(ELeave) CDesCArraySeg(1); |
|
693 } |
|
694 for (TInt i=0; i < fileOwnershipArraySize; i++) |
|
695 { |
|
696 TPtrC fileNamePtr = aResourceReader.ReadTPtrCL(); |
|
697 iOwnedFileArray->AppendL(fileNamePtr); |
|
698 } |
|
699 } |
|
700 |
|
701 void CApaAppInfoReaderV2::ReadDataTypesL(RResourceReader& aResourceReader, |
|
702 CArrayFixFlat<TDataTypeWithPriority>& aDatatypes) |
|
703 { |
|
704 // read LEN WORD STRUCT datatype_list[] |
|
705 const TInt dataTypeArraySize = aResourceReader.ReadInt16L(); |
|
706 if (dataTypeArraySize <= 0) |
|
707 { |
|
708 return; |
|
709 } |
|
710 |
|
711 for (TInt i=0; i < dataTypeArraySize; i++) |
|
712 { |
|
713 TDataTypePriority priority = static_cast<TDataTypePriority>(aResourceReader.ReadInt32L()); |
|
714 |
|
715 //Check for data priority of UnTrusted apps however the trusted apps will not have any restrictions |
|
716 //over the data priority. |
|
717 //If an untrusted app has write device data capability (i.e. still has priority = KDataTypePrioritySystem), |
|
718 //do not restrict to KDataTypeUnTrustedPriorityThreshold |
|
719 if (priority > KDataTypeUnTrustedPriorityThreshold || priority == KDataTypePrioritySystem ) |
|
720 { |
|
721 ReadAppSecurityInfo(); |
|
722 |
|
723 if (priority == KDataTypePrioritySystem) |
|
724 { |
|
725 // Check that the app has capability WriteDeviceData |
|
726 if (!iHasWriteDeviceDataCap) |
|
727 { |
|
728 priority = KDataTypePriorityNormal; |
|
729 } |
|
730 } |
|
731 else |
|
732 { |
|
733 //data priority for UnTrusted apps would be capped if it is greater than the threshold priority i.e, KMaxTInt16. |
|
734 TInt match=iRegistrationFileName.MatchF(KLitPathForUntrustedRegistrationResourceFiles); |
|
735 if (match != KErrNotFound && !iIsSidTrusted) |
|
736 { |
|
737 //if registration file is in import directory and |
|
738 //its sid is in unprotected range - downgrade the priority |
|
739 priority = KDataTypeUnTrustedPriorityThreshold; |
|
740 } |
|
741 } |
|
742 } |
|
743 TPtrC8 dataTypePtr = aResourceReader.ReadTPtrC8L(); |
|
744 TDataType dataType(dataTypePtr); |
|
745 TDataTypeWithPriority dataTypeWithPriority(dataType, priority); |
|
746 aDatatypes.AppendL(dataTypeWithPriority); |
|
747 } |
|
748 } |
|
749 |
|
750 // This method can be used to check whether app has a WriteDeviceCap |
|
751 // and its sid is trusted |
|
752 void CApaAppInfoReaderV2::ReadAppSecurityInfo() |
|
753 { |
|
754 if (!iSecurityInfoHasBeenRead) |
|
755 { |
|
756 __ASSERT_DEBUG( iAppBinaryFullName, Panic(EPanicNullPointer) ); |
|
757 const TInt err = CApaSecurityUtils::CheckAppSecurity( *iAppBinaryFullName, |
|
758 iHasWriteDeviceDataCap, |
|
759 iIsSidTrusted); |
|
760 if ( KErrNone != err ) |
|
761 { |
|
762 iHasWriteDeviceDataCap = EFalse; |
|
763 iIsSidTrusted = EFalse; |
|
764 } |
|
765 iSecurityInfoHasBeenRead = ETrue; |
|
766 } |
|
767 } |
|
768 |
|
769 // |
|
770 // Class CApaIconLoader |
|
771 // |
|
772 |
|
773 CApaIconLoader* CApaIconLoader::NewL(RFs& aFs) |
|
774 { |
|
775 CApaIconLoader* self = NewLC(aFs); |
|
776 CleanupStack::Pop(self); |
|
777 return self; |
|
778 } |
|
779 |
|
780 CApaIconLoader* CApaIconLoader::NewLC(RFs& aFs) |
|
781 { |
|
782 CApaIconLoader* self = new(ELeave) CApaIconLoader(aFs); |
|
783 CleanupStack::PushL(self); |
|
784 self->ConstructL(); |
|
785 return self; |
|
786 } |
|
787 |
|
788 CApaIconLoader::CApaIconLoader(RFs& aFs) : |
|
789 iFs(aFs) |
|
790 { |
|
791 } |
|
792 |
|
793 void CApaIconLoader::ConstructL() |
|
794 { |
|
795 } //lint !e1762 Suppress member function could be made const |
|
796 |
|
797 |
|
798 CApaIconLoader::~CApaIconLoader() |
|
799 { |
|
800 TInt arrayCount = iIconIndexArray.Count(); |
|
801 while (--arrayCount >= 0) |
|
802 { |
|
803 delete (iIconIndexArray[arrayCount].iFileName); |
|
804 } |
|
805 iIconIndexArray.Close(); |
|
806 iIconArrays.Close(); |
|
807 } |
|
808 |
|
809 void CApaIconLoader::AddIconArrayL(const CApaAppIconArray& aIcons) |
|
810 { |
|
811 iIconArrays.AppendL(&aIcons); |
|
812 } |
|
813 |
|
814 void CApaIconLoader::LoadAllIconsL() |
|
815 { |
|
816 const TInt iconArraysCount = iIconArrays.Count(); |
|
817 CleanupClosePushL(iIconArrays); |
|
818 for (TInt ii = 0; ii <iconArraysCount; ++ii) |
|
819 { |
|
820 iIconArrays[ii]->LoadIconsL(); |
|
821 } |
|
822 CleanupStack::PopAndDestroy(&iIconArrays); |
|
823 } |
|
824 |
|
825 // given an mbm filename, returns the next index to read from the file |
|
826 // always set aUseCache to EFalse on first call in a sequence of calls |
|
827 TInt CApaIconLoader::IconIndexL(const TDesC& aFileName, TBool& aUseCache) |
|
828 { |
|
829 if (aUseCache) |
|
830 { |
|
831 TInt ret = iIconIndexArray[iCachedArrayIndex].iIndex++; |
|
832 return ret; |
|
833 } |
|
834 else |
|
835 { |
|
836 aUseCache = ETrue; |
|
837 } |
|
838 |
|
839 // if filename in array, get the next index |
|
840 TInt ret = 0; |
|
841 const TInt arrayCount = iIconIndexArray.Count(); |
|
842 TInt arrayIndex; |
|
843 for (arrayIndex = 0; arrayIndex < arrayCount; arrayIndex++) |
|
844 { |
|
845 __ASSERT_DEBUG(iIconIndexArray[arrayIndex].iFileName, Panic(EDPanicInvalidIconIndexArray)); |
|
846 if (iIconIndexArray[arrayIndex].iFileName->CompareF(aFileName) == 0) |
|
847 { |
|
848 ret = iIconIndexArray[arrayIndex].iIndex++; |
|
849 iCachedArrayIndex = arrayIndex; |
|
850 break; |
|
851 } |
|
852 } |
|
853 |
|
854 if (arrayIndex >= arrayCount) |
|
855 { |
|
856 // filename not found, add it to array |
|
857 TKeyValuePair keyValuePair; |
|
858 keyValuePair.iFileName = aFileName.AllocL(); |
|
859 keyValuePair.iIndex = 0; |
|
860 ret = keyValuePair.iIndex++; |
|
861 User::LeaveIfError(iIconIndexArray.Append(keyValuePair)); |
|
862 iCachedArrayIndex = arrayCount; |
|
863 } |
|
864 return ret; |
|
865 } |
|
866 |
|
867 |
|
868 |
|
869 // returns EFalse if there was an error obtaining aMbmFileName's entry information, |
|
870 // otherwise returns ETrue. |
|
871 // Leaves if an error occurs while trying to populate aIcons or sort icons |
|
872 TBool CApaIconLoader::LoadIconsL(TInt aNumOfIcons, const TDesC& aMbmFileName, CArrayPtr<CApaMaskedBitmap>& aIcons) |
|
873 { |
|
874 TEntry entry; |
|
875 TInt error=iFs.Entry(aMbmFileName,entry); |
|
876 if (error!=KErrNone) |
|
877 { |
|
878 return EFalse; |
|
879 } |
|
880 TInt iconIndex; |
|
881 TInt fileIndex; |
|
882 TBool useCache = EFalse; |
|
883 |
|
884 |
|
885 // create link to CApaAppList which owns this object as it has a separate share protected RFs |
|
886 // which can be used to load bitmap icons |
|
887 CApaAppList* const appList = CApaAppList::Self(); |
|
888 |
|
889 RFile mbmFile; |
|
890 CleanupClosePushL(mbmFile); |
|
891 User::LeaveIfError(mbmFile.Open(appList->ShareProtectedFileServer(), aMbmFileName, EFileShareReadersOnly)); |
|
892 |
|
893 for(iconIndex=0; iconIndex<aNumOfIcons; ++iconIndex) |
|
894 { |
|
895 CApaMaskedBitmap* bitmap = CApaMaskedBitmap::NewLC(); |
|
896 fileIndex = IconIndexL(aMbmFileName, useCache); |
|
897 User::LeaveIfError(bitmap->Load(mbmFile, 2*fileIndex)); |
|
898 User::LeaveIfError((bitmap->Mask())->Load(mbmFile,2*fileIndex+1)); |
|
899 aIcons.AppendL(bitmap); |
|
900 CleanupStack::Pop(bitmap); |
|
901 } |
|
902 |
|
903 CleanupStack::PopAndDestroy(&mbmFile); // close mbmFile |
|
904 |
|
905 // now sort them in ascending order of size |
|
906 TInt numberOfIcons = aIcons.Count(); |
|
907 // create a new array that we can sort by area, populated from aIcons |
|
908 RPointerArray<CApaMaskedBitmap> ptrArray(numberOfIcons); |
|
909 CleanupClosePushL(ptrArray); |
|
910 TLinearOrder<CApaMaskedBitmap> order(CApaIconLoader::CompareIcons); |
|
911 for (iconIndex=0; iconIndex<numberOfIcons; iconIndex++) |
|
912 { |
|
913 User::LeaveIfError(ptrArray.InsertInOrderAllowRepeats(aIcons[iconIndex], order)); |
|
914 } |
|
915 // copy the sorted icon pointers back into aIcons - must not Leave inside the loop below |
|
916 for (iconIndex=0; iconIndex<numberOfIcons; iconIndex++) |
|
917 { |
|
918 aIcons[iconIndex]=ptrArray[iconIndex]; |
|
919 } |
|
920 CleanupStack::PopAndDestroy(&ptrArray); |
|
921 |
|
922 return ETrue; |
|
923 } |
|
924 |
|
925 TInt CApaIconLoader::CompareIcons(const CApaMaskedBitmap& aFirst, const CApaMaskedBitmap& aSecond) |
|
926 { // static |
|
927 TSize sizeFirst = aFirst.SizeInPixels(); |
|
928 TInt areaFirst = sizeFirst.iWidth*sizeFirst.iHeight; |
|
929 TSize sizeSecond = aSecond.SizeInPixels(); |
|
930 TInt areaSecond = sizeSecond.iWidth*sizeSecond.iHeight; |
|
931 return areaFirst - areaSecond; |
|
932 } |
|
933 |
|
934 // |
|
935 // Class CApaAppIconArray |
|
936 // |
|
937 |
|
938 CApaAppIconArray* CApaAppIconArray::NewL() |
|
939 { |
|
940 return new(ELeave) CApaAppIconArray(); |
|
941 } |
|
942 |
|
943 /* public factory functions */ |
|
944 CApaAppIconArray* CApaAppIconArray::NewAppIconsL(TInt aNumOfIcons, const TDesC& aMbmFileName, CApaIconLoader& aIconLoader) |
|
945 { |
|
946 return NewL(aNumOfIcons,aMbmFileName,aIconLoader,ETrue); |
|
947 } |
|
948 |
|
949 CApaAppIconArray* CApaAppIconArray::NewViewIconsL(TInt aNumOfIcons, const TDesC& aMbmFileName, CApaIconLoader& aIconLoader) |
|
950 { |
|
951 return NewL(aNumOfIcons,aMbmFileName,aIconLoader,EFalse); |
|
952 } |
|
953 |
|
954 CApaAppIconArray* CApaAppIconArray::NewDefaultIconsL() |
|
955 { |
|
956 CApaAppIconArray* self = NewL(); |
|
957 CleanupStack::PushL(self); |
|
958 self->GetDefaultIconsL(); |
|
959 CleanupStack::Pop(self); |
|
960 return self; |
|
961 } |
|
962 |
|
963 CApaAppIconArray* CApaAppIconArray::NewRealDefaultIconsLC(TInt aNumOfIcons, const TDesC& aMbmFileName, CApaIconLoader& aIconLoader) |
|
964 { |
|
965 return NewLC(aNumOfIcons,aMbmFileName,aIconLoader,EFalse); |
|
966 } |
|
967 |
|
968 /* real NewL and NewLC, private */ |
|
969 CApaAppIconArray* CApaAppIconArray::NewL(TInt aNumOfIcons, const TDesC& aMbmFileName, CApaIconLoader& aIconLoader, TBool aFallbackToDefaultIcons) |
|
970 { |
|
971 CApaAppIconArray* self = NewLC(aNumOfIcons,aMbmFileName,aIconLoader,aFallbackToDefaultIcons); |
|
972 CleanupStack::Pop(self); |
|
973 return self; |
|
974 } |
|
975 |
|
976 CApaAppIconArray* CApaAppIconArray::NewLC(TInt aNumOfIcons, const TDesC& aMbmFileName, CApaIconLoader& aIconLoader, TBool aFallbackToDefaultIcons) |
|
977 { |
|
978 CApaAppIconArray* self = new(ELeave) CApaAppIconArray(aNumOfIcons,aIconLoader,aFallbackToDefaultIcons); |
|
979 CleanupStack::PushL(self); |
|
980 self->ConstructL(aMbmFileName); |
|
981 return self; |
|
982 } |
|
983 |
|
984 CApaAppIconArray::CApaAppIconArray() |
|
985 { |
|
986 } |
|
987 |
|
988 CApaAppIconArray::CApaAppIconArray(TInt aNumOfIcons, CApaIconLoader& aIconLoader, TBool aFallbackToDefaultIcons) : |
|
989 iNumOfIcons(aNumOfIcons), |
|
990 iIconLoader(&aIconLoader), |
|
991 iFallbackToDefaultIcons(aFallbackToDefaultIcons) |
|
992 { |
|
993 } |
|
994 |
|
995 void CApaAppIconArray::ConstructL(const TDesC& aMbmFileName) |
|
996 { |
|
997 iMbmFileName = aMbmFileName.AllocL(); |
|
998 ASSERT(iIconLoader); |
|
999 iIconLoader->AddIconArrayL(*this); |
|
1000 } |
|
1001 |
|
1002 CApaAppIconArray::~CApaAppIconArray() |
|
1003 { |
|
1004 if(iDefaultIconsUsed) |
|
1005 { |
|
1006 ASSERT(iDefaultIconsProvider); |
|
1007 if(iDefaultIconsProvider) |
|
1008 iDefaultIconsProvider->ReleaseDefaultIconArray(); |
|
1009 } |
|
1010 delete iMbmFileName; |
|
1011 if (iIcons) |
|
1012 { |
|
1013 iIcons->ResetAndDestroy(); |
|
1014 delete iIcons; |
|
1015 } |
|
1016 iDefaultIconsProvider = NULL; |
|
1017 iIconLoader = NULL; |
|
1018 } |
|
1019 |
|
1020 // returns EFalse if there was an error obtaining iMbmFileName's entry information, |
|
1021 // otherwise returns ETrue or leaves with a system-wide error code |
|
1022 TBool CApaAppIconArray::LoadIconsL() |
|
1023 { |
|
1024 ASSERT(iIconLoader); |
|
1025 ASSERT(!iDefaultIconsUsed); |
|
1026 ASSERT(!iIcons); |
|
1027 iIcons = new(ELeave) CArrayPtrFlat<CApaMaskedBitmap>(5); |
|
1028 TBool badMbmEntryInfo = EFalse; |
|
1029 TRAPD(err,badMbmEntryInfo = !iIconLoader->LoadIconsL(iNumOfIcons,*iMbmFileName,*iIcons)); |
|
1030 |
|
1031 // We'll be called by the iconLoader at most once, and after we've been called, |
|
1032 // it might be destroyed. So we shouldn't keep a pointer to it anymore. |
|
1033 iIconLoader = NULL; |
|
1034 |
|
1035 if ((badMbmEntryInfo || err != KErrNone) && iFallbackToDefaultIcons) |
|
1036 { |
|
1037 GetDefaultIconsL(); |
|
1038 } |
|
1039 else if (badMbmEntryInfo) |
|
1040 { |
|
1041 return EFalse; |
|
1042 } |
|
1043 else if (err != KErrNone) |
|
1044 { |
|
1045 User::Leave(err); |
|
1046 } |
|
1047 return ETrue; |
|
1048 } |
|
1049 |
|
1050 CApaMaskedBitmap* CApaAppIconArray::IconBySize(const TSize& aSize) const |
|
1051 { |
|
1052 if(iDefaultIconsUsed) |
|
1053 { |
|
1054 return DefaultIcons().IconBySize(aSize); |
|
1055 } |
|
1056 else if(iIcons == NULL && iIconLoader == NULL) |
|
1057 { |
|
1058 // Then we've been created with the default constructor, just pretend |
|
1059 // there's no icon of the right size |
|
1060 return NULL; |
|
1061 } |
|
1062 else if(iIcons == NULL) |
|
1063 { |
|
1064 #ifndef SYMBIAN_APPARC_APPINFO_CACHE |
|
1065 // Arriving here means the the icons need loading but havn't been loaded yet. |
|
1066 // when we have lazy loading, this will be a trigger condition for loading them |
|
1067 ASSERT(iIcons); |
|
1068 return NULL; |
|
1069 } |
|
1070 else |
|
1071 { |
|
1072 #else |
|
1073 // Arriving here means the the icons need loading but havn't been loaded yet. |
|
1074 TRAPD(err, iIconLoader->LoadAllIconsL()); |
|
1075 if (err != KErrNone) |
|
1076 { |
|
1077 return NULL; |
|
1078 } |
|
1079 } |
|
1080 #endif // SYMBIAN_APPARC_APPINFO_CACHE |
|
1081 |
|
1082 const TInt count = iIcons->Count(); |
|
1083 CApaMaskedBitmap* bmp=NULL; |
|
1084 for (TInt ii=0;ii<count;ii++) |
|
1085 { |
|
1086 if ((*iIcons)[ii]->SizeInPixels()==aSize) |
|
1087 bmp=(*iIcons)[ii]; |
|
1088 } |
|
1089 if (!bmp) |
|
1090 {// if the exact size has not been found get one with nearest but smaller area |
|
1091 TInt differenceOfClosest=KMaxTInt; |
|
1092 TInt indexOfClosest=KMaxTInt; |
|
1093 TInt reqArea=aSize.iHeight*aSize.iWidth; |
|
1094 TSize bmpSize; |
|
1095 TInt difference; |
|
1096 for (TInt jj=0;jj<count;jj++) |
|
1097 { |
|
1098 bmpSize=(*iIcons)[jj]->SizeInPixels(); |
|
1099 difference=reqArea-bmpSize.iHeight*bmpSize.iWidth; |
|
1100 if (difference<differenceOfClosest && difference>=0) |
|
1101 { |
|
1102 differenceOfClosest=difference; |
|
1103 indexOfClosest=jj; |
|
1104 } |
|
1105 } |
|
1106 if (indexOfClosest<KMaxTInt) |
|
1107 bmp=(*iIcons)[indexOfClosest]; |
|
1108 } |
|
1109 return bmp; |
|
1110 #ifndef SYMBIAN_APPARC_APPINFO_CACHE |
|
1111 } |
|
1112 #endif // SYMBIAN_APPARC_APPINFO_CACHE |
|
1113 } |
|
1114 |
|
1115 CArrayFixFlat<TSize>* CApaAppIconArray::IconSizesL() const |
|
1116 { |
|
1117 if(iDefaultIconsUsed) |
|
1118 { |
|
1119 return DefaultIcons().IconSizesL(); |
|
1120 } |
|
1121 else if(iIcons == NULL && iIconLoader == NULL) |
|
1122 { |
|
1123 return new(ELeave)CArrayFixFlat<TSize>(1); |
|
1124 } |
|
1125 else if(iIcons == NULL) |
|
1126 { |
|
1127 #ifndef SYMBIAN_APPARC_APPINFO_CACHE |
|
1128 // Arriving here means the the icons need loading but havn't been loaded yet. |
|
1129 // when we have lazy loading, this will be a trigger condition for loading them |
|
1130 ASSERT(iIcons); |
|
1131 return new(ELeave)CArrayFixFlat<TSize>(1); |
|
1132 } |
|
1133 else |
|
1134 { |
|
1135 #else |
|
1136 // Arriving here means the the icons need loading but havn't been loaded yet. |
|
1137 TRAPD(err, iIconLoader->LoadAllIconsL()); |
|
1138 if (err != KErrNone) |
|
1139 { |
|
1140 return new(ELeave)CArrayFixFlat<TSize>(1); |
|
1141 } |
|
1142 } |
|
1143 #endif // SYMBIAN_APPARC_APPINFO_CACHE |
|
1144 const TInt count=iIcons->Count(); |
|
1145 CArrayFixFlat<TSize>* arrayOfSizes=new(ELeave)CArrayFixFlat<TSize>(1); |
|
1146 CleanupStack::PushL(arrayOfSizes); |
|
1147 for(TInt ii=0;ii<count;ii++) |
|
1148 { |
|
1149 arrayOfSizes->AppendL((*iIcons)[ii]->SizeInPixels()); |
|
1150 } |
|
1151 CleanupStack::Pop(arrayOfSizes); |
|
1152 return arrayOfSizes; |
|
1153 #ifndef SYMBIAN_APPARC_APPINFO_CACHE |
|
1154 } |
|
1155 #endif // SYMBIAN_APPARC_APPINFO_CACHE |
|
1156 } |
|
1157 |
|
1158 TInt CApaAppIconArray::Count() const |
|
1159 { |
|
1160 if(iDefaultIconsUsed) |
|
1161 { |
|
1162 return DefaultIcons().Count(); |
|
1163 } |
|
1164 else if(iIcons == NULL && iIconLoader == NULL) |
|
1165 { |
|
1166 return 0; |
|
1167 } |
|
1168 #ifndef SYMBIAN_APPARC_APPINFO_CACHE |
|
1169 else if(iIcons == NULL) |
|
1170 { |
|
1171 // Arriving here means the the icons need loading but havn't been loaded yet. |
|
1172 // when we have lazy loading, this will be a trigger condition for loading them |
|
1173 ASSERT(iIcons); |
|
1174 return 0; |
|
1175 } |
|
1176 else |
|
1177 { |
|
1178 return iIcons->Count(); |
|
1179 } |
|
1180 #else |
|
1181 else if(iIcons == NULL) |
|
1182 { |
|
1183 // Arriving here means the the icons need loading but havn't been loaded yet. |
|
1184 TRAPD(err, iIconLoader->LoadAllIconsL()); |
|
1185 if (err != KErrNone) |
|
1186 { |
|
1187 return 0; |
|
1188 } |
|
1189 } |
|
1190 return iIcons->Count(); |
|
1191 #endif // SYMBIAN_APPARC_APPINFO_CACHE |
|
1192 } |
|
1193 |
|
1194 TBool CApaAppIconArray::DefaultIconsUsed() const |
|
1195 { |
|
1196 return iDefaultIconsUsed; |
|
1197 } |
|
1198 |
|
1199 CApaMaskedBitmap* CApaAppIconArray::operator[](TInt aIndex) const |
|
1200 { |
|
1201 if(iDefaultIconsUsed) |
|
1202 { |
|
1203 return DefaultIcons()[aIndex]; |
|
1204 } |
|
1205 else if(iIcons == NULL && iIconLoader == NULL) |
|
1206 { |
|
1207 Panic(EPanicIndexOutOfRange); |
|
1208 return NULL; |
|
1209 } |
|
1210 #ifndef SYMBIAN_APPARC_APPINFO_CACHE |
|
1211 else if(iIcons == NULL) |
|
1212 { |
|
1213 // Arriving here means the the icons need loading but havn't been loaded yet. |
|
1214 // when we have lazy loading, this will be a trigger condition for loading them |
|
1215 ASSERT(iIcons); |
|
1216 return NULL; |
|
1217 } |
|
1218 else |
|
1219 { |
|
1220 return (*iIcons)[aIndex]; |
|
1221 } |
|
1222 #else |
|
1223 else if(iIcons == NULL) |
|
1224 { |
|
1225 // Arriving here means the the icons need loading but havn't been loaded yet. |
|
1226 TRAPD(err, iIconLoader->LoadAllIconsL()); |
|
1227 if (err != KErrNone) |
|
1228 { |
|
1229 return NULL; |
|
1230 } |
|
1231 } |
|
1232 return (*iIcons)[aIndex]; |
|
1233 #endif // SYMBIAN_APPARC_APPINFO_CACHE |
|
1234 } |
|
1235 |
|
1236 #ifdef SYMBIAN_APPARC_APPINFO_CACHE |
|
1237 TBool CApaAppIconArray::AreAppIconsLoaded() const |
|
1238 { |
|
1239 if (iDefaultIconsUsed) |
|
1240 { |
|
1241 return ETrue; |
|
1242 } |
|
1243 if (iNumOfIcons > 0 && !iIcons) |
|
1244 { |
|
1245 return EFalse; |
|
1246 } |
|
1247 return ETrue; |
|
1248 } |
|
1249 |
|
1250 TBool CApaAppIconArray::AreViewIconsLoaded() const |
|
1251 { |
|
1252 if (iNumOfIcons > 0 && !iIcons ) |
|
1253 { |
|
1254 return EFalse; |
|
1255 } |
|
1256 return ETrue; |
|
1257 } |
|
1258 #endif // SYMBIAN_APPARC_APPINFO_CACHE |
|
1259 |
|
1260 void CApaAppIconArray::GetDefaultIconsL() |
|
1261 { |
|
1262 ASSERT(!iDefaultIconsUsed); |
|
1263 iDefaultIconsProvider = CApaAppList::Self(); |
|
1264 ASSERT(iDefaultIconsProvider); |
|
1265 iDefaultIconsProvider->AcquireDefaultIconArrayL(); |
|
1266 iDefaultIconsUsed = ETrue; |
|
1267 delete iMbmFileName; |
|
1268 iMbmFileName = NULL; |
|
1269 if (iIcons) |
|
1270 { |
|
1271 iIcons->ResetAndDestroy(); |
|
1272 delete iIcons; |
|
1273 iIcons = NULL; |
|
1274 } |
|
1275 } |
|
1276 |
|
1277 const CApaAppIconArray& CApaAppIconArray::DefaultIcons() const |
|
1278 { |
|
1279 ASSERT(iDefaultIconsUsed && iDefaultIconsProvider); |
|
1280 return iDefaultIconsProvider->DefaultIconArray(); |
|
1281 } |
|