--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/provider/deviceinteraction/src/ncdinstallationserviceimpl.cpp Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,2206 @@
+/*
+* Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Definition of CNcdInstallationService
+*
+*/
+
+
+#include "ncdinstallationserviceimpl.h"
+
+#include <DocumentHandler.h>
+#include <apmstd.h>
+#include <apmrec.h>
+#include <bautils.h>
+
+#include <swi/sisregistrypackage.h>
+#include <caf/caf.h>
+#include <caf/supplier.h>
+#include <caf/importfile.h>
+#include <Oma2Agent.h>
+#include <s32file.h>
+#include <e32property.h>
+#include <sacls.h>
+
+#ifdef USE_OLD_JAVA_API
+ #include <mjavaregistry.h>
+ #include <swi/minstalledappsregistry.h>
+#else
+ #include <javaregistry.h>
+ #include <javaregistrypackageentry.h>
+
+ using namespace Java;
+#endif
+
+#include "ncdinstallationserviceobserver.h"
+#include "ncdactiveoperationobserver.h"
+#include "ncdsilentinstallactiveobserver.h"
+#include "ncderrors.h"
+#include "catalogsutils.h"
+#include "catalogsconstants.h"
+#include "catalogsdebug.h"
+
+_LIT( KJadFileExtension, ".jad" );
+const TInt KDelayWhenAppListInvalid = 500000;
+
+const TUint KFileOpenFlags = EFileShareReadersOrWriters;
+
+#ifdef __SERIES60_31__
+
+ const TInt32 KPSUidJavaLatestInstallation = KUidJmiLatestInstallation;
+
+#else
+
+ // Defined originally in /mw/java/inc/javauids.h
+ // This should become available at some point in javadomainpskeys.h
+ //const TInt32 KPSUidJavaLatestInstallation = 0x10282567;
+ #include <javadomainpskeys.h>
+
+#endif
+
+// length taken from WidgetRegistryData.h
+const TInt KWidgetBundleIdLength = KWidgetRegistryVal + 1;
+
+_LIT( KWidgetExtension, ".wgz" );
+
+// ======== CALLBACK FUNCTION ========
+
+static TInt InstallationCompleteCallback( TAny* aData )
+ {
+ DLTRACEIN((""));
+ TRAPD( err,
+ {
+ CNcdInstallationService* service =
+ reinterpret_cast<CNcdInstallationService*>( aData );
+ DASSERT( service );
+ service->NotifyObserverL();
+ } );
+
+ DLTRACEOUT((""));
+ return err;
+ }
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// Constructor.
+// ---------------------------------------------------------------------------
+//
+CNcdInstallationService* CNcdInstallationService::NewL()
+ {
+ CNcdInstallationService* self = NewLC();
+ CleanupStack::Pop();
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Constructor.
+// ---------------------------------------------------------------------------
+//
+CNcdInstallationService* CNcdInstallationService::NewLC()
+ {
+ CNcdInstallationService* self =
+ new (ELeave) CNcdInstallationService();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CNcdInstallationService::~CNcdInstallationService()
+ {
+ DLTRACEIN((""));
+ delete iSilentInstallActiveObserver;
+ iSilentInstallActiveObserver = NULL;
+ delete iDocHandler;
+ iRegistrySession.Close();
+ iFs.Close();
+ iAknsSrv.Close();
+ delete iInstallationCompleteCallback;
+ delete iJadFileName;
+ delete iRecognizedMime;
+#ifdef USE_OLD_JAVA_API
+ iMIDletUids.Close();
+#endif
+ iApaLs.Close();
+ if( iThemes )
+ {
+ iThemes->ResetAndDestroy();
+ delete iThemes;
+ }
+
+ // Deletes iInstallStatusObserver and closes iInstaller
+ CancelInstall();
+ iRomUids.Close();
+
+ if ( iWidgetRegistry.Handle() )
+ {
+ // decreases widget server's refcount but this cannot be called
+ // if Connect has not been called or we'll get a KERN-EXEC 0
+ iWidgetRegistry.Disconnect();
+ }
+ else
+ {
+ iWidgetRegistry.Close();
+ }
+ iInstalledWidgets.ResetAndDestroy();
+ }
+
+// ---------------------------------------------------------------------------
+// Constructor.
+// ---------------------------------------------------------------------------
+//
+CNcdInstallationService::CNcdInstallationService()
+ {
+ }
+
+// ---------------------------------------------------------------------------
+// Constructor.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::ConstructL()
+ {
+ DLTRACEIN((""));
+ iDocHandler = CDocumentHandler::NewL();
+ iDocHandler->SetExitObserver( this );
+
+ User::LeaveIfError( iFs.Connect() );
+ User::LeaveIfError( iFs.ShareProtected() );
+ User::LeaveIfError( iRegistrySession.Connect() );
+ User::LeaveIfError( iAknsSrv.Connect() );
+
+ iInstallationCompleteCallback = new(ELeave) CAsyncCallBack(
+ TCallBack( InstallationCompleteCallback, this ),
+ CActive::EPriorityStandard );
+
+ InitializeRomApplicationListL();
+ }
+
+
+// ---------------------------------------------------------------------------
+// Installs all kinds of files.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::InstallL( const TDesC& aFileName,
+ const TDesC& aMimeType,
+ const TNcdItemPurpose& aPurpose )
+ {
+ DLTRACEIN((""));
+ RFile file;
+ CleanupClosePushL( file );
+ User::LeaveIfError( file.Open( FileServerSession(), aFileName, KFileOpenFlags ) );
+ InstallL( file, aMimeType, aPurpose, NULL );
+ CleanupStack::PopAndDestroy( &file );
+ DLTRACEOUT((""));
+ }
+
+// ---------------------------------------------------------------------------
+// Installs all kinds of files.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::InstallL( RFile& aFile,
+ const TDesC& aMimeType,
+ const TNcdItemPurpose& aPurpose )
+ {
+ DLTRACEIN((""));
+ InstallL( aFile, aMimeType, aPurpose, NULL );
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Installs java files.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::InstallJavaL( const TDesC& aFileName,
+ const TDesC& aMimeType,
+ const TDesC8& aDescriptorData )
+ {
+ DLTRACEIN((""));
+ RFile file;
+ CleanupClosePushL( file );
+ User::LeaveIfError( file.Open( FileServerSession(), aFileName, KFileOpenFlags ) );
+ InstallJavaL( file, aMimeType, aDescriptorData, NULL );
+ CleanupStack::PopAndDestroy( &file );
+ DLTRACEOUT((""));
+ }
+
+// ---------------------------------------------------------------------------
+// Installs java files.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::InstallJavaL( RFile& aFile,
+ const TDesC& aMimeType,
+ const TDesC8& aDescriptorData )
+ {
+ DLTRACEIN((""));
+ InstallJavaL( aFile, aMimeType, aDescriptorData, NULL );
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Installs all kinds of files silently.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::SilentInstallL( RFile& aFile,
+ const TDesC& aMimeType,
+ const TNcdItemPurpose& aPurpose,
+ const SwiUI::TInstallOptionsPckg& aInstallOptionsPckg )
+ {
+ DLTRACEIN((""));
+
+ if ( iSilentInstallActiveObserver == NULL )
+ {
+ DLINFO(("Create active observer for silent install"));
+ iSilentInstallActiveObserver = CNcdSilentInstallActiveObserver::NewL( *this );
+ }
+
+ InstallL( aFile, aMimeType, aPurpose, &aInstallOptionsPckg );
+
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Installs java files silently.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::SilentInstallJavaL( RFile& aFile,
+ const TDesC& aMimeType,
+ const TDesC8& aDescriptorData,
+ const SwiUI::TInstallOptionsPckg& aInstallOptionsPckg )
+ {
+ DLTRACEIN((""));
+
+ if ( iSilentInstallActiveObserver == NULL )
+ {
+ DLINFO(("Create active observer for silent install"));
+ iSilentInstallActiveObserver = CNcdSilentInstallActiveObserver::NewL( *this );
+ }
+
+ InstallJavaL( aFile, aMimeType, aDescriptorData, &aInstallOptionsPckg );
+
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Cancell silent install.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::CancelSilentInstall( HBufC*& aFileName,
+ TUid& aAppUid,
+ TInt& aError )
+ {
+ DLTRACEIN((""));
+
+ // Silent install can only be cancelled if silent is allowed.
+ // The capability check makes sure of this.
+
+ // Set intial values for the reference parameters.
+ delete aFileName;
+ aFileName = NULL;
+ aAppUid = KNullUid;
+ aError = KErrCancel;
+
+ if ( iBusy )
+ {
+ DLINFO(("Install operation was busy"));
+
+ // Some operation is on. Here we expect that it is silent.
+ // Inform the installer that the asynchronous silent install request
+ // needs to be cancelled.
+ // Because we use a dummy active object to observe
+ // completion of installation and that dummy object uses call backs
+ // to inform completion to observer, we have to cancel the operation
+ // by using the dummy object here.
+ aError = iSilentInstallActiveObserver->CancelAsyncOperation();
+
+ if ( aError == KErrNone )
+ {
+ DLINFO(("Installation was success even if cancel was issued."))
+
+ // The installation was finished after all.
+ TRAPD( trapError,
+ HandleSilentInstallSuccessAfterCancelL( aFileName,
+ aAppUid,
+ aError ) );
+ if ( trapError != KErrNone )
+ {
+ DLERROR(("Install success handling leave."));
+ aError = trapError;
+ }
+ }
+
+ // Do cleaning if necessary.
+ if( iJadFileName != NULL )
+ {
+ // Delete tmp JAD file that was created in the beginning of
+ // the install operation. It will be recreated in new install operation
+ // if needed.
+ BaflUtils::DeleteFile( iFs, *iJadFileName ); // NOTE, error ignored
+ delete iJadFileName;
+ iJadFileName = NULL;
+ }
+
+#ifdef USE_OLD_JAVA_API
+ // Clean the array.
+ iMIDletUids.Reset();
+#endif
+
+ // Reset information flags.
+ InstallationFinishedSetup( aError );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// Sets observer for installation services.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::SetObserver(
+ MNcdInstallationServiceObserver& aObserver )
+ {
+ iObserver = &aObserver;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Gets version of installed application by using its UID.
+// ---------------------------------------------------------------------------
+//
+TInt CNcdInstallationService::ApplicationVersion( const TUid& aUid,
+ TCatalogsVersion& aVersion )
+ {
+ DLTRACEIN(("Uid=%X",aUid.iUid));
+
+ // First case: see if the uid is directly in the sis registry.
+ Swi::RSisRegistryEntry entry;
+
+ TVersion version;
+ TRAPD( err,
+ {
+ SisRegistryEntryLC( entry, aUid );
+ // Get version number
+ version = entry.VersionL();
+ CleanupStack::PopAndDestroy( &entry );
+ });
+
+ if ( err != KErrNone )
+ {
+ DLTRACEOUT(("Error: %d", err));
+ return err;
+ }
+
+ aVersion.iMajor = version.iMajor;
+ aVersion.iMinor = version.iMinor;
+ aVersion.iBuild = version.iBuild;
+
+ DLTRACEOUT(("err=%d",err));
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// Checks whether an application is installed on the device.
+// ---------------------------------------------------------------------------
+//
+TBool CNcdInstallationService::IsApplicationInstalledL( const TUid& aUid )
+ {
+ DLTRACEIN(("uid=%X",aUid.iUid));
+ TBool result = EFalse;
+
+ Swi::RSisRegistryEntry entry;
+
+ // First case: See if the UID is directly in the SIS Registry.
+ TRAPD( err,
+ {
+ SisRegistryEntryLC( entry, aUid );
+
+ DLTRACE(("Check that entry is present"));
+ result = entry.IsPresentL();
+ CleanupStack::PopAndDestroy( &entry );
+ });
+
+ LeaveIfNotErrorL( err, KErrNotFound );
+
+ // Third case: see if the UID is mapped to the Java Registry or is a Widget
+ if ( !result )
+ {
+ result = ( JavaAppExistsL( aUid ) ||
+ WidgetExistsL( aUid ) );
+ }
+
+
+ // Check if the app is ROM only
+ if ( !result )
+ {
+ result = IsRomApplication( aUid );
+ }
+ DLTRACEOUT(("result=%d",result));
+ return result;
+ }
+
+// ---------------------------------------------------------------------------
+// Opens SIS registry entry
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::SisRegistryEntryLC(
+ Swi::RSisRegistryEntry& aEntry,
+ const TUid& aUid )
+ {
+ DLTRACEIN((""));
+ CleanupClosePushL( aEntry );
+
+ if ( aEntry.Open( iRegistrySession, aUid ) == KErrNone )
+ {
+ DLTRACEOUT(("Entry opened"));
+ return;
+ }
+
+ // Second case: See if the UID is mapped to a package/entry
+ // in the registry ( -> APP UID that differs from SIS UID ).
+
+ Swi::CSisRegistryPackage* sisRegistryPackage =
+ iRegistrySession.SidToPackageL( aUid );
+ CleanupStack::PushL( sisRegistryPackage );
+
+ TInt err = aEntry.OpenL( iRegistrySession, *sisRegistryPackage );
+ User::LeaveIfError( err );
+
+ CleanupStack::PopAndDestroy( sisRegistryPackage );
+
+ DLTRACEOUT(("Entry opened"));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Open java suite entry
+//
+// ---------------------------------------------------------------------------
+//
+#ifdef USE_OLD_JAVA_API
+
+TBool CNcdInstallationService::JavaAppExistsL(
+ const TUid& aUid )
+ {
+ DLTRACEIN((""));
+
+ MJavaRegistry* javaRegistry = MJavaRegistry::CreateL();
+ CleanupReleasePushL( *javaRegistry );
+
+ TRAPD( err,
+ {
+ // Leaves with KErrNotFound if not found
+ MJavaRegistryMIDletEntry* midletEntry = javaRegistry->MIDletEntryL(
+ aUid );
+ midletEntry->Release();
+ });
+
+ LeaveIfNotErrorL( err, KErrNotFound );
+
+ CleanupStack::PopAndDestroy( javaRegistry );
+ return err == KErrNone;
+ }
+
+#else
+
+TBool CNcdInstallationService::JavaAppExistsL(
+ const TUid& aUid )
+ {
+ DLTRACEIN((""));
+
+ CJavaRegistry* javaRegistry = CJavaRegistry::NewLC();
+
+ TBool exists = javaRegistry->RegistryEntryExistsL( aUid );
+
+ CleanupStack::PopAndDestroy( javaRegistry );
+ return exists;
+ }
+
+#endif
+
+// ---------------------------------------------------------------------------
+// Checks the application status
+// ---------------------------------------------------------------------------
+//
+TNcdApplicationStatus CNcdInstallationService::IsApplicationInstalledL(
+ const TUid& aUid, const TCatalogsVersion& aVersion )
+ {
+ DLTRACEIN((""));
+
+ TNcdApplicationStatus status( ENcdApplicationNotInstalled );
+
+ if ( aUid == TUid::Null() )
+ {
+ DLTRACEOUT(("Null uid"));
+ return status;
+ }
+
+
+ Swi::RSisRegistryEntry entry;
+ TCatalogsVersion installedVersion;
+
+ // Get SIS-app version
+ TRAPD( err,
+ {
+ SisRegistryEntryLC( entry, aUid );
+
+ DLTRACE(("Check that entry is present"));
+
+ if ( entry.IsPresentL() )
+ {
+ DLTRACE(("Is present"));
+ status = ENcdApplicationInstalled;
+ }
+
+ TVersion version = entry.VersionL();
+ installedVersion = TCatalogsVersion(
+ version.iMajor,
+ version.iMinor,
+ version.iBuild );
+
+ CleanupStack::PopAndDestroy( &entry );
+ });
+
+ // SIS app not found, try to get java
+ if ( err == KErrNotFound &&
+ ( JavaAppExistsL( aUid ) ||
+ WidgetExistsL( aUid ) ) )
+ {
+ status = ENcdApplicationInstalled;
+ }
+
+ LeaveIfNotErrorL( err, KErrNotFound );
+
+ // Some app found, check version numbers if they are something else than
+ // 0.0.0
+ if ( err == KErrNone &&
+ status == ENcdApplicationInstalled &&
+ installedVersion != TCatalogsVersion() &&
+ aVersion != TCatalogsVersion() )
+ {
+ DLINFO(("Installed version: %d.%d.%d, comparing to: %d.%d.%d",
+ installedVersion.iMajor,
+ installedVersion.iMinor,
+ installedVersion.iBuild,
+ aVersion.iMajor,
+ aVersion.iMinor,
+ aVersion.iBuild ));
+
+ if ( installedVersion > aVersion )
+ {
+ status = ENcdApplicationNewerVersionInstalled;
+ }
+ else if ( !( installedVersion == aVersion ) )
+ {
+ status = ENcdApplicationOlderVersionInstalled;
+ }
+ }
+
+ // Checking if the app is ROM only
+ if ( status == ENcdApplicationNotInstalled &&
+ IsRomApplication( aUid ) )
+ {
+ status = ENcdApplicationInstalled;
+ }
+
+ DLTRACEOUT(("Status: %d", status));
+ return status;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Gets the first SID from the SIS registry package
+// ---------------------------------------------------------------------------
+//
+TUid CNcdInstallationService::SidFromSisRegistryL( const TUid& aUid )
+ {
+ DLTRACEIN(("uid=%X",aUid.iUid));
+ Swi::RSisRegistryEntry entry;
+ TUid sid( KNullUid );
+
+ User::LeaveIfError( entry.Open( iRegistrySession, aUid ) );
+ CleanupClosePushL( entry );
+
+ RArray<TUid> sids;
+ CleanupClosePushL( sids );
+ entry.SidsL( sids );
+
+ DLINFO(("sid count=%d",sids.Count()));
+
+ if ( sids.Count() > 0 )
+ {
+ sid.iUid = sids[0].iUid;
+ }
+ else
+ {
+ DLERROR(("No SIDs found"));
+ User::Leave( KErrNotFound );
+ }
+
+ CleanupStack::PopAndDestroy( &sids );
+ CleanupStack::PopAndDestroy( &entry );
+
+ DLTRACEOUT(("uid=%X",sid.iUid));
+ return sid;
+ }
+
+// ---------------------------------------------------------------------------
+// Appends rights into the rights database.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::AppendRightsL(
+ const TDesC8& aRightsObject,
+ const TDataType& aMimeType )
+ {
+ DLTRACEIN(("MimeType: %S", &aMimeType.Des8() ));
+
+ ContentAccess::CSupplier* supplier =
+ ContentAccess::CSupplier::NewLC();
+ ContentAccess::CMetaDataArray* metaData =
+ ContentAccess::CMetaDataArray::NewLC();
+
+ DLTRACE(("Creating CImportFile"));
+ // Indicate what type of content we are importing.
+ ContentAccess::CImportFile* file = supplier->ImportFileL( aMimeType.Des8(), *metaData );
+ CleanupStack::PushL( file );
+
+ DLTRACE(("Importing data"));
+ // Start importing data. This can also be done in parts.
+ User::LeaveIfError( file->WriteData( aRightsObject ) );
+
+ DLTRACE(("Finished importing"));
+ // Indicate that we are finished
+ User::LeaveIfError( file->WriteDataComplete() );
+
+ CleanupStack::PopAndDestroy( file );
+ CleanupStack::PopAndDestroy( metaData );
+ CleanupStack::PopAndDestroy( supplier );
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Reads the package uid from a SISX file
+// ---------------------------------------------------------------------------
+//
+TUid CNcdInstallationService::PackageUidFromSisL( RFile& aFile ) const
+ {
+ DLTRACEIN((""));
+ RFileReadStream readStream( aFile );
+ CleanupClosePushL( readStream );
+
+ // Get Application UID
+ //
+
+ // NOTE: In 3.0 the SIS file format has changed
+ // the UID is the third long word ( 32 bits ) of the file.
+ TInt dummy = readStream.ReadUint32L();
+ dummy = readStream.ReadUint32L();
+
+ TUid uid( TUid::Uid( readStream.ReadUint32L() ) );
+
+ // this closes the attached file too
+ CleanupStack::PopAndDestroy( &readStream );
+ DLTRACEOUT(( _L("Uid: %S"), &uid.Name() ));
+ return uid;
+ }
+
+
+// ---------------------------------------------------------------------------
+// IsThemeInstalled
+// ---------------------------------------------------------------------------
+//
+TBool CNcdInstallationService::IsThemeInstalledL( const TDesC& aThemeName )
+ {
+ DLTRACEIN(( _L("Theme: %S"), &aThemeName ));
+ TInt result = EFalse;
+
+ if ( aThemeName != KNullDesC )
+ {
+ RAknsSrvSession skinSrvSession;
+ User::LeaveIfError( skinSrvSession.Connect() );
+ CleanupClosePushL( skinSrvSession );
+
+ CArrayPtr<CAknsSrvSkinInformationPkg>* srvArray = NULL;
+ // Look themes from C: and E: drives
+ for ( TInt index = 0; index < 2; index++ )
+ {
+ //TUint skinLocation = 0;
+ if ( index == 0 )
+ {
+ //skinLocation = EAknsSrvPhone;
+ srvArray = skinSrvSession.EnumerateSkinPackagesL( EAknsSrvPhone );
+ CleanupStack::PushL( srvArray );
+ }
+ else
+ {
+ //skinLocation = EAknsSrvMMC;
+ srvArray = skinSrvSession.EnumerateSkinPackagesL( EAknsSrvMMC );
+ CleanupStack::PushL( srvArray );
+ }
+
+ while ( srvArray && srvArray->Count() > 0 )
+ {
+ CAknsSrvSkinInformationPkg* info = srvArray->At( 0 );
+
+ // If match is found, theme can be set
+ if ( info->Name().Compare( aThemeName ) == 0 )
+ {
+ result = ETrue;
+ }
+
+ delete info;
+ srvArray->Delete( 0 );
+ }
+
+ CleanupStack::PopAndDestroy( srvArray );
+
+ if ( result )
+ {
+ break;
+ }
+ }
+
+ CleanupStack::PopAndDestroy(); // skinSrvSession
+ }
+ DLTRACEOUT(("Result: %d", result));
+ return result;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Deletes the given file
+// ---------------------------------------------------------------------------
+//
+TInt CNcdInstallationService::DeleteFile( const TDesC& aFilename )
+ {
+ DLTRACEIN(( _L("Filepath: %S"), &aFilename ));
+ // Ensure that we don't accidentally delete whole directories
+ // because of empty path
+ if ( aFilename.Length() )
+ {
+ return BaflUtils::DeleteFile( iFs, aFilename );
+ }
+ return KErrArgument;
+ }
+
+
+// ---------------------------------------------------------------------------
+// File server session getter
+// ---------------------------------------------------------------------------
+//
+RFs& CNcdInstallationService::FileServerSession()
+ {
+ return iFs;
+ }
+
+
+// ---------------------------------------------------------------------------
+// JAD writer
+// ---------------------------------------------------------------------------
+//
+HBufC* CNcdInstallationService::WriteJadL(
+ const TDesC& aJarFileName, const TDesC8& aJad )
+ {
+ DLTRACEIN(("Writing JAD"));
+ TParsePtrC jarParse( aJarFileName );
+ HBufC* jadFileName = HBufC::NewLC(
+ aJarFileName.Length() + KJadFileExtension().Length() );
+ TPtr jadPtr( jadFileName->Des() );
+ jadPtr.Append( jarParse.DriveAndPath() );
+ jadPtr.Append( jarParse.Name() );
+ jadPtr.Append( KJadFileExtension );
+
+ RFile file;
+ CleanupClosePushL( file );
+ User::LeaveIfError( file.Replace( iFs, *jadFileName, EFileWrite | EFileShareAny ) );
+ User::LeaveIfError( file.Write( aJad ) );
+ DLINFO(( _L("JAD=%S"), jadFileName ));
+ CleanupStack::PopAndDestroy( &file );
+ CleanupStack::Pop( jadFileName );
+ return jadFileName;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Documenthandler getter
+// ---------------------------------------------------------------------------
+//
+CDocumentHandler& CNcdInstallationService::DocumentHandler()
+ {
+ return *iDocHandler;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Callback function of MNcdAsyncOperationObserver interface
+// This is called when an async operation has finished.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::AsyncOperationComplete( TInt aError )
+ {
+ DLTRACEIN(("aError: %d", aError));
+
+ iInstaller.Close();
+
+ if ( aError == SwiUI::KSWInstErrUserCancel )
+ {
+ DLTRACE(("User cancelled, converting error to KErrAbort" ) );
+ aError = KErrAbort;
+ }
+
+ // Handle this like in normal cases.
+ HandleServerAppExit( aError );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Callback function of MNcdAsyncSilentInstallObserver interface
+// This is called when the silent install has finished.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::AsyncSilentInstallComplete( TInt aError )
+ {
+ DLTRACEIN(("aError: %d", aError));
+
+ // Handle this like in normal cases.
+ HandleServerAppExit( aError );
+ }
+
+
+// ---------------------------------------------------------------------------
+// This function is called after application installer has finished.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::NotifyObserverL()
+ {
+ DLTRACEIN(("install error: %d", iInstallError ));
+
+ if ( iInstallType == EWidgetInstall )
+ {
+ HandleInstalledWidgetL();
+ }
+ else if ( iInstallType == EJavaInstall )
+ {
+ if( iJadFileName )
+ {
+ BaflUtils::DeleteFile( iFs, *iJadFileName ); // NOTE, error ignored
+ delete iJadFileName;
+ iJadFileName = 0;
+ }
+
+ if ( iInstallError != KErrNone )
+ {
+ DLTRACE(("Notify install error"));
+#ifdef USE_OLD_JAVA_API
+ iMIDletUids.Reset();
+#endif
+ iObserver->InstallationCompleteL( KNullDesC, TUid(), iInstallError );
+ return;
+ }
+
+ TUid midletUid = InstalledMidletUidL();
+
+ DLINFO(("Installed midlet uid=%X", midletUid.iUid ));
+
+ iObserver->InstallationCompleteL( KNullDesC, midletUid,
+ // Return error if nothing found.
+ midletUid == KNullUid ? KErrNotFound : KErrNone );
+ }
+
+ else if ( iInstallType == ESisInstall )
+ {
+
+ if ( iInstallError != KErrNone )
+ {
+ DLTRACE(("Notify install error"));
+ iObserver->InstallationCompleteL( KNullDesC, TUid(), iInstallError );
+ return;
+ }
+
+ // Get theme name if such was installed
+ const TDesC& name( LatestThemeL() );
+
+ // Notify about theme installation
+ if ( iPackageUid.iUid == KNcdThemeSisUid || name != KNullDesC )
+ {
+ DLTRACE(( _L("Notify observer about theme installation, theme: %S"),
+ &name ));
+ // Ensure that uid is theme uid
+ iPackageUid.iUid = KNcdThemeSisUid;
+
+ if ( name == KNullDesC && iThemePackageUid.iUid != KNcdThemeSisUid )
+ {
+ DLTRACE(("Checking theme installation status with package uid, %x",
+ iThemePackageUid.iUid ));
+
+ TBool themeInstalled = EFalse;
+
+ // Check if the theme was indeed successfully installed
+ TRAP_IGNORE( themeInstalled = IsApplicationInstalledL(
+ iThemePackageUid ) );
+
+ if ( themeInstalled )
+ {
+ DLINFO(("Theme is installed but we didn't get the name"));
+ iObserver->InstallationCompleteL(
+ name,
+ iPackageUid,
+ KNcdThemeReinstalled );
+ }
+ else
+ {
+ DLINFO(("Theme was not installed"));
+ iObserver->InstallationCompleteL(
+ name,
+ iPackageUid,
+ KErrGeneral );
+
+ }
+ }
+ else
+ {
+ DLTRACE(("Either theme name was acquired or package uid was theme"));
+ iObserver->InstallationCompleteL(
+ name,
+ iPackageUid,
+ // Consider missing theme name as a theme reinstallation
+ name == KNullDesC ? KNcdThemePossiblyReinstalled : KErrNone );
+ }
+ }
+ else
+ {
+
+ // Get the actual app UID from sis registry
+ TRAPD( err, iAppUid = SidFromSisRegistryL( iPackageUid ) );
+
+ DLTRACE(("Notify observer about application installation, uid: %x",
+ iAppUid.iUid ));
+
+ if ( err == KErrNotFound )
+ {
+ DLTRACE(("Didn't get SID, using package UID: %x",
+ iPackageUid.iUid));
+ iAppUid.iUid = iPackageUid.iUid;
+ err = KErrNone;
+ }
+
+ if ( err == KErrNone )
+ {
+ DLTRACE(("Check the application is actually installed"));
+ TBool installed = EFalse;
+ TRAP( err, installed = IsApplicationInstalledL( iAppUid ) );
+ if ( err == KErrNone )
+ {
+ if ( !installed )
+ {
+ err = KErrGeneral;
+ }
+ else
+ {
+ TCatalogsVersion version;
+ err = ApplicationVersion( iAppUid, version );
+ if ( err == KErrNone )
+ {
+ DLTRACE(("Converting version to string"));
+ // Put application version as the filename
+ HBufC* versionString =
+ TCatalogsVersion::ConvertLC( version );
+ // Notify about application installation
+ iObserver->InstallationCompleteL(
+ *versionString,
+ iAppUid,
+ err );
+ CleanupStack::PopAndDestroy( versionString );
+ return;
+ }
+ }
+ }
+
+ }
+
+ // Notify about application installation
+ iObserver->InstallationCompleteL( KNullDesC, iAppUid, err );
+ }
+ }
+ else
+ {
+ DLTRACE(("Was not Java nor SIS install"));
+ // This is executed after a content file has been moved.
+ // We don't set the exit observer as NULL since it panics in debug builds
+ }
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// This function is called after application installer has finished.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::HandleServerAppExit( TInt aReason )
+ {
+ DLTRACEIN(("aReason=%d",aReason));
+
+ InstallationFinishedSetup( aReason );
+
+ // If observer exists, notify it.
+ iInstallationCompleteCallback->CallBack();
+ }
+
+
+// ---------------------------------------------------------------------------
+// Update the list of installed themes
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::UpdateInstalledThemesL()
+ {
+ DLTRACEIN((""));
+ if ( iThemes )
+ {
+ DLTRACE(("Delete old list"));
+ iThemes->ResetAndDestroy();
+ delete iThemes;
+ iThemes = NULL;
+ }
+
+ iThemes = iAknsSrv.EnumerateSkinPackagesL( EAknsSrvAll );
+
+ DLTRACEOUT(("Got new theme list"));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Get name of the theme installed after the latest UpdateInstalledThemesL()
+// call
+// ---------------------------------------------------------------------------
+//
+const TDesC& CNcdInstallationService::LatestThemeL()
+ {
+ DLTRACEIN((""));
+
+ if ( !iThemes )
+ {
+ DLTRACEOUT(("Was not installing a theme"));
+ return KNullDesC();
+ }
+
+ CArrayPtr<CAknsSrvSkinInformationPkg>* newThemes =
+ iAknsSrv.EnumerateSkinPackagesL( EAknsSrvAll );
+
+#ifdef CATALOGS_BUILD_CONFIG_DEBUG
+ DLTRACE(("Installed old themes, count: %d", iThemes->Count() ));
+ for ( TInt i = 0; i < iThemes->Count(); ++i )
+ {
+ DLINFO(( _L("%S"), &iThemes->At( i )->Name() ));
+ }
+
+ DLTRACE(("Installed new themes, count: %d", newThemes->Count() ));
+ for ( TInt i = 0; i < newThemes->Count(); ++i )
+ {
+ DLINFO(( _L("%S"), &newThemes->At( i )->Name() ));
+ }
+#endif
+
+ // Empty previous information
+ delete iThemeName;
+ iThemeName = NULL;
+ iPID.Set( TUid::Uid( 0 ) );
+
+ // Check if new theme has been installed after last
+ // call to the GetInstalledSkinPackagesL()
+ if ( newThemes->Count() > iThemes->Count() )
+ {
+ DLTRACE(("New themes installed, count: %d",
+ newThemes->Count() - iThemes->Count() ));
+
+ // New theme has been installed
+ for ( TInt i = 0; i < newThemes->Count(); i++ )
+ {
+ TInt j = 0;
+
+ for ( ; j < iThemes->Count(); j++ )
+ {
+ if ( newThemes->At( i )->PID() == iThemes->At( j )->PID() )
+ {
+ // PID found from old theme list. This is not the
+ // new theme.
+ break;
+ }
+ }
+
+ if ( j == iThemes->Count() )
+ {
+ DLTRACE(("Found new theme"));
+ // PID was not found from old theme list. This is the
+ // new theme.
+ iPID = newThemes->At( i )->PID();
+ TRAPD( err, iThemeName = newThemes->At( i )->Name().AllocL() );
+ if ( err != KErrNone )
+ {
+ newThemes->ResetAndDestroy();
+ delete newThemes;
+ User::Leave( err );
+ }
+ break;
+ }
+ }
+ }
+
+ newThemes->ResetAndDestroy();
+ delete newThemes;
+ if ( iThemeName )
+ {
+ DLTRACEOUT(( _L("Theme: %S"), iThemeName ));
+ return *iThemeName;
+ }
+ DLTRACEOUT(("No theme"));
+ return KNullDesC();
+ }
+
+
+// ---------------------------------------------------------------------------
+// Try to recognize the data from the file
+// ---------------------------------------------------------------------------
+//
+HBufC* CNcdInstallationService::RecognizeDataL( const TDesC& aFileName )
+ {
+ DLTRACEIN(( _L("Filename: %S"), &aFileName ));
+
+ if ( aFileName.Length() == 0 )
+ {
+ DLTRACEOUT(("Empty filename"));
+ return KNullDesC().AllocL();
+ }
+
+ ConnectApaLsL();
+
+ TInt recognizeBufferLength = 0;
+ User::LeaveIfError( iApaLs.GetPreferredBufSize( recognizeBufferLength ) );
+ HBufC8* buffer = HBufC8::NewLC( recognizeBufferLength );
+ TPtr8 ptr8( buffer->Des() );
+
+ TDataRecognitionResult result;
+ // Read necessary amount of bytes from the file
+ User::LeaveIfError( iFs.ReadFileSection(
+ aFileName, 0, ptr8, recognizeBufferLength ) );
+
+
+ // Try to recognize data
+ User::LeaveIfError( iApaLs.RecognizeData(
+ aFileName, *buffer, result ) );
+
+ HBufC* resultMime = Des8ToDes16L( result.iDataType.Des8() );
+ CleanupStack::PopAndDestroy( buffer );
+ iApaLs.Close();
+ DLTRACEOUT(( _L("Determined MIME: %S"), resultMime ));
+ return resultMime;
+ }
+
+// ---------------------------------------------------------------------------
+// Try to recognize the data from the file
+// ---------------------------------------------------------------------------
+//
+HBufC* CNcdInstallationService::RecognizeDataL( RFile& aFile )
+ {
+ DLTRACEIN((""));
+ ConnectApaLsL();
+
+ TDataRecognitionResult result;
+
+ // Try to recognize data
+ User::LeaveIfError( iApaLs.RecognizeData(
+ aFile, result ) );
+
+ HBufC* resultMime = Des8ToDes16L( result.iDataType.Des8() );
+
+ iApaLs.Close();
+ DLTRACEOUT(( _L("Determined MIME: %S"), resultMime ));
+ return resultMime;
+ }
+
+
+void CNcdInstallationService::ConnectApaLsL()
+ {
+ DLTRACEIN((""));
+ User::LeaveIfError( iApaLs.Connect() );
+ DLTRACEOUT(("Connected successfully"));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Installs all kinds of files in normal or in silent way.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::InstallL( RFile& aFile,
+ const TDesC& aMimeType,
+ const TNcdItemPurpose& aPurpose,
+ const SwiUI::TInstallOptionsPckg* aSilentInstallOptionsPckg )
+ {
+ DLTRACEIN(( _L("iBusy=%d, MIME: %S"),iBusy, &aMimeType ));
+ DASSERT( iObserver );
+ DASSERT( iDocHandler );
+
+
+ // Check if some installation is already in progress.
+ if ( iBusy )
+ {
+ DLERROR(("busy"));
+ User::Leave( KErrInUse );
+ }
+
+ // Reset app uid info
+ iAppUid.iUid = 0;
+ iPackageUid.iUid = 0;
+ iThemePackageUid.iUid = KNcdThemeSisUid;
+
+ iPurpose = aPurpose;
+
+ iInstallError = KErrNone;
+
+ delete iRecognizedMime;
+ iRecognizedMime = NULL;
+
+ // Try to recognize the data if no mime given or it's DRM content
+ // in which case we don't know the type of the actual content
+
+ DLTRACE(("Recognizing mime type of the content"));
+ TRAPD( err, iRecognizedMime = RecognizeDataL( aFile ) );
+ if ( err != KErrNone )
+ {
+ DLERROR(("Couldn't recognize the mime type, error: %d", err));
+ iRecognizedMime = KNullDesC().AllocL();
+ }
+
+ // Fail-safe in case someone tries to install a Java application
+ // with this method
+ if ( MatchJava( *iRecognizedMime ) )
+ {
+ DLTRACE(("Java"));
+ InstallJavaL(
+ aFile,
+ *iRecognizedMime,
+ KNullDesC8,
+ aSilentInstallOptionsPckg );
+ return;
+ }
+ else if ( MatchWidget( aFile, aMimeType ) )
+ {
+ DLTRACE(("Widget"));
+ InstallWidgetL(
+ aFile,
+ aSilentInstallOptionsPckg );
+ return;
+ }
+
+ // Handle SIS(X) and DRM content which has a suitable purpose
+ if ( aMimeType.MatchF( KMimeTypeMatchSymbianInstall ) != KErrNotFound
+ || aMimeType.MatchF( KMimeTypeMatchSisx ) != KErrNotFound
+ || aMimeType.MatchF( KMimeTypeMatchApplicationStream ) != KErrNotFound
+ || iRecognizedMime->MatchF( KMimeTypeMatchSymbianInstall ) != KErrNotFound
+ || iRecognizedMime->MatchF( KMimeTypeMatchSisx ) != KErrNotFound
+ || iRecognizedMime->MatchF( KMimeTypeMatchApplicationStream ) != KErrNotFound )
+ {
+ DLINFO(("Installing SIS"));
+ iInstallType = ESisInstall;
+ // Get package UID
+
+ // PackageUidFromSisL( RFile& ) closes the filehandle so we need to make
+ // a duplicate
+ RFile fileCopy;
+ User::LeaveIfError( fileCopy.Duplicate( aFile ) );
+ CleanupClosePushL( fileCopy );
+ iPackageUid = PackageUidFromSisL( fileCopy );
+ CleanupStack::PopAndDestroy( &fileCopy );
+
+ // Check if the file is a theme sis
+ if ( aPurpose == ENcdItemPurposeTheme ||
+ iPackageUid.iUid == KNcdThemeSisUid )
+ {
+ DLINFO(("This seems to be a theme"));
+ iThemePackageUid = iPackageUid;
+ // Ensure that package uid is a theme UID
+ iPackageUid.iUid = KNcdThemeSisUid;
+ }
+
+ // Update the theme list in case it actually is a theme but purpose is wrong
+ // and the package doesn't have the theme uid
+ UpdateInstalledThemesL();
+
+ TDataType dataType;
+ // Start application installation.
+ DLINFO(( "Calling doc handler Open" ));
+
+ if ( !aSilentInstallOptionsPckg )
+ {
+ DLINFO(("Normal install"));
+ InitializeInstallerL();
+ iCancelCode = SwiUI::ERequestInstallHandle;
+
+ iInstaller.Install( iInstallStatusObserver->iStatus, aFile );
+ iInstallStatusObserver->StartToObserve();
+ }
+ else
+ {
+ DLINFO(("Silent install"));
+ // Set the observer active because it will be informed about the completion
+ // of the silent install and it will forward the information for the callback
+ // function of this class object.
+ iSilentInstallActiveObserver->StartToObserveL( aFile,
+ *aSilentInstallOptionsPckg );
+ }
+
+ iBusy = ETrue;
+
+ }
+ else // Handle images etc. and DRM content that didn't have a matching purpose
+ {
+ DLINFO(("Installing content"));
+ // File is some common format.
+ iInstallType = EFileInstall;
+ TDataType dataType;
+
+ if ( aMimeType != KNullDesC )
+ {
+ // If mime type is given, it will be used in document handler.
+ HBufC8* tempBuf = Des16ToDes8LC( aMimeType );
+ dataType = TDataType( *tempBuf );
+ CleanupStack::PopAndDestroy( tempBuf );
+ DLINFO(("DataType: %S", &dataType.Des8() ));
+ }
+
+ TInt docHandlerError( KErrNone );
+
+ DLINFO(("Normal install"));
+ // Have to use CopyL since MoveL works only with filepaths
+ // We can't use SilentMoveL either
+ docHandlerError =
+ iDocHandler->CopyL( aFile,
+ KNullDesC(),
+ dataType,
+ KEntryAttNormal );
+
+ DLTRACE(("After move"));
+ if( docHandlerError != KErrNone )
+ {
+ DLINFO(("error=%d",docHandlerError));
+
+ // Use KErrAbort for user cancellation
+ if ( docHandlerError == KUserCancel )
+ {
+ docHandlerError = KErrAbort;
+ }
+ iObserver->InstallationCompleteL( KNullDesC, KNullUid, docHandlerError );
+ }
+ else
+ {
+ DLTRACE(("Installation successful"));
+
+ RBuf installFileName;
+ CleanupClosePushL( installFileName );
+
+ installFileName.CreateL( KMaxPath );
+
+ User::LeaveIfError( iDocHandler->GetPath( installFileName ) );
+ iObserver->InstallationCompleteL( installFileName, KNullUid, KErrNone );
+ CleanupStack::PopAndDestroy( &installFileName );
+
+ }
+ }
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Installs java files in normal or in silent way.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::InstallJavaL( RFile& aFile,
+ const TDesC& /*aMimeType*/,
+ const TDesC8& aDescriptorData,
+ const SwiUI::TInstallOptionsPckg* aSilentInstallOptionsPckg )
+ {
+ DLTRACEIN((_L("iBusy=%d, descriptor=%d"),iBusy, aDescriptorData.Length() ));
+ DASSERT( iObserver );
+
+ // Check if some installation is already in progress.
+ if ( iBusy )
+ {
+ DLERROR(("busy"));
+ User::Leave( KErrInUse );
+ }
+
+ iInstallError = KErrNone;
+
+#ifdef USE_OLD_JAVA_API
+ // Store installed java app uids before installation to see
+ // which one is a new java app later.
+ MJavaRegistry* javaRegistry = MJavaRegistry::CreateL();
+ CleanupReleasePushL( *javaRegistry );
+ iMIDletUids.Reset();
+ javaRegistry->InstalledMIDletUidsL( iMIDletUids );
+ CleanupStack::PopAndDestroy( javaRegistry );
+#endif
+
+ // In platform security systems JAR and JAD has to be in same folder
+ // to get the installation process work correctly.
+ // First form the JAD filename from the JAR filename.
+
+ delete iJadFileName;
+ iJadFileName = 0;
+
+ if( aDescriptorData != KNullDesC8 )
+ {
+ DLINFO(("Writing JAD"));
+ TPath fileName;
+ User::LeaveIfError( aFile.FullName( fileName ) );
+
+ iJadFileName = WriteJadL( fileName, aDescriptorData );
+ }
+
+
+ iInstallType = EJavaInstall;
+ TDataType dataType;
+
+ if ( aSilentInstallOptionsPckg == NULL )
+ {
+ DLINFO(("Normal install"));
+ InitializeInstallerL();
+ if( iJadFileName )
+ {
+ DLTRACE(("Installing JAD+JAR"));
+ // JAD+JAR install
+ iCancelCode = SwiUI::ERequestInstall;
+ iInstaller.Install( iInstallStatusObserver->iStatus, *iJadFileName );
+ }
+ else
+ {
+ DLTRACE(("Installing JAR"));
+ // JAR install
+ iCancelCode = SwiUI::ERequestInstallHandle;
+ iInstaller.Install( iInstallStatusObserver->iStatus, aFile );
+ }
+
+ iInstallStatusObserver->StartToObserve();
+ }
+ else
+ {
+ DLINFO(("Silent install"));
+ if( iJadFileName )
+ {
+ DLINFO(("Silent jad and jar"));
+ // JAD+JAR install
+ // Set the observer active because it will be informed about the completion
+ // of the silent install and it will forward the information for the callback
+ // function of this class object.
+ iSilentInstallActiveObserver->StartToObserveL( *iJadFileName,
+ *aSilentInstallOptionsPckg );
+ }
+ else
+ {
+ DLINFO(("Silent jar"));
+ // JAR install
+ // Set the observer active because it will be informed about the completion
+ // of the silent install and it will forward the information for the callback
+ // function of this class object.
+ iSilentInstallActiveObserver->StartToObserveL( aFile,
+ *aSilentInstallOptionsPckg );
+ }
+ }
+
+ iBusy = ETrue;
+
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Installs Widgets files in normal or in silent way.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::InstallWidgetL(
+ RFile& aFile,
+ const SwiUI::TInstallOptionsPckg* aSilentInstallOptionsPckg )
+ {
+ DLTRACEIN((""));
+
+ iInstallType = EWidgetInstall;
+
+ // Get the list of installed widget uids so that we can
+ // get the uid of the new widget after installation
+ PopulateInstalledWidgetUidsL();
+
+ TDataType dataType;
+ // Start application installation.
+ DLINFO(( "Calling doc handler Open" ));
+
+ if ( !aSilentInstallOptionsPckg )
+ {
+ DLINFO(("Normal install"));
+ InitializeInstallerL();
+ iCancelCode = SwiUI::ERequestInstallHandle;
+
+ iInstaller.Install( iInstallStatusObserver->iStatus, aFile );
+ iInstallStatusObserver->StartToObserve();
+ }
+ else
+ {
+ DLINFO(("Silent install"));
+ // Set the observer active because it will be informed about the completion
+ // of the silent install and it will forward the information for the callback
+ // function of this class object.
+ iSilentInstallActiveObserver->StartToObserveL( aFile,
+ *aSilentInstallOptionsPckg );
+ }
+
+ iBusy = ETrue;
+
+ }
+
+// ---------------------------------------------------------------------------
+// Initializes installer
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::InitializeInstallerL()
+ {
+ DLTRACEIN((""));
+ DeletePtr( iInstallStatusObserver );
+ iInstallStatusObserver = CNcdActiveOperationObserver::NewL( *this );
+
+ if ( !iInstaller.Handle() )
+ {
+ User::LeaveIfError( iInstaller.Connect() );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// Cancels installation
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::CancelInstall()
+ {
+ DLTRACEIN((""));
+ if ( iInstallStatusObserver &&
+ iInstaller.Handle() )
+ {
+ DLTRACE(("Cancelling installation"));
+ iInstaller.CancelAsyncRequest( iCancelCode );
+ }
+
+ DeletePtr( iInstallStatusObserver );
+ iInstaller.Close();
+ }
+
+
+// ---------------------------------------------------------------------------
+// Sets the flags after installation has been finished.
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::InstallationFinishedSetup( TInt aReason )
+ {
+ DLTRACEIN(("aReason=%d",aReason));
+
+ // Installation has finished.
+ iBusy = EFalse;
+
+ iInstallError = aReason;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Handles the situation when installation was finished even if cancel request
+// was issued for silent install operation
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::HandleSilentInstallSuccessAfterCancelL( HBufC*& aFileName,
+ TUid& aAppUid,
+ TInt& aError )
+ {
+ DLTRACEIN((""));
+
+ // Set the error to KErrNone.
+ // So, initially we think that installation was success.
+ // If we later notice that installation was not finished,
+ // then we suppose that cancellation was success and set the
+ // value to KErrCancel
+ aError = KErrNone;
+
+ if ( iInstallType == EJavaInstall )
+ {
+ // Set the midlet UID for the aAppUid variable.
+ aAppUid = InstalledMidletUidL();
+
+ if ( aAppUid == KNullUid )
+ {
+ DLINFO(("Installed midlet was not found"));
+ // Because the new midlet was not found, we can suppose that the
+ // application was not installed. So, set the error as KErrCancel.
+ aError = KErrCancel;
+ }
+ }
+ else if ( iInstallType == ESisInstall )
+ {
+ // Get theme name if such was installed
+ const TDesC& name( LatestThemeL() );
+
+ // Notify about theme installation
+ if ( iPackageUid.iUid == KNcdThemeSisUid || name != KNullDesC )
+ {
+ DLINFO(( _L("Theme installation, theme: %S"), &name ));
+ // Ensure that uid is theme uid
+ iPackageUid.iUid = KNcdThemeSisUid;
+
+ // Set the uid value for the reference parameter
+ aAppUid = iPackageUid;
+
+ if ( name == KNullDesC && iThemePackageUid.iUid != KNcdThemeSisUid )
+ {
+ DLINFO(("Checking theme installation status with package uid, %x",
+ iThemePackageUid.iUid ));
+
+ // Check if the theme was indeed successfully installed
+ TBool themeInstalled( EFalse );
+ TRAP_IGNORE(
+ themeInstalled = IsApplicationInstalledL( iThemePackageUid ) );
+
+ if ( !themeInstalled )
+ {
+ DLINFO(("Theme was not installed"));
+ // Theme was not installed. So, let us suppose that cancel
+ // was success after all
+ aError = KErrCancel;
+ // Because name is KNullDesC, do not set the aFileName here
+ }
+ }
+ else
+ {
+ DLTRACE(("Either theme name was acquired or package uid was theme"));
+ if ( name != KNullDesC )
+ {
+ aFileName = name.AllocL();
+ }
+ aAppUid = iPackageUid;
+ }
+ }
+ else
+ {
+ // Get the actual app UID from sis registry
+ TRAPD( err, aAppUid = SidFromSisRegistryL( iPackageUid ) );
+
+ DLTRACE(("Notify observer about application installation, uid: %x",
+ aAppUid.iUid ));
+
+ if ( err == KErrNotFound )
+ {
+ DLINFO(("Didn't get SID, using package UID: %x",
+ iPackageUid.iUid));
+ aAppUid.iUid = iPackageUid.iUid;
+ err = KErrNone;
+ }
+
+ if ( err == KErrNone )
+ {
+ DLTRACE(("Check the application is actually installed"));
+ TBool installed = IsApplicationInstalledL( aAppUid );
+ if ( !installed )
+ {
+ aError = KErrCancel;
+ }
+ }
+ }
+ }
+ else
+ {
+ DLTRACE(("Was not Java nor SIS install"));
+ // This is executed after a content file has been moved.
+ }
+
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Creates a list of applications that are in ROM but that are not
+// in the SIS or Java registry
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::InitializeRomApplicationListL()
+ {
+ DLTRACEIN((""));
+
+ TApaAppInfo info;
+ ConnectApaLsL();
+ User::LeaveIfError( iApaLs.GetAllApps() );
+
+ iRomUids.Reset();
+
+ RArray<TUid> midletUids;
+ CleanupClosePushL( midletUids );
+
+ MidletUidsL( midletUids );
+
+ DLTRACE(("%d Midlet UIDs", midletUids.Count() ));
+
+#ifdef CATALOGS_BUILD_CONFIG_DEBUG
+ TInt appCount = 0;
+ iApaLs.AppCount( appCount );
+ DLTRACE(("apps: %d", appCount));
+#endif // CATALOGS_BUILD_CONFIG_DEBUG
+
+ // If the application list is not OK after 5 tries, give up
+ // Each break is 0.5 seconds
+ TInt retryCount = 5;
+ TInt appErr = KErrNone;
+
+ do
+ {
+ appErr = iApaLs.GetNextApp( info );
+ if ( appErr == KErrNone )
+ {
+ // App is considered a ROM app if its not found either
+ // in SIS registry or midlet registry
+ // Note: ROM apps can be in SIS registry also but that doesn't
+ // matter because we just want to get a list of apps that are
+ // not found anywhere else but apparc
+ if ( midletUids.Find( info.iUid ) == KErrNotFound &&
+ !iRegistrySession.IsSidPresentL( info.iUid ) )
+ {
+
+ DLTRACE(( _L("Found ROM app: %x, caption: %S, path: %S"),
+ info.iUid.iUid,
+ &info.iCaption,
+ &info.iFullName ));
+ iRomUids.AppendL( info.iUid );
+ }
+ }
+ else if( appErr == RApaLsSession::EAppListInvalid )
+ {
+ // Application list is not yet fully populated
+ // https://jira.bothi.fi/jira/browse/PRECLI-1364
+ if ( retryCount > 0 )
+ {
+ DLINFO(( "Application list not yet populated, waiting" ));
+ User::After( KDelayWhenAppListInvalid );
+ retryCount--;
+ appErr = KErrNone;
+ }
+ else
+ {
+ User::Leave( KErrNotReady );
+ }
+ }
+ // Some unknown error. That shouldn't happen.
+ else if( appErr != RApaLsSession::ENoMoreAppsInList )
+ {
+ DLERROR(("Unknown error with application list. %d", appErr));
+ User::Leave( KErrGeneral );
+ }
+ }
+ while( appErr == KErrNone && retryCount >= 0 );
+
+ iApaLs.Close();
+ CleanupStack::PopAndDestroy( &midletUids );
+
+ DLTRACEOUT(("ROM apps: %d", iRomUids.Count() ));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Gets a list of installed midlet UIDs
+// ---------------------------------------------------------------------------
+//
+#ifdef USE_OLD_JAVA_API
+
+void CNcdInstallationService::MidletUidsL( RArray<TUid>& aUids )
+ {
+ DLTRACEIN((""));
+ MJavaRegistry* javaRegistry = MJavaRegistry::CreateL();
+ CleanupReleasePushL( *javaRegistry );
+ javaRegistry->InstalledMIDletUidsL( aUids );
+ CleanupStack::PopAndDestroy( javaRegistry );
+ }
+
+#else
+
+void CNcdInstallationService::MidletUidsL( RArray<TUid>& aUids )
+ {
+ DLTRACEIN((""));
+ CJavaRegistry* javaRegistry = CJavaRegistry::NewLC();
+ javaRegistry->GetRegistryEntryUidsL( aUids );
+ CleanupStack::PopAndDestroy( javaRegistry );
+ }
+
+#endif
+
+
+// ---------------------------------------------------------------------------
+// Checks if the application is in ROM
+// ---------------------------------------------------------------------------
+//
+TBool CNcdInstallationService::IsRomApplication( const TUid& aUid ) const
+ {
+ DLTRACEIN(("UID: %x", aUid.iUid ));
+ return iRomUids.Find( aUid ) != KErrNotFound;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Returns the UID of the latest installed midlet, NULL UID if none have
+// been installed since the last device restart
+// ---------------------------------------------------------------------------
+//
+#ifdef USE_OLD_JAVA_API
+
+TUid CNcdInstallationService::LatestMidletUidL(
+ MJavaRegistry& aJavaRegistry ) const
+ {
+ DLTRACEIN((""));
+ TInt suiteUid = 0;
+
+ // Get UID for the latest installed Midlet suite
+ // KPSUidJavaLatestInstallation = 0x10282567
+ // Ignoring error in case the key or read policy change so that client
+ // doesn't behave strangely
+ RProperty::Get( KUidSystemCategory,
+ KPSUidJavaLatestInstallation, suiteUid );
+
+ DLTRACE(("JMI UID: %x", suiteUid ));
+
+ if ( !suiteUid )
+ {
+ return KNullUid;
+ }
+
+ // Get entry for the installed suite
+ MJavaRegistrySuiteEntry* suite = aJavaRegistry.SuiteEntryL(
+ TUid::Uid( suiteUid ) );
+ CleanupReleasePushL( *suite );
+ RArray<TUid> suiteUids;
+ CleanupClosePushL( suiteUids );
+
+ TUid midletUid = KNullUid;
+ suite->MIDletUidsL( suiteUids );
+
+ // Take first midlet UID from the suite
+ if ( suiteUids.Count() )
+ {
+ midletUid = suiteUids[0];
+ }
+ DLTRACE(("Midlets in suite: %d", suite->NumberOfMIDletsL() ));
+ CleanupStack::PopAndDestroy( &suiteUids );
+ DLTRACE(("InstalledAppsEntryUid: %x", midletUid.iUid ));
+
+ CleanupStack::PopAndDestroy( suite );
+ return midletUid;
+ }
+
+#else
+
+TUid CNcdInstallationService::LatestMidletUidL(
+ CJavaRegistry& aJavaRegistry ) const
+ {
+ DLTRACEIN((""));
+ TInt suiteUid = 0;
+
+ // Get UID for the latest installed Midlet suite
+ // KPSUidJavaLatestInstallation = 0x10282567
+ // Ignoring error in case the key or read policy change so that client
+ // doesn't behave strangely
+ RProperty::Get( KUidSystemCategory,
+ KPSUidJavaLatestInstallation, suiteUid );
+
+ DLTRACE(("JMI UID: %x", suiteUid ));
+
+ if ( !suiteUid )
+ {
+ return KNullUid;
+ }
+
+ // Get entry for the installed suite
+ CJavaRegistryEntry* suite = aJavaRegistry.RegistryEntryL(
+ TUid::Uid( suiteUid ) );
+
+ if ( !suite )
+ {
+ return KNullUid;
+ }
+
+ CleanupStack::PushL( suite );
+
+ DASSERT( suite->Type() < EGeneralApplication &&
+ suite->Type() >= EGeneralPackage );
+
+ CJavaRegistryPackageEntry* entry =
+ static_cast<CJavaRegistryPackageEntry*>( suite );
+
+ TUid midletUid = KNullUid;
+ TInt count = entry->NumberOfEmbeddedEntries();
+ TBool appFound = EFalse;
+ TInt index = 0;
+
+ // Find the first application from the suite
+ while ( index < count && !appFound )
+ {
+ CJavaRegistryEntry* app = entry->EmbeddedEntryByNumberL( index );
+ if ( app->Type() >= EGeneralApplication )
+ {
+ midletUid = app->Uid();
+ appFound = ETrue;
+ DLTRACE(( "Found app: %x", midletUid.iUid ));
+ }
+ delete app;
+ ++index;
+ }
+
+ CleanupStack::PopAndDestroy( suite );
+ return midletUid;
+ }
+
+
+#endif
+
+// ---------------------------------------------------------------------------
+// Returns true if the MIME type matches a Java application or descriptor
+// ---------------------------------------------------------------------------
+//
+TBool CNcdInstallationService::MatchJava( const TDesC& aMime )
+ {
+ return ( aMime.MatchF( KMimeTypeMatch1JavaApplication ) != KErrNotFound ||
+ aMime.MatchF( KMimeTypeMatch2JavaApplication ) != KErrNotFound ||
+ aMime.MatchF( KMimeTypeMatchJad ) != KErrNotFound );
+ }
+
+
+#ifdef USE_OLD_JAVA_API
+
+TUid CNcdInstallationService::InstalledMidletUidL()
+ {
+ DLTRACEIN((""));
+ RArray<TUid> MIDletUids;
+ CleanupClosePushL( MIDletUids );
+
+ MJavaRegistry* javaRegistry = MJavaRegistry::CreateL();
+ CleanupReleasePushL( *javaRegistry );
+ javaRegistry->InstalledMIDletUidsL( MIDletUids );
+ TUid MIDletUid = KNullUid;
+ // Search for new uids in Java registry.
+ for ( TInt i = 0 ; i < MIDletUids.Count() ; i++ )
+ {
+ if ( iMIDletUids.Find( MIDletUids[i] ) == KErrNotFound )
+ {
+ // A new uid found, this is the installed midlet's uid
+ MIDletUid = MIDletUids[i];
+ break;
+ }
+ }
+
+ // We didn't get any new UID so we have to check Java installer's
+ // P&S key for the installed suite UID and the get the midlet UID
+ // from that. This happens when a midlet with predefined UID,
+ // eg. WidSets, is reinstalled. Midlet UIDs are predefined with
+ // the attribute Nokia-MIDlet-UID-<n> in a JAD or JAR manifest
+ if ( MIDletUid == KNullUid )
+ {
+ MIDletUid = LatestMidletUidL( *javaRegistry );
+ }
+
+ CleanupStack::PopAndDestroy( javaRegistry );
+ CleanupStack::PopAndDestroy( &MIDletUids );
+
+ iMIDletUids.Reset();
+ return MIDletUid;
+ }
+
+#else // USE_OLD_JAVA_API
+
+TUid CNcdInstallationService::InstalledMidletUidL()
+ {
+ DLTRACEIN((""));
+ CJavaRegistry* registry = CJavaRegistry::NewLC();
+ TUid midletUid = LatestMidletUidL( *registry );
+ CleanupStack::PopAndDestroy( registry );
+ return midletUid;
+ }
+
+#endif // USE_OLD_JAVA_API
+
+
+// ---------------------------------------------------------------------------
+// Populates the list of installed widgets
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::PopulateInstalledWidgetUidsL()
+ {
+ DLTRACEIN((""));
+
+ if ( !iWidgetRegistry.Handle() )
+ {
+ User::LeaveIfError( iWidgetRegistry.Connect() );
+ }
+
+ iInstalledWidgets.ResetAndDestroy();
+ User::LeaveIfError( iWidgetRegistry.InstalledWidgetsL( iInstalledWidgets ) );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Gets the name of widget that was installed last
+// ---------------------------------------------------------------------------
+//
+HBufC* CNcdInstallationService::InstalledWidgetNameLC()
+ {
+ DLTRACEIN((""));
+
+ TUid widgetUid = InstalledWidgetUidL();
+
+ if ( widgetUid == KNullUid )
+ {
+ DLERROR(("No widget uid"));
+ // No new UID was found, so we assume user canceled the installation.
+ // Installer does not give any error code in that case.
+ return NULL;
+ }
+
+ HBufC* bundleId = HBufC::NewLC( KWidgetBundleIdLength );
+ TPtr des( bundleId->Des() );
+ iWidgetRegistry.GetWidgetBundleId( widgetUid, des );
+
+ DLTRACEOUT(( _L("Widget bundle id: %S"), bundleId ));
+ return bundleId;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Gets the UID of the widget that was just installed
+// ---------------------------------------------------------------------------
+//
+TUid CNcdInstallationService::InstalledWidgetUidL()
+ {
+ DLTRACEIN((""));
+
+ RWidgetInfoArray widgets;
+ CleanupResetAndDestroyPushL( widgets );
+
+ User::LeaveIfError( iWidgetRegistry.InstalledWidgetsL( widgets ) );
+ DLINFO(("widget count: %d", widgets.Count() ));
+
+ TUid uid( KNullUid );
+
+ const TInt count = widgets.Count();
+ const TInt installedCount = iInstalledWidgets.Count();
+
+ // Try to find a widget that was not installed earlier.
+ for ( TInt i = 0; i < count; ++i )
+ {
+ TBool wasInstalled = EFalse;
+ CWidgetInfo* widgetInfo = widgets[ i ];
+ for ( TInt j = 0; j < installedCount; j++ )
+ {
+ if ( iInstalledWidgets[ j ]->iUid == widgetInfo->iUid )
+ {
+ wasInstalled = ETrue;
+ break;
+ }
+ }
+
+ if ( !wasInstalled )
+ {
+ DLTRACE(("Found installed widget"));
+ uid = widgets[ i ]->iUid;
+ break;
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &widgets );
+
+ DLTRACEOUT(("Installed uid: %x", uid.iUid ));
+ return uid;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Checks from the MIME type and file extension and returns ETrue if
+// either of them matches widgets
+// ---------------------------------------------------------------------------
+//
+TBool CNcdInstallationService::MatchWidget( RFile& aFile, const TDesC& aMime )
+ {
+ DLTRACEIN((""));
+ if ( aMime.CompareF( KMimeTypeMatchWidget ) == 0 )
+ {
+ DLTRACEOUT(( "Mime type matches" ));
+ return ETrue;
+ }
+
+ TBool match = EFalse;
+ TFileName filename;
+ TInt err = aFile.Name( filename );
+ if ( err == KErrNone )
+ {
+ TParsePtrC parse( filename );
+ match = parse.ExtPresent() &&
+ ( KWidgetExtension().CompareF( parse.Ext() ) == 0 );
+ }
+ DLTRACEOUT(( "Filename match: %d", match ));
+ return match;
+ }
+
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CNcdInstallationService::HandleInstalledWidgetL()
+ {
+ DLTRACEIN((""));
+ TUid uid( KNullUid );
+ if ( iInstallError == KErrNone )
+ {
+ uid = InstalledWidgetUidL();
+ if ( uid == KNullUid )
+ {
+ iInstallError = KErrAbort;
+ }
+ }
+
+ iObserver->InstallationCompleteL( KNullDesC, uid, iInstallError );
+ }
+
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool CNcdInstallationService::WidgetExistsL( const TUid& aUid )
+ {
+ DLTRACEIN((""));
+
+ if ( !iWidgetRegistry.Handle() )
+ {
+ User::LeaveIfError( iWidgetRegistry.Connect() );
+ }
+
+ if ( iWidgetRegistry.IsWidget( aUid ) )
+ {
+ TBuf<KWidgetBundleIdLength> id;
+ iWidgetRegistry.GetWidgetBundleId( aUid, id );
+ return iWidgetRegistry.WidgetExistsL( id );
+ }
+ return EFalse;
+ }