|
1 /* |
|
2 * Copyright (c) 2008-2009 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 the License "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: |
|
15 * This file implements Reference Install tasks for getting ComponentInfo, installation, uninstallation and activation/deactivation. |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 #include "sifrefinstallertask.h" |
|
21 #include "sifrefbinpkgextractor.h" |
|
22 #include "usiflog.h" |
|
23 #include <usif/usiferror.h> |
|
24 |
|
25 using namespace Usif; |
|
26 |
|
27 _LIT(KRefInstPrivateDir, "c:\\private\\1028634e\\"); |
|
28 |
|
29 /** |
|
30 A set of helper functions for Reference Installer tasks. |
|
31 */ |
|
32 namespace InstallHelper |
|
33 { |
|
34 _LIT(KSifReferenceSoftwareType, "reference"); |
|
35 _LIT(KUiConfirmationQuestion, "Are you sure you want to %S component: %S, vendor: %S"); |
|
36 _LIT(KParamNameErrDesc, "Error Description"); |
|
37 _LIT(KErrFileAlreadyExists, "File already exists: "); |
|
38 _LIT(KUiConfirmationTypeInstall, "install"); |
|
39 _LIT(KUiConfirmationTypeUpgrade, "upgrade"); |
|
40 _LIT(KUiConfirmationTypeUninstall, "uninstall"); |
|
41 _LIT(KUiParserErrorDesc, "Installer encountered a problem when parsing a package file."); |
|
42 const TInt KMaxConfirmationTypeLengh = KUiConfirmationTypeUninstall.iTypeLength; |
|
43 |
|
44 // This Reference Installer uses Component Name and Vendor Name in order to |
|
45 // identify a component in the SCR database. This identification scheme doesn't provide |
|
46 // unique ids and its results depend on the current language. Hence, a real installer |
|
47 // must use the Unique Id mechanism provided by the SCR. |
|
48 void FindComponentL(RSoftwareComponentRegistry& aScr, TComponentSearchData& aCompSearchData, const CSifRefPkgParser& aParser) |
|
49 { |
|
50 DEBUG_PRINTF(_L8("InstallHelper::FindComponentL()")); |
|
51 |
|
52 // Get the index of the current language |
|
53 const TLanguage curLang = User::Language(); |
|
54 TInt langIndex = aParser.GetLanguageIndex(curLang); |
|
55 if (langIndex == KErrNotFound) |
|
56 { |
|
57 ASSERT(aParser.Languages().Count() > 0); // The parser should have already rejected packages without languages |
|
58 langIndex = 0; |
|
59 } |
|
60 |
|
61 // Data for CComponentInfo |
|
62 aCompSearchData.iName = aParser.ComponentNames()[langIndex]; |
|
63 aCompSearchData.iVersion = aParser.Version().Name(); |
|
64 aCompSearchData.iVendor = aParser.VendorNames()[langIndex]; |
|
65 aCompSearchData.iScomoState = EDeactivated; |
|
66 aCompSearchData.iInstallStatus = ENewComponent; |
|
67 aCompSearchData.iComponentId = 0; |
|
68 |
|
69 RSoftwareComponentRegistryView scrView; |
|
70 CComponentFilter* filter = CComponentFilter::NewLC(); |
|
71 filter->SetNameL(*aCompSearchData.iName); |
|
72 filter->SetVendorL(*aCompSearchData.iVendor); |
|
73 filter->SetSoftwareTypeL(KSifReferenceSoftwareType); |
|
74 |
|
75 scrView.OpenViewL(aScr, filter); |
|
76 CleanupClosePushL(scrView); |
|
77 |
|
78 // Iterate over matching components in order to determine the status of the package being processed. |
|
79 CComponentEntry* component = NULL; |
|
80 while ((component = scrView.NextComponentL()) != NULL) |
|
81 { |
|
82 const TDesC& installedVersion = component->Version(); |
|
83 const TInt cmp = RSoftwareComponentRegistry::CompareVersionsL(installedVersion, aCompSearchData.iVersion); |
|
84 if (cmp > 0) |
|
85 { |
|
86 aCompSearchData.iInstallStatus = ENewerVersionAlreadyInstalled; |
|
87 aCompSearchData.iScomoState = component->ScomoState(); |
|
88 aCompSearchData.iComponentId = component->ComponentId(); |
|
89 delete component; |
|
90 break; |
|
91 } |
|
92 else if (cmp == 0 && aCompSearchData.iInstallStatus < EAlreadyInstalled) |
|
93 { |
|
94 aCompSearchData.iInstallStatus = EAlreadyInstalled; |
|
95 aCompSearchData.iScomoState = component->ScomoState(); |
|
96 aCompSearchData.iComponentId = component->ComponentId(); |
|
97 } |
|
98 else if (cmp < 0 && aCompSearchData.iInstallStatus < EUpgrade) |
|
99 { |
|
100 aCompSearchData.iInstallStatus = EUpgrade; |
|
101 aCompSearchData.iScomoState = component->ScomoState(); |
|
102 aCompSearchData.iComponentId = component->ComponentId(); |
|
103 } |
|
104 delete component; |
|
105 } |
|
106 CleanupStack::PopAndDestroy(2, filter); |
|
107 } |
|
108 |
|
109 TBool UnregisterAndDeleteFileL(RSoftwareComponentRegistry& aScr, RSoftwareComponentRegistryFilesList& aFileList, RStsSession& aSts, TComponentId aComponentId) |
|
110 { |
|
111 DEBUG_PRINTF(_L8("InstallHelper::UnregisterAndDeleteFileL()")); |
|
112 |
|
113 // Get next file |
|
114 HBufC* file = aFileList.NextFileL(); |
|
115 if (file != NULL) |
|
116 { |
|
117 // and remove it from the file system |
|
118 CleanupStack::PushL(file); |
|
119 aSts.RemoveL(*file); |
|
120 CleanupStack::PopAndDestroy(file); |
|
121 } |
|
122 else |
|
123 { |
|
124 // Remove the component from the SCR if there are no files left |
|
125 aFileList.Close(); |
|
126 aScr.DeleteComponentL(aComponentId); |
|
127 |
|
128 // Copying complete |
|
129 return ETrue; |
|
130 } |
|
131 |
|
132 // Copying in progress |
|
133 return EFalse; |
|
134 } |
|
135 |
|
136 MInstallerUIHandler* CreateUiHandlerL(const COpaqueNamedParams* aCustomArguments, TInstallerUIHandlerFactory aUiHandlerFactory) |
|
137 { |
|
138 DEBUG_PRINTF(_L8("InstallHelper::CreateUiHandlerL()")); |
|
139 |
|
140 // Instantiate a UI handler for non-silent requests |
|
141 if (aCustomArguments != NULL) |
|
142 { |
|
143 TInt silent = EFalse; |
|
144 aCustomArguments->GetIntByNameL(_L("Silent"), silent); |
|
145 if (silent) |
|
146 { |
|
147 return NULL; |
|
148 } |
|
149 } |
|
150 |
|
151 return aUiHandlerFactory(); |
|
152 } |
|
153 |
|
154 enum TConfirmationType |
|
155 { |
|
156 EConfirmationInstall, |
|
157 EConfirmationUpgrade, |
|
158 EConfirmationUninstall |
|
159 }; |
|
160 |
|
161 void userConfirmationL(TConfirmationType aType, MInstallerUIHandler& uiHandler, const TDesC& aComponent, const TDesC& aVendor) |
|
162 { |
|
163 DEBUG_PRINTF(_L8("InstallHelper::userConfirmationL()")); |
|
164 |
|
165 const TInt maxLen = KUiConfirmationQuestion.iTypeLength + KMaxConfirmationTypeLengh + aComponent.Length() + aVendor.Length(); |
|
166 HBufC* info = HBufC::NewLC(maxLen); |
|
167 TPtr bufInfo(info->Des()); |
|
168 |
|
169 switch (aType) |
|
170 { |
|
171 case EConfirmationInstall: |
|
172 bufInfo.Format(KUiConfirmationQuestion, &KUiConfirmationTypeInstall, &aComponent, &aVendor); |
|
173 break; |
|
174 |
|
175 case EConfirmationUpgrade: |
|
176 bufInfo.Format(KUiConfirmationQuestion, &KUiConfirmationTypeUpgrade, &aComponent, &aVendor); |
|
177 break; |
|
178 |
|
179 case EConfirmationUninstall: |
|
180 bufInfo.Format(KUiConfirmationQuestion, &KUiConfirmationTypeUninstall, &aComponent, &aVendor); |
|
181 break; |
|
182 |
|
183 default: |
|
184 User::Leave(KErrArgument); |
|
185 } |
|
186 |
|
187 if (!uiHandler.ConfirmationUIHandler(*info)) |
|
188 { |
|
189 User::Leave(KErrCancel); |
|
190 } |
|
191 |
|
192 CleanupStack::PopAndDestroy(info); |
|
193 } |
|
194 } |
|
195 |
|
196 // ============================================================================================================= |
|
197 |
|
198 CSifRefGetComponentInfoTask* CSifRefGetComponentInfoTask::NewL(TTransportTaskParams& aParams) |
|
199 { |
|
200 DEBUG_PRINTF(_L8("CSifRefGetComponentInfoTask::NewL()")); |
|
201 |
|
202 // Validate the arguments first. |
|
203 if ((aParams.iFileName == NULL && aParams.iFileHandle == NULL) || aParams.iComponentInfo == NULL) |
|
204 { |
|
205 User::Leave(KErrArgument); |
|
206 } |
|
207 |
|
208 CSifRefGetComponentInfoTask* self = new (ELeave) CSifRefGetComponentInfoTask(aParams); |
|
209 return self; |
|
210 } |
|
211 |
|
212 CSifRefGetComponentInfoTask::CSifRefGetComponentInfoTask(TTransportTaskParams& aParams) |
|
213 : CSifTransportTask(aParams, EFalse), iStep(EExtractEmbeddedPkgs) |
|
214 { |
|
215 } |
|
216 |
|
217 CSifRefGetComponentInfoTask::~CSifRefGetComponentInfoTask() |
|
218 { |
|
219 DEBUG_PRINTF(_L8("CSifRefGetComponentInfoTask::~CSifRefGetComponentInfoTask()")); |
|
220 |
|
221 iFile.Close(); |
|
222 iFs.Close(); |
|
223 iScr.Close(); |
|
224 iSts.Close(); |
|
225 iEmbeddedComponents.Close(); |
|
226 if (iSifRequestInProgress) |
|
227 { |
|
228 iSif.CancelOperation(); |
|
229 } |
|
230 iSif.Close(); |
|
231 delete iParser; |
|
232 delete iComponentInfo; |
|
233 } |
|
234 |
|
235 TBool CSifRefGetComponentInfoTask::ExecuteImplL() |
|
236 { |
|
237 DEBUG_PRINTF2(_L8("Exiting from CSifRefGetComponentInfoTask::ExecuteImplL(), iStep = %d"), iStep); |
|
238 |
|
239 TBool done = EFalse; |
|
240 |
|
241 switch (iStep) |
|
242 { |
|
243 case EExtractEmbeddedPkgs: |
|
244 ExtractEmbeddedPkgsL(); |
|
245 ++iStep; |
|
246 break; |
|
247 |
|
248 case EParsePkgFile: |
|
249 iStep = ParsePkgFileL(); |
|
250 break; |
|
251 |
|
252 case EFindComponent: |
|
253 InstallHelper::FindComponentL(iScr, iCompSearchData, *iParser); |
|
254 ++iStep; |
|
255 break; |
|
256 |
|
257 case ECreateComponentInfoNode: |
|
258 iStep = CreateComponentInfoNodeL(); |
|
259 break; |
|
260 |
|
261 case ESetComponentInfo: |
|
262 SetComponentInfoL(); |
|
263 done = ETrue; |
|
264 break; |
|
265 |
|
266 default: |
|
267 User::Leave(KErrGeneral); |
|
268 } |
|
269 |
|
270 if (!iSifRequestInProgress) |
|
271 { |
|
272 TRequestStatus* status(RequestStatus()); |
|
273 User::RequestComplete(status, KErrNone); |
|
274 } |
|
275 |
|
276 DEBUG_PRINTF3(_L8("Exiting from CSifRefGetComponentInfoTask::ExecuteImplL(), done = %d, iStep = %d"), done, iStep); |
|
277 |
|
278 return done; |
|
279 } |
|
280 |
|
281 void CSifRefGetComponentInfoTask::ExtractEmbeddedPkgsL() |
|
282 { |
|
283 DEBUG_PRINTF(_L8("CSifRefGetComponentInfoTask::ExtractEmbeddedPkgsL()")); |
|
284 |
|
285 // Start an STS transaction. The extraction of a package requires creation of temporary |
|
286 // files that must be deleted when the GetComponentInfo requiest is complete. This is why |
|
287 // we need this STS transaction here. |
|
288 iSts.CreateTransactionL(); |
|
289 |
|
290 if (FileName()) |
|
291 { |
|
292 SifRefBinPkgExtractor::BuildPkgTreeL(iSts, *FileName(), KRefInstPrivateDir, iEmbeddedComponents); |
|
293 } |
|
294 else if (FileHandle()) |
|
295 { |
|
296 SifRefBinPkgExtractor::BuildPkgTreeL(iSts, *FileHandle(), KRefInstPrivateDir, iEmbeddedComponents); |
|
297 } |
|
298 else |
|
299 { |
|
300 ASSERT(0); |
|
301 } |
|
302 |
|
303 // Connect to the SCR. The installer needs this session to check if a component being queried |
|
304 // is already installed and, if yes, obtain its detials. |
|
305 User::LeaveIfError(iScr.Connect()); |
|
306 } |
|
307 |
|
308 TInt CSifRefGetComponentInfoTask::ParsePkgFileL() |
|
309 { |
|
310 DEBUG_PRINTF(_L8("CSifRefGetComponentInfoTask::ParsePkgFileL()")); |
|
311 |
|
312 delete iParser; |
|
313 iParser = NULL; |
|
314 |
|
315 // Check if the next component is of the type our installer supports. If yes, add it to the list of |
|
316 // the components to be processed. If not, use the SIF API to obtain its details. |
|
317 const SifRefBinPkgExtractor::CAuxNode& node = *iEmbeddedComponents[iCurrentComponent]; |
|
318 if (node.Foreign()) |
|
319 { |
|
320 // Connect to the SIF server |
|
321 iComponentInfo = CComponentInfo::NewL(); |
|
322 User::LeaveIfError(iSif.Connect()); |
|
323 |
|
324 // Our installer keeps temporary files under its private folder and therefore we have to |
|
325 // pass a file handle to the SIF API. |
|
326 User::LeaveIfError(iFs.Connect()); |
|
327 iFs.ShareProtected(); |
|
328 User::LeaveIfError(iFile.Open(iFs, node.FileNameL(), EFileShareReadersOnly)); |
|
329 |
|
330 // Submit a SIF request |
|
331 iSif.GetComponentInfo(iFile, *iComponentInfo, *RequestStatus()); |
|
332 |
|
333 iSifRequestInProgress = ETrue; |
|
334 |
|
335 return ECreateComponentInfoNode; |
|
336 } |
|
337 else |
|
338 { |
|
339 iParser = CSifRefPkgParser::NewL(node.FileNameL()); |
|
340 return EFindComponent; |
|
341 } |
|
342 } |
|
343 |
|
344 TInt CSifRefGetComponentInfoTask::CreateComponentInfoNodeL() |
|
345 { |
|
346 DEBUG_PRINTF(_L8("CSifRefGetComponentInfoTask::CreateComponentInfoNodeL()")); |
|
347 |
|
348 SifRefBinPkgExtractor::CAuxNode& auxNode = *iEmbeddedComponents[iCurrentComponent]; |
|
349 |
|
350 if (iSifRequestInProgress) |
|
351 { |
|
352 iSif.Close(); |
|
353 iFile.Close(); |
|
354 iFs.Close(); |
|
355 |
|
356 iSifRequestInProgress = EFalse; |
|
357 |
|
358 // Add the root node of iComponentInfo to the tree |
|
359 User::LeaveIfError(RequestStatus()->Int()); |
|
360 auxNode.SetCompInfoL(iComponentInfo); |
|
361 iComponentInfo = NULL; |
|
362 } |
|
363 else |
|
364 { |
|
365 // This reference installer uses the KExampleFileSize const value to calculate the maximum size of the installed |
|
366 // component on a phone. This is because the reference package file carries only the list of the files to be installed |
|
367 // without the files themselves. A real installer should use the size of the files to be installed. |
|
368 const TInt KExampleFileSize = 1024; |
|
369 const TInt maxInstalledSize = iParser->Files().Count() * KExampleFileSize; |
|
370 const TBool hasExe = EFalse; |
|
371 // The example capabilities below are hardcoded due to the same reason. The reference package file doesn't contain |
|
372 // user grantable capabilities but a real package file should provide them. |
|
373 TCapabilitySet userGrantableCaps(ECapabilityReadUserData, ECapabilityWriteUserData); |
|
374 |
|
375 // Create a ComponentInfo node and set it as a root node. |
|
376 CComponentInfo::CNode* compInfoNode = CComponentInfo::CNode::NewLC(InstallHelper::KSifReferenceSoftwareType, |
|
377 *iCompSearchData.iName, iCompSearchData.iVersion, *iCompSearchData.iVendor, |
|
378 iCompSearchData.iScomoState, iCompSearchData.iInstallStatus, iCompSearchData.iComponentId, |
|
379 *iCompSearchData.iName, ENotAuthenticated, userGrantableCaps, maxInstalledSize, hasExe); |
|
380 |
|
381 auxNode.SetNodeL(compInfoNode); |
|
382 CleanupStack::Pop(compInfoNode); |
|
383 } |
|
384 |
|
385 return (++iCurrentComponent < iEmbeddedComponents.Count()) ? EParsePkgFile : ESetComponentInfo; |
|
386 } |
|
387 |
|
388 void CSifRefGetComponentInfoTask::SetComponentInfoL() |
|
389 { |
|
390 DEBUG_PRINTF(_L8("CSifRefGetComponentInfoTask::SetComponentInfoL()")); |
|
391 |
|
392 // At least one node must exist, otherwise we can't reach this point. |
|
393 ASSERT (iEmbeddedComponents.Count() > 0); |
|
394 |
|
395 // Build a real tree of the nodes from iEmbeddedComponents which is a flat list |
|
396 for (TInt i=iEmbeddedComponents.Count()-1; i>=1; --i) |
|
397 { |
|
398 iEmbeddedComponents[i]->RegisterChildToParentL(); |
|
399 } |
|
400 |
|
401 // Set the tree built above as the root node of ComponentInfo(). |
|
402 iEmbeddedComponents[0]->SetAsRootNodeL(*ComponentInfo()); |
|
403 } |
|
404 |
|
405 // ============================================================================================================= |
|
406 |
|
407 CSifRefInstallTask* CSifRefInstallTask::NewL(TTransportTaskParams& aParams, TInstallerUIHandlerFactory aUiHandlerFactory) |
|
408 { |
|
409 DEBUG_PRINTF(_L8("CSifRefInstallTask::NewL()")); |
|
410 |
|
411 CSifRefInstallTask* self = new (ELeave) CSifRefInstallTask(aParams); |
|
412 CleanupStack::PushL(self); |
|
413 self->ConstructL(aUiHandlerFactory); |
|
414 CleanupStack::Pop(self); |
|
415 return self; |
|
416 } |
|
417 |
|
418 CSifRefInstallTask::CSifRefInstallTask(TTransportTaskParams& aParams) |
|
419 : CSifTransportTask(aParams, EFalse), iStep(EExtractEmbeddedPkgs) |
|
420 { |
|
421 } |
|
422 |
|
423 CSifRefInstallTask::~CSifRefInstallTask() |
|
424 { |
|
425 DEBUG_PRINTF(_L8("CSifRefInstallTask::~CSifRefInstallTask()")); |
|
426 |
|
427 iFileList.Close(); |
|
428 iFile.Close(); |
|
429 iFs.Close(); |
|
430 iScr.Close(); |
|
431 iSts.Close(); |
|
432 iEmbeddedComponents.Close(); |
|
433 if (iSifRequestInProgress) |
|
434 { |
|
435 iSif.CancelOperation(); |
|
436 } |
|
437 iSif.Close(); |
|
438 delete iParser; |
|
439 delete iUiHandler; |
|
440 delete iOpaqueArguments; |
|
441 delete iOpaqueResults; |
|
442 } |
|
443 |
|
444 void CSifRefInstallTask::ConstructL(TInstallerUIHandlerFactory aUiHandlerFactory) |
|
445 { |
|
446 if ((FileName() == NULL && FileHandle() == NULL) || |
|
447 CustomArguments() == NULL || |
|
448 CustomResults() == NULL) |
|
449 { |
|
450 User::Leave(KErrArgument); |
|
451 } |
|
452 |
|
453 iUiHandler = InstallHelper::CreateUiHandlerL(CustomArguments(), aUiHandlerFactory); |
|
454 } |
|
455 |
|
456 TBool CSifRefInstallTask::ExecuteImplL() |
|
457 { |
|
458 DEBUG_PRINTF2(_L8("Exiting from CSifRefInstallTask::ExecuteImplL(), iStep = %d"), iStep); |
|
459 |
|
460 TBool done = EFalse; |
|
461 |
|
462 switch (iStep) |
|
463 { |
|
464 case EExtractEmbeddedPkgs: |
|
465 ExtractEmbeddedPkgsL(); |
|
466 ++iStep; |
|
467 break; |
|
468 |
|
469 case EParsePkgFile: |
|
470 iStep = ParsePkgFileL(); |
|
471 break; |
|
472 |
|
473 case ELaunchForeignInstall: |
|
474 LaunchForeignInstallL(); |
|
475 ++iStep; |
|
476 break; |
|
477 |
|
478 case EFinishForeignInstall: |
|
479 FinishForeignInstallL(); |
|
480 iStep = EParsePkgFile; |
|
481 break; |
|
482 |
|
483 case EFindAndCheckComponent: |
|
484 // Next step differs for ENewComponent and EUpgrade |
|
485 iStep = FindAndCheckComponentL(); |
|
486 break; |
|
487 |
|
488 case EGetInstalledFileList: |
|
489 GetInstalledFileListL(); |
|
490 ++iStep; |
|
491 break; |
|
492 |
|
493 case EUnregisterAndDeleteFile: |
|
494 if (UnregisterAndDeleteFileL()) |
|
495 { |
|
496 ++iStep; |
|
497 } |
|
498 break; |
|
499 |
|
500 case ERegisterComponent: |
|
501 RegisterComponentL(); |
|
502 ++iStep; |
|
503 break; |
|
504 |
|
505 case ECopyFile: |
|
506 if (CopyFileL()) |
|
507 { |
|
508 ++iStep; |
|
509 } |
|
510 break; |
|
511 |
|
512 case ESetScomoState: |
|
513 iStep = SetScomoStateL(); |
|
514 break; |
|
515 |
|
516 case ECommit: |
|
517 CommitL(); |
|
518 done = ETrue; |
|
519 break; |
|
520 |
|
521 default: |
|
522 User::Leave(KErrGeneral); |
|
523 } |
|
524 |
|
525 if (!iSifRequestInProgress) |
|
526 { |
|
527 TRequestStatus* status(RequestStatus()); |
|
528 User::RequestComplete(status, KErrNone); |
|
529 } |
|
530 |
|
531 DEBUG_PRINTF3(_L8("Exiting from CSifRefInstallTask::ExecuteImplL(), done = %d, iStep = %d"), done, iStep); |
|
532 |
|
533 return done; |
|
534 } |
|
535 |
|
536 namespace |
|
537 { |
|
538 TInt AuxNodeSorter(const SifRefBinPkgExtractor::CAuxNode& aLeft, const SifRefBinPkgExtractor::CAuxNode& aRight) |
|
539 { |
|
540 const TBool l = aLeft.Foreign(); |
|
541 const TBool r = aRight.Foreign(); |
|
542 if (l == r) |
|
543 { |
|
544 return 0; |
|
545 } |
|
546 else if (!l && r) |
|
547 { |
|
548 return 1; |
|
549 } |
|
550 else |
|
551 { |
|
552 return -1; |
|
553 } |
|
554 } |
|
555 } |
|
556 |
|
557 void CSifRefInstallTask::ExtractEmbeddedPkgsL() |
|
558 { |
|
559 DEBUG_PRINTF(_L8("CSifRefInstallTask::ExtractEmbeddedPkgsL()")); |
|
560 |
|
561 // Start an STS transaction |
|
562 iSts.CreateTransactionL(); |
|
563 |
|
564 if (FileName()) |
|
565 { |
|
566 SifRefBinPkgExtractor::BuildPkgTreeL(iSts, *FileName(), KRefInstPrivateDir, iEmbeddedComponents); |
|
567 } |
|
568 else if (FileHandle()) |
|
569 { |
|
570 SifRefBinPkgExtractor::BuildPkgTreeL(iSts, *FileHandle(), KRefInstPrivateDir, iEmbeddedComponents); |
|
571 } |
|
572 else |
|
573 { |
|
574 ASSERT(0); |
|
575 } |
|
576 |
|
577 // Sort the list of the embedded components in order to install foreign packages first |
|
578 const TLinearOrder<SifRefBinPkgExtractor::CAuxNode> sortOrder(AuxNodeSorter); |
|
579 iEmbeddedComponents.Sort(sortOrder); |
|
580 } |
|
581 |
|
582 TInt CSifRefInstallTask::ParsePkgFileL() |
|
583 { |
|
584 DEBUG_PRINTF(_L8("CSifRefInstallTask::ParsePkgFileL()")); |
|
585 |
|
586 TInt nextStep = -1; |
|
587 TRAPD(err, nextStep = ParsePkgFileImplL()); |
|
588 if (err != KErrNone) |
|
589 { |
|
590 if (iUiHandler) |
|
591 { |
|
592 iUiHandler->ErrorDescriptionUIHandler(InstallHelper::KUiParserErrorDesc); |
|
593 } |
|
594 User::Leave(err); |
|
595 } |
|
596 |
|
597 return nextStep; |
|
598 } |
|
599 |
|
600 TInt CSifRefInstallTask::ParsePkgFileImplL() |
|
601 { |
|
602 DEBUG_PRINTF(_L8("CSifRefInstallTask::ParsePkgFileImplL()")); |
|
603 |
|
604 delete iParser; |
|
605 iParser = NULL; |
|
606 |
|
607 // Check if the next component is of the type our installer supports. If yes, add it to the list of |
|
608 // the components to be processed. If not, use the SIF API to install it. |
|
609 const SifRefBinPkgExtractor::CAuxNode& node = *iEmbeddedComponents[iCurrentComponent]; |
|
610 if (node.Foreign()) |
|
611 { |
|
612 return ELaunchForeignInstall; |
|
613 } |
|
614 else |
|
615 { |
|
616 iParser = CSifRefPkgParser::NewL(node.FileNameL()); |
|
617 return EFindAndCheckComponent; |
|
618 } |
|
619 } |
|
620 |
|
621 void CSifRefInstallTask::LaunchForeignInstallL() |
|
622 { |
|
623 DEBUG_PRINTF(_L8("CSifRefInstallTask::LaunchForeignInstallL()")); |
|
624 |
|
625 const SifRefBinPkgExtractor::CAuxNode& node = *iEmbeddedComponents[iCurrentComponent]; |
|
626 |
|
627 // Connect to the SIF server |
|
628 User::LeaveIfError(iSif.Connect()); |
|
629 |
|
630 // Our installer keeps temporary files under its private folder and therefore we have to |
|
631 // pass a file handle to the SIF API. |
|
632 User::LeaveIfError(iFs.Connect()); |
|
633 iFs.ShareProtected(); |
|
634 User::LeaveIfError(iFile.Open(iFs, node.FileNameL(), EFileShareReadersOnly)); |
|
635 |
|
636 // Submit a SIF request |
|
637 iOpaqueArguments = COpaqueNamedParams::NewL(); |
|
638 iOpaqueResults = COpaqueNamedParams::NewL(); |
|
639 iSif.Install(iFile, *iOpaqueArguments, *iOpaqueResults, *RequestStatus(), EFalse); |
|
640 |
|
641 iSifRequestInProgress = ETrue; |
|
642 } |
|
643 |
|
644 void CSifRefInstallTask::FinishForeignInstallL() |
|
645 { |
|
646 DEBUG_PRINTF(_L8("CSifRefInstallTask::FinishForeignInstallL()")); |
|
647 |
|
648 iSif.Close(); |
|
649 iFile.Close(); |
|
650 iFs.Close(); |
|
651 delete iOpaqueArguments; |
|
652 iOpaqueArguments = NULL; |
|
653 delete iOpaqueResults; |
|
654 iOpaqueResults = NULL; |
|
655 |
|
656 // Check the result of the concurrent installation |
|
657 iSifRequestInProgress = EFalse; |
|
658 User::LeaveIfError(RequestStatus()->Int()); |
|
659 |
|
660 // There must be at least one component left because we install foreign components first |
|
661 ++iCurrentComponent; |
|
662 } |
|
663 |
|
664 TInt CSifRefInstallTask::FindAndCheckComponentL() |
|
665 { |
|
666 DEBUG_PRINTF(_L8("CSifRefInstallTask::FindAndCheckComponentL()")); |
|
667 |
|
668 // Connect to the SCR and create a new transaction to continue the installation of our own type |
|
669 if (!iScrTransaction) |
|
670 { |
|
671 User::LeaveIfError(iScr.Connect()); |
|
672 iScr.CreateTransactionL(); |
|
673 iScrTransaction = ETrue; |
|
674 } |
|
675 |
|
676 // Exit code |
|
677 TInt nextStep = ERegisterComponent; |
|
678 |
|
679 // Check if already installed |
|
680 InstallHelper::FindComponentL(iScr, iCompSearchData, *iParser); |
|
681 switch (iCompSearchData.iInstallStatus) |
|
682 { |
|
683 case ENewComponent: |
|
684 // nextStep already set to ERegisterComponent |
|
685 break; |
|
686 |
|
687 case EUpgrade: |
|
688 // Uninstall the previous version |
|
689 nextStep = EGetInstalledFileList; |
|
690 break; |
|
691 |
|
692 case EAlreadyInstalled: |
|
693 User::Leave(KErrSifSameVersionAlreadyInstalled); |
|
694 break; |
|
695 |
|
696 case ENewerVersionAlreadyInstalled: |
|
697 User::Leave(KErrSifNewerVersionAlreadyInstalled); |
|
698 break; |
|
699 |
|
700 default: |
|
701 ASSERT(0); |
|
702 } |
|
703 |
|
704 // Ask the user for the confirmation |
|
705 if (iUiHandler != NULL) |
|
706 { |
|
707 userConfirmationL(iCompSearchData.iInstallStatus == ENewComponent ? InstallHelper::EConfirmationInstall : InstallHelper::EConfirmationUpgrade, *iUiHandler, *iCompSearchData.iName, *iCompSearchData.iVendor); |
|
708 } |
|
709 |
|
710 return nextStep; |
|
711 } |
|
712 |
|
713 void CSifRefInstallTask::GetInstalledFileListL() |
|
714 { |
|
715 DEBUG_PRINTF(_L8("CSifRefInstallTask::GetInstalledFileListL()")); |
|
716 |
|
717 // Get a list of files to be deleted |
|
718 iFileList.OpenListL(iScr, iCompSearchData.iComponentId); |
|
719 } |
|
720 |
|
721 TBool CSifRefInstallTask::UnregisterAndDeleteFileL() |
|
722 { |
|
723 DEBUG_PRINTF(_L8("CSifRefInstallTask::UnregisterAndDeleteFileL()")); |
|
724 |
|
725 return InstallHelper::UnregisterAndDeleteFileL(iScr, iFileList, iSts, iCompSearchData.iComponentId); |
|
726 } |
|
727 |
|
728 void CSifRefInstallTask::RegisterComponentL() |
|
729 { |
|
730 DEBUG_PRINTF(_L8("CSifRefInstallTask::RegisterComponentL()")); |
|
731 |
|
732 // Register a new component in the SCR |
|
733 RCPointerArray<CLocalizableComponentInfo> componentInfoArray; |
|
734 CleanupClosePushL(componentInfoArray); |
|
735 |
|
736 // ...for each language |
|
737 const RLanguageArray& languages = iParser->Languages(); |
|
738 const TInt langCount = languages.Count(); |
|
739 for (TInt i=0; i<langCount; ++i) |
|
740 { |
|
741 const TDesC& locName = *iParser->ComponentNames()[i]; |
|
742 const TDesC& locVendor = *iParser->VendorNames()[i]; |
|
743 CLocalizableComponentInfo* componentInfo = CLocalizableComponentInfo::NewLC(locName, locVendor, languages[i]); |
|
744 componentInfoArray.AppendL(componentInfo); |
|
745 CleanupStack::Pop(componentInfo); |
|
746 } |
|
747 iCompSearchData.iComponentId = iScr.AddComponentL(componentInfoArray, InstallHelper::KSifReferenceSoftwareType); |
|
748 |
|
749 // Set the version of a new component |
|
750 iScr.SetComponentVersionL(iCompSearchData.iComponentId, iCompSearchData.iVersion); |
|
751 |
|
752 CleanupStack::PopAndDestroy(&componentInfoArray); |
|
753 |
|
754 iCopyFileIndex = 0; |
|
755 iComponentSize = 0; |
|
756 |
|
757 // Send the id if the installed component to the client. If this is a compound package we send the id of the root component only. |
|
758 if (iEmbeddedComponents[iCurrentComponent]->Root()) |
|
759 { |
|
760 CustomResults()->AddIntL(KSifOutParam_ComponentId, iCompSearchData.iComponentId); |
|
761 } |
|
762 } |
|
763 |
|
764 namespace |
|
765 { |
|
766 TBool CheckPathExistenceL(const TDesC& filePath) |
|
767 { |
|
768 TBool exists = EFalse; |
|
769 |
|
770 RFs fs; |
|
771 User::LeaveIfError(fs.Connect()); |
|
772 CleanupClosePushL(fs); |
|
773 TEntry entry; |
|
774 TInt error = fs.Entry(filePath, entry); |
|
775 if (error == KErrNone) |
|
776 { |
|
777 exists = ETrue; |
|
778 } |
|
779 else if (error != KErrPathNotFound && error != KErrNotFound) |
|
780 { |
|
781 User::Leave(error); |
|
782 } |
|
783 |
|
784 CleanupStack::PopAndDestroy(&fs); |
|
785 |
|
786 return exists; |
|
787 } |
|
788 } |
|
789 |
|
790 TBool CSifRefInstallTask::CopyFileL() |
|
791 { |
|
792 DEBUG_PRINTF(_L8("CSifRefInstallTask::CopyFileL()")); |
|
793 |
|
794 // List of files to be copied from a package file |
|
795 const RCHBufCArray& files = iParser->Files(); |
|
796 |
|
797 // Register and copy a file if any left |
|
798 if (iCopyFileIndex < files.Count()) |
|
799 { |
|
800 // The name of the current file |
|
801 const TDesC& filePath = *files[iCopyFileIndex]; |
|
802 |
|
803 // Check if filePath already exists |
|
804 if (CheckPathExistenceL(filePath)) |
|
805 { |
|
806 // Add a custom result describing the error |
|
807 HBufC* desc = HBufC::NewLC(InstallHelper::KErrFileAlreadyExists.iTypeLength + filePath.Length()); |
|
808 TPtr bufDesc = desc->Des(); |
|
809 bufDesc.Copy(InstallHelper::KErrFileAlreadyExists); |
|
810 bufDesc.Copy(filePath); |
|
811 CustomResults()->AddStringL(InstallHelper::KParamNameErrDesc, *desc); |
|
812 CleanupStack::PopAndDestroy(desc); |
|
813 } |
|
814 |
|
815 // Register the file in the SCR |
|
816 iScr.RegisterComponentFileL(iCompSearchData.iComponentId, filePath); |
|
817 |
|
818 // Copy the current file |
|
819 RFile file; |
|
820 iSts.CreateNewL(filePath, file, TFileMode(EFileShareExclusive |EFileWrite)); |
|
821 _LIT8(KReferenceFootprint, "This file belongs to the SIF reference component.\n"); |
|
822 const TInt numLines = 100; // The operation must take a while to simulate real copying |
|
823 for (TInt i=0; i<numLines; ++i) |
|
824 { |
|
825 User::LeaveIfError(file.Write(KReferenceFootprint)); |
|
826 } |
|
827 iComponentSize += KReferenceFootprint.iTypeLength*numLines; |
|
828 file.Close(); |
|
829 |
|
830 ++iCopyFileIndex; |
|
831 } |
|
832 else |
|
833 { |
|
834 // Set the size of the component in the SCR |
|
835 iScr.SetComponentSizeL(iCompSearchData.iComponentId, iComponentSize); |
|
836 |
|
837 // Step complete, all the files have been copied |
|
838 return ETrue; |
|
839 } |
|
840 |
|
841 // Step not complete, there are still files left |
|
842 |
|
843 DEBUG_PRINTF(_L8("Exiting from CSifRefInstallTask::CopyFileL()")); |
|
844 |
|
845 return EFalse; |
|
846 } |
|
847 |
|
848 TInt CSifRefInstallTask::SetScomoStateL() |
|
849 { |
|
850 DEBUG_PRINTF(_L8("CSifRefInstallTask::SetScomoStateL()")); |
|
851 |
|
852 // Activate the newly added component |
|
853 TInt inactive = EFalse; |
|
854 if (!CustomArguments()->GetIntByNameL(_L("InstallInactive"), inactive) || !inactive) |
|
855 { |
|
856 iScr.SetScomoStateL(iCompSearchData.iComponentId, EActivated); |
|
857 } |
|
858 |
|
859 // Check if there are any components to be installed left |
|
860 return (++iCurrentComponent < iEmbeddedComponents.Count()) ? EParsePkgFile : ECommit; |
|
861 } |
|
862 |
|
863 void CSifRefInstallTask::CommitL() |
|
864 { |
|
865 DEBUG_PRINTF(_L8("CSifRefInstallTask::CommitL()")); |
|
866 |
|
867 // Commit the STS & SCR transactions |
|
868 iSts.CommitL(); |
|
869 iScr.CommitTransactionL(); |
|
870 } |
|
871 |
|
872 // ============================================================================================================= |
|
873 |
|
874 CSifRefUninstallTask* CSifRefUninstallTask::NewL(TTransportTaskParams& aParams, TInstallerUIHandlerFactory aUiHandlerFactory) |
|
875 { |
|
876 DEBUG_PRINTF(_L8("CSifRefUninstallTask::NewL()")); |
|
877 |
|
878 CSifRefUninstallTask* self = new (ELeave) CSifRefUninstallTask(aParams); |
|
879 CleanupStack::PushL(self); |
|
880 self->ConstructL(aUiHandlerFactory); |
|
881 CleanupStack::Pop(self); |
|
882 return self; |
|
883 } |
|
884 |
|
885 CSifRefUninstallTask::CSifRefUninstallTask(TTransportTaskParams& aParams) |
|
886 : CSifTransportTask(aParams), iStep(EGetFileList) |
|
887 { |
|
888 } |
|
889 |
|
890 void CSifRefUninstallTask::ConstructL(TInstallerUIHandlerFactory aUiHandlerFactory) |
|
891 { |
|
892 if (ComponentId() == NULL || CustomArguments() == NULL || CustomResults() == NULL) |
|
893 { |
|
894 User::Leave(KErrArgument); |
|
895 } |
|
896 |
|
897 iUiHandler = InstallHelper::CreateUiHandlerL(CustomArguments(), aUiHandlerFactory); |
|
898 } |
|
899 |
|
900 CSifRefUninstallTask::~CSifRefUninstallTask() |
|
901 { |
|
902 DEBUG_PRINTF(_L8("CSifRefUninstallTask::~CSifRefUninstallTask()")); |
|
903 |
|
904 // Make sure to close sub-session before the session |
|
905 iFileList.Close(); |
|
906 iScr.Close(); |
|
907 iSts.Close(); |
|
908 delete iUiHandler; |
|
909 } |
|
910 |
|
911 TBool CSifRefUninstallTask::ExecuteImplL() |
|
912 { |
|
913 DEBUG_PRINTF2(_L8("CSifRefInstallTask::ExecuteImplL(), iStep = %d"), iStep); |
|
914 |
|
915 switch (iStep) |
|
916 { |
|
917 case EGetFileList: |
|
918 GetFileListL(); |
|
919 break; |
|
920 |
|
921 case EUnregisterAndDeleteFile: |
|
922 if (!UnregisterAndDeleteFileL()) |
|
923 { |
|
924 return EFalse; |
|
925 } |
|
926 break; |
|
927 |
|
928 case ECommit: |
|
929 CommitL(); |
|
930 return ETrue; |
|
931 |
|
932 default: |
|
933 User::Leave(KErrGeneral); |
|
934 } |
|
935 |
|
936 ++iStep; |
|
937 |
|
938 DEBUG_PRINTF2(_L8("Exiting from CSifRefInstallTask::ExecuteImplL(), iStep = %d"), iStep); |
|
939 |
|
940 return EFalse; |
|
941 } |
|
942 |
|
943 void CSifRefUninstallTask::GetFileListL() |
|
944 { |
|
945 DEBUG_PRINTF(_L8("CSifRefUninstallTask::GetFileListL()")); |
|
946 |
|
947 // Connect to the SCR and start a transaction |
|
948 User::LeaveIfError(iScr.Connect()); |
|
949 iScr.CreateTransactionL(); |
|
950 |
|
951 // Ask the user for confirmation |
|
952 if (iUiHandler != NULL) |
|
953 { |
|
954 CComponentEntry* entry = CComponentEntry::NewLC(); |
|
955 if (!iScr.GetComponentL(ComponentId(), *entry)) |
|
956 { |
|
957 User::Leave(KErrNotFound); |
|
958 } |
|
959 userConfirmationL(InstallHelper::EConfirmationUninstall, *iUiHandler, entry->Name(), entry->Vendor()); |
|
960 CleanupStack::PopAndDestroy(entry); |
|
961 } |
|
962 |
|
963 // Get a list of files to be deleted |
|
964 iFileList.OpenListL(iScr, ComponentId()); |
|
965 |
|
966 // Start an STS transaction |
|
967 iSts.CreateTransactionL(); |
|
968 } |
|
969 |
|
970 TBool CSifRefUninstallTask::UnregisterAndDeleteFileL() |
|
971 { |
|
972 DEBUG_PRINTF(_L8("CSifRefUninstallTask::UnregisterAndDeleteFileL()")); |
|
973 |
|
974 return InstallHelper::UnregisterAndDeleteFileL(iScr, iFileList, iSts, ComponentId()); |
|
975 } |
|
976 |
|
977 void CSifRefUninstallTask::CommitL() |
|
978 { |
|
979 DEBUG_PRINTF(_L8("CSifRefUninstallTask::CommitL()")); |
|
980 |
|
981 // Commit the STS & SCR transactions |
|
982 iSts.CommitL(); |
|
983 iScr.CommitTransactionL(); |
|
984 } |
|
985 |
|
986 // ============================================================================================================= |
|
987 |
|
988 CSifRefActivateDeactivateTask::CSifRefActivateDeactivateTask(TTransportTaskParams& aParams, TScomoState aScomoState) |
|
989 : CSifTransportTask(aParams), iScomoState(aScomoState) |
|
990 { |
|
991 DEBUG_PRINTF(_L8("CSifRefActivateDeactivateTask::CSifRefActivateDeactivateTask()")); |
|
992 } |
|
993 |
|
994 CSifRefActivateDeactivateTask::~CSifRefActivateDeactivateTask() |
|
995 { |
|
996 DEBUG_PRINTF(_L8("CSifRefActivateDeactivateTask::~CSifRefActivateDeactivateTask()")); |
|
997 |
|
998 iScr.Close(); |
|
999 } |
|
1000 |
|
1001 TBool CSifRefActivateDeactivateTask::ExecuteImplL() |
|
1002 { |
|
1003 DEBUG_PRINTF(_L8("CSifRefActivateDeactivateTask::ExecuteImplL()")); |
|
1004 |
|
1005 if (ComponentId() == NULL) |
|
1006 { |
|
1007 User::Leave(KErrArgument); |
|
1008 } |
|
1009 |
|
1010 // Connect to SCR and activate/deactivate component |
|
1011 User::LeaveIfError(iScr.Connect()); |
|
1012 iScr.SetScomoStateL(ComponentId(), iScomoState); |
|
1013 |
|
1014 return ETrue; |
|
1015 } |