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/mainwindow.py | 122 +++++++++---------------------------- 1 file changed, 30 insertions(+), 92 deletions(-) (limited to 'src/leap/bitmask/gui/mainwindow.py') 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/mainwindow.py') 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/mainwindow.py') 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/mainwindow.py') 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/mainwindow.py | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) (limited to 'src/leap/bitmask/gui/mainwindow.py') 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) -- 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/mainwindow.py') 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/mainwindow.py') 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 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'src/leap/bitmask/gui/mainwindow.py') 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): """ -- 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/mainwindow.py') 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 ++++++++++++++++--------------------- 1 file changed, 88 insertions(+), 119 deletions(-) (limited to 'src/leap/bitmask/gui/mainwindow.py') 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): """ -- 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/mainwindow.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'src/leap/bitmask/gui/mainwindow.py') 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/mainwindow.py') 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/mainwindow.py | 403 +++++++------------------------------ 1 file changed, 71 insertions(+), 332 deletions(-) (limited to 'src/leap/bitmask/gui/mainwindow.py') 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 -- 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 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'src/leap/bitmask/gui/mainwindow.py') 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. -- 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/mainwindow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/bitmask/gui/mainwindow.py') 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) -- 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/mainwindow.py') 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/mainwindow.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/leap/bitmask/gui/mainwindow.py') 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) -- 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 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/leap/bitmask/gui/mainwindow.py') 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() -- 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/mainwindow.py') 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/mainwindow.py | 1 + 1 file changed, 1 insertion(+) (limited to 'src/leap/bitmask/gui/mainwindow.py') 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 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/mainwindow.py | 1 + 1 file changed, 1 insertion(+) (limited to 'src/leap/bitmask/gui/mainwindow.py') 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/mainwindow.py | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) (limited to 'src/leap/bitmask/gui/mainwindow.py') 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/mainwindow.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/leap/bitmask/gui/mainwindow.py') 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/mainwindow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/bitmask/gui/mainwindow.py') 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 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/mainwindow.py | 1 + 1 file changed, 1 insertion(+) (limited to 'src/leap/bitmask/gui/mainwindow.py') 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): -- cgit v1.2.3