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 ++++++++++++++++++++++--------- src/leap/bitmask/gui/preferenceswindow.py | 3 ++ 2 files changed, 44 insertions(+), 15 deletions(-) (limited to 'src/leap/bitmask/gui') 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) diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py index b4bddef2..517a90c4 100644 --- a/src/leap/bitmask/gui/preferenceswindow.py +++ b/src/leap/bitmask/gui/preferenceswindow.py @@ -42,6 +42,8 @@ class PreferencesWindow(QtGui.QDialog): """ Window that displays the preferences. """ + preferences_saved = QtCore.Signal() + def __init__(self, parent, srp_auth, provider_config, soledad, domain): """ :param parent: parent object of the PreferencesWindow. @@ -369,6 +371,7 @@ class PreferencesWindow(QtGui.QDialog): "Services settings for provider '{0}' saved.".format(provider)) logger.debug(msg) self._set_providers_services_status(msg, success=True) + self.preferences_saved.emit() def _get_provider_config(self, domain): """ -- 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 +- src/leap/bitmask/gui/ui/mainwindow.ui | 198 ++++++++++++---------------------- 2 files changed, 76 insertions(+), 133 deletions(-) (limited to 'src/leap/bitmask/gui') 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. """ diff --git a/src/leap/bitmask/gui/ui/mainwindow.ui b/src/leap/bitmask/gui/ui/mainwindow.ui index 3b83788e..4dc39d03 100644 --- a/src/leap/bitmask/gui/ui/mainwindow.ui +++ b/src/leap/bitmask/gui/ui/mainwindow.ui @@ -85,108 +85,8 @@ 0 - - - - - 0 - - - 0 - - - - - - 0 - 0 - - - - QFrame{background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(160, 160, 160, 128), stop:1 rgba(255, 255, 255, 0));} - - - - 24 - - - 24 - - - - - - 16 - 75 - true - - - - background-color: rgba(255, 255, 255, 0); - - - Encrypted Internet - - - - - - - - 48 - 20 - - - - - - - - - - - :/images/black/32/gear.png:/images/black/32/gear.png - - - false - - - false - - - false - - - - - - - - - - 12 - - - 0 - - - 12 - - - 0 - - - - - - - - - - Qt::Horizontal - - - + + @@ -199,9 +99,7 @@ false - QFrame{ -background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(160, 160, 160, 128), stop:1 rgba(255, 255, 255, 0)); -} + background-color: rgba(0,0,0,20); border-bottom: 1px solid rgba(0,0,0,30); @@ -214,36 +112,15 @@ background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgb - 16 75 true - background-color: rgba(255, 255, 255, 0); - - - Login - - - - - - - - 48 - 20 - - - - + background-color: rgba(255, 255, 255, 0); border: none; - - - - - :/images/black/32/gear.png:/images/black/32/gear.png + Please Log In @@ -257,13 +134,54 @@ background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgb + - + Qt::Horizontal + + + + + + + 0 + + + 0 + + + + + 12 + + + 0 + + + 12 + + + 0 + + + + + + + + + + + Qt::Horizontal + + + + + @@ -286,6 +204,15 @@ background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgb + + + + + Qt::Horizontal + + + + @@ -390,6 +317,9 @@ background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgb + + + @@ -406,8 +336,16 @@ background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgb + + true + + + Account Preferences... + + + - Preferences... + Internet Preferences... -- cgit v1.2.3 From 551e02141d5ffa72b76d2d1541bda2f877c8d379 Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 11 Dec 2013 23:01:43 -0800 Subject: modified eip widget: change font to look better when under login widget, tightened spacing, moved upload and download icons to the buttons themselves, get rid of extra left whitespace padding on bandwidth status. --- src/leap/bitmask/gui/eip_status.py | 4 +-- src/leap/bitmask/gui/ui/eip_status.ui | 66 ++++++----------------------------- 2 files changed, 13 insertions(+), 57 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py index 4b4d360f..92bb623e 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -41,8 +41,8 @@ class EIPStatusWidget(QtGui.QWidget): EIP Status widget that displays the current state of the EIP service """ DISPLAY_TRAFFIC_RATES = True - RATE_STR = "%14.2f KB/s" - TOTAL_STR = "%14.2f Kb" + RATE_STR = "%1.2f KB/s" + TOTAL_STR = "%1.2f Kb" eip_connection_connected = QtCore.Signal() diff --git a/src/leap/bitmask/gui/ui/eip_status.ui b/src/leap/bitmask/gui/ui/eip_status.ui index d078ca0c..64821ad6 100644 --- a/src/leap/bitmask/gui/ui/eip_status.ui +++ b/src/leap/bitmask/gui/ui/eip_status.ui @@ -25,6 +25,9 @@ + + 0 + @@ -75,13 +78,6 @@ 0 - - - 14 - 75 - true - - Traffic is being routed in the clear @@ -124,12 +120,6 @@ - - - 16777215 - 32 - - 0 @@ -145,16 +135,6 @@ QLayout::SetDefaultConstraint - - - - - - - :/images/light/16/down-arrow.png - - - @@ -175,25 +155,18 @@ 16777215 - - - 11 - 75 - true - - PointingHandCursor - - text-align: left; - 0.0 KB/s true + + :/images/light/16/down-arrow.png + @@ -206,22 +179,12 @@ - 10 + 20 20 - - - - - - - :/images/light/16/up-arrow.png - - - @@ -242,25 +205,18 @@ 16777215 - - - 11 - 75 - true - - PointingHandCursor - - text-align: left; - 0.0 KB/s true + + :/images/light/16/up-arrow.png + @@ -271,7 +227,7 @@ 0 - 20 + 0 -- cgit v1.2.3 From 714c9afedfaee3c0288536cb1c3b138b20bab03c Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 11 Dec 2013 23:02:18 -0800 Subject: login widget: tighten spacing, get rid of non-standard font family. --- src/leap/bitmask/gui/ui/login.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/ui/login.ui b/src/leap/bitmask/gui/ui/login.ui index e7ca1652..7e8f9daf 100644 --- a/src/leap/bitmask/gui/ui/login.ui +++ b/src/leap/bitmask/gui/ui/login.ui @@ -215,7 +215,7 @@ 0 - 24 + 0 @@ -255,7 +255,7 @@ color: rgb(132, 132, 132); -font: 75 12pt "Lucida Grande"; +font: 75 12pt; -- cgit v1.2.3 From 2a8632e60a538828e8c5b417c5b02fbdaaccc88d Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 11 Dec 2013 23:06:03 -0800 Subject: main window ui: remove unused statusbar --- src/leap/bitmask/gui/ui/mainwindow.ui | 1 - 1 file changed, 1 deletion(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/ui/mainwindow.ui b/src/leap/bitmask/gui/ui/mainwindow.ui index 4dc39d03..ce05f8f3 100644 --- a/src/leap/bitmask/gui/ui/mainwindow.ui +++ b/src/leap/bitmask/gui/ui/mainwindow.ui @@ -334,7 +334,6 @@ - true -- cgit v1.2.3 From 97700c4278fdd67123317584dd66c946ee9340a8 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 12 Dec 2013 16:53:35 -0300 Subject: Add view for stored public keys. Closes #4734. --- src/leap/bitmask/gui/advanced_key_management.py | 22 +++++- src/leap/bitmask/gui/ui/advanced_key_management.ui | 79 ++++++++++++++++------ 2 files changed, 79 insertions(+), 22 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/advanced_key_management.py b/src/leap/bitmask/gui/advanced_key_management.py index 2c0fa034..8f15719d 100644 --- a/src/leap/bitmask/gui/advanced_key_management.py +++ b/src/leap/bitmask/gui/advanced_key_management.py @@ -50,7 +50,8 @@ class AdvancedKeyManagement(QtGui.QWidget): # if Soledad is not started yet if sameProxiedObjects(soledad, None): - self.ui.container.setEnabled(False) + self.ui.gbMyKeyPair.setEnabled(False) + self.ui.gbStoredPublicKeys.setEnabled(False) msg = self.tr("NOTE: " "To use this, you need to enable/start {0}.") msg = msg.format(get_service_display_name(MX_SERVICE)) @@ -79,6 +80,12 @@ class AdvancedKeyManagement(QtGui.QWidget): self.ui.pbImportKeys.clicked.connect(self._import_keys) self.ui.pbExportKeys.clicked.connect(self._export_keys) + # Stretch columns to content + self.ui.twPublicKeys.horizontalHeader().setResizeMode( + 0, QtGui.QHeaderView.Stretch) + + self._list_keys() + def _import_keys(self): """ Imports the user's key pair. @@ -183,3 +190,16 @@ class AdvancedKeyManagement(QtGui.QWidget): return else: logger.debug('Export canceled by the user.') + + def _list_keys(self): + """ + Loads all the public keys stored in the local db to the keys table. + """ + keys = self._keymanager.get_all_keys_in_local_db() + + keys_table = self.ui.twPublicKeys + for key in keys: + row = keys_table.rowCount() + keys_table.insertRow(row) + keys_table.setItem(row, 0, QtGui.QTableWidgetItem(key.address)) + keys_table.setItem(row, 1, QtGui.QTableWidgetItem(key.key_id)) diff --git a/src/leap/bitmask/gui/ui/advanced_key_management.ui b/src/leap/bitmask/gui/ui/advanced_key_management.ui index d61aa87e..1112670f 100644 --- a/src/leap/bitmask/gui/ui/advanced_key_management.ui +++ b/src/leap/bitmask/gui/ui/advanced_key_management.ui @@ -6,8 +6,8 @@ 0 0 - 431 - 188 + 504 + 546 @@ -17,10 +17,13 @@ :/images/mask-icon.png:/images/mask-icon.png - - - - + + + + + My key pair + + @@ -90,20 +93,7 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - - + @@ -135,9 +125,56 @@ + leKeyID + leUser + leFingerprint + label_3 + label_5 + label + + + + + + Stored public keys + + + + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + Qt::ElideRight + + + true + + + + Email + + + + + Key ID + + + + + - + -- cgit v1.2.3 From 768a460a0f524e32528063e36a0203a3d83e8de1 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 17 Dec 2013 17:38:18 -0300 Subject: Reset registration error and input widgets. The registration widgets are cleared if the user goes back to the provider selection page. [Closes #4742] --- src/leap/bitmask/gui/wizard.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index 5f5224ae..ad0565e4 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -597,6 +597,7 @@ class Wizard(QtGui.QWizard): Prepares the pages when they appear """ if pageId == self.SELECT_PROVIDER_PAGE: + self._clear_register_widgets() skip = self.ui.rbExistingProvider.isChecked() if not self._provider_checks_ok: self._enable_check() @@ -670,3 +671,12 @@ class Wizard(QtGui.QWizard): return self.SERVICES_PAGE return QtGui.QWizard.nextId(self) + + def _clear_register_widgets(self): + """ + Clears the widgets that my be filled and a possible error message. + """ + self._set_register_status("") + self.ui.lblUser.setText("") + self.ui.lblPassword.setText("") + self.ui.lblPassword2.setText("") -- 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') 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 +++++++++++++++++++++---------------- src/leap/bitmask/gui/wizard.py | 68 +++++++++--------- 2 files changed, 115 insertions(+), 92 deletions(-) (limited to 'src/leap/bitmask/gui') 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 diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index ad0565e4..ec007110 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -30,7 +30,6 @@ from twisted.internet import threads from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.crypto.srpregister import SRPRegister -from leap.bitmask.provider.providerbootstrapper import ProviderBootstrapper from leap.bitmask.services import get_service_display_name, get_supported from leap.bitmask.util.request_helpers import get_content from leap.bitmask.util.keyring_helpers import has_keyring @@ -55,12 +54,15 @@ class Wizard(QtGui.QWizard): BARE_USERNAME_REGEX = r"^[A-Za-z\d_]+$" - def __init__(self, bypass_checks=False): + def __init__(self, backend, bypass_checks=False): """ Constructor for the main Wizard. + :param backend: Backend being used + :type backend: Backend :param bypass_checks: Set to true if the app should bypass - first round of checks for CA certificates at bootstrap + first round of checks for CA + certificates at bootstrap :type bypass_checks: bool """ QtGui.QWizard.__init__(self) @@ -68,6 +70,8 @@ class Wizard(QtGui.QWizard): self.ui = Ui_Wizard() self.ui.setupUi(self) + self._backend = backend + self.setPixmap(QtGui.QWizard.LogoPixmap, QtGui.QPixmap(":/images/mask-icon.png")) @@ -86,23 +90,25 @@ class Wizard(QtGui.QWizard): self.ui.btnCheck.clicked.connect(self._check_provider) self.ui.lnProvider.returnPressed.connect(self._check_provider) - self._provider_bootstrapper = ProviderBootstrapper(bypass_checks) - self._provider_bootstrapper.name_resolution.connect( + self._backend.signaler.prov_name_resolution.connect( self._name_resolution) - self._provider_bootstrapper.https_connection.connect( + self._backend.signaler.prov_https_connection.connect( self._https_connection) - self._provider_bootstrapper.download_provider_info.connect( + self._backend.signaler.prov_download_provider_info.connect( self._download_provider_info) - self._provider_bootstrapper.download_ca_cert.connect( + self._backend.signaler.prov_download_ca_cert.connect( self._download_ca_cert) - self._provider_bootstrapper.check_ca_fingerprint.connect( + self._backend.signaler.prov_check_ca_fingerprint.connect( self._check_ca_fingerprint) - self._provider_bootstrapper.check_api_certificate.connect( + self._backend.signaler.prov_check_api_certificate.connect( self._check_api_certificate) self._domain = None - self._provider_config = ProviderConfig() + # HACK!! We need provider_config for the time being, it'll be + # removed + self._provider_config = ( + self._backend._components["provider"]._provider_config) # We will store a reference to the defers for eventual use # (eg, to cancel them) but not doing anything with them right now. @@ -385,8 +391,8 @@ class Wizard(QtGui.QWizard): self._domain = self.ui.lnProvider.text() self.ui.lblNameResolution.setPixmap(self.QUESTION_ICON) - self._provider_select_defer = self._provider_bootstrapper.\ - run_provider_select_checks(self._domain) + self._provider_select_defer = self._backend.\ + setup_provider(self._domain) def _skip_provider_checks(self, skip): """ @@ -423,8 +429,8 @@ class Wizard(QtGui.QWizard): :param complete_page: page id to complete :type complete_page: int """ - passed = data[self._provider_bootstrapper.PASSED_KEY] - error = data[self._provider_bootstrapper.ERROR_KEY] + passed = data[self._backend.PASSED_KEY] + error = data[self._backend.ERROR_KEY] if passed: label.setPixmap(self.OK_ICON) if complete: @@ -437,13 +443,13 @@ class Wizard(QtGui.QWizard): def _name_resolution(self, data): """ SLOT - TRIGGER: self._provider_bootstrapper.name_resolution + TRIGGER: self._backend.signaler.prov_name_resolution Sets the status for the name resolution check """ self._complete_task(data, self.ui.lblNameResolution) status = "" - passed = data[self._provider_bootstrapper.PASSED_KEY] + passed = data[self._backend.PASSED_KEY] if not passed: status = self.tr("Non-existent " "provider") @@ -456,16 +462,16 @@ class Wizard(QtGui.QWizard): def _https_connection(self, data): """ SLOT - TRIGGER: self._provider_bootstrapper.https_connection + TRIGGER: self._backend.signaler.prov_https_connection Sets the status for the https connection check """ self._complete_task(data, self.ui.lblHTTPS) status = "" - passed = data[self._provider_bootstrapper.PASSED_KEY] + passed = data[self._backend.PASSED_KEY] if not passed: status = self.tr("%s") \ - % (data[self._provider_bootstrapper.ERROR_KEY]) + % (data[self._backend.ERROR_KEY]) self.ui.lblProviderSelectStatus.setText(status) else: self.ui.lblProviderInfo.setPixmap(self.QUESTION_ICON) @@ -475,7 +481,7 @@ class Wizard(QtGui.QWizard): def _download_provider_info(self, data): """ SLOT - TRIGGER: self._provider_bootstrapper.download_provider_info + TRIGGER: self._backend.signaler.prov_download_provider_info Sets the status for the provider information download check. Since this check is the last of this set, it also @@ -490,14 +496,14 @@ class Wizard(QtGui.QWizard): self._provider_checks_ok = True else: new_data = { - self._provider_bootstrapper.PASSED_KEY: False, - self._provider_bootstrapper.ERROR_KEY: + self._backend.PASSED_KEY: False, + self._backend.ERROR_KEY: self.tr("Unable to load provider configuration") } self._complete_task(new_data, self.ui.lblProviderInfo) status = "" - if not data[self._provider_bootstrapper.PASSED_KEY]: + if not data[self._backend.PASSED_KEY]: status = self.tr("Not a valid provider" "") self.ui.lblProviderSelectStatus.setText(status) @@ -507,31 +513,31 @@ class Wizard(QtGui.QWizard): def _download_ca_cert(self, data): """ SLOT - TRIGGER: self._provider_bootstrapper.download_ca_cert + TRIGGER: self._backend.signaler.prov_download_ca_cert Sets the status for the download of the CA certificate check """ self._complete_task(data, self.ui.lblDownloadCaCert) - passed = data[self._provider_bootstrapper.PASSED_KEY] + passed = data[self._backend.PASSED_KEY] if passed: self.ui.lblCheckCaFpr.setPixmap(self.QUESTION_ICON) def _check_ca_fingerprint(self, data): """ SLOT - TRIGGER: self._provider_bootstrapper.check_ca_fingerprint + TRIGGER: self._backend.signaler.prov_check_ca_fingerprint Sets the status for the CA fingerprint check """ self._complete_task(data, self.ui.lblCheckCaFpr) - passed = data[self._provider_bootstrapper.PASSED_KEY] + passed = data[self._backend.PASSED_KEY] if passed: self.ui.lblCheckApiCert.setPixmap(self.QUESTION_ICON) def _check_api_certificate(self, data): """ SLOT - TRIGGER: self._provider_bootstrapper.check_api_certificate + TRIGGER: self._backend.signaler.prov_check_api_certificate Sets the status for the API certificate check. Also finishes the provider bootstrapper thread since it's not needed anymore @@ -612,8 +618,8 @@ class Wizard(QtGui.QWizard): sub_title = sub_title.format(self._provider_config.get_name()) self.page(pageId).setSubTitle(sub_title) self.ui.lblDownloadCaCert.setPixmap(self.QUESTION_ICON) - self._provider_setup_defer = self._provider_bootstrapper.\ - run_provider_setup_checks(self._provider_config) + self._provider_setup_defer = self._backend.\ + provider_bootstrap(self._domain) if pageId == self.PRESENT_PROVIDER_PAGE: self.page(pageId).setSubTitle(self.tr("Description of services " -- 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') 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') 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/eip_status.py | 6 +++--- src/leap/bitmask/gui/mainwindow.py | 10 ++++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py index 92bb623e..19942d9d 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -248,10 +248,10 @@ class EIPStatusWidget(QtGui.QWidget): Triggered when a default provider_config has not been found. Disables the start button and adds instructions to the user. """ - logger.debug('Hiding EIP start button') + #logger.debug('Hiding EIP start button') # you might be tempted to change this for a .setEnabled(False). # it won't work. it's under the claws of the state machine. - # probably the best thing would be to make a transitional + # probably the best thing would be to make a conditional # transition there, but that's more involved. self.eip_button.hide() msg = self.tr("You must login to use {0}".format(self._service_name)) @@ -272,7 +272,7 @@ class EIPStatusWidget(QtGui.QWidget): Triggered after a successful login. Enables the start button. """ - logger.debug('Showing EIP start button') + #logger.debug('Showing EIP start button') self.eip_button.show() # Restore the eip action menu 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 +++-- src/leap/bitmask/gui/wizard.py | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 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! diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index ec007110..b99e8db6 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -686,3 +686,26 @@ class Wizard(QtGui.QWizard): self.ui.lblUser.setText("") self.ui.lblPassword.setText("") self.ui.lblPassword2.setText("") + + def closeEvent(self, event): + """ + This method is called when the wizard dialog is closed. + We disconnect all the backend signals in here. + """ + try: + # disconnect backend signals + self._backend.signaler.prov_name_resolution.disconnect( + self._name_resolution) + self._backend.signaler.prov_https_connection.disconnect( + self._https_connection) + self._backend.signaler.prov_download_provider_info.disconnect( + self._download_provider_info) + + self._backend.signaler.prov_download_ca_cert.disconnect( + self._download_ca_cert) + self._backend.signaler.prov_check_ca_fingerprint.disconnect( + self._check_ca_fingerprint) + self._backend.signaler.prov_check_api_certificate.disconnect( + self._check_api_certificate) + except RuntimeError: + pass # Signal was not connected -- 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') 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') 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') 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') 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/login.py | 24 ++++--- src/leap/bitmask/gui/mainwindow.py | 134 +++++++++++++++++++++++++++++-------- 2 files changed, 123 insertions(+), 35 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/login.py b/src/leap/bitmask/gui/login.py index b21057f0..d0cb20b1 100644 --- a/src/leap/bitmask/gui/login.py +++ b/src/leap/bitmask/gui/login.py @@ -19,12 +19,13 @@ Login widget implementation """ import logging -import keyring - from PySide import QtCore, QtGui from ui_login import Ui_LoginWidget +from leap.bitmask.config import flags +from leap.bitmask.util import make_address from leap.bitmask.util.keyring_helpers import has_keyring +from leap.bitmask.util.keyring_helpers import get_keyring from leap.common.check import leap_assert_type logger = logging.getLogger(__name__) @@ -304,14 +305,15 @@ class LoginWidget(QtGui.QWidget): if self.get_remember() and has_keyring(): # in the keyring and in the settings # we store the value 'usename@provider' - username_domain = (username + '@' + provider).encode("utf8") + full_user_id = make_address(username, provider).encode("utf8") try: + keyring = get_keyring() keyring.set_password(self.KEYRING_KEY, - username_domain, + full_user_id, password.encode("utf8")) # Only save the username if it was saved correctly in # the keyring - self._settings.set_user(username_domain) + self._settings.set_user(full_user_id) except Exception as e: logger.exception("Problem saving data to keyring. %r" % (e,)) @@ -323,15 +325,20 @@ class LoginWidget(QtGui.QWidget): """ self.ui.login_widget.hide() self.ui.logged_widget.show() - self.ui.lblUser.setText("%s@%s" % (self.get_user(), - self.get_selected_provider())) + self.ui.lblUser.setText(make_address( + self.get_user(), self.get_selected_provider())) self.set_login_status("") - self.logged_in_signal.emit() + + if flags.OFFLINE is False: + self.logged_in_signal.emit() def logged_out(self): """ Sets the widgets to the logged out state """ + # TODO consider "logging out offline" too... + # how that would be ??? + self.ui.login_widget.show() self.ui.logged_widget.hide() @@ -396,6 +403,7 @@ class LoginWidget(QtGui.QWidget): saved_password = None try: + keyring = get_keyring() saved_password = keyring.get_password(self.KEYRING_KEY, saved_user .encode("utf8")) 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') 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/login.py | 17 --------------- src/leap/bitmask/gui/mainwindow.py | 5 ++--- src/leap/bitmask/gui/ui/login.ui | 43 ++++++++++++++------------------------ 3 files changed, 18 insertions(+), 47 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/login.py b/src/leap/bitmask/gui/login.py index d0cb20b1..8a7c6996 100644 --- a/src/leap/bitmask/gui/login.py +++ b/src/leap/bitmask/gui/login.py @@ -327,7 +327,6 @@ class LoginWidget(QtGui.QWidget): self.ui.logged_widget.show() self.ui.lblUser.setText(make_address( self.get_user(), self.get_selected_provider())) - self.set_login_status("") if flags.OFFLINE is False: self.logged_in_signal.emit() @@ -346,22 +345,6 @@ class LoginWidget(QtGui.QWidget): self.set_enabled(True) self.set_status("", error=False) - def set_login_status(self, msg, error=False): - """ - Sets the status label for the logged in state. - - :param msg: status message - :type msg: str or unicode - :param error: if the status is an erroneous one, then set this - to True - :type error: bool - """ - leap_assert_type(error, bool) - if error: - msg = "%s" % (msg,) - self.ui.lblLoginStatus.setText(msg) - self.ui.lblLoginStatus.show() - def start_logout(self): """ Sets the widgets to the logging out state 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. diff --git a/src/leap/bitmask/gui/ui/login.ui b/src/leap/bitmask/gui/ui/login.ui index 7e8f9daf..f5725d5a 100644 --- a/src/leap/bitmask/gui/ui/login.ui +++ b/src/leap/bitmask/gui/ui/login.ui @@ -217,26 +217,6 @@ 0 - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Logout - - - @@ -251,17 +231,26 @@ - - - - color: rgb(132, 132, 132); -font: 75 12pt; - + + - + Logout + + + + Qt::Horizontal + + + + 40 + 20 + + + +
-- cgit v1.2.3 From cd1ddb919b535800cee96d38a908f31f93f85e29 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 14 Jan 2014 11:07:45 -0300 Subject: Add an extra string for the singular 'email' word. Client should say 1 unread email, not emails. [Closes #4952] --- src/leap/bitmask/gui/mail_status.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py index 3c933c9a..6db17427 100644 --- a/src/leap/bitmask/gui/mail_status.py +++ b/src/leap/bitmask/gui/mail_status.py @@ -363,9 +363,13 @@ class MailStatusWidget(QtGui.QWidget): if req.event == proto.IMAP_UNREAD_MAIL: if self._started: - if req.content != "0": - self._set_mail_status(self.tr("%s Unread Emails") % - (req.content,), ready=2) + count = req.content + if count != "0": + status = self.tr("{0} Unread Emails").format(count) + if count == "1": + status = self.tr("1 Unread Email") + + self._set_mail_status(status, ready=2) else: self._set_mail_status("", ready=2) elif req.event == proto.IMAP_SERVICE_STARTED: -- 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') 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 01208db08da7cb48ee6239c917fceb2d6846228d Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 20 Jan 2014 11:36:41 -0300 Subject: Disable Advanced Key Manager import. Closes #4877. --- src/leap/bitmask/gui/advanced_key_management.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/advanced_key_management.py b/src/leap/bitmask/gui/advanced_key_management.py index 8f15719d..cbc8c3e3 100644 --- a/src/leap/bitmask/gui/advanced_key_management.py +++ b/src/leap/bitmask/gui/advanced_key_management.py @@ -48,6 +48,9 @@ class AdvancedKeyManagement(QtGui.QWidget): self.ui = Ui_AdvancedKeyManagement() self.ui.setupUi(self) + # XXX: Temporarily disable the key import. + self.ui.pbImportKeys.setVisible(False) + # if Soledad is not started yet if sameProxiedObjects(soledad, None): self.ui.gbMyKeyPair.setEnabled(False) @@ -57,12 +60,13 @@ class AdvancedKeyManagement(QtGui.QWidget): msg = msg.format(get_service_display_name(MX_SERVICE)) self.ui.lblStatus.setText(msg) return - else: - msg = self.tr( - "WARNING:
" - "This is an experimental feature, you can lose access to " - "existing e-mails.") - self.ui.lblStatus.setText(msg) + # XXX: since import is disabled this is no longer a dangerous feature. + # else: + # msg = self.tr( + # "WARNING:
" + # "This is an experimental feature, you can lose access to " + # "existing e-mails.") + # self.ui.lblStatus.setText(msg) self._keymanager = keymanager self._soledad = soledad -- 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') 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 1221160b11a32164c966cb1130bb3e0d74866d98 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 22 Jan 2014 17:18:08 -0300 Subject: Select by default the use of an existing provider. [Closes #4488] --- src/leap/bitmask/gui/ui/wizard.ui | 73 ++++++++++++++++++++------------------- src/leap/bitmask/gui/wizard.py | 4 +++ 2 files changed, 42 insertions(+), 35 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/ui/wizard.ui b/src/leap/bitmask/gui/ui/wizard.ui index cf591470..1ddd854f 100644 --- a/src/leap/bitmask/gui/ui/wizard.ui +++ b/src/leap/bitmask/gui/ui/wizard.ui @@ -269,7 +269,20 @@ Configure or select a provider - + + + + + + + https:// + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + Configure new provider: @@ -279,30 +292,20 @@ - - + + - Use existing one: + Check - - + + - https:// - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Use existing one: - - - - - - - - - Check + + false @@ -820,8 +823,8 @@ setFocus() - 167 - 192 + 174 + 174 265 @@ -836,12 +839,12 @@ setFocus() - 171 - 164 + 174 + 227 - 246 - 164 + 425 + 254 @@ -852,12 +855,12 @@ setDisabled(bool) - 169 - 196 + 174 + 174 - 327 - 163 + 454 + 254 @@ -868,8 +871,8 @@ setDisabled(bool) - 169 - 162 + 174 + 227 269 @@ -884,12 +887,12 @@ setDisabled(bool) - 154 - 193 + 169 + 174 - 498 - 170 + 520 + 255 diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index b99e8db6..d5940c52 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -205,6 +205,10 @@ class Wizard(QtGui.QWizard): random.shuffle(pinned) # don't prioritize alphabetically self.ui.cbProviders.addItems(pinned) + # We have configured providers, so by default we select the + # 'Use existing provider' option. + self.ui.rbExistingProvider.setChecked(True) + def get_domain(self): return self._domain -- cgit v1.2.3 From d4e53f6cef9ba2b476cc8308f132d8af20e79156 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 23 Jan 2014 17:07:02 -0300 Subject: Replace provider hardcoded path with helper. Also reorder some imports and remove unused ones. --- src/leap/bitmask/gui/preferenceswindow.py | 7 ++----- src/leap/bitmask/gui/wizard.py | 9 +++------ 2 files changed, 5 insertions(+), 11 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py index 517a90c4..b2cc2236 100644 --- a/src/leap/bitmask/gui/preferenceswindow.py +++ b/src/leap/bitmask/gui/preferenceswindow.py @@ -18,7 +18,6 @@ """ Preferences window """ -import os import logging from functools import partial @@ -26,6 +25,7 @@ from functools import partial from PySide import QtCore, QtGui from zope.proxy import sameProxiedObjects +from leap.bitmask.provider import get_provider_path from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.gui.ui_preferences import Ui_Preferences from leap.soledad.client import NoStorageSecret @@ -383,10 +383,7 @@ class PreferencesWindow(QtGui.QDialog): :rtype: ProviderConfig or None if there is a problem loading the config """ provider_config = ProviderConfig() - provider_config_path = os.path.join( - "leap", "providers", domain, "provider.json") - - if not provider_config.load(provider_config_path): + if not provider_config.load(get_provider_path(domain)): provider_config = None return provider_config diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index d5940c52..baf1ab8b 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -17,7 +17,6 @@ """ First run wizard """ -import os import logging import json import random @@ -30,10 +29,11 @@ from twisted.internet import threads from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.crypto.srpregister import SRPRegister +from leap.bitmask.provider import get_provider_path from leap.bitmask.services import get_service_display_name, get_supported -from leap.bitmask.util.request_helpers import get_content from leap.bitmask.util.keyring_helpers import has_keyring from leap.bitmask.util.password import basic_password_checks +from leap.bitmask.util.request_helpers import get_content from ui_wizard import Ui_Wizard @@ -491,10 +491,7 @@ class Wizard(QtGui.QWizard): check. Since this check is the last of this set, it also completes the page if passed """ - if self._provider_config.load(os.path.join("leap", - "providers", - self._domain, - "provider.json")): + if self._provider_config.load(get_provider_path(self._domain)): self._complete_task(data, self.ui.lblProviderInfo, True, self.SELECT_PROVIDER_PAGE) self._provider_checks_ok = True -- cgit v1.2.3 From f4f0930ab7ce749b09d7ab12e26cb14e3085d54e Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 24 Jan 2014 11:29:09 -0300 Subject: Handle wizard close correctly. Closes #4986. - Refactor connection and disconnection from backend. --- src/leap/bitmask/gui/wizard.py | 49 +++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 25 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index baf1ab8b..e1bed6b8 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -70,8 +70,6 @@ class Wizard(QtGui.QWizard): self.ui = Ui_Wizard() self.ui.setupUi(self) - self._backend = backend - self.setPixmap(QtGui.QWizard.LogoPixmap, QtGui.QPixmap(":/images/mask-icon.png")) @@ -90,19 +88,8 @@ class Wizard(QtGui.QWizard): self.ui.btnCheck.clicked.connect(self._check_provider) self.ui.lnProvider.returnPressed.connect(self._check_provider) - self._backend.signaler.prov_name_resolution.connect( - self._name_resolution) - self._backend.signaler.prov_https_connection.connect( - self._https_connection) - self._backend.signaler.prov_download_provider_info.connect( - self._download_provider_info) - - self._backend.signaler.prov_download_ca_cert.connect( - self._download_ca_cert) - self._backend.signaler.prov_check_ca_fingerprint.connect( - self._check_ca_fingerprint) - self._backend.signaler.prov_check_api_certificate.connect( - self._check_api_certificate) + self._backend = backend + self._backend_connect() self._domain = None # HACK!! We need provider_config for the time being, it'll be @@ -172,6 +159,7 @@ class Wizard(QtGui.QWizard): self._provider_setup_ok = False self.ui.lnProvider.setText('') self.ui.grpCheckProvider.setVisible(False) + self._backend_disconnect() def _load_configured_providers(self): """ @@ -688,25 +676,36 @@ class Wizard(QtGui.QWizard): self.ui.lblPassword.setText("") self.ui.lblPassword2.setText("") - def closeEvent(self, event): + def _backend_connect(self): + """ + Connects all the backend signals with the wizard. + """ + sig = self._backend.signaler + sig.prov_name_resolution.connect(self._name_resolution) + sig.prov_https_connection.connect(self._https_connection) + sig.prov_download_provider_info.connect(self._download_provider_info) + + sig.prov_download_ca_cert.connect(self._download_ca_cert) + sig.prov_check_ca_fingerprint.connect(self._check_ca_fingerprint) + sig.prov_check_api_certificate.connect(self._check_api_certificate) + + def _backend_disconnect(self): """ This method is called when the wizard dialog is closed. We disconnect all the backend signals in here. """ + sig = self._backend.signaler try: # disconnect backend signals - self._backend.signaler.prov_name_resolution.disconnect( - self._name_resolution) - self._backend.signaler.prov_https_connection.disconnect( - self._https_connection) - self._backend.signaler.prov_download_provider_info.disconnect( + sig.prov_name_resolution.disconnect(self._name_resolution) + sig.prov_https_connection.disconnect(self._https_connection) + sig.prov_download_provider_info.disconnect( self._download_provider_info) - self._backend.signaler.prov_download_ca_cert.disconnect( - self._download_ca_cert) - self._backend.signaler.prov_check_ca_fingerprint.disconnect( + sig.prov_download_ca_cert.disconnect(self._download_ca_cert) + sig.prov_check_ca_fingerprint.disconnect( self._check_ca_fingerprint) - self._backend.signaler.prov_check_api_certificate.disconnect( + sig.prov_check_api_certificate.disconnect( self._check_api_certificate) except RuntimeError: pass # Signal was not connected -- cgit v1.2.3 From d25b720cae45b87538985ead37e03e1a83bf7fa0 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 4 Feb 2014 11:22:13 -0300 Subject: Update menu name in wizard. [Closes 4984] --- src/leap/bitmask/gui/ui/wizard.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/ui/wizard.ui b/src/leap/bitmask/gui/ui/wizard.ui index 1ddd854f..d9b8499e 100644 --- a/src/leap/bitmask/gui/ui/wizard.ui +++ b/src/leap/bitmask/gui/ui/wizard.ui @@ -59,7 +59,7 @@ - <html><head/><body><p>Now we will guide you through some configuration that is needed before you can connect for the first time.</p><p>If you ever need to modify these options again, you can find the wizard in the <span style=" font-style:italic;">'Settings'</span> menu from the main window.</p><p>Do you want to <span style=" font-weight:600;">sign up</span> for a new account, or <span style=" font-weight:600;">log in</span> with an already existing username?</p></body></html> + <html><head/><body><p>Now we will guide you through some configuration that is needed before you can connect for the first time.</p><p>If you ever need to modify these options again, you can find the wizard in the <span style=" font-style:italic;">'Bitmask -&gt; Create new account...'</span> menu from the main window.</p><p>Do you want to <span style=" font-weight:600;">sign up</span> for a new account, or <span style=" font-weight:600;">log in</span> with an already existing username?</p></body></html> Qt::RichText -- 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') 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') 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') 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') 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/login.py | 11 ++++++++++- src/leap/bitmask/gui/mainwindow.py | 11 ++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/login.py b/src/leap/bitmask/gui/login.py index 8a7c6996..4a483c32 100644 --- a/src/leap/bitmask/gui/login.py +++ b/src/leap/bitmask/gui/login.py @@ -222,6 +222,15 @@ class LoginWidget(QtGui.QWidget): self._set_cancel(not enabled) + def set_logout_btn_enabled(self, enabled): + """ + Enables or disables the logout button. + + :param enabled: wether they should be enabled or not + :type enabled: bool + """ + self.ui.btnLogout.setEnabled(enabled) + def _set_cancel(self, enabled=False): """ Enables or disables the cancel action in the "log in" process. @@ -349,7 +358,7 @@ class LoginWidget(QtGui.QWidget): """ Sets the widgets to the logging out state """ - self.ui.btnLogout.setText(self.tr("Loggin out...")) + self.ui.btnLogout.setText(self.tr("Logging out...")) self.ui.btnLogout.setEnabled(False) def done_logout(self): 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') 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 2abe8f333f9b920b79d30903697f0ecd616d8c71 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Tue, 25 Feb 2014 22:01:55 -0400 Subject: fix phrasing of unread mail notification --- src/leap/bitmask/gui/mail_status.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py index 6db17427..1d5ff319 100644 --- a/src/leap/bitmask/gui/mail_status.py +++ b/src/leap/bitmask/gui/mail_status.py @@ -362,12 +362,17 @@ class MailStatusWidget(QtGui.QWidget): ext_status = None if req.event == proto.IMAP_UNREAD_MAIL: + # By now, the semantics of the UNREAD_MAIL event are + # limited to mails with the Unread flag *in the Inbox". + # We could make this configurable to include all unread mail + # or all unread mail in subscribed folders. if self._started: count = req.content if count != "0": - status = self.tr("{0} Unread Emails").format(count) + status = self.tr("{0} Unread Emails " + "in your Inbox").format(count) if count == "1": - status = self.tr("1 Unread Email") + status = self.tr("1 Unread Email in your Inbox") self._set_mail_status(status, ready=2) else: -- cgit v1.2.3 From 0f56f7c2c5ac1367e42694b34778d6e1b513feb7 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 25 Feb 2014 13:28:48 -0300 Subject: Add Pastebin button to logger window. Also add png image for the button and license information. --- src/leap/bitmask/gui/ui/loggerwindow.ui | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/ui/loggerwindow.ui b/src/leap/bitmask/gui/ui/loggerwindow.ui index 3de786f7..b19ed91a 100644 --- a/src/leap/bitmask/gui/ui/loggerwindow.ui +++ b/src/leap/bitmask/gui/ui/loggerwindow.ui @@ -6,8 +6,8 @@ 0 0 - 648 - 469 + 769 + 464
@@ -154,6 +154,17 @@
+ + + + Send to Pastebin.com + + + + :/images/pastebin.png:/images/pastebin.png + + +
-- cgit v1.2.3 From 4fddabec963015655a7129f1f95b95412b10ccf6 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 24 Feb 2014 18:38:39 -0300 Subject: Add pastebin support for upload logs. --- src/leap/bitmask/gui/loggerwindow.py | 61 ++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/loggerwindow.py b/src/leap/bitmask/gui/loggerwindow.py index 6ef58558..b32852c0 100644 --- a/src/leap/bitmask/gui/loggerwindow.py +++ b/src/leap/bitmask/gui/loggerwindow.py @@ -22,10 +22,13 @@ import logging import cgi from PySide import QtGui +from twisted.internet import threads from ui_loggerwindow import Ui_LoggerWindow +from leap.bitmask.util.constants import PASTEBIN_API_DEV_KEY from leap.bitmask.util.leap_log_handler import LeapLogHandler +from leap.bitmask.util.pastebin import PastebinAPI, PastebinError from leap.common.check import leap_assert, leap_assert_type logger = logging.getLogger(__name__) @@ -42,6 +45,9 @@ class LoggerWindow(QtGui.QDialog): :param handler: Custom handler that supports history and signal. :type handler: LeapLogHandler. """ + from twisted.internet import reactor + self.reactor = reactor + QtGui.QDialog.__init__(self) leap_assert(handler, "We need a handler for the logger window") leap_assert_type(handler, LeapLogHandler) @@ -59,8 +65,10 @@ class LoggerWindow(QtGui.QDialog): self.ui.btnCritical.toggled.connect(self._load_history) self.ui.leFilterBy.textEdited.connect(self._filter_by) self.ui.cbCaseInsensitive.stateChanged.connect(self._load_history) + self.ui.btnPastebin.clicked.connect(self._pastebin_this) self._current_filter = "" + self._current_history = "" # Load logging history and connect logger with the widget self._logging_handler = handler @@ -116,8 +124,13 @@ class LoggerWindow(QtGui.QDialog): self._set_logs_to_display() self.ui.txtLogHistory.clear() history = self._logging_handler.log_history + current_history = [] for line in history: self._add_log_line(line) + message = cgi.escape(line[LeapLogHandler.MESSAGE_KEY]) + current_history.append(message) + + self._current_history = "\n".join(current_history) def _set_logs_to_display(self): """ @@ -164,3 +177,51 @@ class LoggerWindow(QtGui.QDialog): logger.error("Error saving log file: %r" % (e, )) else: logger.debug('Log not saved!') + + def _pastebin_this(self): + """ + Send the current log history to pastebin.com and gives the user a link + to see it. + """ + def do_pastebin(): + """ + Send content to pastebin and return the link. + """ + content = self._current_history + pb = PastebinAPI() + link = pb.paste(PASTEBIN_API_DEV_KEY, content, + paste_name="Bitmask log", + paste_expire_date='1W') + return link + + def pastebin_ok(link): + """ + Callback handler for `do_pastebin`. + + :param link: the recently created pastebin link. + :type link: str + """ + msg = self.tr("Your pastebin link {0}") + msg = msg.format(link) + logger.debug(msg) + show_info = lambda: QtGui.QMessageBox.information( + self, self.tr("Pastebin OK"), msg) + self.reactor.callLater(0, show_info) + + def pastebin_err(failure): + """ + Errback handler for `do_pastebin`. + + :param failure: the failure that triggered the errback. + :type failure: twisted.python.failure.Failure + """ + logger.error(repr(failure)) + msg = self.tr("Sending logs to Pastebin failed!") + show_err = lambda: QtGui.QMessageBox.error( + self, self.tr("Pastebin Error"), msg) + self.reactor.callLater(0, show_err) + failure.trap(PastebinError) + + d = threads.deferToThread(do_pastebin) + d.addCallback(pastebin_ok) + d.addErrback(pastebin_err) -- cgit v1.2.3 From 6650529db2f001718bb79eab34aee4d4830eb346 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 26 Feb 2014 11:30:15 -0300 Subject: Show sending status in button and return raw link. --- src/leap/bitmask/gui/loggerwindow.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/loggerwindow.py b/src/leap/bitmask/gui/loggerwindow.py index b32852c0..9b6cef91 100644 --- a/src/leap/bitmask/gui/loggerwindow.py +++ b/src/leap/bitmask/gui/loggerwindow.py @@ -178,6 +178,21 @@ class LoggerWindow(QtGui.QDialog): else: logger.debug('Log not saved!') + def _set_pastebin_sending(self, sending): + """ + Define the status of the pastebin button. + Change the text and enable/disable according to the current action. + + :param sending: if we are sending to pastebin or not. + :type sending: bool + """ + if sending: + self.ui.btnPastebin.setText(self.tr("Sending to pastebin...")) + self.ui.btnPastebin.setEnabled(False) + else: + self.ui.btnPastebin.setText(self.tr("Send to Pastebin.com")) + self.ui.btnPastebin.setEnabled(True) + def _pastebin_this(self): """ Send the current log history to pastebin.com and gives the user a link @@ -192,6 +207,10 @@ class LoggerWindow(QtGui.QDialog): link = pb.paste(PASTEBIN_API_DEV_KEY, content, paste_name="Bitmask log", paste_expire_date='1W') + + # convert to 'raw' link + link = "http://pastebin.com/raw.php?i=" + link.split('/')[-1] + return link def pastebin_ok(link): @@ -206,6 +225,7 @@ class LoggerWindow(QtGui.QDialog): logger.debug(msg) show_info = lambda: QtGui.QMessageBox.information( self, self.tr("Pastebin OK"), msg) + self._set_pastebin_sending(False) self.reactor.callLater(0, show_info) def pastebin_err(failure): @@ -219,9 +239,11 @@ class LoggerWindow(QtGui.QDialog): msg = self.tr("Sending logs to Pastebin failed!") show_err = lambda: QtGui.QMessageBox.error( self, self.tr("Pastebin Error"), msg) + self._set_pastebin_sending(False) self.reactor.callLater(0, show_err) failure.trap(PastebinError) + self._set_pastebin_sending(True) d = threads.deferToThread(do_pastebin) d.addCallback(pastebin_ok) d.addErrback(pastebin_err) -- cgit v1.2.3 From ffec4eaf33b24565dec2fd1e2483e4edccecc887 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 26 Feb 2014 15:39:00 -0300 Subject: Fix wrong method name for pastebin error. --- src/leap/bitmask/gui/loggerwindow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/loggerwindow.py b/src/leap/bitmask/gui/loggerwindow.py index 9b6cef91..c01642fc 100644 --- a/src/leap/bitmask/gui/loggerwindow.py +++ b/src/leap/bitmask/gui/loggerwindow.py @@ -237,7 +237,7 @@ class LoggerWindow(QtGui.QDialog): """ logger.error(repr(failure)) msg = self.tr("Sending logs to Pastebin failed!") - show_err = lambda: QtGui.QMessageBox.error( + show_err = lambda: QtGui.QMessageBox.critical( self, self.tr("Pastebin Error"), msg) self._set_pastebin_sending(False) self.reactor.callLater(0, show_err) -- cgit v1.2.3 From 75c9b86e605742f2850d8b50b2419d75129e7949 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 28 Feb 2014 14:47:44 -0300 Subject: Do version checks in the wizard too. When the user choose to use an existing provider we download the provider.json again so the version checks are executed. [Closes #5048] --- src/leap/bitmask/gui/ui/wizard.ui | 73 ++++++++++++++++++++++++--------------- src/leap/bitmask/gui/wizard.py | 11 +++--- 2 files changed, 50 insertions(+), 34 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/ui/wizard.ui b/src/leap/bitmask/gui/ui/wizard.ui index d9b8499e..6c592522 100644 --- a/src/leap/bitmask/gui/ui/wizard.ui +++ b/src/leap/bitmask/gui/ui/wizard.ui @@ -269,20 +269,7 @@ Configure or select a provider - - - - - - - https:// - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - + Configure new provider: @@ -292,14 +279,27 @@ - - + + + + false + + + + + - Check + https:// + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + + + + Use existing one: @@ -309,7 +309,7 @@ - + https:// @@ -319,12 +319,29 @@ - - - - false - - + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Check + + + + @@ -859,8 +876,8 @@ 174 - 454 - 254 + 450 + 266 @@ -884,7 +901,7 @@ rbExistingProvider toggled(bool) btnCheck - setDisabled(bool) + setEnabled(bool) 169 diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index e1bed6b8..024b23bc 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -223,7 +223,7 @@ class Wizard(QtGui.QWizard): depending on the lnProvider content. """ enabled = len(self.ui.lnProvider.text()) != 0 - enabled = enabled and self.ui.rbNewProvider.isChecked() + enabled = enabled or self.ui.rbExistingProvider.isChecked() self.ui.btnCheck.setEnabled(enabled) if reset: @@ -367,8 +367,10 @@ class Wizard(QtGui.QWizard): Starts the checks for a given provider """ - if len(self.ui.lnProvider.text()) == 0: - return + if self.ui.rbNewProvider.isChecked(): + self._domain = self.ui.lnProvider.text() + else: + self._domain = self.ui.cbProviders.currentText() self._provider_checks_ok = False @@ -380,7 +382,6 @@ class Wizard(QtGui.QWizard): self.ui.btnCheck.setEnabled(False) self.ui.lnProvider.setEnabled(False) self.button(QtGui.QWizard.BackButton).clearFocus() - self._domain = self.ui.lnProvider.text() self.ui.lblNameResolution.setPixmap(self.QUESTION_ICON) self._provider_select_defer = self._backend.\ @@ -401,8 +402,6 @@ class Wizard(QtGui.QWizard): if skip: self._reset_provider_check() - self.page(self.SELECT_PROVIDER_PAGE).set_completed(skip) - self.button(QtGui.QWizard.NextButton).setEnabled(skip) self._use_existing_provider = skip def _complete_task(self, data, label, complete=False, complete_page=-1): -- cgit v1.2.3 From e90b36f9c1c2672c07e662d99e55dd87e5357711 Mon Sep 17 00:00:00 2001 From: KwadroNaut Date: Tue, 4 Mar 2014 17:32:20 +0100 Subject: =?UTF-8?q?double=20dot=20=E2=86=92=20ellipsis?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/leap/bitmask/gui/mail_status.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py index 1d5ff319..8da26f6d 100644 --- a/src/leap/bitmask/gui/mail_status.py +++ b/src/leap/bitmask/gui/mail_status.py @@ -213,7 +213,7 @@ class MailStatusWidget(QtGui.QWidget): self._service_name)) elif ready == 1: icon = self.CONNECTING_ICON - self._mx_status = self.tr('Starting..') + self._mx_status = self.tr('Starting…') tray_status = self.tr('Mail is starting') elif ready >= 2: icon = self.CONNECTED_ICON -- 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/eip_preferenceswindow.py | 21 ++++++++++++++++----- src/leap/bitmask/gui/mainwindow.py | 3 ++- 2 files changed, 18 insertions(+), 6 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/eip_preferenceswindow.py b/src/leap/bitmask/gui/eip_preferenceswindow.py index 504d1cf1..dcaa8b1e 100644 --- a/src/leap/bitmask/gui/eip_preferenceswindow.py +++ b/src/leap/bitmask/gui/eip_preferenceswindow.py @@ -22,7 +22,7 @@ import os import logging from functools import partial -from PySide import QtGui +from PySide import QtCore, QtGui from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.config.providerconfig import ProviderConfig @@ -37,10 +37,12 @@ class EIPPreferencesWindow(QtGui.QDialog): """ Window that displays the EIP preferences. """ - def __init__(self, parent): + def __init__(self, parent, domain): """ :param parent: parent object of the EIPPreferencesWindow. - :parent type: QWidget + :type parent: QWidget + :param domain: the selected by default domain. + :type domain: unicode """ QtGui.QDialog.__init__(self, parent) self.AUTOMATIC_GATEWAY_LABEL = self.tr("Automatic") @@ -59,7 +61,7 @@ class EIPPreferencesWindow(QtGui.QDialog): self.ui.cbGateways.currentIndexChanged[unicode].connect( lambda x: self.ui.lblProvidersGatewayStatus.setVisible(False)) - self._add_configured_providers() + self._add_configured_providers(domain) def _set_providers_gateway_status(self, status, success=False, error=False): @@ -83,9 +85,12 @@ class EIPPreferencesWindow(QtGui.QDialog): self.ui.lblProvidersGatewayStatus.setVisible(True) self.ui.lblProvidersGatewayStatus.setText(status) - def _add_configured_providers(self): + def _add_configured_providers(self, domain=None): """ Add the client's configured providers to the providers combo boxes. + + :param domain: the domain to be selected by default. + :type domain: unicode """ self.ui.cbProvidersGateway.clear() providers = self._settings.get_configured_providers() @@ -100,6 +105,12 @@ class EIPPreferencesWindow(QtGui.QDialog): label = provider + self.tr(" (uninitialized)") self.ui.cbProvidersGateway.addItem(label, userData=provider) + # Select provider by name + if domain is not None: + provider_index = self.ui.cbProvidersGateway.findText( + domain, QtCore.Qt.MatchStartsWith) + self.ui.cbProvidersGateway.setCurrentIndex(provider_index) + def _save_selected_gateway(self, provider): """ SLOT 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') 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') 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 + src/leap/bitmask/gui/twisted_main.py | 18 ------------------ 2 files changed, 1 insertion(+), 18 deletions(-) (limited to 'src/leap/bitmask/gui') 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, diff --git a/src/leap/bitmask/gui/twisted_main.py b/src/leap/bitmask/gui/twisted_main.py index e11af7bd..1e876c57 100644 --- a/src/leap/bitmask/gui/twisted_main.py +++ b/src/leap/bitmask/gui/twisted_main.py @@ -27,24 +27,6 @@ from twisted.internet import error logger = logging.getLogger(__name__) -def start(app): - """ - Start the mainloop. - - :param app: the main qt QApplication instance. - :type app: QtCore.QApplication - """ - from twisted.internet import reactor - logger.debug('starting twisted reactor') - - # this seems to be troublesome under some - # unidentified settings. - #reactor.run() - - reactor.runReturn() - app.exec_() - - def quit(app): """ Stop the mainloop. -- 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') 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') 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') 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/mail_status.py | 38 ++++++++++++++++++++++++++++++------- src/leap/bitmask/gui/mainwindow.py | 2 ++ 2 files changed, 33 insertions(+), 7 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py index 8da26f6d..44a138e2 100644 --- a/src/leap/bitmask/gui/mail_status.py +++ b/src/leap/bitmask/gui/mail_status.py @@ -112,6 +112,10 @@ class MailStatusWidget(QtGui.QWidget): callback=self._mail_handle_imap_events, reqcbk=lambda req, resp: None) + register(signal=proto.SOLEDAD_INVALID_AUTH_TOKEN, + callback=self.set_soledad_invalid_auth_token, + reqcbk=lambda req, resp: None) + self._soledad_event.connect( self._mail_handle_soledad_events_slot) self._imap_event.connect( @@ -191,6 +195,17 @@ class MailStatusWidget(QtGui.QWidget): msg = self.tr("There was an unexpected problem with Soledad.") self._set_mail_status(msg, ready=-1) + def set_soledad_invalid_auth_token(self): + """ + SLOT + TRIGGER: + SoledadBootstrapper.soledad_invalid_token + + This method is called when the auth token is invalid + """ + msg = self.tr("Invalid auth token, try logging in again.") + self._set_mail_status(msg, ready=-1) + def _set_mail_status(self, status, ready=0): """ Sets the Mail status in the label and in the tray icon. @@ -384,7 +399,7 @@ class MailStatusWidget(QtGui.QWidget): def about_to_start(self): """ - Displays the correct UI for the point where mail components + Display the correct UI for the point where mail components haven't really started, but they are about to in a second. """ self._set_mail_status(self.tr("About to start, please wait..."), @@ -392,7 +407,7 @@ class MailStatusWidget(QtGui.QWidget): def set_disabled(self): """ - Displays the correct UI for disabled mail. + Display the correct UI for disabled mail. """ self._set_mail_status(self.tr("Disabled"), -1) @@ -403,7 +418,7 @@ class MailStatusWidget(QtGui.QWidget): @QtCore.Slot() def mail_state_disconnected(self): """ - Displays the correct UI for the disconnected state. + Display the correct UI for the disconnected state. """ # XXX this should handle the disabled state better. self._started = False @@ -415,7 +430,7 @@ class MailStatusWidget(QtGui.QWidget): @QtCore.Slot() def mail_state_connecting(self): """ - Displays the correct UI for the connecting state. + Display the correct UI for the connecting state. """ self._disabled = False self._started = True @@ -424,23 +439,32 @@ class MailStatusWidget(QtGui.QWidget): @QtCore.Slot() def mail_state_disconnecting(self): """ - Displays the correct UI for the connecting state. + Display the correct UI for the connecting state. """ self._set_mail_status(self.tr("Disconnecting..."), 1) @QtCore.Slot() def mail_state_connected(self): """ - Displays the correct UI for the connected state. + Display the correct UI for the connected state. """ self._set_mail_status(self.tr("ON"), 2) @QtCore.Slot() def mail_state_disabled(self): """ - Displays the correct UI for the disabled state. + Display the correct UI for the disabled state. """ self._disabled = True status = self.tr("You must be logged in to use {0}.").format( self._service_name) self._set_mail_status(status, -1) + + @QtCore.Slot() + def soledad_invalid_auth_token(self): + """ + Display the correct UI for the invalid token state + """ + self._disabled = True + status = self.tr("Invalid auth token, try logging in again.") + self._set_mail_status(status, -1) 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 ec04455ddbdf2d1ae1b3fcc3bebc433f89f53601 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 18 Mar 2014 18:04:51 -0300 Subject: Move srpregister interaction to the backend. Also: - remove unused code. - add status attributes for srpauth responses. - split response handling - remove unneeded hack to avoid segfault emitting None --- src/leap/bitmask/gui/wizard.py | 106 +++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 47 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index 024b23bc..2f274e33 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -18,22 +18,18 @@ First run wizard """ import logging -import json import random from functools import partial from PySide import QtCore, QtGui -from twisted.internet import threads from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.config.providerconfig import ProviderConfig -from leap.bitmask.crypto.srpregister import SRPRegister from leap.bitmask.provider import get_provider_path from leap.bitmask.services import get_service_display_name, get_supported from leap.bitmask.util.keyring_helpers import has_keyring from leap.bitmask.util.password import basic_password_checks -from leap.bitmask.util.request_helpers import get_content from ui_wizard import Ui_Wizard @@ -253,16 +249,11 @@ class Wizard(QtGui.QWizard): ok, msg = basic_password_checks(username, password, password2) if ok: - register = SRPRegister(provider_config=self._provider_config) - register.registration_finished.connect( - self._registration_finished) - - threads.deferToThread( - partial(register.register_user, username, password)) + self._set_register_status(self.tr("Starting registration...")) + self._backend.register_user(self._domain, username, password) self._username = username self._password = password - self._set_register_status(self.tr("Starting registration...")) else: self._set_register_status(msg, error=True) self._focus_password() @@ -289,42 +280,59 @@ class Wizard(QtGui.QWizard): # register button self.ui.btnRegister.setVisible(visible) - def _registration_finished(self, ok, req): - if ok: - user_domain = self._username + "@" + self._domain - message = "

" - message += self.tr("User %s successfully registered.") % ( - user_domain, ) - message += "

" - self._set_register_status(message) - - self.ui.lblPassword2.clearFocus() - self._set_registration_fields_visibility(False) - - # Allow the user to remember his password - if has_keyring(): - self.ui.chkRemember.setVisible(True) - self.ui.chkRemember.setEnabled(True) - - self.page(self.REGISTER_USER_PAGE).set_completed() - self.button(QtGui.QWizard.BackButton).setEnabled(False) - else: - old_username = self._username - self._username = None - self._password = None - error_msg = self.tr("Something has gone wrong. " - "Please try again.") - try: - content, _ = get_content(req) - json_content = json.loads(content) - error_msg = json_content.get("errors").get("login")[0] - if not error_msg.istitle(): - error_msg = "%s %s" % (old_username, error_msg) - except Exception as e: - logger.error("Unknown error: %r" % (e,)) - - self._set_register_status(error_msg, error=True) - self.ui.btnRegister.setEnabled(True) + def _registration_finished(self): + """ + SLOT + TRIGGERS: + self._backend.signaler.srp_registration_finished + + The registration has finished successfully, so we do some final steps. + """ + user_domain = self._username + "@" + self._domain + message = "

" + message += self.tr("User %s successfully registered.") % ( + user_domain, ) + message += "

" + self._set_register_status(message) + + self.ui.lblPassword2.clearFocus() + self._set_registration_fields_visibility(False) + + # Allow the user to remember his password + if has_keyring(): + self.ui.chkRemember.setVisible(True) + self.ui.chkRemember.setEnabled(True) + + self.page(self.REGISTER_USER_PAGE).set_completed() + self.button(QtGui.QWizard.BackButton).setEnabled(False) + + def _registration_failed(self): + """ + SLOT + TRIGGERS: + self._backend.signaler.srp_registration_failed + + The registration has failed, so we report the problem. + """ + self._username = self._password = None + + error_msg = self.tr("Something has gone wrong. Please try again.") + self._set_register_status(error_msg, error=True) + self.ui.btnRegister.setEnabled(True) + + def _registration_taken(self): + """ + SLOT + TRIGGERS: + self._backend.signaler.srp_registration_taken + + The requested username is taken, warn the user about that. + """ + self._username = self._password = None + + error_msg = self.tr("The requested username is taken, choose another.") + self._set_register_status(error_msg, error=True) + self.ui.btnRegister.setEnabled(True) def _set_register_status(self, status, error=False): """ @@ -688,6 +696,10 @@ class Wizard(QtGui.QWizard): sig.prov_check_ca_fingerprint.connect(self._check_ca_fingerprint) sig.prov_check_api_certificate.connect(self._check_api_certificate) + sig.srp_registration_finished.connect(self._registration_finished) + sig.srp_registration_failed.connect(self._registration_failed) + sig.srp_registration_taken.connect(self._registration_taken) + def _backend_disconnect(self): """ This method is called when the wizard dialog is closed. -- 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') 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 b3e476088b8b94d9f914199a01b0bee69550396f Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 2 Apr 2014 12:18:07 -0300 Subject: Add hotkey for the Help menu. Closes #5401. --- src/leap/bitmask/gui/ui/mainwindow.ui | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/ui/mainwindow.ui b/src/leap/bitmask/gui/ui/mainwindow.ui index ce05f8f3..d755115a 100644 --- a/src/leap/bitmask/gui/ui/mainwindow.ui +++ b/src/leap/bitmask/gui/ui/mainwindow.ui @@ -75,7 +75,7 @@ 0 0 524 - 651 + 667 @@ -85,8 +85,6 @@ 0 - - @@ -134,7 +132,6 @@
- @@ -142,8 +139,6 @@ - - @@ -172,7 +167,6 @@ - @@ -180,8 +174,6 @@ - - @@ -204,7 +196,6 @@ - @@ -212,7 +203,6 @@ - @@ -307,7 +297,7 @@ 0 0 524 - 21 + 23 @@ -324,7 +314,7 @@ - Help + &Help -- cgit v1.2.3 From f8f428395b32f5e0d4f4c8dfb5595755dae80e54 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 2 Apr 2014 14:38:19 -0300 Subject: Don't escape logs for pastebin. Closes #5433. --- src/leap/bitmask/gui/loggerwindow.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/loggerwindow.py b/src/leap/bitmask/gui/loggerwindow.py index c01642fc..9f396574 100644 --- a/src/leap/bitmask/gui/loggerwindow.py +++ b/src/leap/bitmask/gui/loggerwindow.py @@ -127,7 +127,7 @@ class LoggerWindow(QtGui.QDialog): current_history = [] for line in history: self._add_log_line(line) - message = cgi.escape(line[LeapLogHandler.MESSAGE_KEY]) + message = line[LeapLogHandler.MESSAGE_KEY] current_history.append(message) self._current_history = "\n".join(current_history) @@ -222,7 +222,6 @@ class LoggerWindow(QtGui.QDialog): """ msg = self.tr("Your pastebin link {0}") msg = msg.format(link) - logger.debug(msg) show_info = lambda: QtGui.QMessageBox.information( self, self.tr("Pastebin OK"), msg) self._set_pastebin_sending(False) -- 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') 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') 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 b8e529c1656db1dc059b3cc1cb8d5319614c3986 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 2 Apr 2014 18:23:50 -0300 Subject: Reset checks if the provider is changed in wizard. Closes #5396. --- src/leap/bitmask/gui/wizard.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/leap/bitmask/gui') diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index 2f274e33..e2c1a16e 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -103,6 +103,8 @@ class Wizard(QtGui.QWizard): self.ui.lnProvider.textChanged.connect(self._enable_check) self.ui.rbNewProvider.toggled.connect( lambda x: self._enable_check()) + self.ui.cbProviders.currentIndexChanged[int].connect( + self._reset_provider_check) self.ui.lblUser.returnPressed.connect( self._focus_password) -- 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') 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