mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-26 21:41:11 +00:00
chore(@desktop/keycard): improvement in terms of avoiding overlapping keycard library flows
This commit is contained in:
parent
e552a01d2b
commit
608bb38874
@ -170,6 +170,14 @@ proc disconnectAll*(self: Controller) =
|
||||
proc delete*(self: Controller) =
|
||||
self.disconnectAll()
|
||||
|
||||
proc checkKeycardAvailability*(self: Controller) =
|
||||
if self.keycardService.isBusy():
|
||||
self.keycardService.registerForKeycardAvailability(proc () =
|
||||
self.delegate.keycardReady()
|
||||
)
|
||||
else:
|
||||
self.delegate.keycardReady()
|
||||
|
||||
proc init*(self: Controller, fullConnect = true) =
|
||||
self.connectKeycardReponseSignal()
|
||||
|
||||
|
@ -106,6 +106,9 @@ type
|
||||
method delete*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method keycardReady*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
@ -35,6 +35,15 @@ type
|
||||
authenticationPopupIsAlreadyRunning: bool
|
||||
runningFlow: FlowType # in general used to mark the global shared flow that is being running (`Authentication` or `Sign`)
|
||||
|
||||
# temporary variables used to store data while we're wiating for keycard lib to get ready
|
||||
tmpFlowToRun: FlowType
|
||||
tmpKeyUid: string
|
||||
tmpBip44Paths: seq[string]
|
||||
tmpTxHash: string
|
||||
tmpForceFlow: bool
|
||||
tmpReturnToFlow: FlowType
|
||||
tmpPin: string
|
||||
|
||||
proc newModule*[T](delegate: T,
|
||||
uniqueIdentifier: string,
|
||||
events: EventEmitter,
|
||||
@ -58,6 +67,10 @@ proc newModule*[T](delegate: T,
|
||||
|
||||
{.push warning[Deprecated]: off.}
|
||||
|
||||
## Forward declarations
|
||||
proc proceedWithSyncKeycardBasedOnAppState[T](self: Module[T], keyUid: string, pin: string)
|
||||
proc proceedWithRunFlow[T](self: Module[T], flowToRun: FlowType, keyUid: string, bip44Paths: seq[string], txHash: string, forceFlow: bool, returnToFlow: FlowType)
|
||||
|
||||
method delete*[T](self: Module[T]) =
|
||||
self.view.delete
|
||||
self.viewVariant.delete
|
||||
@ -69,6 +82,12 @@ proc init[T](self: Module[T], fullConnect = true) =
|
||||
self.controller.cleanReceivedKeycardData()
|
||||
self.controller.init(fullConnect)
|
||||
|
||||
method keycardReady*[T](self: Module[T]) =
|
||||
if self.tmpPin.len > 0:
|
||||
self.proceedWithSyncKeycardBasedOnAppState(self.tmpKeyUid, self.tmpPin)
|
||||
else:
|
||||
self.proceedWithRunFlow(self.tmpFlowToRun, self.tmpKeyUid, self.tmpBip44Paths, self.tmpTxHash, self.tmpForceFlow, self.tmpReturnToFlow)
|
||||
|
||||
method getModuleAsVariant*[T](self: Module[T]): QVariant =
|
||||
return self.viewVariant
|
||||
|
||||
@ -318,6 +337,11 @@ method syncKeycardBasedOnAppState*[T](self: Module[T], keyUid: string, pin: stri
|
||||
if keyUid.len == 0:
|
||||
debug "cannot sync with the empty keyUid"
|
||||
return
|
||||
self.tmpKeyUid = keyUid
|
||||
self.tmpPin = pin
|
||||
self.controller.checkKeycardAvailability()
|
||||
|
||||
proc proceedWithSyncKeycardBasedOnAppState[T](self: Module[T], keyUid: string, pin: string) =
|
||||
self.init(fullConnect = false)
|
||||
self.controller.setKeyUidWhichIsBeingSyncing(keyUid)
|
||||
self.controller.setPin(pin)
|
||||
@ -478,6 +502,15 @@ method runFlow*[T](self: Module[T], flowToRun: FlowType, keyUid = "", bip44Paths
|
||||
self.controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
|
||||
error "sm_cannot run an general flow"
|
||||
return
|
||||
self.tmpFlowToRun = flowToRun
|
||||
self.tmpKeyUid = keyUid
|
||||
self.tmpBip44Paths = bip44Paths
|
||||
self.tmpTxHash = txHash
|
||||
self.tmpForceFlow = forceFlow
|
||||
self.tmpReturnToFlow = returnToFlow
|
||||
self.controller.checkKeycardAvailability()
|
||||
|
||||
proc proceedWithRunFlow[T](self: Module[T], flowToRun: FlowType, keyUid: string, bip44Paths: seq[string], txHash: string, forceFlow: bool, returnToFlow: FlowType) =
|
||||
self.init()
|
||||
self.view.setForceFlow(forceFlow)
|
||||
self.view.setReturnToFlow(returnToFlow)
|
||||
|
@ -5,8 +5,9 @@
|
||||
type
|
||||
TimerTaskArg = ref object of QObjectTaskArg
|
||||
timeoutInMilliseconds: int
|
||||
reason: string
|
||||
|
||||
const timerTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[TimerTaskArg](argEncoded)
|
||||
sleep(arg.timeoutInMilliseconds)
|
||||
arg.finish("")
|
||||
arg.finish(arg.reason)
|
@ -37,10 +37,15 @@ const SupportedMnemonicLength18* = 18
|
||||
const SupportedMnemonicLength24* = 24
|
||||
|
||||
const MnemonicLengthForStatusApp = SupportedMnemonicLength12
|
||||
const TimerIntervalInMilliseconds = 3 * 1000 # 3 seconds
|
||||
const ReRunCurrentFlowInterval = 3 * 1000 # 3 seconds
|
||||
const CheckKeycardAvailabilityInterval = 1000 # 1 seconds
|
||||
|
||||
const SIGNAL_KEYCARD_RESPONSE* = "keycardResponse"
|
||||
|
||||
type TimerReason {.pure.} = enum
|
||||
ReRunCurrentFlowLater = "ReRunCurrentFlowLater"
|
||||
WaitForKeycardAvailability = "WaitForKeycardAvailability"
|
||||
|
||||
logScope:
|
||||
topics = "keycard-service"
|
||||
|
||||
@ -63,6 +68,16 @@ QtObject:
|
||||
lastReceivedKeycardData: tuple[flowType: string, flowEvent: KeycardEvent]
|
||||
setPayloadForCurrentFlow: JsonNode
|
||||
doLogging: bool
|
||||
busy: bool
|
||||
waitingFlows: seq[tuple[flow: KCSFlowType, payload: JsonNode]]
|
||||
registeredCallback: proc ()
|
||||
|
||||
## Forward declaration
|
||||
proc startFlow(self: Service, payload: JsonNode)
|
||||
proc runTimer(self: Service, timeoutInMilliseconds: int, reason: string)
|
||||
|
||||
proc isBusy*(self: Service): bool =
|
||||
return self.busy
|
||||
|
||||
proc delete*(self: Service) =
|
||||
self.closingApp = true
|
||||
@ -108,7 +123,13 @@ QtObject:
|
||||
self.events.emit(SIGNAL_KEYCARD_RESPONSE, KeycardLibArgs(flowType: flowType, flowEvent: flowEvent))
|
||||
|
||||
proc receiveKeycardSignal(self: Service, signal: string) {.slot.} =
|
||||
self.busy = false
|
||||
self.processSignal(signal)
|
||||
if self.waitingFlows.len > 0:
|
||||
let (flow, payload) = self.waitingFlows[0]
|
||||
self.waitingFlows.delete(0)
|
||||
self.currentFlow = flow
|
||||
self.startFlow(payload)
|
||||
|
||||
proc getLastReceivedKeycardData*(self: Service): tuple[flowType: string, flowEvent: KeycardEvent] =
|
||||
return self.lastReceivedKeycardData
|
||||
@ -132,18 +153,28 @@ QtObject:
|
||||
return self.currentFlow
|
||||
|
||||
proc startFlow(self: Service, payload: JsonNode) =
|
||||
if self.busy:
|
||||
self.waitingFlows.add((flow: self.currentFlow, payload: payload))
|
||||
return
|
||||
self.busy = true
|
||||
self.updateLocalPayloadForCurrentFlow(payload, cleanBefore = true)
|
||||
let response = keycard_go.keycardStartFlow(self.currentFlow.int, $payload)
|
||||
if self.doLogging:
|
||||
debug "keycardStartFlow", kcServiceCurrFlow=($self.currentFlow), payload=payload, response=response
|
||||
|
||||
proc resumeFlow(self: Service, payload: JsonNode) =
|
||||
if self.busy:
|
||||
return
|
||||
self.busy = true
|
||||
self.updateLocalPayloadForCurrentFlow(payload)
|
||||
let response = keycard_go.keycardResumeFlow($payload)
|
||||
if self.doLogging:
|
||||
debug "keycardResumeFlow", kcServiceCurrFlow=($self.currentFlow), payload=payload, response=response
|
||||
|
||||
proc cancelCurrentFlow*(self: Service) =
|
||||
if self.busy:
|
||||
return
|
||||
writeStackTrace()
|
||||
let response = keycard_go.keycardCancelFlow()
|
||||
self.currentFlow = KCSFlowType.NoFlow
|
||||
if self.doLogging:
|
||||
@ -199,13 +230,23 @@ QtObject:
|
||||
result = result & $rand(0 .. 9)
|
||||
|
||||
proc onTimeout(self: Service, response: string) {.slot.} =
|
||||
if(self.closingApp or self.currentFlow == KCSFlowType.NoFlow):
|
||||
return
|
||||
if self.doLogging:
|
||||
debug "onTimeout, about to start flow: ", kcServiceCurrFlow=($self.currentFlow)
|
||||
self.startFlow(self.setPayloadForCurrentFlow)
|
||||
if response == $TimerReason.ReRunCurrentFlowLater:
|
||||
if(self.closingApp or self.currentFlow == KCSFlowType.NoFlow):
|
||||
return
|
||||
if self.doLogging:
|
||||
debug "onTimeout, about to start flow: ", kcServiceCurrFlow=($self.currentFlow)
|
||||
self.startFlow(self.setPayloadForCurrentFlow)
|
||||
elif response == $TimerReason.WaitForKeycardAvailability:
|
||||
if self.busy:
|
||||
self.runTimer(CheckKeycardAvailabilityInterval, $TimerReason.WaitForKeycardAvailability)
|
||||
return
|
||||
if self.registeredCallback != nil:
|
||||
self.registeredCallback()
|
||||
self.registeredCallback = nil
|
||||
else:
|
||||
error "unknown timer reason", reason = response
|
||||
|
||||
proc runTimer(self: Service) =
|
||||
proc runTimer(self: Service, timeoutInMilliseconds: int, reason: string) =
|
||||
if(self.closingApp or self.currentFlow == KCSFlowType.NoFlow):
|
||||
return
|
||||
|
||||
@ -213,7 +254,8 @@ QtObject:
|
||||
tptr: cast[ByteAddress](timerTask),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "onTimeout",
|
||||
timeoutInMilliseconds: TimerIntervalInMilliseconds
|
||||
timeoutInMilliseconds: timeoutInMilliseconds,
|
||||
reason: reason
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
@ -440,4 +482,11 @@ QtObject:
|
||||
let tmpFlow = self.currentFlow
|
||||
self.cancelCurrentFlow()
|
||||
self.currentFlow = tmpFlow
|
||||
self.runTimer()
|
||||
self.runTimer(ReRunCurrentFlowInterval, "reRunCurrentFlowLater")
|
||||
|
||||
proc registerForKeycardAvailability*(self: Service, p: proc()) =
|
||||
if not self.busy:
|
||||
error "registerForKeycardAvailability can be called only when keycard is busy"
|
||||
return
|
||||
self.registeredCallback = p
|
||||
self.runTimer(CheckKeycardAvailabilityInterval, $TimerReason.WaitForKeycardAvailability)
|
Loading…
x
Reference in New Issue
Block a user