menucontentsrv/handlersrc/menuuninstalloperation.cpp
changeset 0 79c6a41cd166
child 1 844b978f8d5e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/menucontentsrv/handlersrc/menuuninstalloperation.cpp	Thu Dec 17 08:54:17 2009 +0200
@@ -0,0 +1,395 @@
+/*
+* Copyright (c) 2009 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:
+*
+*/
+#include <apgcli.h>
+#include <swi/sisregistrysession.h>
+#include <swi/sisregistryentry.h>
+#include <WidgetRegistryClient.h>
+#include <javaregistry.h>
+#include <javaregistrypackageentry.h>
+#include <javaregistryapplicationentry.h>
+#include <mcsmenuutils.h>
+#include "mcsdef.h"
+#include "mcsmenu.h"
+#include "mcsmenuitem.h"
+#include "menuuninstalloperation.h"
+
+_LIT8( KAppMimeType, "x-epoc/x-sisx-app" );
+_LIT8( KMidletMimeType, "application/java-archive" );
+_LIT8( KWidgetMimeType, "application/x-nokia-widget");
+
+const TUid KMidletType = { 0x10210E26 };
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CMenuUninstallOperation::~CMenuUninstallOperation
+// ---------------------------------------------------------
+//
+CMenuUninstallOperation::~CMenuUninstallOperation()
+    {
+    Cancel();
+    iUninstaller.Close();
+    delete iRemoveOperation;
+    }
+
+// ---------------------------------------------------------
+// CMenuUninstallOperation::NewL
+// ---------------------------------------------------------
+//
+CMenuUninstallOperation* CMenuUninstallOperation::NewL(
+    RMenu &aMenu,
+    TInt aPriority,
+    TRequestStatus &aObserverStatus,
+    CMenuItem& aItem )
+    {
+    CMenuUninstallOperation* self;
+
+    self = new ( ELeave ) CMenuUninstallOperation( aMenu, aPriority, aObserverStatus );
+    CleanupStack::PushL( self );
+    self->ConstructL( aItem );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ---------------------------------------------------------
+// CMenuUninstallOperation::CMenuUninstallOperation
+// ---------------------------------------------------------
+//
+CMenuUninstallOperation::CMenuUninstallOperation
+( RMenu &aMenu, TInt aPriority, TRequestStatus &aObserverStatus )
+: CMenuOperation( aMenu, aPriority, aObserverStatus ),
+iState( EIdle ),
+iRemoveOperation( NULL )
+    {
+    CActiveScheduler::Add( this );
+    }
+
+// ---------------------------------------------------------
+// CMenuUninstallOperation::ConstructL
+// ---------------------------------------------------------
+//
+void CMenuUninstallOperation::ConstructL( CMenuItem& aItem )
+    {
+    TBool exists;
+    TPtrC uidAttr( aItem.GetAttributeL( KMenuAttrUid, exists ) );
+    TUint uid;
+    TUid packageUid = KNullUid;
+    TPtrC8 mimeType;
+
+
+    if( !exists )
+        {
+        User::Leave( KErrCorrupt );
+        }
+
+    if( aItem.Flags() & TMenuItem::ELockDelete )
+    	{
+        iObserverStatus = KRequestPending;
+        SetActive();
+        TRequestStatus* status = &iStatus;
+        User::RequestComplete( status, KErrAccessDenied );
+        return;
+    	}
+
+    User::LeaveIfError( iUninstaller.Connect() );
+
+    iId = aItem.Id();
+    
+    // Prepare parameters
+    MenuUtils::GetTUint( uidAttr, uid );
+    
+    AppInfoL( TUid::Uid( uid ), mimeType, packageUid );
+
+    // Commence the uninstallations
+    iUninstaller.Uninstall( iStatus, packageUid, mimeType );
+    iObserverStatus = KRequestPending;
+    if( mimeType == KMidletMimeType()
+            && IsWidgetL( TUid::Uid( uid ) ) )	
+		{
+    	//we remove java type app(it will gain different uid
+		//during next install) and widget type app(it MIGHT get
+		//different uid during next install) from xml
+    	iState = EUninstalling;
+    	}
+    else
+    	{
+    	//if its not java or widget app we leave it in xml,
+    	//appscanner will hide it for later passible reinstallation 
+    	iState = ERemoving;
+    	}
+    
+    SetActive();
+    }
+
+// ---------------------------------------------------------
+// CMenuUninstallOperation::AppInfo
+// ---------------------------------------------------------
+//
+void CMenuUninstallOperation::AppInfoL( const TUid& aAppUid, TPtrC8& aMimeType, TUid& aPackageUid )
+	{
+	TUid typeUid;
+	RApaLsSession apaLsSession;
+
+	User::LeaveIfError( apaLsSession.Connect() );
+	CleanupClosePushL( apaLsSession );
+	User::LeaveIfError( apaLsSession.GetAllApps() );
+
+    if( KErrNone == apaLsSession.GetAppType( typeUid, aAppUid  ) &&
+    		typeUid == KMidletType )
+        {
+        GetJavaSuitUidL( aAppUid, aPackageUid );
+        aMimeType.Set( KMidletMimeType );
+        }
+    else if( IsWidgetL( aAppUid ) )
+        {
+        aPackageUid = aAppUid;
+        aMimeType.Set( KWidgetMimeType );
+        }
+    else
+        {
+        TApaAppInfo appInfo;
+        User::LeaveIfError( apaLsSession.GetAppInfo( appInfo, aAppUid ) );
+        if( !GetInstallPkgUidL( appInfo.iFullName, aPackageUid ) )
+        	{
+        	aPackageUid = aAppUid;
+        	}
+        aMimeType.Set( KAppMimeType );
+        }
+
+    CleanupStack::PopAndDestroy( &apaLsSession );
+	}
+
+// ---------------------------------------------------------
+// CMenuUninstallOperation::GetInstallPkgUidL
+// ---------------------------------------------------------
+//
+TBool CMenuUninstallOperation::GetInstallPkgUidL( const TDesC& aAppFullName, TUid& aPackageUid )
+	{
+	// Search for the full name of the application amongst every file name in
+	// every installed packages.
+	TBool found = EFalse;
+	Swi::RSisRegistrySession iSisRegSession;
+
+	// Get the array of ids of every installed packages
+	if( KErrNone != iSisRegSession.Connect() )
+		{
+		return found;
+		}
+	CleanupClosePushL( iSisRegSession );
+    
+    RArray<TUid> packageIds;
+    CleanupClosePushL( packageIds );
+    
+    iSisRegSession.InstalledUidsL( packageIds );
+    
+    RPointerArray< HBufC > packageFiles;
+    CleanupClosePushL( packageFiles );
+    
+    for( TInt i = 0; i < packageIds.Count() && !found; ++i )
+        {
+        const TUid packageId = packageIds[i];
+        Swi::RSisRegistryEntry packageEntry;
+
+        // Get the array of file names in the current install package and look
+        // if there is one suggesting that the application was installed from
+        // the package.
+        if( KErrNone == packageEntry.Open( iSisRegSession, packageId ) )
+        	{
+	        CleanupClosePushL( packageEntry );
+	        packageEntry.FilesL( packageFiles );
+	        for( TInt pf = 0; pf < packageFiles.Count() && !found; ++pf )
+	            {
+	            if( packageFiles[pf]->FindC( aAppFullName ) == 0 )
+	                {
+	                aPackageUid = packageId;
+	                found = ETrue;
+	                }
+	            }
+	        packageFiles.ResetAndDestroy();
+	        CleanupStack::PopAndDestroy( &packageEntry );    
+        	}
+        }
+        
+    CleanupStack::PopAndDestroy( &packageFiles );
+    CleanupStack::PopAndDestroy( &packageIds );
+    CleanupStack::PopAndDestroy( &iSisRegSession );
+
+    return found;
+	}
+
+// ---------------------------------------------------------
+// CMenuUninstallOperation::GetJavaSuitUidL
+// ---------------------------------------------------------
+//
+void CMenuUninstallOperation::GetJavaSuitUidL( const TUid& aAppUid, TUid& aPackageUid )
+	{
+	Java::CJavaRegistry* javaRegistry;
+	javaRegistry = Java::CJavaRegistry::NewLC();
+
+	Java::CJavaRegistryEntry* regEntry = 
+		javaRegistry->RegistryEntryL( aAppUid );
+	if( regEntry )
+		{
+	CleanupStack::PushL( regEntry );
+
+	Java::TJavaRegistryEntryType entryType = regEntry->Type();
+	
+	if ( ( entryType >= Java::EGeneralPackage ) && 
+			(entryType < Java::EGeneralApplication) )
+		{
+		//package entry
+		aPackageUid = regEntry->Uid();
+		}
+	else 
+		{
+		//application entry
+		Java::CJavaRegistryApplicationEntry* regApplicationEntry = 
+			static_cast<Java::CJavaRegistryApplicationEntry*>( regEntry );
+		Java::CJavaRegistryPackageEntry* regPackageEntry = 
+			regApplicationEntry->PackageEntryL();
+		aPackageUid = regPackageEntry->Uid();
+		delete regPackageEntry;
+		}
+		CleanupStack::PopAndDestroy( regEntry );
+		}
+	else
+		{
+		aPackageUid = aAppUid;
+		}
+	CleanupStack::PopAndDestroy( javaRegistry );
+	}
+
+// ---------------------------------------------------------
+// CMenuUninstallOperation::IsWidget
+// ---------------------------------------------------------
+//
+
+TBool CMenuUninstallOperation::IsWidgetL( const TUid& aAppUid )
+	{
+	RWidgetRegistryClientSession widgetReg;
+	TBool isWidget;
+
+	if( KErrNone != widgetReg.Connect() )
+		{
+		return EFalse;
+		}
+	CleanupClosePushL( widgetReg);
+	isWidget = widgetReg.IsWidget( aAppUid );
+	CleanupStack::PopAndDestroy( &widgetReg );
+
+	return isWidget;
+	}
+
+// ---------------------------------------------------------
+// CMenuUninstallOperation::RunL
+// ---------------------------------------------------------
+//
+void CMenuUninstallOperation::RunL()
+    {
+    if( KErrNone == iStatus.Int() )
+        {
+        switch( iState )
+            {
+            case EUninstalling:
+                {
+                __ASSERT_DEBUG( NULL == iRemoveOperation, User::Invariant() );
+                iState = ERemoving;
+                iRemoveOperation = iMenu.RemoveL( iId, iStatus );
+                SetActive();
+                }
+                break;
+
+            case ERemoving:
+                {
+                delete iRemoveOperation;
+                iRemoveOperation = NULL;
+                iState = EIdle;
+                TRequestStatus* status = &iObserverStatus;
+                User::RequestComplete( status, iStatus.Int() );
+                }
+                break;
+
+            default:
+                // Object is in an unexpected state
+                __ASSERT_DEBUG( 0, User::Invariant() );
+            }
+        }
+    else if ( KErrNotFound == iStatus.Int() && iState == ERemoving )
+    	{
+    	// Most probably: After uninstalling the application the application
+    	// scanner removed the corresponding item from the xml so not finding
+    	// the menuitem is not an error here.
+        delete iRemoveOperation;
+        iRemoveOperation = NULL;
+        iState = EIdle;
+        TRequestStatus* status = &iObserverStatus;
+        User::RequestComplete( status, KErrNone );
+    	}
+    else
+        {
+        // Report error
+        delete iRemoveOperation;
+        iRemoveOperation = NULL;
+        iState = EIdle;
+        TRequestStatus* status = &iObserverStatus;
+        User::RequestComplete( status, iStatus.Int() );
+        }
+    }
+
+// ---------------------------------------------------------
+// CMenuUninstallOperation::DoCancel
+// ---------------------------------------------------------
+//
+void CMenuUninstallOperation::DoCancel()
+    {
+    switch( iState )
+        {
+        case EUninstalling:
+            {
+            iState = EIdle;
+            }
+            break;
+
+        case ERemoving:
+            {
+            delete iRemoveOperation;
+            iRemoveOperation = NULL;
+            iState = EIdle;
+            }
+            break;
+
+        default:
+            // Object is in an unexpected state
+            __ASSERT_DEBUG( 0, User::Invariant() );
+        }
+    iUninstaller.CancelAsyncRequest( SwiUI::ERequestUninstall );
+    // Complete the caller:
+    TRequestStatus* status = &iObserverStatus;
+    User::RequestComplete( status, iStatus.Int() );
+    }
+
+// ---------------------------------------------------------
+// CMenuUninstallOperation::RunError
+// ---------------------------------------------------------
+//
+TInt CMenuUninstallOperation::RunError( TInt aError )
+    {
+    TRequestStatus* status = &iObserverStatus;
+    User::RequestComplete( status, aError );
+
+    return KErrNone;
+    }