From 72b7d49966637c019e97fae7f186774097e5e96f Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 28 Apr 2014 18:19:36 -0300 Subject: Refactor SoledadBootstrapper to backend. --- src/leap/bitmask/gui/mail_status.py | 2 +- src/leap/bitmask/gui/mainwindow.py | 122 +++++++++--------------------------- 2 files changed, 31 insertions(+), 93 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py index d3346780..5caef745 100644 --- a/src/leap/bitmask/gui/mail_status.py +++ b/src/leap/bitmask/gui/mail_status.py @@ -188,7 +188,7 @@ class MailStatusWidget(QtGui.QWidget): def set_soledad_failed(self): """ TRIGGERS: - SoledadBootstrapper.soledad_failed + Signaler.soledad_bootstrap_failed This method is called whenever soledad has a failure. """ diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index e3848c46..cceb1efe 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -57,8 +57,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.connection import EIPConnection -from leap.bitmask.services.soledad.soledadbootstrapper import \ - SoledadBootstrapper from leap.bitmask.util import make_address from leap.bitmask.util.keyring_helpers import has_keyring @@ -195,7 +193,6 @@ class MainWindow(QtGui.QMainWindow): self._provisional_provider_config = ProviderConfig() self._already_started_eip = False - self._already_started_soledad = False # This is created once we have a valid provider config self._srp_auth = None @@ -205,18 +202,6 @@ class MainWindow(QtGui.QMainWindow): self._backend_connected_signals = {} self._backend_connect() - self._soledad_bootstrapper = SoledadBootstrapper() - self._soledad_bootstrapper.download_config.connect( - self._soledad_intermediate_stage) - self._soledad_bootstrapper.gen_key.connect( - self._soledad_bootstrapped_stage) - self._soledad_bootstrapper.local_only_ready.connect( - self._soledad_bootstrapped_stage) - self._soledad_bootstrapper.soledad_invalid_auth_token.connect( - self._mail_status.set_soledad_invalid_auth_token) - self._soledad_bootstrapper.soledad_failed.connect( - self._mail_status.set_soledad_failed) - self.ui.action_preferences.triggered.connect(self._show_preferences) self.ui.action_eip_preferences.triggered.connect( self._show_eip_preferences) @@ -302,8 +287,6 @@ class MainWindow(QtGui.QMainWindow): self._soledad = ProxyBase(None) self._keymanager = ProxyBase(None) - self._soledad_defer = None - self._mail_conductor = mail_conductor.MailConductor( self._soledad, self._keymanager) self._mail_conductor.connect_mail_signals(self._mail_status) @@ -461,6 +444,21 @@ class MainWindow(QtGui.QMainWindow): sig.eip_can_start.connect(self._backend_can_start_eip) sig.eip_cannot_start.connect(self._backend_cannot_start_eip) + # Soledad signals + sig.soledad_bootstrap_failed.connect( + self._mail_status.set_soledad_failed) + sig.soledad_bootstrap_finished.connect(self._on_soledad_ready) + + sig.soledad_offline_failed.connect( + self._mail_status.set_soledad_failed) + sig.soledad_offline_finished.connect(self._on_soledad_ready) + + sig.soledad_invalid_auth_token.connect( + self._mail_status.set_soledad_invalid_auth_token) + + # TODO: connect this with something + # sig.soledad_cancelled_bootstrap.connect() + def _disconnect_and_untrack(self): """ Helper to disconnect the tracked signals. @@ -1252,11 +1250,7 @@ class MainWindow(QtGui.QMainWindow): # XXX: Should we stop all the backend defers? self._backend.cancel_setup_provider() self._backend.cancel_login() - - if self._soledad_defer is not None: - logger.debug("Cancelling soledad defer.") - self._soledad_defer.cancel() - self._soledad_defer = None + self._backend.cancel_soledad_bootstrap() @QtCore.Slot() def _set_login_cancelled(self): @@ -1317,9 +1311,9 @@ class MainWindow(QtGui.QMainWindow): if MX_SERVICE in self._enabled_services: btn_enabled = self._login_widget.set_logout_btn_enabled btn_enabled(False) - self.soledad_ready.connect(lambda: btn_enabled(True)) - self._soledad_bootstrapper.soledad_failed.connect( - lambda: btn_enabled(True)) + sig = self._backend.signaler + sig.soledad_bootstrap_failed.connect(lambda: btn_enabled(True)) + sig.soledad_bootstrap_finished.connect(lambda: btn_enabled(True)) if not self._get_best_provider_config().provides_mx(): self._set_mx_visible(False) @@ -1372,9 +1366,6 @@ class MainWindow(QtGui.QMainWindow): Conditionally start Soledad. """ # TODO split. - if self._already_started_soledad is True: - return - if not self._provides_mx_and_enabled(): return @@ -1382,11 +1373,7 @@ class MainWindow(QtGui.QMainWindow): password = unicode(self._login_widget.get_password()) provider_domain = self._login_widget.get_selected_provider() - sb = self._soledad_bootstrapper if flags.OFFLINE is True: - provider_domain = self._login_widget.get_selected_provider() - sb._password = password - self._provisional_provider_config.load( provider.get_provider_path(provider_domain)) @@ -1399,74 +1386,32 @@ class MainWindow(QtGui.QMainWindow): # this is mostly for internal use/debug for now. logger.warning("Sorry! Log-in at least one time.") return - fun = sb.load_offline_soledad - fun(full_user_id, password, uuid) + self._backend.load_offline_soledad(full_user_id, password, uuid) else: - provider_config = self._provider_config - if self._logged_user is not None: - self._soledad_defer = sb.run_soledad_setup_checks( - provider_config, username, password, - download_if_needed=True) + domain = self._provider_config.get_domain() + self._backend.soledad_bootstrap(username, domain, password) ################################################################### # Service control methods: soledad - @QtCore.Slot(dict) - def _soledad_intermediate_stage(self, data): - # TODO missing param docstring - """ - TRIGGERS: - 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 - they fail. - """ - passed = data[self._soledad_bootstrapper.PASSED_KEY] - if not passed: - # TODO display in the GUI: - # should pass signal to a slot in status_panel - # that sets the global status - logger.error("Soledad failed to start: %s" % - (data[self._soledad_bootstrapper.ERROR_KEY],)) - - @QtCore.Slot(dict) - def _soledad_bootstrapped_stage(self, data): + @QtCore.Slot() + def _on_soledad_ready(self): """ TRIGGERS: - self._soledad_bootstrapper.gen_key - self._soledad_bootstrapper.local_only_ready + Signaler.soledad_bootstrap_finished - If there was a problem, displays it, otherwise it does nothing. - This is used for intermediate bootstrapping stages, in case - they fail. - - :param data: result from the bootstrapping stage for Soledad - :type data: dict + Actions to take when Soledad is ready. """ - passed = data[self._soledad_bootstrapper.PASSED_KEY] - if not passed: - # TODO should actually *display* on the panel. - logger.debug("ERROR on soledad bootstrapping:") - logger.error("%r" % data[self._soledad_bootstrapper.ERROR_KEY]) - return - logger.debug("Done bootstrapping Soledad") # Update the proxy objects to point to # the initialized instances. - setProxiedObject(self._soledad, - self._soledad_bootstrapper.soledad) - setProxiedObject(self._keymanager, - self._soledad_bootstrapper.keymanager) + setProxiedObject(self._soledad, self._backend.get_soledad()) + setProxiedObject(self._keymanager, self._backend.get_keymanager()) - # Ok, now soledad is ready, so we can allow other things that - # depend on soledad to start. - self._soledad_defer = None + self._soledad_started = True - # this will trigger start_imap_service - # and start_smtp_boostrapping self.soledad_ready.emit() ################################################################### @@ -1991,9 +1936,6 @@ class MainWindow(QtGui.QMainWindow): self._cancel_ongoing_defers() - # reset soledad status flag - self._already_started_soledad = False - # XXX: If other defers are doing authenticated stuff, this # might conflict with those. CHECK! self._backend.logout() @@ -2101,11 +2043,7 @@ class MainWindow(QtGui.QMainWindow): if self._logged_user is not None: self._backend.logout() - if self._soledad_bootstrapper.soledad is not None: - logger.debug("Closing soledad...") - self._soledad_bootstrapper.soledad.close() - else: - logger.error("No instance of soledad was found.") + self._backend.close_soledad() logger.debug('Terminating vpn') self._backend.stop_eip(shutdown=True) -- cgit v1.2.3 From 2f57c31cda8208340322efd5c02f8b9120ce29aa Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 6 May 2014 16:16:40 -0300 Subject: Separate imap/smtp logic from conductor. --- src/leap/bitmask/gui/mainwindow.py | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index cceb1efe..bf76f574 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -87,7 +87,6 @@ class MainWindow(QtGui.QMainWindow): new_updates = QtCore.Signal(object) raise_window = QtCore.Signal([]) soledad_ready = QtCore.Signal([]) - mail_client_logged_in = QtCore.Signal([]) logout = QtCore.Signal([]) # We use this flag to detect abnormal terminations @@ -123,9 +122,6 @@ class MainWindow(QtGui.QMainWindow): register(signal=proto.RAISE_WINDOW, callback=self._on_raise_window_event, reqcbk=lambda req, resp: None) # make rpc call async - register(signal=proto.IMAP_CLIENT_LOGIN, - callback=self._on_mail_client_logged_in, - reqcbk=lambda req, resp: None) # make rpc call async # end register leap events #################################### self._quit_callback = quit_callback @@ -265,7 +261,6 @@ class MainWindow(QtGui.QMainWindow): # XXX should connect to mail_conductor.start_mail_service instead self.soledad_ready.connect(self._start_smtp_bootstrapping) self.soledad_ready.connect(self._start_imap_service) - self.mail_client_logged_in.connect(self._fetch_incoming_mail) self.logout.connect(self._stop_imap_service) self.logout.connect(self._stop_smtp_service) @@ -1373,7 +1368,7 @@ class MainWindow(QtGui.QMainWindow): password = unicode(self._login_widget.get_password()) provider_domain = self._login_widget.get_selected_provider() - if flags.OFFLINE is True: + if flags.OFFLINE: self._provisional_provider_config.load( provider.get_provider_path(provider_domain)) @@ -1455,34 +1450,19 @@ class MainWindow(QtGui.QMainWindow): # in the mail state machine so it shows that imap is active # (but not smtp since it's not yet ready for offline use) start_fun = self._mail_conductor.start_imap_service - if flags.OFFLINE is True: + if flags.OFFLINE: provider_domain = self._login_widget.get_selected_provider() self._provider_config.load( provider.get_provider_path(provider_domain)) provides_mx = self._provider_config.provides_mx() - if flags.OFFLINE is True and provides_mx: + if flags.OFFLINE and provides_mx: start_fun() return if self._provides_mx_and_enabled(): start_fun() - def _on_mail_client_logged_in(self, req): - """ - Triggers qt signal when client login event is received. - """ - self.mail_client_logged_in.emit() - - @QtCore.Slot() - def _fetch_incoming_mail(self): - """ - TRIGGERS: - self.mail_client_logged_in - """ - # TODO connect signal directly!!! - self._mail_conductor.fetch_incoming_mail() - @QtCore.Slot() def _stop_imap_service(self): """ -- cgit v1.2.3 From 3a81b31204680bf2ba0abe26467aef201cf030fa Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 14 May 2014 12:25:00 -0300 Subject: Move Mail logic to backend. --- src/leap/bitmask/gui/mainwindow.py | 8 ++++---- 1 file changed, 4 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 bf76f574..370a9d43 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -282,8 +282,9 @@ class MainWindow(QtGui.QMainWindow): self._soledad = ProxyBase(None) self._keymanager = ProxyBase(None) - self._mail_conductor = mail_conductor.MailConductor( - self._soledad, self._keymanager) + self._mail_conductor = mail_conductor.MailConductor(self._backend) + # self._mail_conductor = mail_conductor.MailConductor( + # self._soledad, self._keymanager) self._mail_conductor.connect_mail_signals(self._mail_status) # Eip machine is a public attribute where the state machine for @@ -1423,8 +1424,7 @@ class MainWindow(QtGui.QMainWindow): return if self._provides_mx_and_enabled(): - self._mail_conductor.start_smtp_service(self._provider_config, - download_if_needed=True) + self._mail_conductor.start_smtp_service(download_if_needed=True) # XXX --- should remove from here, and connecte directly to the state # machine. -- cgit v1.2.3 From 8b7e1336806332c3466405bc1df1da3682689524 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 14 May 2014 17:53:29 -0300 Subject: Avoid reconnect same signals several times. We don't want to connect again the untracked signals after the wizard was finished. --- src/leap/bitmask/gui/mainwindow.py | 30 ++++++++++++++++++++++++------ 1 file changed, 24 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 370a9d43..cd3e77c9 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -349,14 +349,23 @@ class MainWindow(QtGui.QMainWindow): logger.error("Bad call to the backend:") logger.error(data) - def _backend_connect(self): + def _backend_connect(self, only_tracked=False): """ - Helper to connect to backend signals + Connect to backend signals. + + We track some signals in order to disconnect them on demand. + For instance, in the wizard we need to connect to some signals that are + already connected in the mainwindow, so to avoid conflicts we do: + - disconnect signals needed in wizard (`_disconnect_and_untrack`) + - use wizard + - reconnect disconnected signals (we use the `only_tracked` param) + + :param only_tracked: whether or not we should connect only the signals + that we are tracking to disconnect later. + :type only_tracked: bool """ 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, @@ -412,7 +421,16 @@ class MainWindow(QtGui.QMainWindow): self._connect_and_track(sig.eip_client_certificate_ready, self._finish_eip_bootstrap) + ################################################### + # Add tracked signals above this, untracked bellow! + ################################################### + if only_tracked: + return + # We don't want to disconnect some signals so don't track them: + + sig.backend_bad_call.connect(self._backend_bad_call) + sig.prov_unsupported_client.connect(self._needs_update) sig.prov_unsupported_api.connect(self._incompatible_api) @@ -491,7 +509,7 @@ class MainWindow(QtGui.QMainWindow): # This happens if the user finishes the provider # setup but does not register self._wizard = None - self._backend_connect() + self._backend_connect(only_tracked=True) if self._wizard_firstrun: self._finish_init() @@ -811,7 +829,7 @@ class MainWindow(QtGui.QMainWindow): self.eip_needs_login.emit() self._wizard = None - self._backend_connect() + self._backend_connect(only_tracked=True) else: self._update_eip_enabled_status() -- cgit v1.2.3 From f0951ad92cb0bf2116a333b8df8279918c5febd6 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 15 May 2014 16:46:00 -0300 Subject: Move soledad password change to backend. Also cleanup soledad usage in the GUI. --- src/leap/bitmask/gui/advanced_key_management.py | 12 ++--- src/leap/bitmask/gui/mainwindow.py | 27 ++++------ src/leap/bitmask/gui/preferenceswindow.py | 70 +++++++++++++++++-------- 3 files changed, 61 insertions(+), 48 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 be6b4410..1681caca 100644 --- a/src/leap/bitmask/gui/advanced_key_management.py +++ b/src/leap/bitmask/gui/advanced_key_management.py @@ -20,7 +20,6 @@ Advanced Key Management import logging from PySide import QtGui -from zope.proxy import sameProxiedObjects from leap.keymanager import openpgp from leap.keymanager.errors import KeyAddressMismatch, KeyFingerprintMismatch @@ -34,7 +33,7 @@ class AdvancedKeyManagement(QtGui.QDialog): """ Advanced Key Management """ - def __init__(self, parent, has_mx, user, keymanager, soledad): + def __init__(self, parent, has_mx, user, keymanager, soledad_started): """ :param parent: parent object of AdvancedKeyManagement. :parent type: QWidget @@ -45,8 +44,8 @@ class AdvancedKeyManagement(QtGui.QDialog): :type user: unicode :param keymanager: the existing keymanager instance :type keymanager: KeyManager - :param soledad: a loaded instance of Soledad - :type soledad: Soledad + :param soledad_started: whether soledad has started or not + :type soledad_started: bool """ QtGui.QDialog.__init__(self, parent) @@ -56,7 +55,6 @@ 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}.") @@ -64,8 +62,7 @@ class AdvancedKeyManagement(QtGui.QDialog): self._disable_ui(msg) return - # if Soledad is not started yet - if sameProxiedObjects(soledad, None): + if not soledad_started: msg = self.tr("To use this, you need to enable/start {0}.") msg = msg.format(get_service_display_name(MX_SERVICE)) self._disable_ui(msg) @@ -79,7 +76,6 @@ class AdvancedKeyManagement(QtGui.QDialog): # self.ui.lblStatus.setText(msg) self._keymanager = keymanager - self._soledad = soledad self._key = keymanager.get_key(user, openpgp.OpenPGPKey) self._key_priv = keymanager.get_key( diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index cd3e77c9..e1527bbe 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -189,6 +189,7 @@ class MainWindow(QtGui.QMainWindow): self._provisional_provider_config = ProviderConfig() self._already_started_eip = False + self._soledad_started = False # This is created once we have a valid provider config self._srp_auth = None @@ -276,15 +277,9 @@ class MainWindow(QtGui.QMainWindow): 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 - # around. - self._soledad = ProxyBase(None) self._keymanager = ProxyBase(None) self._mail_conductor = mail_conductor.MailConductor(self._backend) - # self._mail_conductor = mail_conductor.MailConductor( - # self._soledad, self._keymanager) self._mail_conductor.connect_mail_signals(self._mail_status) # Eip machine is a public attribute where the state machine for @@ -603,8 +598,8 @@ class MainWindow(QtGui.QMainWindow): provider_config = self._get_best_provider_config() has_mx = provider_config.provides_mx() - akm = AdvancedKeyManagement( - self, has_mx, logged_user, self._keymanager, self._soledad) + akm = AdvancedKeyManagement(self, has_mx, logged_user, + self._keymanager, self._soledad_started) akm.show() @QtCore.Slot() @@ -619,8 +614,8 @@ class MainWindow(QtGui.QMainWindow): user = self._login_widget.get_user() prov = self._login_widget.get_selected_provider() preferences = PreferencesWindow( - self, self._backend, self._provider_config, self._soledad, - user, prov) + self, self._backend, self._provider_config, + self._soledad_started, user, prov) self.soledad_ready.connect(preferences.set_soledad_ready) preferences.show() @@ -1265,6 +1260,9 @@ class MainWindow(QtGui.QMainWindow): self._backend.cancel_setup_provider() self._backend.cancel_login() self._backend.cancel_soledad_bootstrap() + self._backend.close_soledad() + + self._soledad_started = False @QtCore.Slot() def _set_login_cancelled(self): @@ -1419,9 +1417,8 @@ class MainWindow(QtGui.QMainWindow): """ logger.debug("Done bootstrapping Soledad") - # Update the proxy objects to point to - # the initialized instances. - setProxiedObject(self._soledad, self._backend.get_soledad()) + # Update the proxy objects to point to the initialized instances. + # setProxiedObject(self._soledad, self._backend.get_soledad()) setProxiedObject(self._keymanager, self._backend.get_keymanager()) self._soledad_started = True @@ -1930,8 +1927,6 @@ class MainWindow(QtGui.QMainWindow): Starts the logout sequence """ - setProxiedObject(self._soledad, None) - self._cancel_ongoing_defers() # XXX: If other defers are doing authenticated stuff, this @@ -2041,8 +2036,6 @@ class MainWindow(QtGui.QMainWindow): if self._logged_user is not None: self._backend.logout() - self._backend.close_soledad() - logger.debug('Terminating vpn') self._backend.stop_eip(shutdown=True) diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py index 2947c5db..77a3994f 100644 --- a/src/leap/bitmask/gui/preferenceswindow.py +++ b/src/leap/bitmask/gui/preferenceswindow.py @@ -23,12 +23,10 @@ import logging from functools import partial from PySide import QtCore, QtGui -from zope.proxy import sameProxiedObjects 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.util.password import basic_password_checks from leap.bitmask.services import get_supported from leap.bitmask.config.providerconfig import ProviderConfig @@ -43,8 +41,8 @@ class PreferencesWindow(QtGui.QDialog): """ preferences_saved = QtCore.Signal() - def __init__(self, parent, backend, provider_config, - soledad, username, domain): + def __init__(self, parent, backend, provider_config, soledad_started, + username, domain): """ :param parent: parent object of the PreferencesWindow. :parent type: QWidget @@ -52,8 +50,8 @@ class PreferencesWindow(QtGui.QDialog): :type backend: Backend :param provider_config: ProviderConfig object. :type provider_config: ProviderConfig - :param soledad: Soledad instance - :type soledad: Soledad + :param soledad_started: whether soledad has started or not + :type soledad_started: bool :param username: the user set in the login widget :type username: unicode :param domain: the selected domain in the login widget @@ -64,8 +62,8 @@ class PreferencesWindow(QtGui.QDialog): self._backend = backend self._settings = LeapSettings() - self._soledad = soledad self._provider_config = provider_config + self._soledad_started = soledad_started self._username = username self._domain = domain @@ -118,7 +116,7 @@ class PreferencesWindow(QtGui.QDialog): pw_enabled = False else: # check if Soledad is bootstrapped - if sameProxiedObjects(self._soledad, None): + if not self._soledad_started: msg = self.tr( "You need to wait until {0} is ready in " "order to change the password.".format(mx_name)) @@ -209,10 +207,10 @@ class PreferencesWindow(QtGui.QDialog): return self._set_changing_password(True) - self._backend.change_password(current_password, new_password) + self._backend.auth_change_password(current_password, new_password) @QtCore.Slot() - def _change_password_ok(self): + def _srp_change_password_ok(self): """ TRIGGERS: self._backend.signaler.srp_password_change_ok @@ -221,12 +219,33 @@ class PreferencesWindow(QtGui.QDialog): """ new_password = self.ui.leNewPassword.text() logger.debug("SRP password changed successfully.") - try: - self._soledad.change_passphrase(new_password) - logger.debug("Soledad password changed successfully.") - except NoStorageSecret: - logger.debug( - "No storage secret for password change in Soledad.") + self._backend.soledad_change_password(new_password) + + @QtCore.Slot(unicode) + def _srp_change_password_problem(self, msg): + """ + TRIGGERS: + self._backend.signaler.srp_password_change_error + self._backend.signaler.srp_password_change_badpw + + 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) + + @QtCore.Slot() + def _soledad_change_password_ok(self): + """ + TRIGGERS: + Signaler.soledad_password_change_ok + + Callback used to display a successfully changed password. + """ + logger.debug("Soledad password changed successfully.") self._set_password_change_status( self.tr("Password changed successfully."), success=True) @@ -234,18 +253,17 @@ class PreferencesWindow(QtGui.QDialog): self._set_changing_password(False) @QtCore.Slot(unicode) - def _change_password_problem(self, msg): + def _soledad_change_password_problem(self, msg): """ TRIGGERS: - self._backend.signaler.srp_password_change_error - self._backend.signaler.srp_password_change_badpw + Signaler.soledad_password_change_error 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") + logger.error("Error changing soledad password") self._set_password_change_status(msg, error=True) self._set_changing_password(False) @@ -418,12 +436,18 @@ class PreferencesWindow(QtGui.QDialog): 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) + sig.srp_password_change_ok.connect(self._srp_change_password_ok) - pwd_change_error = lambda: self._change_password_problem( + pwd_change_error = lambda: self._srp_change_password_problem( self.tr("There was a problem changing the password.")) sig.srp_password_change_error.connect(pwd_change_error) - pwd_change_badpw = lambda: self._change_password_problem( + pwd_change_badpw = lambda: self._srp_change_password_problem( self.tr("You did not enter a correct current password.")) sig.srp_password_change_badpw.connect(pwd_change_badpw) + + sig.soledad_password_change_ok.connect( + self._soledad_change_password_ok) + + sig.soledad_password_change_error.connect( + self._soledad_change_password_problem) -- cgit v1.2.3 From 10cf84e5f8be978574b7a7e1a145903b37801753 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 16 May 2014 16:17:14 -0300 Subject: Move waiting logic for imap stop to the backend. Also, improve quit and cleanup calls. --- src/leap/bitmask/gui/mainwindow.py | 107 +++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 57 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index e1527bbe..557f3828 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -21,7 +21,6 @@ import logging import socket import time -from threading import Condition from datetime import datetime from PySide import QtCore, QtGui @@ -93,10 +92,10 @@ class MainWindow(QtGui.QMainWindow): user_stopped_eip = False # We give EIP some time to come up before starting soledad anyway - EIP_TIMEOUT = 60000 # in milliseconds + EIP_START_TIMEOUT = 60000 # in milliseconds - # We give each service some time to come to a halt before forcing quit - SERVICE_STOP_TIMEOUT = 20 + # We give the services some time to a halt before forcing quit. + SERVICES_STOP_TIMEOUT = 20 def __init__(self, quit_callback, bypass_checks=False, start_hidden=False): """ @@ -262,9 +261,6 @@ class MainWindow(QtGui.QMainWindow): # XXX should connect to mail_conductor.start_mail_service instead self.soledad_ready.connect(self._start_smtp_bootstrapping) self.soledad_ready.connect(self._start_imap_service) - self.logout.connect(self._stop_imap_service) - self.logout.connect(self._stop_smtp_service) - ################################# end Qt Signals connection ######## init_platform() @@ -282,6 +278,8 @@ class MainWindow(QtGui.QMainWindow): self._mail_conductor = mail_conductor.MailConductor(self._backend) self._mail_conductor.connect_mail_signals(self._mail_status) + self.logout.connect(self._mail_conductor.stop_mail_services) + # Eip machine is a public attribute where the state machine for # the eip connection will be available to the different components. # Remember that this will not live in the +1600LOC mainwindow for @@ -1441,17 +1439,6 @@ class MainWindow(QtGui.QMainWindow): if self._provides_mx_and_enabled(): self._mail_conductor.start_smtp_service(download_if_needed=True) - # XXX --- should remove from here, and connecte directly to the state - # machine. - @QtCore.Slot() - def _stop_smtp_service(self): - """ - TRIGGERS: - self.logout - """ - # TODO call stop_mail_service - self._mail_conductor.stop_smtp_service() - ################################################################### # Service control methods: imap @@ -1478,20 +1465,6 @@ class MainWindow(QtGui.QMainWindow): if self._provides_mx_and_enabled(): start_fun() - @QtCore.Slot() - def _stop_imap_service(self): - """ - TRIGGERS: - self.logout - """ - cv = Condition() - cv.acquire() - # TODO call stop_mail_service - threads.deferToThread(self._mail_conductor.stop_imap_service, cv) - # and wait for it to be stopped - logger.debug('Waiting for imap service to stop.') - cv.wait(self.SERVICE_STOP_TIMEOUT) - # end service control methods (imap) ################################################################### @@ -1840,7 +1813,7 @@ class MainWindow(QtGui.QMainWindow): # we want to start soledad anyway after a certain timeout if eip # fails to come up QtCore.QTimer.singleShot( - self.EIP_TIMEOUT, + self.EIP_START_TIMEOUT, self._maybe_run_soledad_setup_checks) else: if not self._already_started_eip: @@ -2015,25 +1988,20 @@ class MainWindow(QtGui.QMainWindow): # cleanup and quit methods # - def _cleanup_pidfiles(self): + def _stop_services(self): """ - Removes lockfiles on a clean shutdown. - - Triggered after aboutToQuit signal. + Stop services and cancel ongoing actions (if any). """ - if IS_WIN: - WindowsLock.release_all_locks() + logger.debug('About to quit, doing cleanup.') - def _cleanup_and_quit(self): - """ - Call all the cleanup actions in a serialized way. - Should be called from the quit function. - """ - logger.debug('About to quit, doing cleanup...') + self._cancel_ongoing_defers() - self._stop_imap_service() + logger.debug('Stopping mail services') + self._backend.stop_imap_service() + self._backend.stop_smtp_service() if self._logged_user is not None: + logger.debug("Doing logout") self._backend.logout() logger.debug('Terminating vpn') @@ -2042,7 +2010,8 @@ class MainWindow(QtGui.QMainWindow): # 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) + # TODO: handle this, I commented this fix to merge 'cleanly' + # QtCore.QTimer.singleShot(3000, self._shutdown) def _shutdown(self): """ @@ -2061,7 +2030,8 @@ class MainWindow(QtGui.QMainWindow): def quit(self): """ - Cleanup and tidely close the main window before quitting. + Start the quit sequence and wait for services to finish. + Cleanup and close the main window before quitting. """ # TODO separate the shutting down of services from the # UI stuff. @@ -2074,22 +2044,45 @@ class MainWindow(QtGui.QMainWindow): self.tr('The app is quitting, please wait.')) # explicitly process events to display tooltip immediately - QtCore.QCoreApplication.processEvents() + QtCore.QCoreApplication.processEvents(0, 10) + + # Close other windows if any. + if self._wizard: + self._wizard.close() + + if self._logger_window: + self._logger_window.close() # Set this in case that the app is hidden QtGui.QApplication.setQuitOnLastWindowClosed(True) - self._cleanup_and_quit() + self._stop_services() - # 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: - self._wizard.close() + # call final_quit when imap is stopped + self._backend.signaler.imap_stopped.connect(self.final_quit) + # or if we reach the timeout + reactor.callLater(self.SERVICES_STOP_TIMEOUT, self._backend.stop) - if self._logger_window: - self._logger_window.close() + @QtCore.Slot() + def final_quit(self): + """ + Final steps to quit the app, starting from here we don't care about + running services or user interaction, just quitting. + """ + logger.debug('Final quit...') + + try: + # disconnect signal if we get here due a timeout. + self._backend.signaler.imap_stopped.disconnect(self.final_quit) + except RuntimeError: + pass # Signal was not connected + + # Remove lockfiles on a clean shutdown. + logger.debug('Cleaning pidfiles') + if IS_WIN: + WindowsLock.release_all_locks() + self._backend.stop() self.close() -- cgit v1.2.3 From baeb605e53c2e8a7dceee86035f6d4cc6b49e131 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 19 May 2014 17:51:58 -0300 Subject: Improve wait and quit process. Refactor logic from backend to the vpnprocess. --- src/leap/bitmask/gui/mainwindow.py | 69 ++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 26 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 557f3828..7cc88c1f 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -19,7 +19,6 @@ Main window for Bitmask. """ import logging import socket -import time from datetime import datetime @@ -87,6 +86,7 @@ class MainWindow(QtGui.QMainWindow): raise_window = QtCore.Signal([]) soledad_ready = QtCore.Signal([]) logout = QtCore.Signal([]) + all_services_stopped = QtCore.Signal() # We use this flag to detect abnormal terminations user_stopped_eip = False @@ -195,6 +195,12 @@ class MainWindow(QtGui.QMainWindow): self._logged_user = None self._logged_in_offline = False + # Set used to track the services being stopped and need wait. + self._services_being_stopped = {} + + # timeout object used to trigger quit + self._quit_timeout_callater = None + self._backend_connected_signals = {} self._backend_connect() @@ -1996,6 +2002,14 @@ class MainWindow(QtGui.QMainWindow): self._cancel_ongoing_defers() + self._services_being_stopped = {'imap', 'eip'} + + imap_stopped = lambda: self._remove_service('imap') + self._backend.signaler.imap_stopped.connect(imap_stopped) + + eip_stopped = lambda: self._remove_service('eip') + self._backend.signaler.eip_stopped.connect(eip_stopped) + logger.debug('Stopping mail services') self._backend.stop_imap_service() self._backend.stop_smtp_service() @@ -2007,27 +2021,6 @@ 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. - # TODO: handle this, I commented this fix to merge 'cleanly' - # 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): """ Start the quit sequence and wait for services to finish. @@ -2060,10 +2053,27 @@ class MainWindow(QtGui.QMainWindow): self._really_quit = True - # call final_quit when imap is stopped - self._backend.signaler.imap_stopped.connect(self.final_quit) + # call final quit when all the services are stopped + self.all_services_stopped.connect(self.final_quit) # or if we reach the timeout - reactor.callLater(self.SERVICES_STOP_TIMEOUT, self._backend.stop) + self._quit_timeout_callater = reactor.callLater( + self.SERVICES_STOP_TIMEOUT, self.final_quit) + + @QtCore.Slot() + def _remove_service(self, service): + """ + Remove the given service from the waiting list and check if we have + running services that we need to wait until we quit. + Emit self.all_services_stopped signal if we don't need to keep waiting. + + :param service: the service that we want to remove + :type service: str + """ + self._services_being_stopped.discard(service) + + if not self._services_being_stopped: + logger.debug("All services stopped.") + self.all_services_stopped.emit() @QtCore.Slot() def final_quit(self): @@ -2075,10 +2085,15 @@ class MainWindow(QtGui.QMainWindow): try: # disconnect signal if we get here due a timeout. - self._backend.signaler.imap_stopped.disconnect(self.final_quit) + self.all_services_stopped.disconnect(self.final_quit) except RuntimeError: pass # Signal was not connected + # Cancel timeout to avoid being called if we reached here through the + # signal + if self._quit_timeout_callater.active(): + self._quit_timeout_callater.cancel() + # Remove lockfiles on a clean shutdown. logger.debug('Cleaning pidfiles') if IS_WIN: @@ -2086,3 +2101,5 @@ class MainWindow(QtGui.QMainWindow): self._backend.stop() self.close() + + reactor.callLater(1, self._quit_callback) -- cgit v1.2.3 From a61889110118d04703b023936048b44517947516 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 21 May 2014 13:58:26 -0300 Subject: Rename backend methods for consistency. --- src/leap/bitmask/gui/mainwindow.py | 36 +++++++++++++++---------------- src/leap/bitmask/gui/preferenceswindow.py | 4 ++-- src/leap/bitmask/gui/wizard.py | 4 ++-- 3 files changed, 22 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 7cc88c1f..fc4b4d75 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -653,7 +653,7 @@ class MainWindow(QtGui.QMainWindow): # 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) + self._backend.eip_setup(default_provider, skip_network=True) def _backend_can_start_eip(self): """ @@ -1167,7 +1167,7 @@ class MainWindow(QtGui.QMainWindow): """ # XXX should rename this provider, name clash. provider = self._login_widget.get_selected_provider() - self._backend.setup_provider(provider) + self._backend.provider_setup(provider) @QtCore.Slot(dict) def _load_provider_config(self, data): @@ -1261,10 +1261,10 @@ 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() - self._backend.cancel_login() - self._backend.cancel_soledad_bootstrap() - self._backend.close_soledad() + self._backend.provider_cancel_setup() + self._backend.user_cancel_login() + self._backend.soledad_cancel_bootstrap() + self._backend.soledad_close() self._soledad_started = False @@ -1273,7 +1273,7 @@ class MainWindow(QtGui.QMainWindow): """ TRIGGERS: Signaler.prov_cancelled_setup fired by - self._backend.cancel_setup_provider() + self._backend.provider_cancel_setup() This method re-enables the login widget and display a message for the cancelled operation. @@ -1299,7 +1299,7 @@ class MainWindow(QtGui.QMainWindow): self._show_hide_unsupported_services() domain = self._provider_config.get_domain() - self._backend.login(domain, username, password) + self._backend.user_login(domain, username, password) else: logger.error(data[self._backend.ERROR_KEY]) self._login_problem_provider() @@ -1402,7 +1402,7 @@ class MainWindow(QtGui.QMainWindow): # this is mostly for internal use/debug for now. logger.warning("Sorry! Log-in at least one time.") return - self._backend.load_offline_soledad(full_user_id, password, uuid) + self._backend.soledad_load_offline(full_user_id, password, uuid) else: if self._logged_user is not None: domain = self._provider_config.get_domain() @@ -1609,7 +1609,7 @@ class MainWindow(QtGui.QMainWindow): # won't try the next time. self._settings.set_autostart_eip(True) - self._backend.start_eip() + self._backend.eip_start() @QtCore.Slot() def _on_eip_connection_aborted(self): @@ -1692,7 +1692,7 @@ class MainWindow(QtGui.QMainWindow): :type abnormal: bool """ self.user_stopped_eip = True - self._backend.stop_eip() + self._backend.eip_stop() self._set_eipstatus_off(False) self._already_started_eip = False @@ -1783,7 +1783,7 @@ class MainWindow(QtGui.QMainWindow): eip_status_label = eip_status_label.format(self._eip_name) self._eip_status.set_eip_status(eip_status_label, error=True) signal = qtsigs.connection_aborted_signal - self._backend.terminate_eip() + self._backend.eip_terminate() elif exitCode != 0 or not self.user_stopped_eip: eip_status_label = self.tr("{0} finished in an unexpected manner!") @@ -1813,7 +1813,7 @@ class MainWindow(QtGui.QMainWindow): self.tr("Starting...")) domain = self._login_widget.get_selected_provider() - self._backend.setup_eip(domain) + self._backend.eip_setup(domain) self._already_started_eip = True # we want to start soledad anyway after a certain timeout if eip @@ -1910,7 +1910,7 @@ class MainWindow(QtGui.QMainWindow): # XXX: If other defers are doing authenticated stuff, this # might conflict with those. CHECK! - self._backend.logout() + self._backend.user_logout() self.logout.emit() @QtCore.Slot() @@ -2011,15 +2011,15 @@ class MainWindow(QtGui.QMainWindow): self._backend.signaler.eip_stopped.connect(eip_stopped) logger.debug('Stopping mail services') - self._backend.stop_imap_service() - self._backend.stop_smtp_service() + self._backend.imap_stop_service() + self._backend.smtp_stop_service() if self._logged_user is not None: logger.debug("Doing logout") - self._backend.logout() + self._backend.user_logout() logger.debug('Terminating vpn') - self._backend.stop_eip(shutdown=True) + self._backend.eip_stop(shutdown=True) def quit(self): """ diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py index 77a3994f..47011a85 100644 --- a/src/leap/bitmask/gui/preferenceswindow.py +++ b/src/leap/bitmask/gui/preferenceswindow.py @@ -87,7 +87,7 @@ class PreferencesWindow(QtGui.QDialog): else: self._add_configured_providers() - self._backend.get_logged_in_status() + self._backend.user_get_logged_in_status() self._select_provider_by_name(domain) @@ -207,7 +207,7 @@ class PreferencesWindow(QtGui.QDialog): return self._set_changing_password(True) - self._backend.auth_change_password(current_password, new_password) + self._backend.user_change_password(current_password, new_password) @QtCore.Slot() def _srp_change_password_ok(self): diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index 020a58e2..316b2bff 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -257,7 +257,7 @@ class Wizard(QtGui.QWizard): if ok: self._set_register_status(self.tr("Starting registration...")) - self._backend.register_user(self._domain, username, password) + self._backend.user_register(self._domain, username, password) self._username = username self._password = password else: @@ -406,7 +406,7 @@ class Wizard(QtGui.QWizard): self.ui.lblNameResolution.setPixmap(self.QUESTION_ICON) self._provider_select_defer = self._backend.\ - setup_provider(self._domain) + provider_setup(self._domain) @QtCore.Slot(bool) def _skip_provider_checks(self, skip): -- cgit v1.2.3 From d0a9ecf0cba998b44a216c5cdf1800eea152f379 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 21 May 2014 18:18:58 -0300 Subject: Update username regex to support the same as webapp. Rename password util to credentials and add a username check helper. Move the username regexp to the credentials module. Closes #5695. --- src/leap/bitmask/gui/login.py | 5 ++--- src/leap/bitmask/gui/preferenceswindow.py | 4 ++-- src/leap/bitmask/gui/wizard.py | 25 ++++++++++++++++++------- 3 files changed, 22 insertions(+), 12 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/login.py b/src/leap/bitmask/gui/login.py index ac7ad878..f66e71d9 100644 --- a/src/leap/bitmask/gui/login.py +++ b/src/leap/bitmask/gui/login.py @@ -24,6 +24,7 @@ from ui_login import Ui_LoginWidget from leap.bitmask.config import flags from leap.bitmask.util import make_address +from leap.bitmask.util.credentials import USERNAME_REGEX from leap.bitmask.util.keyring_helpers import has_keyring from leap.bitmask.util.keyring_helpers import get_keyring from leap.common.check import leap_assert_type @@ -48,8 +49,6 @@ class LoginWidget(QtGui.QWidget): MAX_STATUS_WIDTH = 40 - BARE_USERNAME_REGEX = r"^[A-Za-z\d_]+$" - # Keyring KEYRING_KEY = "bitmask" @@ -87,7 +86,7 @@ class LoginWidget(QtGui.QWidget): self.ui.btnLogout.clicked.connect( self.logout) - username_re = QtCore.QRegExp(self.BARE_USERNAME_REGEX) + username_re = QtCore.QRegExp(USERNAME_REGEX) self.ui.lnUser.setValidator( QtGui.QRegExpValidator(username_re, self)) diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py index 47011a85..0a4c7f56 100644 --- a/src/leap/bitmask/gui/preferenceswindow.py +++ b/src/leap/bitmask/gui/preferenceswindow.py @@ -27,7 +27,7 @@ from PySide import QtCore, QtGui 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.bitmask.util.password import basic_password_checks +from leap.bitmask.util.credentials import password_checks from leap.bitmask.services import get_supported from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.services import get_service_display_name, MX_SERVICE @@ -198,7 +198,7 @@ class PreferencesWindow(QtGui.QDialog): new_password = self.ui.leNewPassword.text() new_password2 = self.ui.leNewPassword2.text() - ok, msg = basic_password_checks(username, new_password, new_password2) + ok, msg = password_checks(username, new_password, new_password2) if not ok: self._set_changing_password(False) diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index 316b2bff..ce45b431 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -29,8 +29,9 @@ from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.provider import get_provider_path from leap.bitmask.services import get_service_display_name, get_supported +from leap.bitmask.util.credentials import password_checks, username_checks +from leap.bitmask.util.credentials import USERNAME_REGEX from leap.bitmask.util.keyring_helpers import has_keyring -from leap.bitmask.util.password import basic_password_checks from ui_wizard import Ui_Wizard @@ -49,8 +50,6 @@ class Wizard(QtGui.QWizard): REGISTER_USER_PAGE = 4 SERVICES_PAGE = 5 - BARE_USERNAME_REGEX = r"^[A-Za-z\d_]+$" - def __init__(self, backend, bypass_checks=False): """ Constructor for the main Wizard. @@ -118,7 +117,7 @@ class Wizard(QtGui.QWizard): self.ui.rbExistingProvider.toggled.connect(self._skip_provider_checks) - usernameRe = QtCore.QRegExp(self.BARE_USERNAME_REGEX) + usernameRe = QtCore.QRegExp(USERNAME_REGEX) self.ui.lblUser.setValidator( QtGui.QRegExpValidator(usernameRe, self)) @@ -231,6 +230,12 @@ class Wizard(QtGui.QWizard): if reset: self._reset_provider_check() + def _focus_username(self): + """ + Focus at the username lineedit for the registration page + """ + self.ui.lblUser.setFocus() + def _focus_password(self): """ Focuses at the password lineedit for the registration page @@ -253,16 +258,22 @@ class Wizard(QtGui.QWizard): password = self.ui.lblPassword.text() password2 = self.ui.lblPassword2.text() - ok, msg = basic_password_checks(username, password, password2) - if ok: + user_ok, msg = username_checks(username) + if user_ok: + pass_ok, msg = password_checks(username, password, password2) + + if user_ok and pass_ok: self._set_register_status(self.tr("Starting registration...")) self._backend.user_register(self._domain, username, password) self._username = username self._password = password else: + if user_ok: + self._focus_password() + else: + self._focus_username() self._set_register_status(msg, error=True) - self._focus_password() self.ui.btnRegister.setEnabled(True) def _set_registration_fields_visibility(self, visible): -- cgit v1.2.3 From 100848992f96f8edd32433dd8f5efc7dc1230079 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 19 May 2014 11:11:31 -0500 Subject: do not tear fw down during restarts --- src/leap/bitmask/gui/mainwindow.py | 8 ++++---- 1 file changed, 4 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 fc4b4d75..201a24ec 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1680,7 +1680,7 @@ class MainWindow(QtGui.QMainWindow): self._set_eipstatus_off() @QtCore.Slot() - def _stop_eip(self): + def _stop_eip(self, restart=False): """ TRIGGERS: self._eip_connection.qtsigs.do_disconnect_signal (via state machine) @@ -1691,8 +1691,8 @@ class MainWindow(QtGui.QMainWindow): :param abnormal: whether this was an abnormal termination. :type abnormal: bool """ - self.user_stopped_eip = True - self._backend.eip_stop() + self.user_stopped_eip = not restart + self._backend.eip_stop(restart=restart) self._set_eipstatus_off(False) self._already_started_eip = False @@ -1731,7 +1731,7 @@ class MainWindow(QtGui.QMainWindow): """ # for some reason, emitting the do_disconnect/do_connect # signals hangs the UI. - self._stop_eip() + self._stop_eip(restart=True) QtCore.QTimer.singleShot(2000, self._start_EIP) def _set_eipstatus_off(self, error=True): -- cgit v1.2.3 From 37353a2c57a759e160a7060c412b15d30ebde4bb Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 22 May 2014 17:34:24 -0300 Subject: Refactor cleanup, ProviderConfig to backend. --- src/leap/bitmask/gui/mainwindow.py | 207 +++++++++++++----------------- src/leap/bitmask/gui/preferenceswindow.py | 114 ++++++++-------- src/leap/bitmask/gui/wizard.py | 73 ++++++----- 3 files changed, 183 insertions(+), 211 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 201a24ec..4d79305e 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -30,7 +30,6 @@ from leap.bitmask import __version__ as VERSION from leap.bitmask import __version_hash__ as VERSION_HASH from leap.bitmask.config import flags from leap.bitmask.config.leapsettings import LeapSettings -from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.gui import statemachines from leap.bitmask.gui.advanced_key_management import AdvancedKeyManagement @@ -43,7 +42,6 @@ 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 from leap.bitmask.platform_init.initializers import init_platform @@ -64,7 +62,6 @@ if IS_WIN: from leap.bitmask.platform_init.locks import WindowsLock from leap.bitmask.platform_init.locks import raise_window_ack -from leap.common.check import leap_assert from leap.common.events import register from leap.common.events import events_pb2 as proto @@ -178,15 +175,6 @@ class MainWindow(QtGui.QMainWindow): 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 - # provider_config in here - self._provider_config = self._backend.get_provider_config() - - # Used for automatic start of EIP - self._provisional_provider_config = ProviderConfig() - self._already_started_eip = False self._soledad_started = False @@ -247,6 +235,8 @@ class MainWindow(QtGui.QMainWindow): self._ui_mx_visible = True self._ui_eip_visible = True + self._provider_details = None + # last minute UI manipulations self._center_window() @@ -383,6 +373,9 @@ class MainWindow(QtGui.QMainWindow): self._connect_and_track(sig.prov_cancelled_setup, self._set_login_cancelled) + self._connect_and_track(sig.prov_get_details, + self._provider_get_details) + # Login signals self._connect_and_track(sig.srp_auth_ok, self._authentication_finished) @@ -430,9 +423,14 @@ class MainWindow(QtGui.QMainWindow): sig.backend_bad_call.connect(self._backend_bad_call) + sig.prov_check_api_certificate.connect(self._get_provider_details) + sig.prov_unsupported_client.connect(self._needs_update) sig.prov_unsupported_api.connect(self._incompatible_api) + sig.prov_get_all_services.connect( + self._provider_get_all_services) + # EIP start signals sig.eip_openvpn_already_running.connect( self._on_eip_openvpn_already_running) @@ -597,12 +595,13 @@ 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() + details = self._provider_details + mx_provided = False + if details is not None: + mx_provided = MX_SERVICE in details - akm = AdvancedKeyManagement(self, has_mx, logged_user, + # XXX: handle differently not logged in user? + akm = AdvancedKeyManagement(self, mx_provided, logged_user, self._keymanager, self._soledad_started) akm.show() @@ -618,8 +617,7 @@ class MainWindow(QtGui.QMainWindow): user = self._login_widget.get_user() prov = self._login_widget.get_selected_provider() preferences = PreferencesWindow( - self, self._backend, self._provider_config, - self._soledad_started, user, prov) + self, self._backend, self._soledad_started, user, prov) self.soledad_ready.connect(preferences.set_soledad_ready) preferences.show() @@ -857,16 +855,9 @@ class MainWindow(QtGui.QMainWindow): """ providers = self._settings.get_configured_providers() - services = set() - - for prov in providers: - provider_config = ProviderConfig() - loaded = provider_config.load( - provider.get_provider_path(prov)) - if loaded: - for service in provider_config.get_services(): - services.add(service) + self._backend.provider_get_all_services(providers) + def _provider_get_all_services(self, services): self._set_eip_visible(EIP_SERVICE in services) self._set_mx_visible(MX_SERVICE in services) @@ -904,14 +895,11 @@ class MainWindow(QtGui.QMainWindow): """ Set the login label to reflect offline status. """ - if self._logged_in_offline: - provider = "" - else: + provider = "" + if not self._logged_in_offline: provider = self.ui.lblLoginProvider.text() - self.ui.lblLoginProvider.setText( - provider + - self.tr(" (offline mode)")) + self.ui.lblLoginProvider.setText(provider + self.tr(" (offline mode)")) # # systray @@ -1165,9 +1153,8 @@ class MainWindow(QtGui.QMainWindow): provider configuration if it's not present, otherwise will emit the corresponding signals inmediately """ - # XXX should rename this provider, name clash. - provider = self._login_widget.get_selected_provider() - self._backend.provider_setup(provider) + domain = self._login_widget.get_selected_provider() + self._backend.provider_setup(domain) @QtCore.Slot(dict) def _load_provider_config(self, data): @@ -1175,12 +1162,11 @@ class MainWindow(QtGui.QMainWindow): 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 - part of the bootstrapping sequence + Once the provider config has been downloaded, start the second + part of the bootstrapping sequence. :param data: result from the last stage of the - run_provider_select_checks + backend.provider_setup() :type data: dict """ if data[self._backend.PASSED_KEY]: @@ -1222,7 +1208,6 @@ class MainWindow(QtGui.QMainWindow): self._set_label_offline() 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() @@ -1290,15 +1275,13 @@ class MainWindow(QtGui.QMainWindow): Once the provider configuration is loaded, this starts the SRP authentication """ - leap_assert(self._provider_config, "We need a provider config!") - if data[self._backend.PASSED_KEY]: username = self._login_widget.get_user() password = self._login_widget.get_password() self._show_hide_unsupported_services() - domain = self._provider_config.get_domain() + domain = self._login_widget.get_selected_provider() self._backend.user_login(domain, username, password) else: logger.error(data[self._backend.ERROR_KEY]) @@ -1317,7 +1300,7 @@ class MainWindow(QtGui.QMainWindow): self._logged_user = self._login_widget.get_user() user = self._logged_user - domain = self._provider_config.get_domain() + domain = self._login_widget.get_selected_provider() full_user_id = make_address(user, domain) self._mail_conductor.userid = full_user_id self._start_eip_bootstrap() @@ -1331,7 +1314,7 @@ class MainWindow(QtGui.QMainWindow): sig.soledad_bootstrap_failed.connect(lambda: btn_enabled(True)) sig.soledad_bootstrap_finished.connect(lambda: btn_enabled(True)) - if not self._get_best_provider_config().provides_mx(): + if not MX_SERVICE in self._provider_details.services: self._set_mx_visible(False) def _start_eip_bootstrap(self): @@ -1341,11 +1324,10 @@ class MainWindow(QtGui.QMainWindow): """ self._login_widget.logged_in() - provider = self._provider_config.get_domain() - self.ui.lblLoginProvider.setText(provider) + domain = self._login_widget.get_selected_provider() + self.ui.lblLoginProvider.setText(domain) - self._enabled_services = self._settings.get_enabled_services( - self._provider_config.get_domain()) + self._enabled_services = self._settings.get_enabled_services(domain) # TODO separate UI from logic. if self._provides_mx_and_enabled(): @@ -1355,6 +1337,30 @@ class MainWindow(QtGui.QMainWindow): self._maybe_start_eip() + @QtCore.Slot() + def _get_provider_details(self): + """ + TRIGGERS: + prov_check_api_certificate + + Set the attributes to know if the EIP and MX services are supported + and enabled. + This is triggered right after the provider has been set up. + """ + domain = self._login_widget.get_selected_provider() + lang = QtCore.QLocale.system().name() + self._backend.provider_get_details(domain, lang) + + @QtCore.Slot() + def _provider_get_details(self, details): + """ + Set the details for the just downloaded provider. + + :param details: the details of the provider. + :type details: ProviderConfigLight + """ + self._provider_details = details + def _provides_mx_and_enabled(self): """ Defines if the current provider provides mx and if we have it enabled. @@ -1362,9 +1368,15 @@ class MainWindow(QtGui.QMainWindow): :returns: True if provides and is enabled, False otherwise :rtype: bool """ - provider_config = self._get_best_provider_config() - return (provider_config.provides_mx() and - MX_SERVICE in self._enabled_services) + domain = self._login_widget.get_selected_provider() + enabled_services = self._settings.get_enabled_services(domain) + + mx_enabled = MX_SERVICE in enabled_services + mx_provided = False + if self._provider_details is not None: + mx_provided = MX_SERVICE in self._provider_details.services + + return mx_enabled and mx_provided def _provides_eip_and_enabled(self): """ @@ -1373,16 +1385,23 @@ class MainWindow(QtGui.QMainWindow): :returns: True if provides and is enabled, False otherwise :rtype: bool """ - provider_config = self._get_best_provider_config() - return (provider_config.provides_eip() and - EIP_SERVICE in self._enabled_services) + domain = self._login_widget.get_selected_provider() + enabled_services = self._settings.get_enabled_services(domain) + + eip_enabled = EIP_SERVICE in enabled_services + eip_provided = False + if self._provider_details is not None: + eip_provided = EIP_SERVICE in self._provider_details.services + + return eip_enabled and eip_provided def _maybe_run_soledad_setup_checks(self): """ Conditionally start Soledad. """ # TODO split. - if not self._provides_mx_and_enabled(): + if not self._provides_mx_and_enabled() and not flags.OFFLINE: + logger.debug("Does not provides and enabled MX") return username = self._login_widget.get_user() @@ -1390,9 +1409,6 @@ class MainWindow(QtGui.QMainWindow): provider_domain = self._login_widget.get_selected_provider() if flags.OFFLINE: - self._provisional_provider_config.load( - provider.get_provider_path(provider_domain)) - full_user_id = make_address(username, provider_domain) uuid = self._settings.get_uuid(full_user_id) self._mail_conductor.userid = full_user_id @@ -1405,7 +1421,7 @@ class MainWindow(QtGui.QMainWindow): self._backend.soledad_load_offline(full_user_id, password, uuid) else: if self._logged_user is not None: - domain = self._provider_config.get_domain() + domain = self._login_widget.get_selected_provider() self._backend.soledad_bootstrap(username, domain, password) ################################################################### @@ -1457,19 +1473,8 @@ class MainWindow(QtGui.QMainWindow): # TODO in the OFFLINE mode we should also modify the rules # in the mail state machine so it shows that imap is active # (but not smtp since it's not yet ready for offline use) - start_fun = self._mail_conductor.start_imap_service - if flags.OFFLINE: - provider_domain = self._login_widget.get_selected_provider() - self._provider_config.load( - provider.get_provider_path(provider_domain)) - provides_mx = self._provider_config.provides_mx() - - if flags.OFFLINE and provides_mx: - start_fun() - return - - if self._provides_mx_and_enabled(): - start_fun() + if self._provides_mx_and_enabled() or flags.OFFLINE: + self._mail_conductor.start_imap_service() # end service control methods (imap) @@ -1519,9 +1524,7 @@ class MainWindow(QtGui.QMainWindow): """ self._eip_connection.qtsigs.connected_signal.emit() - provider_config = self._get_best_provider_config() - domain = provider_config.get_domain() - + domain = self._login_widget.get_selected_provider() self._eip_status.set_provider(domain) self._settings.set_defaultprovider(domain) self._already_started_eip = True @@ -1582,19 +1585,8 @@ class MainWindow(QtGui.QMainWindow): self._enabled_services = settings.get_enabled_services( default_provider) - loaded = self._provisional_provider_config.load( - provider.get_provider_path(default_provider)) - 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. + if settings.get_autostart_eip(): self._maybe_start_eip() - 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." % - (default_provider,)) @QtCore.Slot() def _start_EIP(self): @@ -1700,11 +1692,12 @@ class MainWindow(QtGui.QMainWindow): logger.debug('Setting autostart to: False') self._settings.set_autostart_eip(False) - if self._logged_user: - self._eip_status.set_provider( - make_address( - self._logged_user, - self._get_best_provider_config().get_domain())) + user = self._logged_user + if user: + domain = self._login_widget.get_selected_provider() + full_user_id = make_address(user, domain) + self._eip_status.set_provider(full_user_id) + self._eip_status.eip_stopped() @QtCore.Slot() @@ -1874,30 +1867,6 @@ class MainWindow(QtGui.QMainWindow): # end of EIP methods --------------------------------------------- - def _get_best_provider_config(self): - """ - Returns the best ProviderConfig to use at a moment. We may - have to use self._provider_config or - self._provisional_provider_config depending on the start - status. - - :rtype: ProviderConfig - """ - # TODO move this out of gui. - leap_assert(self._provider_config is not None or - self._provisional_provider_config is not None, - "We need a provider config") - - provider_config = None - if self._provider_config.loaded(): - provider_config = self._provider_config - elif self._provisional_provider_config.loaded(): - provider_config = self._provisional_provider_config - else: - leap_assert(False, "We could not find any usable ProviderConfig.") - - return provider_config - @QtCore.Slot() def _logout(self): """ diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py index 0a4c7f56..c67052f3 100644 --- a/src/leap/bitmask/gui/preferenceswindow.py +++ b/src/leap/bitmask/gui/preferenceswindow.py @@ -24,12 +24,9 @@ from functools import partial from PySide import QtCore, QtGui -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.bitmask.util.credentials import password_checks -from leap.bitmask.services import get_supported -from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.services import get_service_display_name, MX_SERVICE logger = logging.getLogger(__name__) @@ -41,15 +38,12 @@ class PreferencesWindow(QtGui.QDialog): """ preferences_saved = QtCore.Signal() - def __init__(self, parent, backend, provider_config, soledad_started, - username, domain): + def __init__(self, parent, backend, soledad_started, username, domain): """ :param parent: parent object of the PreferencesWindow. :parent type: QWidget :param backend: Backend being used :type backend: Backend - :param provider_config: ProviderConfig object. - :type provider_config: ProviderConfig :param soledad_started: whether soledad has started or not :type soledad_started: bool :param username: the user set in the login widget @@ -62,7 +56,6 @@ class PreferencesWindow(QtGui.QDialog): self._backend = backend self._settings = LeapSettings() - self._provider_config = provider_config self._soledad_started = soledad_started self._username = username self._domain = domain @@ -99,31 +92,7 @@ class PreferencesWindow(QtGui.QDialog): 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 not self._soledad_started: - 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) + self._backend.provider_provides_mx() @QtCore.Slot() def _not_logged_in(self): @@ -138,6 +107,44 @@ class PreferencesWindow(QtGui.QDialog): self._set_password_change_status(msg) self.ui.gbPasswordChange.setEnabled(False) + @QtCore.Slot() + def _provides_mx(self): + """ + TRIGGERS: + Signaler.prov_provides_mx + + Actions to perform if the provider provides MX. + """ + pw_enabled = True + enabled_services = self._settings.get_enabled_services(self._domain) + mx_name = get_service_display_name(MX_SERVICE) + + 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 not self._soledad_started: + 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) + + @QtCore.Slot() + def _not_provides_mx(self): + """ + TRIGGERS: + Signaler.prov_not_provides_mx + + Actions to perform if the provider does not provides MX. + """ + self.ui.gbPasswordChange.setEnabled(False) + @QtCore.Slot() def set_soledad_ready(self): """ @@ -339,8 +346,7 @@ class PreferencesWindow(QtGui.QDialog): TRIGGERS: self.ui.cbProvidersServices.currentIndexChanged[unicode] - Loads the services that the provider provides into the UI for - the user to enable or disable. + Fill the services list with the selected provider's services. :param domain: the domain of the provider to load services from. :type domain: str @@ -351,10 +357,6 @@ class PreferencesWindow(QtGui.QDialog): if not domain: return - provider_config = self._get_provider_config(domain) - if provider_config is None: - return - # set the proper connection for the 'save' button try: self.ui.pbSaveServices.clicked.disconnect() @@ -364,7 +366,21 @@ class PreferencesWindow(QtGui.QDialog): save_services = partial(self._save_enabled_services, domain) self.ui.pbSaveServices.clicked.connect(save_services) - services = get_supported(provider_config.get_services()) + self._backend.provider_get_supported_services(domain) + + @QtCore.Slot(str) + def _load_services(self, services): + """ + TRIGGERS: + self.ui.cbProvidersServices.currentIndexChanged[unicode] + + Loads the services that the provider provides into the UI for + the user to enable or disable. + + :param domain: the domain of the provider to load services from. + :type domain: str + """ + domain = self.ui.cbProvidersServices.currentText() services_conf = self._settings.get_enabled_services(domain) # discard changes if other provider is selected @@ -412,27 +428,15 @@ class PreferencesWindow(QtGui.QDialog): self._set_providers_services_status(msg, success=True) self.preferences_saved.emit() - def _get_provider_config(self, domain): - """ - Helper to return a valid Provider Config from the domain name. - - :param domain: the domain name of the provider. - :type domain: str - - :rtype: ProviderConfig or None if there is a problem loading the config - """ - provider_config = ProviderConfig() - if not provider_config.load(get_provider_path(domain)): - provider_config = None - - return provider_config - def _backend_connect(self): """ Helper to connect to backend signals """ sig = self._backend.signaler + sig.prov_provides_mx.connect(self._provides_mx) + sig.prov_get_supported_services.connect(self._load_services) + sig.srp_status_logged_in.connect(self._is_logged_in) sig.srp_status_not_logged_in.connect(self._not_logged_in) diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index ce45b431..4d774907 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -26,8 +26,6 @@ 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 from leap.bitmask.services import get_service_display_name, get_supported from leap.bitmask.util.credentials import password_checks, username_checks from leap.bitmask.util.credentials import USERNAME_REGEX @@ -88,10 +86,9 @@ class Wizard(QtGui.QWizard): self._backend_connect() self._domain = None - # HACK!! We need provider_config for the time being, it'll be - # removed - self._provider_config = ( - self._backend._components["provider"]._provider_config) + + # this details are set when the provider download is complete. + self._provider_details = None # We will store a reference to the defers for eventual use # (eg, to cancel them) but not doing anything with them right now. @@ -513,10 +510,12 @@ class Wizard(QtGui.QWizard): check. Since this check is the last of this set, it also completes the page if passed """ - if self._provider_config.load(get_provider_path(self._domain)): + if data[self._backend.PASSED_KEY]: self._complete_task(data, self.ui.lblProviderInfo, True, self.SELECT_PROVIDER_PAGE) self._provider_checks_ok = True + lang = QtCore.QLocale.system().name() + self._backend.provider_get_details(self._domain, lang) else: new_data = { self._backend.PASSED_KEY: False, @@ -538,6 +537,16 @@ class Wizard(QtGui.QWizard): else: self.ui.cbProviders.setEnabled(True) + @QtCore.Slot() + def _provider_get_details(self, details): + """ + Set the details for the just downloaded provider. + + :param details: the details of the provider. + :type details: ProviderConfigLight + """ + self._provider_details = details + @QtCore.Slot(dict) def _download_ca_cert(self, data): """ @@ -605,11 +614,9 @@ class Wizard(QtGui.QWizard): the user to enable or disable. """ self.ui.grpServices.setTitle( - self.tr("Services by %s") % - (self._provider_config.get_name(),)) + self.tr("Services by {0}").format(self._provider_details.name)) - services = get_supported( - self._provider_config.get_services()) + services = get_supported(self._provider_details.services) for service in services: try: @@ -652,38 +659,31 @@ class Wizard(QtGui.QWizard): if not self._provider_setup_ok: self._reset_provider_setup() sub_title = self.tr("Gathering configuration options for {0}") - sub_title = sub_title.format(self._provider_config.get_name()) + sub_title = sub_title.format(self._provider_details.name) self.page(pageId).setSubTitle(sub_title) self.ui.lblDownloadCaCert.setPixmap(self.QUESTION_ICON) self._provider_setup_defer = self._backend.\ provider_bootstrap(self._domain) if pageId == self.PRESENT_PROVIDER_PAGE: - self.page(pageId).setSubTitle(self.tr("Description of services " - "offered by %s") % - (self._provider_config - .get_name(),)) - - lang = QtCore.QLocale.system().name() - self.ui.lblProviderName.setText( - "%s" % - (self._provider_config.get_name(lang=lang),)) - self.ui.lblProviderURL.setText( - "https://%s" % (self._provider_config.get_domain(),)) - self.ui.lblProviderDesc.setText( - "%s" % - (self._provider_config.get_description(lang=lang),)) - - self.ui.lblServicesOffered.setText(self._provider_config - .get_services_string()) - self.ui.lblProviderPolicy.setText(self._provider_config - .get_enrollment_policy()) + sub_title = self.tr("Description of services offered by {0}") + sub_title = sub_title.format(self._provider_details.name) + self.page(pageId).setSubTitle(sub_title) + + details = self._provider_details + name = "{0}".format(details.name) + domain = "https://{0}".format(details.domain) + description = "{0}".format(details.description) + self.ui.lblProviderName.setText(name) + self.ui.lblProviderURL.setText(domain) + self.ui.lblProviderDesc.setText(description) + self.ui.lblServicesOffered.setText(details.services_string) + self.ui.lblProviderPolicy.setText(details.enrollment_policy) if pageId == self.REGISTER_USER_PAGE: - self.page(pageId).setSubTitle(self.tr("Register a new user with " - "%s") % - (self._provider_config - .get_name(),)) + sub_title = self.tr("Register a new user with {0}") + sub_title = sub_title.format(self._provider_details.name) + self.page(pageId).setSubTitle(sub_title) self.ui.chkRemember.setVisible(False) if pageId == self.SERVICES_PAGE: @@ -706,8 +706,6 @@ class Wizard(QtGui.QWizard): if self.currentPage() == self.page(self.SELECT_PROVIDER_PAGE): if self._use_existing_provider: self._domain = self.ui.cbProviders.currentText() - self._provider_config = ProviderConfig.get_provider_config( - self._domain) if self._show_register: return self.REGISTER_USER_PAGE else: @@ -732,6 +730,7 @@ class Wizard(QtGui.QWizard): sig.prov_name_resolution.connect(self._name_resolution) sig.prov_https_connection.connect(self._https_connection) sig.prov_download_provider_info.connect(self._download_provider_info) + sig.prov_get_details.connect(self._provider_get_details) sig.prov_download_ca_cert.connect(self._download_ca_cert) sig.prov_check_ca_fingerprint.connect(self._check_ca_fingerprint) -- cgit v1.2.3 From f330589af3e8752dd9e948b1bbd171f503780a91 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 27 May 2014 13:28:56 -0300 Subject: Refactor cleanup and move Keymanager to backend. --- src/leap/bitmask/gui/advanced_key_management.py | 237 ++++++++++++++---------- src/leap/bitmask/gui/mainwindow.py | 12 +- 2 files changed, 146 insertions(+), 103 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 1681caca..b3a4ed8e 100644 --- a/src/leap/bitmask/gui/advanced_key_management.py +++ b/src/leap/bitmask/gui/advanced_key_management.py @@ -19,10 +19,8 @@ Advanced Key Management """ import logging -from PySide import QtGui +from PySide import QtCore, QtGui -from leap.keymanager import openpgp -from leap.keymanager.errors import KeyAddressMismatch, KeyFingerprintMismatch from leap.bitmask.services import get_service_display_name, MX_SERVICE from ui_advanced_key_management import Ui_AdvancedKeyManagement @@ -33,7 +31,7 @@ class AdvancedKeyManagement(QtGui.QDialog): """ Advanced Key Management """ - def __init__(self, parent, has_mx, user, keymanager, soledad_started): + def __init__(self, parent, has_mx, user, backend, soledad_started): """ :param parent: parent object of AdvancedKeyManagement. :parent type: QWidget @@ -42,8 +40,8 @@ class AdvancedKeyManagement(QtGui.QDialog): :type has_mx: bool :param user: the current logged in user. :type user: unicode - :param keymanager: the existing keymanager instance - :type keymanager: KeyManager + :param backend: Backend being used + :type backend: Backend :param soledad_started: whether soledad has started or not :type soledad_started: bool """ @@ -75,16 +73,12 @@ class AdvancedKeyManagement(QtGui.QDialog): # "existing e-mails.") # self.ui.lblStatus.setText(msg) - self._keymanager = keymanager - - self._key = keymanager.get_key(user, openpgp.OpenPGPKey) - self._key_priv = keymanager.get_key( - user, openpgp.OpenPGPKey, private=True) + self._user = user + self._backend = backend + self._backend_connect() # show current key information self.ui.leUser.setText(user) - self.ui.leKeyID.setText(self._key.key_id) - self.ui.leFingerprint.setText(self._key.fingerprint) # set up connections self.ui.pbImportKeys.clicked.connect(self._import_keys) @@ -94,7 +88,15 @@ class AdvancedKeyManagement(QtGui.QDialog): self.ui.twPublicKeys.horizontalHeader().setResizeMode( 0, QtGui.QHeaderView.Stretch) - self._list_keys() + self._backend.keymanager_get_key_details(user) + self._backend.keymanager_list_keys() + + def _keymanager_key_details(self, details): + """ + Set the current user's key details into the gui. + """ + self.ui.leKeyID.setText(details[0]) + self.ui.leFingerprint.setText(details[1]) def _disable_ui(self, msg): """ @@ -113,53 +115,11 @@ class AdvancedKeyManagement(QtGui.QDialog): Imports the user's key pair. Those keys need to be ascii armored. """ - fileName, filtr = QtGui.QFileDialog.getOpenFileName( + file_name, filtr = QtGui.QFileDialog.getOpenFileName( self, self.tr("Open keys file"), options=QtGui.QFileDialog.DontUseNativeDialog) - if fileName: - new_key = '' - try: - with open(fileName, 'r') as keys_file: - new_key = keys_file.read() - except IOError as e: - logger.error("IOError importing key. {0!r}".format(e)) - QtGui.QMessageBox.critical( - self, self.tr("Input/Output error"), - self.tr("There was an error accessing the file.\n" - "Import canceled.")) - return - - keymanager = self._keymanager - try: - public_key, private_key = keymanager.parse_openpgp_ascii_key( - new_key) - except (KeyAddressMismatch, KeyFingerprintMismatch) as e: - logger.error(repr(e)) - QtGui.QMessageBox.warning( - self, self.tr("Data mismatch"), - self.tr("The public and private key should have the " - "same address and fingerprint.\n" - "Import canceled.")) - return - - if public_key is None or private_key is None: - QtGui.QMessageBox.warning( - self, self.tr("Missing key"), - self.tr("You need to provide the public AND private " - "key in the same file.\n" - "Import canceled.")) - return - - if public_key.address != self._key.address: - logger.error("The key does not match the ID") - QtGui.QMessageBox.warning( - self, self.tr("Address mismatch"), - self.tr("The identity for the key needs to be the same " - "as your user address.\n" - "Import canceled.")) - return - + if file_name: question = self.tr("Are you sure that you want to replace " "the current key pair whith the imported?") res = QtGui.QMessageBox.question( @@ -167,61 +127,152 @@ class AdvancedKeyManagement(QtGui.QDialog): QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.No) # default No - if res == QtGui.QMessageBox.No: - return + if res == QtGui.QMessageBox.Yes: + self._backend.keymanager_import_keys(self._user, file_name) + else: + logger.debug('Import canceled by the user.') - keymanager.delete_key(self._key) - keymanager.delete_key(self._key_priv) - keymanager.put_key(public_key) - keymanager.put_key(private_key) - keymanager.send_key(openpgp.OpenPGPKey) + @QtCore.Slot() + def _keymanager_import_ok(self): + """ + TRIGGERS: + Signaler.keymanager_import_ok - logger.debug('Import ok') + Notify the user that the key import went OK. + """ + QtGui.QMessageBox.information( + self, self.tr("Import Successful"), + self.tr("The key pair was imported successfully.")) - QtGui.QMessageBox.information( - self, self.tr("Import Successful"), - self.tr("The key pair was imported successfully.")) - else: - logger.debug('Import canceled by the user.') + @QtCore.Slot() + def _import_ioerror(self): + """ + TRIGGERS: + Signaler.keymanager_import_ioerror + + Notify the user that the key import had an IOError problem. + """ + QtGui.QMessageBox.critical( + self, self.tr("Input/Output error"), + self.tr("There was an error accessing the file.\n" + "Import canceled.")) + + @QtCore.Slot() + def _import_datamismatch(self): + """ + TRIGGERS: + Signaler.keymanager_import_datamismatch + + Notify the user that the key import had an data mismatch problem. + """ + QtGui.QMessageBox.warning( + self, self.tr("Data mismatch"), + self.tr("The public and private key should have the " + "same address and fingerprint.\n" + "Import canceled.")) + + @QtCore.Slot() + def _import_missingkey(self): + """ + TRIGGERS: + Signaler.keymanager_import_missingkey + + Notify the user that the key import failed due a missing key. + """ + QtGui.QMessageBox.warning( + self, self.tr("Missing key"), + self.tr("You need to provide the public AND private " + "key in the same file.\n" + "Import canceled.")) + + @QtCore.Slot() + def _import_addressmismatch(self): + """ + TRIGGERS: + Signaler.keymanager_import_addressmismatch + + Notify the user that the key import failed due an address mismatch. + """ + QtGui.QMessageBox.warning( + self, self.tr("Address mismatch"), + self.tr("The identity for the key needs to be the same " + "as your user address.\n" + "Import canceled.")) def _export_keys(self): """ Exports the user's key pair. """ - fileName, filtr = QtGui.QFileDialog.getSaveFileName( + file_name, filtr = QtGui.QFileDialog.getSaveFileName( self, self.tr("Save keys file"), options=QtGui.QFileDialog.DontUseNativeDialog) - if fileName: - try: - with open(fileName, 'w') as keys_file: - keys_file.write(self._key.key_data) - keys_file.write(self._key_priv.key_data) - - logger.debug('Export ok') - QtGui.QMessageBox.information( - self, self.tr("Export Successful"), - self.tr("The key pair was exported successfully.\n" - "Please, store your private key in a safe place.")) - except IOError as e: - logger.error("IOError exporting key. {0!r}".format(e)) - QtGui.QMessageBox.critical( - self, self.tr("Input/Output error"), - self.tr("There was an error accessing the file.\n" - "Export canceled.")) - return + if file_name: + self._backend.keymanager_export_keys(self._user, file_name) else: logger.debug('Export canceled by the user.') - def _list_keys(self): + @QtCore.Slot() + def _keymanager_export_ok(self): + """ + TRIGGERS: + Signaler.keymanager_export_ok + + Notify the user that the key export went OK. """ - Loads all the public keys stored in the local db to the keys table. + QtGui.QMessageBox.information( + self, self.tr("Export Successful"), + self.tr("The key pair was exported successfully.\n" + "Please, store your private key in a safe place.")) + + @QtCore.Slot() + def _keymanager_export_error(self): + """ + TRIGGERS: + Signaler.keymanager_export_error + + Notify the user that the key export didn't go well. + """ + QtGui.QMessageBox.critical( + self, self.tr("Input/Output error"), + self.tr("There was an error accessing the file.\n" + "Export canceled.")) + + @QtCore.Slot() + def _keymanager_keys_list(self, keys): """ - keys = self._keymanager.get_all_keys_in_local_db() + TRIGGERS: + Signaler.keymanager_keys_list + Load the keys given as parameter in the table. + + :param keys: the list of keys to load. + :type keys: list + """ keys_table = self.ui.twPublicKeys + for key in keys: row = keys_table.rowCount() keys_table.insertRow(row) keys_table.setItem(row, 0, QtGui.QTableWidgetItem(key.address)) keys_table.setItem(row, 1, QtGui.QTableWidgetItem(key.key_id)) + + def _backend_connect(self): + """ + Connect to backend signals. + """ + sig = self._backend.signaler + + sig.keymanager_export_ok.connect(self._keymanager_export_ok) + sig.keymanager_export_error.connect(self._keymanager_export_error) + sig.keymanager_keys_list.connect(self._keymanager_keys_list) + + sig.keymanager_key_details.connect(self._keymanager_key_details) + + sig.keymanager_import_ok.connect(self._keymanager_import_ok) + + sig.keymanager_import_ioerror.connect(self._import_ioerror) + sig.keymanager_import_datamismatch.connect(self._import_datamismatch) + sig.keymanager_import_missingkey.connect(self._import_missingkey) + sig.keymanager_import_addressmismatch.connect( + self._import_addressmismatch) diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 4d79305e..cf6614be 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -23,7 +23,6 @@ import socket from datetime import datetime from PySide import QtCore, QtGui -from zope.proxy import ProxyBase, setProxiedObject from twisted.internet import reactor, threads from leap.bitmask import __version__ as VERSION @@ -269,8 +268,6 @@ class MainWindow(QtGui.QMainWindow): self._bypass_checks = bypass_checks self._start_hidden = start_hidden - self._keymanager = ProxyBase(None) - self._mail_conductor = mail_conductor.MailConductor(self._backend) self._mail_conductor.connect_mail_signals(self._mail_status) @@ -598,11 +595,11 @@ class MainWindow(QtGui.QMainWindow): details = self._provider_details mx_provided = False if details is not None: - mx_provided = MX_SERVICE in details + mx_provided = MX_SERVICE in details.services # XXX: handle differently not logged in user? akm = AdvancedKeyManagement(self, mx_provided, logged_user, - self._keymanager, self._soledad_started) + self._backend, self._soledad_started) akm.show() @QtCore.Slot() @@ -1437,12 +1434,7 @@ class MainWindow(QtGui.QMainWindow): """ logger.debug("Done bootstrapping Soledad") - # Update the proxy objects to point to the initialized instances. - # setProxiedObject(self._soledad, self._backend.get_soledad()) - setProxiedObject(self._keymanager, self._backend.get_keymanager()) - self._soledad_started = True - self.soledad_ready.emit() ################################################################### -- cgit v1.2.3 From 1b467b53ec99352280d098bea78cf1dceffef2d5 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 29 May 2014 10:40:34 -0300 Subject: Avoid 'provides eip' check during eip autostart. --- src/leap/bitmask/gui/mainwindow.py | 15 ++++++++++++--- 1 file changed, 12 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 cf6614be..fd9a70ac 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1578,7 +1578,7 @@ class MainWindow(QtGui.QMainWindow): default_provider) if settings.get_autostart_eip(): - self._maybe_start_eip() + self._maybe_start_eip(autostart=True) @QtCore.Slot() def _start_EIP(self): @@ -1787,12 +1787,21 @@ class MainWindow(QtGui.QMainWindow): # eip boostrapping, config etc... - def _maybe_start_eip(self): + def _maybe_start_eip(self, autostart=False): """ Start the EIP bootstrapping sequence if the client is configured to do so. + + :param autostart: we are autostarting EIP when this is True + :type autostart: bool """ - if self._provides_eip_and_enabled() and not self._already_started_eip: + # during autostart we assume that the provider provides EIP + if autostart: + should_start = EIP_SERVICE in self._enabled_services + else: + should_start = self._provides_eip_and_enabled() + + if should_start and not self._already_started_eip: # XXX this should be handled by the state machine. self._eip_status.set_eip_status( self.tr("Starting...")) -- cgit v1.2.3 From ccc8973bdc5cc0858906751eada622de74fd5d37 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 21 May 2014 18:42:05 -0500 Subject: refactor eip start/stop control to conductor and cleanup a little bit of the signal mess. --- src/leap/bitmask/gui/eip_status.py | 161 ++++++++++++-- src/leap/bitmask/gui/mainwindow.py | 403 ++++++---------------------------- src/leap/bitmask/gui/statemachines.py | 13 +- 3 files changed, 225 insertions(+), 352 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 ca28b8bf..9da231f2 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -24,7 +24,6 @@ from functools import partial from PySide import QtCore, QtGui -from leap.bitmask.services.eip.connection import EIPConnection 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 @@ -43,9 +42,14 @@ class EIPStatusWidget(QtGui.QWidget): RATE_STR = "%1.2f KB/s" TOTAL_STR = "%1.2f Kb" - eip_connection_connected = QtCore.Signal() + def __init__(self, parent=None, eip_conductor=None): + """ + :param parent: the parent of the widget. + :type parent: QObject - def __init__(self, parent=None): + :param eip_conductor: an EIPConductor object. + :type eip_conductor: EIPConductor + """ QtGui.QWidget.__init__(self, parent) self._systray = None @@ -54,7 +58,8 @@ class EIPStatusWidget(QtGui.QWidget): self.ui = Ui_EIPStatus() self.ui.setupUi(self) - self.eipconnection = EIPConnection() + self.eip_conductor = eip_conductor + self.eipconnection = eip_conductor.eip_connection # set systray tooltip status self._eip_status = "" @@ -75,11 +80,36 @@ class EIPStatusWidget(QtGui.QWidget): self._make_status_clickable() self._provider = "" + self.is_restart = False # Action for the systray self._eip_disabled_action = QtGui.QAction( "{0} is {1}".format(self._service_name, self.tr("disabled")), self) + def connect_backend_signals(self): + """ + Connect backend signals. + """ + signaler = self.eip_conductor._backend.signaler + + signaler.eip_openvpn_already_running.connect( + self._on_eip_openvpn_already_running) + signaler.eip_alien_openvpn_already_running.connect( + self._on_eip_alien_openvpn_already_running) + signaler.eip_openvpn_not_found_error.connect( + self._on_eip_openvpn_not_found_error) + signaler.eip_vpn_launcher_exception.connect( + self._on_eip_vpn_launcher_exception) + signaler.eip_no_polkit_agent_error.connect( + self._on_eip_no_polkit_agent_error) + signaler.eip_no_pkexec_error.connect(self._on_eip_no_pkexec_error) + signaler.eip_no_tun_kext_error.connect(self._on_eip_no_tun_kext_error) + + signaler.eip_state_changed.connect(self.update_vpn_state) + signaler.eip_status_changed.connect(self.update_vpn_status) + signaler.eip_network_unreachable.connect( + self._on_eip_network_unreachable) + def _make_status_clickable(self): """ Makes upload and download figures clickable. @@ -238,7 +268,7 @@ class EIPStatusWidget(QtGui.QWidget): def eip_pre_up(self): """ Triggered when the app activates eip. - Hides the status box and disables the start/stop button. + Disables the start/stop button. """ self.set_startstop_enabled(False) @@ -248,7 +278,7 @@ class EIPStatusWidget(QtGui.QWidget): Triggered when a default provider_config has not been found. Disables the start button and adds instructions to the user. """ - #logger.debug('Hiding EIP start button') + logger.debug('Hiding EIP start button') # you might be tempted to change this for a .setEnabled(False). # it won't work. it's under the claws of the state machine. # probably the best thing would be to make a conditional @@ -326,26 +356,26 @@ class EIPStatusWidget(QtGui.QWidget): Sets the state of the widget to how it should look after EIP has started """ - self.ui.btnEipStartStop.setText(self.tr("Turn OFF")) self.ui.btnEipStartStop.disconnect(self) self.ui.btnEipStartStop.clicked.connect( self.eipconnection.qtsigs.do_connect_signal) - # XXX disable ----------------------------- - def eip_stopped(self): + @QtCore.Slot(dict) + def eip_stopped(self, restart=False): """ + TRIGGERS: + EIPConductor.qtsigs.disconnected_signal + Sets the state of the widget to how it should look after EIP has stopped """ - # XXX should connect this to EIPConnection.disconnected_signal self._reset_traffic_rates() - # XXX disable ----------------------------- - self.ui.btnEipStartStop.setText(self.tr("Turn ON")) - self.ui.btnEipStartStop.disconnect(self) - self.ui.btnEipStartStop.clicked.connect( - self.eipconnection.qtsigs.do_disconnect_signal) - self.ui.eip_bandwidth.hide() + + # XXX FIXME ! ----------------------- this needs to + # accomodate the messages about firewall up or not. + # Or better call it from the conductor... + self.ui.lblEIPMessage.setText( self.tr("Traffic is being routed in the clear")) self.ui.lblEIPStatus.show() @@ -407,7 +437,8 @@ class EIPStatusWidget(QtGui.QWidget): self.ui.lblEIPStatus.hide() # XXX should be handled by the state machine too. - self.eip_connection_connected.emit() + # --- is this currently being sent? + self.eipconnection.qtsigs.connected_signal.emit() # XXX should lookup vpn_state map in EIPConnection elif vpn_state == "AUTH": @@ -423,8 +454,9 @@ class EIPStatusWidget(QtGui.QWidget): elif vpn_state == "ALREADYRUNNING": # Put the following calls in Qt's event queue, otherwise # the UI won't update properly + #self.send_disconnect_signal() QtCore.QTimer.singleShot( - 0, self.eipconnection.qtsigs.do_disconnect_signal) + 0, self.eipconnection.qtsigns.do_disconnect_signal.emit) msg = self.tr("Unable to start VPN, it's already running.") QtCore.QTimer.singleShot(0, partial(self.set_eip_status, msg)) else: @@ -470,3 +502,96 @@ class EIPStatusWidget(QtGui.QWidget): self._provider = provider self.ui.lblEIPMessage.setText( self.tr("Route traffic through: {0}").format(self._provider)) + + # + # Slots for signals + # + + @QtCore.Slot() + def _on_eip_connection_aborted(self): + """ + TRIGGERS: + Signaler.eip_connection_aborted + """ + logger.error("Tried to start EIP but cannot find any " + "available provider!") + + eip_status_label = self.tr("Could not load {0} configuration.") + eip_status_label = eip_status_label.format( + self._eip_conductor.eip_name) + self.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.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.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.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.set_eip_status("VPN Launcher error.", error=True) + self.set_eipstatus_off() + + def _on_eip_no_polkit_agent_error(self): + self.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.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.set_eip_status( + self.tr("{0} cannot be started because the tuntap extension is " + "not installed properly in your " + "system.").format(self._eip_conductor.eip_name)) + self.set_eipstatus_off() + + @QtCore.Slot() + def _on_eip_network_unreachable(self): + """ + TRIGGERS: + self._eip_connection.qtsigs.network_unreachable + + Displays a "network unreachable" error in the EIP status panel. + """ + self.set_eip_status(self.tr("Network is unreachable"), + error=True) + self.set_eip_status_icon("error") + + def set_eipstatus_off(self, error=True): + # XXX this should be handled by the state machine. + """ + Sets eip status to off + """ + self.set_eip_status("", error=error) + self.set_eip_status_icon("error") diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index fd9a70ac..27ef6109 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -30,7 +30,6 @@ from leap.bitmask import __version_hash__ as VERSION_HASH from leap.bitmask.config import flags from leap.bitmask.config.leapsettings import LeapSettings -from leap.bitmask.gui import statemachines from leap.bitmask.gui.advanced_key_management import AdvancedKeyManagement from leap.bitmask.gui.eip_preferenceswindow import EIPPreferencesWindow from leap.bitmask.gui.eip_status import EIPStatusWidget @@ -46,12 +45,10 @@ from leap.bitmask.platform_init.initializers import init_platform from leap.bitmask import backend -from leap.bitmask.services import get_service_display_name - +from leap.bitmask.services.eip import conductor as eip_conductor from leap.bitmask.services.mail import conductor as mail_conductor from leap.bitmask.services import EIP_SERVICE, MX_SERVICE -from leap.bitmask.services.eip.connection import EIPConnection from leap.bitmask.util import make_address from leap.bitmask.util.keyring_helpers import has_keyring @@ -68,6 +65,7 @@ from leap.mail.imap.service.imap import IMAP_PORT from ui_mainwindow import Ui_MainWindow +QtDelayedCall = QtCore.QTimer.singleShot logger = logging.getLogger(__name__) @@ -131,11 +129,16 @@ class MainWindow(QtGui.QMainWindow): self._settings = LeapSettings() + # Login Widget self._login_widget = LoginWidget( self._settings, self) self.ui.loginLayout.addWidget(self._login_widget) + # Mail Widget + self._mail_status = MailStatusWidget(self) + self.ui.mailLayout.addWidget(self._mail_status) + # Qt Signal Connections ##################################### # TODO separate logic from ui signals. @@ -144,34 +147,27 @@ class MainWindow(QtGui.QMainWindow): self._login_widget.show_wizard.connect(self._launch_wizard) self._login_widget.logout.connect(self._logout) - self._eip_status = EIPStatusWidget(self) - self.ui.eipLayout.addWidget(self._eip_status) - self._login_widget.logged_in_signal.connect( - self._eip_status.enable_eip_start) - self._login_widget.logged_in_signal.connect( - self._enable_eip_start_action) - - self._mail_status = MailStatusWidget(self) - self.ui.mailLayout.addWidget(self._mail_status) - - self._eip_connection = EIPConnection() + # EIP Control redux ######################################### + self._eip_conductor = eip_conductor.EIPConductor( + self._settings, self._backend) + self._eip_status = EIPStatusWidget(self, self._eip_conductor) - # XXX this should be handled by EIP Conductor - self._eip_connection.qtsigs.connecting_signal.connect( - self._start_EIP) - self._eip_connection.qtsigs.disconnecting_signal.connect( - self._stop_eip) + self.ui.eipLayout.addWidget(self._eip_status) + self._eip_conductor.add_eip_widget(self._eip_status) - self._eip_status.eip_connection_connected.connect( + self._eip_conductor.connect_signals() + self._eip_conductor.qtsigs.connected_signal.connect( self._on_eip_connection_connected) - self._eip_status.eip_connection_connected.connect( + self._eip_conductor.qtsigs.connected_signal.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._already_started_eip = False self._trying_to_start_eip = False self._already_started_eip = False @@ -215,8 +211,7 @@ class MainWindow(QtGui.QMainWindow): self._systray = None - # XXX separate actions into a different - # module. + # XXX separate actions into a different module. self._action_mail_status = QtGui.QAction(self.tr("Mail is OFF"), self) self._mail_status.set_action_mail_status(self._action_mail_status) @@ -280,20 +275,19 @@ class MainWindow(QtGui.QMainWindow): # the EIPConductor or some other clever component that we will # instantiate from here. - self.eip_machine = None # start event machines - self.start_eip_machine() + # TODO should encapsulate all actions into one object + self._eip_conductor.start_eip_machine( + action=self._action_eip_startstop) self._mail_conductor.start_mail_machine() - self._eip_name = get_service_display_name(EIP_SERVICE) - if self._first_run(): self._wizard_firstrun = True 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 - QtCore.QTimer.singleShot(1, self._launch_wizard) + QtDelayedCall(1, self._launch_wizard) self._wizard.accepted.connect(self._finish_init) self._wizard.rejected.connect(self._rejected_wizard) else: @@ -351,67 +345,50 @@ class MainWindow(QtGui.QMainWindow): :type only_tracked: bool """ sig = self._backend.signaler + conntrack = self._connect_and_track + auth_err = self._authentication_error - 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) + conntrack(sig.prov_name_resolution, self._intermediate_stage) + conntrack(sig.prov_https_connection, self._intermediate_stage) + conntrack(sig.prov_download_ca_cert, self._intermediate_stage) + conntrack(sig.prov_download_provider_info, self._load_provider_config) + conntrack(sig.prov_check_api_certificate, self._provider_config_loaded) - 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) + conntrack(sig.prov_problem_with_provider, self._login_problem_provider) + conntrack(sig.prov_cancelled_setup, self._set_login_cancelled) self._connect_and_track(sig.prov_get_details, self._provider_get_details) # Login signals - self._connect_and_track(sig.srp_auth_ok, self._authentication_finished) + conntrack(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_error = lambda: auth_err(self.tr("Unknown error.")) + conntrack(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_server_error = lambda: auth_err(self.tr( + "There was a server problem with authentication.")) + conntrack(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_connection_error = lambda: auth_err(self.tr( + "Could not establish a connection.")) + conntrack(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) + auth_bad_user_or_password = lambda: auth_err(self.tr( + "Invalid username or password.")) + conntrack(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) + conntrack(sig.srp_logout_ok, self._logout_ok) + conntrack(sig.srp_logout_error, self._logout_error) + conntrack(sig.srp_not_logged_in_error, self._not_logged_in_error) # EIP bootstrap signals - self._connect_and_track(sig.eip_config_ready, - self._eip_intermediate_stage) - self._connect_and_track(sig.eip_client_certificate_ready, - self._finish_eip_bootstrap) + conntrack(sig.eip_config_ready, self._eip_intermediate_stage) + conntrack(sig.eip_client_certificate_ready, self._finish_eip_bootstrap) ################################################### - # Add tracked signals above this, untracked bellow! + # Add tracked signals above this, untracked below! ################################################### if only_tracked: return @@ -421,38 +398,20 @@ class MainWindow(QtGui.QMainWindow): sig.backend_bad_call.connect(self._backend_bad_call) sig.prov_check_api_certificate.connect(self._get_provider_details) - sig.prov_unsupported_client.connect(self._needs_update) sig.prov_unsupported_api.connect(self._incompatible_api) + sig.prov_get_all_services.connect(self._provider_get_all_services) - sig.prov_get_all_services.connect( - self._provider_get_all_services) - - # 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) + # EIP start signals ============================================== + self._eip_conductor.connect_backend_signals() sig.eip_can_start.connect(self._backend_can_start_eip) sig.eip_cannot_start.connect(self._backend_cannot_start_eip) + # ================================================================== + # Soledad signals + # TODO delegate connection to soledad bootstrapper sig.soledad_bootstrap_failed.connect( self._mail_status.set_soledad_failed) sig.soledad_bootstrap_finished.connect(self._on_soledad_ready) @@ -919,7 +878,8 @@ class MainWindow(QtGui.QMainWindow): systrayMenu.addAction(self._action_visible) systrayMenu.addSeparator() - eip_status_label = "{0}: {1}".format(self._eip_name, self.tr("OFF")) + eip_status_label = "{0}: {1}".format( + self._eip_conductor.eip_name, self.tr("OFF")) 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) @@ -1001,7 +961,7 @@ class MainWindow(QtGui.QMainWindow): # Wait a bit until the window visibility has changed so # the menu is set with the correct value. - QtCore.QTimer.singleShot(500, self._update_hideshow_menu) + QtDelayedCall(500, self._update_hideshow_menu) def _center_window(self): """ @@ -1473,21 +1433,6 @@ class MainWindow(QtGui.QMainWindow): ################################################################### # Service control methods: eip - def start_eip_machine(self): - """ - Initializes and starts the EIP state machine - """ - button = self._eip_status.eip_button - action = self._action_eip_startstop - label = self._eip_status.eip_label - builder = statemachines.ConnectionMachineBuilder(self._eip_connection) - eip_machine = builder.make_machine(button=button, - action=action, - label=label) - self.eip_machine = eip_machine - self.eip_machine.start() - logger.debug('eip machine started') - @QtCore.Slot() def _disable_eip_start_action(self): """ @@ -1506,17 +1451,14 @@ class MainWindow(QtGui.QMainWindow): def _on_eip_connection_connected(self): """ TRIGGERS: - self._eip_status.eip_connection_connected - - Emits the EIPConnection.qtsigs.connected_signal + self._eip_conductor.qtsigs.connected_signal This is a little workaround for connecting the vpn-connected signal that currently is beeing processed under status_panel. After the refactor to EIPConductor this should not be necessary. """ - self._eip_connection.qtsigs.connected_signal.emit() - domain = self._login_widget.get_selected_provider() + self._eip_status.set_provider(domain) self._settings.set_defaultprovider(domain) self._already_started_eip = True @@ -1525,6 +1467,9 @@ class MainWindow(QtGui.QMainWindow): self._check_name_resolution(domain) def _check_name_resolution(self, domain): + # FIXME this has to be moved to backend !!! + # Should move to netchecks module. + # and separate qt from reactor... """ Check if we can resolve the given domain name. @@ -1555,7 +1500,7 @@ class MainWindow(QtGui.QMainWindow): "missing some helper files that are needed to securely use " "DNS while {1} is active. To install these helper files, quit " "this application and start it again." - ).format(domain, self._eip_name) + ).format(domain, self._eip_conductor.eip_name) show_err = lambda: QtGui.QMessageBox.critical( self, self.tr("Connection Error"), msg) @@ -1580,211 +1525,6 @@ class MainWindow(QtGui.QMainWindow): if settings.get_autostart_eip(): self._maybe_start_eip(autostart=True) - @QtCore.Slot() - def _start_EIP(self): - """ - Starts EIP - """ - 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. - self._settings.set_autostart_eip(True) - - self._backend.eip_start() - - @QtCore.Slot() - def _on_eip_connection_aborted(self): - """ - TRIGGERS: - Signaler.eip_connection_aborted - """ - logger.error("Tried to start EIP but cannot find any " - "available provider!") - - 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() - - @QtCore.Slot() - def _stop_eip(self, restart=False): - """ - TRIGGERS: - self._eip_connection.qtsigs.do_disconnect_signal (via state machine) - - Stops vpn process and makes gui adjustments to reflect - the change of state. - - :param abnormal: whether this was an abnormal termination. - :type abnormal: bool - """ - self.user_stopped_eip = not restart - self._backend.eip_stop(restart=restart) - - self._set_eipstatus_off(False) - self._already_started_eip = False - - logger.debug('Setting autostart to: False') - self._settings.set_autostart_eip(False) - - user = self._logged_user - if user: - domain = self._login_widget.get_selected_provider() - full_user_id = make_address(user, domain) - self._eip_status.set_provider(full_user_id) - - self._eip_status.eip_stopped() - - @QtCore.Slot() - def _on_eip_network_unreachable(self): - # XXX Should move to EIP Conductor - """ - TRIGGERS: - self._eip_connection.qtsigs.network_unreachable - - Displays a "network unreachable" error in the EIP status panel. - """ - self._eip_status.set_eip_status(self.tr("Network is unreachable"), - error=True) - self._eip_status.set_eip_status_icon("error") - - @QtCore.Slot() - def _do_eip_restart(self): - # XXX Should move to EIP Conductor - """ - TRIGGERS: - self._eip_connection.qtsigs.process_restart - - Restart the connection. - """ - # for some reason, emitting the do_disconnect/do_connect - # signals hangs the UI. - self._stop_eip(restart=True) - QtCore.QTimer.singleShot(2000, self._start_EIP) - - def _set_eipstatus_off(self, error=True): - """ - Sets eip status to off - """ - # XXX this should be handled by the state machine. - self._eip_status.set_eip_status("", error=error) - self._eip_status.set_eip_status_icon("error") - - @QtCore.Slot(int) - def _eip_finished(self, exitCode): - """ - TRIGGERS: - Signaler.eip_process_finished - - Triggered when the EIP/VPN process finishes to set the UI - accordingly. - - Ideally we would have the right exit code here, - but the use of different wrappers (pkexec, cocoasudo) swallows - the openvpn exit code so we get zero exit in some cases where we - shouldn't. As a workaround we just use a flag to indicate - a purposeful switch off, and mark everything else as unexpected. - - In the near future we should trigger a native notification from here, - since the user really really wants to know she is unprotected asap. - And the right thing to do will be to fail-close. - - :param exitCode: the exit code of the eip process. - :type exitCode: int - """ - # TODO move to EIPConductor. - # TODO Add error catching to the openvpn log observer - # so we can have a more precise idea of which type - # of error did we have (server side, local problem, etc) - - logger.info("VPN process finished with exitCode %s..." - % (exitCode,)) - - qtsigs = self._eip_connection.qtsigs - signal = qtsigs.disconnected_signal - - # XXX check if these exitCodes are pkexec/cocoasudo specific - if exitCode in (126, 127): - eip_status_label = self.tr( - "{0} could not be launched " - "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) - signal = qtsigs.connection_aborted_signal - self._backend.eip_terminate() - - 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 - - if exitCode == 0 and IS_MAC: - # XXX remove this warning after I fix cocoasudo. - logger.warning("The above exit code MIGHT BE WRONG.") - - # We emit signals to trigger transitions in the state machine: - signal.emit() - # eip boostrapping, config etc... def _maybe_start_eip(self, autostart=False): @@ -1812,9 +1552,8 @@ class MainWindow(QtGui.QMainWindow): self._already_started_eip = True # we want to start soledad anyway after a certain timeout if eip # fails to come up - QtCore.QTimer.singleShot( - self.EIP_START_TIMEOUT, - self._maybe_run_soledad_setup_checks) + QtDelayedCall(self.EIP_START_TIMEOUT, + self._maybe_run_soledad_setup_checks) else: if not self._already_started_eip: if EIP_SERVICE in self._enabled_services: @@ -1833,8 +1572,8 @@ class MainWindow(QtGui.QMainWindow): TRIGGERS: self._backend.signaler.eip_client_certificate_ready - Starts the VPN thread if the eip configuration is properly - loaded + Start the VPN thread if the eip configuration is properly + loaded. """ passed = data[self._backend.PASSED_KEY] @@ -1846,11 +1585,11 @@ class MainWindow(QtGui.QMainWindow): return # DO START EIP Connection! - self._eip_connection.qtsigs.do_connect_signal.emit() + self._eip_conductor.do_connect() @QtCore.Slot(dict) def _eip_intermediate_stage(self, data): - # TODO missing param + # TODO missing param documentation """ TRIGGERS: self._backend.signaler.eip_config_ready diff --git a/src/leap/bitmask/gui/statemachines.py b/src/leap/bitmask/gui/statemachines.py index 31938a70..f8e5479d 100644 --- a/src/leap/bitmask/gui/statemachines.py +++ b/src/leap/bitmask/gui/statemachines.py @@ -504,6 +504,11 @@ class ConnectionMachineBuilder(object): conn.qtsigs.connection_died_signal, states[_OFF]) + # XXX adding this--------------------- + states[_ON].addTransition( + conn.qtsigs.do_disconnect_signal, + states[_DIS]) + # * If we receive the connection_aborted, we transition # from connecting to the off state states[_CON].addTransition( @@ -551,7 +556,8 @@ class ConnectionMachineBuilder(object): # TODO add tooltip # OFF State ---------------------- - off = QState() + off = SignallingState( + None, name=conn.name) off_label = _tr("Turn {0}").format( conn.Connected.short_label) if button: @@ -587,7 +593,10 @@ class ConnectionMachineBuilder(object): states[_CON] = connecting # ON State ------------------------ - on = QState() + on = SignallingState( + None, name=conn.name) + on_label = _tr("Turn {0}").format( + conn.Disconnected.short_label) if button: on.assignProperty( button, 'text', on_label) -- cgit v1.2.3 From b85d6ed72460f15b6029f36ccfef3bccd57e530c Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 28 May 2014 16:29:42 -0500 Subject: fix non-existing logged_user caused by a bad rebase. --- src/leap/bitmask/gui/mainwindow.py | 21 +++++++++++++++++++++ src/leap/bitmask/gui/statemachines.py | 4 ++++ 2 files changed, 25 insertions(+) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 27ef6109..aa317d96 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -158,6 +158,8 @@ class MainWindow(QtGui.QMainWindow): self._eip_conductor.connect_signals() self._eip_conductor.qtsigs.connected_signal.connect( self._on_eip_connection_connected) + self._eip_conductor.qtsigs.disconnected_signal.connect( + self._on_eip_connection_disconnected) self._eip_conductor.qtsigs.connected_signal.connect( self._maybe_run_soledad_setup_checks) @@ -1466,6 +1468,25 @@ class MainWindow(QtGui.QMainWindow): # check for connectivity self._check_name_resolution(domain) + @QtCore.Slot() + def _on_eip_connection_disconnected(self): + """ + TRIGGERS: + self._eip_conductor.qtsigs.disconnected_signal + + Workaround for updating the eip_status widget with + the provider when the eip connection disconnects. + """ + # TODO + # We should move this to the conductor<->widget interface. + # To do that, we need to subscribe to logged_user, + # for example by using the observer pattern or a proxy object. + user = self._logged_user + if user: + domain = self._login_widget.get_selected_provider() + full_user_id = make_address(user, domain) + self._eip_status.set_provider(full_user_id) + def _check_name_resolution(self, domain): # FIXME this has to be moved to backend !!! # Should move to netchecks module. diff --git a/src/leap/bitmask/gui/statemachines.py b/src/leap/bitmask/gui/statemachines.py index f8e5479d..2a876b83 100644 --- a/src/leap/bitmask/gui/statemachines.py +++ b/src/leap/bitmask/gui/statemachines.py @@ -55,6 +55,10 @@ class SignallingState(QState): """ Emits the signal on entry. """ + print "IIIIIIIIIIIIIIIIIII" + print "TO STATE", self._name, self.objectName() + print "IIIIIIIIIIIIIIIIIII" + logger.debug('State %s::%s entered. Emitting signal ...' % (self._name, self.objectName())) if self._signal is not None: -- cgit v1.2.3 From 2174acd89500ebad2c9b3df034d276e0e857b6f8 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 29 May 2014 12:44:56 -0500 Subject: change eip status during restarts --- src/leap/bitmask/gui/eip_status.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 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 9da231f2..ca209d6a 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -373,11 +373,19 @@ class EIPStatusWidget(QtGui.QWidget): self.ui.eip_bandwidth.hide() # XXX FIXME ! ----------------------- this needs to - # accomodate the messages about firewall up or not. + # accomodate the messages about firewall status. Right now + # we're assuming it works correctly, but we should test fw + # status positively. # Or better call it from the conductor... - self.ui.lblEIPMessage.setText( - self.tr("Traffic is being routed in the clear")) + clear_traffic = self.tr("Traffic is being routed in the clear") + unreachable_net = self.tr("Network is unreachable") + + if restart: + msg = unreachable_net + else: + msg = clear_traffic + self.ui.lblEIPMessage.setText(msg) self.ui.lblEIPStatus.show() @QtCore.Slot(dict) -- cgit v1.2.3 From 5f6e44241b4858f1c407f0babfc41f40a06405f1 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 29 May 2014 12:45:46 -0500 Subject: display restart error after SIGTERM[soft,tls-error] - fix tls-error: is SIGTERM now - connect to connection-died signal - display error to user --- src/leap/bitmask/gui/eip_status.py | 21 +++++++++++++++++---- src/leap/bitmask/gui/mainwindow.py | 2 +- src/leap/bitmask/gui/statemachines.py | 4 ---- 3 files changed, 18 insertions(+), 9 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 ca209d6a..04acc167 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -361,7 +361,7 @@ class EIPStatusWidget(QtGui.QWidget): self.eipconnection.qtsigs.do_connect_signal) @QtCore.Slot(dict) - def eip_stopped(self, restart=False): + def eip_stopped(self, restart=False, failed=False): """ TRIGGERS: EIPConductor.qtsigs.disconnected_signal @@ -378,16 +378,29 @@ class EIPStatusWidget(QtGui.QWidget): # status positively. # Or better call it from the conductor... - clear_traffic = self.tr("Traffic is being routed in the clear") - unreachable_net = self.tr("Network is unreachable") + clear_traffic = self.tr("Traffic is being routed in the clear.") + unreachable_net = self.tr("Network is unreachable.") + failed_msg = self.tr("Cannot start Encrypted Proxy.") if restart: msg = unreachable_net + elif failed: + msg = failed_msg else: msg = clear_traffic self.ui.lblEIPMessage.setText(msg) self.ui.lblEIPStatus.show() + def eip_failed_to_restart(self): + """ + Update EIP messages. + """ + msg = self.tr("Could not restart Encrypted Proxy") + self.ui.lblEIPMessage.setText(msg) + self.ui.lblEIPStatus.show() + + self.set_eip_status(self.tr("You can start the service manually.")) + @QtCore.Slot(dict) def update_vpn_status(self, data=None): """ @@ -530,7 +543,7 @@ class EIPStatusWidget(QtGui.QWidget): self.set_eip_status(eip_status_label, error=True) # signal connection_aborted to state machine: - qtsigs = self._eip_connection.qtsigs + qtsigs = self._eipconnection.qtsigs qtsigs.connection_aborted_signal.emit() def _on_eip_openvpn_already_running(self): diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index aa317d96..98d9fb8b 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1764,7 +1764,7 @@ class MainWindow(QtGui.QMainWindow): if self._systray is not None: self._systray.showMessage( self.tr('Quitting...'), - self.tr('The app is quitting, please wait.')) + self.tr('Bitmask is quitting, please wait.')) # explicitly process events to display tooltip immediately QtCore.QCoreApplication.processEvents(0, 10) diff --git a/src/leap/bitmask/gui/statemachines.py b/src/leap/bitmask/gui/statemachines.py index 2a876b83..f8e5479d 100644 --- a/src/leap/bitmask/gui/statemachines.py +++ b/src/leap/bitmask/gui/statemachines.py @@ -55,10 +55,6 @@ class SignallingState(QState): """ Emits the signal on entry. """ - print "IIIIIIIIIIIIIIIIIII" - print "TO STATE", self._name, self.objectName() - print "IIIIIIIIIIIIIIIIIII" - logger.debug('State %s::%s entered. Emitting signal ...' % (self._name, self.objectName())) if self._signal is not None: -- cgit v1.2.3 From efea398e18f806ad5bb7cec4aa0dcef5f94319bc Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 29 May 2014 12:49:44 -0500 Subject: rephrase --- 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 98d9fb8b..1d467e60 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1360,7 +1360,7 @@ class MainWindow(QtGui.QMainWindow): """ # TODO split. if not self._provides_mx_and_enabled() and not flags.OFFLINE: - logger.debug("Does not provides and enabled MX") + logger.debug("Provider does not offer MX, but it is enabled.") return username = self._login_widget.get_user() -- cgit v1.2.3 From d4d6b0c5476b45629d632debe4527f9d6cb3cb0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Thu, 29 May 2014 16:44:25 -0300 Subject: Check openvpn bin path before starting openvpn --- src/leap/bitmask/gui/eip_status.py | 36 ++++++++++++++++++++++++++++++++--- src/leap/bitmask/gui/mainwindow.py | 5 ++--- src/leap/bitmask/gui/statemachines.py | 4 ++++ 3 files changed, 39 insertions(+), 6 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 04acc167..ba041968 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -102,6 +102,8 @@ class EIPStatusWidget(QtGui.QWidget): self._on_eip_vpn_launcher_exception) signaler.eip_no_polkit_agent_error.connect( self._on_eip_no_polkit_agent_error) + signaler.eip_connection_aborted.connect( + self._on_eip_connection_aborted) signaler.eip_no_pkexec_error.connect(self._on_eip_no_pkexec_error) signaler.eip_no_tun_kext_error.connect(self._on_eip_no_tun_kext_error) @@ -539,11 +541,11 @@ class EIPStatusWidget(QtGui.QWidget): eip_status_label = self.tr("Could not load {0} configuration.") eip_status_label = eip_status_label.format( - self._eip_conductor.eip_name) + self.eip_conductor.eip_name) self.set_eip_status(eip_status_label, error=True) # signal connection_aborted to state machine: - qtsigs = self._eipconnection.qtsigs + qtsigs = self.eipconnection.qtsigs qtsigs.connection_aborted_signal.emit() def _on_eip_openvpn_already_running(self): @@ -553,6 +555,10 @@ class EIPStatusWidget(QtGui.QWidget): error=True) self.set_eipstatus_off() + # signal connection_aborted to state machine: + qtsigs = self.eipconnection.qtsigs + qtsigs.connection_aborted_signal.emit() + def _on_eip_alien_openvpn_already_running(self): self.set_eip_status( self.tr("Another openvpn instance is already running, and " @@ -561,18 +567,30 @@ class EIPStatusWidget(QtGui.QWidget): error=True) self.set_eipstatus_off() + # signal connection_aborted to state machine: + qtsigs = self.eipconnection.qtsigs + qtsigs.connection_aborted_signal.emit() + def _on_eip_openvpn_not_found_error(self): self.set_eip_status( self.tr("We could not find openvpn binary."), error=True) self.set_eipstatus_off() + # signal connection_aborted to state machine: + qtsigs = self.eipconnection.qtsigs + qtsigs.connection_aborted_signal.emit() + 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.set_eip_status("VPN Launcher error.", error=True) self.set_eipstatus_off() + # signal connection_aborted to state machine: + qtsigs = self.eipconnection.qtsigs + qtsigs.connection_aborted_signal.emit() + def _on_eip_no_polkit_agent_error(self): self.set_eip_status( # XXX this should change to polkit-kde where @@ -584,19 +602,31 @@ class EIPStatusWidget(QtGui.QWidget): error=True) self.set_eipstatus_off() + # signal connection_aborted to state machine: + qtsigs = self.eipconnection.qtsigs + qtsigs.connection_aborted_signal.emit() + def _on_eip_no_pkexec_error(self): self.set_eip_status( self.tr("We could not find pkexec in your system."), error=True) self.set_eipstatus_off() + # signal connection_aborted to state machine: + qtsigs = self.eipconnection.qtsigs + qtsigs.connection_aborted_signal.emit() + def _on_eip_no_tun_kext_error(self): self.set_eip_status( self.tr("{0} cannot be started because the tuntap extension is " "not installed properly in your " - "system.").format(self._eip_conductor.eip_name)) + "system.").format(self.eip_conductor.eip_name)) self.set_eipstatus_off() + # signal connection_aborted to state machine: + qtsigs = self.eipconnection.qtsigs + qtsigs.connection_aborted_signal.emit() + @QtCore.Slot() def _on_eip_network_unreachable(self): """ diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 1d467e60..a0eb84a2 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -597,7 +597,7 @@ class MainWindow(QtGui.QMainWindow): default_provider = settings.get_defaultprovider() if default_provider is None: - logger.warning("Trying toupdate eip enabled status but there's no" + logger.warning("Trying to update eip enabled status but there's no" " default provider. Disabling EIP for the time" " being...") self._backend_cannot_start_eip() @@ -637,7 +637,6 @@ class MainWindow(QtGui.QMainWindow): # 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")) @@ -664,7 +663,6 @@ class MainWindow(QtGui.QMainWindow): # 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")) @@ -1566,6 +1564,7 @@ class MainWindow(QtGui.QMainWindow): # XXX this should be handled by the state machine. self._eip_status.set_eip_status( self.tr("Starting...")) + self._eip_status.eip_button.setEnabled(False) domain = self._login_widget.get_selected_provider() self._backend.eip_setup(domain) diff --git a/src/leap/bitmask/gui/statemachines.py b/src/leap/bitmask/gui/statemachines.py index f8e5479d..00a1387e 100644 --- a/src/leap/bitmask/gui/statemachines.py +++ b/src/leap/bitmask/gui/statemachines.py @@ -565,11 +565,15 @@ class ConnectionMachineBuilder(object): button, 'text', off_label) off.assignProperty( button, 'enabled', True) + off.assignProperty( + button, 'visible', True) if action: off.assignProperty( action, 'text', off_label) off.assignProperty( action, 'enabled', True) + off.assignProperty( + action, 'visible', True) off.setObjectName(_OFF) states[_OFF] = off -- cgit v1.2.3 From 8b237f08b76bc94cfcd24d13945006a89c3aeeee Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 30 May 2014 12:16:17 -0300 Subject: Change password skips soledad if mx is not enabled. Use information from mainwindow instead of asking again to the backend. --- src/leap/bitmask/gui/mainwindow.py | 11 +++-- src/leap/bitmask/gui/preferenceswindow.py | 71 +++++++++++++------------------ 2 files changed, 36 insertions(+), 46 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index a0eb84a2..d46ef863 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -572,10 +572,13 @@ 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._soledad_started, user, prov) + user = self._logged_user + domain = self._login_widget.get_selected_provider() + mx_provided = False + if self._provider_details is not None: + mx_provided = MX_SERVICE in self._provider_details.services + preferences = PreferencesWindow(self, user, domain, self._backend, + self._soledad_started, mx_provided) 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 c67052f3..a3b81d38 100644 --- a/src/leap/bitmask/gui/preferenceswindow.py +++ b/src/leap/bitmask/gui/preferenceswindow.py @@ -38,28 +38,31 @@ class PreferencesWindow(QtGui.QDialog): """ preferences_saved = QtCore.Signal() - def __init__(self, parent, backend, soledad_started, username, domain): + def __init__(self, parent, username, domain, backend, soledad_started, mx): """ :param parent: parent object of the PreferencesWindow. :parent type: QWidget - :param backend: Backend being used - :type backend: Backend - :param soledad_started: whether soledad has started or not - :type soledad_started: bool :param username: the user set in the login widget :type username: unicode :param domain: the selected domain in the login widget :type domain: unicode + :param backend: Backend being used + :type backend: Backend + :param soledad_started: whether soledad has started or not + :type soledad_started: bool + :param mx: whether the current provider provides mx or not. + :type mx: bool """ QtGui.QDialog.__init__(self, parent) self.AUTOMATIC_GATEWAY_LABEL = self.tr("Automatic") - self._backend = backend - self._settings = LeapSettings() - self._soledad_started = soledad_started self._username = username self._domain = domain + self._backend = backend + self._soledad_started = soledad_started + self._mx_provided = mx + self._settings = LeapSettings() self._backend_connect() # Load UI @@ -80,26 +83,17 @@ class PreferencesWindow(QtGui.QDialog): else: self._add_configured_providers() - self._backend.user_get_logged_in_status() + if self._username is None: + self._not_logged_in() + else: + self.ui.gbPasswordChange.setEnabled(True) + if self._mx_provided: + self._provides_mx() self._select_provider_by_name(domain) - @QtCore.Slot() - def _is_logged_in(self): - """ - TRIGGERS: - Signaler.srp_status_logged_in - - Actions to perform is the user is logged in. - """ - self._backend.provider_provides_mx() - - @QtCore.Slot() def _not_logged_in(self): """ - TRIGGERS: - Signaler.srp_status_not_logged_in - Actions to perform if the user is not logged in. """ msg = self.tr( @@ -107,12 +101,8 @@ class PreferencesWindow(QtGui.QDialog): self._set_password_change_status(msg) self.ui.gbPasswordChange.setEnabled(False) - @QtCore.Slot() def _provides_mx(self): """ - TRIGGERS: - Signaler.prov_provides_mx - Actions to perform if the provider provides MX. """ pw_enabled = True @@ -135,16 +125,6 @@ class PreferencesWindow(QtGui.QDialog): self.ui.gbPasswordChange.setEnabled(pw_enabled) - @QtCore.Slot() - def _not_provides_mx(self): - """ - TRIGGERS: - Signaler.prov_not_provides_mx - - Actions to perform if the provider does not provides MX. - """ - self.ui.gbPasswordChange.setEnabled(False) - @QtCore.Slot() def set_soledad_ready(self): """ @@ -226,7 +206,11 @@ class PreferencesWindow(QtGui.QDialog): """ new_password = self.ui.leNewPassword.text() logger.debug("SRP password changed successfully.") - self._backend.soledad_change_password(new_password) + + if self._mx_provided: + self._backend.soledad_change_password(new_password) + else: + self._change_password_success() @QtCore.Slot(unicode) def _srp_change_password_problem(self, msg): @@ -250,6 +234,13 @@ class PreferencesWindow(QtGui.QDialog): TRIGGERS: Signaler.soledad_password_change_ok + Soledad password change went OK. + """ + logger.debug("Soledad password changed successfully.") + self._change_password_success() + + def _change_password_success(self): + """ Callback used to display a successfully changed password. """ logger.debug("Soledad password changed successfully.") @@ -434,12 +425,8 @@ class PreferencesWindow(QtGui.QDialog): """ sig = self._backend.signaler - sig.prov_provides_mx.connect(self._provides_mx) sig.prov_get_supported_services.connect(self._load_services) - 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._srp_change_password_ok) pwd_change_error = lambda: self._srp_change_password_problem( -- cgit v1.2.3 From b82589e29ce402725c2053dace1117ba8a785535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Fri, 30 May 2014 12:56:13 -0300 Subject: Improve signal handling in the mainwindow and wizard --- src/leap/bitmask/gui/mainwindow.py | 13 ++++++------- 1 file changed, 6 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 a0eb84a2..af7b2699 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -186,7 +186,7 @@ class MainWindow(QtGui.QMainWindow): # timeout object used to trigger quit self._quit_timeout_callater = None - self._backend_connected_signals = {} + self._backend_connected_signals = [] self._backend_connect() self.ui.action_preferences.triggered.connect(self._show_preferences) @@ -318,7 +318,7 @@ class MainWindow(QtGui.QMainWindow): :param method: the method to call when the signal is triggered. :type method: callable, Slot or Signal """ - self._backend_connected_signals[signal] = method + self._backend_connected_signals.append((signal, method)) signal.connect(method) def _backend_bad_call(self, data): @@ -355,12 +355,12 @@ class MainWindow(QtGui.QMainWindow): conntrack(sig.prov_download_ca_cert, self._intermediate_stage) conntrack(sig.prov_download_provider_info, self._load_provider_config) conntrack(sig.prov_check_api_certificate, self._provider_config_loaded) + conntrack(sig.prov_check_api_certificate, self._get_provider_details) conntrack(sig.prov_problem_with_provider, self._login_problem_provider) conntrack(sig.prov_cancelled_setup, self._set_login_cancelled) - self._connect_and_track(sig.prov_get_details, - self._provider_get_details) + conntrack(sig.prov_get_details, self._provider_get_details) # Login signals conntrack(sig.srp_auth_ok, self._authentication_finished) @@ -399,7 +399,6 @@ class MainWindow(QtGui.QMainWindow): sig.backend_bad_call.connect(self._backend_bad_call) - sig.prov_check_api_certificate.connect(self._get_provider_details) sig.prov_unsupported_client.connect(self._needs_update) sig.prov_unsupported_api.connect(self._incompatible_api) sig.prov_get_all_services.connect(self._provider_get_all_services) @@ -435,13 +434,13 @@ class MainWindow(QtGui.QMainWindow): Some signals are emitted from the wizard, and we want to ignore those. """ - for signal, method in self._backend_connected_signals.items(): + for signal, method in self._backend_connected_signals: try: signal.disconnect(method) except RuntimeError: pass # Signal was not connected - self._backend_connected_signals = {} + self._backend_connected_signals = [] @QtCore.Slot() def _rejected_wizard(self): -- cgit v1.2.3 From 520ffec305f89cd1ee504c24adee9e1bee21c452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Fri, 30 May 2014 11:44:33 -0300 Subject: Update EIP UI if it fails to load the config --- src/leap/bitmask/gui/eip_status.py | 40 +++++++++++++++----------------------- src/leap/bitmask/gui/mainwindow.py | 1 + 2 files changed, 17 insertions(+), 24 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 ba041968..e7795083 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -526,6 +526,14 @@ class EIPStatusWidget(QtGui.QWidget): self.ui.lblEIPMessage.setText( self.tr("Route traffic through: {0}").format(self._provider)) + def aborted(self): + """ + Notify the state machine that EIP was aborted for some reason. + """ + # signal connection_aborted to state machine: + qtsigs = self.eipconnection.qtsigs + qtsigs.connection_aborted_signal.emit() + # # Slots for signals # @@ -544,9 +552,7 @@ class EIPStatusWidget(QtGui.QWidget): self.eip_conductor.eip_name) self.set_eip_status(eip_status_label, error=True) - # signal connection_aborted to state machine: - qtsigs = self.eipconnection.qtsigs - qtsigs.connection_aborted_signal.emit() + self.aborted() def _on_eip_openvpn_already_running(self): self.set_eip_status( @@ -555,9 +561,7 @@ class EIPStatusWidget(QtGui.QWidget): error=True) self.set_eipstatus_off() - # signal connection_aborted to state machine: - qtsigs = self.eipconnection.qtsigs - qtsigs.connection_aborted_signal.emit() + self.aborted() def _on_eip_alien_openvpn_already_running(self): self.set_eip_status( @@ -567,9 +571,7 @@ class EIPStatusWidget(QtGui.QWidget): error=True) self.set_eipstatus_off() - # signal connection_aborted to state machine: - qtsigs = self.eipconnection.qtsigs - qtsigs.connection_aborted_signal.emit() + self.aborted() def _on_eip_openvpn_not_found_error(self): self.set_eip_status( @@ -577,9 +579,7 @@ class EIPStatusWidget(QtGui.QWidget): error=True) self.set_eipstatus_off() - # signal connection_aborted to state machine: - qtsigs = self.eipconnection.qtsigs - qtsigs.connection_aborted_signal.emit() + self.aborted() def _on_eip_vpn_launcher_exception(self): # XXX We should implement again translatable exceptions so @@ -587,9 +587,7 @@ class EIPStatusWidget(QtGui.QWidget): self.set_eip_status("VPN Launcher error.", error=True) self.set_eipstatus_off() - # signal connection_aborted to state machine: - qtsigs = self.eipconnection.qtsigs - qtsigs.connection_aborted_signal.emit() + self.aborted() def _on_eip_no_polkit_agent_error(self): self.set_eip_status( @@ -602,9 +600,7 @@ class EIPStatusWidget(QtGui.QWidget): error=True) self.set_eipstatus_off() - # signal connection_aborted to state machine: - qtsigs = self.eipconnection.qtsigs - qtsigs.connection_aborted_signal.emit() + self.aborted() def _on_eip_no_pkexec_error(self): self.set_eip_status( @@ -612,9 +608,7 @@ class EIPStatusWidget(QtGui.QWidget): error=True) self.set_eipstatus_off() - # signal connection_aborted to state machine: - qtsigs = self.eipconnection.qtsigs - qtsigs.connection_aborted_signal.emit() + self.aborted() def _on_eip_no_tun_kext_error(self): self.set_eip_status( @@ -623,9 +617,7 @@ class EIPStatusWidget(QtGui.QWidget): "system.").format(self.eip_conductor.eip_name)) self.set_eipstatus_off() - # signal connection_aborted to state machine: - qtsigs = self.eipconnection.qtsigs - qtsigs.connection_aborted_signal.emit() + self.aborted() @QtCore.Slot() def _on_eip_network_unreachable(self): diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index a0eb84a2..5420eb4d 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1624,6 +1624,7 @@ class MainWindow(QtGui.QMainWindow): self.tr("Unable to connect: Problem with provider")) logger.error(data[self._backend.ERROR_KEY]) self._already_started_eip = False + self._eip_status.aborted() # end of EIP methods --------------------------------------------- -- cgit v1.2.3 From 687e1a87da9321b27ad966907db0f58f1c25b157 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 2 Jun 2014 15:45:06 -0500 Subject: add restore clearnet button. Closes: #5726 --- src/leap/bitmask/gui/eip_status.py | 76 +++++++++++++++++++++++++++++------ src/leap/bitmask/gui/ui/eip_status.ui | 27 ++++++++----- 2 files changed, 82 insertions(+), 21 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 e7795083..fd8b35c3 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -31,6 +31,7 @@ from leap.common.check import leap_assert_type from ui_eip_status import Ui_EIPStatus +QtDelayedCall = QtCore.QTimer.singleShot logger = logging.getLogger(__name__) @@ -66,6 +67,9 @@ class EIPStatusWidget(QtGui.QWidget): self._service_name = get_service_display_name(EIP_SERVICE) self.ui.eip_bandwidth.hide() + self.hide_fw_down_button() + self.ui.btnFwDown.clicked.connect( + self._on_fw_down_button_clicked) # Set the EIP status icons self.CONNECTING_ICON = None @@ -109,8 +113,12 @@ class EIPStatusWidget(QtGui.QWidget): signaler.eip_state_changed.connect(self.update_vpn_state) signaler.eip_status_changed.connect(self.update_vpn_status) - signaler.eip_network_unreachable.connect( - self._on_eip_network_unreachable) + + # XXX we cannot connect this signal now because + # it interferes with the proper notifications during restarts + # without available network. + #signaler.eip_network_unreachable.connect( + #self._on_eip_network_unreachable) def _make_status_clickable(self): """ @@ -273,6 +281,8 @@ class EIPStatusWidget(QtGui.QWidget): Disables the start/stop button. """ self.set_startstop_enabled(False) + msg = self.tr("Encrypted Internet is starting") + self.set_eip_message(msg) @QtCore.Slot() def disable_eip_start(self): @@ -314,10 +324,18 @@ class EIPStatusWidget(QtGui.QWidget): if self.isVisible(): self._eip_status_menu.menuAction().setVisible(True) - # XXX disable (later) -------------------------- + def set_eip_message(self, message): + """ + Set the EIP Widget main message. + + :param message: the message to set in the widget + :type message: str or unicode + """ + self.ui.lblEIPMessage.setText(message) + def set_eip_status(self, status, error=False): """ - Sets the status label at the VPN stage to status + Set the status label at the VPN stage to status. :param status: status message :type status: str or unicode @@ -362,6 +380,26 @@ class EIPStatusWidget(QtGui.QWidget): self.ui.btnEipStartStop.clicked.connect( self.eipconnection.qtsigs.do_connect_signal) + def hide_fw_down_button(self): + """ + Hide firewall-down button. + """ + self.ui.btnFwDown.hide() + + def show_fw_down_button(self): + """ + Enable firewall-down button. + """ + self.ui.btnFwDown.show() + + def _on_fw_down_button_clicked(self): + """ + Raise a signal for tearing down the firewall, and hide the button + afterwards. + """ + self.eip_conductor._backend.tear_fw_down() + QtDelayedCall(50, self.hide_fw_down_button) + @QtCore.Slot(dict) def eip_stopped(self, restart=False, failed=False): """ @@ -382,7 +420,7 @@ class EIPStatusWidget(QtGui.QWidget): clear_traffic = self.tr("Traffic is being routed in the clear.") unreachable_net = self.tr("Network is unreachable.") - failed_msg = self.tr("Cannot start Encrypted Proxy.") + failed_msg = self.tr("Cannot start Encrypted Internet") if restart: msg = unreachable_net @@ -390,18 +428,19 @@ class EIPStatusWidget(QtGui.QWidget): msg = failed_msg else: msg = clear_traffic - self.ui.lblEIPMessage.setText(msg) + self.set_eip_message(msg) self.ui.lblEIPStatus.show() + self.show() def eip_failed_to_restart(self): """ Update EIP messages. """ - msg = self.tr("Could not restart Encrypted Proxy") + msg = self.tr("Could not restart Encrypted Internet") self.ui.lblEIPMessage.setText(msg) self.ui.lblEIPStatus.show() - - self.set_eip_status(self.tr("You can start the service manually.")) + self.set_eip_status(self.tr("You can launch the service manually.")) + self.show_fw_down_button() @QtCore.Slot(dict) def update_vpn_status(self, data=None): @@ -462,10 +501,15 @@ class EIPStatusWidget(QtGui.QWidget): # XXX should be handled by the state machine too. # --- is this currently being sent? self.eipconnection.qtsigs.connected_signal.emit() + self._on_eip_connected() # XXX should lookup vpn_state map in EIPConnection elif vpn_state == "AUTH": self.set_eip_status(self.tr("Authenticating...")) + # we wipe up any previous error info in the EIP message + # when we detect vpn authentication is happening + msg = self.tr("Encrypted Internet is starting") + self.set_eip_message(msg) elif vpn_state == "GET_CONFIG": self.set_eip_status(self.tr("Retrieving configuration...")) elif vpn_state == "WAIT": @@ -478,10 +522,10 @@ class EIPStatusWidget(QtGui.QWidget): # Put the following calls in Qt's event queue, otherwise # the UI won't update properly #self.send_disconnect_signal() - QtCore.QTimer.singleShot( + QtDelayedCall( 0, self.eipconnection.qtsigns.do_disconnect_signal.emit) msg = self.tr("Unable to start VPN, it's already running.") - QtCore.QTimer.singleShot(0, partial(self.set_eip_status, msg)) + QtDelayedCall(0, partial(self.set_eip_status, msg)) else: self.set_eip_status(vpn_state) @@ -524,7 +568,8 @@ class EIPStatusWidget(QtGui.QWidget): def set_provider(self, provider): self._provider = provider self.ui.lblEIPMessage.setText( - self.tr("Route traffic through: {0}").format(self._provider)) + self.tr("Routing traffic through: {0}").format( + self._provider)) def aborted(self): """ @@ -619,6 +664,13 @@ class EIPStatusWidget(QtGui.QWidget): self.aborted() + def _on_eip_connected(self): + """ + Reconnect the disconnecting signal when we are just connected, + so that we restore the disconnecting -> stop behaviour. + """ + self.eip_conductor.reconnect_stop_signal() + @QtCore.Slot() def _on_eip_network_unreachable(self): """ diff --git a/src/leap/bitmask/gui/ui/eip_status.ui b/src/leap/bitmask/gui/ui/eip_status.ui index 64821ad6..01d6b371 100644 --- a/src/leap/bitmask/gui/ui/eip_status.ui +++ b/src/leap/bitmask/gui/ui/eip_status.ui @@ -28,7 +28,7 @@ 0 - + Turn On @@ -86,7 +86,7 @@ - + @@ -118,7 +118,7 @@ - + @@ -161,12 +161,13 @@ 0.0 KB/s + + + :/images/black/32/arrow-down.png:/images/black/32/arrow-down.png + true - - :/images/light/16/down-arrow.png - @@ -211,12 +212,13 @@ 0.0 KB/s + + + :/images/black/32/arrow-up.png:/images/black/32/arrow-up.png + true - - :/images/light/16/up-arrow.png - @@ -237,6 +239,13 @@ + + + + Allow unencrypted traffic + + + -- cgit v1.2.3 From 0626d6349472bdcd934328165cfe1a0e7d891bfe Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 4 Jun 2014 10:11:46 -0500 Subject: catch openvpn unexpected ending show also the back-to-clearnet button on that case. --- src/leap/bitmask/gui/eip_status.py | 5 +++++ src/leap/bitmask/gui/mainwindow.py | 1 + 2 files changed, 6 insertions(+) (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 fd8b35c3..7649f840 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -400,6 +400,11 @@ class EIPStatusWidget(QtGui.QWidget): self.eip_conductor._backend.tear_fw_down() QtDelayedCall(50, self.hide_fw_down_button) + # XXX do actual check + msg = "Traffic is being routed in the clear." + self.set_eip_message(msg) + self.set_eip_status("") + @QtCore.Slot(dict) def eip_stopped(self, restart=False, failed=False): """ diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index e7406106..968e5ead 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1564,6 +1564,7 @@ class MainWindow(QtGui.QMainWindow): if should_start and not self._already_started_eip: # XXX this should be handled by the state machine. + self._enable_eip_start_action() self._eip_status.set_eip_status( self.tr("Starting...")) self._eip_status.eip_button.setEnabled(False) -- cgit v1.2.3 From 532a4f63d219e9d9daa1a3252aa8909ca6d8030a Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 4 Jun 2014 11:31:31 -0500 Subject: fix status errors during first eip connection - show eip button - update systray action - remove the provider update on disconnection. --- src/leap/bitmask/gui/eip_status.py | 9 ++++++++- src/leap/bitmask/gui/mainwindow.py | 22 +--------------------- 2 files changed, 9 insertions(+), 22 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 7649f840..f03a1a1d 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -332,6 +332,7 @@ class EIPStatusWidget(QtGui.QWidget): :type message: str or unicode """ self.ui.lblEIPMessage.setText(message) + self.ui.lblEIPMessage.show() def set_eip_status(self, status, error=False): """ @@ -515,6 +516,8 @@ class EIPStatusWidget(QtGui.QWidget): # when we detect vpn authentication is happening msg = self.tr("Encrypted Internet is starting") self.set_eip_message(msg) + # on the first-run path, we hadn't showed the button yet. + self.eip_button.show() elif vpn_state == "GET_CONFIG": self.set_eip_status(self.tr("Retrieving configuration...")) elif vpn_state == "WAIT": @@ -572,9 +575,10 @@ class EIPStatusWidget(QtGui.QWidget): def set_provider(self, provider): self._provider = provider + self.ui.lblEIPMessage.setText( self.tr("Routing traffic through: {0}").format( - self._provider)) + provider)) def aborted(self): """ @@ -594,6 +598,9 @@ class EIPStatusWidget(QtGui.QWidget): TRIGGERS: Signaler.eip_connection_aborted """ + # TODO this name is very misleading, since there's a generic signal + # that's called connection_aborted / connection_died... + # should rename to something more specific about missing config. logger.error("Tried to start EIP but cannot find any " "available provider!") diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 968e5ead..6d30e399 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -158,8 +158,6 @@ class MainWindow(QtGui.QMainWindow): self._eip_conductor.connect_signals() self._eip_conductor.qtsigs.connected_signal.connect( self._on_eip_connection_connected) - self._eip_conductor.qtsigs.disconnected_signal.connect( - self._on_eip_connection_disconnected) self._eip_conductor.qtsigs.connected_signal.connect( self._maybe_run_soledad_setup_checks) @@ -1448,6 +1446,7 @@ class MainWindow(QtGui.QMainWindow): Enables the EIP start action in the systray menu. """ self._action_eip_startstop.setEnabled(True) + self._eip_status.enable_eip_start() @QtCore.Slot() def _on_eip_connection_connected(self): @@ -1468,25 +1467,6 @@ class MainWindow(QtGui.QMainWindow): # check for connectivity self._check_name_resolution(domain) - @QtCore.Slot() - def _on_eip_connection_disconnected(self): - """ - TRIGGERS: - self._eip_conductor.qtsigs.disconnected_signal - - Workaround for updating the eip_status widget with - the provider when the eip connection disconnects. - """ - # TODO - # We should move this to the conductor<->widget interface. - # To do that, we need to subscribe to logged_user, - # for example by using the observer pattern or a proxy object. - user = self._logged_user - if user: - domain = self._login_widget.get_selected_provider() - full_user_id = make_address(user, domain) - self._eip_status.set_provider(full_user_id) - def _check_name_resolution(self, domain): # FIXME this has to be moved to backend !!! # Should move to netchecks module. -- cgit v1.2.3 From aba3ea21d83e6e073baf01643b68832530a6f4d0 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 4 Jun 2014 12:18:18 -0500 Subject: tear down fw on cold starts. Closes: ##5727 --- src/leap/bitmask/gui/eip_status.py | 2 ++ src/leap/bitmask/gui/mainwindow.py | 2 ++ 2 files changed, 4 insertions(+) (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 f03a1a1d..280ce79e 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -85,6 +85,7 @@ class EIPStatusWidget(QtGui.QWidget): self._provider = "" self.is_restart = False + self.is_cold_start = True # Action for the systray self._eip_disabled_action = QtGui.QAction( @@ -508,6 +509,7 @@ class EIPStatusWidget(QtGui.QWidget): # --- is this currently being sent? self.eipconnection.qtsigs.connected_signal.emit() self._on_eip_connected() + self.is_cold_start = False # XXX should lookup vpn_state map in EIPConnection elif vpn_state == "AUTH": diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 6d30e399..a3b81fde 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1543,6 +1543,8 @@ class MainWindow(QtGui.QMainWindow): should_start = self._provides_eip_and_enabled() if should_start and not self._already_started_eip: + if self._eip_status.is_cold_start: + self._backend.tear_fw_down() # XXX this should be handled by the state machine. self._enable_eip_start_action() self._eip_status.set_eip_status( -- cgit v1.2.3 From 2e0062555fd0a092e0f9f25ac46d189b44805108 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 5 Jun 2014 15:21:18 -0300 Subject: Reorder logging helpers and handlers. --- src/leap/bitmask/gui/loggerwindow.py | 2 +- src/leap/bitmask/gui/mainwindow.py | 2 +- 2 files changed, 2 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 f19b172f..3a8354b1 100644 --- a/src/leap/bitmask/gui/loggerwindow.py +++ b/src/leap/bitmask/gui/loggerwindow.py @@ -27,7 +27,7 @@ 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.logs.leap_log_handler import LeapLogHandler from leap.bitmask.util import pastebin from leap.common.check import leap_assert, leap_assert_type diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index a3b81fde..c61b7dc9 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -52,7 +52,7 @@ from leap.bitmask.services import EIP_SERVICE, MX_SERVICE from leap.bitmask.util import make_address from leap.bitmask.util.keyring_helpers import has_keyring -from leap.bitmask.util.leap_log_handler import LeapLogHandler +from leap.bitmask.logs.leap_log_handler import LeapLogHandler if IS_WIN: from leap.bitmask.platform_init.locks import WindowsLock -- cgit v1.2.3 From bc60662ccc740d191cf8a1d368e66459dd1c4ae5 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 5 Jun 2014 15:38:09 -0500 Subject: change elements naming --- src/leap/bitmask/gui/eip_status.py | 21 ++++++++++++--------- src/leap/bitmask/gui/ui/eip_status.ui | 2 +- 2 files changed, 13 insertions(+), 10 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 280ce79e..dcd7ef42 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -249,7 +249,7 @@ class EIPStatusWidget(QtGui.QWidget): def set_action_eip_startstop(self, action_eip_startstop): """ - Sets the action_eip_startstop to use. + Set the action_eip_startstop to use. :param action_eip_startstop: action_eip_status to be used :type action_eip_startstop: QtGui.QAction @@ -392,6 +392,9 @@ class EIPStatusWidget(QtGui.QWidget): """ Enable firewall-down button. """ + retry_msg = self.tr("Retry") + self.ui.btnEipStartStop.setText(retry_msg) + self._action_eip_startstop.setText(retry_msg) self.ui.btnFwDown.show() def _on_fw_down_button_clicked(self): @@ -404,6 +407,7 @@ class EIPStatusWidget(QtGui.QWidget): # XXX do actual check msg = "Traffic is being routed in the clear." + self.ui.btnEipStartStop.setText(self.tr("Turn ON")) self.set_eip_message(msg) self.set_eip_status("") @@ -419,15 +423,13 @@ class EIPStatusWidget(QtGui.QWidget): self._reset_traffic_rates() self.ui.eip_bandwidth.hide() - # XXX FIXME ! ----------------------- this needs to - # accomodate the messages about firewall status. Right now - # we're assuming it works correctly, but we should test fw + # This is assuming the firewall works correctly, but we should test fw # status positively. # Or better call it from the conductor... clear_traffic = self.tr("Traffic is being routed in the clear.") unreachable_net = self.tr("Network is unreachable.") - failed_msg = self.tr("Cannot start Encrypted Internet") + failed_msg = self.tr("Error connecting") if restart: msg = unreachable_net @@ -439,14 +441,15 @@ class EIPStatusWidget(QtGui.QWidget): self.ui.lblEIPStatus.show() self.show() - def eip_failed_to_restart(self): + def eip_failed_to_connect(self): """ - Update EIP messages. + Update EIP messages with error during (re)connection. """ - msg = self.tr("Could not restart Encrypted Internet") + msg = self.tr("Error connecting.") self.ui.lblEIPMessage.setText(msg) self.ui.lblEIPStatus.show() - self.set_eip_status(self.tr("You can launch the service manually.")) + self.set_eip_status(self.tr("Bitmask is blocking " + "unencrypted traffic.")) self.show_fw_down_button() @QtCore.Slot(dict) diff --git a/src/leap/bitmask/gui/ui/eip_status.ui b/src/leap/bitmask/gui/ui/eip_status.ui index 01d6b371..892f0f00 100644 --- a/src/leap/bitmask/gui/ui/eip_status.ui +++ b/src/leap/bitmask/gui/ui/eip_status.ui @@ -242,7 +242,7 @@ - Allow unencrypted traffic + Turn Off -- cgit v1.2.3 From 57aa4d51e37228333e56e98d9af3bfe7b278e2d1 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 5 Jun 2014 16:38:56 -0500 Subject: add icons for the vpn exit nodes --- src/leap/bitmask/gui/eip_status.py | 24 ++++++++++++++++++++++++ src/leap/bitmask/gui/mainwindow.py | 1 + src/leap/bitmask/gui/ui/eip_status.ui | 21 ++++++++++++++------- 3 files changed, 39 insertions(+), 7 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 280ce79e..69ef2616 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -24,6 +24,7 @@ from functools import partial from PySide import QtCore, QtGui +from leap.bitmask.config import flags 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 @@ -416,6 +417,7 @@ class EIPStatusWidget(QtGui.QWidget): Sets the state of the widget to how it should look after EIP has stopped """ + self.set_country_code("") self._reset_traffic_rates() self.ui.eip_bandwidth.hide() @@ -582,6 +584,25 @@ class EIPStatusWidget(QtGui.QWidget): self.tr("Routing traffic through: {0}").format( provider)) + ccode = flags.CURRENT_VPN_COUNTRY + if ccode is not None: + self.set_country_code(ccode) + + def set_country_code(self, code): + """ + Set the pixmap of the given country code + + :param code: the country code + :type code: str + """ + if code is not None and len(code) == 2: + img = ":/images/countries/%s.png" % (code.lower(),) + else: + img = None + cc = self.ui.lblGatewayCountryCode + cc.setPixmap(QtGui.QPixmap(img)) + cc.setToolTip(code) + def aborted(self): """ Notify the state machine that EIP was aborted for some reason. @@ -704,3 +725,6 @@ class EIPStatusWidget(QtGui.QWidget): """ self.set_eip_status("", error=error) self.set_eip_status_icon("error") + +import eipstatus_rc +assert(eipstatus_rc) diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index a3b81fde..c22c8892 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1465,6 +1465,7 @@ class MainWindow(QtGui.QMainWindow): self._already_started_eip = True # check for connectivity + # we might want to leave a little time here... self._check_name_resolution(domain) def _check_name_resolution(self, domain): diff --git a/src/leap/bitmask/gui/ui/eip_status.ui b/src/leap/bitmask/gui/ui/eip_status.ui index 01d6b371..ee24ca71 100644 --- a/src/leap/bitmask/gui/ui/eip_status.ui +++ b/src/leap/bitmask/gui/ui/eip_status.ui @@ -28,7 +28,7 @@ 0 - + Turn On @@ -51,7 +51,7 @@ - + @@ -70,7 +70,7 @@ - + @@ -86,7 +86,7 @@ - + @@ -105,7 +105,7 @@ - + Qt::Horizontal @@ -118,7 +118,7 @@ - + @@ -239,13 +239,20 @@ - + Allow unencrypted traffic + + + + + + + -- cgit v1.2.3