tTrezor: add session timeout to preferences - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 43fd684d979307c68b2270456bfe024fceb6232f DIR parent 87363c8301acc0689c0e0a4c59219fdd40b16a07 HTML Author: Neil Booth <kyuupichan@gmail.com> Date: Sun, 3 Jan 2016 17:25:47 +0900 Trezor: add session timeout to preferences Fixes #803 Diffstat: M plugins/trezor/plugin.py | 30 +++++++++++++++++++++++++++--- M plugins/trezor/qt_generic.py | 27 ++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 4 deletions(-) --- DIR diff --git a/plugins/trezor/plugin.py b/plugins/trezor/plugin.py t@@ -29,11 +29,18 @@ class TrezorCompatibleWallet(BIP44_Wallet): # This is set when paired with a device, and used to re-pair # a device that is disconnected and re-connected self.device_id = None + # After timeout seconds we clear the device session + self.session_timeout = storage.get('session_timeout', 180) # Errors and other user interaction is done through the wallet's # handler. The handler is per-window and preserved across # device reconnects self.handler = None + def set_session_timeout(self, seconds): + self.print_error("setting session timeout to %d seconds" % seconds) + self.session_timeout = seconds + self.storage.put('session_timeout', seconds) + def disconnected(self): self.print_error("disconnected") self.handler.watching_only_changed() t@@ -46,9 +53,8 @@ class TrezorCompatibleWallet(BIP44_Wallet): self.print_error("wiped") self.handler.watching_only_changed() - def initialized(self): - self.print_error("initialized") - self.handler.watching_only_changed() + def timeout(self): + self.print_error("timed out") def get_action(self): pass t@@ -155,6 +161,7 @@ class TrezorCompatiblePlugin(BasePlugin): BasePlugin.__init__(self, parent, config, name) self.device = self.wallet_class.device self.wallet_class.plugin = self + self.prevent_timeout = time.time() + 3600 * 24 * 365 # A set of client instances to USB paths self.clients = set() # The device wallets we have seen to inform on reconnection t@@ -173,6 +180,13 @@ class TrezorCompatiblePlugin(BasePlugin): if now > self.last_scan + 1: self.last_scan = now self.scan_devices() + for wallet in self.paired_wallets: + if now > wallet.last_operation + wallet.session_timeout: + client = self.lookup_client(wallet) + if client: + wallet.last_operation = self.prevent_timeout + self.clear_session(client) + wallet.timeout() def scan_devices(self): paths = self.HidTransport.enumerate() t@@ -221,6 +235,9 @@ class TrezorCompatiblePlugin(BasePlugin): client.clear_session() def initialize_device(self, wallet, wizard): + # Prevent timeouts during initialization + wallet.last_operation = self.prevent_timeout + (strength, label, pin_protection, passphrase_protection) \ = wizard.request_trezor_reset_settings(self.device) t@@ -247,10 +264,16 @@ class TrezorCompatiblePlugin(BasePlugin): if not client.is_initialized(): self.initialize_device(wallet, wizard) + def operated_on(self, wallet): + self.print_error("set last_operation") + wallet.last_operation = time.time() + def pair_wallet(self, wallet, client): self.print_error("pairing wallet %s to device %s" % (wallet, client)) + self.operated_on(wallet) self.paired_wallets.add(wallet) wallet.device_id = client.features.device_id + wallet.last_operation = time.time() client.wallet = wallet wallet.connected() t@@ -301,6 +324,7 @@ class TrezorCompatiblePlugin(BasePlugin): assert isinstance(wallet, self.wallet_class) assert wallet.handler != None + self.operated_on(wallet) if wallet.device_id is None: client = self.try_to_pair_wallet(wallet) else: DIR diff --git a/plugins/trezor/qt_generic.py b/plugins/trezor/qt_generic.py t@@ -1,6 +1,7 @@ from functools import partial import threading +from PyQt4.Qt import Qt from PyQt4.Qt import QGridLayout, QInputDialog, QPushButton from PyQt4.Qt import QVBoxLayout, QLabel, SIGNAL from electrum_gui.qt.main_window import StatusBarButton t@@ -217,12 +218,17 @@ def qt_plugin_class(base_plugin_class): client().wipe_device() refresh() + def slider_moved(): + mins = timeout_slider.sliderPosition() + timeout_label.setText(_("%2d minutes") % mins) + wallet = window.wallet handler = wallet.handler device = self.device info_tab = QWidget() - info_layout = QGridLayout(info_tab) + tab_layout = QVBoxLayout(info_tab) + info_layout = QGridLayout() noyes = [_("No"), _("Yes")] bl_hash_label = QLabel() device_label = QLabel() t@@ -249,6 +255,22 @@ def qt_plugin_class(base_plugin_class): (_("Firmware Version"), version_label), (_("Language"), language_label), ]) + tab_layout.addLayout(info_layout) + + timeout_layout = QHBoxLayout() + timeout_label = QLabel() + timeout_slider = QSlider(Qt.Horizontal) + timeout_slider.setRange(1, 60) + timeout_slider.setSingleStep(1) + timeout_slider.setSliderPosition(wallet.session_timeout // 60) + timeout_slider.setTickInterval(5) + timeout_slider.setTickPosition(QSlider.TicksBelow) + timeout_slider.setTracking(True) + timeout_slider.valueChanged.connect(slider_moved) + timeout_layout.addWidget(QLabel(_("Session Timeout"))) + timeout_layout.addWidget(timeout_slider) + timeout_layout.addWidget(timeout_label) + tab_layout.addLayout(timeout_layout) advanced_tab = QWidget() advanced_layout = QGridLayout(advanced_tab) t@@ -267,8 +289,11 @@ def qt_plugin_class(base_plugin_class): vbox.addStretch(1) vbox.addLayout(Buttons(CloseButton(dialog))) + # Show values + slider_moved() refresh() dialog.setLayout(vbox) handler.exec_dialog(dialog) + wallet.set_session_timeout(timeout_slider.sliderPosition() * 60) return QtPlugin