From fbb35a54cb645fe377a8518880c9f49e6f7b5d58 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 10 Apr 2014 13:05:55 -0300 Subject: Use non blocking dialog for Pastebin result With this change we no longer need to call the dialog with reactor.callLater. Also removed useless failure.trap Closes #5404. --- src/leap/bitmask/gui/loggerwindow.py | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/loggerwindow.py b/src/leap/bitmask/gui/loggerwindow.py index 9f396574..4bf20e35 100644 --- a/src/leap/bitmask/gui/loggerwindow.py +++ b/src/leap/bitmask/gui/loggerwindow.py @@ -21,14 +21,14 @@ History log window import logging import cgi -from PySide import QtGui +from PySide import QtCore, QtGui from twisted.internet import threads from ui_loggerwindow import Ui_LoggerWindow from leap.bitmask.util.constants import PASTEBIN_API_DEV_KEY from leap.bitmask.util.leap_log_handler import LeapLogHandler -from leap.bitmask.util.pastebin import PastebinAPI, PastebinError +from leap.bitmask.util.pastebin import PastebinAPI from leap.common.check import leap_assert, leap_assert_type logger = logging.getLogger(__name__) @@ -220,12 +220,16 @@ class LoggerWindow(QtGui.QDialog): :param link: the recently created pastebin link. :type link: str """ + self._set_pastebin_sending(False) msg = self.tr("Your pastebin link {0}") msg = msg.format(link) - show_info = lambda: QtGui.QMessageBox.information( - self, self.tr("Pastebin OK"), msg) - self._set_pastebin_sending(False) - self.reactor.callLater(0, show_info) + + # We save the dialog in an instance member to avoid dialog being + # deleted right after we exit this method + self._msgBox = msgBox = QtGui.QMessageBox( + QtGui.QMessageBox.Information, self.tr("Pastebin OK"), msg) + msgBox.setWindowModality(QtCore.Qt.NonModal) + msgBox.show() def pastebin_err(failure): """ @@ -234,13 +238,17 @@ class LoggerWindow(QtGui.QDialog): :param failure: the failure that triggered the errback. :type failure: twisted.python.failure.Failure """ + self._set_pastebin_sending(False) logger.error(repr(failure)) + msg = self.tr("Sending logs to Pastebin failed!") - show_err = lambda: QtGui.QMessageBox.critical( - self, self.tr("Pastebin Error"), msg) - self._set_pastebin_sending(False) - self.reactor.callLater(0, show_err) - failure.trap(PastebinError) + + # We save the dialog in an instance member to avoid dialog being + # deleted right after we exit this method + self._msgBox = msgBox = QtGui.QMessageBox( + QtGui.QMessageBox.Critical, self.tr("Pastebin Error"), msg) + msgBox.setWindowModality(QtCore.Qt.NonModal) + msgBox.show() self._set_pastebin_sending(True) d = threads.deferToThread(do_pastebin) -- cgit v1.2.3 From d0797917bc516a44b2201251c2032d7231637d8a Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 10 Apr 2014 17:01:42 -0300 Subject: Hide mainwindow on quit and show tooltip. --- src/leap/bitmask/gui/mainwindow.py | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 5abfaa67..f097faca 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -2041,6 +2041,15 @@ class MainWindow(QtGui.QMainWindow): # TODO separate the shutting down of services from the # UI stuff. + # first thing to do quitting, hide the mainwindow and show tooltip. + self.hide() + self._systray.showMessage( + self.tr('Quitting...'), + self.tr('The app is quitting, please wait.')) + + # explicitly process events to display tooltip immediately + QtCore.QCoreApplication.processEvents() + # Set this in case that the app is hidden QtGui.QApplication.setQuitOnLastWindowClosed(True) -- cgit v1.2.3 From 65bbc9ac87092053a8079d4d7d88cac4df5fbc36 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 10 Apr 2014 16:59:07 -0300 Subject: Add flag to start the app hidden in the tray. Closes #4990. --- src/leap/bitmask/gui/mainwindow.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 5abfaa67..0cc6104b 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -124,7 +124,8 @@ class MainWindow(QtGui.QMainWindow): def __init__(self, quit_callback, openvpn_verb=1, - bypass_checks=False): + bypass_checks=False, + start_hidden=False): """ Constructor for the client main window @@ -136,6 +137,9 @@ class MainWindow(QtGui.QMainWindow): first round of checks for CA certificates at bootstrap :type bypass_checks: bool + :param start_hidden: Set to true if the app should not show the window + but just the tray. + :type start_hidden: bool """ QtGui.QMainWindow.__init__(self) @@ -342,6 +346,7 @@ class MainWindow(QtGui.QMainWindow): self._logger_window = None self._bypass_checks = bypass_checks + self._start_hidden = start_hidden # We initialize Soledad and Keymanager instances as # transparent proxies, so we can pass the reference freely @@ -666,9 +671,11 @@ class MainWindow(QtGui.QMainWindow): providers = self._settings.get_configured_providers() self._login_widget.set_providers(providers) self._show_systray() - self.show() - if IS_MAC: - self.raise_() + + if not self._start_hidden: + self.show() + if IS_MAC: + self.raise_() self._hide_unsupported_services() @@ -787,6 +794,12 @@ class MainWindow(QtGui.QMainWindow): self._mail_status.set_systray(self._systray) self._eip_status.set_systray(self._systray) + hello = lambda: self._systray.showMessage( + self.tr('Hello!'), + self.tr('Bitmask has started in the tray.')) + # we wait for the systray to be ready + reactor.callLater(1, hello) + def _tray_activated(self, reason=None): """ SLOT -- cgit v1.2.3 From 236285888bbdbb37d2fc90e0b4977c3a4bd7045b Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 11 Apr 2014 12:17:43 -0300 Subject: Handle pastebin post limit error. Closes #5492. --- src/leap/bitmask/gui/loggerwindow.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/loggerwindow.py b/src/leap/bitmask/gui/loggerwindow.py index 4bf20e35..b0e45a50 100644 --- a/src/leap/bitmask/gui/loggerwindow.py +++ b/src/leap/bitmask/gui/loggerwindow.py @@ -28,7 +28,7 @@ from ui_loggerwindow import Ui_LoggerWindow from leap.bitmask.util.constants import PASTEBIN_API_DEV_KEY from leap.bitmask.util.leap_log_handler import LeapLogHandler -from leap.bitmask.util.pastebin import PastebinAPI +from leap.bitmask.util import pastebin from leap.common.check import leap_assert, leap_assert_type logger = logging.getLogger(__name__) @@ -203,7 +203,7 @@ class LoggerWindow(QtGui.QDialog): Send content to pastebin and return the link. """ content = self._current_history - pb = PastebinAPI() + pb = pastebin.PastebinAPI() link = pb.paste(PASTEBIN_API_DEV_KEY, content, paste_name="Bitmask log", paste_expire_date='1W') @@ -242,6 +242,8 @@ class LoggerWindow(QtGui.QDialog): logger.error(repr(failure)) msg = self.tr("Sending logs to Pastebin failed!") + if failure.check(pastebin.PostLimitError): + msg = self.tr('Maximum posts per day reached') # We save the dialog in an instance member to avoid dialog being # deleted right after we exit this method -- cgit v1.2.3 From a6e96bc487ffb9c4b4d34957ca4b2b48a88b0ccb Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 11 Apr 2014 13:50:15 -0300 Subject: Enable provider widget depending on radio button. Disable providers combo box during check and enable combo or line edit depending on radio button. [Closes #5495] --- src/leap/bitmask/gui/wizard.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index e2c1a16e..ebcee400 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -390,7 +390,13 @@ class Wizard(QtGui.QWizard): self.ui.grpCheckProvider.setVisible(True) self.ui.btnCheck.setEnabled(False) - self.ui.lnProvider.setEnabled(False) + + # Disable provider widget + if self.ui.rbNewProvider.isChecked(): + self.ui.lnProvider.setEnabled(False) + else: + self.ui.cbProviders.setEnabled(False) + self.button(QtGui.QWizard.BackButton).clearFocus() self.ui.lblNameResolution.setPixmap(self.QUESTION_ICON) @@ -506,7 +512,12 @@ class Wizard(QtGui.QWizard): "") self.ui.lblProviderSelectStatus.setText(status) self.ui.btnCheck.setEnabled(True) - self.ui.lnProvider.setEnabled(True) + + # Enable provider widget + if self.ui.rbNewProvider.isChecked(): + self.ui.lnProvider.setEnabled(True) + else: + self.ui.cbProviders.setEnabled(True) def _download_ca_cert(self, data): """ -- cgit v1.2.3 From c6c67fd8d9c40fec61c9f7ee7677544301f437dd Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 11 Apr 2014 17:49:26 -0300 Subject: Hide bandwidth if the openvpn process is killed. [Closes #5497] --- src/leap/bitmask/gui/mainwindow.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 9d0f9145..56ac1545 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1783,6 +1783,8 @@ class MainWindow(QtGui.QMainWindow): elif exitCode != 0 or not self.user_stopped_eip: eip_status_label = self.tr("{0} finished in an unexpected manner!") eip_status_label = eip_status_label.format(self._eip_name) + self._eip_status.eip_stopped() + self._eip_status.set_eip_status_icon("error") self._eip_status.set_eip_status(eip_status_label, error=True) signal = qtsigs.connection_died_signal -- cgit v1.2.3 From e2ea44e2b042e86c0eb3a02eb52a92457b6bf179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Thu, 20 Mar 2014 10:41:48 -0300 Subject: Refactor EIPBootstrapper to the backend --- src/leap/bitmask/gui/mainwindow.py | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 56ac1545..61aff5f9 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -61,7 +61,6 @@ from leap.bitmask.services.mail import conductor as mail_conductor from leap.bitmask.services import EIP_SERVICE, MX_SERVICE from leap.bitmask.services.eip import eipconfig from leap.bitmask.services.eip import get_openvpn_management -from leap.bitmask.services.eip.eipbootstrapper import EIPBootstrapper from leap.bitmask.services.eip.connection import EIPConnection from leap.bitmask.services.eip.vpnprocess import VPN from leap.bitmask.services.eip.vpnprocess import OpenVPNAlreadyRunning @@ -230,17 +229,6 @@ class MainWindow(QtGui.QMainWindow): self._backend_connect() - # This thread is similar to the provider bootstrapper - self._eip_bootstrapper = EIPBootstrapper() - - # EIP signals ---- move to eip conductor. - # TODO change the name of "download_config" signal to - # something less confusing (config_ready maybe) - self._eip_bootstrapper.download_config.connect( - self._eip_intermediate_stage) - self._eip_bootstrapper.download_client_certificate.connect( - self._finish_eip_bootstrap) - self._vpn = VPN(openvpn_verb=openvpn_verb) # connect vpn process signals @@ -410,6 +398,9 @@ class MainWindow(QtGui.QMainWindow): sig.prov_cancelled_setup.connect(self._set_login_cancelled) + sig.eip_download_config.connect(self._eip_intermediate_stage) + sig.eip_download_client_certificate.connect(self._finish_eip_bootstrap) + def _backend_disconnect(self): """ Helper to disconnect from backend signals. @@ -1802,17 +1793,16 @@ class MainWindow(QtGui.QMainWindow): Start the EIP bootstrapping sequence if the client is configured to do so. """ - leap_assert(self._eip_bootstrapper, "We need an eip bootstrapper!") - provider_config = self._get_best_provider_config() if self._provides_eip_and_enabled() and not self._already_started_eip: # XXX this should be handled by the state machine. self._eip_status.set_eip_status( self.tr("Starting...")) - self._eip_bootstrapper.run_eip_setup_checks( - provider_config, - download_if_needed=True) + + domain = self._login_widget.get_selected_provider() + self._backend.setup_eip(domain) + self._already_started_eip = True # we want to start soledad anyway after a certain timeout if eip # fails to come up @@ -1834,18 +1824,18 @@ class MainWindow(QtGui.QMainWindow): def _finish_eip_bootstrap(self, data): """ SLOT - TRIGGER: self._eip_bootstrapper.download_client_certificate + TRIGGER: self._backend.signaler.eip_download_client_certificate Starts the VPN thread if the eip configuration is properly loaded """ leap_assert(self._eip_config, "We need an eip config!") - passed = data[self._eip_bootstrapper.PASSED_KEY] + passed = data[self._backend.PASSED_KEY] if not passed: error_msg = self.tr("There was a problem with the provider") self._eip_status.set_eip_status(error_msg, error=True) - logger.error(data[self._eip_bootstrapper.ERROR_KEY]) + logger.error(data[self._backend.ERROR_KEY]) self._already_started_eip = False return @@ -1869,7 +1859,7 @@ class MainWindow(QtGui.QMainWindow): """ SLOT TRIGGERS: - self._eip_bootstrapper.download_config + self._backend.signaler.eip_download_config If there was a problem, displays it, otherwise it does nothing. This is used for intermediate bootstrapping stages, in case @@ -1964,7 +1954,7 @@ class MainWindow(QtGui.QMainWindow): self._backend.signaler.prov_name_resolution self._backend.signaler.prov_https_connection self._backend.signaler.prov_download_ca_cert - self._eip_bootstrapper.download_config + self._backend.signaler.eip_download_config If there was a problem, displays it, otherwise it does nothing. This is used for intermediate bootstrapping stages, in case -- cgit v1.2.3 From 6444c6c9c758b1f4bd291d5e4e5455b84345ec9b Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 19 Mar 2014 16:06:07 -0300 Subject: Move SRPAuth to the backend. * Move methods from SRPAuth to backend: login, logout, change_password. * Add backend section to hold temporary hack code, needed in the process of splitting frontend and backend. * Replace pyside signals with Signaler signals. * Move all the signaling and thread launching in SRPAuth inside of __impl. * Move defer handling code (callbacks/errbacks) to the backend and left only signal handling in the GUI. [Closes #5347] --- src/leap/bitmask/gui/mainwindow.py | 121 ++++++++++++------------ src/leap/bitmask/gui/preferenceswindow.py | 150 ++++++++++++++++++------------ 2 files changed, 155 insertions(+), 116 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 61aff5f9..492ea125 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -20,13 +20,13 @@ Main window for Bitmask. import logging import socket +from functools import partial from threading import Condition from datetime import datetime from PySide import QtCore, QtGui from zope.proxy import ProxyBase, setProxiedObject from twisted.internet import reactor, threads -from twisted.internet.defer import CancelledError from leap.bitmask import __version__ as VERSION from leap.bitmask import __version_hash__ as VERSION_HASH @@ -34,9 +34,6 @@ from leap.bitmask.config import flags from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.config.providerconfig import ProviderConfig -from leap.bitmask.crypto import srpauth -from leap.bitmask.crypto.srpauth import SRPAuth - from leap.bitmask.gui.loggerwindow import LoggerWindow from leap.bitmask.gui.advanced_key_management import AdvancedKeyManagement from leap.bitmask.gui.login import LoginWidget @@ -213,8 +210,8 @@ class MainWindow(QtGui.QMainWindow): # than once # XXX HACK!! But we need it as long as we are using # provider_config in here - self._provider_config = ( - self._backend._components["provider"]._provider_config) + self._provider_config = self._backend.get_provider_config() + # Used for automatic start of EIP self._provisional_provider_config = ProviderConfig() self._eip_config = eipconfig.EIPConfig() @@ -342,7 +339,6 @@ class MainWindow(QtGui.QMainWindow): self._soledad = ProxyBase(None) self._keymanager = ProxyBase(None) - self._login_defer = None self._soledad_defer = None self._mail_conductor = mail_conductor.MailConductor( @@ -377,6 +373,18 @@ class MainWindow(QtGui.QMainWindow): # so this has to be done after eip_machine is started self._finish_init() + def _not_logged_in_error(self): + """ + Handle the 'not logged in' backend error if we try to do an operation + that requires to be logged in. + """ + logger.critical("You are trying to do an operation that requires " + "log in first.") + QtGui.QMessageBox.critical( + self, self.tr("Application error"), + self.tr("You are trying to do an operation " + "that requires logging in first.")) + def _backend_connect(self): """ Helper to connect to backend signals @@ -401,6 +409,34 @@ class MainWindow(QtGui.QMainWindow): sig.eip_download_config.connect(self._eip_intermediate_stage) sig.eip_download_client_certificate.connect(self._finish_eip_bootstrap) + # Authentication related signals + sig.srp_auth_ok.connect(self._authentication_finished) + + auth_error = partial( + self._authentication_error, + self.tr("Unknown error.")) + sig.srp_auth_error.connect(auth_error) + + auth_server_error = partial( + self._authentication_error, + self.tr("There was a server problem with authentication.")) + sig.srp_auth_server_error.connect(auth_server_error) + + auth_connection_error = partial( + self._authentication_error, + self.tr("Could not establish a connection.")) + sig.srp_auth_connection_error.connect(auth_connection_error) + + auth_bad_user_or_password = partial( + self._authentication_error, + self.tr("Invalid username or password.")) + sig.srp_auth_bad_user_or_password.connect(auth_bad_user_or_password) + + sig.srp_logout_ok.connect(self._logout_ok) + sig.srp_logout_error.connect(self._logout_error) + + sig.srp_not_logged_in_error.connect(self._not_logged_in_error) + def _backend_disconnect(self): """ Helper to disconnect from backend signals. @@ -538,7 +574,7 @@ class MainWindow(QtGui.QMainWindow): Displays the preferences window. """ preferences = PreferencesWindow( - self, self._srp_auth, self._provider_config, self._soledad, + self, self._backend, self._provider_config, self._soledad, self._login_widget.get_selected_provider()) self.soledad_ready.connect(preferences.set_soledad_ready) @@ -1050,39 +1086,20 @@ class MainWindow(QtGui.QMainWindow): if self._login_widget.start_login(): self._download_provider_config() - def _login_errback(self, failure): - """ - Error handler for the srpauth.authenticate method. - - :param failure: failure object that Twisted generates - :type failure: twisted.python.failure.Failure + def _authentication_error(self, msg): """ - # NOTE: this behavior needs to be managed through the signaler, - # as we are doing with the prov_cancelled_setup signal. - # After we move srpauth to the backend, we need to update this. - logger.error("Error logging in, {0!r}".format(failure)) + SLOT + TRIGGERS: + Signaler.srp_auth_error + Signaler.srp_auth_server_error + Signaler.srp_auth_connection_error + Signaler.srp_auth_bad_user_or_password - if failure.check(CancelledError): - logger.debug("Defer cancelled.") - failure.trap(Exception) - self._set_login_cancelled() - return - elif failure.check(srpauth.SRPAuthBadUserOrPassword): - msg = self.tr("Invalid username or password.") - elif failure.check(srpauth.SRPAuthBadStatusCode, - srpauth.SRPAuthenticationError, - srpauth.SRPAuthVerificationFailed, - srpauth.SRPAuthNoSessionId, - srpauth.SRPAuthNoSalt, srpauth.SRPAuthNoB, - srpauth.SRPAuthBadDataFromServer, - srpauth.SRPAuthJSONDecodeError): - msg = self.tr("There was a server problem with authentication.") - elif failure.check(srpauth.SRPAuthConnectionError): - msg = self.tr("Could not establish a connection.") - else: - # this shouldn't happen, but just in case. - msg = self.tr("Unknown error: {0!r}".format(failure.value)) + Handle the authentication errors. + :param msg: the message to show to the user. + :type msg: unicode + """ self._login_widget.set_status(msg) self._login_widget.set_enabled(True) @@ -1101,12 +1118,9 @@ class MainWindow(QtGui.QMainWindow): """ Cancel the running defers to avoid app blocking. """ + # XXX: Should we stop all the backend defers? self._backend.cancel_setup_provider() - - if self._login_defer is not None: - logger.debug("Cancelling login defer.") - self._login_defer.cancel() - self._login_defer = None + self._backend.cancel_login() if self._soledad_defer is not None: logger.debug("Cancelling soledad defer.") @@ -1142,15 +1156,8 @@ class MainWindow(QtGui.QMainWindow): self._hide_unsupported_services() - if self._srp_auth is None: - self._srp_auth = SRPAuth(self._provider_config) - self._srp_auth.authentication_finished.connect( - self._authentication_finished) - self._srp_auth.logout_ok.connect(self._logout_ok) - self._srp_auth.logout_error.connect(self._logout_error) - - self._login_defer = self._srp_auth.authenticate(username, password) - self._login_defer.addErrback(self._login_errback) + domain = self._provider_config.get_domain() + self._backend.login(domain, username, password) else: self._login_widget.set_status( "Unable to login: Problem with provider") @@ -1172,7 +1179,6 @@ class MainWindow(QtGui.QMainWindow): domain = self._provider_config.get_domain() full_user_id = make_address(user, domain) self._mail_conductor.userid = full_user_id - self._login_defer = None self._start_eip_bootstrap() # if soledad/mail is enabled: @@ -1916,7 +1922,7 @@ class MainWindow(QtGui.QMainWindow): # XXX: If other defers are doing authenticated stuff, this # might conflict with those. CHECK! - threads.deferToThread(self._srp_auth.logout) + self._backend.logout() self.logout.emit() def _logout_error(self): @@ -2017,11 +2023,8 @@ class MainWindow(QtGui.QMainWindow): self._stop_imap_service() - if self._srp_auth is not None: - if self._srp_auth.get_session_id() is not None or \ - self._srp_auth.get_token() is not None: - # XXX this can timeout after loong time: See #3368 - self._srp_auth.logout() + if self._logged_user is not None: + self._backend.logout() if self._soledad_bootstrapper.soledad is not None: logger.debug("Closing soledad...") diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py index b2cc2236..f6bd1ed3 100644 --- a/src/leap/bitmask/gui/preferenceswindow.py +++ b/src/leap/bitmask/gui/preferenceswindow.py @@ -29,7 +29,6 @@ from leap.bitmask.provider import get_provider_path from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.gui.ui_preferences import Ui_Preferences from leap.soledad.client import NoStorageSecret -from leap.bitmask.crypto.srpauth import SRPAuthBadUserOrPassword from leap.bitmask.util.password import basic_password_checks from leap.bitmask.services import get_supported from leap.bitmask.config.providerconfig import ProviderConfig @@ -44,12 +43,12 @@ class PreferencesWindow(QtGui.QDialog): """ preferences_saved = QtCore.Signal() - def __init__(self, parent, srp_auth, provider_config, soledad, domain): + def __init__(self, parent, backend, provider_config, soledad, domain): """ :param parent: parent object of the PreferencesWindow. :parent type: QWidget - :param srp_auth: SRPAuth object configured in the main app. - :type srp_auth: SRPAuth + :param backend: Backend being used + :type backend: Backend :param provider_config: ProviderConfig object. :type provider_config: ProviderConfig :param soledad: Soledad instance @@ -60,9 +59,13 @@ class PreferencesWindow(QtGui.QDialog): QtGui.QDialog.__init__(self, parent) self.AUTOMATIC_GATEWAY_LABEL = self.tr("Automatic") - self._srp_auth = srp_auth + self._backend = backend self._settings = LeapSettings() self._soledad = soledad + self._provider_config = provider_config + self._domain = domain + + self._backend_connect() # Load UI self.ui = Ui_Preferences() @@ -82,40 +85,57 @@ class PreferencesWindow(QtGui.QDialog): else: self._add_configured_providers() - pw_enabled = False - - # check if the user is logged in - if srp_auth is not None and srp_auth.get_token() is not None: - # check if provider has 'mx' ... - if provider_config.provides_mx(): - enabled_services = self._settings.get_enabled_services(domain) - mx_name = get_service_display_name(MX_SERVICE) - - # ... and if the user have it enabled - if MX_SERVICE not in enabled_services: - msg = self.tr("You need to enable {0} in order to change " - "the password.".format(mx_name)) - self._set_password_change_status(msg, error=True) - else: - if sameProxiedObjects(self._soledad, None): - msg = self.tr( - "You need to wait until {0} is ready in " - "order to change the password.".format(mx_name)) - self._set_password_change_status(msg) - else: - # Soledad is bootstrapped - pw_enabled = True - else: - pw_enabled = True - else: - msg = self.tr( - "In order to change your password you need to be logged in.") - self._set_password_change_status(msg) + self._backend.get_logged_in_status() self._select_provider_by_name(domain) + def _is_logged_in(self): + """ + SLOT + TRIGGERS: + Signaler.srp_status_logged_in + + Actions to perform is the user is logged in. + """ + settings = self._settings + pw_enabled = True + + # check if provider has 'mx' ... + # TODO: we should move this to the backend. + if self._provider_config.provides_mx(): + enabled_services = settings.get_enabled_services(self._domain) + mx_name = get_service_display_name(MX_SERVICE) + + # ... and if the user have it enabled + if MX_SERVICE not in enabled_services: + msg = self.tr("You need to enable {0} in order to change " + "the password.".format(mx_name)) + self._set_password_change_status(msg, error=True) + pw_enabled = False + else: + # check if Soledad is bootstrapped + if sameProxiedObjects(self._soledad, None): + msg = self.tr( + "You need to wait until {0} is ready in " + "order to change the password.".format(mx_name)) + self._set_password_change_status(msg) + pw_enabled = False + self.ui.gbPasswordChange.setEnabled(pw_enabled) + def _not_logged_in(self): + """ + SLOT + TRIGGERS: + Signaler.srp_status_not_logged_in + + Actions to perform if the user is not logged in. + """ + msg = self.tr( + "In order to change your password you need to be logged in.") + self._set_password_change_status(msg) + self.ui.gbPasswordChange.setEnabled(False) + def set_soledad_ready(self): """ SLOT @@ -185,19 +205,17 @@ class PreferencesWindow(QtGui.QDialog): return self._set_changing_password(True) - d = self._srp_auth.change_password(current_password, new_password) - d.addCallback(partial(self._change_password_success, new_password)) - d.addErrback(self._change_password_problem) + self._backend.change_password(current_password, new_password) - def _change_password_success(self, new_password, _): + def _change_password_ok(self): """ - Callback used to display a successfully performed action. + SLOT + TRIGGERS: + self._backend.signaler.srp_password_change_ok - :param new_password: the new password for the user. - :type new_password: str. - :param _: the returned data from self._srp_auth.change_password - Ignored + Callback used to display a successfully changed password. """ + new_password = self.ui.leNewPassword.text() logger.debug("SRP password changed successfully.") try: self._soledad.change_passphrase(new_password) @@ -211,24 +229,21 @@ class PreferencesWindow(QtGui.QDialog): self._clear_password_inputs() self._set_changing_password(False) - def _change_password_problem(self, failure): - """ - Errback called if there was a problem with the deferred. - Also is used to display an error message. - - :param failure: the cause of the method failed. - :type failure: twisted.python.Failure + def _change_password_problem(self, msg): """ - logger.error("Error changing password: %s", (failure, )) - problem = self.tr("There was a problem changing the password.") - - if failure.check(SRPAuthBadUserOrPassword): - problem = self.tr("You did not enter a correct current password.") + SLOT + TRIGGERS: + self._backend.signaler.srp_password_change_error + self._backend.signaler.srp_password_change_badpw - self._set_password_change_status(problem, error=True) + Callback used to display an error on changing password. + :param msg: the message to show to the user. + :type msg: unicode + """ + logger.error("Error changing password") + self._set_password_change_status(msg, error=True) self._set_changing_password(False) - failure.trap(Exception) def _clear_password_inputs(self): """ @@ -387,3 +402,24 @@ class PreferencesWindow(QtGui.QDialog): provider_config = None return provider_config + + def _backend_connect(self): + """ + Helper to connect to backend signals + """ + sig = self._backend.signaler + + sig.srp_status_logged_in.connect(self._is_logged_in) + sig.srp_status_not_logged_in.connect(self._not_logged_in) + + sig.srp_password_change_ok.connect(self._change_password_ok) + + pwd_change_error = partial( + self._change_password_problem, + self.tr("There was a problem changing the password.")) + sig.srp_password_change_error.connect(pwd_change_error) + + pwd_change_badpw = partial( + self._change_password_problem, + self.tr("You did not enter a correct current password.")) + sig.srp_password_change_badpw.connect(pwd_change_badpw) -- cgit v1.2.3 From 0af9f067381772b6108e7e705a5b60e90c75aaef Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 25 Mar 2014 17:17:15 -0300 Subject: Keep track of backend's connected signals. --- src/leap/bitmask/gui/mainwindow.py | 126 +++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 55 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 492ea125..24997d83 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -20,7 +20,6 @@ Main window for Bitmask. import logging import socket -from functools import partial from threading import Condition from datetime import datetime @@ -224,6 +223,7 @@ class MainWindow(QtGui.QMainWindow): self._logged_user = None self._logged_in_offline = False + self._backend_connected_signals = {} self._backend_connect() self._vpn = VPN(openvpn_verb=openvpn_verb) @@ -361,7 +361,7 @@ class MainWindow(QtGui.QMainWindow): if self._first_run(): self._wizard_firstrun = True - self._backend_disconnect() + self._disconnect_and_untrack() self._wizard = Wizard(backend=self._backend, bypass_checks=bypass_checks) # Give this window time to finish init and then show the wizard @@ -385,72 +385,88 @@ class MainWindow(QtGui.QMainWindow): self.tr("You are trying to do an operation " "that requires logging in first.")) + def _connect_and_track(self, signal, method): + """ + Helper to connect signals and keep track of them. + + :param signal: the signal to connect to. + :type signal: QtCore.Signal + :param method: the method to call when the signal is triggered. + :type method: callable, Slot or Signal + """ + self._backend_connected_signals[signal] = method + signal.connect(method) + def _backend_connect(self): """ Helper to connect to backend signals """ sig = self._backend.signaler - sig.prov_name_resolution.connect(self._intermediate_stage) - sig.prov_https_connection.connect(self._intermediate_stage) - sig.prov_download_ca_cert.connect(self._intermediate_stage) - - sig.prov_download_provider_info.connect(self._load_provider_config) - sig.prov_check_api_certificate.connect(self._provider_config_loaded) - - # Only used at login, no need to disconnect this like we do - # with the other - sig.prov_problem_with_provider.connect(self._login_problem_provider) - + self._connect_and_track(sig.prov_name_resolution, + self._intermediate_stage) + self._connect_and_track(sig.prov_https_connection, + self._intermediate_stage) + self._connect_and_track(sig.prov_download_ca_cert, + self._intermediate_stage) + + self._connect_and_track(sig.prov_download_provider_info, + self._load_provider_config) + self._connect_and_track(sig.prov_check_api_certificate, + self._provider_config_loaded) + + self._connect_and_track(sig.prov_problem_with_provider, + self._login_problem_provider) + + self._connect_and_track(sig.prov_cancelled_setup, + self._set_login_cancelled) + + self._connect_and_track(sig.srp_auth_ok, self._authentication_finished) + + auth_error = ( + lambda: self._authentication_error(self.tr("Unknown error."))) + self._connect_and_track(sig.srp_auth_error, auth_error) + + auth_server_error = ( + lambda: self._authentication_error( + self.tr("There was a server problem with authentication."))) + self._connect_and_track(sig.srp_auth_server_error, auth_server_error) + + auth_connection_error = ( + lambda: self._authentication_error( + self.tr("Could not establish a connection."))) + self._connect_and_track(sig.srp_auth_connection_error, + auth_connection_error) + + auth_bad_user_or_password = ( + lambda: self._authentication_error( + self.tr("Invalid username or password."))) + self._connect_and_track(sig.srp_auth_bad_user_or_password, + auth_bad_user_or_password) + + self._connect_and_track(sig.srp_logout_ok, self._logout_ok) + self._connect_and_track(sig.srp_logout_error, self._logout_error) + + self._connect_and_track(sig.srp_not_logged_in_error, + self._not_logged_in_error) + + # We don't want to disconnect some signals so don't track them: sig.prov_unsupported_client.connect(self._needs_update) sig.prov_unsupported_api.connect(self._incompatible_api) - sig.prov_cancelled_setup.connect(self._set_login_cancelled) - - sig.eip_download_config.connect(self._eip_intermediate_stage) - sig.eip_download_client_certificate.connect(self._finish_eip_bootstrap) - - # Authentication related signals - sig.srp_auth_ok.connect(self._authentication_finished) - - auth_error = partial( - self._authentication_error, - self.tr("Unknown error.")) - sig.srp_auth_error.connect(auth_error) - - auth_server_error = partial( - self._authentication_error, - self.tr("There was a server problem with authentication.")) - sig.srp_auth_server_error.connect(auth_server_error) - - auth_connection_error = partial( - self._authentication_error, - self.tr("Could not establish a connection.")) - sig.srp_auth_connection_error.connect(auth_connection_error) - - auth_bad_user_or_password = partial( - self._authentication_error, - self.tr("Invalid username or password.")) - sig.srp_auth_bad_user_or_password.connect(auth_bad_user_or_password) - - sig.srp_logout_ok.connect(self._logout_ok) - sig.srp_logout_error.connect(self._logout_error) - - sig.srp_not_logged_in_error.connect(self._not_logged_in_error) - - def _backend_disconnect(self): + def _disconnect_and_untrack(self): """ - Helper to disconnect from backend signals. + Helper to disconnect the tracked signals. Some signals are emitted from the wizard, and we want to ignore those. """ - sig = self._backend.signaler - sig.prov_name_resolution.disconnect(self._intermediate_stage) - sig.prov_https_connection.disconnect(self._intermediate_stage) - sig.prov_download_ca_cert.disconnect(self._intermediate_stage) + for signal, method in self._backend_connected_signals.items(): + try: + signal.disconnect(method) + except RuntimeError: + pass # Signal was not connected - sig.prov_download_provider_info.disconnect(self._load_provider_config) - sig.prov_check_api_certificate.disconnect(self._provider_config_loaded) + self._backend_connected_signals = {} def _rejected_wizard(self): """ @@ -489,7 +505,7 @@ class MainWindow(QtGui.QMainWindow): there. """ if self._wizard is None: - self._backend_disconnect() + self._disconnect_and_untrack() self._wizard = Wizard(backend=self._backend, bypass_checks=self._bypass_checks) self._wizard.accepted.connect(self._finish_init) -- cgit v1.2.3 From dae03c6f8eeeee7ed573b9b829032a7eea766bf1 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 25 Mar 2014 18:36:10 -0300 Subject: Disable wizard if we are logging in. This avoids signaling conflicts like the provider being setup in the wizard and being bootstrapped during login. --- src/leap/bitmask/gui/mainwindow.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 24997d83..83a6ce45 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1099,6 +1099,7 @@ class MainWindow(QtGui.QMainWindow): self.offline_mode_bypass_login.emit() else: leap_assert(self._provider_config, "We need a provider config") + self.ui.action_create_new_account.setEnabled(False) if self._login_widget.start_login(): self._download_provider_config() @@ -1118,6 +1119,7 @@ class MainWindow(QtGui.QMainWindow): """ self._login_widget.set_status(msg) self._login_widget.set_enabled(True) + self.ui.action_create_new_account.setEnabled(True) def _cancel_login(self): """ @@ -1196,6 +1198,7 @@ class MainWindow(QtGui.QMainWindow): full_user_id = make_address(user, domain) self._mail_conductor.userid = full_user_id self._start_eip_bootstrap() + self.ui.action_create_new_account.setEnabled(True) # if soledad/mail is enabled: if MX_SERVICE in self._enabled_services: -- cgit v1.2.3 From 733dc642962c14cd664aba694e4d3b5300e69d8b Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 28 Mar 2014 11:37:13 -0300 Subject: Move openvpn_verb to config.flags --- src/leap/bitmask/gui/mainwindow.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 83a6ce45..6eaf2dfb 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -118,7 +118,6 @@ class MainWindow(QtGui.QMainWindow): SERVICE_STOP_TIMEOUT = 20 def __init__(self, quit_callback, - openvpn_verb=1, bypass_checks=False, start_hidden=False): """ @@ -226,7 +225,7 @@ class MainWindow(QtGui.QMainWindow): self._backend_connected_signals = {} self._backend_connect() - self._vpn = VPN(openvpn_verb=openvpn_verb) + self._vpn = VPN() # connect vpn process signals self._vpn.qtsigs.state_changed.connect( -- cgit v1.2.3 From a73c432400eb6a614706fc615a505ed78d4031e3 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 27 Mar 2014 17:16:04 -0300 Subject: Move EIP to the backend. - Add backend eip management - Connect gui with new eip signals - remove old unused code - remove Qt dependency from backend services. - use Signaler to emit status/state changes from openvpn --- src/leap/bitmask/gui/eip_status.py | 55 +++---- src/leap/bitmask/gui/mainwindow.py | 297 +++++++++++++++++-------------------- 2 files changed, 160 insertions(+), 192 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py index 19942d9d..f24d87c7 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -25,7 +25,6 @@ from functools import partial from PySide import QtCore, QtGui from leap.bitmask.services.eip.connection import EIPConnection -from leap.bitmask.services.eip.vpnprocess import VPNManager from leap.bitmask.services import get_service_display_name, EIP_SERVICE from leap.bitmask.platform_init import IS_LINUX from leap.bitmask.util.averages import RateMovingAverage @@ -99,7 +98,7 @@ class EIPStatusWidget(QtGui.QWidget): status figures. """ self.DISPLAY_TRAFFIC_RATES = not self.DISPLAY_TRAFFIC_RATES - self.update_vpn_status(None) # refresh + self.update_vpn_status() # refresh def _set_traffic_rates(self): """ @@ -117,7 +116,7 @@ class EIPStatusWidget(QtGui.QWidget): """ self._up_rate.reset() self._down_rate.reset() - self.update_vpn_status(None) + self.update_vpn_status() def _update_traffic_rates(self, up, down): """ @@ -348,23 +347,26 @@ class EIPStatusWidget(QtGui.QWidget): self.tr("Traffic is being routed in the clear")) self.ui.lblEIPStatus.show() - def update_vpn_status(self, data): + def update_vpn_status(self, data=None): """ SLOT - TRIGGER: VPN.status_changed + TRIGGER: Signaler.eip_status_changed - Updates the download/upload labels based on the data provided - by the VPN thread. + Updates the download/upload labels based on the data provided by the + VPN thread. + If data is None, we just will refresh the display based on the previous + data. :param data: a dictionary with the tcp/udp write and read totals. - If data is None, we just will refresh the display based - on the previous data. :type data: dict """ - if data: - upload = float(data[VPNManager.TCPUDP_WRITE_KEY] or "0") - download = float(data[VPNManager.TCPUDP_READ_KEY] or "0") - self._update_traffic_rates(upload, download) + if data is not None: + try: + upload, download = map(float, data) + self._update_traffic_rates(upload, download) + except Exception: + # discard invalid data + return if self.DISPLAY_TRAFFIC_RATES: uprate, downrate = self._get_traffic_rates() @@ -379,39 +381,38 @@ class EIPStatusWidget(QtGui.QWidget): self.ui.btnUpload.setText(upload_str) self.ui.btnDownload.setText(download_str) - def update_vpn_state(self, data): + def update_vpn_state(self, vpn_state): """ SLOT - TRIGGER: VPN.state_changed + TRIGGER: Signaler.eip_state_changed Updates the displayed VPN state based on the data provided by the VPN thread. Emits: - If the status is connected, we emit EIPConnection.qtsigs. + If the vpn_state is connected, we emit EIPConnection.qtsigs. connected_signal """ - status = data[VPNManager.STATUS_STEP_KEY] - self.set_eip_status_icon(status) - if status == "CONNECTED": + self.set_eip_status_icon(vpn_state) + if vpn_state == "CONNECTED": self.ui.eip_bandwidth.show() self.ui.lblEIPStatus.hide() # XXX should be handled by the state machine too. self.eip_connection_connected.emit() - # XXX should lookup status map in EIPConnection - elif status == "AUTH": + # XXX should lookup vpn_state map in EIPConnection + elif vpn_state == "AUTH": self.set_eip_status(self.tr("Authenticating...")) - elif status == "GET_CONFIG": + elif vpn_state == "GET_CONFIG": self.set_eip_status(self.tr("Retrieving configuration...")) - elif status == "WAIT": + elif vpn_state == "WAIT": self.set_eip_status(self.tr("Waiting to start...")) - elif status == "ASSIGN_IP": + elif vpn_state == "ASSIGN_IP": self.set_eip_status(self.tr("Assigning IP")) - elif status == "RECONNECTING": + elif vpn_state == "RECONNECTING": self.set_eip_status(self.tr("Reconnecting...")) - elif status == "ALREADYRUNNING": + elif vpn_state == "ALREADYRUNNING": # Put the following calls in Qt's event queue, otherwise # the UI won't update properly QtCore.QTimer.singleShot( @@ -419,7 +420,7 @@ class EIPStatusWidget(QtGui.QWidget): msg = self.tr("Unable to start VPN, it's already running.") QtCore.QTimer.singleShot(0, partial(self.set_eip_status, msg)) else: - self.set_eip_status(status) + self.set_eip_status(vpn_state) def set_eip_icon(self, icon): """ diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 6eaf2dfb..985ad945 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -33,16 +33,16 @@ from leap.bitmask.config import flags from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.config.providerconfig import ProviderConfig -from leap.bitmask.gui.loggerwindow import LoggerWindow +from leap.bitmask.gui import statemachines from leap.bitmask.gui.advanced_key_management import AdvancedKeyManagement -from leap.bitmask.gui.login import LoginWidget -from leap.bitmask.gui.preferenceswindow import PreferencesWindow from leap.bitmask.gui.eip_preferenceswindow import EIPPreferencesWindow -from leap.bitmask.gui import statemachines from leap.bitmask.gui.eip_status import EIPStatusWidget +from leap.bitmask.gui.loggerwindow import LoggerWindow +from leap.bitmask.gui.login import LoginWidget from leap.bitmask.gui.mail_status import MailStatusWidget -from leap.bitmask.gui.wizard import Wizard +from leap.bitmask.gui.preferenceswindow import PreferencesWindow from leap.bitmask.gui.systray import SysTray +from leap.bitmask.gui.wizard import Wizard from leap.bitmask import provider from leap.bitmask.platform_init import IS_WIN, IS_MAC, IS_LINUX @@ -55,19 +55,7 @@ from leap.bitmask.services import get_service_display_name from leap.bitmask.services.mail import conductor as mail_conductor from leap.bitmask.services import EIP_SERVICE, MX_SERVICE -from leap.bitmask.services.eip import eipconfig -from leap.bitmask.services.eip import get_openvpn_management from leap.bitmask.services.eip.connection import EIPConnection -from leap.bitmask.services.eip.vpnprocess import VPN -from leap.bitmask.services.eip.vpnprocess import OpenVPNAlreadyRunning -from leap.bitmask.services.eip.vpnprocess import AlienOpenVPNAlreadyRunning - -from leap.bitmask.services.eip.vpnlauncher import VPNLauncherException -from leap.bitmask.services.eip.vpnlauncher import OpenVPNNotFoundException -from leap.bitmask.services.eip.linuxvpnlauncher import EIPNoPkexecAvailable -from leap.bitmask.services.eip.linuxvpnlauncher import \ - EIPNoPolkitAuthAgentAvailable -from leap.bitmask.services.eip.darwinvpnlauncher import EIPNoTunKextLoaded from leap.bitmask.services.soledad.soledadbootstrapper import \ SoledadBootstrapper @@ -94,11 +82,6 @@ class MainWindow(QtGui.QMainWindow): """ Main window for login and presenting status updates to the user """ - - # StackedWidget indexes - LOGIN_INDEX = 0 - EIP_STATUS_INDEX = 1 - # Signals eip_needs_login = QtCore.Signal([]) offline_mode_bypass_login = QtCore.Signal([]) @@ -117,9 +100,7 @@ class MainWindow(QtGui.QMainWindow): # We give each service some time to come to a halt before forcing quit SERVICE_STOP_TIMEOUT = 20 - def __init__(self, quit_callback, - bypass_checks=False, - start_hidden=False): + def __init__(self, quit_callback, bypass_checks=False, start_hidden=False): """ Constructor for the client main window @@ -127,9 +108,8 @@ class MainWindow(QtGui.QMainWindow): the application. :type quit_callback: callable - :param bypass_checks: Set to true if the app should bypass - first round of checks for CA - certificates at bootstrap + :param bypass_checks: Set to true if the app should bypass first round + of checks for CA certificates at bootstrap :type bypass_checks: bool :param start_hidden: Set to true if the app should not show the window but just the tray. @@ -188,21 +168,19 @@ class MainWindow(QtGui.QMainWindow): # XXX this should be handled by EIP Conductor self._eip_connection.qtsigs.connecting_signal.connect( - self._start_eip) + self._start_EIP) self._eip_connection.qtsigs.disconnecting_signal.connect( self._stop_eip) self._eip_status.eip_connection_connected.connect( - self._on_eip_connected) + self._on_eip_connection_connected) self._eip_status.eip_connection_connected.connect( self._maybe_run_soledad_setup_checks) self.offline_mode_bypass_login.connect( self._maybe_run_soledad_setup_checks) - self.eip_needs_login.connect( - self._eip_status.disable_eip_start) - self.eip_needs_login.connect( - self._disable_eip_start_action) + self.eip_needs_login.connect(self._eip_status.disable_eip_start) + self.eip_needs_login.connect(self._disable_eip_start_action) # This is loaded only once, there's a bug when doing that more # than once @@ -212,7 +190,6 @@ class MainWindow(QtGui.QMainWindow): # Used for automatic start of EIP self._provisional_provider_config = ProviderConfig() - self._eip_config = eipconfig.EIPConfig() self._already_started_eip = False self._already_started_soledad = False @@ -225,22 +202,6 @@ class MainWindow(QtGui.QMainWindow): self._backend_connected_signals = {} self._backend_connect() - self._vpn = VPN() - - # connect vpn process signals - self._vpn.qtsigs.state_changed.connect( - self._eip_status.update_vpn_state) - self._vpn.qtsigs.status_changed.connect( - self._eip_status.update_vpn_status) - self._vpn.qtsigs.process_finished.connect( - self._eip_finished) - self._vpn.qtsigs.network_unreachable.connect( - self._on_eip_network_unreachable) - self._vpn.qtsigs.process_restart_tls.connect( - self._do_eip_restart) - self._vpn.qtsigs.process_restart_ping.connect( - self._do_eip_restart) - self._soledad_bootstrapper = SoledadBootstrapper() self._soledad_bootstrapper.download_config.connect( self._soledad_intermediate_stage) @@ -419,6 +380,7 @@ class MainWindow(QtGui.QMainWindow): self._connect_and_track(sig.prov_cancelled_setup, self._set_login_cancelled) + # Login signals self._connect_and_track(sig.srp_auth_ok, self._authentication_finished) auth_error = ( @@ -442,16 +404,44 @@ class MainWindow(QtGui.QMainWindow): self._connect_and_track(sig.srp_auth_bad_user_or_password, auth_bad_user_or_password) + # Logout signals self._connect_and_track(sig.srp_logout_ok, self._logout_ok) self._connect_and_track(sig.srp_logout_error, self._logout_error) self._connect_and_track(sig.srp_not_logged_in_error, self._not_logged_in_error) + # EIP bootstrap signals + self._connect_and_track(sig.eip_download_config, + self._eip_intermediate_stage) + self._connect_and_track(sig.eip_download_client_certificate, + self._finish_eip_bootstrap) + # We don't want to disconnect some signals so don't track them: sig.prov_unsupported_client.connect(self._needs_update) sig.prov_unsupported_api.connect(self._incompatible_api) + # EIP start signals + sig.eip_openvpn_already_running.connect( + self._on_eip_openvpn_already_running) + sig.eip_alien_openvpn_already_running.connect( + self._on_eip_alien_openvpn_already_running) + sig.eip_openvpn_not_found_error.connect( + self._on_eip_openvpn_not_found_error) + sig.eip_vpn_launcher_exception.connect( + self._on_eip_vpn_launcher_exception) + sig.eip_no_polkit_agent_error.connect( + self._on_eip_no_polkit_agent_error) + sig.eip_no_pkexec_error.connect(self._on_eip_no_pkexec_error) + sig.eip_no_tun_kext_error.connect(self._on_eip_no_tun_kext_error) + + sig.eip_state_changed.connect(self._eip_status.update_vpn_state) + sig.eip_status_changed.connect(self._eip_status.update_vpn_status) + sig.eip_process_finished.connect(self._eip_finished) + sig.eip_network_unreachable.connect(self._on_eip_network_unreachable) + sig.eip_process_restart_tls.connect(self._do_eip_restart) + sig.eip_process_restart_ping.connect(self._do_eip_restart) + def _disconnect_and_untrack(self): """ Helper to disconnect the tracked signals. @@ -1495,7 +1485,7 @@ class MainWindow(QtGui.QMainWindow): self._action_eip_startstop.setEnabled(True) @QtCore.Slot() - def _on_eip_connected(self): + def _on_eip_connection_connected(self): """ SLOT TRIGGERS: @@ -1585,114 +1575,101 @@ class MainWindow(QtGui.QMainWindow): (default_provider,)) @QtCore.Slot() - def _start_eip(self): + def _start_EIP(self): """ - SLOT - TRIGGERS: - self._eip_connection.qtsigs.do_connect_signal - (via state machine) - or called from _finish_eip_bootstrap - Starts EIP """ - provider_config = self._get_best_provider_config() - provider = provider_config.get_domain() self._eip_status.eip_pre_up() self.user_stopped_eip = False - # until we set an option in the preferences window, - # we'll assume that by default we try to autostart. - # If we switch it off manually, it won't try the next - # time. + # Until we set an option in the preferences window, we'll assume that + # by default we try to autostart. If we switch it off manually, it + # won't try the next time. self._settings.set_autostart_eip(True) - loaded = eipconfig.load_eipconfig_if_needed( - provider_config, self._eip_config, provider) + self._backend.start_eip() - if not loaded: - eip_status_label = self.tr("Could not load {0} configuration.") - eip_status_label = eip_status_label.format(self._eip_name) - self._eip_status.set_eip_status(eip_status_label, error=True) - # signal connection aborted to state machine - qtsigs = self._eip_connection.qtsigs - qtsigs.connection_aborted_signal.emit() - logger.error("Tried to start EIP but cannot find any " - "available provider!") - return + def _on_eip_connection_aborted(self): + """ + SLOT + TRIGGERS: + Signaler.eip_connection_aborted + """ + logger.error("Tried to start EIP but cannot find any " + "available provider!") - try: - # XXX move this to EIPConductor - host, port = get_openvpn_management() - self._vpn.start(eipconfig=self._eip_config, - providerconfig=provider_config, - socket_host=host, - socket_port=port) - self._settings.set_defaultprovider(provider) - - # XXX move to the state machine too - self._eip_status.set_provider(provider) - - # TODO refactor exceptions so they provide translatable - # usef-facing messages. - except EIPNoPolkitAuthAgentAvailable: - self._eip_status.set_eip_status( - # XXX this should change to polkit-kde where - # applicable. - self.tr("We could not find any " - "authentication " - "agent in your system.
" - "Make sure you have " - "polkit-gnome-authentication-" - "agent-1 " - "running and try again."), - error=True) - self._set_eipstatus_off() - except EIPNoTunKextLoaded: - self._eip_status.set_eip_status( - self.tr("{0} cannot be started because " - "the tuntap extension is not installed properly " - "in your system.").format(self._eip_name)) - self._set_eipstatus_off() - except EIPNoPkexecAvailable: - self._eip_status.set_eip_status( - self.tr("We could not find pkexec " - "in your system."), - error=True) - self._set_eipstatus_off() - except OpenVPNNotFoundException: - self._eip_status.set_eip_status( - self.tr("We could not find openvpn binary."), - error=True) - self._set_eipstatus_off() - except OpenVPNAlreadyRunning as e: - self._eip_status.set_eip_status( - self.tr("Another openvpn instance is already running, and " - "could not be stopped."), - error=True) - self._set_eipstatus_off() - except AlienOpenVPNAlreadyRunning as e: - self._eip_status.set_eip_status( - self.tr("Another openvpn instance is already running, and " - "could not be stopped because it was not launched by " - "Bitmask. Please stop it and try again."), - error=True) - self._set_eipstatus_off() - except VPNLauncherException as e: - # XXX We should implement again translatable exceptions so - # we can pass a translatable string to the panel (usermessage attr) - self._eip_status.set_eip_status("%s" % (e,), error=True) - self._set_eipstatus_off() - else: - self._already_started_eip = True + eip_status_label = self.tr("Could not load {0} configuration.") + eip_status_label = eip_status_label.format(self._eip_name) + self._eip_status.set_eip_status(eip_status_label, error=True) + + # signal connection_aborted to state machine: + qtsigs = self._eip_connection.qtsigs + qtsigs.connection_aborted_signal.emit() + + def _on_eip_openvpn_already_running(self): + self._eip_status.set_eip_status( + self.tr("Another openvpn instance is already running, and " + "could not be stopped."), + error=True) + self._set_eipstatus_off() + + def _on_eip_alien_openvpn_already_running(self): + self._eip_status.set_eip_status( + self.tr("Another openvpn instance is already running, and " + "could not be stopped because it was not launched by " + "Bitmask. Please stop it and try again."), + error=True) + self._set_eipstatus_off() + + def _on_eip_openvpn_not_found_error(self): + self._eip_status.set_eip_status( + self.tr("We could not find openvpn binary."), + error=True) + self._set_eipstatus_off() + + def _on_eip_vpn_launcher_exception(self): + # XXX We should implement again translatable exceptions so + # we can pass a translatable string to the panel (usermessage attr) + self._eip_status.set_eip_status("VPN Launcher error.", error=True) + self._set_eipstatus_off() + + def _on_eip_no_polkit_agent_error(self): + self._eip_status.set_eip_status( + # XXX this should change to polkit-kde where + # applicable. + self.tr("We could not find any authentication agent in your " + "system.
Make sure you have" + "polkit-gnome-authentication-agent-1 running and" + "try again."), + error=True) + self._set_eipstatus_off() + + def _on_eip_no_pkexec_error(self): + self._eip_status.set_eip_status( + self.tr("We could not find pkexec in your system."), + error=True) + self._set_eipstatus_off() + + def _on_eip_no_tun_kext_error(self): + self._eip_status.set_eip_status( + self.tr("{0} cannot be started because the tuntap extension is " + "not installed properly in your " + "system.").format(self._eip_name)) + self._set_eipstatus_off() + + def _on_eip_connected(self): + # XXX move to the state machine too + self._eip_status.set_provider(provider) + + self._settings.set_defaultprovider(provider) + self._already_started_eip = True @QtCore.Slot() def _stop_eip(self): """ SLOT TRIGGERS: - self._eip_connection.qtsigs.do_disconnect_signal - (via state machine) - or called from _eip_finished + self._eip_connection.qtsigs.do_disconnect_signal (via state machine) Stops vpn process and makes gui adjustments to reflect the change of state. @@ -1701,7 +1678,7 @@ class MainWindow(QtGui.QMainWindow): :type abnormal: bool """ self.user_stopped_eip = True - self._vpn.terminate() + self._backend.stop_eip() self._set_eipstatus_off(False) self._already_started_eip = False @@ -1742,7 +1719,7 @@ class MainWindow(QtGui.QMainWindow): # for some reason, emitting the do_disconnect/do_connect # signals hangs the UI. self._stop_eip() - QtCore.QTimer.singleShot(2000, self._start_eip) + QtCore.QTimer.singleShot(2000, self._start_EIP) def _set_eipstatus_off(self, error=True): """ @@ -1756,7 +1733,7 @@ class MainWindow(QtGui.QMainWindow): """ SLOT TRIGGERS: - self._vpn.process_finished + Signaler.eip_process_finished Triggered when the EIP/VPN process finishes to set the UI accordingly. @@ -1792,8 +1769,8 @@ class MainWindow(QtGui.QMainWindow): "because you did not authenticate properly.") eip_status_label = eip_status_label.format(self._eip_name) self._eip_status.set_eip_status(eip_status_label, error=True) - self._vpn.killit() signal = qtsigs.connection_aborted_signal + self._backend.terminate_eip() elif exitCode != 0 or not self.user_stopped_eip: eip_status_label = self.tr("{0} finished in an unexpected manner!") @@ -1853,7 +1830,6 @@ class MainWindow(QtGui.QMainWindow): Starts the VPN thread if the eip configuration is properly loaded """ - leap_assert(self._eip_config, "We need an eip config!") passed = data[self._backend.PASSED_KEY] if not passed: @@ -1863,20 +1839,8 @@ class MainWindow(QtGui.QMainWindow): self._already_started_eip = False return - provider_config = self._get_best_provider_config() - domain = provider_config.get_domain() - - # XXX move check to _start_eip ? - loaded = eipconfig.load_eipconfig_if_needed( - provider_config, self._eip_config, domain) - - if loaded: - # DO START EIP Connection! - self._eip_connection.qtsigs.do_connect_signal.emit() - else: - eip_status_label = self.tr("Could not load {0} configuration.") - eip_status_label = eip_status_label.format(self._eip_name) - self._eip_status.set_eip_status(eip_status_label, error=True) + # DO START EIP Connection! + self._eip_connection.qtsigs.do_connect_signal.emit() def _eip_intermediate_stage(self, data): # TODO missing param @@ -2051,7 +2015,7 @@ class MainWindow(QtGui.QMainWindow): logger.error("No instance of soledad was found.") logger.debug('Terminating vpn') - self._vpn.terminate(shutdown=True) + self._backend.stop_eip(shutdown=True) self._cancel_ongoing_defers() @@ -2079,8 +2043,11 @@ class MainWindow(QtGui.QMainWindow): # Set this in case that the app is hidden QtGui.QApplication.setQuitOnLastWindowClosed(True) - self._backend.stop() self._cleanup_and_quit() + + # We queue the call to stop since we need to wait until EIP is stopped. + # Otherwise we may exit leaving an unmanaged openvpn process. + reactor.callLater(0, self._backend.stop) self._really_quit = True if self._wizard: -- cgit v1.2.3 From a4772ef52bb7f258a079aaa88cc41a4f8e086073 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 8 Apr 2014 13:16:56 -0300 Subject: Move gateway selection helpers to backend. --- src/leap/bitmask/gui/eip_preferenceswindow.py | 136 +++++++++++++++++--------- src/leap/bitmask/gui/mainwindow.py | 2 +- 2 files changed, 91 insertions(+), 47 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/eip_preferenceswindow.py b/src/leap/bitmask/gui/eip_preferenceswindow.py index dcaa8b1e..baf17395 100644 --- a/src/leap/bitmask/gui/eip_preferenceswindow.py +++ b/src/leap/bitmask/gui/eip_preferenceswindow.py @@ -18,17 +18,13 @@ """ EIP Preferences window """ -import os import logging from functools import partial from PySide import QtCore, QtGui from leap.bitmask.config.leapsettings import LeapSettings -from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.gui.ui_eippreferences import Ui_EIPPreferences -from leap.bitmask.services.eip.eipconfig import EIPConfig, VPNGatewaySelector -from leap.bitmask.services.eip.eipconfig import get_eipconfig_path logger = logging.getLogger(__name__) @@ -37,17 +33,20 @@ class EIPPreferencesWindow(QtGui.QDialog): """ Window that displays the EIP preferences. """ - def __init__(self, parent, domain): + def __init__(self, parent, domain, backend): """ :param parent: parent object of the EIPPreferencesWindow. :type parent: QWidget :param domain: the selected by default domain. :type domain: unicode + :param backend: Backend being used + :type backend: Backend """ QtGui.QDialog.__init__(self, parent) self.AUTOMATIC_GATEWAY_LABEL = self.tr("Automatic") self._settings = LeapSettings() + self._backend = backend # Load UI self.ui = Ui_EIPPreferences() @@ -61,7 +60,11 @@ class EIPPreferencesWindow(QtGui.QDialog): self.ui.cbGateways.currentIndexChanged[unicode].connect( lambda x: self.ui.lblProvidersGatewayStatus.setVisible(False)) - self._add_configured_providers(domain) + self._selected_domain = domain + self._configured_providers = [] + + self._backend_connect() + self._add_configured_providers() def _set_providers_gateway_status(self, status, success=False, error=False): @@ -85,27 +88,41 @@ class EIPPreferencesWindow(QtGui.QDialog): self.ui.lblProvidersGatewayStatus.setVisible(True) self.ui.lblProvidersGatewayStatus.setText(status) - def _add_configured_providers(self, domain=None): + def _add_configured_providers(self): """ Add the client's configured providers to the providers combo boxes. + """ + providers = self._settings.get_configured_providers() + if not providers: + return - :param domain: the domain to be selected by default. - :type domain: unicode + self._backend.eip_get_initialized_providers(providers) + + def _load_providers_in_combo(self, providers): + """ + SLOT + TRIGGERS: + Signaler.eip_get_initialized_providers + + Add the client's configured providers to the providers combo boxes. + + :param providers: the list of providers to add and whether each one is + initialized or not. + :type providers: list of tuples (str, bool) """ self.ui.cbProvidersGateway.clear() - providers = self._settings.get_configured_providers() if not providers: self.ui.gbGatewaySelector.setEnabled(False) return - for provider in providers: + for provider, is_initialized in providers: label = provider - eip_config_path = get_eipconfig_path(provider, relative=False) - if not os.path.isfile(eip_config_path): - label = provider + self.tr(" (uninitialized)") + if not is_initialized: + label += self.tr(" (uninitialized)") self.ui.cbProvidersGateway.addItem(label, userData=provider) # Select provider by name + domain = self._selected_domain if domain is not None: provider_index = self.ui.cbProvidersGateway.findText( domain, QtCore.Qt.MatchStartsWith) @@ -155,18 +172,24 @@ class EIPPreferencesWindow(QtGui.QDialog): return domain = self.ui.cbProvidersGateway.itemData(domain_idx) + self._selected_domain = domain - if not os.path.isfile(get_eipconfig_path(domain, relative=False)): - self._set_providers_gateway_status( - self.tr("This is an uninitialized provider, " - "please log in first."), - error=True) - self.ui.pbSaveGateway.setEnabled(False) - self.ui.cbGateways.setEnabled(False) - return - else: - self.ui.pbSaveGateway.setEnabled(True) - self.ui.cbGateways.setEnabled(True) + self._backend.eip_get_gateways_list(domain) + + def _update_gateways_list(self, gateways): + """ + SLOT + TRIGGERS: + Signaler.eip_get_gateways_list + + Add the available gateways and select the one stored in configuration + file. + """ + self.ui.pbSaveGateway.setEnabled(True) + self.ui.cbGateways.setEnabled(True) + + self.ui.cbGateways.clear() + self.ui.cbGateways.addItem(self.AUTOMATIC_GATEWAY_LABEL) try: # disconnect previously connected save method @@ -175,31 +198,13 @@ class EIPPreferencesWindow(QtGui.QDialog): pass # Signal was not connected # set the proper connection for the 'save' button + domain = self._selected_domain save_gateway = partial(self._save_selected_gateway, domain) self.ui.pbSaveGateway.clicked.connect(save_gateway) - eip_config = EIPConfig() - provider_config = ProviderConfig.get_provider_config(domain) - - api_version = provider_config.get_api_version() - eip_config.set_api_version(api_version) - eip_loaded = eip_config.load(get_eipconfig_path(domain)) - - if not eip_loaded or provider_config is None: - self._set_providers_gateway_status( - self.tr("There was a problem with configuration files."), - error=True) - return + selected_gateway = self._settings.get_selected_gateway( + self._selected_domain) - gateways = VPNGatewaySelector(eip_config).get_gateways_list() - logger.debug(gateways) - - self.ui.cbGateways.clear() - self.ui.cbGateways.addItem(self.AUTOMATIC_GATEWAY_LABEL) - - # Add the available gateways and - # select the one stored in configuration file. - selected_gateway = self._settings.get_selected_gateway(domain) index = 0 for idx, (gw_name, gw_ip) in enumerate(gateways): gateway = "{0} ({1})".format(gw_name, gw_ip) @@ -208,3 +213,42 @@ class EIPPreferencesWindow(QtGui.QDialog): index = idx + 1 self.ui.cbGateways.setCurrentIndex(index) + + def _gateways_list_error(self): + """ + SLOT + TRIGGERS: + Signaler.eip_get_gateways_list_error + + An error has occurred retrieving the gateway list so we inform the + user. + """ + self._set_providers_gateway_status( + self.tr("There was a problem with configuration files."), + error=True) + self.ui.pbSaveGateway.setEnabled(False) + self.ui.cbGateways.setEnabled(False) + + def _gateways_list_uninitialized(self): + """ + SLOT + TRIGGERS: + Signaler.eip_uninitialized_provider + + The requested provider in not initialized yet, so we give the user an + error msg. + """ + self._set_providers_gateway_status( + self.tr("This is an uninitialized provider, please log in first."), + error=True) + self.ui.pbSaveGateway.setEnabled(False) + self.ui.cbGateways.setEnabled(False) + + def _backend_connect(self): + sig = self._backend.signaler + sig.eip_get_gateways_list.connect(self._update_gateways_list) + sig.eip_get_gateways_list_error.connect(self._gateways_list_error) + sig.eip_uninitialized_provider.connect( + self._gateways_list_uninitialized) + sig.eip_get_initialized_providers.connect( + self._load_providers_in_combo) diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 985ad945..fb37f102 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -632,7 +632,7 @@ class MainWindow(QtGui.QMainWindow): Displays the EIP preferences window. """ domain = self._login_widget.get_selected_provider() - EIPPreferencesWindow(self, domain).show() + EIPPreferencesWindow(self, domain, self._backend).show() # # updates -- cgit v1.2.3 From 37577fdf037f2987ae3eb9493457dd8d4447aaf7 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 14 Apr 2014 15:35:16 -0300 Subject: Use less confusing signal names. Renames: eip_download_config -> eip_config_ready eip_download_client_certificate -> eip_client_certificate_ready --- src/leap/bitmask/gui/mainwindow.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index fb37f102..e5c11eb7 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -412,9 +412,9 @@ class MainWindow(QtGui.QMainWindow): self._not_logged_in_error) # EIP bootstrap signals - self._connect_and_track(sig.eip_download_config, + self._connect_and_track(sig.eip_config_ready, self._eip_intermediate_stage) - self._connect_and_track(sig.eip_download_client_certificate, + self._connect_and_track(sig.eip_client_certificate_ready, self._finish_eip_bootstrap) # We don't want to disconnect some signals so don't track them: @@ -1825,7 +1825,7 @@ class MainWindow(QtGui.QMainWindow): def _finish_eip_bootstrap(self, data): """ SLOT - TRIGGER: self._backend.signaler.eip_download_client_certificate + TRIGGER: self._backend.signaler.eip_client_certificate_ready Starts the VPN thread if the eip configuration is properly loaded @@ -1847,7 +1847,7 @@ class MainWindow(QtGui.QMainWindow): """ SLOT TRIGGERS: - self._backend.signaler.eip_download_config + self._backend.signaler.eip_config_ready If there was a problem, displays it, otherwise it does nothing. This is used for intermediate bootstrapping stages, in case @@ -1942,7 +1942,7 @@ class MainWindow(QtGui.QMainWindow): self._backend.signaler.prov_name_resolution self._backend.signaler.prov_https_connection self._backend.signaler.prov_download_ca_cert - self._backend.signaler.eip_download_config + self._backend.signaler.eip_config_ready If there was a problem, displays it, otherwise it does nothing. This is used for intermediate bootstrapping stages, in case -- cgit v1.2.3 From 6d3a9952cf713dc9bf70710ed04f5db7d7c98869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Tue, 15 Apr 2014 15:59:43 -0300 Subject: Properly stop the Qt app before stopping the reactor --- src/leap/bitmask/gui/twisted_main.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/twisted_main.py b/src/leap/bitmask/gui/twisted_main.py index 1e876c57..ece32ca2 100644 --- a/src/leap/bitmask/gui/twisted_main.py +++ b/src/leap/bitmask/gui/twisted_main.py @@ -19,7 +19,8 @@ Main functions for integration of twisted reactor """ import logging -from twisted.internet import error +from twisted.internet import error, reactor +from PySide import QtCore # Resist the temptation of putting the import reactor here, # it will raise an "reactor already imported" error. @@ -27,6 +28,14 @@ from twisted.internet import error logger = logging.getLogger(__name__) +def stop(): + logger.debug("Really stoping all the things...") + QtCore.QCoreApplication.sendPostedEvents() + QtCore.QCoreApplication.flush() + reactor.stop() + logger.debug("Done stopping all the things.") + + def quit(app): """ Stop the mainloop. @@ -34,9 +43,8 @@ def quit(app): :param app: the main qt QApplication instance. :type app: QtCore.QApplication """ - from twisted.internet import reactor logger.debug('Stopping twisted reactor') try: - reactor.callLater(0, reactor.stop) + reactor.callLater(0, stop) except error.ReactorNotRunning: logger.debug('Reactor not running') -- cgit v1.2.3 From def537bb5a78e046a75a9e13ea75449eec2b34c8 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 16 Apr 2014 14:48:53 -0300 Subject: Use Slot decorator instead of SLOT docstring. --- src/leap/bitmask/gui/eip_preferenceswindow.py | 12 ++--- src/leap/bitmask/gui/eip_status.py | 6 +-- src/leap/bitmask/gui/login.py | 2 +- src/leap/bitmask/gui/mail_status.py | 12 ++--- src/leap/bitmask/gui/mainwindow.py | 75 ++++++++++++--------------- src/leap/bitmask/gui/preferenceswindow.py | 18 +++---- src/leap/bitmask/gui/wizard.py | 30 +++++------ 7 files changed, 72 insertions(+), 83 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/eip_preferenceswindow.py b/src/leap/bitmask/gui/eip_preferenceswindow.py index baf17395..fd2d3c5d 100644 --- a/src/leap/bitmask/gui/eip_preferenceswindow.py +++ b/src/leap/bitmask/gui/eip_preferenceswindow.py @@ -98,9 +98,9 @@ class EIPPreferencesWindow(QtGui.QDialog): self._backend.eip_get_initialized_providers(providers) + @QtCore.Slot(list) def _load_providers_in_combo(self, providers): """ - SLOT TRIGGERS: Signaler.eip_get_initialized_providers @@ -128,9 +128,9 @@ class EIPPreferencesWindow(QtGui.QDialog): domain, QtCore.Qt.MatchStartsWith) self.ui.cbProvidersGateway.setCurrentIndex(provider_index) + @QtCore.Slot(str) def _save_selected_gateway(self, provider): """ - SLOT TRIGGERS: self.ui.pbSaveGateway.clicked @@ -153,9 +153,9 @@ class EIPPreferencesWindow(QtGui.QDialog): "Gateway settings for provider '{0}' saved.").format(provider) self._set_providers_gateway_status(msg, success=True) + @QtCore.Slot(int) def _populate_gateways(self, domain_idx): """ - SLOT TRIGGERS: self.ui.cbProvidersGateway.currentIndexChanged[unicode] @@ -176,9 +176,9 @@ class EIPPreferencesWindow(QtGui.QDialog): self._backend.eip_get_gateways_list(domain) + @QtCore.Slot(list) def _update_gateways_list(self, gateways): """ - SLOT TRIGGERS: Signaler.eip_get_gateways_list @@ -214,9 +214,9 @@ class EIPPreferencesWindow(QtGui.QDialog): self.ui.cbGateways.setCurrentIndex(index) + @QtCore.Slot() def _gateways_list_error(self): """ - SLOT TRIGGERS: Signaler.eip_get_gateways_list_error @@ -229,9 +229,9 @@ class EIPPreferencesWindow(QtGui.QDialog): self.ui.pbSaveGateway.setEnabled(False) self.ui.cbGateways.setEnabled(False) + @QtCore.Slot() def _gateways_list_uninitialized(self): """ - SLOT TRIGGERS: Signaler.eip_uninitialized_provider diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py index f24d87c7..2ced7dc7 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -88,9 +88,9 @@ class EIPStatusWidget(QtGui.QWidget): self.ui.btnUpload.clicked.connect(onclicked) self.ui.btnDownload.clicked.connect(onclicked) + @QtCore.Slot() def _on_VPN_status_clicked(self): """ - SLOT TRIGGER: self.ui.btnUpload.clicked self.ui.btnDownload.clicked @@ -347,9 +347,9 @@ class EIPStatusWidget(QtGui.QWidget): self.tr("Traffic is being routed in the clear")) self.ui.lblEIPStatus.show() + @QtCore.Slot(dict) def update_vpn_status(self, data=None): """ - SLOT TRIGGER: Signaler.eip_status_changed Updates the download/upload labels based on the data provided by the @@ -381,9 +381,9 @@ class EIPStatusWidget(QtGui.QWidget): self.ui.btnUpload.setText(upload_str) self.ui.btnDownload.setText(download_str) + @QtCore.Slot(dict) def update_vpn_state(self, vpn_state): """ - SLOT TRIGGER: Signaler.eip_state_changed Updates the displayed VPN state based on the data provided by diff --git a/src/leap/bitmask/gui/login.py b/src/leap/bitmask/gui/login.py index 4a483c32..4a9626a6 100644 --- a/src/leap/bitmask/gui/login.py +++ b/src/leap/bitmask/gui/login.py @@ -260,8 +260,8 @@ class LoginWidget(QtGui.QWidget): self.ui.lnPassword.setFocus() def _current_provider_changed(self, param): + @QtCore.Slot(int) """ - SLOT TRIGGERS: self.ui.cmbProviders.currentIndexChanged """ if param == (self.ui.cmbProviders.count() - 1): diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py index 44a138e2..059e5d68 100644 --- a/src/leap/bitmask/gui/mail_status.py +++ b/src/leap/bitmask/gui/mail_status.py @@ -184,9 +184,9 @@ class MailStatusWidget(QtGui.QWidget): leap_assert_type(action_mail_status, QtGui.QAction) self._action_mail_status = action_mail_status + @QtCore.Slot() def set_soledad_failed(self): """ - SLOT TRIGGER: SoledadBootstrapper.soledad_failed @@ -195,9 +195,9 @@ class MailStatusWidget(QtGui.QWidget): msg = self.tr("There was an unexpected problem with Soledad.") self._set_mail_status(msg, ready=-1) + @QtCore.Slot() def set_soledad_invalid_auth_token(self): """ - SLOT TRIGGER: SoledadBootstrapper.soledad_invalid_token @@ -250,9 +250,9 @@ class MailStatusWidget(QtGui.QWidget): """ self._soledad_event.emit(req) + @QtCore.Slot(object) def _mail_handle_soledad_events_slot(self, req): """ - SLOT TRIGGER: _mail_handle_soledad_events Reacts to an Soledad event @@ -284,9 +284,9 @@ class MailStatusWidget(QtGui.QWidget): """ self._keymanager_event.emit(req) + @QtCore.Slot(object) def _mail_handle_keymanager_events_slot(self, req): """ - SLOT TRIGGER: _mail_handle_keymanager_events Reacts to an KeyManager event @@ -330,9 +330,9 @@ class MailStatusWidget(QtGui.QWidget): """ self._smtp_event.emit(req) + @QtCore.Slot(object) def _mail_handle_smtp_events_slot(self, req): """ - SLOT TRIGGER: _mail_handle_smtp_events Reacts to an SMTP event @@ -364,9 +364,9 @@ class MailStatusWidget(QtGui.QWidget): """ self._imap_event.emit(req) + @QtCore.Slot(object) def _mail_handle_imap_events_slot(self, req): """ - SLOT TRIGGER: _mail_handle_imap_events Reacts to an IMAP event diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index e5c11eb7..6bdfe7c0 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -457,9 +457,9 @@ class MainWindow(QtGui.QMainWindow): self._backend_connected_signals = {} + @QtCore.Slot() def _rejected_wizard(self): """ - SLOT TRIGGERS: self._wizard.rejected Called if the wizard has been cancelled or closed before @@ -481,9 +481,9 @@ class MainWindow(QtGui.QMainWindow): if self._wizard_firstrun: self._finish_init() + @QtCore.Slot() def _launch_wizard(self): """ - SLOT TRIGGERS: self._login_widget.show_wizard self.ui.action_wizard.triggered @@ -509,9 +509,9 @@ class MainWindow(QtGui.QMainWindow): self._wizard.finished.connect(self._wizard_finished) self._settings.set_skip_first_run(True) + @QtCore.Slot() def _wizard_finished(self): """ - SLOT TRIGGERS self._wizard.finished @@ -534,9 +534,9 @@ class MainWindow(QtGui.QMainWindow): return h return None + @QtCore.Slot() def _show_logger_window(self): """ - SLOT TRIGGERS: self.ui.action_show_logs.triggered @@ -555,9 +555,9 @@ class MainWindow(QtGui.QMainWindow): else: self._logger_window.setVisible(not self._logger_window.isVisible()) + @QtCore.Slot() def _show_AKM(self): """ - SLOT TRIGGERS: self.ui.action_advanced_key_management.triggered @@ -569,9 +569,9 @@ class MainWindow(QtGui.QMainWindow): logged_user, self._keymanager, self._soledad) self._akm.show() + @QtCore.Slot() def _show_preferences(self): """ - SLOT TRIGGERS: self.ui.btnPreferences.clicked (disabled for now) self.ui.action_preferences @@ -586,9 +586,9 @@ class MainWindow(QtGui.QMainWindow): preferences.show() preferences.preferences_saved.connect(self._update_eip_enabled_status) + @QtCore.Slot() def _update_eip_enabled_status(self): """ - SLOT TRIGGER: PreferencesWindow.preferences_saved @@ -622,9 +622,9 @@ class MainWindow(QtGui.QMainWindow): return eip_enabled + @QtCore.Slot() def _show_eip_preferences(self): """ - SLOT TRIGGERS: self.ui.btnEIPPreferences.clicked self.ui.action_eip_preferences (disabled for now) @@ -647,9 +647,9 @@ class MainWindow(QtGui.QMainWindow): """ self.new_updates.emit(req) + @QtCore.Slot(object) def _react_to_new_updates(self, req): """ - SLOT TRIGGER: self._new_updates_available Displays the new updates label and sets the updates_content @@ -659,9 +659,9 @@ class MainWindow(QtGui.QMainWindow): self.ui.btnMore.setVisible(True) self._updates_content = req.content + @QtCore.Slot() def _updates_details(self): """ - SLOT TRIGGER: self.ui.btnMore.clicked Parses and displays the updates details @@ -686,9 +686,9 @@ class MainWindow(QtGui.QMainWindow): self.tr("Updates available"), msg) + @QtCore.Slot() def _finish_init(self): """ - SLOT TRIGGERS: self._wizard.accepted @@ -832,9 +832,9 @@ class MainWindow(QtGui.QMainWindow): # we wait for the systray to be ready reactor.callLater(1, hello) + @QtCore.Slot(int) def _tray_activated(self, reason=None): """ - SLOT TRIGGER: self._systray.activated Displays the context menu from the tray icon @@ -862,9 +862,9 @@ class MainWindow(QtGui.QMainWindow): visible = self.isVisible() and self.isActiveWindow() self._action_visible.setText(get_action(visible)) + @QtCore.Slot() def _toggle_visible(self): """ - SLOT TRIGGER: self._action_visible.triggered Toggles the window visibility @@ -909,9 +909,9 @@ class MainWindow(QtGui.QMainWindow): if state is not None: self.restoreState(state) + @QtCore.Slot() def _about(self): """ - SLOT TRIGGERS: self.ui.action_about_leap.triggered Display the About Bitmask dialog @@ -936,9 +936,9 @@ class MainWindow(QtGui.QMainWindow): "More about LEAP" "") % (VERSION, VERSION_HASH[:10], greet)) + @QtCore.Slot() def _help(self): """ - SLOT TRIGGERS: self.ui.action_help.triggered Display the Bitmask help dialog. @@ -1036,9 +1036,9 @@ class MainWindow(QtGui.QMainWindow): provider = self._login_widget.get_selected_provider() self._backend.setup_provider(provider) + @QtCore.Slot(dict) def _load_provider_config(self, data): """ - SLOT TRIGGER: self._backend.signaler.prov_download_provider_info Once the provider config has been downloaded, this loads the @@ -1064,9 +1064,9 @@ class MainWindow(QtGui.QMainWindow): self.tr("Unable to login: Problem with provider")) self._login_widget.set_enabled(True) + @QtCore.Slot() def _login(self): """ - SLOT TRIGGERS: self._login_widget.login @@ -1092,9 +1092,9 @@ class MainWindow(QtGui.QMainWindow): if self._login_widget.start_login(): self._download_provider_config() + @QtCore.Slot(unicode) def _authentication_error(self, msg): """ - SLOT TRIGGERS: Signaler.srp_auth_error Signaler.srp_auth_server_error @@ -1110,9 +1110,9 @@ class MainWindow(QtGui.QMainWindow): self._login_widget.set_enabled(True) self.ui.action_create_new_account.setEnabled(True) + @QtCore.Slot() def _cancel_login(self): """ - SLOT TRIGGERS: self._login_widget.cancel_login @@ -1134,9 +1134,9 @@ class MainWindow(QtGui.QMainWindow): self._soledad_defer.cancel() self._soledad_defer = None + @QtCore.Slot() def _set_login_cancelled(self): """ - SLOT TRIGGERS: Signaler.prov_cancelled_setup fired by self._backend.cancel_setup_provider() @@ -1147,9 +1147,9 @@ class MainWindow(QtGui.QMainWindow): self._login_widget.set_status(self.tr("Log in cancelled by the user.")) self._login_widget.set_enabled(True) + @QtCore.Slot(dict) def _provider_config_loaded(self, data): """ - SLOT TRIGGER: self._backend.signaler.prov_check_api_certificate Once the provider configuration is loaded, this starts the SRP @@ -1171,9 +1171,9 @@ class MainWindow(QtGui.QMainWindow): logger.error(data[self._backend.ERROR_KEY]) self._login_widget.set_enabled(True) + @QtCore.Slot() def _authentication_finished(self): """ - SLOT TRIGGER: self._srp_auth.authentication_finished Once the user is properly authenticated, try starting the EIP @@ -1285,10 +1285,10 @@ class MainWindow(QtGui.QMainWindow): ################################################################### # Service control methods: soledad + @QtCore.Slot(dict) def _soledad_intermediate_stage(self, data): # TODO missing param docstring """ - SLOT TRIGGERS: self._soledad_bootstrapper.download_config @@ -1320,9 +1320,9 @@ class MainWindow(QtGui.QMainWindow): logger.warning("Max number of soledad initialization " "retries reached.") + @QtCore.Slot(dict) def _soledad_bootstrapped_stage(self, data): """ - SLOT TRIGGERS: self._soledad_bootstrapper.gen_key self._soledad_bootstrapper.local_only_ready @@ -1364,7 +1364,6 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _start_smtp_bootstrapping(self): """ - SLOT TRIGGERS: self.soledad_ready """ @@ -1385,7 +1384,6 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _stop_smtp_service(self): """ - SLOT TRIGGERS: self.logout """ @@ -1398,7 +1396,6 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _start_imap_service(self): """ - SLOT TRIGGERS: self.soledad_ready """ @@ -1428,7 +1425,6 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _fetch_incoming_mail(self): """ - SLOT TRIGGERS: self.mail_client_logged_in """ @@ -1438,7 +1434,6 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _stop_imap_service(self): """ - SLOT TRIGGERS: self.logout """ @@ -1487,7 +1482,6 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _on_eip_connection_connected(self): """ - SLOT TRIGGERS: self._eip_status.eip_connection_connected Emits the EIPConnection.qtsigs.connected_signal @@ -1589,9 +1583,9 @@ class MainWindow(QtGui.QMainWindow): self._backend.start_eip() + @QtCore.Slot() def _on_eip_connection_aborted(self): """ - SLOT TRIGGERS: Signaler.eip_connection_aborted """ @@ -1667,7 +1661,6 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _stop_eip(self): """ - SLOT TRIGGERS: self._eip_connection.qtsigs.do_disconnect_signal (via state machine) @@ -1697,7 +1690,6 @@ class MainWindow(QtGui.QMainWindow): def _on_eip_network_unreachable(self): # XXX Should move to EIP Conductor """ - SLOT TRIGGERS: self._eip_connection.qtsigs.network_unreachable @@ -1711,7 +1703,7 @@ class MainWindow(QtGui.QMainWindow): def _do_eip_restart(self): # XXX Should move to EIP Conductor """ - SLOT + TRIGGER: self._eip_connection.qtsigs.process_restart Restart the connection. @@ -1729,9 +1721,9 @@ class MainWindow(QtGui.QMainWindow): self._eip_status.set_eip_status("", error=error) self._eip_status.set_eip_status_icon("error") + @QtCore.Slot(int) def _eip_finished(self, exitCode): """ - SLOT TRIGGERS: Signaler.eip_process_finished @@ -1822,9 +1814,9 @@ class MainWindow(QtGui.QMainWindow): # eip will not start, so we start soledad anyway self._maybe_run_soledad_setup_checks() + @QtCore.Slot(dict) def _finish_eip_bootstrap(self, data): """ - SLOT TRIGGER: self._backend.signaler.eip_client_certificate_ready Starts the VPN thread if the eip configuration is properly @@ -1842,10 +1834,10 @@ class MainWindow(QtGui.QMainWindow): # DO START EIP Connection! self._eip_connection.qtsigs.do_connect_signal.emit() + @QtCore.Slot(dict) def _eip_intermediate_stage(self, data): # TODO missing param """ - SLOT TRIGGERS: self._backend.signaler.eip_config_ready @@ -1889,7 +1881,6 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _logout(self): """ - SLOT TRIGGER: self._login_widget.logout Starts the logout sequence @@ -1907,9 +1898,9 @@ class MainWindow(QtGui.QMainWindow): self._backend.logout() self.logout.emit() + @QtCore.Slot() def _logout_error(self): """ - SLOT TRIGGER: self._srp_auth.logout_error Inform the user about a logout error. @@ -1919,9 +1910,9 @@ class MainWindow(QtGui.QMainWindow): self._login_widget.set_status( self.tr("Something went wrong with the logout.")) + @QtCore.Slot() def _logout_ok(self): """ - SLOT TRIGGER: self._srp_auth.logout_ok Switches the stackedWidget back to the login stage after @@ -1934,10 +1925,10 @@ class MainWindow(QtGui.QMainWindow): self._login_widget.logged_out() self._mail_status.mail_state_disabled() + @QtCore.Slot(dict) def _intermediate_stage(self, data): # TODO this method name is confusing as hell. """ - SLOT TRIGGERS: self._backend.signaler.prov_name_resolution self._backend.signaler.prov_https_connection @@ -1967,9 +1958,9 @@ class MainWindow(QtGui.QMainWindow): raise_window_ack() self.raise_window.emit() + @QtCore.Slot() def _do_raise_mainwindow(self): """ - SLOT TRIGGERS: self._on_raise_window_event diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py index f6bd1ed3..111ec6d2 100644 --- a/src/leap/bitmask/gui/preferenceswindow.py +++ b/src/leap/bitmask/gui/preferenceswindow.py @@ -89,9 +89,9 @@ class PreferencesWindow(QtGui.QDialog): self._select_provider_by_name(domain) + @QtCore.Slot() def _is_logged_in(self): """ - SLOT TRIGGERS: Signaler.srp_status_logged_in @@ -123,9 +123,9 @@ class PreferencesWindow(QtGui.QDialog): self.ui.gbPasswordChange.setEnabled(pw_enabled) + @QtCore.Slot() def _not_logged_in(self): """ - SLOT TRIGGERS: Signaler.srp_status_not_logged_in @@ -136,9 +136,9 @@ class PreferencesWindow(QtGui.QDialog): self._set_password_change_status(msg) self.ui.gbPasswordChange.setEnabled(False) + @QtCore.Slot() def set_soledad_ready(self): """ - SLOT TRIGGERS: parent.soledad_ready @@ -183,9 +183,9 @@ class PreferencesWindow(QtGui.QDialog): self.ui.leNewPassword2.setEnabled(not disable) self.ui.pbChangePassword.setEnabled(not disable) + @QtCore.Slot() def _change_password(self): """ - SLOT TRIGGERS: self.ui.pbChangePassword.clicked @@ -207,9 +207,9 @@ class PreferencesWindow(QtGui.QDialog): self._set_changing_password(True) self._backend.change_password(current_password, new_password) + @QtCore.Slot() def _change_password_ok(self): """ - SLOT TRIGGERS: self._backend.signaler.srp_password_change_ok @@ -229,9 +229,9 @@ class PreferencesWindow(QtGui.QDialog): self._clear_password_inputs() self._set_changing_password(False) + @QtCore.Slot(unicode) def _change_password_problem(self, msg): """ - SLOT TRIGGERS: self._backend.signaler.srp_password_change_error self._backend.signaler.srp_password_change_badpw @@ -287,9 +287,9 @@ class PreferencesWindow(QtGui.QDialog): provider_index = self.ui.cbProvidersServices.findText(name) self.ui.cbProvidersServices.setCurrentIndex(provider_index) + @QtCore.Slot(str, int) def _service_selection_changed(self, service, state): """ - SLOT TRIGGER: service_checkbox.stateChanged Adds the service to the state if the state is checked, removes it otherwise @@ -309,9 +309,9 @@ class PreferencesWindow(QtGui.QDialog): # We hide the maybe-visible status label after a change self.ui.lblProvidersServicesStatus.setVisible(False) + @QtCore.Slot(str) def _populate_services(self, domain): """ - SLOT TRIGGERS: self.ui.cbProvidersServices.currentIndexChanged[unicode] @@ -368,9 +368,9 @@ class PreferencesWindow(QtGui.QDialog): logger.error("Something went wrong while trying to " "load service %s" % (service,)) + @QtCore.Slot(str) def _save_enabled_services(self, provider): """ - SLOT TRIGGERS: self.ui.pbSaveServices.clicked diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index ebcee400..52cbab48 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -145,7 +145,6 @@ class Wizard(QtGui.QWizard): @QtCore.Slot() def _wizard_finished(self): """ - SLOT TRIGGER: self.finished @@ -210,10 +209,9 @@ class Wizard(QtGui.QWizard): def get_services(self): return self._selected_services - @QtCore.Slot() + @QtCore.Slot(unicode) def _enable_check(self, reset=True): """ - SLOT TRIGGER: self.ui.lnProvider.textChanged @@ -282,9 +280,9 @@ class Wizard(QtGui.QWizard): # register button self.ui.btnRegister.setVisible(visible) + @QtCore.Slot() def _registration_finished(self): """ - SLOT TRIGGERS: self._backend.signaler.srp_registration_finished @@ -308,9 +306,9 @@ class Wizard(QtGui.QWizard): self.page(self.REGISTER_USER_PAGE).set_completed() self.button(QtGui.QWizard.BackButton).setEnabled(False) + @QtCore.Slot() def _registration_failed(self): """ - SLOT TRIGGERS: self._backend.signaler.srp_registration_failed @@ -322,9 +320,9 @@ class Wizard(QtGui.QWizard): self._set_register_status(error_msg, error=True) self.ui.btnRegister.setEnabled(True) + @QtCore.Slot() def _registration_taken(self): """ - SLOT TRIGGERS: self._backend.signaler.srp_registration_taken @@ -368,9 +366,9 @@ class Wizard(QtGui.QWizard): self.ui.lblCheckCaFpr.setPixmap(None) self.ui.lblCheckApiCert.setPixmap(None) + @QtCore.Slot() def _check_provider(self): """ - SLOT TRIGGERS: self.ui.btnCheck.clicked self.ui.lnProvider.returnPressed @@ -403,9 +401,9 @@ class Wizard(QtGui.QWizard): self._provider_select_defer = self._backend.\ setup_provider(self._domain) + @QtCore.Slot(bool) def _skip_provider_checks(self, skip): """ - SLOT Triggered: self.ui.rbExistingProvider.toggled @@ -447,9 +445,9 @@ class Wizard(QtGui.QWizard): label.setPixmap(self.ERROR_ICON) logger.error(error) + @QtCore.Slot(dict) def _name_resolution(self, data): """ - SLOT TRIGGER: self._backend.signaler.prov_name_resolution Sets the status for the name resolution check @@ -466,9 +464,9 @@ class Wizard(QtGui.QWizard): self.ui.btnCheck.setEnabled(not passed) self.ui.lnProvider.setEnabled(not passed) + @QtCore.Slot(dict) def _https_connection(self, data): """ - SLOT TRIGGER: self._backend.signaler.prov_https_connection Sets the status for the https connection check @@ -485,9 +483,9 @@ class Wizard(QtGui.QWizard): self.ui.btnCheck.setEnabled(not passed) self.ui.lnProvider.setEnabled(not passed) + @QtCore.Slot(dict) def _download_provider_info(self, data): """ - SLOT TRIGGER: self._backend.signaler.prov_download_provider_info Sets the status for the provider information download @@ -519,9 +517,9 @@ class Wizard(QtGui.QWizard): else: self.ui.cbProviders.setEnabled(True) + @QtCore.Slot(dict) def _download_ca_cert(self, data): """ - SLOT TRIGGER: self._backend.signaler.prov_download_ca_cert Sets the status for the download of the CA certificate check @@ -531,9 +529,9 @@ class Wizard(QtGui.QWizard): if passed: self.ui.lblCheckCaFpr.setPixmap(self.QUESTION_ICON) + @QtCore.Slot(dict) def _check_ca_fingerprint(self, data): """ - SLOT TRIGGER: self._backend.signaler.prov_check_ca_fingerprint Sets the status for the CA fingerprint check @@ -543,9 +541,9 @@ class Wizard(QtGui.QWizard): if passed: self.ui.lblCheckApiCert.setPixmap(self.QUESTION_ICON) + @QtCore.Slot(dict) def _check_api_certificate(self, data): """ - SLOT TRIGGER: self._backend.signaler.prov_check_api_certificate Sets the status for the API certificate check. Also finishes @@ -556,9 +554,9 @@ class Wizard(QtGui.QWizard): True, self.SETUP_PROVIDER_PAGE) self._provider_setup_ok = True + @QtCore.Slot(str, int) def _service_selection_changed(self, service, state): """ - SLOT TRIGGER: service_checkbox.stateChanged Adds the service to the state if the state is checked, removes it otherwise @@ -604,9 +602,9 @@ class Wizard(QtGui.QWizard): self.tr("Something went wrong while trying to " "load service %s" % (service,))) + @QtCore.Slot(int) def _current_id_changed(self, pageId): """ - SLOT TRIGGER: self.currentIdChanged Prepares the pages when they appear -- cgit v1.2.3 From 5218fda6b524cb8e694113e123e7b0d05b205ddc Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 16 Apr 2014 15:25:41 -0300 Subject: Use consistent wording for triggers documentation. --- src/leap/bitmask/gui/eip_status.py | 11 ++-- src/leap/bitmask/gui/login.py | 3 +- src/leap/bitmask/gui/mail_status.py | 16 +++--- src/leap/bitmask/gui/mainwindow.py | 85 ++++++++++++++++++------------- src/leap/bitmask/gui/preferenceswindow.py | 10 ++-- src/leap/bitmask/gui/wizard.py | 41 +++++++++------ 6 files changed, 100 insertions(+), 66 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py index 2ced7dc7..8f4d64b4 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -91,8 +91,9 @@ class EIPStatusWidget(QtGui.QWidget): @QtCore.Slot() def _on_VPN_status_clicked(self): """ - TRIGGER: self.ui.btnUpload.clicked - self.ui.btnDownload.clicked + TRIGGERS: + self.ui.btnUpload.clicked + self.ui.btnDownload.clicked Toggles between rate and total throughput display for vpn status figures. @@ -350,7 +351,8 @@ class EIPStatusWidget(QtGui.QWidget): @QtCore.Slot(dict) def update_vpn_status(self, data=None): """ - TRIGGER: Signaler.eip_status_changed + TRIGGERS: + Signaler.eip_status_changed Updates the download/upload labels based on the data provided by the VPN thread. @@ -384,7 +386,8 @@ class EIPStatusWidget(QtGui.QWidget): @QtCore.Slot(dict) def update_vpn_state(self, vpn_state): """ - TRIGGER: Signaler.eip_state_changed + TRIGGERS: + Signaler.eip_state_changed Updates the displayed VPN state based on the data provided by the VPN thread. diff --git a/src/leap/bitmask/gui/login.py b/src/leap/bitmask/gui/login.py index 4a9626a6..681c0915 100644 --- a/src/leap/bitmask/gui/login.py +++ b/src/leap/bitmask/gui/login.py @@ -262,7 +262,8 @@ class LoginWidget(QtGui.QWidget): def _current_provider_changed(self, param): @QtCore.Slot(int) """ - TRIGGERS: self.ui.cmbProviders.currentIndexChanged + TRIGGERS: + self.ui.cmbProviders.currentIndexChanged """ if param == (self.ui.cmbProviders.count() - 1): self.show_wizard.emit() diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py index 059e5d68..d3346780 100644 --- a/src/leap/bitmask/gui/mail_status.py +++ b/src/leap/bitmask/gui/mail_status.py @@ -187,7 +187,7 @@ class MailStatusWidget(QtGui.QWidget): @QtCore.Slot() def set_soledad_failed(self): """ - TRIGGER: + TRIGGERS: SoledadBootstrapper.soledad_failed This method is called whenever soledad has a failure. @@ -198,7 +198,7 @@ class MailStatusWidget(QtGui.QWidget): @QtCore.Slot() def set_soledad_invalid_auth_token(self): """ - TRIGGER: + TRIGGERS: SoledadBootstrapper.soledad_invalid_token This method is called when the auth token is invalid @@ -253,7 +253,8 @@ class MailStatusWidget(QtGui.QWidget): @QtCore.Slot(object) def _mail_handle_soledad_events_slot(self, req): """ - TRIGGER: _mail_handle_soledad_events + TRIGGERS: + _mail_handle_soledad_events Reacts to an Soledad event @@ -287,7 +288,8 @@ class MailStatusWidget(QtGui.QWidget): @QtCore.Slot(object) def _mail_handle_keymanager_events_slot(self, req): """ - TRIGGER: _mail_handle_keymanager_events + TRIGGERS: + _mail_handle_keymanager_events Reacts to an KeyManager event @@ -333,7 +335,8 @@ class MailStatusWidget(QtGui.QWidget): @QtCore.Slot(object) def _mail_handle_smtp_events_slot(self, req): """ - TRIGGER: _mail_handle_smtp_events + TRIGGERS: + _mail_handle_smtp_events Reacts to an SMTP event @@ -367,7 +370,8 @@ class MailStatusWidget(QtGui.QWidget): @QtCore.Slot(object) def _mail_handle_imap_events_slot(self, req): """ - TRIGGER: _mail_handle_imap_events + TRIGGERS: + _mail_handle_imap_events Reacts to an IMAP event diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 6bdfe7c0..708ecf7f 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -460,7 +460,8 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _rejected_wizard(self): """ - TRIGGERS: self._wizard.rejected + TRIGGERS: + self._wizard.rejected Called if the wizard has been cancelled or closed before finishing. @@ -485,8 +486,8 @@ class MainWindow(QtGui.QMainWindow): def _launch_wizard(self): """ TRIGGERS: - self._login_widget.show_wizard - self.ui.action_wizard.triggered + self._login_widget.show_wizard + self.ui.action_wizard.triggered Also called in first run. @@ -512,8 +513,8 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _wizard_finished(self): """ - TRIGGERS - self._wizard.finished + TRIGGERS: + self._wizard.finished Called when the wizard has finished. """ @@ -538,7 +539,7 @@ class MainWindow(QtGui.QMainWindow): def _show_logger_window(self): """ TRIGGERS: - self.ui.action_show_logs.triggered + self.ui.action_show_logs.triggered Displays the window with the history of messages logged until now and displays the new ones on arrival. @@ -573,8 +574,8 @@ class MainWindow(QtGui.QMainWindow): def _show_preferences(self): """ TRIGGERS: - self.ui.btnPreferences.clicked (disabled for now) - self.ui.action_preferences + self.ui.btnPreferences.clicked (disabled for now) + self.ui.action_preferences Displays the preferences window. """ @@ -626,8 +627,8 @@ class MainWindow(QtGui.QMainWindow): def _show_eip_preferences(self): """ TRIGGERS: - self.ui.btnEIPPreferences.clicked - self.ui.action_eip_preferences (disabled for now) + self.ui.btnEIPPreferences.clicked + self.ui.action_eip_preferences (disabled for now) Displays the EIP preferences window. """ @@ -650,7 +651,8 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot(object) def _react_to_new_updates(self, req): """ - TRIGGER: self._new_updates_available + TRIGGERS: + self._new_updates_available Displays the new updates label and sets the updates_content """ @@ -662,7 +664,8 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _updates_details(self): """ - TRIGGER: self.ui.btnMore.clicked + TRIGGERS: + self.ui.btnMore.clicked Parses and displays the updates details """ @@ -690,7 +693,7 @@ class MainWindow(QtGui.QMainWindow): def _finish_init(self): """ TRIGGERS: - self._wizard.accepted + self._wizard.accepted Also called at the end of the constructor if not first run. @@ -835,7 +838,8 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot(int) def _tray_activated(self, reason=None): """ - TRIGGER: self._systray.activated + TRIGGERS: + self._systray.activated Displays the context menu from the tray icon """ @@ -865,7 +869,8 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _toggle_visible(self): """ - TRIGGER: self._action_visible.triggered + TRIGGERS: + self._action_visible.triggered Toggles the window visibility """ @@ -912,7 +917,8 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _about(self): """ - TRIGGERS: self.ui.action_about_leap.triggered + TRIGGERS: + self.ui.action_about_leap.triggered Display the About Bitmask dialog """ @@ -939,7 +945,8 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _help(self): """ - TRIGGERS: self.ui.action_help.triggered + TRIGGERS: + self.ui.action_help.triggered Display the Bitmask help dialog. """ @@ -1039,7 +1046,8 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot(dict) def _load_provider_config(self, data): """ - TRIGGER: self._backend.signaler.prov_download_provider_info + TRIGGERS: + self._backend.signaler.prov_download_provider_info Once the provider config has been downloaded, this loads the self._provider_config instance with it and starts the second @@ -1068,7 +1076,7 @@ class MainWindow(QtGui.QMainWindow): def _login(self): """ TRIGGERS: - self._login_widget.login + self._login_widget.login Starts the login sequence. Which involves bootstrapping the selected provider if the selection is valid (not empty), then @@ -1114,7 +1122,7 @@ class MainWindow(QtGui.QMainWindow): def _cancel_login(self): """ TRIGGERS: - self._login_widget.cancel_login + self._login_widget.cancel_login Stops the login sequence. """ @@ -1150,7 +1158,8 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot(dict) def _provider_config_loaded(self, data): """ - TRIGGER: self._backend.signaler.prov_check_api_certificate + TRIGGERS: + self._backend.signaler.prov_check_api_certificate Once the provider configuration is loaded, this starts the SRP authentication @@ -1174,7 +1183,8 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _authentication_finished(self): """ - TRIGGER: self._srp_auth.authentication_finished + TRIGGERS: + self._srp_auth.authentication_finished Once the user is properly authenticated, try starting the EIP service @@ -1290,7 +1300,7 @@ class MainWindow(QtGui.QMainWindow): # TODO missing param docstring """ TRIGGERS: - self._soledad_bootstrapper.download_config + self._soledad_bootstrapper.download_config If there was a problem, displays it, otherwise it does nothing. This is used for intermediate bootstrapping stages, in case @@ -1324,8 +1334,8 @@ class MainWindow(QtGui.QMainWindow): def _soledad_bootstrapped_stage(self, data): """ TRIGGERS: - self._soledad_bootstrapper.gen_key - self._soledad_bootstrapper.local_only_ready + self._soledad_bootstrapper.gen_key + self._soledad_bootstrapper.local_only_ready If there was a problem, displays it, otherwise it does nothing. This is used for intermediate bootstrapping stages, in case @@ -1484,6 +1494,7 @@ class MainWindow(QtGui.QMainWindow): """ TRIGGERS: self._eip_status.eip_connection_connected + Emits the EIPConnection.qtsigs.connected_signal This is a little workaround for connecting the vpn-connected @@ -1703,7 +1714,7 @@ class MainWindow(QtGui.QMainWindow): def _do_eip_restart(self): # XXX Should move to EIP Conductor """ - TRIGGER: + TRIGGERS: self._eip_connection.qtsigs.process_restart Restart the connection. @@ -1817,7 +1828,8 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot(dict) def _finish_eip_bootstrap(self, data): """ - TRIGGER: self._backend.signaler.eip_client_certificate_ready + TRIGGERS: + self._backend.signaler.eip_client_certificate_ready Starts the VPN thread if the eip configuration is properly loaded @@ -1839,7 +1851,7 @@ class MainWindow(QtGui.QMainWindow): # TODO missing param """ TRIGGERS: - self._backend.signaler.eip_config_ready + self._backend.signaler.eip_config_ready If there was a problem, displays it, otherwise it does nothing. This is used for intermediate bootstrapping stages, in case @@ -1881,7 +1893,8 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _logout(self): """ - TRIGGER: self._login_widget.logout + TRIGGERS: + self._login_widget.logout Starts the logout sequence """ @@ -1901,7 +1914,8 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _logout_error(self): """ - TRIGGER: self._srp_auth.logout_error + TRIGGER: + self._srp_auth.logout_error Inform the user about a logout error. """ @@ -1913,7 +1927,8 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _logout_ok(self): """ - TRIGGER: self._srp_auth.logout_ok + TRIGGER: + self._srp_auth.logout_ok Switches the stackedWidget back to the login stage after logging out @@ -1930,10 +1945,10 @@ class MainWindow(QtGui.QMainWindow): # TODO this method name is confusing as hell. """ TRIGGERS: - self._backend.signaler.prov_name_resolution - self._backend.signaler.prov_https_connection - self._backend.signaler.prov_download_ca_cert - self._backend.signaler.eip_config_ready + self._backend.signaler.prov_name_resolution + self._backend.signaler.prov_https_connection + self._backend.signaler.prov_download_ca_cert + self._backend.signaler.eip_config_ready If there was a problem, displays it, otherwise it does nothing. This is used for intermediate bootstrapping stages, in case diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py index 111ec6d2..014a0a4f 100644 --- a/src/leap/bitmask/gui/preferenceswindow.py +++ b/src/leap/bitmask/gui/preferenceswindow.py @@ -211,7 +211,7 @@ class PreferencesWindow(QtGui.QDialog): def _change_password_ok(self): """ TRIGGERS: - self._backend.signaler.srp_password_change_ok + self._backend.signaler.srp_password_change_ok Callback used to display a successfully changed password. """ @@ -233,8 +233,8 @@ class PreferencesWindow(QtGui.QDialog): def _change_password_problem(self, msg): """ TRIGGERS: - self._backend.signaler.srp_password_change_error - self._backend.signaler.srp_password_change_badpw + self._backend.signaler.srp_password_change_error + self._backend.signaler.srp_password_change_badpw Callback used to display an error on changing password. @@ -290,7 +290,9 @@ class PreferencesWindow(QtGui.QDialog): @QtCore.Slot(str, int) def _service_selection_changed(self, service, state): """ - TRIGGER: service_checkbox.stateChanged + TRIGGERS: + service_checkbox.stateChanged + Adds the service to the state if the state is checked, removes it otherwise diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index 52cbab48..957a67e0 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -145,7 +145,7 @@ class Wizard(QtGui.QWizard): @QtCore.Slot() def _wizard_finished(self): """ - TRIGGER: + TRIGGERS: self.finished This method is called when the wizard is accepted or rejected. @@ -212,7 +212,7 @@ class Wizard(QtGui.QWizard): @QtCore.Slot(unicode) def _enable_check(self, reset=True): """ - TRIGGER: + TRIGGERS: self.ui.lnProvider.textChanged Enables/disables the 'check' button in the SELECT_PROVIDER_PAGE @@ -284,7 +284,7 @@ class Wizard(QtGui.QWizard): def _registration_finished(self): """ TRIGGERS: - self._backend.signaler.srp_registration_finished + self._backend.signaler.srp_registration_finished The registration has finished successfully, so we do some final steps. """ @@ -310,7 +310,7 @@ class Wizard(QtGui.QWizard): def _registration_failed(self): """ TRIGGERS: - self._backend.signaler.srp_registration_failed + self._backend.signaler.srp_registration_failed The registration has failed, so we report the problem. """ @@ -324,7 +324,7 @@ class Wizard(QtGui.QWizard): def _registration_taken(self): """ TRIGGERS: - self._backend.signaler.srp_registration_taken + self._backend.signaler.srp_registration_taken The requested username is taken, warn the user about that. """ @@ -370,8 +370,8 @@ class Wizard(QtGui.QWizard): def _check_provider(self): """ TRIGGERS: - self.ui.btnCheck.clicked - self.ui.lnProvider.returnPressed + self.ui.btnCheck.clicked + self.ui.lnProvider.returnPressed Starts the checks for a given provider """ @@ -404,7 +404,7 @@ class Wizard(QtGui.QWizard): @QtCore.Slot(bool) def _skip_provider_checks(self, skip): """ - Triggered: + TRIGGERS: self.ui.rbExistingProvider.toggled Allows the user to move to the next page without make any checks, @@ -448,7 +448,8 @@ class Wizard(QtGui.QWizard): @QtCore.Slot(dict) def _name_resolution(self, data): """ - TRIGGER: self._backend.signaler.prov_name_resolution + TRIGGERS: + self._backend.signaler.prov_name_resolution Sets the status for the name resolution check """ @@ -467,7 +468,8 @@ class Wizard(QtGui.QWizard): @QtCore.Slot(dict) def _https_connection(self, data): """ - TRIGGER: self._backend.signaler.prov_https_connection + TRIGGERS: + self._backend.signaler.prov_https_connection Sets the status for the https connection check """ @@ -486,7 +488,8 @@ class Wizard(QtGui.QWizard): @QtCore.Slot(dict) def _download_provider_info(self, data): """ - TRIGGER: self._backend.signaler.prov_download_provider_info + TRIGGERS: + self._backend.signaler.prov_download_provider_info Sets the status for the provider information download check. Since this check is the last of this set, it also @@ -520,7 +523,8 @@ class Wizard(QtGui.QWizard): @QtCore.Slot(dict) def _download_ca_cert(self, data): """ - TRIGGER: self._backend.signaler.prov_download_ca_cert + TRIGGERS: + self._backend.signaler.prov_download_ca_cert Sets the status for the download of the CA certificate check """ @@ -532,7 +536,8 @@ class Wizard(QtGui.QWizard): @QtCore.Slot(dict) def _check_ca_fingerprint(self, data): """ - TRIGGER: self._backend.signaler.prov_check_ca_fingerprint + TRIGGERS: + self._backend.signaler.prov_check_ca_fingerprint Sets the status for the CA fingerprint check """ @@ -544,7 +549,8 @@ class Wizard(QtGui.QWizard): @QtCore.Slot(dict) def _check_api_certificate(self, data): """ - TRIGGER: self._backend.signaler.prov_check_api_certificate + TRIGGERS: + self._backend.signaler.prov_check_api_certificate Sets the status for the API certificate check. Also finishes the provider bootstrapper thread since it's not needed anymore @@ -557,7 +563,9 @@ class Wizard(QtGui.QWizard): @QtCore.Slot(str, int) def _service_selection_changed(self, service, state): """ - TRIGGER: service_checkbox.stateChanged + TRIGGERS: + service_checkbox.stateChanged + Adds the service to the state if the state is checked, removes it otherwise @@ -605,7 +613,8 @@ class Wizard(QtGui.QWizard): @QtCore.Slot(int) def _current_id_changed(self, pageId): """ - TRIGGER: self.currentIdChanged + TRIGGERS: + self.currentIdChanged Prepares the pages when they appear """ -- cgit v1.2.3 From fa81e2f08335334f8def3a9275c00ba133e5f714 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 17 Apr 2014 11:45:03 -0300 Subject: Improve parameters docstrings. Also rename a parameter named 'param' to a more meaningful 'idx'. --- src/leap/bitmask/gui/eip_preferenceswindow.py | 3 +++ src/leap/bitmask/gui/eip_status.py | 3 +++ src/leap/bitmask/gui/login.py | 9 ++++++--- src/leap/bitmask/gui/mainwindow.py | 8 +++++++- src/leap/bitmask/gui/wizard.py | 8 ++++++++ 5 files changed, 27 insertions(+), 4 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/eip_preferenceswindow.py b/src/leap/bitmask/gui/eip_preferenceswindow.py index fd2d3c5d..530cd38d 100644 --- a/src/leap/bitmask/gui/eip_preferenceswindow.py +++ b/src/leap/bitmask/gui/eip_preferenceswindow.py @@ -182,6 +182,9 @@ class EIPPreferencesWindow(QtGui.QDialog): TRIGGERS: Signaler.eip_get_gateways_list + :param gateways: a list of gateways + :type gateways: list of unicode + Add the available gateways and select the one stored in configuration file. """ diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py index 8f4d64b4..0d75b8e5 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -392,6 +392,9 @@ class EIPStatusWidget(QtGui.QWidget): Updates the displayed VPN state based on the data provided by the VPN thread. + :param vpn_state: the state of the VPN + :type vpn_state: dict + Emits: If the vpn_state is connected, we emit EIPConnection.qtsigs. connected_signal diff --git a/src/leap/bitmask/gui/login.py b/src/leap/bitmask/gui/login.py index 681c0915..ac7ad878 100644 --- a/src/leap/bitmask/gui/login.py +++ b/src/leap/bitmask/gui/login.py @@ -259,13 +259,16 @@ class LoginWidget(QtGui.QWidget): """ self.ui.lnPassword.setFocus() - def _current_provider_changed(self, param): @QtCore.Slot(int) + def _current_provider_changed(self, idx): """ TRIGGERS: self.ui.cmbProviders.currentIndexChanged + + :param idx: the index of the new selected item + :type idx: int """ - if param == (self.ui.cmbProviders.count() - 1): + if idx == (self.ui.cmbProviders.count() - 1): self.show_wizard.emit() # Leave the previously selected provider in the combobox prev_provider = 0 @@ -275,7 +278,7 @@ class LoginWidget(QtGui.QWidget): self.ui.cmbProviders.setCurrentIndex(prev_provider) self.ui.cmbProviders.blockSignals(False) else: - self._selected_provider_index = param + self._selected_provider_index = idx def start_login(self): """ diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 708ecf7f..b911e5d8 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -652,9 +652,12 @@ class MainWindow(QtGui.QMainWindow): def _react_to_new_updates(self, req): """ TRIGGERS: - self._new_updates_available + self.new_updates Displays the new updates label and sets the updates_content + + :param req: Request type + :type req: leap.common.events.events_pb2.SignalRequest """ self.moveToThread(QtCore.QCoreApplication.instance().thread()) self.ui.lblNewUpdates.setVisible(True) @@ -841,6 +844,9 @@ class MainWindow(QtGui.QMainWindow): TRIGGERS: self._systray.activated + :param reason: the reason why the tray got activated. + :type reason: int + Displays the context menu from the tray icon """ self._update_hideshow_menu() diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index 957a67e0..cc8c2624 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -217,6 +217,11 @@ class Wizard(QtGui.QWizard): Enables/disables the 'check' button in the SELECT_PROVIDER_PAGE depending on the lnProvider content. + + :param reset: this contains the text of the line edit, and when is + called directly defines whether we want to reset the + checks. + :type reset: unicode or bool """ enabled = len(self.ui.lnProvider.text()) != 0 enabled = enabled or self.ui.rbExistingProvider.isChecked() @@ -617,6 +622,9 @@ class Wizard(QtGui.QWizard): self.currentIdChanged Prepares the pages when they appear + + :param pageId: the new current page id. + :type pageId: int """ if pageId == self.SELECT_PROVIDER_PAGE: self._clear_register_widgets() -- cgit v1.2.3 From f4e3286274333af361eb4075682648f07e4ad24b Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 17 Apr 2014 14:52:18 -0300 Subject: Show the tray message only if we started hidden. --- src/leap/bitmask/gui/mainwindow.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index b911e5d8..2d854bc3 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -832,11 +832,12 @@ class MainWindow(QtGui.QMainWindow): self._mail_status.set_systray(self._systray) self._eip_status.set_systray(self._systray) - hello = lambda: self._systray.showMessage( - self.tr('Hello!'), - self.tr('Bitmask has started in the tray.')) - # we wait for the systray to be ready - reactor.callLater(1, hello) + if self._start_hidden: + hello = lambda: self._systray.showMessage( + self.tr('Hello!'), + self.tr('Bitmask has started in the tray.')) + # we wait for the systray to be ready + reactor.callLater(1, hello) @QtCore.Slot(int) def _tray_activated(self, reason=None): -- cgit v1.2.3 From f30ccf9e91935b9b29092ad3518a5bb5fa7ee642 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 21 Apr 2014 17:53:00 -0300 Subject: Show the user if there was an error during provider setup. Also: - add slot decorator where needed - remove incorrect trigger docstring - factor out setting the same message into an existing helper [Closes #5424] --- src/leap/bitmask/gui/mainwindow.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index b911e5d8..fc1ab10a 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1068,8 +1068,9 @@ class MainWindow(QtGui.QMainWindow): self._backend.provider_bootstrap(selected_provider) else: logger.error(data[self._backend.ERROR_KEY]) - self._login_widget.set_enabled(True) + self._login_problem_provider() + @QtCore.Slot() def _login_problem_provider(self): """ Warns the user about a problem with the provider during login. @@ -1181,10 +1182,8 @@ class MainWindow(QtGui.QMainWindow): domain = self._provider_config.get_domain() self._backend.login(domain, username, password) else: - self._login_widget.set_status( - "Unable to login: Problem with provider") logger.error(data[self._backend.ERROR_KEY]) - self._login_widget.set_enabled(True) + self._login_problem_provider() @QtCore.Slot() def _authentication_finished(self): @@ -1803,8 +1802,6 @@ class MainWindow(QtGui.QMainWindow): Start the EIP bootstrapping sequence if the client is configured to do so. """ - provider_config = self._get_best_provider_config() - if self._provides_eip_and_enabled() and not self._already_started_eip: # XXX this should be handled by the state machine. self._eip_status.set_eip_status( @@ -1954,7 +1951,6 @@ class MainWindow(QtGui.QMainWindow): self._backend.signaler.prov_name_resolution self._backend.signaler.prov_https_connection self._backend.signaler.prov_download_ca_cert - self._backend.signaler.eip_config_ready If there was a problem, displays it, otherwise it does nothing. This is used for intermediate bootstrapping stages, in case @@ -1962,10 +1958,8 @@ class MainWindow(QtGui.QMainWindow): """ passed = data[self._backend.PASSED_KEY] if not passed: - msg = self.tr("Unable to connect: Problem with provider") - self._login_widget.set_status(msg) - self._login_widget.set_enabled(True) logger.error(data[self._backend.ERROR_KEY]) + self._login_problem_provider() # # window handling methods -- cgit v1.2.3 From b0dc286e5381d3328f3408b97541818e47865ad5 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 22 Apr 2014 13:33:37 -0300 Subject: Use QDialog as base for AKM. This allows the akm to be treated as a preferences dialog instead of an extra 'main window'. --- src/leap/bitmask/gui/advanced_key_management.py | 8 +++++--- src/leap/bitmask/gui/mainwindow.py | 6 +++--- src/leap/bitmask/gui/ui/advanced_key_management.ui | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/advanced_key_management.py b/src/leap/bitmask/gui/advanced_key_management.py index cbc8c3e3..95e5eedf 100644 --- a/src/leap/bitmask/gui/advanced_key_management.py +++ b/src/leap/bitmask/gui/advanced_key_management.py @@ -30,12 +30,14 @@ from ui_advanced_key_management import Ui_AdvancedKeyManagement logger = logging.getLogger(__name__) -class AdvancedKeyManagement(QtGui.QWidget): +class AdvancedKeyManagement(QtGui.QDialog): """ Advanced Key Management """ - def __init__(self, user, keymanager, soledad): + def __init__(self, parent, user, keymanager, soledad): """ + :param parent: parent object of AdvancedKeyManagement. + :parent type: QWidget :param user: the current logged in user. :type user: unicode :param keymanager: the existing keymanager instance @@ -43,7 +45,7 @@ class AdvancedKeyManagement(QtGui.QWidget): :param soledad: a loaded instance of Soledad :type soledad: Soledad """ - QtGui.QWidget.__init__(self) + QtGui.QDialog.__init__(self, parent) self.ui = Ui_AdvancedKeyManagement() self.ui.setupUi(self) diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index b911e5d8..3296bb04 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -566,9 +566,9 @@ class MainWindow(QtGui.QMainWindow): """ domain = self._login_widget.get_selected_provider() logged_user = "{0}@{1}".format(self._logged_user, domain) - self._akm = AdvancedKeyManagement( - logged_user, self._keymanager, self._soledad) - self._akm.show() + akm = AdvancedKeyManagement( + self, logged_user, self._keymanager, self._soledad) + akm.show() @QtCore.Slot() def _show_preferences(self): diff --git a/src/leap/bitmask/gui/ui/advanced_key_management.ui b/src/leap/bitmask/gui/ui/advanced_key_management.ui index 1112670f..3b567347 100644 --- a/src/leap/bitmask/gui/ui/advanced_key_management.ui +++ b/src/leap/bitmask/gui/ui/advanced_key_management.ui @@ -1,7 +1,7 @@ AdvancedKeyManagement - + 0 -- cgit v1.2.3 From b84bcd9e5282dffe7d1208b84f0ab2e31a28cae5 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 22 Apr 2014 13:59:30 -0300 Subject: Show specific note for providers not supporting mx. Also add a helper method to disable the ui and show a message. --- src/leap/bitmask/gui/advanced_key_management.py | 32 ++++++++++++++++++++----- src/leap/bitmask/gui/mainwindow.py | 8 ++++++- 2 files changed, 33 insertions(+), 7 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/advanced_key_management.py b/src/leap/bitmask/gui/advanced_key_management.py index 95e5eedf..be6b4410 100644 --- a/src/leap/bitmask/gui/advanced_key_management.py +++ b/src/leap/bitmask/gui/advanced_key_management.py @@ -34,10 +34,13 @@ class AdvancedKeyManagement(QtGui.QDialog): """ Advanced Key Management """ - def __init__(self, parent, user, keymanager, soledad): + def __init__(self, parent, has_mx, user, keymanager, soledad): """ :param parent: parent object of AdvancedKeyManagement. :parent type: QWidget + :param has_mx: defines whether the current provider provides email or + not. + :type has_mx: bool :param user: the current logged in user. :type user: unicode :param keymanager: the existing keymanager instance @@ -53,14 +56,19 @@ class AdvancedKeyManagement(QtGui.QDialog): # XXX: Temporarily disable the key import. self.ui.pbImportKeys.setVisible(False) + # if Soledad is not started yet + if not has_mx: + msg = self.tr("The provider that you are using " + "does not support {0}.") + msg = msg.format(get_service_display_name(MX_SERVICE)) + self._disable_ui(msg) + return + # if Soledad is not started yet if sameProxiedObjects(soledad, None): - self.ui.gbMyKeyPair.setEnabled(False) - self.ui.gbStoredPublicKeys.setEnabled(False) - msg = self.tr("NOTE: " - "To use this, you need to enable/start {0}.") + msg = self.tr("To use this, you need to enable/start {0}.") msg = msg.format(get_service_display_name(MX_SERVICE)) - self.ui.lblStatus.setText(msg) + self._disable_ui(msg) return # XXX: since import is disabled this is no longer a dangerous feature. # else: @@ -92,6 +100,18 @@ class AdvancedKeyManagement(QtGui.QDialog): self._list_keys() + def _disable_ui(self, msg): + """ + Disable the UI and set a note in the status bar. + + :param msg: note to display in the status bar. + :type msg: unicode + """ + self.ui.gbMyKeyPair.setEnabled(False) + self.ui.gbStoredPublicKeys.setEnabled(False) + msg = self.tr("NOTE: ") + msg + self.ui.lblStatus.setText(msg) + def _import_keys(self): """ Imports the user's key pair. diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 3296bb04..b0369e5b 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -566,8 +566,14 @@ class MainWindow(QtGui.QMainWindow): """ domain = self._login_widget.get_selected_provider() logged_user = "{0}@{1}".format(self._logged_user, domain) + + has_mx = True + if self._logged_user is not None: + provider_config = self._get_best_provider_config() + has_mx = provider_config.provides_mx() + akm = AdvancedKeyManagement( - self, logged_user, self._keymanager, self._soledad) + self, has_mx, logged_user, self._keymanager, self._soledad) akm.show() @QtCore.Slot() -- cgit v1.2.3 From 3fe586a7aad16de5401090d3d1725e58fca0ed3e Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 22 Apr 2014 16:49:29 -0300 Subject: Add checks to avoid errors when ctrl-c in wizard. Check that systray exists, not the case during first run. Cleanup reactor stop code. Closes #5559. --- src/leap/bitmask/gui/mainwindow.py | 7 ++++--- src/leap/bitmask/gui/twisted_main.py | 15 ++++++--------- 2 files changed, 10 insertions(+), 12 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 907d4ceb..e4443434 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -2046,9 +2046,10 @@ class MainWindow(QtGui.QMainWindow): # first thing to do quitting, hide the mainwindow and show tooltip. self.hide() - self._systray.showMessage( - self.tr('Quitting...'), - self.tr('The app is quitting, please wait.')) + if self._systray is not None: + self._systray.showMessage( + self.tr('Quitting...'), + self.tr('The app is quitting, please wait.')) # explicitly process events to display tooltip immediately QtCore.QCoreApplication.processEvents() diff --git a/src/leap/bitmask/gui/twisted_main.py b/src/leap/bitmask/gui/twisted_main.py index ece32ca2..f39d0bbe 100644 --- a/src/leap/bitmask/gui/twisted_main.py +++ b/src/leap/bitmask/gui/twisted_main.py @@ -22,9 +22,6 @@ import logging from twisted.internet import error, reactor from PySide import QtCore -# Resist the temptation of putting the import reactor here, -# it will raise an "reactor already imported" error. - logger = logging.getLogger(__name__) @@ -32,7 +29,11 @@ def stop(): logger.debug("Really stoping all the things...") QtCore.QCoreApplication.sendPostedEvents() QtCore.QCoreApplication.flush() - reactor.stop() + try: + reactor.stop() + logger.debug('Twisted reactor stopped') + except error.ReactorNotRunning: + logger.debug('Twisted reactor not running') logger.debug("Done stopping all the things.") @@ -43,8 +44,4 @@ def quit(app): :param app: the main qt QApplication instance. :type app: QtCore.QApplication """ - logger.debug('Stopping twisted reactor') - try: - reactor.callLater(0, stop) - except error.ReactorNotRunning: - logger.debug('Reactor not running') + reactor.callLater(0, stop) -- cgit v1.2.3 From bcf3c5d5928585e06c058bf1754100d078919bbd Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 22 Apr 2014 17:06:46 -0300 Subject: Add flag to skip provider checks in wizard. --- src/leap/bitmask/gui/wizard.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index cc8c2624..020a58e2 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -24,6 +24,7 @@ from functools import partial from PySide import QtCore, QtGui +from leap.bitmask.config import flags from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.provider import get_provider_path @@ -361,7 +362,8 @@ class Wizard(QtGui.QWizard): self.ui.lblProviderSelectStatus.setText("") self._domain = None self.button(QtGui.QWizard.NextButton).setEnabled(False) - self.page(self.SELECT_PROVIDER_PAGE).set_completed(False) + self.page(self.SELECT_PROVIDER_PAGE).set_completed( + flags.SKIP_WIZARD_CHECKS) def _reset_provider_setup(self): """ -- cgit v1.2.3 From 58a1381764b16ebe01639020c73d4c96632cadfa Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 23 Apr 2014 12:54:29 -0300 Subject: Swap upload/download data strings. Closes #5563. --- src/leap/bitmask/gui/eip_status.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py index 0d75b8e5..bc31b91d 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -359,8 +359,8 @@ class EIPStatusWidget(QtGui.QWidget): If data is None, we just will refresh the display based on the previous data. - :param data: a dictionary with the tcp/udp write and read totals. - :type data: dict + :param data: a tuple with download/upload totals (download, upload). + :type data: tuple """ if data is not None: try: -- cgit v1.2.3 From 48406e9fb4a789eb6b4f14b626332e89b53d7312 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 23 Apr 2014 16:08:02 -0300 Subject: Get password change working again. Closes #5540. - get the username from the login widget instead of the now not available srp_auth. - use lambda instead of partial to parametrize the error messages. --- src/leap/bitmask/gui/mainwindow.py | 4 +++- src/leap/bitmask/gui/preferenceswindow.py | 14 ++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index e4443434..3a94a58d 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -585,9 +585,11 @@ class MainWindow(QtGui.QMainWindow): Displays the preferences window. """ + user = self._login_widget.get_user() + prov = self._login_widget.get_selected_provider() preferences = PreferencesWindow( self, self._backend, self._provider_config, self._soledad, - self._login_widget.get_selected_provider()) + user, prov) self.soledad_ready.connect(preferences.set_soledad_ready) preferences.show() diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py index 014a0a4f..2947c5db 100644 --- a/src/leap/bitmask/gui/preferenceswindow.py +++ b/src/leap/bitmask/gui/preferenceswindow.py @@ -43,7 +43,8 @@ class PreferencesWindow(QtGui.QDialog): """ preferences_saved = QtCore.Signal() - def __init__(self, parent, backend, provider_config, soledad, domain): + def __init__(self, parent, backend, provider_config, + soledad, username, domain): """ :param parent: parent object of the PreferencesWindow. :parent type: QWidget @@ -53,6 +54,8 @@ class PreferencesWindow(QtGui.QDialog): :type provider_config: ProviderConfig :param soledad: Soledad instance :type soledad: Soledad + :param username: the user set in the login widget + :type username: unicode :param domain: the selected domain in the login widget :type domain: unicode """ @@ -63,6 +66,7 @@ class PreferencesWindow(QtGui.QDialog): self._settings = LeapSettings() self._soledad = soledad self._provider_config = provider_config + self._username = username self._domain = domain self._backend_connect() @@ -191,7 +195,7 @@ class PreferencesWindow(QtGui.QDialog): Changes the user's password if the inputboxes are correctly filled. """ - username = self._srp_auth.get_username() + username = self._username current_password = self.ui.leCurrentPassword.text() new_password = self.ui.leNewPassword.text() new_password2 = self.ui.leNewPassword2.text() @@ -416,12 +420,10 @@ class PreferencesWindow(QtGui.QDialog): sig.srp_password_change_ok.connect(self._change_password_ok) - pwd_change_error = partial( - self._change_password_problem, + pwd_change_error = lambda: self._change_password_problem( self.tr("There was a problem changing the password.")) sig.srp_password_change_error.connect(pwd_change_error) - pwd_change_badpw = partial( - self._change_password_problem, + pwd_change_badpw = lambda: self._change_password_problem( self.tr("You did not enter a correct current password.")) sig.srp_password_change_badpw.connect(pwd_change_badpw) -- cgit v1.2.3 From 639c78246da3de6bc0d176bc64dc95ecddbbc03f Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 24 Apr 2014 16:49:09 -0300 Subject: Show which provider we are using to rounte traffic. Closes #5551. --- src/leap/bitmask/gui/mainwindow.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 3a94a58d..b49717c9 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1517,9 +1517,14 @@ class MainWindow(QtGui.QMainWindow): """ self._eip_connection.qtsigs.connected_signal.emit() - # check for connectivity provider_config = self._get_best_provider_config() domain = provider_config.get_domain() + + self._eip_status.set_provider(domain) + self._settings.set_defaultprovider(provider) + self._already_started_eip = True + + # check for connectivity self._check_name_resolution(domain) def _check_name_resolution(self, domain): @@ -1676,13 +1681,6 @@ class MainWindow(QtGui.QMainWindow): "system.").format(self._eip_name)) self._set_eipstatus_off() - def _on_eip_connected(self): - # XXX move to the state machine too - self._eip_status.set_provider(provider) - - self._settings.set_defaultprovider(provider) - self._already_started_eip = True - @QtCore.Slot() def _stop_eip(self): """ -- cgit v1.2.3 From 70cc6563573f5a6d33782c02fd63525278811a6a Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 25 Apr 2014 11:01:04 -0300 Subject: Fix typo, use domain name correctly. --- src/leap/bitmask/gui/mainwindow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index b49717c9..73cf9419 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1521,7 +1521,7 @@ class MainWindow(QtGui.QMainWindow): domain = provider_config.get_domain() self._eip_status.set_provider(domain) - self._settings.set_defaultprovider(provider) + self._settings.set_defaultprovider(domain) self._already_started_eip = True # check for connectivity -- cgit v1.2.3 From b74620fd45d56a7a9a193572010068efa6be681f Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 25 Apr 2014 11:25:35 -0300 Subject: Enable eip action after disconnecting. If you don't give root access to EIP, e.g. cancel guisudo dialog, the eip does not start, the button is enabled but not the action. This change fixes that issue. --- src/leap/bitmask/gui/statemachines.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/statemachines.py b/src/leap/bitmask/gui/statemachines.py index 93731ce0..31938a70 100644 --- a/src/leap/bitmask/gui/statemachines.py +++ b/src/leap/bitmask/gui/statemachines.py @@ -562,6 +562,8 @@ class ConnectionMachineBuilder(object): if action: off.assignProperty( action, 'text', off_label) + off.assignProperty( + action, 'enabled', True) off.setObjectName(_OFF) states[_OFF] = off -- cgit v1.2.3 From 477f57876be9bdc8b90cb0a031dc2c7d691a8574 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 24 Apr 2014 12:12:17 -0300 Subject: Improve action/widget/menu display conditions. * Hide services that the current logged in provider does not have. * If we don't have a provider supporting that service we hide the actions along with the widgets. * Use more significative method naming. * Keep track of ui component groups visibility. --- src/leap/bitmask/gui/eip_status.py | 14 ++++++----- src/leap/bitmask/gui/mainwindow.py | 49 +++++++++++++++++++++++++++++++++----- 2 files changed, 51 insertions(+), 12 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py index bc31b91d..ca28b8bf 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -260,11 +260,12 @@ class EIPStatusWidget(QtGui.QWidget): self._service_name, self.tr("disabled"))) # Replace EIP tray menu with an action that displays a "disabled" text - menu = self._systray.contextMenu() - menu.insertAction( - self._eip_status_menu.menuAction(), - self._eip_disabled_action) - self._eip_status_menu.menuAction().setVisible(False) + if self.isVisible(): + menu = self._systray.contextMenu() + menu.insertAction( + self._eip_status_menu.menuAction(), + self._eip_disabled_action) + self._eip_status_menu.menuAction().setVisible(False) @QtCore.Slot() def enable_eip_start(self): @@ -278,7 +279,8 @@ class EIPStatusWidget(QtGui.QWidget): # Restore the eip action menu menu = self._systray.contextMenu() menu.removeAction(self._eip_disabled_action) - self._eip_status_menu.menuAction().setVisible(True) + if self.isVisible(): + self._eip_status_menu.menuAction().setVisible(True) # XXX disable (later) -------------------------- def set_eip_status(self, status, error=False): diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 73cf9419..a5c81983 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -256,6 +256,8 @@ class MainWindow(QtGui.QMainWindow): # self.ui.btnEIPPreferences.clicked.connect(self._show_eip_preferences) self._enabled_services = [] + self._ui_mx_visible = True + self._ui_eip_visible = True # last minute UI manipulations @@ -723,7 +725,7 @@ class MainWindow(QtGui.QMainWindow): if IS_MAC: self.raise_() - self._hide_unsupported_services() + self._show_hide_unsupported_services() if self._wizard: possible_username = self._wizard.get_username() @@ -765,7 +767,7 @@ class MainWindow(QtGui.QMainWindow): if self._login_widget.load_user_from_keyring(saved_user): self._login() - def _hide_unsupported_services(self): + def _show_hide_unsupported_services(self): """ Given a set of configured providers, it creates a set of available services among all of them and displays the service @@ -786,8 +788,38 @@ class MainWindow(QtGui.QMainWindow): for service in provider_config.get_services(): services.add(service) - self.ui.eipWidget.setVisible(EIP_SERVICE in services) - self.ui.mailWidget.setVisible(MX_SERVICE in services) + self._set_eip_visible(EIP_SERVICE in services) + self._set_mx_visible(MX_SERVICE in services) + + def _set_mx_visible(self, visible): + """ + Change the visibility of MX_SERVICE related UI components. + + :param visible: whether the components should be visible or not. + :type visible: bool + """ + # only update visibility if it is something to change + if self._ui_mx_visible ^ visible: + self.ui.mailWidget.setVisible(visible) + self.ui.lineUnderEmail.setVisible(visible) + self._action_mail_status.setVisible(visible) + self._ui_mx_visible = visible + + def _set_eip_visible(self, visible): + """ + Change the visibility of EIP_SERVICE related UI components. + + :param visible: whether the components should be visible or not. + :type visible: bool + """ + # NOTE: we use xor to avoid the code being run if the visibility hasn't + # changed. This is meant to avoid the eip menu being displayed floating + # around at start because the systray isn't rendered yet. + if self._ui_eip_visible ^ visible: + self.ui.eipWidget.setVisible(visible) + self.ui.lineUnderEIP.setVisible(visible) + self._eip_menu.setVisible(visible) + self._ui_eip_visible = visible def _set_label_offline(self): """ @@ -824,7 +856,7 @@ class MainWindow(QtGui.QMainWindow): systrayMenu.addSeparator() eip_status_label = "{0}: {1}".format(self._eip_name, self.tr("OFF")) - eip_menu = systrayMenu.addMenu(eip_status_label) + self._eip_menu = eip_menu = systrayMenu.addMenu(eip_status_label) eip_menu.addAction(self._action_eip_startstop) self._eip_status.set_eip_status_menu(eip_menu) systrayMenu.addSeparator() @@ -1186,7 +1218,7 @@ class MainWindow(QtGui.QMainWindow): username = self._login_widget.get_user() password = self._login_widget.get_password() - self._hide_unsupported_services() + self._show_hide_unsupported_services() domain = self._provider_config.get_domain() self._backend.login(domain, username, password) @@ -1221,6 +1253,9 @@ class MainWindow(QtGui.QMainWindow): self._soledad_bootstrapper.soledad_failed.connect( lambda: btn_enabled(True)) + if not self._get_best_provider_config().provides_mx(): + self._set_mx_visible(False) + def _start_eip_bootstrap(self): """ Changes the stackedWidget index to the EIP status one and @@ -1950,6 +1985,8 @@ class MainWindow(QtGui.QMainWindow): self._login_widget.logged_out() self._mail_status.mail_state_disabled() + self._show_hide_unsupported_services() + @QtCore.Slot(dict) def _intermediate_stage(self, data): # TODO this method name is confusing as hell. -- cgit v1.2.3 From c546964e79c1a66688ec305f4f29699dec685e42 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 28 Apr 2014 13:15:39 -0300 Subject: Increase life of a pastebin from 1 Week to 1 Month. --- src/leap/bitmask/gui/loggerwindow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/loggerwindow.py b/src/leap/bitmask/gui/loggerwindow.py index b0e45a50..f19b172f 100644 --- a/src/leap/bitmask/gui/loggerwindow.py +++ b/src/leap/bitmask/gui/loggerwindow.py @@ -206,7 +206,7 @@ class LoggerWindow(QtGui.QDialog): pb = pastebin.PastebinAPI() link = pb.paste(PASTEBIN_API_DEV_KEY, content, paste_name="Bitmask log", - paste_expire_date='1W') + paste_expire_date='1M') # convert to 'raw' link link = "http://pastebin.com/raw.php?i=" + link.split('/')[-1] -- cgit v1.2.3 From 1b5e1e5356c2dc4d7a56604801aaf5a0378c9bff Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 30 Apr 2014 13:35:15 -0300 Subject: Handle retries in the soledad bootstrapper object. --- src/leap/bitmask/gui/mainwindow.py | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index a5c81983..d66d518e 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -209,8 +209,6 @@ class MainWindow(QtGui.QMainWindow): self._soledad_bootstrapped_stage) self._soledad_bootstrapper.local_only_ready.connect( self._soledad_bootstrapped_stage) - self._soledad_bootstrapper.soledad_timeout.connect( - self._retry_soledad_connection) self._soledad_bootstrapper.soledad_invalid_auth_token.connect( self._mail_status.set_soledad_invalid_auth_token) self._soledad_bootstrapper.soledad_failed.connect( @@ -1362,22 +1360,6 @@ class MainWindow(QtGui.QMainWindow): # that sets the global status logger.error("Soledad failed to start: %s" % (data[self._soledad_bootstrapper.ERROR_KEY],)) - self._retry_soledad_connection() - - def _retry_soledad_connection(self): - """ - Retries soledad connection. - """ - # XXX should move logic to soledad boostrapper itself - logger.debug("Retrying soledad connection.") - if self._soledad_bootstrapper.should_retry_initialization(): - self._soledad_bootstrapper.increment_retries_count() - # XXX should cancel the existing socket --- this - # is avoiding a clean termination. - self._maybe_run_soledad_setup_checks() - else: - logger.warning("Max number of soledad initialization " - "retries reached.") @QtCore.Slot(dict) def _soledad_bootstrapped_stage(self, data): @@ -1943,7 +1925,6 @@ class MainWindow(QtGui.QMainWindow): Starts the logout sequence """ - self._soledad_bootstrapper.cancel_bootstrap() setProxiedObject(self._soledad, None) self._cancel_ongoing_defers() -- cgit v1.2.3 From 31c524e2abb98ca13ea993ebc2ec26e9f3d81975 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 7 May 2014 17:27:27 -0300 Subject: Organize smtp logic in the bootstrapper. --- src/leap/bitmask/gui/mainwindow.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index d66d518e..1a88fcce 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1412,13 +1412,9 @@ class MainWindow(QtGui.QMainWindow): logger.debug("not starting smtp in offline mode") return - # TODO for simmetry, this should be called start_smtp_service - # (and delegate all the checks to the conductor) if self._provides_mx_and_enabled(): - self._mail_conductor.smtp_bootstrapper.run_smtp_setup_checks( - self._provider_config, - self._mail_conductor.smtp_config, - download_if_needed=True) + self._mail_conductor.start_smtp_service(self._provider_config, + download_if_needed=True) # XXX --- should remove from here, and connecte directly to the state # machine. -- cgit v1.2.3 From 0890db9160c1b77da45587273bdd7398a87d1a9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Thu, 8 May 2014 16:43:11 -0300 Subject: Fix logout button margins --- src/leap/bitmask/gui/ui/login.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/ui/login.ui b/src/leap/bitmask/gui/ui/login.ui index f5725d5a..216eca9e 100644 --- a/src/leap/bitmask/gui/ui/login.ui +++ b/src/leap/bitmask/gui/ui/login.ui @@ -215,7 +215,7 @@ 0 - 0 + 12 -- cgit v1.2.3 From ca0e9b85a831f716a0959c5fdb9dbb571515de97 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 7 May 2014 15:42:56 -0500 Subject: tear down fw on quit-action too --- src/leap/bitmask/gui/mainwindow.py | 5 +++++ src/leap/bitmask/gui/twisted_main.py | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index a5c81983..70fad204 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -19,6 +19,7 @@ Main window for Bitmask. """ import logging import socket +import time from threading import Condition from datetime import datetime @@ -2067,6 +2068,10 @@ class MainWindow(QtGui.QMainWindow): logger.debug('Terminating vpn') self._backend.stop_eip(shutdown=True) + # XXX this *has* to block, since we have some delay in vpn.terminate + # it should receive a signal from backend that everything is clear to + # proceed, or timeout happened. + self._cancel_ongoing_defers() # TODO missing any more cancels? diff --git a/src/leap/bitmask/gui/twisted_main.py b/src/leap/bitmask/gui/twisted_main.py index f39d0bbe..dfd69033 100644 --- a/src/leap/bitmask/gui/twisted_main.py +++ b/src/leap/bitmask/gui/twisted_main.py @@ -26,7 +26,6 @@ logger = logging.getLogger(__name__) def stop(): - logger.debug("Really stoping all the things...") QtCore.QCoreApplication.sendPostedEvents() QtCore.QCoreApplication.flush() try: -- cgit v1.2.3 From d68e35c611638a57bbda99665f9685e5ae6fcd23 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 7 May 2014 17:24:12 -0500 Subject: introduce delay on shutdown after resolvconf was daemonized --- src/leap/bitmask/gui/mainwindow.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 70fad204..681432b3 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -2068,9 +2068,12 @@ class MainWindow(QtGui.QMainWindow): logger.debug('Terminating vpn') self._backend.stop_eip(shutdown=True) - # XXX this *has* to block, since we have some delay in vpn.terminate - # it should receive a signal from backend that everything is clear to - # proceed, or timeout happened. + # XXX this *has* to wait for a reasonable lapse, since we have some + # delay in vpn.terminate. + # For a better solution it should receive be + # signaled from backend that + # everything is clear to proceed, or timeout happened. + time.sleep(1.5) self._cancel_ongoing_defers() -- cgit v1.2.3 From 66c94c7533a81cf9512b41090ccab4ee8360e611 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 8 May 2014 17:19:01 -0500 Subject: wait on shutdown until firewall is down --- src/leap/bitmask/gui/mainwindow.py | 7 ------- 1 file changed, 7 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 681432b3..c55dbb82 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -2068,13 +2068,6 @@ class MainWindow(QtGui.QMainWindow): logger.debug('Terminating vpn') self._backend.stop_eip(shutdown=True) - # XXX this *has* to wait for a reasonable lapse, since we have some - # delay in vpn.terminate. - # For a better solution it should receive be - # signaled from backend that - # everything is clear to proceed, or timeout happened. - time.sleep(1.5) - self._cancel_ongoing_defers() # TODO missing any more cancels? -- cgit v1.2.3 From 02b7b4a35d45671542f1e665767e9227c81207af Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Tue, 13 May 2014 01:55:28 -0500 Subject: give some time for eip to shudown on bundle. Closes: #5663 --- src/leap/bitmask/gui/mainwindow.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index c55dbb82..8b60ad8e 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -2068,12 +2068,25 @@ class MainWindow(QtGui.QMainWindow): logger.debug('Terminating vpn') self._backend.stop_eip(shutdown=True) + # We need to give some time to the ongoing signals for shutdown + # to come into action. This needs to be solved using + # back-communication from backend. + QtCore.QTimer.singleShot(3000, self._shutdown) + + def _shutdown(self): + """ + Actually shutdown. + """ self._cancel_ongoing_defers() # TODO missing any more cancels? logger.debug('Cleaning pidfiles') self._cleanup_pidfiles() + if self._quit_callback: + self._quit_callback() + + logger.debug('Bye.') def quit(self): """ @@ -2109,8 +2122,3 @@ class MainWindow(QtGui.QMainWindow): self._logger_window.close() self.close() - - if self._quit_callback: - self._quit_callback() - - logger.debug('Bye.') -- cgit v1.2.3 From bc424a8d5c9bdd64d837e27636b4b02d8be7d582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Tue, 13 May 2014 16:15:57 -0300 Subject: Enable EIP whenever possible --- src/leap/bitmask/gui/mainwindow.py | 87 +++++++++++++++++++++++++++++++++----- 1 file changed, 76 insertions(+), 11 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 1a88fcce..6e270de1 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -182,6 +182,8 @@ class MainWindow(QtGui.QMainWindow): self.eip_needs_login.connect(self._eip_status.disable_eip_start) self.eip_needs_login.connect(self._disable_eip_start_action) + self._trying_to_start_eip = False + # This is loaded only once, there's a bug when doing that more # than once # XXX HACK!! But we need it as long as we are using @@ -357,11 +359,24 @@ class MainWindow(QtGui.QMainWindow): self._backend_connected_signals[signal] = method signal.connect(method) + def _backend_bad_call(self, data): + """ + Callback for debugging bad backend calls + + :param data: data from the backend about the problem + :type data: str + """ + logger.error("Bad call to the backend:") + logger.error(data) + def _backend_connect(self): """ Helper to connect to backend signals """ sig = self._backend.signaler + + sig.backend_bad_call.connect(self._backend_bad_call) + self._connect_and_track(sig.prov_name_resolution, self._intermediate_stage) self._connect_and_track(sig.prov_https_connection, @@ -442,6 +457,9 @@ class MainWindow(QtGui.QMainWindow): sig.eip_process_restart_tls.connect(self._do_eip_restart) sig.eip_process_restart_ping.connect(self._do_eip_restart) + sig.eip_can_start.connect(self._backend_can_start_eip) + sig.eip_cannot_start.connect(self._backend_cannot_start_eip) + def _disconnect_and_untrack(self): """ Helper to disconnect the tracked signals. @@ -609,17 +627,43 @@ class MainWindow(QtGui.QMainWindow): """ settings = self._settings default_provider = settings.get_defaultprovider() + + if default_provider is None: + logger.warning("Trying toupdate eip enabled status but there's no" + " default provider. Disabling EIP for the time" + " being...") + self._backend_cannot_start_eip() + return + + self._trying_to_start_eip = settings.get_autostart_eip() + self._backend.eip_can_start(default_provider) + + # If we don't want to start eip, we leave everything + # initialized to quickly start it + if not self._trying_to_start_eip: + self._backend.setup_eip(default_provider, skip_network=True) + + def _backend_can_start_eip(self): + """ + TRIGGER: + self._backend.signaler.eip_can_start + + If EIP can be started right away, and the client is configured + to do so, start it. Otherwise it leaves everything in place + for the user to click Turn ON. + """ + settings = self._settings + default_provider = settings.get_defaultprovider() enabled_services = [] if default_provider is not None: enabled_services = settings.get_enabled_services(default_provider) eip_enabled = False if EIP_SERVICE in enabled_services: - should_autostart = settings.get_autostart_eip() - if should_autostart and default_provider is not None: + eip_enabled = True + if default_provider is not None: self._eip_status.enable_eip_start() self._eip_status.set_eip_status("") - eip_enabled = True else: # we don't have an usable provider # so the user needs to log in first @@ -629,7 +673,32 @@ class MainWindow(QtGui.QMainWindow): self._eip_status.disable_eip_start() self._eip_status.set_eip_status(self.tr("Disabled")) - return eip_enabled + if eip_enabled and self._trying_to_start_eip: + self._trying_to_start_eip = False + self._try_autostart_eip() + + def _backend_cannot_start_eip(self): + """ + TRIGGER: + self._backend.signaler.eip_cannot_start + + If EIP can't be started right away, get the UI to what it + needs to look like and waits for a proper login/eip bootstrap. + """ + settings = self._settings + default_provider = settings.get_defaultprovider() + enabled_services = [] + if default_provider is not None: + enabled_services = settings.get_enabled_services(default_provider) + + if EIP_SERVICE in enabled_services: + # we don't have a usable provider + # so the user needs to log in first + self._eip_status.disable_eip_start() + else: + self._stop_eip() + self._eip_status.disable_eip_start() + self._eip_status.set_eip_status(self.tr("Disabled")) @QtCore.Slot() def _show_eip_preferences(self): @@ -749,7 +818,7 @@ class MainWindow(QtGui.QMainWindow): self._wizard = None self._backend_connect() else: - self._try_autostart_eip() + self._update_eip_enabled_status() domain = self._settings.get_provider() if domain is not None: @@ -1589,23 +1658,19 @@ class MainWindow(QtGui.QMainWindow): Tries to autostart EIP """ settings = self._settings - - if not self._update_eip_enabled_status(): - return - default_provider = settings.get_defaultprovider() self._enabled_services = settings.get_enabled_services( default_provider) loaded = self._provisional_provider_config.load( provider.get_provider_path(default_provider)) - if loaded: + if loaded and settings.get_autostart_eip(): # XXX I think we should not try to re-download config every time, # it adds some delay. # Maybe if it's the first run in a session, # or we can try only if it fails. self._maybe_start_eip() - else: + elif settings.get_autostart_eip(): # XXX: Display a proper message to the user self.eip_needs_login.emit() logger.error("Unable to load %s config, cannot autostart." % -- cgit v1.2.3