From bd9e1619fa681efe73d78750dd4ca4bdc3997a9e Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Tue, 25 Aug 2020 16:19:46 -0400 Subject: [PATCH] refactor: never save mnemonic in memory unless totally necessary Necessary cases are: - Onboarding to show the list of 5 accounts - In QML when we show it to the user for the backup - Change it to a Loader, so the component and its memory is cleaned when closed --- src/app/profile/core.nim | 2 - src/app/profile/view.nim | 15 +- src/nim_status_client.nim | 10 +- .../Profile/Sections/BackupSeedModal.qml | 174 +++++++++--------- ui/nim-status-client.pro | 1 + 5 files changed, 103 insertions(+), 99 deletions(-) diff --git a/src/app/profile/core.nim b/src/app/profile/core.nim index f0d3998f78..753ebb9bb5 100644 --- a/src/app/profile/core.nim +++ b/src/app/profile/core.nim @@ -33,7 +33,6 @@ proc init*(self: ProfileController, account: Account) = let profile = account.toProfileModel() let pubKey = status_settings.getSetting[string](Setting.PublicKey, "0x0") - let mnemonic = status_settings.getSetting[string](Setting.Mnemonic, "") let network = status_settings.getSetting[string](Setting.Networks_CurrentNetwork, constants.DEFAULT_NETWORK_NAME) let appearance = status_settings.getSetting[int](Setting.Appearance) profile.appearance = appearance @@ -43,7 +42,6 @@ proc init*(self: ProfileController, account: Account) = self.view.addDevices(devices.getAllDevices()) self.view.setDeviceSetup(devices.isDeviceSetup()) self.view.setNewProfile(profile) - self.view.setMnemonic(mnemonic) self.view.setNetwork(network) self.view.ens.init() diff --git a/src/app/profile/view.nim b/src/app/profile/view.nim index c2f14f85c3..99e0458dca 100644 --- a/src/app/profile/view.nim +++ b/src/app/profile/view.nim @@ -4,6 +4,7 @@ import ../../status/profile/[mailserver, profile, devices] import ../../status/profile as status_profile import ../../status/contacts as status_contacts import ../../status/accounts as status_accounts +import ../../status/libstatus/settings as status_settings import ../../status/status import ../../status/devices as status_devices import ../../status/ens as status_ens @@ -19,7 +20,6 @@ QtObject: addedContacts*: ContactList blockedContacts*: ContactList deviceList*: DeviceList - mnemonic: string network: string status*: Status isDeviceSetup: bool @@ -50,7 +50,6 @@ QtObject: result.blockedContacts = newContactList() result.deviceList = newDeviceList() result.ens = newEnsManager(status) - result.mnemonic = "" result.network = "" result.status = status result.isDeviceSetup = false @@ -109,19 +108,13 @@ QtObject: read = getBlockedContacts notify = contactListChanged - proc mnemonicChanged*(self: ProfileView) {.signal.} - proc getMnemonic*(self: ProfileView): QVariant {.slot.} = - return newQVariant(self.mnemonic) - - proc setMnemonic*(self: ProfileView, mnemonic: string) = - self.mnemonic = mnemonic - self.mnemonicChanged() + # Do not keep the mnemonic in memory, so fetch it when necessary + let mnemonic = status_settings.getSetting[string](Setting.Mnemonic, "") + return newQVariant(mnemonic) QtProperty[QVariant] mnemonic: read = getMnemonic - write = setMnemonic - notify = mnemonicChanged proc networkChanged*(self: ProfileView) {.signal.} diff --git a/src/nim_status_client.nim b/src/nim_status_client.nim index c3c80bcf42..82ca236034 100644 --- a/src/nim_status_client.nim +++ b/src/nim_status_client.nim @@ -72,17 +72,21 @@ proc mainProc() = var profile = profile.newController(status, changeLanguage) engine.setRootContextProperty("profileModel", profile.variant) + var login = login.newController(status) + var onboarding = onboarding.newController(status) + status.events.once("login") do(a: Args): var args = AccountArgs(a) + # Delete login and onboarding from memory to remove any mnemonic that would have been saved in the accounts list + login.delete() + onboarding.delete() + status.startMessenger() profile.init(args.account) wallet.init() chat.init() - var login = login.newController(status) - var onboarding = onboarding.newController(status) - engine.setRootContextProperty("loginModel", login.variant) engine.setRootContextProperty("onboardingModel", onboarding.variant) diff --git a/ui/app/AppLayouts/Profile/Sections/BackupSeedModal.qml b/ui/app/AppLayouts/Profile/Sections/BackupSeedModal.qml index f8f9064691..6cddbdb746 100644 --- a/ui/app/AppLayouts/Profile/Sections/BackupSeedModal.qml +++ b/ui/app/AppLayouts/Profile/Sections/BackupSeedModal.qml @@ -10,100 +10,108 @@ ModalPopup { //% "Write down your seed phrase" title: qsTrId("write-down-your-seed-phrase") - Item { + Loader { + active: popup.opened + width: parent.width + height: item.height - id: seed - anchors.left: parent.left - anchors.right: parent.right - width: parent.width - height: children[0].height + sourceComponent: Component { + id: seedComponent + Item { + id: seed + width: parent.width + height: children[0].height - Rectangle { - id: wrapper - property int len: profileModel.mnemonic.split(" ").length - anchors.top: parent.top - anchors.topMargin: Style.current.padding - height: 40*(len/2) - width: 350 - border.width: 1 - color: Style.current.background - border.color: Style.current.border - radius: Style.current.radius - anchors.horizontalCenter: parent.horizontalCenter + Rectangle { + id: wrapper + property int len: mnemonicRepeater.count + anchors.top: parent.top + anchors.topMargin: Style.current.padding + height: 40 * (len / 2) + width: 350 + border.width: 1 + color: Style.current.background + border.color: Style.current.border + radius: Style.current.radius + anchors.horizontalCenter: parent.horizontalCenter - Repeater { - model: profileModel.mnemonic.split(" ") - Rectangle { - id: word - height: 40 - width: 175 - color: "transparent" - anchors.top: (index == 0 || index == (wrapper.len/2)) ? parent.top : parent.children[index-1].bottom - anchors.left: (index < (wrapper.len/2)) ? parent.left : undefined - anchors.right: (index >= wrapper.len/2) ? parent.right : undefined + Repeater { + id: mnemonicRepeater + model: profileModel.mnemonic.split(" ") + Rectangle { + id: word + height: 40 + width: 175 + color: "transparent" + anchors.top: (index == 0 + || index == (wrapper.len / 2)) ? parent.top : parent.children[index - 1].bottom + anchors.left: (index < (wrapper.len / 2)) ? parent.left : undefined + anchors.right: (index >= wrapper.len / 2) ? parent.right : undefined - Rectangle { - width: 1 - height: parent.height - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.right: parent.right - anchors.rightMargin: 175 - color: Style.current.inputBackground - visible: index >= wrapper.len/2 + Rectangle { + width: 1 + height: parent.height + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.rightMargin: 175 + color: Style.current.inputBackground + visible: index >= wrapper.len / 2 + } + + StyledText { + id: count + text: index + 1 + color: Style.current.darkGrey + anchors.bottom: parent.bottom + anchors.bottomMargin: Style.current.smallPadding + anchors.left: parent.left + anchors.leftMargin: Style.current.bigPadding + font.pixelSize: 15 + } + + StyledTextEdit { + text: modelData + font.pixelSize: 15 + anchors.bottom: parent.bottom + anchors.bottomMargin: Style.current.smallPadding + anchors.left: count.right + anchors.leftMargin: Style.current.padding + selectByMouse: true + readOnly: true + } + } + } + } } - - StyledText { - id: count - text: index+1 - color: Style.current.darkGrey - anchors.bottom: parent.bottom - anchors.bottomMargin: Style.current.smallPadding - anchors.left: parent.left - anchors.leftMargin: Style.current.bigPadding - font.pixelSize: 15 - } - - StyledTextEdit { - text: modelData - font.pixelSize: 15 - anchors.bottom: parent.bottom - anchors.bottomMargin: Style.current.smallPadding - anchors.left: count.right - anchors.leftMargin: Style.current.padding - selectByMouse: true - readOnly: true - } - - } } - } } StyledText { - id: confirmationsInfo - //% "With this 12 words you can always get your key back. Write it down. Keep it safe, offline, and separate from this device." - text: qsTrId("with-this-12-words-you-can-always-get-your-key-back.-write-it-down.-keep-it-safe,-offline,-and-separate-from-this-device.") - font.pixelSize: 14 - font.weight: Font.Medium - color: Style.current.darkGrey - anchors.bottom: parent.bottom - anchors.bottomMargin: Style.current.padding - anchors.left: parent.left - anchors.leftMargin: Style.current.smallPadding - anchors.right: parent.right - anchors.rightMargin: Style.current.smallPadding - wrapMode: Text.WordWrap + id: confirmationsInfo + //% "With this 12 words you can always get your key back. Write it down. Keep it safe, offline, and separate from this device." + text: qsTrId( + "with-this-12-words-you-can-always-get-your-key-back.-write-it-down.-keep-it-safe,-offline,-and-separate-from-this-device.") + font.pixelSize: 14 + font.weight: Font.Medium + color: Style.current.darkGrey + anchors.bottom: parent.bottom + anchors.bottomMargin: Style.current.padding + anchors.left: parent.left + anchors.leftMargin: Style.current.smallPadding + anchors.right: parent.right + anchors.rightMargin: Style.current.smallPadding + wrapMode: Text.WordWrap } footer: StyledButton { - //% "Done" - label: qsTrId("done") - anchors.right: parent.right - anchors.rightMargin: Style.current.smallPadding - anchors.bottom: parent.bottom - onClicked: { - backupSeedModal.close() - } + //% "Done" + label: qsTrId("done") + anchors.right: parent.right + anchors.rightMargin: Style.current.smallPadding + anchors.bottom: parent.bottom + onClicked: { + backupSeedModal.close() + } } } diff --git a/ui/nim-status-client.pro b/ui/nim-status-client.pro index c07706bcd0..0ca4ce6d6d 100644 --- a/ui/nim-status-client.pro +++ b/ui/nim-status-client.pro @@ -152,6 +152,7 @@ DISTFILES += \ app/AppLayouts/Profile/LeftTab/components/MenuButton.qml \ app/AppLayouts/Chat/data/EmojiReactions.qml \ app/AppLayouts/Profile/Sections/AppearanceContainer.qml \ + app/AppLayouts/Profile/Sections/BackupSeedModal.qml \ app/AppLayouts/Profile/Sections/MyProfileContainer.qml \ app/AppLayouts/Profile/Sections/SoundsContainer.qml \ app/AppLayouts/Wallet/ReceiveModal.qml \