From 58e4317945ac857bb57d2a20e38fe9a632b19df0 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 12 Dec 2013 10:14:28 -0300 Subject: Disable and stop EIP on setting save. --- src/leap/bitmask/gui/mainwindow.py | 56 ++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 15 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 929919ac..44fee6b5 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -471,12 +471,49 @@ class MainWindow(QtGui.QMainWindow): Displays the preferences window. """ - preferences_window = PreferencesWindow( + preferences = PreferencesWindow( self, self._srp_auth, self._provider_config, self._soledad, self._login_widget.get_selected_provider()) - self.soledad_ready.connect(preferences_window.set_soledad_ready) - preferences_window.show() + self.soledad_ready.connect(preferences.set_soledad_ready) + preferences.show() + preferences.preferences_saved.connect(self._update_eip_enabled_status) + + def _update_eip_enabled_status(self): + """ + SLOT + TRIGGER: + PreferencesWindow.preferences_saved + + Enable or disable the EIP start/stop actions and stop EIP if the user + disabled that service. + + :returns: if the eip actions were enabled or disabled + :rtype: bool + """ + settings = self._settings + default_provider = settings.get_defaultprovider() + enabled_services = [] + if default_provider is not None: + enabled_services = settings.get_enabled_services(default_provider) + + eip_enabled = False + if EIP_SERVICE in enabled_services: + should_autostart = settings.get_autostart_eip() + if should_autostart and default_provider is not None: + self._eip_status.enable_eip_start() + self._eip_status.set_eip_status("") + eip_enabled = True + else: + # we don't have an usable provider + # so the user needs to log in first + 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")) + + return eip_enabled def _show_eip_preferences(self): """ @@ -1177,21 +1214,10 @@ class MainWindow(QtGui.QMainWindow): """ settings = self._settings - should_autostart = settings.get_autostart_eip() - if not should_autostart: - logger.debug('Will not autostart EIP since it is setup ' - 'to not to do it') - self.eip_needs_login.emit() + if not self._update_eip_enabled_status(): return default_provider = settings.get_defaultprovider() - - if default_provider is None: - logger.info("Cannot autostart Encrypted Internet because there is " - "no default provider configured") - self.eip_needs_login.emit() - return - self._enabled_services = settings.get_enabled_services( default_provider) -- cgit v1.2.3 From 722cf92e10cf73e79e54f463aa19b2d01bd3cf75 Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 11 Dec 2013 22:58:59 -0800 Subject: move login widget to top of main window, move preference buttons to menu. --- src/leap/bitmask/gui/mainwindow.py | 11 ++++++++--- 1 file changed, 8 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 44fee6b5..1c80cce8 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -248,6 +248,8 @@ class MainWindow(QtGui.QMainWindow): 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) self.ui.action_about_leap.triggered.connect(self._about) self.ui.action_quit.triggered.connect(self.quit) self.ui.action_wizard.triggered.connect(self._launch_wizard) @@ -279,8 +281,9 @@ class MainWindow(QtGui.QMainWindow): self._action_visible = QtGui.QAction(self.tr("Hide Main Window"), self) self._action_visible.triggered.connect(self._toggle_visible) - self.ui.btnPreferences.clicked.connect(self._show_preferences) - self.ui.btnEIPPreferences.clicked.connect(self._show_eip_preferences) + # disable buttons for now, may come back later. + # self.ui.btnPreferences.clicked.connect(self._show_preferences) + # self.ui.btnEIPPreferences.clicked.connect(self._show_eip_preferences) self._enabled_services = [] @@ -467,7 +470,8 @@ class MainWindow(QtGui.QMainWindow): """ SLOT TRIGGERS: - self.ui.btnPreferences.clicked + self.ui.btnPreferences.clicked (disabled for now) + self.ui.action_preferences Displays the preferences window. """ @@ -520,6 +524,7 @@ class MainWindow(QtGui.QMainWindow): SLOT TRIGGERS: self.ui.btnEIPPreferences.clicked + self.ui.action_eip_preferences (disabled for now) Displays the EIP preferences window. """ -- cgit v1.2.3 From 6b7a1fc2d567a0adb05e1976f809ff78f550f98e Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Tue, 17 Dec 2013 17:38:40 -0400 Subject: pep8 --- src/leap/bitmask/gui/mainwindow.py | 3 ++- 1 file changed, 2 insertions(+), 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 1c80cce8..75a16eb9 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -249,7 +249,8 @@ class MainWindow(QtGui.QMainWindow): 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) + self.ui.action_eip_preferences.triggered.connect( + self._show_eip_preferences) self.ui.action_about_leap.triggered.connect(self._about) self.ui.action_quit.triggered.connect(self.quit) self.ui.action_wizard.triggered.connect(self._launch_wizard) -- cgit v1.2.3 From d9d558d44660777795d3e85611b0cfe848a92a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Wed, 11 Dec 2013 14:48:49 -0300 Subject: Refactor provider_bootstrapper out of mainwindow --- src/leap/bitmask/gui/mainwindow.py | 139 +++++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 61 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 75a16eb9..7dcb9908 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -18,9 +18,9 @@ Main window for Bitmask. """ import logging -import os from PySide import QtCore, QtGui +from functools import partial from twisted.internet import threads from zope.proxy import ProxyBase, setProxiedObject @@ -42,9 +42,10 @@ from leap.bitmask.gui.systray import SysTray from leap.bitmask import provider from leap.bitmask.platform_init import IS_WIN, IS_MAC from leap.bitmask.platform_init.initializers import init_platform -from leap.bitmask.provider.providerbootstrapper import ProviderBootstrapper -from leap.bitmask.services import get_service_display_name, EIP_SERVICE +from leap.bitmask import backend + +from leap.bitmask.services import get_service_display_name from leap.bitmask.services.mail import conductor as mail_conductor @@ -138,6 +139,9 @@ class MainWindow(QtGui.QMainWindow): self.ui = Ui_MainWindow() self.ui.setupUi(self) + self._backend = backend.Backend(bypass_checks) + self._backend.start() + self._settings = LeapSettings() self._login_widget = LoginWidget( @@ -180,7 +184,10 @@ class MainWindow(QtGui.QMainWindow): # This is loaded only once, there's a bug when doing that more # than once - self._provider_config = ProviderConfig() + # XXX HACK!! But we need it as long as we are using + # provider_config in here + self._provider_config = ( + self._backend._components["provider"]._provider_config) # Used for automatic start of EIP self._provisional_provider_config = ProviderConfig() self._eip_config = eipconfig.EIPConfig() @@ -191,25 +198,7 @@ class MainWindow(QtGui.QMainWindow): self._srp_auth = None self._logged_user = None - # This thread is always running, although it's quite - # lightweight when it's done setting up provider - # configuration and certificate. - self._provider_bootstrapper = ProviderBootstrapper(bypass_checks) - - # Intermediate stages, only do something if there was an error - self._provider_bootstrapper.name_resolution.connect( - self._intermediate_stage) - self._provider_bootstrapper.https_connection.connect( - self._intermediate_stage) - self._provider_bootstrapper.download_ca_cert.connect( - self._intermediate_stage) - - # Important stages, loads the provider config and checks - # certificates - self._provider_bootstrapper.download_provider_info.connect( - self._load_provider_config) - self._provider_bootstrapper.check_api_certificate.connect( - self._provider_config_loaded) + self._backend_connect() # This thread is similar to the provider bootstrapper self._eip_bootstrapper = EIPBootstrapper() @@ -349,7 +338,9 @@ class MainWindow(QtGui.QMainWindow): if self._first_run(): self._wizard_firstrun = True - self._wizard = Wizard(bypass_checks=bypass_checks) + self._backend_disconnect() + 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) self._wizard.accepted.connect(self._finish_init) @@ -359,6 +350,47 @@ class MainWindow(QtGui.QMainWindow): # so this has to be done after eip_machine is started self._finish_init() + def _backend_connect(self): + """ + Helper to connect to backend signals + """ + self._backend.signaler.prov_name_resolution.connect( + self._intermediate_stage) + self._backend.signaler.prov_https_connection.connect( + self._intermediate_stage) + self._backend.signaler.prov_download_ca_cert.connect( + self._intermediate_stage) + + self._backend.signaler.prov_download_provider_info.connect( + self._load_provider_config) + self._backend.signaler.prov_check_api_certificate.connect( + self._provider_config_loaded) + + # Only used at login, no need to disconnect this like we do + # with the other + self._backend.signaler.prov_problem_with_provider.connect( + partial(self._login_widget.set_status, + self.tr("Unable to login: Problem with provider"))) + + def _backend_disconnect(self): + """ + Helper to disconnect from backend signals. + + Some signals are emitted from the wizard, and we want to + ignore those. + """ + self._backend.signaler.prov_name_resolution.disconnect( + self._intermediate_stage) + self._backend.signaler.prov_https_connection.disconnect( + self._intermediate_stage) + self._backend.signaler.prov_download_ca_cert.disconnect( + self._intermediate_stage) + + self._backend.signaler.prov_download_provider_info.disconnect( + self._load_provider_config) + self._backend.signaler.prov_check_api_certificate.disconnect( + self._provider_config_loaded) + def _rejected_wizard(self): """ SLOT @@ -379,6 +411,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._finish_init() def _launch_wizard(self): @@ -394,7 +427,9 @@ class MainWindow(QtGui.QMainWindow): there. """ if self._wizard is None: - self._wizard = Wizard(bypass_checks=self._bypass_checks) + self._backend_disconnect() + self._wizard = Wizard(backend=self._backend, + bypass_checks=self._bypass_checks) self._wizard.accepted.connect(self._finish_init) self._wizard.rejected.connect(self._wizard.close) @@ -628,6 +663,7 @@ class MainWindow(QtGui.QMainWindow): self.eip_needs_login.emit() self._wizard = None + self._backend_connect() else: self._try_autostart_eip() @@ -856,14 +892,12 @@ class MainWindow(QtGui.QMainWindow): # XXX should rename this provider, name clash. provider = self._login_widget.get_selected_provider() - pb = self._provider_bootstrapper - d = pb.run_provider_select_checks(provider, download_if_needed=True) - self._download_provider_defer = d + self._backend.setup_provider(provider) def _load_provider_config(self, data): """ SLOT - TRIGGER: self._provider_bootstrapper.download_provider_info + TRIGGER: 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 @@ -873,31 +907,13 @@ class MainWindow(QtGui.QMainWindow): run_provider_select_checks :type data: dict """ - if data[self._provider_bootstrapper.PASSED_KEY]: - # XXX should rename this provider, name clash. - provider = self._login_widget.get_selected_provider() - - # If there's no loaded provider or - # we want to connect to other provider... - if (not self._provider_config.loaded() or - self._provider_config.get_domain() != provider): - self._provider_config.load( - os.path.join("leap", "providers", - provider, "provider.json")) - - if self._provider_config.loaded(): - self._provider_bootstrapper.run_provider_setup_checks( - self._provider_config, - download_if_needed=True) - else: - self._login_widget.set_status( - self.tr("Unable to login: Problem with provider")) - logger.error("Could not load provider configuration.") - self._login_widget.set_enabled(True) + if data[self._backend.PASSED_KEY]: + selected_provider = self._login_widget.get_selected_provider() + self._backend.provider_bootstrap(selected_provider) else: self._login_widget.set_status( self.tr("Unable to login: Problem with provider")) - logger.error(data[self._provider_bootstrapper.ERROR_KEY]) + logger.error(data[self._backend.ERROR_KEY]) self._login_widget.set_enabled(True) def _login(self): @@ -939,14 +955,14 @@ class MainWindow(QtGui.QMainWindow): def _provider_config_loaded(self, data): """ SLOT - TRIGGER: self._provider_bootstrapper.check_api_certificate + TRIGGER: self._backend.signaler.prov_check_api_certificate Once the provider configuration is loaded, this starts the SRP authentication """ leap_assert(self._provider_config, "We need a provider config!") - if data[self._provider_bootstrapper.PASSED_KEY]: + if data[self._backend.PASSED_KEY]: username = self._login_widget.get_user() password = self._login_widget.get_password() @@ -964,7 +980,7 @@ class MainWindow(QtGui.QMainWindow): else: self._login_widget.set_status( "Unable to login: Problem with provider") - logger.error(data[self._provider_bootstrapper.ERROR_KEY]) + logger.error(data[self._backend.ERROR_KEY]) self._login_widget.set_enabled(True) def _authentication_finished(self, ok, message): @@ -1538,11 +1554,11 @@ class MainWindow(QtGui.QMainWindow): This is used for intermediate bootstrapping stages, in case they fail. """ - passed = data[self._provider_bootstrapper.PASSED_KEY] + passed = data[self._backend.PASSED_KEY] if not passed: self._login_widget.set_status( self.tr("Unable to connect: Problem with provider")) - logger.error(data[self._provider_bootstrapper.ERROR_KEY]) + logger.error(data[self._backend.ERROR_KEY]) self._already_started_eip = False # end of EIP methods --------------------------------------------- @@ -1615,21 +1631,21 @@ class MainWindow(QtGui.QMainWindow): """ SLOT TRIGGERS: - self._provider_bootstrapper.name_resolution - self._provider_bootstrapper.https_connection - self._provider_bootstrapper.download_ca_cert + self._backend.signaler.prov_name_resolution + self._backend.signaler.prov_https_connection + self._backend.signaler.prov_download_ca_cert self._eip_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._provider_bootstrapper.PASSED_KEY] + passed = data[self._backend.PASSED_KEY] if not passed: self._login_widget.set_enabled(True) self._login_widget.set_status( self.tr("Unable to connect: Problem with provider")) - logger.error(data[self._provider_bootstrapper.ERROR_KEY]) + logger.error(data[self._backend.ERROR_KEY]) # # window handling methods @@ -1719,6 +1735,7 @@ class MainWindow(QtGui.QMainWindow): # Set this in case that the app is hidden QtGui.QApplication.setQuitOnLastWindowClosed(True) + self._backend.stop() self._cleanup_and_quit() self._really_quit = True -- cgit v1.2.3 From 2ef6913425a4cae950c01c9d00c1016afbb3206d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Thu, 19 Dec 2013 17:05:38 -0300 Subject: Display domain instead of provider name in the login info --- 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 75a16eb9..979becc6 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -999,7 +999,7 @@ class MainWindow(QtGui.QMainWindow): """ self._login_widget.logged_in() - self.ui.lblLoginProvider.setText(self._provider_config.get_name()) + self.ui.lblLoginProvider.setText(self._provider_config.get_domain()) self._enabled_services = self._settings.get_enabled_services( self._provider_config.get_domain()) -- cgit v1.2.3 From 6f93bd407cb9f36a7ff58e607ebdd069868888ae Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 23 Dec 2013 15:37:52 -0400 Subject: add hash specifically in about dialog. --- src/leap/bitmask/gui/mainwindow.py | 5 +++-- 1 file changed, 3 insertions(+), 2 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 96aa8074..51456473 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -25,6 +25,7 @@ from twisted.internet import threads from zope.proxy import ProxyBase, setProxiedObject from leap.bitmask import __version__ as VERSION +from leap.bitmask import __version_hash__ as VERSION_HASH from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.crypto.srpauth import SRPAuth @@ -829,7 +830,7 @@ class MainWindow(QtGui.QMainWindow): """ QtGui.QMessageBox.about( self, self.tr("About Bitmask - %s") % (VERSION,), - self.tr("Version: %s
" + self.tr("Version: %s (%s)
" "
" "Bitmask is the Desktop client application for " "the LEAP platform, supporting encrypted internet " @@ -842,7 +843,7 @@ class MainWindow(QtGui.QMainWindow): "and widely available.
" "
" "More about LEAP" - "") % (VERSION,)) + "") % (VERSION, VERSION_HASH[:10])) def changeEvent(self, e): """ -- cgit v1.2.3 From 17b19d82439143193af8b8eefcfa05f20d011c89 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 26 Dec 2013 12:37:57 -0400 Subject: comments here and there --- src/leap/bitmask/gui/mainwindow.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 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 51456473..c05d65fe 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -20,6 +20,7 @@ Main window for Bitmask. import logging from PySide import QtCore, QtGui +from datetime import datetime from functools import partial from twisted.internet import threads from zope.proxy import ProxyBase, setProxiedObject @@ -828,10 +829,13 @@ class MainWindow(QtGui.QMainWindow): Display the About Bitmask dialog """ + today = datetime.now().date() + greet = ("Happy New 1984!... or not ;)

" + if today.month == 1 and today.day < 15 else "") QtGui.QMessageBox.about( self, self.tr("About Bitmask - %s") % (VERSION,), self.tr("Version: %s (%s)
" - "
" + "
%s" "Bitmask is the Desktop client application for " "the LEAP platform, supporting encrypted internet " "proxy, secure email, and secure chat (coming soon).
" @@ -843,7 +847,7 @@ class MainWindow(QtGui.QMainWindow): "and widely available.
" "
" "More about LEAP" - "") % (VERSION, VERSION_HASH[:10])) + "") % (VERSION, VERSION_HASH[:10], greet)) def changeEvent(self, e): """ @@ -1070,6 +1074,8 @@ class MainWindow(QtGui.QMainWindow): logger.debug("Retrying soledad connection.") if self._soledad_bootstrapper.should_retry_initialization(): self._soledad_bootstrapper.increment_retries_count() + # XXX should cancel the existing socket --- this + # is avoiding a clean termination. threads.deferToThread( self._soledad_bootstrapper.load_and_sync_soledad) else: -- cgit v1.2.3 From 5e3adedc6c4de23fe8ef5ee99f3c88977c420329 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 6 Jan 2014 18:35:51 -0300 Subject: Disconnect signals before closing the wizard. [Closes #4817] --- src/leap/bitmask/gui/mainwindow.py | 5 +++-- 1 file changed, 3 insertions(+), 2 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 c05d65fe..1fe2cfca 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -414,7 +414,8 @@ class MainWindow(QtGui.QMainWindow): # setup but does not register self._wizard = None self._backend_connect() - self._finish_init() + if self._wizard_firstrun: + self._finish_init() def _launch_wizard(self): """ @@ -433,7 +434,7 @@ class MainWindow(QtGui.QMainWindow): self._wizard = Wizard(backend=self._backend, bypass_checks=self._bypass_checks) self._wizard.accepted.connect(self._finish_init) - self._wizard.rejected.connect(self._wizard.close) + self._wizard.rejected.connect(self._rejected_wizard) self.setVisible(False) # Do NOT use exec_, it will use a child event loop! -- cgit v1.2.3 From 257b42bf0baf923c1437778cd99d0a9cbf69637d Mon Sep 17 00:00:00 2001 From: drebs Date: Tue, 7 Jan 2014 12:40:26 -0200 Subject: Make Soledad wait for EIP before starting (#4885). --- src/leap/bitmask/gui/mainwindow.py | 57 ++++++++++++++++++++++++++------------ 1 file changed, 40 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 c05d65fe..01e72597 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -105,6 +105,9 @@ class MainWindow(QtGui.QMainWindow): # We use this flag to detect abnormal terminations user_stopped_eip = False + # We give EIP some time to come up before starting soledad anyway + EIP_TIMEOUT = 60000 # in milliseconds + def __init__(self, quit_callback, openvpn_verb=1, bypass_checks=False): @@ -179,6 +182,8 @@ class MainWindow(QtGui.QMainWindow): self._eip_status.eip_connection_connected.connect( self._on_eip_connected) + self._eip_status.eip_connection_connected.connect( + self._maybe_run_soledad_setup_checks) self.eip_needs_login.connect( self._eip_status.disable_eip_start) self.eip_needs_login.connect( @@ -195,6 +200,7 @@ class MainWindow(QtGui.QMainWindow): self._eip_config = eipconfig.EIPConfig() self._already_started_eip = False + self._already_started_soledad = False # This is created once we have a valid provider config self._srp_auth = None @@ -1026,22 +1032,27 @@ class MainWindow(QtGui.QMainWindow): self._provider_config.get_domain()) # TODO separate UI from logic. - # TODO soledad should check if we want to run only over EIP. if self._provider_config.provides_mx() and \ self._enabled_services.count(MX_SERVICE) > 0: self._mail_status.about_to_start() + else: + self._mail_status.set_disabled() + + self._maybe_start_eip() + def _maybe_run_soledad_setup_checks(self): + """ + """ + # TODO soledad should check if we want to run only over EIP. + if self._already_started_soledad is False \ + and self._logged_user is not None: + self._already_started_soledad = True self._soledad_bootstrapper.run_soledad_setup_checks( self._provider_config, self._login_widget.get_user(), self._login_widget.get_password(), download_if_needed=True) - else: - self._mail_status.set_disabled() - # XXX the config should be downloaded from the start_eip - # method. - self._download_eip_config() ################################################################### # Service control methods: soledad @@ -1257,7 +1268,7 @@ class MainWindow(QtGui.QMainWindow): # it adds some delay. # Maybe if it's the first run in a session, # or we can try only if it fails. - self._download_eip_config() + self._maybe_start_eip() else: # XXX: Display a proper message to the user self.eip_needs_login.emit() @@ -1489,9 +1500,10 @@ class MainWindow(QtGui.QMainWindow): # eip boostrapping, config etc... - def _download_eip_config(self): + def _maybe_start_eip(self): """ - Starts the EIP bootstrapping sequence + Start the EIP bootstrapping sequence if the client is configured to + do so. """ leap_assert(self._eip_bootstrapper, "We need an eip bootstrapper!") @@ -1508,14 +1520,22 @@ class MainWindow(QtGui.QMainWindow): provider_config, download_if_needed=True) self._already_started_eip = True - elif not self._already_started_eip: - if self._enabled_services.count(EIP_SERVICE) > 0: - self._eip_status.set_eip_status( - self.tr("Not supported"), - error=True) - else: - self._eip_status.disable_eip_start() - self._eip_status.set_eip_status(self.tr("Disabled")) + # we want to start soledad anyway after a certain timeout if eip + # fails to come up + QtCore.QTimer.singleShot( + self.EIP_TIMEOUT, + self._maybe_run_soledad_setup_checks) + else: + if not self._already_started_eip: + if self._enabled_services.count(EIP_SERVICE) > 0: + self._eip_status.set_eip_status( + self.tr("Not supported"), + error=True) + else: + self._eip_status.disable_eip_start() + self._eip_status.set_eip_status(self.tr("Disabled")) + # eip will not start, so we start soledad anyway + self._maybe_run_soledad_setup_checks() def _finish_eip_bootstrap(self, data): """ @@ -1606,6 +1626,9 @@ class MainWindow(QtGui.QMainWindow): self._soledad_bootstrapper.cancel_bootstrap() setProxiedObject(self._soledad, None) + # reset soledad status flag + self._already_started_soledad = False + # XXX: If other defers are doing authenticated stuff, this # might conflict with those. CHECK! threads.deferToThread(self._srp_auth.logout) -- cgit v1.2.3 From 74397ee78ab7f01cb622b0e06b3de901a3604f0b Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 7 Jan 2014 18:25:21 -0300 Subject: Warn the user if is using an old app version. [Closes #4636] --- src/leap/bitmask/gui/mainwindow.py | 15 +++++++++++++++ 1 file changed, 15 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 f954006d..69cb4169 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -380,6 +380,9 @@ class MainWindow(QtGui.QMainWindow): partial(self._login_widget.set_status, self.tr("Unable to login: Problem with provider"))) + self._backend.signaler.prov_unsupported_client.connect( + self._needs_update) + def _backend_disconnect(self): """ Helper to disconnect from backend signals. @@ -856,6 +859,18 @@ class MainWindow(QtGui.QMainWindow): "More about LEAP" "") % (VERSION, VERSION_HASH[:10], greet)) + def _needs_update(self): + """ + Display a warning dialog to inform the user that the app needs update. + """ + url = "https://dl.bitmask.net/" + msg = self.tr( + "The current client version is not supported " + "by this provider.
" + "Please update to latest version.

" + "You can get the latest version from {0}").format(url) + QtGui.QMessageBox.warning(self, self.tr("Update Needed"), msg) + def changeEvent(self, e): """ Reimplements the changeEvent method to minimize to tray -- cgit v1.2.3 From 504936617069b7dcba497ba6daf630769c36d4fd Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 7 Jan 2014 18:47:26 -0300 Subject: Move a provider problem to a separate signal. - Some code cleanup - Fix typos --- src/leap/bitmask/gui/mainwindow.py | 50 +++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 28 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 69cb4169..1bbce8d4 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -21,7 +21,6 @@ import logging from PySide import QtCore, QtGui from datetime import datetime -from functools import partial from twisted.internet import threads from zope.proxy import ProxyBase, setProxiedObject @@ -362,26 +361,19 @@ class MainWindow(QtGui.QMainWindow): """ Helper to connect to backend signals """ - self._backend.signaler.prov_name_resolution.connect( - self._intermediate_stage) - self._backend.signaler.prov_https_connection.connect( - self._intermediate_stage) - self._backend.signaler.prov_download_ca_cert.connect( - self._intermediate_stage) + sig = self._backend.signaler + sig.prov_name_resolution.connect(self._intermediate_stage) + sig.prov_https_connection.connect(self._intermediate_stage) + sig.prov_download_ca_cert.connect(self._intermediate_stage) - self._backend.signaler.prov_download_provider_info.connect( - self._load_provider_config) - self._backend.signaler.prov_check_api_certificate.connect( - self._provider_config_loaded) + sig.prov_download_provider_info.connect(self._load_provider_config) + sig.prov_check_api_certificate.connect(self._provider_config_loaded) # Only used at login, no need to disconnect this like we do # with the other - self._backend.signaler.prov_problem_with_provider.connect( - partial(self._login_widget.set_status, - self.tr("Unable to login: Problem with provider"))) + sig.prov_problem_with_provider.connect(self._login_problem_provider) - self._backend.signaler.prov_unsupported_client.connect( - self._needs_update) + sig.prov_unsupported_client.connect(self._needs_update) def _backend_disconnect(self): """ @@ -390,17 +382,13 @@ class MainWindow(QtGui.QMainWindow): Some signals are emitted from the wizard, and we want to ignore those. """ - self._backend.signaler.prov_name_resolution.disconnect( - self._intermediate_stage) - self._backend.signaler.prov_https_connection.disconnect( - self._intermediate_stage) - self._backend.signaler.prov_download_ca_cert.disconnect( - self._intermediate_stage) + sig = self._backend.signaler + sig.prov_name_resolution.disconnect(self._intermediate_stage) + sig.prov_https_connection.disconnect(self._intermediate_stage) + sig.prov_download_ca_cert.disconnect(self._intermediate_stage) - self._backend.signaler.prov_download_provider_info.disconnect( - self._load_provider_config) - self._backend.signaler.prov_check_api_certificate.disconnect( - self._provider_config_loaded) + sig.prov_download_provider_info.disconnect(self._load_provider_config) + sig.prov_check_api_certificate.disconnect(self._provider_config_loaded) def _rejected_wizard(self): """ @@ -938,11 +926,17 @@ class MainWindow(QtGui.QMainWindow): selected_provider = self._login_widget.get_selected_provider() self._backend.provider_bootstrap(selected_provider) else: - self._login_widget.set_status( - self.tr("Unable to login: Problem with provider")) logger.error(data[self._backend.ERROR_KEY]) self._login_widget.set_enabled(True) + def _login_problem_provider(self): + """ + Warns the user about a problem with the provider during login. + """ + self._login_widget.set_status( + self.tr("Unable to login: Problem with provider")) + self._login_widget.set_enabled(True) + def _login(self): """ SLOT -- cgit v1.2.3 From f4a0747e216fb651628490f7849d2e4c9c6d8092 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 7 Jan 2014 19:06:49 -0300 Subject: Warn the user on incompatible api error. - Add a proper signal for the incompatible api error. - Warn the user of an incompatible api. --- src/leap/bitmask/gui/mainwindow.py | 11 +++++++++++ 1 file changed, 11 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 1bbce8d4..8c512ad2 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -374,6 +374,7 @@ class MainWindow(QtGui.QMainWindow): sig.prov_problem_with_provider.connect(self._login_problem_provider) sig.prov_unsupported_client.connect(self._needs_update) + sig.prov_unsupported_api.connect(self._incompatible_api) def _backend_disconnect(self): """ @@ -859,6 +860,16 @@ class MainWindow(QtGui.QMainWindow): "You can get the latest version from {0}").format(url) QtGui.QMessageBox.warning(self, self.tr("Update Needed"), msg) + def _incompatible_api(self): + """ + Display a warning dialog to inform the user that the provider has an + incompatible API. + """ + msg = self.tr( + "This provider is not compatible with the client.

" + "Error: API version incompatible.") + QtGui.QMessageBox.warning(self, self.tr("Incompatible Provider"), msg) + def changeEvent(self, e): """ Reimplements the changeEvent method to minimize to tray -- cgit v1.2.3 From a1db341a39ec336ab62e89280f9bfb315420bfb5 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Sat, 11 Jan 2014 23:10:09 -0400 Subject: offline mode This will skip: * srp authentication with server * remote soledad configuration * keymanager sending key to server * imap fetches. Its main goal is to help us while debugging imap accounts, by cutting almost all communication with server. It will break havoc if you use it without having local keys configured. So, basically, use with care. --- src/leap/bitmask/gui/mainwindow.py | 134 +++++++++++++++++++++++++++++-------- 1 file changed, 107 insertions(+), 27 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 8c512ad2..18ef56e5 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # mainwindow.py -# Copyright (C) 2013 LEAP +# Copyright (C) 2013, 2014 LEAP # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ from zope.proxy import ProxyBase, setProxiedObject 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.crypto.srpauth import SRPAuth @@ -68,6 +69,7 @@ from leap.bitmask.services.eip.darwinvpnlauncher import EIPNoTunKextLoaded from leap.bitmask.services.soledad.soledadbootstrapper import \ SoledadBootstrapper +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 @@ -95,6 +97,7 @@ class MainWindow(QtGui.QMainWindow): # Signals eip_needs_login = QtCore.Signal([]) + offline_mode_bypass_login = QtCore.Signal([]) new_updates = QtCore.Signal(object) raise_window = QtCore.Signal([]) soledad_ready = QtCore.Signal([]) @@ -137,12 +140,11 @@ class MainWindow(QtGui.QMainWindow): # end register leap events #################################### self._quit_callback = quit_callback - self._updates_content = "" + # setup UI self.ui = Ui_MainWindow() self.ui.setupUi(self) - self._backend = backend.Backend(bypass_checks) self._backend.start() @@ -183,6 +185,9 @@ class MainWindow(QtGui.QMainWindow): self._on_eip_connected) self._eip_status.eip_connection_connected.connect( self._maybe_run_soledad_setup_checks) + self.offline_mode_bypass_login.connect( + self._maybe_run_soledad_setup_checks) + self.eip_needs_login.connect( self._eip_status.disable_eip_start) self.eip_needs_login.connect( @@ -204,6 +209,7 @@ class MainWindow(QtGui.QMainWindow): # This is created once we have a valid provider config self._srp_auth = None self._logged_user = None + self._logged_in_offline = False self._backend_connect() @@ -239,6 +245,8 @@ class MainWindow(QtGui.QMainWindow): 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_timeout.connect( self._retry_soledad_connection) self._soledad_bootstrapper.soledad_failed.connect( @@ -284,8 +292,9 @@ class MainWindow(QtGui.QMainWindow): self._enabled_services = [] - self._center_window() + # last minute UI manipulations + self._center_window() self.ui.lblNewUpdates.setVisible(False) self.ui.btnMore.setVisible(False) ######################################### @@ -294,6 +303,8 @@ class MainWindow(QtGui.QMainWindow): self.ui.btnMore.resize(0, 0) ######################################### self.ui.btnMore.clicked.connect(self._updates_details) + if flags.OFFLINE is True: + self._set_label_offline() # Services signals/slots connection self.new_updates.connect(self._react_to_new_updates) @@ -706,6 +717,19 @@ class MainWindow(QtGui.QMainWindow): self.ui.eipWidget.setVisible(EIP_SERVICE in services) self.ui.mailWidget.setVisible(MX_SERVICE in services) + def _set_label_offline(self): + """ + Set the login label to reflect offline status. + """ + if self._logged_in_offline: + provider = "" + else: + provider = self.ui.lblLoginProvider.text() + + self.ui.lblLoginProvider.setText( + provider + + self.tr(" (offline mode)")) + # # systray # @@ -917,7 +941,6 @@ class MainWindow(QtGui.QMainWindow): """ # XXX should rename this provider, name clash. provider = self._login_widget.get_selected_provider() - self._backend.setup_provider(provider) def _load_provider_config(self, data): @@ -930,7 +953,7 @@ class MainWindow(QtGui.QMainWindow): part of the bootstrapping sequence :param data: result from the last stage of the - run_provider_select_checks + run_provider_select_checks :type data: dict """ if data[self._backend.PASSED_KEY]: @@ -959,10 +982,21 @@ class MainWindow(QtGui.QMainWindow): start the SRP authentication, and as the last step bootstrapping the EIP service """ - leap_assert(self._provider_config, "We need a provider config") - - if self._login_widget.start_login(): - self._download_provider_config() + # TODO most of this could ve handled by the login widget, + # but we'd have to move lblLoginProvider into the widget itself, + # instead of having it as a top-level attribute. + if flags.OFFLINE is True: + logger.debug("OFFLINE mode! bypassing remote login") + # TODO reminder, we're not handling logout for offline + # mode. + self._login_widget.logged_in() + self._logged_in_offline = True + self._set_label_offline() + self.offline_mode_bypass_login.emit() + else: + leap_assert(self._provider_config, "We need a provider config") + if self._login_widget.start_login(): + self._download_provider_config() def _cancel_login(self): """ @@ -1033,8 +1067,8 @@ class MainWindow(QtGui.QMainWindow): self._logged_user = self._login_widget.get_user() user = self._logged_user domain = self._provider_config.get_domain() - userid = "%s@%s" % (user, domain) - self._mail_conductor.userid = userid + full_user_id = make_address(user, domain) + self._mail_conductor.userid = full_user_id self._login_defer = None self._start_eip_bootstrap() else: @@ -1047,7 +1081,8 @@ class MainWindow(QtGui.QMainWindow): """ self._login_widget.logged_in() - self.ui.lblLoginProvider.setText(self._provider_config.get_domain()) + provider = self._provider_config.get_domain() + self.ui.lblLoginProvider.setText(provider) self._enabled_services = self._settings.get_enabled_services( self._provider_config.get_domain()) @@ -1063,17 +1098,42 @@ class MainWindow(QtGui.QMainWindow): def _maybe_run_soledad_setup_checks(self): """ + Conditionally start Soledad. """ - # TODO soledad should check if we want to run only over EIP. - if self._already_started_soledad is False \ - and self._logged_user is not None: - self._already_started_soledad = True - self._soledad_bootstrapper.run_soledad_setup_checks( - self._provider_config, - self._login_widget.get_user(), - self._login_widget.get_password(), - download_if_needed=True) + # TODO split. + if self._already_started_soledad is True: + return + + username = self._login_widget.get_user() + 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)) + + full_user_id = make_address(username, provider_domain) + uuid = self._settings.get_uuid(full_user_id) + self._mail_conductor.userid = full_user_id + + if uuid is None: + # We don't need more visibility at the moment, + # 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) + else: + provider_config = self._provider_config + if self._logged_user is not None: + fun = sb.run_soledad_setup_checks + fun(provider_config, username, password, + download_if_needed=True) ################################################################### # Service control methods: soledad @@ -1119,6 +1179,7 @@ class MainWindow(QtGui.QMainWindow): SLOT TRIGGERS: self._soledad_bootstrapper.gen_key + self._soledad_bootstrapper.local_only_ready If there was a problem, displays it, otherwise it does nothing. This is used for intermediate bootstrapping stages, in case @@ -1160,6 +1221,10 @@ class MainWindow(QtGui.QMainWindow): TRIGGERS: self.soledad_ready """ + if flags.OFFLINE is True: + logger.debug("not starting smtp in offline mode") + return + # TODO for simmetry, this should be called start_smtp_service # (and delegate all the checks to the conductor) if self._provider_config.provides_mx() and \ @@ -1191,9 +1256,24 @@ class MainWindow(QtGui.QMainWindow): TRIGGERS: self.soledad_ready """ + # 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 is True: + 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: + start_fun() + return + + enabled_services = self._enabled_services if self._provider_config.provides_mx() and \ - self._enabled_services.count(MX_SERVICE) > 0: - self._mail_conductor.start_imap_service() + enabled_services.count(MX_SERVICE) > 0: + start_fun() def _on_mail_client_logged_in(self, req): """ @@ -1423,8 +1503,9 @@ class MainWindow(QtGui.QMainWindow): if self._logged_user: self._eip_status.set_provider( - "%s@%s" % (self._logged_user, - self._get_best_provider_config().get_domain())) + make_address( + self._logged_user, + self._get_best_provider_config().get_domain())) self._eip_status.eip_stopped() @QtCore.Slot() @@ -1643,7 +1724,6 @@ class MainWindow(QtGui.QMainWindow): Starts the logout sequence """ - self._soledad_bootstrapper.cancel_bootstrap() setProxiedObject(self._soledad, None) -- cgit v1.2.3 From 6cc752e403e08795273270f637ed212270d2eaef Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Sat, 11 Jan 2014 23:17:06 -0400 Subject: beautify link to downloads (make it a link) --- src/leap/bitmask/gui/mainwindow.py | 3 ++- 1 file changed, 2 insertions(+), 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 18ef56e5..83aa47a9 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -881,7 +881,8 @@ class MainWindow(QtGui.QMainWindow): "The current client version is not supported " "by this provider.
" "Please update to latest version.

" - "You can get the latest version from {0}").format(url) + "You can get the latest version from " + "{1}").format(url, url) QtGui.QMessageBox.warning(self, self.tr("Update Needed"), msg) def _incompatible_api(self): -- cgit v1.2.3 From 24e7c4f505d92164187c8afe038b24c67e2bdedc Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 13 Jan 2014 14:20:33 -0300 Subject: Use set_status for all messages. Remove set_login_status since it's a remaining code after split the login in a separated widget. [Closes #4942] --- 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 83aa47a9..ddaa085c 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1754,9 +1754,8 @@ class MainWindow(QtGui.QMainWindow): self._mail_status.mail_state_disabled() else: - self._login_widget.set_login_status( - self.tr("Something went wrong with the logout."), - error=True) + self._login_widget.set_status( + self.tr("Something went wrong with the logout.")) def _intermediate_stage(self, data): # TODO this method name is confusing as hell. -- cgit v1.2.3 From 9bfaaded5adf66a129fb35c2e561a4e435a9179d Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 14 Jan 2014 13:59:14 -0300 Subject: Add dialog with instructions to configure mail. [Closes #4530] --- src/leap/bitmask/gui/mainwindow.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 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 ddaa085c..3f41900b 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -81,6 +81,8 @@ from leap.common.check import leap_assert from leap.common.events import register from leap.common.events import events_pb2 as proto +from leap.mail.imap.service.imap import IMAP_PORT + from ui_mainwindow import Ui_MainWindow logger = logging.getLogger(__name__) @@ -259,6 +261,7 @@ class MainWindow(QtGui.QMainWindow): self.ui.action_quit.triggered.connect(self.quit) self.ui.action_wizard.triggered.connect(self._launch_wizard) self.ui.action_show_logs.triggered.connect(self._show_logger_window) + self.ui.action_help.triggered.connect(self._help) self.ui.action_create_new_account.triggered.connect( self._launch_wizard) @@ -872,6 +875,33 @@ class MainWindow(QtGui.QMainWindow): "More about LEAP" "") % (VERSION, VERSION_HASH[:10], greet)) + def _help(self): + """ + SLOT + TRIGGERS: self.ui.action_help.triggered + + Display the Bitmask help dialog. + """ + # TODO: don't hardcode! + smtp_port = 2013 + + url = ("bitmask addon") + + msg = ( + "Instructions to use mail:
" + "If you use Thunderbird you can use the Bitmask extension helper. " + "Search for 'Bitmask' in the add-on manager or download it " + "from: {0}.

" + "You can configure bitmask manually with this options:
" + "" + " Incoming -> IMAP, port: {1}
" + " Outgoing -> SMTP, port: {2}
" + " Username -> your bitmask username.
" + " Password -> leave it empty." + "
").format(url, IMAP_PORT, smtp_port) + QtGui.QMessageBox.about(self, self.tr("Bitmask Help"), msg) + def _needs_update(self): """ Display a warning dialog to inform the user that the app needs update. -- cgit v1.2.3 From 4426635373a4f59249f4da17b581cea3ee7f33d8 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 22 Jan 2014 14:58:38 -0300 Subject: Don't use an empty password to configure email. - Also add translation support for the help message. [Closes #4985] --- src/leap/bitmask/gui/mainwindow.py | 5 +++-- 1 file changed, 3 insertions(+), 2 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 3f41900b..ffedfa1c 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -888,7 +888,7 @@ class MainWindow(QtGui.QMainWindow): url = ("bitmask addon") - msg = ( + msg = self.tr( "Instructions to use mail:
" "If you use Thunderbird you can use the Bitmask extension helper. " "Search for 'Bitmask' in the add-on manager or download it " @@ -898,7 +898,8 @@ class MainWindow(QtGui.QMainWindow): " Incoming -> IMAP, port: {1}
" " Outgoing -> SMTP, port: {2}
" " Username -> your bitmask username.
" - " Password -> leave it empty." + " Password -> does not matter, use any text. " + " Just don't leave it empty and don't use your account's password." "").format(url, IMAP_PORT, smtp_port) QtGui.QMessageBox.about(self, self.tr("Bitmask Help"), msg) -- cgit v1.2.3 From d0499461511541ea3ca3b0b1bb3f0f5c7f900c86 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 5 Feb 2014 20:13:31 -0400 Subject: fix typos --- 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 ffedfa1c..86fc1022 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -893,7 +893,7 @@ class MainWindow(QtGui.QMainWindow): "If you use Thunderbird you can use the Bitmask extension helper. " "Search for 'Bitmask' in the add-on manager or download it " "from: {0}.

" - "You can configure bitmask manually with this options:
" + "You can configure Bitmask manually with these options:
" "" " Incoming -> IMAP, port: {1}
" " Outgoing -> SMTP, port: {2}
" -- cgit v1.2.3 From e4c80d78567d79ff0ad4be8e15629e9ed93259bb Mon Sep 17 00:00:00 2001 From: drebs Date: Thu, 6 Feb 2014 15:39:14 -0200 Subject: Ensure IMAP flushes data to disk before quitting. Closes #5095. --- src/leap/bitmask/gui/mainwindow.py | 14 +++++++++++--- 1 file changed, 11 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 86fc1022..db24a1c8 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -19,6 +19,7 @@ Main window for Bitmask. """ import logging +from threading import Condition from PySide import QtCore, QtGui from datetime import datetime from twisted.internet import threads @@ -112,6 +113,9 @@ class MainWindow(QtGui.QMainWindow): # We give EIP some time to come up before starting soledad anyway EIP_TIMEOUT = 60000 # in milliseconds + # We give each service some time to come to a halt before forcing quit + SERVICE_STOP_TIMEOUT = 20 + def __init__(self, quit_callback, openvpn_verb=1, bypass_checks=False): @@ -1330,8 +1334,13 @@ class MainWindow(QtGui.QMainWindow): TRIGGERS: self.logout """ + cv = Condition() + cv.acquire() # TODO call stop_mail_service - self._mail_conductor.stop_imap_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) @@ -1857,7 +1866,7 @@ class MainWindow(QtGui.QMainWindow): """ logger.debug('About to quit, doing cleanup...') - self._mail_conductor.stop_imap_service() + self._stop_imap_service() if self._srp_auth is not None: if self._srp_auth.get_session_id() is not None or \ @@ -1899,7 +1908,6 @@ class MainWindow(QtGui.QMainWindow): self._backend.stop() self._cleanup_and_quit() - self._really_quit = True if self._wizard: -- cgit v1.2.3 From 61420592e80d5446f8a5fba317316beeaff287e2 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 7 Feb 2014 16:07:26 -0300 Subject: Pep8 fixes, remove commented ipdb, group imports. --- src/leap/bitmask/gui/mainwindow.py | 3 ++- 1 file changed, 2 insertions(+), 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 db24a1c8..c078e3f4 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -20,8 +20,9 @@ Main window for Bitmask. import logging from threading import Condition -from PySide import QtCore, QtGui from datetime import datetime + +from PySide import QtCore, QtGui from twisted.internet import threads from zope.proxy import ProxyBase, setProxiedObject -- cgit v1.2.3 From 29902330067f564185d7b57a864be2099f8ea2e8 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 10 Feb 2014 14:29:09 -0300 Subject: Properly handle defer cancelling. - Fix issues related to "Cancel login does not work". - Move srpauth errback to mainwindow. - Add signal for provider setup cancel. - Add support to cancel the soledad defer. [Closes #4869] [Closes #4973] --- src/leap/bitmask/gui/mainwindow.py | 69 +++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 15 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 c078e3f4..6512ffce 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -23,8 +23,9 @@ from threading import Condition from datetime import datetime from PySide import QtCore, QtGui -from twisted.internet import threads from zope.proxy import ProxyBase, setProxiedObject +from twisted.internet import threads +from twisted.internet.defer import CancelledError from leap.bitmask import __version__ as VERSION from leap.bitmask import __version_hash__ as VERSION_HASH @@ -342,7 +343,7 @@ class MainWindow(QtGui.QMainWindow): self._keymanager = ProxyBase(None) self._login_defer = None - self._download_provider_defer = None + self._soledad_defer = None self._mail_conductor = mail_conductor.MailConductor( self._soledad, self._keymanager) @@ -395,6 +396,8 @@ class MainWindow(QtGui.QMainWindow): sig.prov_unsupported_client.connect(self._needs_update) sig.prov_unsupported_api.connect(self._incompatible_api) + sig.prov_cancelled_setup.connect(self._set_login_cancelled) + def _backend_disconnect(self): """ Helper to disconnect from backend signals. @@ -1035,6 +1038,25 @@ class MainWindow(QtGui.QMainWindow): if self._login_widget.start_login(): self._download_provider_config() + def _login_errback(self, failure): + """ + Error handler for the srpauth.authenticate method. + + :param failure: failure object that Twisted generates + :type failure: twisted.python.failure.Failure + """ + # NOTE: this behavior needs to be managed through the signaler, + # as we are doing with the prov_cancelled_setup signal. + # After we move srpauth to the backend, we need to update this. + logger.error("Error logging in, {0!r}".format(failure)) + if failure.check(CancelledError): + logger.debug("Defer cancelled.") + failure.trap(Exception) + self._set_login_cancelled() + else: + self._login_widget.set_status(str(failure.value)) + self._login_widget.set_enabled(True) + def _cancel_login(self): """ SLOT @@ -1043,17 +1065,29 @@ class MainWindow(QtGui.QMainWindow): Stops the login sequence. """ - logger.debug("Cancelling log in.") + logger.debug("Cancelling setup provider defer.") + self._backend.cancel_setup_provider() - if self._download_provider_defer: - logger.debug("Cancelling download provider defer.") - self._download_provider_defer.cancel() - - if self._login_defer: + if self._login_defer is not None: logger.debug("Cancelling login defer.") self._login_defer.cancel() + if self._soledad_defer is not None: + logger.debug("Cancelling soledad defer.") + self._soledad_defer.cancel() + + def _set_login_cancelled(self): + """ + SLOT + TRIGGERS: + Signaler.prov_cancelled_setup fired by + self._backend.cancel_setup_provider() + + This method re-enables the login widget and display a message for + the cancelled operation. + """ self._login_widget.set_status(self.tr("Log in cancelled by the user.")) + self._login_widget.set_enabled(True) def _provider_config_loaded(self, data): """ @@ -1080,6 +1114,7 @@ class MainWindow(QtGui.QMainWindow): # TODO Add errback! self._login_defer = self._srp_auth.authenticate(username, password) + self._login_defer.addErrback(self._login_errback) else: self._login_widget.set_status( "Unable to login: Problem with provider") @@ -1168,8 +1203,8 @@ class MainWindow(QtGui.QMainWindow): provider_config = self._provider_config if self._logged_user is not None: - fun = sb.run_soledad_setup_checks - fun(provider_config, username, password, + self._soledad_defer = sb.run_soledad_setup_checks( + provider_config, username, password, download_if_needed=True) ################################################################### @@ -1243,6 +1278,7 @@ class MainWindow(QtGui.QMainWindow): # Ok, now soledad is ready, so we can allow other things that # depend on soledad to start. + self._soledad_defer = None # this will trigger start_imap_service # and start_smtp_boostrapping @@ -1814,9 +1850,9 @@ class MainWindow(QtGui.QMainWindow): """ passed = data[self._backend.PASSED_KEY] if not passed: + msg = self.tr("Unable to connect: Problem with provider") + self._login_widget.set_status(msg) self._login_widget.set_enabled(True) - self._login_widget.set_status( - self.tr("Unable to connect: Problem with provider")) logger.error(data[self._backend.ERROR_KEY]) # @@ -1888,9 +1924,12 @@ class MainWindow(QtGui.QMainWindow): logger.debug("Cancelling login defer.") self._login_defer.cancel() - if self._download_provider_defer: - logger.debug("Cancelling download provider defer.") - self._download_provider_defer.cancel() + logger.debug("Cancelling setup provider defer.") + self._backend.cancel_setup_provider() + + if self._soledad_defer is not None: + logger.debug("Cancelling soledad defer.") + self._soledad_defer.cancel() # TODO missing any more cancels? -- cgit v1.2.3 From 2d45a0e1cb0791c7e94b5d2a33c498954055a38e Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 13 Feb 2014 11:02:31 -0300 Subject: Improve logout action and fix typo. Related to #5131. [Closes #4815] --- src/leap/bitmask/gui/mainwindow.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 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 6512ffce..b14ca19e 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1112,7 +1112,6 @@ class MainWindow(QtGui.QMainWindow): self._srp_auth.logout_finished.connect( self._done_logging_out) - # TODO Add errback! self._login_defer = self._srp_auth.authenticate(username, password) self._login_defer.addErrback(self._login_errback) else: @@ -1143,6 +1142,13 @@ class MainWindow(QtGui.QMainWindow): self._mail_conductor.userid = full_user_id self._login_defer = None self._start_eip_bootstrap() + + # if soledad/mail is enabled: + 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_failed.connect(lambda: btn_enabled(True)) else: self._login_widget.set_enabled(True) @@ -1804,6 +1810,9 @@ class MainWindow(QtGui.QMainWindow): """ self._soledad_bootstrapper.cancel_bootstrap() setProxiedObject(self._soledad, None) + if self._soledad_defer is not None: + logger.debug("Cancelling soledad defer.") + self._soledad_defer.cancel() # reset soledad status flag self._already_started_soledad = False -- cgit v1.2.3 From 0af54b404fb82c4c3c36c9252f3df77afe104ff1 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 24 Feb 2014 16:38:40 -0300 Subject: Connect with correct soledad_failed signal. --- src/leap/bitmask/gui/mainwindow.py | 3 ++- 1 file changed, 2 insertions(+), 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 b14ca19e..eeab7e2b 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1148,7 +1148,8 @@ class MainWindow(QtGui.QMainWindow): btn_enabled = self._login_widget.set_logout_btn_enabled btn_enabled(False) self.soledad_ready.connect(lambda: btn_enabled(True)) - self.soledad_failed.connect(lambda: btn_enabled(True)) + self._soledad_bootstrapper.soledad_failed.connect( + lambda: btn_enabled(True)) else: self._login_widget.set_enabled(True) -- cgit v1.2.3 From f4893104fb402624f788273bc047aac63da673d7 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 6 Mar 2014 14:40:56 -0300 Subject: Select current provider as default in eip settings Set as selected default for the eip preferences window the item selented in the bitmask main window. [Closes #5153] --- src/leap/bitmask/gui/mainwindow.py | 3 ++- 1 file changed, 2 insertions(+), 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 eeab7e2b..13e289fb 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -587,7 +587,8 @@ class MainWindow(QtGui.QMainWindow): Displays the EIP preferences window. """ - EIPPreferencesWindow(self).show() + domain = self._login_widget.get_selected_provider() + EIPPreferencesWindow(self, domain).show() # # updates -- cgit v1.2.3 From 17fcf4f3efd1c016bd0f93129b4bedfd8ca92309 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 7 Mar 2014 17:24:33 -0300 Subject: Run all the soledad bootstrap on error. Before this fix, if the soledad bootstrapping failed during the first download process, we retried since after that point which caused a failure. --- src/leap/bitmask/gui/mainwindow.py | 3 +-- 1 file changed, 1 insertion(+), 2 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 eeab7e2b..6ef3920f 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1247,8 +1247,7 @@ class MainWindow(QtGui.QMainWindow): self._soledad_bootstrapper.increment_retries_count() # XXX should cancel the existing socket --- this # is avoiding a clean termination. - threads.deferToThread( - self._soledad_bootstrapper.load_and_sync_soledad) + self._maybe_run_soledad_setup_checks() else: logger.warning("Max number of soledad initialization " "retries reached.") -- cgit v1.2.3 From f274193b30cbe28f75a976b0fd5710f06c2c9c49 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 5 Mar 2014 17:02:09 -0300 Subject: Move all the defer cancelling to a method. Also add X_defer = None for the defers after being cancelled. --- src/leap/bitmask/gui/mainwindow.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 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 eeab7e2b..2c1d56d3 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1065,16 +1065,24 @@ class MainWindow(QtGui.QMainWindow): Stops the login sequence. """ - logger.debug("Cancelling setup provider defer.") + logger.debug("Cancelling log in.") + self._cancel_ongoing_defers() + + def _cancel_ongoing_defers(self): + """ + Cancel the running defers to avoid app blocking. + """ self._backend.cancel_setup_provider() if self._login_defer is not None: logger.debug("Cancelling login defer.") self._login_defer.cancel() + self._login_defer = None if self._soledad_defer is not None: logger.debug("Cancelling soledad defer.") self._soledad_defer.cancel() + self._soledad_defer = None def _set_login_cancelled(self): """ @@ -1811,9 +1819,8 @@ class MainWindow(QtGui.QMainWindow): """ self._soledad_bootstrapper.cancel_bootstrap() setProxiedObject(self._soledad, None) - if self._soledad_defer is not None: - logger.debug("Cancelling soledad defer.") - self._soledad_defer.cancel() + + self._cancel_ongoing_defers() # reset soledad status flag self._already_started_soledad = False @@ -1930,16 +1937,7 @@ class MainWindow(QtGui.QMainWindow): logger.debug('Terminating vpn') self._vpn.terminate(shutdown=True) - if self._login_defer: - logger.debug("Cancelling login defer.") - self._login_defer.cancel() - - logger.debug("Cancelling setup provider defer.") - self._backend.cancel_setup_provider() - - if self._soledad_defer is not None: - logger.debug("Cancelling soledad defer.") - self._soledad_defer.cancel() + self._cancel_ongoing_defers() # TODO missing any more cancels? -- cgit v1.2.3 From 2f46572ef137bb20c04f443a36361569b4b9e120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Fri, 7 Mar 2014 18:02:58 -0300 Subject: Remove qtreactor dependency --- 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 eeab7e2b..9ee62e17 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -134,6 +134,7 @@ class MainWindow(QtGui.QMainWindow): :type bypass_checks: bool """ QtGui.QMainWindow.__init__(self) + self.menuBar().setNativeMenuBar(False) # register leap events ######################################## register(signal=proto.UPDATER_NEW_UPDATES, -- cgit v1.2.3 From 55fd2d680c1d1f8cdf3433bf408858b72d55178f Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 11 Mar 2014 12:47:28 -0300 Subject: Move error messages for the user to the GUI. --- src/leap/bitmask/gui/mainwindow.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 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 004d135b..949dcb03 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -32,7 +32,10 @@ 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.crypto import srpauth from leap.bitmask.crypto.srpauth import SRPAuth + from leap.bitmask.gui.loggerwindow import LoggerWindow from leap.bitmask.gui.advanced_key_management import AdvancedKeyManagement from leap.bitmask.gui.login import LoginWidget @@ -1051,13 +1054,30 @@ class MainWindow(QtGui.QMainWindow): # as we are doing with the prov_cancelled_setup signal. # After we move srpauth to the backend, we need to update this. logger.error("Error logging in, {0!r}".format(failure)) + if failure.check(CancelledError): logger.debug("Defer cancelled.") failure.trap(Exception) self._set_login_cancelled() + return + elif failure.check(srpauth.SRPAuthBadUserOrPassword): + msg = self.tr("Invalid username or password.") + elif failure.check(srpauth.SRPAuthBadStatusCode, + srpauth.SRPAuthenticationError, + srpauth.SRPAuthVerificationFailed, + srpauth.SRPAuthNoSessionId, + srpauth.SRPAuthNoSalt, srpauth.SRPAuthNoB, + srpauth.SRPAuthBadDataFromServer, + srpauth.SRPAuthJSONDecodeError): + msg = self.tr("There was a server problem with authentication.") + elif failure.check(srpauth.SRPAuthConnectionError): + msg = self.tr("Could not establish a connection.") else: - self._login_widget.set_status(str(failure.value)) - self._login_widget.set_enabled(True) + # this shouldn't happen, but just in case. + msg = self.tr("Unknown error: {0!r}".format(failure.value)) + + self._login_widget.set_status(msg) + self._login_widget.set_enabled(True) def _cancel_login(self): """ -- cgit v1.2.3 From 5c2150723d87e8713bffe23d0fa897d1de088b3f Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 11 Mar 2014 13:07:38 -0300 Subject: Move login/logout success/error msgs to the GUI. Also refactor signals to be more granular and notify clearly if there was an error or not, then in the GUI we show the corresponding message. --- src/leap/bitmask/gui/mainwindow.py | 75 +++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 38 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 949dcb03..7cec4831 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1139,8 +1139,8 @@ class MainWindow(QtGui.QMainWindow): self._srp_auth = SRPAuth(self._provider_config) self._srp_auth.authentication_finished.connect( self._authentication_finished) - self._srp_auth.logout_finished.connect( - self._done_logging_out) + self._srp_auth.logout_ok.connect(self._logout_ok) + self._srp_auth.logout_error.connect(self._logout_error) self._login_defer = self._srp_auth.authenticate(username, password) self._login_defer.addErrback(self._login_errback) @@ -1150,7 +1150,7 @@ class MainWindow(QtGui.QMainWindow): logger.error(data[self._backend.ERROR_KEY]) self._login_widget.set_enabled(True) - def _authentication_finished(self, ok, message): + def _authentication_finished(self): """ SLOT TRIGGER: self._srp_auth.authentication_finished @@ -1158,30 +1158,23 @@ class MainWindow(QtGui.QMainWindow): Once the user is properly authenticated, try starting the EIP service """ - # In general we want to "filter" likely complicated error - # messages, but in this case, the messages make more sense as - # they come. Since they are "Unknown user" or "Unknown - # password" - self._login_widget.set_status(message, error=not ok) - - if ok: - self._logged_user = self._login_widget.get_user() - user = self._logged_user - domain = self._provider_config.get_domain() - full_user_id = make_address(user, domain) - self._mail_conductor.userid = full_user_id - self._login_defer = None - self._start_eip_bootstrap() - - # if soledad/mail is enabled: - 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)) - else: - self._login_widget.set_enabled(True) + self._login_widget.set_status(self.tr("Succeeded"), error=False) + + self._logged_user = self._login_widget.get_user() + user = self._logged_user + domain = self._provider_config.get_domain() + full_user_id = make_address(user, domain) + self._mail_conductor.userid = full_user_id + self._login_defer = None + self._start_eip_bootstrap() + + # if soledad/mail is enabled: + 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)) def _start_eip_bootstrap(self): """ @@ -1851,11 +1844,22 @@ class MainWindow(QtGui.QMainWindow): threads.deferToThread(self._srp_auth.logout) self.logout.emit() - def _done_logging_out(self, ok, message): - # TODO missing params in docstring + def _logout_error(self): """ SLOT - TRIGGER: self._srp_auth.logout_finished + TRIGGER: self._srp_auth.logout_error + + Inform the user about a logout error. + """ + self._login_widget.done_logout() + self.ui.lblLoginProvider.setText(self.tr("Login")) + self._login_widget.set_status( + self.tr("Something went wrong with the logout.")) + + def _logout_ok(self): + """ + SLOT + TRIGGER: self._srp_auth.logout_ok Switches the stackedWidget back to the login stage after logging out @@ -1863,14 +1867,9 @@ class MainWindow(QtGui.QMainWindow): self._login_widget.done_logout() self.ui.lblLoginProvider.setText(self.tr("Login")) - if ok: - self._logged_user = None - self._login_widget.logged_out() - self._mail_status.mail_state_disabled() - - else: - self._login_widget.set_status( - self.tr("Something went wrong with the logout.")) + self._logged_user = None + self._login_widget.logged_out() + self._mail_status.mail_state_disabled() def _intermediate_stage(self, data): # TODO this method name is confusing as hell. -- cgit v1.2.3 From d724a65ca08d5b1c16da1f2ce3fd0b50bd519dec Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 10 Mar 2014 17:29:52 -0300 Subject: Check for DNS resolution after connecting EIP. [Closes #5301] --- src/leap/bitmask/gui/mainwindow.py | 52 +++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 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 7cec4831..758bff4e 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -18,13 +18,14 @@ Main window for Bitmask. """ import logging +import socket from threading import Condition from datetime import datetime from PySide import QtCore, QtGui from zope.proxy import ProxyBase, setProxiedObject -from twisted.internet import threads +from twisted.internet import reactor, threads from twisted.internet.defer import CancelledError from leap.bitmask import __version__ as VERSION @@ -1456,6 +1457,55 @@ class MainWindow(QtGui.QMainWindow): """ self._eip_connection.qtsigs.connected_signal.emit() + # check for connectivity + provider_config = self._get_best_provider_config() + domain = provider_config.get_domain() + self._check_name_resolution(domain) + + def _check_name_resolution(self, domain): + """ + Check if we can resolve the given domain name. + + :param domain: the domain to check. + :type domain: str + """ + def do_check(): + """ + Try to resolve the domain name. + """ + socket.gethostbyname(domain.encode('idna')) + + def check_err(failure): + """ + Errback handler for `do_check`. + + :param failure: the failure that triggered the errback. + :type failure: twisted.python.failure.Failure + """ + logger.error(repr(failure)) + logger.error("Can't resolve hostname.") + + msg = self.tr( + "The server at {0} can't be found, because the DNS lookup " + "failed. DNS is the network service that translates a " + "website's name to its Internet address. Either your computer " + "is having trouble connecting to the network, or you are " + "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) + + show_err = lambda: QtGui.QMessageBox.critical( + self, self.tr("Connection Error"), msg) + reactor.callLater(0, show_err) + + # python 2.7.4 raises socket.error + # python 2.7.5 raises socket.gaierror + failure.trap(socket.gaierror, socket.error) + + d = threads.deferToThread(do_check) + d.addErrback(check_err) + def _try_autostart_eip(self): """ Tries to autostart EIP -- cgit v1.2.3 From 21e8d1a4539b0b0837ca0763de4974ac6f216bf7 Mon Sep 17 00:00:00 2001 From: drebs Date: Mon, 17 Mar 2014 13:21:51 -0300 Subject: Catch soledad invalid token error (#5191). --- 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 758bff4e..e4e71dcc 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -262,6 +262,8 @@ class MainWindow(QtGui.QMainWindow): self._soledad_bootstrapped_stage) self._soledad_bootstrapper.soledad_timeout.connect( self._retry_soledad_connection) + self._soledad_bootstrapper.soledad_invalid_auth_token.connect( + self._mail_status.set_soledad_invalid_auth_token) self._soledad_bootstrapper.soledad_failed.connect( self._mail_status.set_soledad_failed) -- cgit v1.2.3 From 681ef643a977bc7b7975f10a8aac043dbec53fcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Thu, 27 Mar 2014 11:28:37 -0300 Subject: Properly set menubar nativeness after setupUi --- 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 e4e71dcc..6d3a05fa 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -138,7 +138,6 @@ class MainWindow(QtGui.QMainWindow): :type bypass_checks: bool """ QtGui.QMainWindow.__init__(self) - self.menuBar().setNativeMenuBar(False) # register leap events ######################################## register(signal=proto.UPDATER_NEW_UPDATES, @@ -158,6 +157,7 @@ class MainWindow(QtGui.QMainWindow): # setup UI self.ui = Ui_MainWindow() self.ui.setupUi(self) + self.menuBar().setNativeMenuBar(True) self._backend = backend.Backend(bypass_checks) self._backend.start() -- cgit v1.2.3 From 962dbc30fd97176b30eac9df75e8ad1697972bf2 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 2 Apr 2014 16:27:21 -0300 Subject: Refactor check for provided and enabled services. Also use: `item in some_list` instead of `some_list.count(item) > 0`. --- src/leap/bitmask/gui/mainwindow.py | 39 ++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 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 6d3a05fa..feb1e18b 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1193,14 +1193,35 @@ class MainWindow(QtGui.QMainWindow): self._provider_config.get_domain()) # TODO separate UI from logic. - if self._provider_config.provides_mx() and \ - self._enabled_services.count(MX_SERVICE) > 0: + if self._provides_mx_and_enabled(): self._mail_status.about_to_start() else: self._mail_status.set_disabled() self._maybe_start_eip() + def _provides_mx_and_enabled(self): + """ + Defines if the current provider provides mx and if we have it enabled. + + :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) + + def _provides_eip_and_enabled(self): + """ + Defines if the current provider provides eip and if we have it enabled. + + :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) + def _maybe_run_soledad_setup_checks(self): """ Conditionally start Soledad. @@ -1332,8 +1353,7 @@ class MainWindow(QtGui.QMainWindow): # TODO for simmetry, this should be called start_smtp_service # (and delegate all the checks to the conductor) - if self._provider_config.provides_mx() and \ - self._enabled_services.count(MX_SERVICE) > 0: + if self._provides_mx_and_enabled(): self._mail_conductor.smtp_bootstrapper.run_smtp_setup_checks( self._provider_config, self._mail_conductor.smtp_config, @@ -1375,9 +1395,7 @@ class MainWindow(QtGui.QMainWindow): start_fun() return - enabled_services = self._enabled_services - if self._provider_config.provides_mx() and \ - enabled_services.count(MX_SERVICE) > 0: + if self._provides_mx_and_enabled(): start_fun() def _on_mail_client_logged_in(self, req): @@ -1770,10 +1788,7 @@ class MainWindow(QtGui.QMainWindow): provider_config = self._get_best_provider_config() - if provider_config.provides_eip() and \ - self._enabled_services.count(EIP_SERVICE) > 0 and \ - not self._already_started_eip: - + if self._provides_eip_and_enabled() and not self._already_started_eip: # XXX this should be handled by the state machine. self._eip_status.set_eip_status( self.tr("Starting...")) @@ -1788,7 +1803,7 @@ class MainWindow(QtGui.QMainWindow): self._maybe_run_soledad_setup_checks) else: if not self._already_started_eip: - if self._enabled_services.count(EIP_SERVICE) > 0: + if EIP_SERVICE in self._enabled_services: self._eip_status.set_eip_status( self.tr("Not supported"), error=True) -- cgit v1.2.3 From 469a056387fa1d69dd14f0680fa0026e0a3ff80c Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 2 Apr 2014 16:29:29 -0300 Subject: Do not start soledad if its not provided and enabled. [Closes #5411] --- src/leap/bitmask/gui/mainwindow.py | 3 +++ 1 file changed, 3 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 feb1e18b..04a98fac 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1230,6 +1230,9 @@ class MainWindow(QtGui.QMainWindow): if self._already_started_soledad is True: return + if not self._provides_mx_and_enabled(): + return + username = self._login_widget.get_user() password = unicode(self._login_widget.get_password()) provider_domain = self._login_widget.get_selected_provider() -- cgit v1.2.3 From 379d13b2b56a50251144c52273aa0352df7c0222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Fri, 4 Apr 2014 15:33:31 -0300 Subject: Do not do native menu bars in Linux for now --- src/leap/bitmask/gui/mainwindow.py | 4 ++-- 1 file changed, 2 insertions(+), 2 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 04a98fac..5abfaa67 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -49,7 +49,7 @@ from leap.bitmask.gui.wizard import Wizard from leap.bitmask.gui.systray import SysTray from leap.bitmask import provider -from leap.bitmask.platform_init import IS_WIN, IS_MAC +from leap.bitmask.platform_init import IS_WIN, IS_MAC, IS_LINUX from leap.bitmask.platform_init.initializers import init_platform from leap.bitmask import backend @@ -157,7 +157,7 @@ class MainWindow(QtGui.QMainWindow): # setup UI self.ui = Ui_MainWindow() self.ui.setupUi(self) - self.menuBar().setNativeMenuBar(True) + self.menuBar().setNativeMenuBar(not IS_LINUX) self._backend = backend.Backend(bypass_checks) self._backend.start() -- cgit v1.2.3