diff -r 3f419852be07 -r 364021cecc90 smartinstaller/bootstrap/src/bootstrapstatemachine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/smartinstaller/bootstrap/src/bootstrapstatemachine.cpp Wed Jun 30 11:01:26 2010 +0530 @@ -0,0 +1,1686 @@ +/* +* Copyright (c) 2009-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" +* 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: +* CStateMachine class implementation. +* +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // CRepository +#include // KCRUidBrowser + +#include //For download error handling +#include //For download error handling +#include //For download error handling +#include //For download error handling (not in S60 5.0 SDK) + +#include +#include +#include + +#include "bootstrapstatemachine.h" +#include "bootstrapappui.h" +#include "bootstrapconst.h" +#include "bootstrapinstallationobserver.h" +#include "smartinstallerdll.h" +#include "debug.h" +#include "globals.h" +#include "macros.h" +#include "config.h" +#include "utils.h" // HideAppFromMenuL() + +// ADM binary name +_LIT(KAdmExePath, "ADM.exe"); +_LIT(KDownloadFolder,"?:\\system\\adm\\"); +// Sis file extension +_LIT(KSisExtn,".SIS"); +_LIT(KSisxExtn,".SISX"); +// Xml file extension +_LIT(KXMLExtn,".XML"); +// Dep file extension +_LIT(KDepExtn,"_DEP"); +// ADM changes file name +_LIT(KAdmChangesFile, "adm_changes.xml"); +// Private folder of SWI Daemon +_LIT(KSWIDaemonPrivateFolder, "\\private\\10202dce\\"); + +// --------------------------------------------------------------------------- +// CStateMachine::NewLC +// --------------------------------------------------------------------------- +// +CStateMachine* CStateMachine::NewLC(CBootstrapAppUi& aSIUiObj, TUint32 aWrapperUid) + { + CStateMachine* object = new ( ELeave ) CStateMachine(aSIUiObj, aWrapperUid); + CleanupStack::PushL( object ); + object->ConstructL(); + return object; + } + +// --------------------------------------------------------------------------- +// CStateMachine::NewL +// --------------------------------------------------------------------------- +// +CStateMachine* CStateMachine::NewL(CBootstrapAppUi& aSIUiObj, TUint32 aWrapperUid) + { + CStateMachine* object = CStateMachine::NewLC(aSIUiObj, aWrapperUid); + CleanupStack::Pop(); + return object; + } + +// --------------------------------------------------------------------------- +// CStateMachine::CStateMachine +// C++ default constructor. +// --------------------------------------------------------------------------- +// +CStateMachine::CStateMachine(CBootstrapAppUi& aBsAppUiObj, TUint32 aWrapperUid) : + CActive(CActive::EPriorityStandard), + iAppUi(aBsAppUiObj), + iWrapperPackageUid(aWrapperUid), + iAdmChangesInfo(), + iBootstrapFailed(EFalse) +#ifdef USE_LOGFILE + , iLog(aBsAppUiObj.iLog) +#endif + { + CActiveScheduler::Add(this); + } + +// --------------------------------------------------------------------------- +// CStateMachine::ConstructL +// 2nd phase constructor. +// --------------------------------------------------------------------------- +// +void CStateMachine::ConstructL() + { + // Connect to the Download Manager + TBool masterInstance(!(iAppUi.EikonEnv()->StartedAsServerApp())); + iDownloadManager.ConnectL( KUidBootstrapApp, *this, masterInstance ); + + User::LeaveIfError(iLauncher.Connect()); + + iIsAdmInstalled = IsPackagePresentL(KUidAdm, iAdmInstalledVersion); + + ReadConfigurationL(); + } + +// --------------------------------------------------------------------------- +// CStateMachine::~CStateMachine +// Virtual Destructor. +// --------------------------------------------------------------------------- +// +CStateMachine::~CStateMachine() + { + LOG( "~StateMachine()" ); + Cancel(); + DELETE_IF_NONNULL( iDepFilename ); + DELETE_IF_NONNULL( iSisFilename ); + DELETE_IF_NONNULL( iDownloadUrl ); + delete iInstallObsrv; + delete iConfigUrl; + delete iUrl; + delete iDownloadFileName; + iIapArray.Close(); + iDownloadManager.DeleteAll(); + iDownloadManager.Close(); + iLauncher.Close(); + } + +// --------------------------------------------------------------------------- +// CStateMachine::RunL +// Called for each state transition +// --------------------------------------------------------------------------- +// +void CStateMachine::RunL() + { + switch (iAppState) + { + case EBSStateInit: + { + StateInitL(); + RequestState(EBSStateDownloadChanges); + } + break; + case EBSStateDownloadChanges: + { + StateDownloadL(); + // No need to request a state change. HandleDMgrEventL() will + // trigger a correct event after the download has completed. + } + break; + case EBSStateParseChanges: + { + StateParseChangesL(); + if( IsAdmDownloadRequired() ) + { + RequestState(EBSStateDownloadAdm); + } + else + { + RequestState(EBSStateLaunchAdm); + } + } + break; + case EBSStateDownloadAdm: + { + StateDownloadL(); + // No need to request a state change. HandleDMgrEventL() will + // trigger a correct event after the download has completed. + } + break; + case EBSStateInstallAdm: + { + StateInstallAdmL(); + // No need to request a state change. HandleInstallCompleteL() will + // trigger a correct event after the installation has completed. + } + break; + case EBSStateLaunchAdm: + { + StateLaunchAdmL(); + RequestState(EBSStateExit); + } + break; + case EBSStateExit: + { + // Exit the application + Cancel(); + iAppUi.ExitApp(iAppState); + } + break; + case EBSStateExitWithError: + { + Cancel(); + //Error Id needs to be already set before the state transition. + iAppUi.ExitApp(iAppState); + } + break; + default: + LOG2( "Ignoring state change %d", iAppState ); + break; + } + } + +// --------------------------------------------------------------------------- +// CStateMachine::StateComplete +// Trigger the state transition. +// --------------------------------------------------------------------------- +// +void CStateMachine::RequestState(const EBSAppState aNextState) + { + LOG3( "+ RequestState(): %d->%d", iAppState, aNextState ); + iAppState = aNextState; + iStatus = KRequestPending; + + if( !IsActive() ) + { + SetActive(); + } + TRequestStatus* status = &iStatus; + User::RequestComplete( status, KErrNone ); + } + +// --------------------------------------------------------------------------- +// CStateMachine::RunError +// Call Handlefailure incase of error. +// --------------------------------------------------------------------------- +// +TInt CStateMachine::RunError(TInt aError) + { + LOG2( "+ CStateMachine::RunError(%d)", aError ); + if ( aError != KLeaveExit ) + { + HandleFailure(); + return KErrNone; + } + else + { + return KLeaveExit; + } + } + +// --------------------------------------------------------------------------- +// CStateMachine::DoCancel +// --------------------------------------------------------------------------- +// +void CStateMachine::DoCancel() + { + LOG( "+ CStateMachine::DoCancel()" ); + iLauncher.CancelAsyncRequest(SwiUI::ERequestSilentInstall); + iDownloadManager.DeleteAll(); + LOG( "- CStateMachine::DoCancel()" ); + } + +// --------------------------------------------------------------------------- +// CStateMachine::Start +// --------------------------------------------------------------------------- +// +void CStateMachine::Start() + { + SetActive(); + + // send signal that this request has completed + TRequestStatus* status = &iStatus; + User::RequestComplete(status, KErrNone); + } + +// --------------------------------------------------------------------------- +// CStateMachine::Stop +// --------------------------------------------------------------------------- +// +void CStateMachine::Stop() + { + LOG( "+ CStateMachine::Stop()" ); + Cancel(); + } + +// --------------------------------------------------------------------------- +// CBootstrapAppUi::ReadConfigurationL +// Leaves if runs out of memory +// Called from ConstructL in InitState +// @return KErrNone if configuration was read correctly, error code otherwise +// --------------------------------------------------------------------------- +// +TInt CStateMachine::ReadConfigurationL() + { + LOG( "+ ReadConfiguration()" ); + + TFileName configFile; + RArray< TPtrC > lineBuffer; + RFs& rfs = CEikonEnv::Static()->FsSession(); + + // Find the configuration file from the private directory + TInt ret = rfs.PrivatePath( configFile ); + if ( ret == KErrNone ) + { + TBuf<2> appDrive; + // Insert the drive of the running application + appDrive.Copy(iAppUi.Application()->AppFullName().Left(2)); + configFile.Insert( 0, appDrive ); + // Append the configuration file name + configFile.Append( KConfigFile ); + + LOG2( "configFile = %S", &configFile ); + + HBufC* buffer = ReadConfigFile( rfs, configFile, lineBuffer, ret ); + + if ( buffer && ret == KErrNone ) + { + // Get Url from the config file + TPtrC urlLine = GetConfigValue( KCfgTagUrl, lineBuffer, ret ); + if ( ret == KErrNone ) + { + iConfigUrl = HBufC8::NewL( urlLine.Length() ); + iConfigUrl->Des().Copy(urlLine ); + LOG8_2( "configUrl = %S", iConfigUrl ); + } + delete buffer; + } + } + if ( !iConfigUrl ) + { + // Error occured while reading the configuration, use default URL + iConfigUrl = HBufC8::NewL( KDefaultDepServerUrl().Length() ); + *iConfigUrl = KDefaultDepServerUrl; + LOG8_2( "configUrl = %S (default)", iConfigUrl ); + } + + lineBuffer.Close(); + + LOG2("- ReadConfiguration(): %d", ret ); + return ret; + } + +// --------------------------------------------------------------------------- +// CBootstrapAppUi::StateInitL +// Enter in EBSStateSetup, +// +// Read the sis file name and dep file name, based on Bootstrap version +// Set the ADM changes file to download and the url to download from. +// --------------------------------------------------------------------------- +// +void CStateMachine::StateInitL() + { + LOG2( "+ SetFileNameInfo(): ver = %d", KBootstrapVersion ); + + if( ( KBootstrapVersion < 1 ) && ( KBootstrapVersion > 4 ) ) + { + // Unsupported Bootstrap version + User::Leave( KErrNotSupported ); + } + + // Connect to SisRegistry to fetch Package info + Swi::RSisRegistrySession registrySession; + User::LeaveIfError( registrySession.Connect() ); + CleanupClosePushL( registrySession ); + + Swi::RSisRegistryEntry entry; + + // Open registry entry + User::LeaveIfError( entry.Open( registrySession, TUid::Uid( iWrapperPackageUid ) ) ); + CleanupClosePushL( entry ); + + RPointerArray packageFiles; + entry.FilesL( packageFiles ); + const TInt filesCount( packageFiles.Count() ); + + // look into the files installed as part of the package, + // to find the dep file name and actuall application file name. + for ( TInt i=0; iDes(); + extnPtr.UpperCase(); + + if ( KBootstrapVersion != 3 ) + { + if (( extnPtr.Compare(KSisExtn) == 0 ) || ( extnPtr.Compare(KSisxExtn) == 0 ) ) + { + TPtrC privatePath( KNullDesC ); + const TInt KDriveLength = 2; + if ( ( packageFiles[i]->Length() ) > ( KSWIDaemonPrivateFolder().Length() + KDriveLength ) ) + { + privatePath.Set( packageFiles[i]->Des().Mid( KDriveLength ) ); + privatePath.Set( privatePath.Left( KSWIDaemonPrivateFolder().Length() ) ); + } + + // Ignore if its a Stub Sis file + if ( privatePath.CompareF( KSWIDaemonPrivateFolder ) ) + { + if ( iSisFilename == NULL ) + { + iSisFilename = packageFiles[i]->AllocL(); + LOG2( "Application sis '%S'", iSisFilename ); + } + else + // More than one sis present in the Wrapper Pkg + { + LOG2( "! More than one sis file present: '%S'. LEAVE.", packageFiles[i] ); + //TODO:GM: should there be a new error code for this?? + User::Leave( KErrNotSupported ); + } + } + } // if sis extension + } // if (KBoostraVersion != 3) + + if ( KBootstrapVersion != 4 ) + { + if( extnPtr.Compare(KXMLExtn) == 0 ) + { + TPtrC orgName = parse.Name(); + const TInt namelength = orgName.Length(); + const TInt depSuffixlength = KDepExtn().Length(); + + if ( namelength > depSuffixlength ) + { + TPtrC depSuffix = orgName.Mid( ( namelength-depSuffixlength ), depSuffixlength ); + + HBufC* name = depSuffix.AllocLC(); + TPtr namePtr = name->Des(); + namePtr.UpperCase(); + + if ( namePtr.Compare( KDepExtn ) == 0 ) + { + if ( iDepFilename == NULL ) + { + iDepFilename = packageFiles[i]->AllocL(); + LOG2( "Dep file name is '%S'", iDepFilename ); + } + else + // More than one dep file present in the Wrapper Pkg + { + LOG2( "! More than one dep file present: '%S'. LEAVE.", packageFiles[i] ); + //TODO:GM: should there be a new error code for this?? + User::Leave( KErrNotSupported ); + } + } + CleanupStack::PopAndDestroy( name ); + } + } // if XML extn + } // if (KBoostrapVersion != 4) + CleanupStack::PopAndDestroy( extn ); + } + + packageFiles.ResetAndDestroy(); + packageFiles.Close(); + + if (KBootstrapVersion != 3) + { + if ( iSisFilename == NULL ) + { + User::Leave( KErrNotSupported ); + } + } + if (KBootstrapVersion != 4) + { + if ( iDepFilename == NULL ) + { + User::Leave( KErrNotSupported ); + } + } + + CleanupStack::PopAndDestroy(&entry); + CleanupStack::PopAndDestroy(®istrySession); + + iFileName.Set(KAdmChangesFile); + + // URL is already set + DELETE_IF_NONNULL(iUrl); + iUrl = iConfigUrl->AllocL(); + + LOG2( "Filename is '%S'",&iFileName ); + +#ifdef FEATURE_BOOTSTRAP_SETIAP + SetAndValidateIAPL(); +#endif + + LOG( "- SetFileNameInfo()" ); + } + +// --------------------------------------------------------------------------- +// CStateMachine::::IsAdmDownloadRequired +// Enter after EBSStateParseChanges +// +// Verify whether ADM sis download is required. Based on this, the next state will be set. +// --------------------------------------------------------------------------- +// +TBool CStateMachine::IsAdmDownloadRequired() + { + const TBool isAdmDownloadRequired = + CompareVersions(iAdmInstalledVersion, iAdmChangesInfo.iVersion) + == EGreaterSecondVersion; + + if ( isAdmDownloadRequired ) + { + LOG7( "ADM update required (v%d.%02d.%d -> v%d.%02d.%d)", + iAdmInstalledVersion.iMajor, iAdmInstalledVersion.iMinor, iAdmInstalledVersion.iBuild, + iAdmChangesInfo.iVersion.iMajor, iAdmChangesInfo.iVersion.iMinor, iAdmChangesInfo.iVersion.iBuild + ); + + iFileName.Set(*iAdmChangesInfo.iSisName); + + DELETE_IF_NONNULL(iUrl); + + iUrl = iConfigUrl->AllocL(); + } + else + { + LOG4( "ADM is up-to-date (v%d.%02d.%d)", + iAdmInstalledVersion.iMajor, iAdmInstalledVersion.iMinor, iAdmInstalledVersion.iBuild + ); + } + + return isAdmDownloadRequired; + } + +// --------------------------------------------------------------------------- +// CStateMachine::::StateDownloadL +// Enter in case EBSStateDownloadChanges, EBSStateDownloadAdm +// +// Download the specified file from the given url. +// --------------------------------------------------------------------------- +// +void CStateMachine::StateDownloadL() + { + LOG( "+ StateDownloadL()" ); + + // Create the full URL for download + DELETE_IF_NONNULL( iDownloadUrl ); + // +1 for '/' + iDownloadUrl = HBufC8::NewL(iUrl->Length() + iFileName.Length() + 1 ); + TPtr8 ptr(iDownloadUrl->Des()); + ptr.Copy(*iUrl); + + // Append forward slash if that's missing + if (ptr.Right(1)[0] != '/') + { + ptr.Append('/'); + } + ptr.Append(iFileName); + + iDownloadError = EDlErrNoError; + iConnectionAttempt = 0; + + // Set download file name along with path + TChar systemDrive; + RFs::DriveToChar(RFs::GetSystemDrive(), systemDrive); + + DELETE_IF_NONNULL( iDownloadFileName ); + iDownloadFileName = HBufC::NewL(KDownloadFolder().Length() + iFileName.Length()); + TPtr responseFilenamePtr = iDownloadFileName->Des(); + + responseFilenamePtr.Copy(KDownloadFolder); + responseFilenamePtr[0] = systemDrive; + responseFilenamePtr.Append(iFileName); + + // Create new download + LOG2( "Downloading '%S'", iDownloadFileName ); + LOG8_2( " from '%S'", iDownloadUrl ); + + TBool isNewDl = ETrue, tried = EFalse; +retry: + RHttpDownload& dl = iDownloadManager.CreateDownloadL( *iDownloadUrl, isNewDl ); + + ConeUtils::EnsurePathExistsL(*iDownloadFileName); + + if (isNewDl) + { + LOG2( "Receiving '%S'", iDownloadFileName ); + dl.SetStringAttribute( EDlAttrDestFilename, *iDownloadFileName ); + User::LeaveIfError( dl.Start() ); + } + else + { + LOG( "Dl exists." ); + dl.Delete(); + LOG( "Dl deleted." ); + if (tried) + { + LOG( "Tried already, leaving" ); + User::Leave(KErrAlreadyExists); + } + else + { + tried = ETrue; + goto retry; + } + } + + LOG( "- Download()" ); + } + +// --------------------------------------------------------------------------- +// CStateMachine::StateParseChangesL +// Enter in case EBSStateParseChanges +// +// Parse the given changes file. +// --------------------------------------------------------------------------- +// +void CStateMachine::StateParseChangesL() + { + LOG2( "+ ParseFile('%S')", iDownloadFileName ); + User::LeaveIfNull(iDownloadFileName); + + // Initialize the parser + CSenXmlReader* XmlReader = CSenXmlReader::NewLC(EErrorOnUnrecognisedTags); + CSenDomFragment* DomFragment = CSenDomFragment::NewL(); + CleanupStack::PushL(DomFragment); + + XmlReader->SetContentHandler(*DomFragment); + DomFragment->SetReader(*XmlReader); + + // Parse the provided changes file + XmlReader->ParseL(CEikonEnv::Static()->FsSession(), *iDownloadFileName); + + // Get package version + CSenElement* packageElement; + packageElement = DomFragment->AsElement().Element(KFieldVersion); + if (packageElement == NULL) + { + User::Leave(EXmlErrorMissingVersion); + } + else + { + TPtrC8 versionPtr = packageElement->Content(); + TVersion ver; + if (SetVersion(versionPtr, iAdmChangesInfo.iVersion) == EFalse) + { + User::Leave(EXmlErrorInvalidVersion); + } + } + + // Get the ADM sis file name + packageElement = DomFragment->AsElement().Element(KFieldSisName); + if (packageElement) + { + iAdmChangesInfo.iSisName = packageElement->ContentUnicodeL(); + } + else + { + User::Leave(EXmlErrorMissingSisFileName); + } + + // URL read from ADM changes file. + // ADM.sis will be fetched from this url, if present. Or else default config url will be used. +#if USE_ADMCHANGES_URL + // Get the optional URL + packageElement = DomFragment->AsElement().Element(KFieldUrl); + if (packageElement) + { + TPtrC8 urlPtr = packageElement->Content(); + iAdmChangesInfo.iUrl = urlPtr.AllocL(); + } +#endif + + CleanupStack::PopAndDestroy( DomFragment ); + CleanupStack::PopAndDestroy( XmlReader ); + + // Delete no longer required changes file + DeleteFile(*iDownloadFileName); + + LOG( "- ParseFile()" ); + } + +// --------------------------------------------------------------------------- +// CStateMachine::StateInstallAdmL +// Enter in case EBSStateInstallAdm +// +// Silent Install the given sis file. This is asynchronous and the next state transition happens only in the handle function. +// --------------------------------------------------------------------------- +// +void CStateMachine::StateInstallAdmL() + { + LOG( "+ InstallPackage()" ); + SwiUI::TInstallOptions Options; + + Options.iUpgrade = SwiUI::EPolicyAllowed; + Options.iOCSP = SwiUI::EPolicyNotAllowed; + Options.iDrive = 'c'; + Options.iUntrusted = SwiUI::EPolicyNotAllowed; + Options.iCapabilities = SwiUI::EPolicyNotAllowed; + Options.iOverwrite = SwiUI::EPolicyAllowed; + + iOptionsPckg = Options; + + if (iInstallObsrv == NULL) + { + iInstallObsrv = new (ELeave) CInstallObserver(this); + } + iInstallObsrv->iStatus = KRequestPending; + iInstallObsrv->Start(); + // Start asynchronous installation + iLauncher.SilentInstall(iInstallObsrv->iStatus, *iDownloadFileName, iOptionsPckg); + + LOG( "- InstallPackage()" ); + } + +// --------------------------------------------------------------------------- +// CStateMachine::StateLaunchAdmL +// Enter in case EBSStateLaunchAdm +// +// Launch ADM. A few command line args are passed and this depends on the bootstrap version. +// --------------------------------------------------------------------------- +// +void CStateMachine::StateLaunchAdmL() + { + LOG( "+ LaunchAdm()" ); + + TUint32 protocolVer = KBootstrapAdmProtocolVersion; + TUint32 launchCtrl = 0; + + // Command line arguments, version 15 specification: + // + //31 9 8 7 6 5 4 3 2 1 0 + // +-------------+--+--+--+--+--+--+--+--+--+--+ + // | reserved | | | | | | | | + // +-------------+--+--+--+--+--+--+--+--+--+--+ + // + // value + // bits range description + // 0-3 0-15 Command line parameter protocol version: + // 0 = not supported + // 1 = ADM.exe 1 + // 2 = ADM.exe 2 + // 3 = ADM.exe 3 + // 4 = ADM.exe 4 (this was used in beta1, beta2) + // 15 = ADM.exe 15 [parameters as specified by other bits] + // + // since + // bit version type command line parameter present + // 4 4 N Bootstrap version number + // 5 4 N Wrapper UID + // 6 4 N IAP + // 7 4 N ADM launch condition code: + // KCmdLineCancelAdm: ADM needs to cancel installation + // KCmdLineLaunchAdm: ADM starts normally + // 8 4 S Full path to dependency XML file + // 9 4 S Full path to application SIS file + // + // Types: + // N Natural decimal number (range 0 - 2^32-1, fits to TUint32) + // S UTF-8 string, must NOT contains spaces or other whitespaces + // + // Command line parameters appear in the order of the bits set, i.e. + // if bits 4, 8, 9 are set the command line parameters are: + // ADM.exe 784 + // + // If command line protocol version is less than 15, it is assumed that + // old version command line parameter format is used. + // + + // In case of approach 3 , cleanup of only BootStrap + // is required. + if (KBootstrapVersion == 3) + { + iWrapperPackageUid = KUidBootstrapApp.iUid; + } + + // Set the launchCtrl based on Bootstrap Failure/Success + if ( iBootstrapFailed ) + { + if (iSisFilename) + { + // SisFile exists -> resuming is possible + launchCtrl = KCmdLineCancelAdm; + } + else + { + launchCtrl = KCmdLineCancelAdmNoResume; + } + } + else + { + launchCtrl = KCmdLineLaunchAdm; + } + + LOG2( "LaunchCtrl: %d", launchCtrl ); + + // By default, set the following bits: + // 1. BootstrapVersion, + // 2. WrapperUid + // 3. Launchctrl + // 4. IAP (If not set, the value is 0) + protocolVer |= (KCmdLineBitBootstrapVersion | KCmdLineBitWrapperUid) + | KCmdLineBitADMLaunchControl + | KCmdLineBitIAP; + + // Set the mandatory command line parameters + // + // Size of 32-bit Bootstrap Version Value is 10 characters + // Size of 32-bit UID when converted to numeric string is 10 characters (4294967295) + // Size of 32-bit iIAP (TUint32) when converted to numeric string is 10 characters + // Size of 2 spaces is 2 characters + if ( (launchCtrl == KCmdLineCancelAdm) || (launchCtrl == KCmdLineLaunchAdm) ) + { + switch (KBootstrapVersion) + { + case 1: + case 2: + { + User::LeaveIfNull(iSisFilename); + User::LeaveIfNull(iDepFilename); + + protocolVer |= (KCmdLineBitFileSis | KCmdLineBitFileDep); + break; + } + case 3: + { + User::LeaveIfNull(iDepFilename); + protocolVer |= (KCmdLineBitFileDep); + break; + } + case 4: + { + User::LeaveIfNull(iSisFilename); + protocolVer |= (KCmdLineBitFileSis); + break; + } + default: + // Unsupported Bootstrap Version + User::Leave(KErrNotSupported); + break; + } // switch (KBootstrapVersion) + } // if ( (launchCtrl == KCmdLineCancelAdm) || (launchCtrl == KCmdLineLaunchAdm) ) + + // Build the command line parameter string + HBufC *processArgs = NULL; + TInt processArgsLen = 11; // obligatory protocol version number and ' ' + TUint32 tmp = (protocolVer & ~KCmdLineBitProtocolVerMask) >> KCmdLineProtocolVerBits; + for (TInt i = 0; tmp != 0 || i < sizeof(KCmdLineParamLengths); tmp >>= 1, i++) + { + if (tmp & 1) + { + processArgsLen += KCmdLineParamLengths[i]; + } + } + if (iDepFilename) + processArgsLen += iDepFilename->Length()+1; // +1 comes from the appended ' ' + if (iSisFilename) + processArgsLen += iSisFilename->Length(); + LOG2( "len %d", processArgsLen ); + processArgs = HBufC::NewLC(processArgsLen); + TPtr ptr = processArgs->Des(); + + // append the obligatory protocol version number + ptr.AppendNum(protocolVer); + ptr.Append(' '); + + if (protocolVer & KCmdLineBitBootstrapVersion) + { + ptr.AppendNum(KBootstrapVersion); + ptr.Append(' '); + } + if (protocolVer & KCmdLineBitWrapperUid) + { + ptr.AppendNum(iWrapperPackageUid); + ptr.Append(' '); + } + if (protocolVer & KCmdLineBitIAP) + { + ptr.AppendNum(iIAP); + ptr.Append(' '); + } + if (protocolVer & KCmdLineBitADMLaunchControl) + { + ptr.AppendNum(launchCtrl); + ptr.Append(' '); + } + if (protocolVer & KCmdLineBitFileDep) + { + ptr.Append(*iDepFilename); + ptr.Append(' '); + } + if (protocolVer & KCmdLineBitFileSis) + { + ptr.Append(*iSisFilename); + } + + // Launch ADM + LOG3( "Launching %S '%S'", &KAdmExePath, processArgs); + + RProcess process; + CleanupClosePushL( process ); + + const TInt err = process.Create( KAdmExePath, processArgs->Des() ); + if (err != KErrNone) + { + LOG2( "ADM launch failed with error: %d", err ); + CleanupStack::PopAndDestroy( &process ); + CleanupStack::PopAndDestroy( processArgs ); + User::Leave(err); + } + else + { + // ADM was launched properly, set it visible in the menu grid + LOG( "Revealing ADM menu icon" ); + CUtils::HideApplicationFromMenuL( KUidAdm.iUid, EFalse ); + } + +// Do not lower the priority: it will cause the "OK" note to be shown +// on faster, more recent S60 devices +// process.SetPriority( EPriorityBackground ); + process.Resume(); + + CleanupStack::PopAndDestroy( &process ); + CleanupStack::PopAndDestroy( processArgs ); + + LOG2( "- LaunchAdmL(): %d", err ); + } + +// --------------------------------------------------------------------------- +// CStateMachine::HandleDMgrEventL +// Callback to handle the download manager events +// Called in EBSStateDownloadChanges, EBSStateDownloadAdm +// --------------------------------------------------------------------------- +// +void CStateMachine::HandleDMgrEventL( RHttpDownload& aDownload, THttpDownloadEvent aEvent ) + { + TInt32 glErrId = KErrNone; + TInt32 errId = ENoError; + + // Get error IDs + aDownload.GetIntAttribute( EDlAttrGlobalErrorId, glErrId ); + aDownload.GetIntAttribute( EDlAttrErrorId, errId ); + +#ifdef DO_LOG + _LIT(KFmt, ", GlErrId=%6d, ErrId=%d"); + TBuf<64> buf; + + if ( ((glErrId != KErrNone) || (errId != ENoError)) && glErrId != KErrUnknown ) + { + buf.AppendFormat(KFmt, glErrId, errId); + } + + if ( ( iDownloadState != aEvent.iDownloadState ) || + ( iProgressState != aEvent.iProgressState ) ) + { + iDownloadState = aEvent.iDownloadState; + iProgressState = aEvent.iProgressState; + + LOG4( "DlSt=%5d, PrSt=%5d%S", iDownloadState, iProgressState, &buf ); + } +#endif + + switch ( aEvent.iDownloadState ) + { + case EHttpDlCreated: + case EHttpDlInprogress: + { + //Nothing done. + break; + } + case EHttpDlPaused: + case EHttpDlFailed: +// These two fill fold to EHttpDlFailed. We don't want to process failure events twice. +// case EHttpDlNonPausableNetworkLoss: +// case EHttpDlMultipleMOFailed: + { + //Continue download if paused in EHttpContentTypeReceived. + //Pause is received even in ProgNone state! + if( ( aEvent.iProgressState == EHttpContentTypeReceived ) || + ( (aEvent.iProgressState == EHttpProgNone ) && ( errId == ENoError ) ) ) + { + LOG( "Starting download" ); + aDownload.Start(); + break; + } + if ( ProcessDlErrors(glErrId, errId, iDownloadError) ) + { + if ( (iIapArrayIndex+1) < iIapArray.Count() ) + { + // Try the next IAP + iIapArrayIndex++; + LOG3( "Starting download with next IAP[%d]=%d.", iIapArrayIndex, iIapArray[iIapArrayIndex] ); + SetIAP( iIapArray[iIapArrayIndex] ); + aDownload.Start(); + break; + } + else if ( (iIapArrayIndex+1) == iIapArray.Count() ) + { + // We've gone through all the IAPs in the SNAP, prompt the user for an access point + SetIAP( 0 ); + // This ensures that this code path is taken only once + iIapArrayIndex++; + } + if (++iConnectionAttempt < KDownloadConnectionRetries) + { + LOG4( "Restarting download due to network failure (%d: %d, %d)", iConnectionAttempt, glErrId, errId ); + // TODO: Do we need to do a Reset() before Start()? + aDownload.Start(); + // We don't restart the download timer on purpose + // + // Clear the error id so it doesn't get caught below + // as this is not an error situation. + iDownloadError = EDlErrNoError; + } + else + { + LOG4( "Too many download retries, cancelling download (%d; %d, %d)", iDownloadError, glErrId, errId ); + // iDownloadError has been set properly by ProcessDlErrors() + } + } + if ( iDownloadError != EDlErrNoError ) + { + LOG2( "DlErr=%d", iDownloadError ); + + if ( iDownloadError == EDlErrCancelled ) + { + HandleFailure(ETrue); // If user pressed cancel, then iIsIapCancelled is 1 + } + else + { + HandleFailure(EFalse); + } + } + break; + } + case EHttpDlCompleted: + { + // TODO: Get the DownloadfileName?? + iDownloadManager.GetIntAttribute( EDlMgrIap, iIAP ); + LOG2( "IAP set to %d", iIAP ); + + switch (iAppState) + { + case EBSStateDownloadChanges: + RequestState(EBSStateParseChanges); + break; + case EBSStateDownloadAdm: + RequestState(EBSStateInstallAdm); + break; + default: + LOG2( "DlEvent from unknown state %d", iAppState ); + // TODO: Fix the panic code + User::Panic(_L("SmartInst"), 42); + break; + } + break; + } + default: + { + break; + } + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TBool CStateMachine::ProcessDlErrors(const TInt32 aGlErrId, const TInt32 aErrId, EDownloadError& aDownloadError) + { + LOG4( "+ ProcessDlErrors(%d, %d, %d)", aGlErrId, aErrId, aDownloadError ); + TBool requestRestart = EFalse; + const TUint count = iIapArray.Count(); + // Process the error codes + switch (aErrId) + { + case KErrNone: + // everything a-OK! + break; + case EConnectionFailed: + // Request restart, if we haven't exhausted all the IAPs on the list. + if (count > 0 && iIapArrayIndex < count) + { + requestRestart = ETrue; + goto exit; + } + else + { + aDownloadError = EDlErrDownloadFailure; + } + break; + case ETransactionFailed: + // We set the download error to network failure as that's the + // error propagated to TState::DownloadFailed(). + // The state machine will try to restart the download, if the + // error code is EDlErrDownloadFailure, but NOT for EDlErrNetworkFailure. + aDownloadError = EDlErrDownloadFailure; + requestRestart = ETrue; + break; + case EObjectNotFound: + aDownloadError = EDlErrFileNotFound; + break; + default: + LOG2( "Unhandled ErrId %d", aErrId ); + aDownloadError = EDlErrDownloadFailure; + break; + } + // Process the global error code + switch (aGlErrId) + { + case KErrNone: + // everything a-OK! + break; + case KErrCancel: + case KErrAbort: + // The user has cancelled the download / IAP selection box + aDownloadError = EDlErrCancelled; + break; + case KErrDiskFull: + // Disk full + aDownloadError = EDlErrNotEnoughSpace; + break; + case KErrUnknown: + { + if( aErrId == KErrNone ) + { + aDownloadError = EDlErrDownloadFailure; + requestRestart = ETrue; + } + } + break; + case KErrNotFound: + case KErrBadName: + case KErrNotSupported: + case KErrCommsLineFail: + case KErrTimedOut: + case KErrCouldNotConnect: + case KErrDisconnected: + case KErrGprsServicesNotAllowed: + case KErrGsmMMNetworkFailure: + case -8268: // KErrGsmOfflineOpNotAllowed: + // WLAN network related errors: + case KErrWlanNetworkNotFound: + case KErrWlanRoamingFailed: + case KErrWlanNetworkLost: +#if 0 + case KErrBadName: + case KErrNotSupported: + case KErrWlanOpenAuthFailed: + case KErrWlanSharedKeyAuthRequired: + case KErrWlanSharedKeyAuthFailed: + case KErrWlanWpaAuthRequired: + case KErrWlanIllegalEncryptionKeys: + case KErrWlanPskModeRequired: + case KErrWlanEapModeRequired: + case KErrWlanSimNotInstalled: + case KErrWlanNotSubscribed: + case KErrWlanAccessBarred: + case KErrWlanPasswordExpired: + case KErrWlanNoDialinPermissions: + case KErrWlanAccountDisabled: + case KErrWlanRestrictedLogonHours: + case KErrWlanServerCertificateExpired: + case KErrWlanCerficateVerifyFailed: + case KErrWlanNoUserCertificate: + case KErrWlanNoCipherSuite: + case KErrWlanUserRejected: + case KErrWlanUserCertificateExpired: + // less fatal, but still needs to fail the download: + case KErrWlanWpaAuthFailed: + case KErrWlan802dot1xAuthFailed: + case KErrWlanIllegalWpaPskKey: + case KErrWlanEapSimFailed: + case KErrWlanEapTlsFailed: + case KErrWlanEapPeapFailed: + case KErrWlanEapMsChapv2: + case KErrWlanEapAkaFailed: + case KErrWlanEapTtlsFailed: + case KErrWlanLeapFailed: + case KErrWlanEapGtcFailed: +#endif + // A fatal network error has occured, don't retry the download + requestRestart = EFalse; + aDownloadError = EDlErrNetworkFailure; + break; + default: + if (!requestRestart) + { + // We assume all the other error codes to be 'hard' network errors + LOG2( "Unhandled GlErrId %d", aGlErrId ); + aDownloadError = EDlErrNetworkFailure; + } + break; + } +exit: + LOG3( "- ProcessDlErrors(): %d, %d", requestRestart, aDownloadError ); + return requestRestart; + } + +// --------------------------------------------------------------------------- +// CStateMachine::HandleInstallCompleteL +// Callback to handle the Installation events +// Called in EBSStateInstallAdm +// +// If SWI is busy, re attempt installation 6 times +// --------------------------------------------------------------------------- +// +void CStateMachine::HandleInstallCompleteL(const TInt& aStatus) + { + LOG2("+ HandleInstallCompleteL(%d)", aStatus); + TBool retrying = EFalse; + + User::LeaveIfNull(iDownloadFileName); + + // If the install server is busy , try connecting multiple times. + if ( (aStatus == SwiUI::KSWInstErrBusy || + aStatus == KErrInUse || + aStatus == KErrServerBusy) + && ((++iInstallAttempt) <= KMaxInstallerConnectionAttempts)) + { + LOG3( "Installer busy (%d), requesting retry (%d)", iInstallAttempt, aStatus ); + retrying = ETrue; + User::After(KIterationTimer * iInstallAttempt); + RequestState(EBSStateInstallAdm); + } + + if (aStatus == KErrNone) + { + LOG( "ADM installed OK, deleting SIS." ); + // Delete no longer required sis file. + DeleteFile(*iDownloadFileName); + // ADM was installed succesfully, launch it! + RequestState(EBSStateLaunchAdm); + } + else if (!retrying) + { + LOG3( "Installation unsuccessful (%d) after %d attempts, leaving.", aStatus, iInstallAttempt ); + // TODO: Better error handling + User::Leave(aStatus); + } + + LOG("- HandleInstallCompleteL()"); + } + +// --------------------------------------------------------------------------- +// CStateMachine::IsPackagePresentL +// Check whether the given Package (uid & version) is already present in the device. +// Called in EBSStateInit to check for ADM Presence +// --------------------------------------------------------------------------- +// +TBool CStateMachine::IsPackagePresentL(const TUid& aUid, TVersion& aVersion) + { + LOG( "+ ADMPresent()"); + + // Connect to SisRegistry to find if the package is + // already installed. + Swi::RSisRegistrySession registrySession; + + User::LeaveIfError(registrySession.Connect()); + CleanupClosePushL(registrySession); + + const TBool isPkgInstalled = registrySession.IsInstalledL(aUid); + + if (isPkgInstalled) + { + Swi::RSisRegistryEntry entry; + + // Open registry entry + User::LeaveIfError(entry.Open(registrySession, aUid)); + CleanupClosePushL(entry); + aVersion = entry.VersionL(); + + CleanupStack::PopAndDestroy(&entry); + } + + CleanupStack::PopAndDestroy(®istrySession); + + LOG3( "- ADMPresent(): 0x%x = %d", aUid.iUid, isPkgInstalled ); + + return isPkgInstalled; + } + +// --------------------------------------------------------------------------- +// CStateMachine::DeleteFile +// Delete the given file +// --------------------------------------------------------------------------- +// +void CStateMachine::DeleteFile(const TDesC& aFileName) + { + CCoeEnv::Static()->FsSession().Delete(aFileName); + } + +// --------------------------------------------------------------------------- +// CStateMachine::HandleWaitNoteCancel +// Call HandleFailure. +// --------------------------------------------------------------------------- +// +//TODO: Can this be removed and call HandleFailure() directly? +void CStateMachine::HandleWaitNoteCancel() + { + HandleFailure(ETrue); + } + +// --------------------------------------------------------------------------- +// CStateMachine::HandleFailure +// Perform the state specific cleanup incase of failure. +// And then call AppUi Exit. +// --------------------------------------------------------------------------- +// +void CStateMachine::HandleFailure(TInt aError) + { + LOG2( "+ HandleFailure(): %d", aError ); + + switch (iAppState) + { + case EBSStateInit: + case EBSStateSetup: + case EBSStateLaunchAdm: + // No cleanUp required here + break; + case EBSStateDownloadChanges: + case EBSStateDownloadAdm: + // Deletion of all downloads is taken care in destructor + break; + case EBSStateInstallAdm: + // Cancel the installation + iLauncher.CancelAsyncRequest(SwiUI::ERequestSilentInstall); + // fall-through + case EBSStateParseChanges: + { + // Delete the downloaded dep file + if (iDownloadFileName) + { + DeleteFile(*iDownloadFileName); + } + } + break; + default: + break; + } + + // Even in case of any failure, launch ADM, if present in device. + // ADM needs to be launched in Cancel mode. + if( (iAppState < EBSStateLaunchAdm) && iIsAdmInstalled ) + { + // If it is user press cancel or Filenames are itself not set, then remove the whole wrapper package. + // TODO: Should the failure reason be passed to ADM? + // TODO: or show the error note in bootstrap, but launch ADM to remove the wrapper? + if ( aError || ( iAppState <= EBSStateSetup) ) + { + // No need to delete the files here, as the whole package will get removed. + iBootstrapFailed = ETrue; + } + RequestState(EBSStateLaunchAdm); + } + else + { + // Delete the dep file is present + if ( (KBootstrapVersion == 3) && iDepFilename ) + { + DeleteFile(*iDepFilename); + } + else if ( (KBootstrapVersion == 4) && iSisFilename ) + { + DeleteFile(*iSisFilename); + } + + // Set the Error ID based on App State and User Cancel. + if( aError || ((iAppState != EBSStateDownloadChanges) && (iAppState != EBSStateDownloadAdm)) ) + { + iAppUi.SetErrorId(EInstallationFailed); + } + else + { + iAppUi.SetErrorId(EDownloadFailed); + } + + // Now call App Exit to display the error note and exit bootstrap. + RequestState(EBSStateExitWithError); + } + + LOG( "- HandleFailure()" ); + } + +#ifdef FEATURE_BOOTSTRAP_SETIAP +// --------------------------------------------------------------------------- +// Sets the used internet access point (IAP) to same that the Browser uses +// with additional verification that the selected IAP actually exist. +// --------------------------------------------------------------------------- +// +void CStateMachine::SetIAP(const TUint aIAP) + { + LOG2( "+ SetDlMgrIAP(): %d", aIAP ); + iIAP = aIAP; + // Set the download manager to silent mode, if the IAP is valid + iDownloadManager.SetBoolAttribute( EDlMgrSilentMode, aIAP != 0 ); + iDownloadManager.SetIntAttribute( EDlMgrIap, iIAP ); + } + +// --------------------------------------------------------------------------- +// Sets the used internet access point (IAP) to same that the Browser uses +// with additional verification that the selected IAP actually exist. +// --------------------------------------------------------------------------- +// +void CStateMachine::SetAndValidateIAPL() + { + LOG( "+ CBootstrapAppUi::SetAndValidateIAPL()" ); + // Use the browser default IAP, if available + TInt ret; + TInt browserIAP, browserIAPmode, browserSNAP; + TRequestStatus status; + RConnectionMonitor connMon; + + // IsIapActive() requires this + CleanupClosePushL(connMon); + connMon.ConnectL(); + + CRepository *repository = CRepository::NewLC( KCRUidBrowser ); + User::LeaveIfError( repository->Get(KBrowserAccessPointSelectionMode, browserIAPmode) ); + User::LeaveIfError( repository->Get(KBrowserDefaultAccessPoint, browserIAP) ); + ret = repository->Get( KBrowserNGDefaultSnapId, browserSNAP ); + CleanupStack::PopAndDestroy( repository ); + + LOG5( "Browser IAP = %d, mode %d, SNAP %d (%d)", browserIAP, browserIAPmode, browserSNAP, ret ); + + if ( OviStoreRunning() && IsIapActive(connMon, browserIAP) ) + { + LOG2( "Using Ovi Store IAP %d", browserIAP ); + browserIAPmode = EBrowserCenRepApSelModeUserDefined; + // browserIAP now contains the IAP ID that OviStore is using + } + + // Get the IAP IDs for the browser SNAP, if we got the SNAP ID properly + if (ret == KErrNone && browserSNAP > 0) + { + GetSnapIapsL(browserSNAP); + } + + switch (browserIAPmode) + { + case EBrowserCenRepApSelModeDestination: + //LOG( "Destination network "); + break; + case EBrowserCenRepApSelModeUserDefined: + //LOG( "User defined IAP" ); + if (browserIAP > 0) + { + SetIAP(browserIAP); + break; + } + // else fall-through + case EBrowserCenRepApSelModeAlwaysAsk: + default: + LOG( "'Always ask'" ); + // if browser IAP is already active: then we utilise it directly, no prompting + if ( IsIapActive(connMon, browserIAP) ) + { + LOG2( "Connection already up (%d)", browserIAP ); + SetIAP(browserIAP); + } + else + { + LOG( "Prompting IAP" ); + // Set to always ask, we obey it as well + } + // need to set this, if we ended up here with default: + browserIAPmode = EBrowserCenRepApSelModeAlwaysAsk; + break; + } + // Found a proper IAP? + if (iIAP != 0 || browserIAPmode == EBrowserCenRepApSelModeAlwaysAsk) + { +#if 0 + TBuf<64> iapName; + connMon.GetStringAttribute( iIAP, 0, KIAPName, iapName, status ); + User::WaitForRequest( status ); + if ( status.Int() != KErrNone ) + { + // Try access point name + connMon.GetStringAttribute( iIAP, 0, KAccessPointName, iapName, status ); + User::WaitForRequest( status ); + if ( status.Int() != KErrNone ) + { + LOG2( "ConnMon.GetStrAttr() ret = %d, ignoring.", status.Int() ); + } + } + LOG3( "Using IAP %d ('%S')", iIAP, &iapName ); +#else + //LOG2( "Using IAP %d", iIAP ); +#endif + } + else + { + // set the IAP from SNAP, if it's valid + if (iIapArray.Count() > 0 && iIapArray[0] > 0) + { + LOG2( "Starting with IAP %d", iIapArray[0] ); + SetIAP(iIapArray[0]); + } + } + + CleanupStack::PopAndDestroy( &connMon ); + LOG3( "- CBootstrapAppUi::SetAndValidateIAPL(): %d, %d", ret, iIAP ); + } + +// --------------------------------------------------------------------------- +// Get the default IAP for the selected SNAP. SNAP is available since 3.2 +// --------------------------------------------------------------------------- +// +void CStateMachine::GetSnapIapsL(const TUint aSNAPId) + { + // Load the helper library dynamically + _LIT(KLibHelper, "smartinstaller.dll"); + LOG( "Loading helper" ); + RLibrary lib; + const TInt ret = lib.Load( KLibHelper() ); + if (ret == KErrNone) + { + CleanupClosePushL(lib); + const TInt KHelperNewLC = 2; + CHelper* helper = (CHelper*)lib.Lookup(KHelperNewLC)(); + TRAPD(ret, helper->GetSnapIapsL(aSNAPId, iIapArray) ); + LOG3( "Got %d IAPs (%d)", iIapArray.Count(), ret ); +#ifdef DO_LOG + for (TInt i = 0; i < iIapArray.Count(); i++) + { + LOG3( "IAP[%d]=%d", i, iIapArray[i] ); + } +#endif + CleanupStack::PopAndDestroy(2, &lib); // helper, lib + } + else + { + LOG2( "Helper load failed %d", ret ); + } + lib.Close(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TBool CStateMachine::IsIapActive(RConnectionMonitor &aConnMon, TInt& aIAP) + { + LOG2( "+ IsIapActive(): %d", aIAP ); + + TBool ret = EFalse; + // Get the connection info for each connection + TUint id, iapId, count, countSubConn; + TRequestStatus status = KRequestPending; + + aConnMon.GetConnectionCount( count, status ); + User::WaitForRequest( status ); + + if (status.Int() != KErrNone) + { + LOG2( "GetConnCount() failed %d.", status.Int() ); + return ret; + } + + LOG2( "Active connections: %d", count ); + + TInt oviStoreIap = KErrNotFound; + for ( TInt i = 1; i <= count && !ret; i++ ) + { + const TInt err = aConnMon.GetConnectionInfo( i, id, countSubConn ); + if ( err == KErrNone ) + { + LOG3( "ConnID[%d] = %d" , i, id ); + // Get the IAP Id of the connection + aConnMon.GetUintAttribute( id, 0, KIAPId, iapId, status ); + User::WaitForRequest( status ); + if ( status.Int() != KErrNone ) + { + LOG2( "GetIapId failed (%d), trying next", status.Int() ); + // try next connection + continue; + } + else + { + LOG2( "Active IAP = %d", iapId ); + } + + // Find the UIDs using this connection + TConnMonClientEnumBuf clientBuf; + aConnMon.GetPckgAttribute( id, 0, KClientInfo, clientBuf, status ); + User::WaitForRequest( status ); + if ( status.Int() == KErrNone ) + { + //LOG3( "%d clients sharing IAP %d", clientBuf().iCount, iapId ); + for (TUint client = 0; client < clientBuf().iCount; client++) + { + //LOG2( "0x%08X", clientBuf().iUid[client].iUid ); + const TInt KUidSecureWidgetUi = 0x102829A0; + if ( clientBuf().iUid[client].iUid == KUidSecureWidgetUi + && OviStoreRunning() ) + { + if (oviStoreIap == KErrNotFound) + { + //LOG2( "Possible OviStore IAP %d", iapId ); + oviStoreIap = iapId; + } + else + { + // Another secure widget is running, we cannot determine + // which one is ovi store, default to browser IAP + oviStoreIap = 0; + } + } + } + } + else + { + LOG2( "GetClientInfo failed (%d)", status.Int() ); + } + // ignore any errors in KClientInfo query + + // If we found Ovi Store IAP, use that + if (oviStoreIap > 0) + { + LOG2( "Sharing Ovi Store IAP %d", oviStoreIap ); + iapId = oviStoreIap; + } + + if ( iIapArray.Count() > 0 ) + { + // Go through all the SNAP's IAPs + for (TInt iap = 0; iap < iIapArray.Count(); iap++) + { + if ( iapId == iIapArray[iap] ) + { + LOG3( "Using %d (SNAP idx %d)", iapId, iap ); + // Update the IAP to match the found one + aIAP = iapId; + ret = ETrue; + break; + } + } + } + else if ( iapId == aIAP ) + { + LOG2( "Using %d", iapId ); + ret = ETrue; + // we found matching IAP ID, break out of the loop + break; + } + } + else + { + LOG3( "GetConnInfo[%d] failed (%d), trying next", i, err ); + // try next connection + } + } // for +#if 0 + // If we didn't have any connections up, try to find the last used browser + // IAP from the SNAP and use that: + if (!ret && count == 0 && iIapArray.Count() > 0 ) + { + // Go through all the SNAP's IAPs + for (TInt iap = 0; iap < iIapArray.Count(); iap++) + { + if ( iapId == iIapArray[iap] ) + { + LOG3( "Using %d (SNAP idx %d)", iapId, iap ); + // Update the IAP to match the found one + aIAP = iapId; + ret = ETrue; + break; + } + } + } +#endif + LOG3( "- IsIapActive(): %d = %d", aIAP, ret ); + + return ret; + } +#endif // FEATURE_BOOTSTRAP_SETIAP