diff -r 88ee4cf65e19 -r 1aa8c82cb4cb remotestoragefw/remotefileengine/src/rsfwmountstatemachine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/remotestoragefw/remotefileengine/src/rsfwmountstatemachine.cpp Wed Sep 01 12:15:08 2010 +0100 @@ -0,0 +1,517 @@ +/* +* Copyright (c) 2005-2006 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: State machine for mounting +* +*/ + + +#include +#include "rsfwmountstatemachine.h" +#include "rsfwwaitnotemanager.h" +#include "rsfwvolumetable.h" +#include "rsfwvolume.h" +#include "rsfwfileengine.h" +#include "rsfwrferequest.h" +#include "rsfwnotpluginrequest.h" +#include "mdebug.h" +#include + +// CONSTANTS +// errors returned by connection layer +const TInt KRsfwErrNoNetworkCoverage = -4159; // device out of range +const TInt KRsfwErrOfflineNotPossible = -4180; // device in off-line mode + +/************************************* + * CRsfwMountStateMachine + * + * Note that EnteredConnectionState() in CompleteL + * may start reintegration. + * However instead of writing special reintegration states here + * it is better to later implement a reintegration thread. + * + ***************************************/ + + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::NewL +// ---------------------------------------------------------------------------- +// +CRsfwMountStateMachine* +CRsfwMountStateMachine::NewL(TRsfwMountConfig aMountConfig, + TInt aMountState, + CRsfwVolumeTable* aVolumeTable) + { + CRsfwMountStateMachine* self = new (ELeave) CRsfwMountStateMachine(); + CleanupStack::PushL(self); + self->ConstructL(aMountConfig, aMountState, aVolumeTable); + CleanupStack::Pop(self); + return self; + } + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::ConstructL +// ---------------------------------------------------------------------------- +// +void CRsfwMountStateMachine::ConstructL(TRsfwMountConfig aMountConfig, + TInt aMountState, + CRsfwVolumeTable* aVolumeTable) + { + DEBUGSTRING16(("Mounting drive '%c' with uri '%S', flags=0x%x, to=%d", + TUint(aMountConfig.iDriveLetter), + &(aMountConfig).iUri, + aMountConfig.iFlags, + aMountConfig.iInactivityTimeout)); + + iMountConfig = aMountConfig; + iMountState = aMountState; + iFriendlyName = iMountConfig.iName; + SetVolumes(aVolumeTable); + + iVolumeId = Volumes()->VolumeIdByDriveLetter(iMountConfig.iDriveLetter); + if (iVolumeId == KErrNotFound) + { + User::Leave(KErrArgument); + } + + // set volume and file engine + if (iMountState == KMountStateDormant) + { + // volume and file engine must exist + CRsfwVolume* volume = Volumes()->VolumeByVolumeId(iVolumeId); + if (volume) + { + iVolume = volume; + } + else + { + User::Leave(KErrNotFound); + } + } + else + { + // create volume + iVolume = new (ELeave) CRsfwVolume(); + iVolume->iVolumeTable = Volumes(); + + // set mountinfo for the volume + TRsfwMountInfo& mountInfo = iVolume->iMountInfo; + mountInfo.iMountConfig = iMountConfig; + mountInfo.iMountStatus.iVolumeId = iVolumeId; + iVolume->iVolumeTable = Volumes(); + + if (mountInfo.iMountConfig.iInactivityTimeout < 0) + { + // Negative value means that we don't want to time out + mountInfo.iMountConfig.iInactivityTimeout = 0; + } + else if (mountInfo.iMountConfig.iInactivityTimeout > 0) + { + // Positive means using system default + mountInfo.iMountConfig.iInactivityTimeout = + Volumes()->iInactivityTimeout; + } + // Just copy the adapted parameter + mountInfo.iMountStatus.iInactivityTimeout = + mountInfo.iMountConfig.iInactivityTimeout; + + mountInfo.iMountStatus.iPermanence = Volumes()->iPermanence; + if (iMountConfig.iFlags & KMountFlagOffLine) + { + // We are working offline + mountInfo.iMountStatus.iConnectionState = KMountNotConnected; + } + else + { + mountInfo.iMountStatus.iConnectionState = KMountStronglyConnected; + } + + // create fileengine and attack to volume + iVolume->iFileEngine = CRsfwFileEngine::NewL(iVolume); + } + + // set also fileengine pointer in the operation state machine, + // so that the operation can be cancelled + SetFileEngine(iVolume->iFileEngine); + + + } + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::CompleteRequestL +// ---------------------------------------------------------------------------- +// +CRsfwRfeStateMachine::TState* CRsfwMountStateMachine::CompleteRequestL(TInt aError) + { + DEBUGSTRING16(("CRsfwMountStateMachine:::CompleteRequestL error %d", aError)); + // Attach volume to the table + // Note that this is always done, even if "request_connection_state" + // returned an error. + // This is because sending packets to remote server required construction + // of CRsfwFileEngine etc. anyway, and they will be deleted from elsewhere + // (deleting the mount configuration or the inactivity timeout) + if (!(iMountState == KMountStateDormant)) + { + Volumes()->iVolumes[iVolumeId] = iVolume; + } + + // make sure engine disconnects if there was an error + if (aError != KErrNone) + { + iVolume->iFileEngine->RequestConnectionStateL( + KMountNotConnected, + NULL); + } + + return CRsfwWaitNoteStateMachine::CompleteRequestL(aError); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::ErrorOnStateEntry +// ---------------------------------------------------------------------------- +// +CRsfwWaitNoteStateMachine::TState* CRsfwMountStateMachine::ErrorOnStateEntry(TInt aError) + { + DEBUGSTRING16(("CRsfwMountStateMachine::ErrorOnStateEntry %d", aError)); + + if (aError == KEComErrNoInterfaceIdentified) + { + aError = KErrNotFound; + } + + // If error when connecting: + // For most errors we have to show "drive not available, retry?" + // or some other connection error dialog + // for this we must first dismiss the current wait note and then show + // a new note. + // Hower, if user presses Cancel or the red button we return immediately + if ((iRequestingConnection) && (aError != KErrCancel)) + { + iRequestingConnection = EFalse; + iConnectingError = aError; + return new CRsfwMountStateMachine::TDismissConnectionWaitNoteState(this); + } + else + { + return CRsfwWaitNoteStateMachine::ErrorOnStateEntry(aError); + } + } + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::TRequestConnectionState::TRequestConnectionState +// ---------------------------------------------------------------------------- +// +CRsfwMountStateMachine:: +TRequestConnectionState::TRequestConnectionState(CRsfwMountStateMachine* aParent) + : iOperation(aParent) + { + } + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::TRequestConnectionState::EnterL +// ---------------------------------------------------------------------------- +// +void CRsfwMountStateMachine::TRequestConnectionState::EnterL() + { + DEBUGSTRING16(("CRsfwMountStateMachine::TRequestConnectionState::EnterL")); + + // set volume mountconfig + iOperation->iVolume->iMountInfo.iMountConfig = iOperation->iMountConfig; + + // put up a 'Connecting...' global wait note + + iOperation->ShowWaitNoteL( ERemoteOpConnecting ); + + // mark mount connection state as KMountConnecting + // this is done, because will prevent engine from shutdown + iOperation->FileEngine()->EnteredConnectionStateL(KMountConnecting, EFalse); + + // request KMountStronglyConnected state + // this will open connection to the server + iOperation->iRequestingConnection = ETrue; + TUint transactionId = iOperation->FileEngine() + ->RequestConnectionStateL(KMountStronglyConnected, + iOperation); + + // transactionId = 0 means syncronous non-cancellable operation + if (transactionId > 0) + { + iOperation->iRequestingConnection = EFalse; + iOperation->iTransactionId = transactionId; + } + + } + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::TRequestConnectionState::CompleteL +// This function should be able to do what CRsfwVolumeTable::MountL normally does +// after fileEngine->RequestConnectionStateL() has returned +// (with non-error return code) +// ---------------------------------------------------------------------------- +// +CRsfwRfeStateMachine::TState* +CRsfwMountStateMachine::TRequestConnectionState::CompleteL() + { + DEBUGSTRING16(("CRsfwMountStateMachine::TRequestConnectionState::CompleteL")); + + if (iOperation->iRequestingConnection) + { + iOperation->iRequestingConnection = EFalse; + } + + if (!(iOperation->iMountState == KMountStateDormant)) + { + // Attach volume to the table + iOperation->Volumes()->iVolumes[iOperation->iVolumeId] = + iOperation->iVolume; + } + + // Attach volume to the request + // (such that the request can notify File Engine of operation completion) + iOperation->Request()->iVolume = iOperation->iVolume; + + iOperation->FileEngine()->EnteredConnectionStateL(KMountStronglyConnected, EFalse); + + // publish the new connection state (P&S notification) + iOperation->Volumes()->PublishConnectionStatus(iOperation->iVolume); + + // Remember the volume id for the next root setup + iOperation->Volumes()->iLastVolumeId = iOperation->iVolumeId; + + // remember why the connection attempt failed + iOperation->iConnectingError = KErrNone; + + // dismiss the connecting dialog + return new CRsfwMountStateMachine::TDismissConnectionWaitNoteState( + iOperation); + + } + + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::TRequestConnectionState::ErrorL +// ---------------------------------------------------------------------------- +// +CRsfwRfeStateMachine::TState* +CRsfwMountStateMachine::TRequestConnectionState::ErrorL(TInt aCode) + { + DEBUGSTRING16(("CRsfwMountStateMachine::TRequestConnectionState error=%d", aCode)); + + if (iOperation->iRequestingConnection) + { + iOperation->iRequestingConnection = EFalse; + } + + // remember why the connection attempt failed + iOperation->iConnectingError = aCode; + + if ((aCode == KErrNone) || (aCode == KErrCancel)) + { + // immediately return + return iOperation->CompleteRequestL(aCode); + } + + // else remove wait note dialog first + return new CRsfwMountStateMachine::TDismissConnectionWaitNoteState( + iOperation); + } + + +// ************* + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine:: +// TDismissConnectionWaitNoteState::TDismissConnectionWaitNoteState +// ---------------------------------------------------------------------------- +// +CRsfwMountStateMachine:: +TDismissConnectionWaitNoteState::TDismissConnectionWaitNoteState(CRsfwMountStateMachine* aParent) + : iOperation(aParent) + { + } + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::TDismissConnectionWaitNoteState::EnterL +// ---------------------------------------------------------------------------- +// +void CRsfwMountStateMachine::TDismissConnectionWaitNoteState::EnterL() + { + DEBUGSTRING16(("CRsfwMountStateMachine::TDismissConnectionWaitNoteState::EnterL")); + iOperation->DeleteWaitNoteL(EFalse); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::TDismissConnectionWaitNoteState::CompleteL +// ---------------------------------------------------------------------------- +// +CRsfwRfeStateMachine::TState* +CRsfwMountStateMachine::TDismissConnectionWaitNoteState::CompleteL() + { + DEBUGSTRING16(("CRsfwMountStateMachine::TDismissConnectionWaitNoteState::CompleteL")); + switch (iOperation->iConnectingError) + { + case KErrNone: + return iOperation->CompleteRequestL(KErrNone); + case KErrCancel: + return iOperation->CompleteRequestL(KErrCancel); + case KErrAccessDenied: + return new CRsfwMountStateMachine::TGetAuthCredentials(iOperation); + case KErrNoMemory: + iOperation->Volumes()->WaitNoteManager() + ->ShowOutOfMemoryNoteL(); + return iOperation->CompleteRequestL(KErrNoMemory); + case KErrNotFound: + case KErrPathNotFound: + iOperation->Volumes()->WaitNoteManager() + ->ShowAddressNotFoundErrorL(iOperation->iFriendlyName); + return iOperation->CompleteRequestL(iOperation->iConnectingError); + case KRsfwErrNoNetworkCoverage: + iOperation->Volumes()->WaitNoteManager() + ->ShowNoNetworkCoverageNoteL(); + return iOperation->CompleteRequestL(KRsfwErrNoNetworkCoverage); + case KRsfwErrOfflineNotPossible: + iOperation->Volumes()->WaitNoteManager() + ->ShowOfflineNotPossibleNoteL(); + return iOperation->CompleteRequestL(KRsfwErrOfflineNotPossible); + default: + // ask user whether to retry + return new CRsfwMountStateMachine::TUnavailableRetry(iOperation); + } + } + +//----------------------------------------------------------------------------- +// CRsfwMountStateMachine::TDismissConnectionWaitNoteState::ErrorL +// ---------------------------------------------------------------------------- +// +CRsfwRfeStateMachine::TState* +CRsfwMountStateMachine::TDismissConnectionWaitNoteState::ErrorL(TInt /*aCode*/) + { + DEBUGSTRING16(("CRsfwMountStateMachine::TDismissConnectionWaitNoteState::ErrorL")); + // dismissing the dialog failed + // no code for this case + return CompleteL(); + } + +// ************* + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::TGetAuthCredentials::TGetAuthCredentials +// ---------------------------------------------------------------------------- +// +CRsfwMountStateMachine:: +TGetAuthCredentials::TGetAuthCredentials(CRsfwMountStateMachine* aParent) + : iOperation(aParent) + { + } + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::TGetAuthCredentials::EnterL +// ---------------------------------------------------------------------------- +// +void CRsfwMountStateMachine::TGetAuthCredentials::EnterL() + { + DEBUGSTRING16(("CRsfwMountStateMachine::TGetAuthCredentials::EnterL")); + iAuthRequest.iMethod = TRsfwNotPluginRequest::EAuthenticationDlg; + iAuthRequest.iDriveName = iOperation->iFriendlyName; + iAuthRequest.iUserName = iOperation->iMountConfig.iUserName; + iAuthRequest.iPassword = iOperation->iMountConfig.iPassword; + + iOperation->Volumes()->WaitNoteManager()->SetAuthenticationDialogL(iAuthRequest); + iOperation->Volumes()->WaitNoteManager() + ->StartWaitNoteL(ERemoteOpAuthDialog, iOperation); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::TGetAuthCredentials::CompleteL +// ---------------------------------------------------------------------------- +// +CRsfwRfeStateMachine::TState* +CRsfwMountStateMachine::TGetAuthCredentials::CompleteL() + { + DEBUGSTRING16(("CRsfwMountStateMachine::TGetAuthCredentials::CompleteL")); + // re-set username and password and try connecting again + iOperation->iMountConfig.iUserName = iAuthRequest.iUserName; + iOperation->iMountConfig.iPassword = iAuthRequest.iPassword; + + return new CRsfwMountStateMachine::TRequestConnectionState(iOperation); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::TGetAuthCredentials::ErrorL +// ---------------------------------------------------------------------------- +// +CRsfwRfeStateMachine::TState* +CRsfwMountStateMachine::TGetAuthCredentials::ErrorL(TInt /*aCode*/) + { + DEBUGSTRING16(("CRsfwMountStateMachine::TGetAuthCredentials::ErrorL")); + return iOperation->CompleteRequestL(KErrAccessDenied); + } + +// ************** + + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::TUnavailableRetry::TGetAuthCredentials +// ---------------------------------------------------------------------------- +// +CRsfwMountStateMachine:: +TUnavailableRetry::TUnavailableRetry(CRsfwMountStateMachine* aParent) + : iOperation(aParent) + { + } + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::TUnavailableRetry::EnterL +// ---------------------------------------------------------------------------- +// +void CRsfwMountStateMachine::TUnavailableRetry::EnterL() + { + DEBUGSTRING16(("CRsfwMountStateMachine::TUnavailableRetry::EnterL")); + iRetryRequest.iMethod = TRsfwNotPluginRequest::EUnavailableRetryDlg; + iRetryRequest.iDriveName = iOperation->iFriendlyName; + + iOperation->Volumes()->WaitNoteManager()->SetGlobalNoteRequestL(iRetryRequest); + iOperation->Volumes()->WaitNoteManager() + ->StartWaitNoteL(ERemoteUnavailableRetry, iOperation); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::TUnavailableRetry::CompleteL +// ---------------------------------------------------------------------------- +// +CRsfwRfeStateMachine::TState* +CRsfwMountStateMachine::TUnavailableRetry::CompleteL() + { + DEBUGSTRING16(("CRsfwMountStateMachine::TUnavailableRetry::CompleteL")); + // retry + return new CRsfwMountStateMachine::TRequestConnectionState(iOperation); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountStateMachine::TUnavailableRetry::ErrorL +// ---------------------------------------------------------------------------- +// +CRsfwRfeStateMachine::TState* +CRsfwMountStateMachine::TUnavailableRetry::ErrorL(TInt aCode) + { + DEBUGSTRING16(("CRsfwMountStateMachine::TUnavailableRetry::ErrorL")); + if (aCode == KErrCancel) + { + // user cancelled the a dialog + return iOperation->CompleteRequestL(KErrCancel); + } + else + { + return iOperation->CompleteRequestL(aCode); + } + }