|
1 /* |
|
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Implements CNcdNodeInstall class |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "ncdnodeinstallimpl.h" |
|
20 |
|
21 #include <f32file.h> |
|
22 #include <s32mem.h> |
|
23 #include <bautils.h> |
|
24 |
|
25 |
|
26 #include "catalogssession.h" |
|
27 #include "catalogsbasemessage.h" |
|
28 #include "ncdnodefunctionids.h" |
|
29 #include "ncdnodeclassids.h" |
|
30 #include "catalogsconstants.h" |
|
31 #include "ncd_pp_dataentity.h" |
|
32 #include "ncd_cp_query.h" |
|
33 #include "catalogsutils.h" |
|
34 #include "ncdutils.h" |
|
35 #include "ncdpurchaseinstallinfo.h" |
|
36 #include "ncdpurchasedetails.h" |
|
37 #include "ncdpurchasehistorydbimpl.h" |
|
38 #include "ncdinstallinfo.h" |
|
39 #include "ncdfileinfo.h" |
|
40 #include "ncdextendedinstallinfo.h" |
|
41 #include "ncdproviderutils.h" |
|
42 #include "ncdinstallationservice.h" |
|
43 #include "ncdnodemetadataimpl.h" |
|
44 #include "ncdnodecontentinfoimpl.h" |
|
45 #include "ncdpanics.h" |
|
46 #include "ncdpurchasehistoryutils.h" |
|
47 #include "ncdproviderdefines.h" |
|
48 #include "ncdnodecontentinfoimpl.h" |
|
49 #include "ncdnodemanager.h" |
|
50 #include "ncdnodeidentifier.h" |
|
51 |
|
52 #include "catalogsdebug.h" |
|
53 |
|
54 |
|
55 // Maximum number of content file opening attempts if the first |
|
56 // one fails with KErrInUse |
|
57 const TInt KMaxRetries = 3; |
|
58 |
|
59 // Delay between content file opening attempts if the first |
|
60 // one fails with KErrInUse |
|
61 const TInt KOpenDelay = 500000; |
|
62 |
|
63 static TInt CallBackOpenFile( TAny* aObject ) |
|
64 { |
|
65 DLTRACEIN(("")); |
|
66 static_cast<CNcdNodeInstall*>( aObject )->OpenContentFileRunner(); |
|
67 return KErrNone; |
|
68 } |
|
69 |
|
70 // --------------------------------------------------------------------------- |
|
71 // CNcdNodeInstall |
|
72 // --------------------------------------------------------------------------- |
|
73 // |
|
74 |
|
75 |
|
76 CNcdNodeInstall::CNcdNodeInstall( NcdNodeClassIds::TNcdNodeClassId aClassId, |
|
77 const CNcdNodeMetaData& aMetadata ) |
|
78 : CCatalogsCommunicable(), |
|
79 iClassId( aClassId ), |
|
80 iMetadata( aMetadata ) |
|
81 { |
|
82 } |
|
83 |
|
84 void CNcdNodeInstall::ConstructL() |
|
85 { |
|
86 DLTRACEIN(("")); |
|
87 iDownloadedFiles = new(ELeave) CDesCArrayFlat( KListGranularity ); |
|
88 DLTRACEOUT(("")); |
|
89 } |
|
90 |
|
91 |
|
92 CNcdNodeInstall* CNcdNodeInstall::NewL( const CNcdNodeMetaData& aMetadata ) |
|
93 { |
|
94 CNcdNodeInstall* self = |
|
95 CNcdNodeInstall::NewLC( aMetadata ); |
|
96 CleanupStack::Pop( self ); |
|
97 return self; |
|
98 } |
|
99 |
|
100 CNcdNodeInstall* CNcdNodeInstall::NewLC( const CNcdNodeMetaData& aMetadata ) |
|
101 { |
|
102 CNcdNodeInstall* self = |
|
103 new( ELeave ) CNcdNodeInstall( |
|
104 NcdNodeClassIds::ENcdNodeInstallClassId, aMetadata ); |
|
105 CleanupClosePushL( *self ); |
|
106 self->ConstructL(); |
|
107 return self; |
|
108 } |
|
109 |
|
110 |
|
111 CNcdNodeInstall::~CNcdNodeInstall() |
|
112 { |
|
113 DLTRACEIN(("")); |
|
114 |
|
115 // Delete member variables here |
|
116 iInstallInfos.ResetAndDestroy(); |
|
117 delete iDownloadedFiles; |
|
118 |
|
119 delete iInstalledContent; |
|
120 delete iPeriodic; |
|
121 |
|
122 DLTRACEOUT(("")); |
|
123 } |
|
124 |
|
125 NcdNodeClassIds::TNcdNodeClassId CNcdNodeInstall::ClassId() const |
|
126 { |
|
127 return iClassId; |
|
128 } |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 // --------------------------------------------------------------------------- |
|
134 // Set node data from purchase details |
|
135 // --------------------------------------------------------------------------- |
|
136 // |
|
137 TBool CNcdNodeInstall::InternalizeL( const MNcdPurchaseDetails& aDetails ) |
|
138 { |
|
139 DLTRACEIN(("this-ptr: %X", this)); |
|
140 |
|
141 if ( !aDetails.DownloadInfoL().Count() ) |
|
142 { |
|
143 DLTRACEOUT(("No downloadinfos so there's nothing to install")); |
|
144 return EFalse; |
|
145 } |
|
146 |
|
147 DLTRACE(("Copying paths of downloaded files")); |
|
148 |
|
149 CDesCArray* tempDownloads = new(ELeave) CDesCArrayFlat( KListGranularity ); |
|
150 CleanupStack::PushL( tempDownloads ); |
|
151 |
|
152 TBool atLeastOneFile = EFalse; |
|
153 // Get names of downloaded files |
|
154 for ( TInt i = 0; i < aDetails.DownloadedFiles().MdcaCount(); ++i ) |
|
155 { |
|
156 const TDesC& filepath( aDetails.DownloadedFiles().MdcaPoint( i ) ); |
|
157 atLeastOneFile = atLeastOneFile || filepath.Length(); |
|
158 |
|
159 // append even empty descriptors so that the arrays stay identical |
|
160 tempDownloads->AppendL( filepath ); |
|
161 |
|
162 DLINFO(( _L("Downloaded: %S"), |
|
163 &aDetails.DownloadedFiles().MdcaPoint( i ) )); |
|
164 } |
|
165 |
|
166 TArray<MNcdPurchaseInstallInfo*> info ( aDetails.InstallInfoL() ); |
|
167 |
|
168 // Check download status |
|
169 if ( !atLeastOneFile && !info.Count() ) |
|
170 { |
|
171 CleanupStack::PopAndDestroy( tempDownloads ); |
|
172 DLINFO(("Nothing has been downloaded or installed")); |
|
173 return EFalse; |
|
174 } |
|
175 |
|
176 TArray<MNcdPurchaseDownloadInfo*> dlInfo ( aDetails.DownloadInfoL() ); |
|
177 |
|
178 |
|
179 DLTRACE(("Internalizing install infos, count: %d", info.Count() )); |
|
180 |
|
181 RPointerArray<CNcdExtendedInstallInfo> tempInfos; |
|
182 CleanupResetAndDestroyPushL( tempInfos ); |
|
183 |
|
184 tempInfos.ReserveL( info.Count() ); |
|
185 iLaunchable = EFalse; |
|
186 |
|
187 CNcdExtendedInstallInfo* tempInstall = NULL; |
|
188 TBool launchable = EFalse; |
|
189 |
|
190 TBool atLeastOneLauncher = EFalse; |
|
191 TBool atLeastOneLaunchableLauncher = EFalse; |
|
192 TBool atLeastOneLauncherOpen = EFalse; |
|
193 |
|
194 // If there are more install infos than download infos we assume that |
|
195 // the first install infos are for rights files |
|
196 TInt dlIndex = dlInfo.Count() - info.Count(); |
|
197 if ( dlIndex > 0 ) |
|
198 { |
|
199 dlIndex = 0; |
|
200 } |
|
201 |
|
202 // Internalize infos |
|
203 for ( TInt i = 0; i < info.Count(); ++i, ++dlIndex ) |
|
204 { |
|
205 const MNcdPurchaseInstallInfo& install( *info[i] ); |
|
206 |
|
207 if ( dlIndex >= 0 ) |
|
208 { |
|
209 const MNcdPurchaseDownloadInfo& download( *dlInfo[dlIndex] ); |
|
210 |
|
211 launchable = download.IsLaunchable(); |
|
212 DLTRACE(("Launchable from purchase history: %d", launchable )); |
|
213 |
|
214 TBool isLauncher = IsOneOf( download.ContentUsage(), |
|
215 MNcdPurchaseDownloadInfo::ELauncher, |
|
216 MNcdPurchaseDownloadInfo::ELauncherOpen ); |
|
217 |
|
218 // Themes are not launchable. This also checks for reinstalled themes |
|
219 if ( install.ThemeName() != KNullDesC || |
|
220 ( install.ThemeName() == KNullDesC && |
|
221 install.ApplicationUid() == TUid::Null() && |
|
222 install.Filename() == KNullDesC ) ) |
|
223 { |
|
224 launchable = EFalse; |
|
225 } |
|
226 // check launcher apps |
|
227 else if ( isLauncher ) |
|
228 { |
|
229 atLeastOneLauncher = ETrue; |
|
230 // Can't use IsContentInstalledL since it uses iInstallInfos-array |
|
231 // which is generated here |
|
232 if ( CNcdProviderUtils::IsApplicationInstalledL( |
|
233 install.ApplicationUid(), |
|
234 install.ApplicationVersion() ) <= ENcdApplicationNotInstalled ) |
|
235 { |
|
236 DLTRACE(("Setting launchable=EFalse")); |
|
237 launchable = EFalse; |
|
238 } |
|
239 else |
|
240 { |
|
241 atLeastOneLaunchableLauncher = ETrue; |
|
242 } |
|
243 } |
|
244 |
|
245 |
|
246 tempInstall = CNcdExtendedInstallInfo::NewLC( install, |
|
247 download.ContentMimeType(), launchable ); |
|
248 |
|
249 tempInstall->SetUriExists( download.ContentUri().Length() != 0 ); |
|
250 // Sets content type to tempInstall according to download's contentUsage |
|
251 SetContentType( *tempInstall, download ); |
|
252 |
|
253 |
|
254 if ( download.ContentUsage() == |
|
255 MNcdPurchaseDownloadInfo::ELauncherOpen ) |
|
256 { |
|
257 atLeastOneLauncherOpen = ETrue; |
|
258 } |
|
259 |
|
260 // Set item as launchable if at least one file is launchable |
|
261 if ( launchable ) |
|
262 { |
|
263 iLaunchable = ETrue; |
|
264 } |
|
265 } |
|
266 else |
|
267 { |
|
268 DLTRACE(("Rights file")); |
|
269 tempInstall = CNcdExtendedInstallInfo::NewLC( install, |
|
270 KNullDesC, ETrue ); |
|
271 } |
|
272 |
|
273 tempInfos.AppendL( tempInstall ); |
|
274 CleanupStack::Pop( tempInstall ); |
|
275 tempInstall = NULL; |
|
276 |
|
277 DLTRACE(("Info added, iInstallInfo count: %d", iInstallInfos.Count() )); |
|
278 } |
|
279 |
|
280 if ( atLeastOneLauncher && !atLeastOneLaunchableLauncher ) |
|
281 { |
|
282 DLTRACE(("No launchable launchers, setting everything unlaunchable")); |
|
283 iLaunchable = EFalse; |
|
284 TInt count = tempInfos.Count(); |
|
285 while ( count-- ) |
|
286 { |
|
287 tempInfos[ count ]->SetLaunchable( EFalse ); |
|
288 } |
|
289 } |
|
290 |
|
291 // There was at least one launcher/open dependency so we need to go through |
|
292 // the install infos and try to find a suitable file for opening |
|
293 if ( atLeastOneLauncherOpen && |
|
294 tempInfos.Count() <= dlInfo.Count() ) |
|
295 { |
|
296 DLTRACE(("Setting launcher param")); |
|
297 TInt count = tempInfos.Count(); |
|
298 |
|
299 for ( TInt i = 0; i < count; ++i ) |
|
300 { |
|
301 const MNcdPurchaseDownloadInfo& download( *dlInfo[ i ] ); |
|
302 if ( download.ContentUsage() == MNcdPurchaseDownloadInfo::ELauncherOpen ) |
|
303 { |
|
304 SetLaunchParameterL( tempInfos, i ); |
|
305 } |
|
306 } |
|
307 } |
|
308 |
|
309 DLTRACE(("Replacing old values with new ones")); |
|
310 |
|
311 |
|
312 // Read installed status |
|
313 iInstalled = ( aDetails.State() == MNcdPurchaseDetails::EStateInstalled ); |
|
314 |
|
315 DLINFO(( "Installed: %d", iInstalled )); |
|
316 |
|
317 // Get purpose |
|
318 iPurpose = aDetails.ItemPurpose(); |
|
319 DLINFO(( "Purpose: %d", iPurpose )); |
|
320 |
|
321 // Replace old values |
|
322 iInstallInfos.ResetAndDestroy(); |
|
323 iInstallInfos = tempInfos; |
|
324 CleanupStack::Pop( &tempInfos ); |
|
325 |
|
326 |
|
327 delete iDownloadedFiles; |
|
328 iDownloadedFiles = tempDownloads; |
|
329 CleanupStack::Pop( tempDownloads ); |
|
330 |
|
331 TInt depCount = DependencyCount( dlInfo ); |
|
332 |
|
333 if ( !iInstalled && |
|
334 depCount && |
|
335 // must be more download infos than just deps |
|
336 dlInfo.Count() > depCount && |
|
337 // install info count must be at least the amount of dlInfos |
|
338 // since deps have equal number of install and dl infos and |
|
339 // all content must have been installed before |
|
340 info.Count() >= dlInfo.Count() ) |
|
341 { |
|
342 iInstalled = ETrue; |
|
343 DLTRACE(("Dependency has already been installed, setting iInstalled to ETrue")); |
|
344 } |
|
345 |
|
346 |
|
347 if ( iInstalledContent ) |
|
348 { |
|
349 DASSERT( iInstalledContent->ApplicationUid() != TUid::Null() ); |
|
350 |
|
351 // Disable launching if protocol says so. |
|
352 // By default apps defined in content info are launchable |
|
353 iInstalledContent->SetLaunchable( iLaunchable ); |
|
354 |
|
355 // Delete iInstalledContent if it is duplicated in purchase history |
|
356 for ( TInt i = 0; i < iInstallInfos.Count(); ++i ) |
|
357 { |
|
358 |
|
359 if ( iInstalledContent->ApplicationUid() == |
|
360 iInstallInfos[i]->ApplicationUid() ) |
|
361 { |
|
362 DLTRACE(("App has been bought and installed")); |
|
363 delete iInstalledContent; |
|
364 iInstalledContent = NULL; |
|
365 break; |
|
366 } |
|
367 } |
|
368 } |
|
369 |
|
370 SetContentVersionL( aDetails.Version() ); |
|
371 DLTRACEOUT(("iLaunchable: %d", iLaunchable)); |
|
372 return ETrue; |
|
373 } |
|
374 |
|
375 |
|
376 void CNcdNodeInstall::ReceiveMessage( MCatalogsBaseMessage* aMessage, |
|
377 TInt aFunctionNumber ) |
|
378 { |
|
379 DLTRACEIN(("this-ptr: %X", this)); |
|
380 |
|
381 DASSERT( aMessage ); |
|
382 |
|
383 // Now, we can be sure that rest of the time iMessage exists. |
|
384 // This member variable is set for the CounterPartLost function. |
|
385 iMessage = aMessage; |
|
386 |
|
387 TInt trapError( KErrNone ); |
|
388 |
|
389 // Check which function is called by the proxy side object. |
|
390 // Function number are located in ncdnodefunctinoids.h file. |
|
391 switch( aFunctionNumber ) |
|
392 { |
|
393 case NcdNodeFunctionIds::ENcdInternalize: |
|
394 // Internalize the proxy side according to the data |
|
395 // of this object. |
|
396 TRAP( trapError, InternalizeRequestL( *aMessage ) ); |
|
397 break; |
|
398 |
|
399 case NcdNodeFunctionIds::ENcdRelease: |
|
400 // The proxy does not want to use this object anymore. |
|
401 // So, release the handle from the session. |
|
402 ReleaseRequest( *aMessage ); |
|
403 break; |
|
404 |
|
405 case NcdNodeFunctionIds::ENcdInstallOpenFile: |
|
406 TRAP( trapError, OpenContentFileL( *aMessage ) ); |
|
407 break; |
|
408 |
|
409 case NcdNodeFunctionIds::ENcdSetApplicationInstalled: |
|
410 TRAP( trapError, SetApplicationInstalledRequestL( *aMessage ) ); |
|
411 break; |
|
412 |
|
413 default: |
|
414 DLERROR(("Unidentified function request")); |
|
415 DASSERT( EFalse ); |
|
416 break; |
|
417 } |
|
418 |
|
419 if ( trapError != KErrNone ) |
|
420 { |
|
421 // Because something went wrong, the complete has not been |
|
422 // yet called for the message. |
|
423 // So, inform the client about the error if the |
|
424 // message is still available. |
|
425 aMessage->CompleteAndRelease( trapError ); |
|
426 } |
|
427 |
|
428 // Because the message should not be used after this, set it NULL. |
|
429 // So, CounterPartLost function will know that no messages are |
|
430 // waiting the response at the moment. |
|
431 if ( !iPeriodic ) |
|
432 { |
|
433 iMessage = NULL; |
|
434 } |
|
435 |
|
436 DLTRACEOUT(("")); |
|
437 } |
|
438 |
|
439 |
|
440 void CNcdNodeInstall::CounterPartLost( const MCatalogsSession& aSession ) |
|
441 { |
|
442 // This function may be called whenever -- when the message is waiting |
|
443 // response or when the message does not exist. |
|
444 // iMessage may be NULL here, because in the end of the |
|
445 // ReceiveMessage it is set to NULL. The life time of the message |
|
446 // ends shortly after CompleteAndRelease is called. |
|
447 if ( iMessage != NULL ) |
|
448 { |
|
449 iMessage->CounterPartLost( aSession ); |
|
450 } |
|
451 } |
|
452 |
|
453 |
|
454 |
|
455 const MDesCArray& CNcdNodeInstall::DownloadedFiles() const |
|
456 { |
|
457 DASSERT( iDownloadedFiles ); |
|
458 return *iDownloadedFiles; |
|
459 } |
|
460 |
|
461 |
|
462 TNcdApplicationStatus CNcdNodeInstall::IsContentInstalledL( |
|
463 TInt aIndex, |
|
464 TBool aIgnoreMissingUri ) |
|
465 { |
|
466 DLTRACEIN(("aIndex: %d", aIndex)); |
|
467 DASSERT( aIndex >= 0 ); |
|
468 |
|
469 if ( aIndex >= ContentCount() ) |
|
470 { |
|
471 DLTRACEOUT(("Index out of range (count = %d), returning EFalse", |
|
472 ContentCount() )); |
|
473 return ENcdApplicationNotInstalled; |
|
474 } |
|
475 |
|
476 CNcdExtendedInstallInfo& info = *iInstallInfos[aIndex]; |
|
477 |
|
478 TNcdApplicationStatus status = ENcdApplicationNotInstalled; |
|
479 |
|
480 if ( info.Filename() != KNullDesC ) |
|
481 { |
|
482 DLTRACE(("Content: file")); |
|
483 if ( BaflUtils::FileExists( |
|
484 CNcdProviderUtils::FileSession(), |
|
485 info.Filename() ) ) |
|
486 { |
|
487 DLTRACE(( _L("File %S exists"), &info.Filename() )); |
|
488 status = ENcdApplicationInstalled; |
|
489 } |
|
490 } |
|
491 else if ( info.ApplicationUid() != TUid::Null() ) |
|
492 { |
|
493 DLTRACE(("Content: application")); |
|
494 if ( aIgnoreMissingUri && !info.UriExists() ) |
|
495 { |
|
496 DLTRACE(("No uri and ignoring missing uris")); |
|
497 status = ENcdApplicationInstalled; |
|
498 } |
|
499 else |
|
500 { |
|
501 status = CNcdProviderUtils::IsApplicationInstalledL( |
|
502 info.ApplicationUid(), |
|
503 info.ApplicationVersion() ); |
|
504 } |
|
505 } |
|
506 else if ( info.ThemeName() != KNullDesC ) |
|
507 { |
|
508 DLTRACE(("Content: theme")); |
|
509 if ( CNcdProviderUtils::InstallationServiceL().IsThemeInstalledL( |
|
510 info.ThemeName() ) ) |
|
511 { |
|
512 status = ENcdApplicationInstalled; |
|
513 } |
|
514 } |
|
515 info.SetInstalledStatus( status ); |
|
516 |
|
517 return status; |
|
518 } |
|
519 |
|
520 |
|
521 TInt CNcdNodeInstall::ContentCount() const |
|
522 { |
|
523 return iInstallInfos.Count(); |
|
524 } |
|
525 |
|
526 |
|
527 TBool CNcdNodeInstall::IsAllContentInstalledL() |
|
528 { |
|
529 DLTRACEIN(("")); |
|
530 |
|
531 for ( TInt i = 0; i < iInstallInfos.Count(); ++i ) |
|
532 { |
|
533 // Don't care whether older or newer version is installed as long as |
|
534 // some version is installed, ignores application that don't have content URIs |
|
535 |
|
536 if ( IsContentInstalledL( i, ETrue ) == ENcdApplicationNotInstalled ) |
|
537 { |
|
538 return EFalse; |
|
539 } |
|
540 } |
|
541 DLTRACEOUT(("All installed")); |
|
542 return ETrue; |
|
543 } |
|
544 |
|
545 |
|
546 // --------------------------------------------------------------------------- |
|
547 // |
|
548 // --------------------------------------------------------------------------- |
|
549 // |
|
550 TBool CNcdNodeInstall::InternalizeContentInfoL() |
|
551 { |
|
552 DLTRACEIN(("")); |
|
553 |
|
554 if ( iInstallInfos.Count() ) |
|
555 { |
|
556 DLTRACEOUT(("Already installed something")); |
|
557 return EFalse; |
|
558 } |
|
559 |
|
560 const CNcdNodeContentInfo* info = NULL; |
|
561 TRAPD( err, info = &iMetadata.ContentInfoL() ); |
|
562 |
|
563 TBool installed = EFalse; |
|
564 if ( err == KErrNone && info->Uid() != TUid::Null() ) |
|
565 { |
|
566 DLINFO(("Uid: %x", info->Uid().iUid )); |
|
567 TNcdApplicationStatus status = |
|
568 CNcdProviderUtils::IsApplicationInstalledL( |
|
569 info->Uid(), |
|
570 info->Version() ); |
|
571 |
|
572 // Application can be older version for it to be considered installed |
|
573 // Upgrade will be available for the user |
|
574 installed = status != ENcdApplicationNotInstalled; |
|
575 |
|
576 delete iInstalledContent; |
|
577 iInstalledContent = NULL; |
|
578 |
|
579 iInstalled = installed; |
|
580 iLaunchable = installed; |
|
581 |
|
582 if ( installed ) |
|
583 { |
|
584 DLTRACE(("Application installed")); |
|
585 CNcdExtendedInstallInfo* install = CNcdExtendedInstallInfo::NewLC(); |
|
586 install->SetApplicationUid( info->Uid() ); |
|
587 |
|
588 // This ensures that CNcdInstalledApplication actually checks the |
|
589 // application's version number when it checks if it's installed |
|
590 // or not |
|
591 install->SetUriExists( ETrue ); |
|
592 |
|
593 // This will be used to determine whether the app is actually installed |
|
594 // or not |
|
595 install->SetApplicationVersionL( info->Version() ); |
|
596 install->SetLaunchable( ETrue ); |
|
597 |
|
598 // don't set because it can mess upgrade handling in |
|
599 // CNcdNodeMetadata::HandleContentUpgradeL |
|
600 iContentVersion = TCatalogsVersion(); |
|
601 |
|
602 iInstalledContent = install; |
|
603 CleanupStack::Pop( install ); |
|
604 } |
|
605 } |
|
606 return installed; |
|
607 } |
|
608 |
|
609 |
|
610 // --------------------------------------------------------------------------- |
|
611 // Content version getter |
|
612 // --------------------------------------------------------------------------- |
|
613 // |
|
614 const TCatalogsVersion& CNcdNodeInstall::ContentVersion() const |
|
615 { |
|
616 return iContentVersion; |
|
617 } |
|
618 |
|
619 |
|
620 |
|
621 void CNcdNodeInstall::InternalizeRequestL( MCatalogsBaseMessage& aMessage ) |
|
622 { |
|
623 DLTRACEIN(("")); |
|
624 |
|
625 CBufBase* buf = CBufFlat::NewL( KBufExpandSize ); |
|
626 CleanupStack::PushL( buf ); |
|
627 |
|
628 RBufWriteStream stream( *buf ); |
|
629 CleanupClosePushL( stream ); |
|
630 |
|
631 |
|
632 // Include all the necessary node data to the stream |
|
633 ExternalizeDataForRequestL( stream ); |
|
634 |
|
635 |
|
636 // Commits data to the stream when closing. |
|
637 CleanupStack::PopAndDestroy( &stream ); |
|
638 |
|
639 |
|
640 // If this leaves, ReceiveMessage will complete the message. |
|
641 // NOTE: that here we expect that the buffer contains at least |
|
642 // some data. So, make sure that ExternalizeDataForRequestL inserts |
|
643 // something to the buffer. |
|
644 aMessage.CompleteAndReleaseL( buf->Ptr( 0 ), KErrNone ); |
|
645 |
|
646 |
|
647 DLTRACE(("Deleting the buf")); |
|
648 CleanupStack::PopAndDestroy( buf ); |
|
649 |
|
650 DLTRACEOUT(("")); |
|
651 } |
|
652 |
|
653 |
|
654 void CNcdNodeInstall::ExternalizeDataForRequestL( RWriteStream& aStream ) |
|
655 { |
|
656 DLTRACEIN(("this-ptr: %X", this)); |
|
657 |
|
658 // Install existed. So, insert info that meta data was found. |
|
659 aStream.WriteInt32L( ClassId() ); |
|
660 |
|
661 // Add additional content to the stream. |
|
662 // Make sure that this matches to the order that is used in the proxy |
|
663 // side when this stream is internalized. |
|
664 // NOTE: Be careful with the 8- and 16-bit descriptors. Remember to check |
|
665 // if the proxy wants the data in 16 or 8 bits? |
|
666 |
|
667 aStream.WriteInt32L( iPurpose ); |
|
668 |
|
669 aStream.WriteInt32L( iInstalled ); |
|
670 |
|
671 aStream.WriteInt32L( iLaunchable ); |
|
672 |
|
673 TInt count = iInstallInfos.Count(); |
|
674 |
|
675 if ( iInstalledContent ) |
|
676 { |
|
677 DLTRACE(("App from content info is installed, adding install info")); |
|
678 aStream.WriteInt32L( count + 1 ); |
|
679 iInstalledContent->ExternalizeL( aStream ); |
|
680 } |
|
681 else |
|
682 { |
|
683 aStream.WriteInt32L( count ); |
|
684 } |
|
685 |
|
686 DLTRACE(("Externalizing infos, count: %d", count )); |
|
687 |
|
688 for ( TInt i = 0; i < count; ++i ) |
|
689 { |
|
690 iInstallInfos[i]->ExternalizeL( aStream ); |
|
691 } |
|
692 |
|
693 DLTRACEOUT(("")); |
|
694 } |
|
695 |
|
696 |
|
697 // --------------------------------------------------------------------------- |
|
698 // Handle release requests |
|
699 // --------------------------------------------------------------------------- |
|
700 // |
|
701 void CNcdNodeInstall::ReleaseRequest( MCatalogsBaseMessage& aMessage ) const |
|
702 { |
|
703 DLTRACEIN(("")); |
|
704 |
|
705 // Decrease the reference count for this object. |
|
706 // When the reference count reaches zero, this object will be destroyed |
|
707 // and removed from the session. |
|
708 MCatalogsSession& requestSession( aMessage.Session() ); |
|
709 TInt handle( aMessage.Handle() ); |
|
710 |
|
711 // Send complete information back to proxy. |
|
712 aMessage.CompleteAndRelease( KErrNone ); |
|
713 |
|
714 // Remove this object from the session. |
|
715 requestSession.RemoveObject( handle ); |
|
716 |
|
717 DLTRACEOUT(("")); |
|
718 } |
|
719 |
|
720 |
|
721 // --------------------------------------------------------------------------- |
|
722 // Opens a content file |
|
723 // --------------------------------------------------------------------------- |
|
724 // |
|
725 void CNcdNodeInstall::OpenContentFileL( MCatalogsBaseMessage& aMessage ) |
|
726 { |
|
727 DLTRACEIN(("")); |
|
728 RBuf8 buf; |
|
729 buf.CreateL( aMessage.InputLength() ); |
|
730 CleanupClosePushL( buf ); |
|
731 User::LeaveIfError( aMessage.ReadInput( buf ) ); |
|
732 |
|
733 // Read the requested file index |
|
734 TInt fileIndex = Des8ToInt( buf ); |
|
735 if ( fileIndex < 0 || fileIndex >= iInstallInfos.Count() ) |
|
736 { |
|
737 DLERROR(( "Index: %d out of range 0-%d", |
|
738 fileIndex, iInstallInfos.Count() )); |
|
739 User::Leave( KErrArgument ); |
|
740 } |
|
741 |
|
742 DLTRACE(( _L("Opening file %S from index: %d"), |
|
743 &iInstallInfos[fileIndex]->Filename(), fileIndex )); |
|
744 |
|
745 iRetryCount = 0; |
|
746 iFileIndex = fileIndex; |
|
747 |
|
748 // Try to open the file |
|
749 TRAPD( err, OpenContentFileL() ); |
|
750 |
|
751 // N-series hackfix: if the file is in use, |
|
752 // retry opening it about 0.5 seconds later |
|
753 if ( err == KErrInUse ) |
|
754 { |
|
755 DLTRACE(("File in use, retry a little bit later")); |
|
756 if ( iPeriodic ) |
|
757 { |
|
758 iPeriodic->Cancel(); |
|
759 } |
|
760 else |
|
761 { |
|
762 iPeriodic = CPeriodic::NewL( 0 ); |
|
763 } |
|
764 TTimeIntervalMicroSeconds32 delay( KOpenDelay ); |
|
765 iPeriodic->Start( delay, delay, TCallBack( CallBackOpenFile, this ) ); |
|
766 } |
|
767 else |
|
768 { |
|
769 User::LeaveIfError( err ); |
|
770 } |
|
771 |
|
772 CleanupStack::PopAndDestroy( &buf ); // buf |
|
773 DLTRACEOUT(("")); |
|
774 } |
|
775 |
|
776 |
|
777 void CNcdNodeInstall::SetApplicationInstalledRequestL( MCatalogsBaseMessage& aMessage ) |
|
778 { |
|
779 DLTRACEIN(("")); |
|
780 |
|
781 // Note! |
|
782 // This function is only meant for the proxy side usage and for |
|
783 // certain specific exception cases. Also, this will only allow |
|
784 // application info updates. For example, themes are not handled here. |
|
785 |
|
786 |
|
787 // Get the data that was sent from the proxy side. |
|
788 HBufC8* input = HBufC8::NewLC( aMessage.InputLength() ); |
|
789 TPtr8 inputPtr = input->Des(); |
|
790 aMessage.ReadInput( inputPtr ); |
|
791 RDesReadStream inputStream( *input ); |
|
792 CleanupClosePushL( inputStream ); |
|
793 |
|
794 TInt errorCode( inputStream.ReadInt32L() ); |
|
795 DLINFO(( "Error code from message: %d", errorCode )); |
|
796 |
|
797 CleanupStack::PopAndDestroy( &inputStream ); |
|
798 CleanupStack::PopAndDestroy( input ); |
|
799 |
|
800 |
|
801 CNcdPurchaseHistoryDb& purchaseHistoryDb( |
|
802 iMetadata.NodeManager().PurchaseHistory() ); |
|
803 |
|
804 CNcdPurchaseDetails* details( |
|
805 NcdPurchaseHistoryUtils::PurchaseDetailsLC( |
|
806 purchaseHistoryDb, |
|
807 iMetadata.Identifier().ClientUid(), |
|
808 iMetadata.Identifier(), |
|
809 EFalse ) ); |
|
810 |
|
811 if ( details == NULL ) |
|
812 { |
|
813 // Because contents have already been downloaded, there should always |
|
814 // be some details available. Because content has been installed, we |
|
815 // suppose that the content is already downloaded also. |
|
816 User::Leave( KErrNotFound ); |
|
817 } |
|
818 else |
|
819 { |
|
820 // We got the newest details. |
|
821 if ( errorCode == KErrNone ) |
|
822 { |
|
823 if ( details->State() != MNcdPurchaseDetails::EStateInstalled ) |
|
824 { |
|
825 DLINFO(("Content not installed yet")); |
|
826 // Update the fileinfo only if the state is not already installed. |
|
827 // If the state is installed, then the fileinfo is already |
|
828 // up-to-date. |
|
829 const CNcdNodeContentInfo& contentInfo( |
|
830 iMetadata.ContentInfoL() ); |
|
831 if ( ( contentInfo.Purpose() |
|
832 & ENcdItemPurposeTheme ) != 0 ) |
|
833 { |
|
834 DLINFO(("Content purpose is theme. Not allowed.")); |
|
835 // A minor sanity check because themes may have an UID given. |
|
836 // So, if the metadata suggests that the content is theme, |
|
837 // then leave here. Otherwise, trust the user. |
|
838 User::Leave( KErrAbort ); |
|
839 } |
|
840 TUid contentUid( contentInfo.Uid() ); |
|
841 const TDesC& version( contentInfo.Version() ); |
|
842 // The item state is installed when installed info count |
|
843 // corresponds the download info count |
|
844 TInt installCount( details->InstallInfoCount() ); |
|
845 TInt downloadCount( details->DownloadInfoCount() ); |
|
846 for ( TInt i = installCount; i < downloadCount; ++i ) |
|
847 { |
|
848 // Set missing install infos. |
|
849 // Notice, that we only know the main content UID and version. |
|
850 // So, if the content is a bundle, then we need to fake |
|
851 // the UIDs and version here and just use the one that |
|
852 // metadata content info can provide us. |
|
853 CNcdPurchaseInstallInfo* installInfo( |
|
854 CNcdPurchaseInstallInfo::NewLC() ); |
|
855 installInfo->SetApplicationUid( contentUid ); |
|
856 installInfo->SetApplicationVersionL( version ); |
|
857 // Insert new details in the end of the array. |
|
858 details->InsertInstallInfoL( installInfo, |
|
859 details->InstallInfoCount() ); |
|
860 CleanupStack::Pop( installInfo ); |
|
861 } |
|
862 } |
|
863 |
|
864 // Because error code was KErrNone, the content is thought as |
|
865 // successfully installed. So, delete unnecessary installation |
|
866 // files. Notice, that there may be installation files available |
|
867 // even if the details state is EStateInstalled because download |
|
868 // could also be done again even though installation has been |
|
869 // successfull already during the first time. |
|
870 // Get details file information. |
|
871 const MDesCArray& files = details->DownloadedFiles(); |
|
872 for( TInt i = 0; i < files.MdcaCount(); ++i ) |
|
873 { |
|
874 const TDesC& filePath( files.MdcaPoint( i ) ); |
|
875 DLINFO((_L("Delete file: %S"), &filePath)); |
|
876 // Notice, that we need to do the deletion here in the server side. |
|
877 // The installation files may exist in the NCD Engine server |
|
878 // private directory and that directory is normally |
|
879 // accessable only by the NCD Engine server side. |
|
880 TInt deleteError( |
|
881 CNcdProviderUtils::InstallationServiceL(). |
|
882 DeleteFile( filePath ) ); |
|
883 DLINFO(( "Files: %d, delete error: %d", i, deleteError )); |
|
884 } |
|
885 } |
|
886 |
|
887 // Set the error code and the lates operation time |
|
888 details->SetLastOperationErrorCode( errorCode ); |
|
889 details->SetLastUniversalOperationTime(); |
|
890 |
|
891 // Save purhcase details into the purchase history. |
|
892 // This will replace the old detail. |
|
893 // But, do not replace old icon, because we did not load it |
|
894 // for the details above. |
|
895 purchaseHistoryDb.SavePurchaseL( *details, EFalse ); |
|
896 |
|
897 CleanupStack::PopAndDestroy( details ); |
|
898 details = NULL; |
|
899 } |
|
900 |
|
901 // Complete the message because everything went ok. |
|
902 // If some operations above left, then ReceiveMessage will handle |
|
903 // those cases. |
|
904 aMessage.CompleteAndRelease( KErrNone ); |
|
905 } |
|
906 |
|
907 // --------------------------------------------------------------------------- |
|
908 // Opens a content file, called by CallbackOpenFile |
|
909 // --------------------------------------------------------------------------- |
|
910 // |
|
911 void CNcdNodeInstall::OpenContentFileRunner() |
|
912 { |
|
913 DLTRACEIN(("")); |
|
914 TRAPD( err, OpenContentFileL() ); |
|
915 iRetryCount++; |
|
916 if ( err != KErrInUse || iRetryCount >= KMaxRetries ) |
|
917 { |
|
918 DASSERT( iPeriodic ) |
|
919 DLTRACE(("Deleting periodic timer")); |
|
920 delete iPeriodic; |
|
921 iPeriodic = NULL; |
|
922 |
|
923 if ( err != KErrNone ) |
|
924 { |
|
925 DLTRACE(("Handling other errors")); |
|
926 iMessage->CompleteAndRelease( err ); |
|
927 iMessage = NULL; |
|
928 } |
|
929 |
|
930 } |
|
931 } |
|
932 |
|
933 // --------------------------------------------------------------------------- |
|
934 // Opens a content file |
|
935 // --------------------------------------------------------------------------- |
|
936 // |
|
937 void CNcdNodeInstall::OpenContentFileL() |
|
938 { |
|
939 DLTRACEIN(("")); |
|
940 RFs fs; |
|
941 User::LeaveIfError( fs.Connect() ); |
|
942 CleanupClosePushL( fs ); |
|
943 |
|
944 DLTRACE(("Sharing the file server")); |
|
945 User::LeaveIfError( fs.ShareProtected() ); |
|
946 |
|
947 DLTRACE(("Trying to open the file")); |
|
948 RFile file; |
|
949 CleanupClosePushL( file ); |
|
950 User::LeaveIfError( file.Open( fs, |
|
951 iInstallInfos[iFileIndex]->Filename(), |
|
952 NcdProviderDefines::KNcdSharableFileOpenFlags ) ); |
|
953 |
|
954 |
|
955 DLTRACE(("File open, transferring to client")); |
|
956 DASSERT( iMessage ); |
|
957 iMessage->CompleteAndReleaseL( fs, file ); |
|
958 iMessage = NULL; |
|
959 DLTRACE(("File transferred")); |
|
960 CleanupStack::PopAndDestroy( 2, &fs ); // file, fs |
|
961 } |
|
962 |
|
963 |
|
964 // --------------------------------------------------------------------------- |
|
965 // Calculate the number of dependencies |
|
966 // --------------------------------------------------------------------------- |
|
967 // |
|
968 TInt CNcdNodeInstall::DependencyCount( |
|
969 const TArray<MNcdPurchaseDownloadInfo*>& aInfos ) const |
|
970 { |
|
971 DLTRACEIN(("")); |
|
972 TInt depCount = 0; |
|
973 for ( TInt i = 0; i < aInfos.Count(); ++i ) |
|
974 { |
|
975 if ( NcdPurchaseHistoryUtils::IsDependency( *aInfos[i] ) ) |
|
976 { |
|
977 depCount++; |
|
978 } |
|
979 } |
|
980 return depCount; |
|
981 } |
|
982 |
|
983 |
|
984 // --------------------------------------------------------------------------- |
|
985 // |
|
986 // --------------------------------------------------------------------------- |
|
987 // |
|
988 void CNcdNodeInstall::SetContentType( |
|
989 CNcdExtendedInstallInfo& aInstall, |
|
990 const MNcdPurchaseDownloadInfo& aDownload ) const |
|
991 { |
|
992 DLTRACEIN(("")); |
|
993 switch( aDownload.ContentUsage() ) |
|
994 { |
|
995 case MNcdPurchaseDownloadInfo::EDownloadable: |
|
996 { |
|
997 aInstall.SetContentType( MNcdInstalledContent::EInstalledContent ); |
|
998 break; |
|
999 } |
|
1000 |
|
1001 case MNcdPurchaseDownloadInfo::EDependency: |
|
1002 { |
|
1003 aInstall.SetContentType( MNcdInstalledContent::EInstalledDependency ); |
|
1004 break; |
|
1005 } |
|
1006 |
|
1007 case MNcdPurchaseDownloadInfo::ELauncher: // flowthrough |
|
1008 case MNcdPurchaseDownloadInfo::ELauncherOpen: |
|
1009 { |
|
1010 aInstall.SetContentType( MNcdInstalledContent::EInstalledLauncher ); |
|
1011 break; |
|
1012 } |
|
1013 |
|
1014 default: |
|
1015 { |
|
1016 NCD_ASSERT_ALWAYS( 0, ENcdPanicIndexOutOfRange ); |
|
1017 } |
|
1018 } |
|
1019 } |
|
1020 |
|
1021 |
|
1022 // --------------------------------------------------------------------------- |
|
1023 // |
|
1024 // --------------------------------------------------------------------------- |
|
1025 // |
|
1026 void CNcdNodeInstall::SetLaunchParameterL( |
|
1027 RPointerArray<CNcdExtendedInstallInfo>& aInstalls, |
|
1028 TInt aIndex ) const |
|
1029 { |
|
1030 DLTRACEIN(("")); |
|
1031 TInt count = aInstalls.Count(); |
|
1032 CNcdExtendedInstallInfo& launcher( *aInstalls[ aIndex ] ); |
|
1033 |
|
1034 // aIndex is the index of aInstall so increase it |
|
1035 aIndex++; |
|
1036 while ( aIndex < count ) |
|
1037 { |
|
1038 if ( aInstalls[ aIndex ]->Filename().Length() && |
|
1039 aInstalls[ aIndex ]->IsLaunchable() ) |
|
1040 { |
|
1041 DLTRACE(( _L("Found \"%S\", setting as parameter"), |
|
1042 &aInstalls[ aIndex ]->Filename() )); |
|
1043 launcher.SetParameterL( aInstalls[ aIndex ]->Filename() ); |
|
1044 break; |
|
1045 } |
|
1046 aIndex++; |
|
1047 } |
|
1048 } |
|
1049 |
|
1050 |
|
1051 // --------------------------------------------------------------------------- |
|
1052 // |
|
1053 // --------------------------------------------------------------------------- |
|
1054 // |
|
1055 void CNcdNodeInstall::SetContentVersionL( const TDesC& aVersion ) |
|
1056 { |
|
1057 DLTRACEIN(("")); |
|
1058 iContentVersion = TCatalogsVersion(); |
|
1059 |
|
1060 // Convert the version number in purchase history to TCatalogsVersion |
|
1061 TRAPD( err, TCatalogsVersion::ConvertL( |
|
1062 iContentVersion, aVersion ) ); |
|
1063 |
|
1064 LeaveIfNotErrorL( err, KErrArgument, KErrGeneral ); |
|
1065 |
|
1066 } |