diff -r e5618cc85d74 -r 6c158198356e javamanager/javainstaller/javasifplugin/src/javasifplugin.cpp --- a/javamanager/javainstaller/javasifplugin/src/javasifplugin.cpp Thu Jul 15 18:31:06 2010 +0300 +++ b/javamanager/javainstaller/javasifplugin/src/javasifplugin.cpp Thu Aug 19 09:48:13 2010 +0300 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* Copyright (c) 2010 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" @@ -20,33 +20,92 @@ #include #include +#include +#include #include #include -#include -#include +#include +#include #include "comms.h" +#include "commsclientendpoint.h" #include "commsmessage.h" -#include "commsclientendpoint.h" -#include "javasifplugin.h" -#include "javauids.h" -#include "logger.h" +#include "javacommonutils.h" #include "javaoslayer.h" #include "javaprocessconstants.h" #include "javasymbianoslayer.h" +#include "javauids.h" +#include "logger.h" +#include "resultsserver.h" #include "runtimeexception.h" +#include "javasifplugin.h" -using namespace Java::Installer; + +using namespace java::installer; using namespace java::util; using namespace java::comms; _LIT(KPrivateDataCage, "\\private\\"); _LIT(KInboxDataCage, "\\private\\1000484b\\"); +_LIT(KJavaInstallerProcess, "Installer*"); +_LIT(KJavaInstallCopierProcess, "javainstallcopier.exe"); _LIT(KJavaInstallerDataCage, "\\private\\102033e6\\"); _LIT(KJavaInstallerTmp, "\\private\\102033E6\\installer\\tmp\\"); _LIT(KAnyExtension, ".*"); +_LIT(KComponentInfo, " componentinfo"); +_LIT(KCommsResult, " -commsresult="); +_LIT(KJad, " -jad="); +_LIT(KJar, " -jar="); +_LIT(KDoubleQuote, "\""); +_LIT(KInstall, " install"); +_LIT(KSilent, " -silent"); +_LIT(KUninstall, " uninstall"); +_LIT(KCid, " -cid="); +_LIT(KDrive, " -drive="); +_LIT(KYes, "yes"); +_LIT(KNo, "no"); +_LIT(KOcsp, " -ocsp="); +_LIT(KIgnoreOcspWarnings, " -ignore_ocsp_warnings="); +_LIT(KUpgrade, " -upgrade="); +_LIT(KUpgradeData, " -upgrade_data="); +_LIT(KUntrusted, " -untrusted="); +_LIT(KOverwrite, " -overwrite="); +_LIT(KDownload, " -download="); +_LIT(KIap, " -iap="); +_LIT(KSnap, " -snap="); +_LIT(KForceCancel, " -forcecancel"); +_LIT(KBase64, " -base64="); +_LIT(KUsername, " -username="); +_LIT(KPassword, " -password="); +_LIT(KSourceUrl, " -sourceurl="); +_LIT(KCharSet, " -charset="); +_LIT(KJadMimeType, "text/vnd.sun.j2me.app-descriptor"); +_LIT8(K8JadMimeType, "text/vnd.sun.j2me.app-descriptor"); + +// Long Java Installer command lines contain max 2 path names (512 chars max) and +// some options -> 1536 is long enough buffer +const TInt KLongCmdLineLen = 1536; + +// When starting Java Installer for uninstallation the command line is much shorter +const TInt KShortCmdLineLen = 256; + +// Java Installer is executed with same Uid as Java Runtime +_LIT_SECURE_ID(KJavaInstallerSecureID, KJavaMidpSecureId); + +/** + * This function is called to hide the 'Preparing Installation' dialog. + */ +LOCAL_C TInt HidePrepInstDialog(TAny* aPlugin) +{ + CJavaSifPlugin *pPlugin = (CJavaSifPlugin *)aPlugin; + if (NULL != pPlugin) + { + TRAP_IGNORE(pPlugin->HidePrepInstDialogL()); + } + return KErrNone; +} // ============================ MEMBER FUNCTIONS =============================== @@ -61,24 +120,33 @@ CJavaSifPlugin::~CJavaSifPlugin() { - iRFs.Close(); + mRFs.Close(); - TInt nHandles = iHandlesToClose.Count(); + TInt nHandles = mHandlesToClose.Count(); while (nHandles > 0) { nHandles--; - iHandlesToClose[nHandles].Close(); + mHandlesToClose[nHandles].Close(); } - iHandlesToClose.Reset(); + mHandlesToClose.Reset(); + + delete mResultsServer; + mResultsServer = NULL; + + delete mDummyResults; + mDummyResults = NULL; - delete iResultsServer; - iResultsServer = NULL; + delete mDummyInfo; + mDummyInfo = NULL; + + delete mPrepInstDialog; + mPrepInstDialog = NULL; - delete iDummyResults; - iDummyResults = NULL; - - delete iDummyInfo; - iDummyInfo = NULL; + if (mWaitToHideDialog) + { + delete mWaitToHideDialog; + mWaitToHideDialog = NULL; + } } CJavaSifPlugin::CJavaSifPlugin() @@ -87,11 +155,12 @@ void CJavaSifPlugin::ConstructL() { - User::LeaveIfError(iRFs.Connect()); - User::LeaveIfError(iRFs.ShareProtected()); - iResultsServer = NULL; - iDummyResults = COpaqueNamedParams::NewL(); - iDummyInfo = CComponentInfo::NewL(); + User::LeaveIfError(mRFs.Connect()); + User::LeaveIfError(mRFs.ShareProtected()); + mResultsServer = NULL; + mDummyResults = COpaqueNamedParams::NewL(); // codescanner::forgottoputptroncleanupstack + mDummyInfo = CComponentInfo::NewL(); + mWaitToHideDialog = NULL; } void CJavaSifPlugin::GetComponentInfo( @@ -101,7 +170,7 @@ TRequestStatus& aStatus) { RFile fileHandle; - TInt err = fileHandle.Open(iRFs, aFileName, EFileShareReadersOnly | EFileRead); + TInt err = fileHandle.Open(mRFs, aFileName, EFileShareReadersOnly | EFileRead); if (KErrNone != err) { ELOG1(EJavaInstaller, @@ -122,22 +191,37 @@ CComponentInfo& aComponentInfo, TRequestStatus& aStatus) { + if (ExitIfJavaInstallerRunning(*mDummyResults, aStatus)) + { + return; + } + RProcess rJavaInstaller; TFileName fileName; - TBuf<1536> commandLine; + HBufC* pBufCommandLine = NULL; + TRAPD(err, pBufCommandLine = HBufC::NewL(KLongCmdLineLen)) + if (KErrNone != err) + { + TRequestStatus *statusPtr(&aStatus); + User::RequestComplete(statusPtr, err); + return; + } + std::auto_ptr bufCommandLine(pBufCommandLine); + TPtr commandLine = pBufCommandLine->Des(); // Build command line used to pass all necessary info to Java Installer std::auto_ptr installerStarterDll( stringToDes(java::runtime::JAVA_INSTALLER_STARTER_DLL)); commandLine = installerStarterDll->Des(); - commandLine.Append(_L(" componentinfo")); + commandLine.Append(KComponentInfo); // Ask Java Installer to send component info back // as Comms message. 11000 is IPC_ADDRESS_JAVA_SIF_PLUGIN_C Comms endpoint // that our ResultsServer will listen to. - commandLine.Append(_L(" -commsresult=11000")); + commandLine.Append(KCommsResult); + commandLine.AppendNum(IPC_ADDRESS_JAVA_SIF_PLUGIN_C); - TInt err = aFileHandle.FullName(fileName); + err = aFileHandle.FullName(fileName); // Java Installer does not have AllFiles capability. // So if the .jad/.jar file is in the private data cage of @@ -154,42 +238,30 @@ } // Check whether the file is .jad or .jar - RApaLsSession apaSession; - err = apaSession.Connect(); + TBool isJad; + err = IsJadFile(aFileHandle, isJad); if (KErrNone != err) { - ELOG1(EJavaInstaller, - "CJavaSifPlugin::GetComponentInfo RApaLsSession Connect error %d", err); TRequestStatus *statusPtr(&aStatus); User::RequestComplete(statusPtr, err); return; } - TDataType jadFileMimeType(_L8("text/vnd.sun.j2me.app-descriptor")); - TBool isJad = EFalse; - err = apaSession.RecognizeSpecificData(aFileHandle, jadFileMimeType, isJad); - apaSession.Close(); - if (KErrNone != err) - { - // Just log the error - ELOG1(EJavaInstaller, - "CJavaSifPlugin::GetComponentInfo RApaLsSession RecognizeSpecificData error %d", - err); - } if (isJad) { // Installation should be started from JAD file - commandLine.Append(_L(" -jad=")); + commandLine.Append(KJad); } else { // from JAR file - commandLine.Append(_L(" -jar=")); + commandLine.Append(KJar); } + // Filename parameter must be surrounded in double quotes to // ensure that spaces in filename are passed correctly. - commandLine.Append(_L("\"")); + commandLine.Append(KDoubleQuote); commandLine.Append(fileName); - commandLine.Append(_L("\"")); + commandLine.Append(KDoubleQuote); // Start JavaInstaller std::auto_ptr installerProcess( @@ -197,21 +269,7 @@ err = rJavaInstaller.Create(installerProcess->Des(), commandLine); if (KErrNone == err) { - // Destroy old Comms server if it exists - delete iResultsServer; - iResultsServer = NULL; - // Start new Comms server that receives component info and sets it to - // to aComponentInfo. - iResultsServer = new ResultsServer(*iDummyResults, aComponentInfo); - if (NULL == iResultsServer) - { - err = KErrNoMemory; - } - else - { - // Start the server - err = iResultsServer->start(); - } + err = StartResultsServer(*mDummyResults, aComponentInfo); if (KErrNone != err) { // server cannot be started @@ -241,7 +299,16 @@ // Do NOT close rJavaInstaller now -> the caller gets notification when the // process actually closes. - iHandlesToClose.Append(rJavaInstaller); + err = mHandlesToClose.Append(rJavaInstaller); + if ( err ) + { + rJavaInstaller.Close(); + ELOG1(EJavaInstaller, "CJavaSifPlugin::GetComponentInfo mHandles" + "ToClose.Append failed with error %d", err); + TRequestStatus *statusPtr(&aStatus); + User::RequestComplete(statusPtr, err); + return; + } } void CJavaSifPlugin::Install( @@ -252,11 +319,12 @@ TRequestStatus& aStatus) { RFile fileHandle; - TInt err = fileHandle.Open(iRFs, aFileName, EFileShareReadersOnly | EFileRead); + TInt err = fileHandle.Open(mRFs, aFileName, EFileShareReadersOnly | EFileRead); if (KErrNone != err) { ELOG1(EJavaInstaller, "CJavaSifPlugin::Install Opening file for reading failed with error %d", err); + TRAP_IGNORE(aResults.AddIntL(KSifOutParam_ErrCategory, EUnexpectedError)); TRequestStatus *statusPtr(&aStatus); User::RequestComplete(statusPtr, err); return; @@ -273,16 +341,29 @@ COpaqueNamedParams& aResults, TRequestStatus& aStatus) { - RProcess rJavaInstaller; - TFileName fileName; - // Max two path names and some options -> 1536 is enough - TBuf<1536> commandLine; + if (ExitIfJavaInstallerRunning(aResults, aStatus)) + { + return; + } + + // Create buffer for Java Installer command line + HBufC* pBufCommandLine = NULL; + TRAPD(err, pBufCommandLine = HBufC::NewL(KLongCmdLineLen)) + if (KErrNone != err) + { + TRAP_IGNORE(aResults.AddIntL(KSifOutParam_ErrCategory, ELowMemory)); + TRequestStatus *statusPtr(&aStatus); + User::RequestComplete(statusPtr, err); + return; + } + std::auto_ptr bufCommandLine(pBufCommandLine); + TPtr commandLine = pBufCommandLine->Des(); // Build command line used to pass all necessary info to Java Installer std::auto_ptr installerStarterDll( stringToDes(java::runtime::JAVA_INSTALLER_STARTER_DLL)); commandLine = installerStarterDll->Des(); - commandLine.Append(_L(" install")); + commandLine.Append(KInstall); // Check whether this is silent installation TInt silentInstall = 0; @@ -294,175 +375,36 @@ { ELOG(EJavaInstaller, "CJavaSifPlugin::Install The caller did not have TrustedUI capability"); + TRAP_IGNORE(aResults.AddIntL(KSifOutParam_ErrCategory, ESecurityError)); TRequestStatus *statusPtr(&aStatus); User::RequestComplete(statusPtr, KErrPermissionDenied); return; } - commandLine.Append(_L(" -silent")); + commandLine.Append(KSilent); } - - TBool paramFound = EFalse; - TInt intValue = 0; - TDesC desValue = KNullDesC; - - // KSifInParam_Drive -> -drive=install_target_drive (A, B, C, ..., Z) - TRAP_IGNORE(paramFound = aArguments.GetIntByNameL(KSifInParam_Drive, intValue)); - if (paramFound) - { - // Value 0 is 'A:' drive and value 25 is 'Z:' drive - if ((intValue > -1) && (intValue < 26)) - { - commandLine.Append(_L(" -drive=")); - TChar drive('A'); - drive += intValue; - commandLine.Append(drive); - } - else - { - WLOG1(EJavaInstaller, - "CJavaSifPlugin::Install Ignoring illegal KSifInParam_Drive param (value %d)", - intValue); - } - } - - // KSifInParam_PerformOCSP Yes/No/AskUser -> -ocsp=yes|no - TRAP_IGNORE(paramFound = aArguments.GetIntByNameL(KSifInParam_PerformOCSP, intValue)); - if (paramFound) + else { - if (intValue == 0) // Yes - { - commandLine.Append(_L(" -ocsp=yes")); - } - else if (intValue == 1) // No - { - commandLine.Append(_L(" -ocsp=no")); - } - // AskUser is not supported - } - - // KSifInParam_IgnoreOCSPWarnings Yes/No/AskUser -> -ignore_ocsp_warnings=yes|no - TRAP_IGNORE(paramFound = aArguments.GetIntByNameL(KSifInParam_IgnoreOCSPWarnings, intValue)); - if (paramFound) - { - if (intValue == 0) // Yes - { - commandLine.Append(_L(" -ignore_ocsp_warnings=yes")); - } - else if (intValue == 1) // No - { - commandLine.Append(_L(" -ignore_ocsp_warnings=no")); - } - // AskUser is not supported - } - - // KSifInParam_AllowUpgrade Yes/No/AskUser -> -upgrade=yes|no - TRAP_IGNORE(paramFound = aArguments.GetIntByNameL(KSifInParam_AllowUpgrade, intValue)); - if (paramFound) - { - if (intValue == 0) // Yes - { - commandLine.Append(_L(" -upgrade=yes")); - } - else if (intValue == 1) // No - { - commandLine.Append(_L(" -upgrade=no")); - } - // AskUser is not supported + // Uncomment this to enable 'preparing installation' dialog. + //TRAP(err, CreatePrepInstDialogL()); + //if (KErrNone != err) + //{ + // WLOG1(EJavaInstaller, + // "CJavaSifPlugin::Install Creating preparing installation dialog failed, err=%d", + // err); + //} } - // KSifInParam_AllowUntrusted Yes/No/AskUser -> -untrusted=yes|no - TRAP_IGNORE(paramFound = aArguments.GetIntByNameL(KSifInParam_AllowUntrusted, intValue)); - if (paramFound) - { - if (intValue == 0) // Yes - { - commandLine.Append(_L(" -untrusted=yes")); - } - else if (intValue == 1) // No - { - commandLine.Append(_L(" -untrusted=no")); - } - // AskUser is not supported - } - - // KSifInParam_AllowOverwrite Yes/No/AskUser -> -overwrite=yes|no - TRAP_IGNORE(paramFound = aArguments.GetIntByNameL(KSifInParam_AllowOverwrite, intValue)); - if (paramFound) - { - if (intValue == 0) // Yes - { - commandLine.Append(_L(" -overwrite=yes")); - } - else if (intValue == 1) // No - { - commandLine.Append(_L(" -overwrite=no")); - } - // AskUser is not supported - } - - // KSifInParam_AllowDownload Yes/No/AskUser -> -download=yes|no - TRAP_IGNORE(paramFound = aArguments.GetIntByNameL(KSifInParam_AllowDownload, intValue)); - if (paramFound) - { - if (intValue == 0) // Yes - { - commandLine.Append(_L(" -download=yes")); - } - else if (intValue == 1) // No - { - commandLine.Append(_L(" -download=no")); - } - // AskUser is not supported - } - - // KSifInParam_UserName -> -username=download_username - TRAP_IGNORE(desValue = aArguments.StringByNameL(KSifInParam_UserName)); - if (desValue.Length() > 0) - { - commandLine.Append(_L(" -username=")); - commandLine.Append(desValue); - } - - // KSifInParam_Password -> -password=download_password - TRAP_IGNORE(desValue = aArguments.StringByNameL(KSifInParam_Password)); - if (desValue.Length() > 0) - { - commandLine.Append(_L(" -password=")); - commandLine.Append(desValue); - } - - // KSifInParam_SourceUrl -> -sourceurl=original (HTTP) URL of the JAD or JAR file - TRAP_IGNORE(desValue = aArguments.StringByNameL(KSifInParam_SourceUrl)); - if (desValue.Length() > 0) - { - commandLine.Append(_L(" -sourceurl=")); - commandLine.Append(desValue); - } - - // KSifInParam_IAP -> -iap=IAP_ID (internet access point id) - TRAP_IGNORE(paramFound = aArguments.GetIntByNameL(KSifInParam_IAP, intValue)); - if (paramFound) - { - commandLine.Append(_L(" -iap=")); - commandLine.AppendNum(intValue); - } - - // KSifInParam_Charset -> -charset=Internet-standard character set name - TRAP_IGNORE(desValue = aArguments.StringByNameL(KSifInParam_Charset)); - if (desValue.Length() > 0) - { - commandLine.Append(_L(" -charset=")); - commandLine.Append(desValue); - } - + BuildInstallCommandLine(commandLine, aArguments); // Ask Java Installer to send installation results back // as Comms message. 11000 is IPC_ADDRESS_JAVA_SIF_PLUGIN_C Comms endpoint // that our ResultsServer will listen to. - commandLine.Append(_L(" -commsresult=11000")); + commandLine.Append(KCommsResult); + commandLine.AppendNum(IPC_ADDRESS_JAVA_SIF_PLUGIN_C); - TInt err = aFileHandle.FullName(fileName); + TFileName fileName; + err = aFileHandle.FullName(fileName); // Java Installer does not have AllFiles capability. // So if the .jad/.jar file is in the private data cage of @@ -473,74 +415,53 @@ TRAP(err, CopyFilesIfNeededL(fileName)); if (KErrNone != err) { + TRAP_IGNORE(aResults.AddIntL(KSifOutParam_ErrCategory, EUnexpectedError)); TRequestStatus *statusPtr(&aStatus); User::RequestComplete(statusPtr, err); return; } // Check whether the file is .jad or .jar - RApaLsSession apaSession; - err = apaSession.Connect(); + TBool isJad = EFalse; + err = IsJadFile(aFileHandle, aArguments, isJad); if (KErrNone != err) { - ELOG1(EJavaInstaller, - "CJavaSifPlugin::Install RApaLsSession Connect error %d", err); + TRAP_IGNORE(aResults.AddIntL(KSifOutParam_ErrCategory, EUnexpectedError)); TRequestStatus *statusPtr(&aStatus); User::RequestComplete(statusPtr, err); return; } - TDataType jadFileMimeType(_L8("text/vnd.sun.j2me.app-descriptor")); - TBool isJad = EFalse; - err = apaSession.RecognizeSpecificData(aFileHandle, jadFileMimeType, isJad); - apaSession.Close(); - if (KErrNone != err) - { - ELOG1(EJavaInstaller, - "CJavaSifPlugin::Install RApaLsSession RecognizeSpecificData error %d", err); - } if (isJad) { // Installation should be started from JAD file - commandLine.Append(_L(" -jad=")); + commandLine.Append(KJad); } else { // from JAR file - commandLine.Append(_L(" -jar=")); + commandLine.Append(KJar); } // Filename parameter must be surrounded in double quotes to // ensure that spaces in filename are passed correctly. - commandLine.Append(_L("\"")); + commandLine.Append(KDoubleQuote); commandLine.Append(fileName); - commandLine.Append(_L("\"")); + commandLine.Append(KDoubleQuote); // Start JavaInstaller std::auto_ptr installerProcess( stringToDes(java::runtime::JAVA_PROCESS)); + RProcess rJavaInstaller; err = rJavaInstaller.Create(installerProcess->Des(), commandLine); if (KErrNone == err) { - // Destroy old Comms server if it exists - delete iResultsServer; - iResultsServer = NULL; - // Start new Comms server that receives component ids, sets them - // to aResults. - iResultsServer = new ResultsServer(aResults, *iDummyInfo); - if (NULL == iResultsServer) - { - err = KErrNoMemory; - } - else - { - // Start the server - err = iResultsServer->start(); - } + err = StartResultsServer(aResults, *mDummyInfo); if (KErrNone != err) { // server cannot be started rJavaInstaller.Close(); ELOG1(EJavaInstaller, "CJavaSifPlugin::Install: Cannot start results server, err %d", err); + TRAP_IGNORE(aResults.AddIntL(KSifOutParam_ErrCategory, EUnexpectedError)); TRequestStatus *statusPtr(&aStatus); User::RequestComplete(statusPtr, err); return; @@ -555,37 +476,81 @@ rJavaInstaller.Close(); ELOG1(EJavaInstaller, "CJavaSifPlugin::Install: starting JavaInstaller failed, err=%d", err); + TRAP_IGNORE(aResults.AddIntL(KSifOutParam_ErrCategory, EUnexpectedError)); TRequestStatus *statusPtr(&aStatus); User::RequestComplete(statusPtr, err); return; } + if (!silentInstall) + { + TRAP(err, mWaitToHideDialog = + CAsyncWaitCallBack::NewL(TCallBack(HidePrepInstDialog, this))); + if (KErrNone == err) + { + // The active object will wait until JavaInstaller process calls Rendezvous. + // If JavaInstaller specifies reason code EJavaInstaller, then + // the active object will call callback function that will hide the + // 'Preparing installation' dialog. If reason code is not EJavaInstaller, + // the wait object will automatically wait for the next rendezvous. + mWaitToHideDialog->Wait( rJavaInstaller, EJavaInstaller ); + } + else + { + ELOG1(EJavaInstaller, "CJavaSifPlugin::Install: Creating " + "mWaitToHideDialog failed, err %d", err); + } + } rJavaInstaller.Resume(); // Do NOT close rJavaInstaller now -> the caller gets notification when the // process actually closes. - iHandlesToClose.Append(rJavaInstaller); + err = mHandlesToClose.Append(rJavaInstaller); + if ( err ) + { + rJavaInstaller.Close(); + ELOG1(EJavaInstaller, "CJavaSifPlugin::Install mHandles" + "ToClose.Append failed with error %d", err); + TRAP_IGNORE(aResults.AddIntL(KSifOutParam_ErrCategory, ELowMemory)); + TRequestStatus *statusPtr(&aStatus); + User::RequestComplete(statusPtr, err); + return; + } + } void CJavaSifPlugin::Uninstall( TComponentId aComponentId, const TSecurityContext& aSecurityContext, const COpaqueNamedParams& aArguments, - COpaqueNamedParams& /* aResults */, + COpaqueNamedParams& aResults, TRequestStatus& aStatus) { - RProcess rJavaInstaller; - TFileName fileName; - // Max one uid and some options -> 256 is enough - TBuf<256> commandLine; + if (ExitIfJavaInstallerRunning(aResults, aStatus)) + { + return; + } + + // Allocate buffer for Java Installer command line + HBufC* pBufCommandLine = NULL; + TRAPD(err, pBufCommandLine = HBufC::NewL(KShortCmdLineLen)) + if (KErrNone != err) + { + TRAP_IGNORE(aResults.AddIntL(KSifOutParam_ErrCategory, ELowMemory)); + TRequestStatus *statusPtr(&aStatus); + User::RequestComplete(statusPtr, err); + return; + } + std::auto_ptr bufCommandLine(pBufCommandLine); + TPtr commandLine = pBufCommandLine->Des(); // Build command line used to pass all necessary info to Java Installer std::auto_ptr installerStarterDll( stringToDes(java::runtime::JAVA_INSTALLER_STARTER_DLL)); commandLine = installerStarterDll->Des(); - commandLine.Append(_L(" uninstall")); + commandLine.Append(KUninstall); - commandLine.Append(_L(" -cid=")); + commandLine.Append(KCid); commandLine.AppendNum(aComponentId); // Check whether this is silent uninstallation @@ -598,24 +563,35 @@ { ELOG(EJavaInstaller, "CJavaSifPlugin::Uninstall The caller did not have TrustedUI capability"); + TRAP_IGNORE(aResults.AddIntL(KSifOutParam_ErrCategory, ESecurityError)); TRequestStatus *statusPtr(&aStatus); User::RequestComplete(statusPtr, KErrPermissionDenied); return; } - commandLine.Append(_L(" -silent")); + commandLine.Append(KSilent); } - // No need to start iResultsServer because Uninstall() does not - // return anything usefull in aResults. We could return extended - // error code there. - // start JavaInstaller std::auto_ptr installerProcess( stringToDes(java::runtime::JAVA_PROCESS)); - TInt err = rJavaInstaller.Create(installerProcess->Des(), commandLine); + RProcess rJavaInstaller; + err = rJavaInstaller.Create(installerProcess->Des(), commandLine); if (KErrNone == err) { + err = StartResultsServer(aResults, *mDummyInfo); + if (KErrNone != err) + { + // server cannot be started + rJavaInstaller.Close(); + ELOG1(EJavaInstaller, + "CJavaSifPlugin::Uninstall: Cannot start results server, err %d", err); + TRAP_IGNORE(aResults.AddIntL(KSifOutParam_ErrCategory, EUnexpectedError)); + TRequestStatus *statusPtr(&aStatus); + User::RequestComplete(statusPtr, err); + return; + } + // the exit status of Java Installer will be passed to // the asynch caller through aStatus rJavaInstaller.Logon(aStatus); @@ -627,6 +603,7 @@ rJavaInstaller.Close(); ELOG1(EJavaInstaller, "CJavaSifPlugin::Uninstall: starting JavaInstaller failed, err=%d", err); + TRAP_IGNORE(aResults.AddIntL(KSifOutParam_ErrCategory, EUnexpectedError)); TRequestStatus *statusPtr(&aStatus); User::RequestComplete(statusPtr, err); return; @@ -634,7 +611,17 @@ // Do NOT close rJavaInstaller now -> the caller gets notification when the // process actually closes. - iHandlesToClose.Append(rJavaInstaller); + err = mHandlesToClose.Append(rJavaInstaller); + if ( err ) + { + rJavaInstaller.Close(); + ELOG1(EJavaInstaller, "CJavaSifPlugin::Uninstall mHandles" + "ToClose.Append failed with error %d", err); + TRAP_IGNORE(aResults.AddIntL(KSifOutParam_ErrCategory, ELowMemory)); + TRequestStatus *statusPtr(&aStatus); + User::RequestComplete(statusPtr, err); + return; + } } void CJavaSifPlugin::Activate( @@ -664,7 +651,7 @@ // Send cancel message to Java Installer // Check whether there is anything to cancel - if (iHandlesToClose.Count() < 1) + if (mHandlesToClose.Count() < 1) { // No Java Installer process running, do nothing WLOG(EJavaInstaller, @@ -672,64 +659,47 @@ return; } - try - { - CommsMessage message; - message.setModuleId(PLUGIN_ID_SAMPLE_C); - message.setReceiver(IPC_ADDRESS_JAVA_INSTALLER_SERVER_C); - message.setSender(IPC_ADDRESS_JAVA_SIF_PLUGIN_C); - message.setMessageId(INSTALLER_CANCEL_MESSAGE_ID); + CommsMessage message; + message.setReceiver(IPC_ADDRESS_JAVA_INSTALLER_SERVER_C); + message.setSender(IPC_ADDRESS_JAVA_SIF_PLUGIN_C); + message.setMessageId(INSTALLER_CANCEL_MESSAGE_ID); - CommsMessage replyMessage; - int timeout = 10; // 10 seconds + CommsMessage replyMessage; + int timeout = 10; // 10 seconds // codescanner::magicnumbers - CommsClientEndpoint comms; - int err = comms.connect(IPC_ADDRESS_JAVA_INSTALLER_SERVER_C); - if (KErrNone == err) - { - err = comms.sendReceive(message, replyMessage, timeout); - } - else - { - // Cannot connect to Java Installer Comms end point, - // for example Java Installer is still starting up or - // already exiting - WLOG1(EJavaInstaller, - "CJavaSifPlugin:CancelOperation: Cannot connect to Java Installer " - "Comms end point, err %d", err); - return; - } - if (err != 0) - { - // Sending message to Java Installer failed. - ELOG1(EJavaInstaller, - "CJavaSifPlugin:CancelOperation: Cannot send message to Java Installer, err %d", - err); - // Ignore possible errors in disconnect - (void)comms.disconnect(); - return; - } - - // Ignore the cancel result returned in replyMessage - // because current SIF API does not return cancel result - - // Ignore possible errors in disconnect - (void)comms.disconnect(); + CommsClientEndpoint comms; + int err = comms.connect(IPC_ADDRESS_JAVA_INSTALLER_SERVER_C); + if (KErrNone == err) + { + err = comms.sendReceive(message, replyMessage, timeout); } - catch (ExceptionBase& e) + else { - ELOG1(EJavaInstaller, - "CJavaSifPlugin: Send cancel msg failed: ExceptionBase caught: %s ", - e.toString().c_str()); + // Cannot connect to Java Installer Comms end point, + // for example Java Installer is still starting up or + // already exiting + WLOG1(EJavaInstaller, + "CJavaSifPlugin:CancelOperation: Cannot connect to Java Installer " + "Comms end point, err %d", err); return; } - catch (std::exception& e) + if (err != 0) { + // Sending message to Java Installer failed. ELOG1(EJavaInstaller, - "CJavaSifPlugin: Send cancel msg failed: Exception %s caught", e.what()); + "CJavaSifPlugin:CancelOperation: Cannot send message to Java Installer, err %d", + err); + // Ignore possible errors in disconnect + (void)comms.disconnect(); // codescanner::voidparameter return; } + // Ignore the cancel result returned in replyMessage + // because current SIF API does not return cancel result + + // Ignore possible errors in disconnect + (void)comms.disconnect(); // codescanner::voidparameter + // It takes some time before Java Installer had really cancelled // the operation and exited. Wait for it to happen because this function // must return only after the original asynchronous call is completed. @@ -737,14 +707,14 @@ // This array contains process handles for all Java Installer processes // started from this sif plugin. The last handle is the active one. // Check if it is still running - if (iHandlesToClose[iHandlesToClose.Count()-1].ExitReason() != 0) + if (mHandlesToClose[mHandlesToClose.Count()-1].ExitReason() != 0) { // Process has already closed return; } // Wait until it exits - iHandlesToClose[iHandlesToClose.Count()-1].Logon(status); - User::WaitForRequest(status); + mHandlesToClose[mHandlesToClose.Count()-1].Logon(status); + User::WaitForRequest(status); // codescanner::userWaitForRequest // Ignore the exit status of Java Installer because current SIF API // does not return cancel result @@ -755,7 +725,7 @@ { // Check if the file is in the private data cage of some process TInt idx = aFileName.FindF(KPrivateDataCage); - if ((idx != KErrNotFound) && (idx < 3)) + if ((idx != KErrNotFound) && (idx < 3)) // codescanner::magicnumbers { // In case of device Inbox or Java Installer itself do nothing if ((aFileName.FindF(KInboxDataCage) != KErrNotFound) || @@ -770,19 +740,37 @@ // (aFileName is \., copy \.* // to Java Installer tmp dir.) TParse fp; - iRFs.Parse(aFileName, fp); - - CFileMan* fm = CFileMan::NewL(iRFs); + mRFs.Parse(aFileName, fp); TFileName filesToCopy = fp.DriveAndPath(); filesToCopy.Append(fp.Name()); filesToCopy.Append(KAnyExtension); - TInt err = fm->Copy(filesToCopy, KJavaInstallerTmp, CFileMan::ERecurse); - delete fm; - if (KErrNone != err) + + // Use JavaInstallCopier.exe to copy the files. + RProcess rJavaInstallCopier; + TInt err = rJavaInstallCopier.Create( + KJavaInstallCopierProcess, filesToCopy); + if (KErrNone == err) { + TRequestStatus status; + rJavaInstallCopier.Logon(status); + rJavaInstallCopier.Resume(); + User::WaitForRequest(status); // codescanner::userWaitForRequest + err = rJavaInstallCopier.ExitReason(); + rJavaInstallCopier.Close(); + if (KErrNone != err) + { + ELOG1(EJavaInstaller, + "CJavaSifPlugin::CopyFilesIfNeededL: copying files " + "to JavaInstaller data cage failed, err=%d", err); + User::Leave(err); + } + } + else + { + rJavaInstallCopier.Close(); ELOG1(EJavaInstaller, - "CJavaSifPlugin::CopyFilesIfNeededL: copying files " - "to Java Installer data cage failed, err=%d", err); + "CJavaSifPlugin::CopyFilesIfNeededL: starting " + "JavaInstallCopier failed, err=%d", err); User::Leave(err); } @@ -795,4 +783,446 @@ return; } + +TInt CJavaSifPlugin::IsJadFile( + RFile& aFileHandle, + const COpaqueNamedParams& aArguments, + TBool& aIsJad) +{ + TBool mimeTypeGiven = EFalse; + + TRAP_IGNORE( + const TDesC &desValue = aArguments.StringByNameL(KSifInParam_MimeType); + if (desValue.Length() > 0) + { + mimeTypeGiven = ETrue; + if (!desValue.Compare(KJadMimeType)) + { + aIsJad = ETrue; + } + else + { + aIsJad = EFalse; + } + } + ) + if (mimeTypeGiven) + { + return KErrNone; + } + + // Mime type was not given in the input arguments, must check the contents + // of the file itself + return IsJadFile(aFileHandle, aIsJad); +} + + +TInt CJavaSifPlugin::IsJadFile( + RFile& aFileHandle, + TBool& aIsJad) +{ + RApaLsSession apaSession; + TInt err = apaSession.Connect(); + if (KErrNone != err) + { + ELOG1(EJavaInstaller, + "CJavaSifPlugin::IsJadFile RApaLsSession Connect error %d", err); + return err; + } + + TDataType jadFileMimeType(K8JadMimeType); + err = apaSession.RecognizeSpecificData(aFileHandle, jadFileMimeType, aIsJad); + apaSession.Close(); + if (KErrNone != err) + { + // Just log the error + ELOG1(EJavaInstaller, + "CJavaSifPlugin::IsJadFile RApaLsSession RecognizeSpecificData error %d", + err); + return err; + } + + return KErrNone; +} + + +void CJavaSifPlugin::BuildInstallCommandLine( + TPtr& aCommandLine, + const COpaqueNamedParams& aArguments) +{ + // KSifInParam_Drive -> -drive=install_target_drive (A, B, C, ..., Z) + TInt intValue = GetPositiveIntParam(KSifInParam_Drive, aArguments); + // Value 0 is 'A:' drive and value 25 is 'Z:' drive + if ((intValue > -1) && (intValue < 26)) // codescanner::magicnumbers + { + aCommandLine.Append(KDrive); + TChar drive('A'); + drive += intValue; + aCommandLine.Append(drive); + } + + // KSifInParam_PerformOCSP Yes/No/AskUser -> -ocsp=yes|no + intValue = GetPositiveIntParam(KSifInParam_PerformOCSP, aArguments); + if (intValue == 0) // Yes + { + aCommandLine.Append(KOcsp); + aCommandLine.Append(KYes); + } + else if (intValue == 1) // No + { + aCommandLine.Append(KOcsp); + aCommandLine.Append(KNo); + } + // AskUser is not supported + + // KSifInParam_IgnoreOCSPWarnings Yes/No/AskUser -> -ignore_ocsp_warnings=yes|no + intValue = GetPositiveIntParam(KSifInParam_IgnoreOCSPWarnings, aArguments); + if (intValue == 0) // Yes + { + aCommandLine.Append(KIgnoreOcspWarnings); + aCommandLine.Append(KYes); + } + else if (intValue == 1) // No + { + aCommandLine.Append(KIgnoreOcspWarnings); + aCommandLine.Append(KNo); + } + // AskUser is not supported + + // KSifInParam_AllowUpgrade Yes/No/AskUser -> -upgrade=yes|no + intValue = GetPositiveIntParam(KSifInParam_AllowUpgrade, aArguments); + if (intValue == 0) // Yes + { + aCommandLine.Append(KUpgrade); + aCommandLine.Append(KYes); + } + else if (intValue == 1) // No + { + aCommandLine.Append(KUpgrade); + aCommandLine.Append(KNo); + } + // AskUser is not supported + + // KSifInParam_AllowUpgradeData Yes/No/AskUser -> -upgrade_data=yes|no + intValue = GetPositiveIntParam(KSifInParam_AllowUpgradeData, aArguments); + if (intValue == 0) // Yes + { + aCommandLine.Append(KUpgradeData); + aCommandLine.Append(KYes); + } + else if (intValue == 1) // No + { + aCommandLine.Append(KUpgradeData); + aCommandLine.Append(KNo); + } + // AskUser is not supported + + // KSifInParam_AllowUntrusted Yes/No/AskUser -> -untrusted=yes|no + intValue = GetPositiveIntParam(KSifInParam_AllowUntrusted, aArguments); + if (intValue == 0) // Yes + { + aCommandLine.Append(KUntrusted); + aCommandLine.Append(KYes); + } + else if (intValue == 1) // No + { + aCommandLine.Append(KUntrusted); + aCommandLine.Append(KNo); + } + // AskUser is not supported + + // KSifInParam_AllowOverwrite Yes/No/AskUser -> -overwrite=yes|no + intValue = GetPositiveIntParam(KSifInParam_AllowOverwrite, aArguments); + if (intValue == 0) // Yes + { + aCommandLine.Append(KOverwrite); + aCommandLine.Append(KYes); + } + else if (intValue == 1) // No + { + aCommandLine.Append(KOverwrite); + aCommandLine.Append(KNo); + } + // AskUser is not supported + + // KSifInParam_AllowDownload Yes/No/AskUser -> -download=yes|no + intValue = GetPositiveIntParam(KSifInParam_AllowDownload, aArguments); + if (intValue == 0) // Yes + { + aCommandLine.Append(KDownload); + aCommandLine.Append(KYes); + } + else if (intValue == 1) // No + { + aCommandLine.Append(KDownload); + aCommandLine.Append(KNo); + } + // AskUser is not supported + + // KSifInParam_IAP -> -iap=IAP_ID (internet access point id) + intValue = GetPositiveIntParam(KSifInParam_IAP, aArguments); + if (intValue > -1) + { + // IAP ids are always positive + aCommandLine.Append(KIap); + aCommandLine.AppendNum(intValue); + } + + // KSifInParam_SNAP -> -snap=SNAP_ID (service network access point id) + intValue = GetPositiveIntParam(KSifInParam_SNAP, aArguments); + if (intValue > -1) + { + // SNAP ids are always positive + aCommandLine.Append(KSnap); + aCommandLine.AppendNum(intValue); + } + + // When this param is given, Java Installer will cancel installation + // before committing anything. This option is for debugging purposes only. + // KForceCancel -> -forcecancel + // The value of parameter is ignored + TRAP_IGNORE( + const TDesC &desValue = aArguments.StringByNameL(KForceCancel); + if (desValue.Length() > 0) + { + aCommandLine.Append(KForceCancel); + } + ) + + std::wstring base64EncodedArgs; + // KSifInParam_UserName -> -username=download_username + TRAP_IGNORE( + const TDesC &desValue = aArguments.StringByNameL(KSifInParam_UserName); + if (desValue.Length() > 0) + { + try + { + std::wstring value((wchar_t *)(desValue.Ptr()), desValue.Length()); + std::wstring encodedValue = JavaCommonUtils::wbase64encode(value); + aCommandLine.Append(KUsername); + aCommandLine.Append( + (const unsigned short *)encodedValue.c_str(), (int)encodedValue.length()); + base64EncodedArgs.append(L"username,"); + } + catch (std::exception& e) + { + ELOG1(EJavaInstaller, + "CJavaSifPlugin::BuildInstallCommandLine Base64 encoding user " + "name failed, err %s", e.what()); + } + } + ) + + // KSifInParam_Password -> -password=download_password + TRAP_IGNORE( + const TDesC &desValue = aArguments.StringByNameL(KSifInParam_Password); + if (desValue.Length() > 0) + { + try + { + std::wstring value((wchar_t *)(desValue.Ptr()), desValue.Length()); + std::wstring encodedValue = JavaCommonUtils::wbase64encode(value); + aCommandLine.Append(KPassword); + aCommandLine.Append( + (const unsigned short *)encodedValue.c_str(), (int)encodedValue.length()); + base64EncodedArgs.append(L"password,"); + } + catch (std::exception& e) + { + ELOG1(EJavaInstaller, + "CJavaSifPlugin::BuildInstallCommandLine Base64 encoding password " + "failed, err %s", e.what()); + } + } + ) + + // KSifInParam_SourceUrl -> -sourceurl=original (HTTP) URL of the JAD or JAR file + TRAP_IGNORE( + const TDesC &desValue = aArguments.StringByNameL(KSifInParam_SourceUrl); + if (desValue.Length() > 0) + { + try + { + std::wstring value((wchar_t *)(desValue.Ptr()), desValue.Length()); + std::wstring encodedValue = JavaCommonUtils::wbase64encode(value); + aCommandLine.Append(KSourceUrl); + aCommandLine.Append( + (const unsigned short *)encodedValue.c_str(), (int)encodedValue.length()); + base64EncodedArgs.append(L"sourceurl,"); + } + catch (std::exception& e) + { + ELOG1(EJavaInstaller, + "CJavaSifPlugin::BuildInstallCommandLine Base64 encoding source " + "url failed, err %s", e.what()); + } + } + ) + + // KSifInParam_Charset -> -charset=Internet-standard character set name + TRAP_IGNORE( + const TDesC &desValue = aArguments.StringByNameL(KSifInParam_Charset); + if (desValue.Length() > 0) + { + try + { + std::wstring value((wchar_t *)(desValue.Ptr()), desValue.Length()); + std::wstring encodedValue = JavaCommonUtils::wbase64encode(value); + aCommandLine.Append(KCharSet); + aCommandLine.Append( + (const unsigned short *)encodedValue.c_str(), (int)encodedValue.length()); + base64EncodedArgs.append(L"charset,"); + } + catch (std::exception& e) + { + ELOG1(EJavaInstaller, + "CJavaSifPlugin::BuildInstallCommandLine Base64 encoding charset " + "failed, err %s", e.what()); + } + } + ) + + if (base64EncodedArgs.length() > 0) + { + // Tell Java Installer which arguments have been Base64 encoded + aCommandLine.Append(KBase64); + aCommandLine.Append( + (const unsigned short *)base64EncodedArgs.c_str(), (int)base64EncodedArgs.length()); + } + + return; +} + +TInt CJavaSifPlugin::GetPositiveIntParam( + const TDesC& aName, + const COpaqueNamedParams& aArguments) +{ + // Assume that the value will not be found + TInt intValue = -1; + + // If the value can be read, intValue will be set, otherwise this function + // returns -1 + TRAP_IGNORE((void)aArguments.GetIntByNameL(aName, intValue)); // codescanner::voidparameter + + return intValue; +} + + +TInt CJavaSifPlugin::StartResultsServer( + COpaqueNamedParams& aResults, + CComponentInfo& aComponentInfo) +{ + // Destroy old Comms server if it exists + delete mResultsServer; + mResultsServer = NULL; + + // Start new Comms server + mResultsServer = new ResultsServer(aResults, aComponentInfo); // codescanner::nonleavenew + if (NULL == mResultsServer) + { + return KErrNoMemory; + } + else + { + // Start the server + return mResultsServer->start(); + } +} + + +TBool CJavaSifPlugin::ExitIfJavaInstallerRunning( + COpaqueNamedParams& aResults, + TRequestStatus& aStatus) +{ + // If Java Installer is already running, set error category EInstallerBusy etc + // to aResults and return + + TInt err(KErrNone); + RProcess proc; + TFindProcess finder(KJavaInstallerProcess); + TFullName procName; + + // Java Installer process SID is 0x102033E6 and name is "Installer" + while (finder.Next(procName) == KErrNone) + { + if (proc.Open(finder) != KErrNone) + { + continue; + } + if (proc.SecureId() == KJavaInstallerSecureID) + { + if (proc.ExitType() == EExitPending) + { + // Java Installer process is already running + proc.Close(); + + // return error information + TRAP(err, aResults.AddIntL(KSifOutParam_ErrCategory, EInstallerBusy)); + if (KErrNone != err) + { + ELOG1(EJavaInstaller, + "CJavaSifPlugin::ExitIfJavaInstallerRunning aResults.AddIntL " + "ErrCategory err %d", err); + } + + TRAP(err, aResults.AddIntL(KSifOutParam_ErrCode, KErrInUse)); + if (KErrNone != err) + { + ELOG1(EJavaInstaller, + "CJavaSifPlugin::ExitIfJavaInstallerRunning aResults.AddIntL " + "ErrCode err %d", err); + } + + TRAP(err, aResults.AddIntL(KSifOutParam_ExtendedErrCode, 0)); + if (KErrNone != err) + { + ELOG1(EJavaInstaller, + "CJavaSifPlugin::ExitIfJavaInstallerRunning aResults.AddIntL " + "ExtendedErrCode err %d", err); + } + + // TODO: return also localized error message from usif + // common localization file after the localized strings are available + + TRequestStatus *statusPtr(&aStatus); + User::RequestComplete(statusPtr, KErrInUse); + return ETrue; + } + } + proc.Close(); + } + + return EFalse; +} + +/** + * Creates 'preparing installation' dialog. + */ +void CJavaSifPlugin::CreatePrepInstDialogL() +{ + ILOG(EJavaInstaller, "CJavaSifPlugin::CreatePrepInstDialogL creating dialog"); + mPrepInstDialog = CHbDeviceNotificationDialogSymbian::NewL(); + _LIT(KPrepInstText, "Preparing installation..."); + mPrepInstDialog->SetTitleL(KPrepInstText); + mPrepInstDialog->SetTimeout(20*1000); // ms + mPrepInstDialog->ShowL(); + ILOG(EJavaInstaller, "CJavaSifPlugin::CreatePrepInstDialogL dialog created"); +} + +void CJavaSifPlugin::HidePrepInstDialogL() +{ + ILOG(EJavaInstaller, "CJavaSifPlugin::HidePrepInstDialogL hiding dialog"); + // Stop further timed calls + if (mWaitToHideDialog) + { + mWaitToHideDialog->Cancel(); + } + // Close wait dialog. + if (mPrepInstDialog) + { + mPrepInstDialog->Close(); + } + ILOG(EJavaInstaller, "CJavaSifPlugin::HidePrepInstDialogL dialog hidden"); +} + // End of File