summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/leap/bitmask/app.py1
-rw-r--r--src/leap/bitmask/backend.py12
-rw-r--r--src/leap/bitmask/config/flags.py3
-rw-r--r--src/leap/bitmask/gui/advanced_key_management.py38
-rw-r--r--src/leap/bitmask/gui/eip_preferenceswindow.py15
-rw-r--r--src/leap/bitmask/gui/eip_status.py20
-rw-r--r--src/leap/bitmask/gui/login.py14
-rw-r--r--src/leap/bitmask/gui/mail_status.py28
-rw-r--r--src/leap/bitmask/gui/mainwindow.py206
-rw-r--r--src/leap/bitmask/gui/preferenceswindow.py28
-rw-r--r--src/leap/bitmask/gui/twisted_main.py15
-rw-r--r--src/leap/bitmask/gui/ui/advanced_key_management.ui2
-rw-r--r--src/leap/bitmask/gui/wizard.py83
-rw-r--r--src/leap/bitmask/services/mail/conductor.py5
-rw-r--r--src/leap/bitmask/util/leap_argparse.py4
15 files changed, 275 insertions, 199 deletions
diff --git a/src/leap/bitmask/app.py b/src/leap/bitmask/app.py
index 0a315be7..146743b5 100644
--- a/src/leap/bitmask/app.py
+++ b/src/leap/bitmask/app.py
@@ -214,6 +214,7 @@ def main():
flags.APP_VERSION_CHECK = opts.app_version_check
flags.API_VERSION_CHECK = opts.api_version_check
flags.OPENVPN_VERBOSITY = opts.openvpn_verb
+ flags.SKIP_WIZARD_CHECKS = opts.skip_wizard_checks
flags.CA_CERT_FILE = opts.ca_cert_file
diff --git a/src/leap/bitmask/backend.py b/src/leap/bitmask/backend.py
index d208a6cd..d5a8a4e9 100644
--- a/src/leap/bitmask/backend.py
+++ b/src/leap/bitmask/backend.py
@@ -340,11 +340,11 @@ class EIP(object):
try:
self._start_eip()
except vpnprocess.OpenVPNAlreadyRunning:
- signaler.signal(signaler.EIP_OPEN_VPN_ALREADY_RUNNING)
+ signaler.signal(signaler.EIP_OPENVPN_ALREADY_RUNNING)
except vpnprocess.AlienOpenVPNAlreadyRunning:
- signaler.signal(signaler.EIP_ALIEN_OPEN_VPN_ALREADY_RUNNING)
+ signaler.signal(signaler.EIP_ALIEN_OPENVPN_ALREADY_RUNNING)
except vpnlauncher.OpenVPNNotFoundException:
- signaler.signal(signaler.EIP_OPEN_VPN_NOT_FOUND_ERROR)
+ signaler.signal(signaler.EIP_OPENVPN_NOT_FOUND_ERROR)
except vpnlauncher.VPNLauncherException:
# TODO: this seems to be used for 'gateway not found' only.
# see vpnlauncher.py
@@ -1027,15 +1027,15 @@ class Backend(object):
Signals:
backend_bad_call
- eip_alien_open_vpn_already_running
+ eip_alien_openvpn_already_running
eip_connected
eip_connection_aborted
eip_network_unreachable
eip_no_pkexec_error
eip_no_polkit_agent_error
eip_no_tun_kext_error
- eip_open_vpn_already_running
- eip_open_vpn_not_found_error
+ eip_openvpn_already_running
+ eip_openvpn_not_found_error
eip_process_finished
eip_process_restart_ping
eip_process_restart_tls
diff --git a/src/leap/bitmask/config/flags.py b/src/leap/bitmask/config/flags.py
index 7cc8711c..6b70659d 100644
--- a/src/leap/bitmask/config/flags.py
+++ b/src/leap/bitmask/config/flags.py
@@ -52,3 +52,6 @@ CA_CERT_FILE = None
# OpenVPN verbosity level
OPENVPN_VERBOSITY = 1
+
+# Skip the checks in the wizard, use for testing purposes only!
+SKIP_WIZARD_CHECKS = False
diff --git a/src/leap/bitmask/gui/advanced_key_management.py b/src/leap/bitmask/gui/advanced_key_management.py
index cbc8c3e3..be6b4410 100644
--- a/src/leap/bitmask/gui/advanced_key_management.py
+++ b/src/leap/bitmask/gui/advanced_key_management.py
@@ -30,12 +30,17 @@ from ui_advanced_key_management import Ui_AdvancedKeyManagement
logger = logging.getLogger(__name__)
-class AdvancedKeyManagement(QtGui.QWidget):
+class AdvancedKeyManagement(QtGui.QDialog):
"""
Advanced Key Management
"""
- def __init__(self, user, keymanager, soledad):
+ def __init__(self, parent, has_mx, user, keymanager, soledad):
"""
+ :param parent: parent object of AdvancedKeyManagement.
+ :parent type: QWidget
+ :param has_mx: defines whether the current provider provides email or
+ not.
+ :type has_mx: bool
:param user: the current logged in user.
:type user: unicode
:param keymanager: the existing keymanager instance
@@ -43,7 +48,7 @@ class AdvancedKeyManagement(QtGui.QWidget):
:param soledad: a loaded instance of Soledad
:type soledad: Soledad
"""
- QtGui.QWidget.__init__(self)
+ QtGui.QDialog.__init__(self, parent)
self.ui = Ui_AdvancedKeyManagement()
self.ui.setupUi(self)
@@ -52,13 +57,18 @@ class AdvancedKeyManagement(QtGui.QWidget):
self.ui.pbImportKeys.setVisible(False)
# if Soledad is not started yet
+ if not has_mx:
+ msg = self.tr("The provider that you are using "
+ "does not support {0}.")
+ msg = msg.format(get_service_display_name(MX_SERVICE))
+ self._disable_ui(msg)
+ return
+
+ # if Soledad is not started yet
if sameProxiedObjects(soledad, None):
- self.ui.gbMyKeyPair.setEnabled(False)
- self.ui.gbStoredPublicKeys.setEnabled(False)
- msg = self.tr("<span style='color:#0000FF;'>NOTE</span>: "
- "To use this, you need to enable/start {0}.")
+ msg = self.tr("To use this, you need to enable/start {0}.")
msg = msg.format(get_service_display_name(MX_SERVICE))
- self.ui.lblStatus.setText(msg)
+ self._disable_ui(msg)
return
# XXX: since import is disabled this is no longer a dangerous feature.
# else:
@@ -90,6 +100,18 @@ class AdvancedKeyManagement(QtGui.QWidget):
self._list_keys()
+ def _disable_ui(self, msg):
+ """
+ Disable the UI and set a note in the status bar.
+
+ :param msg: note to display in the status bar.
+ :type msg: unicode
+ """
+ self.ui.gbMyKeyPair.setEnabled(False)
+ self.ui.gbStoredPublicKeys.setEnabled(False)
+ msg = self.tr("<span style='color:#0000FF;'>NOTE</span>: ") + msg
+ self.ui.lblStatus.setText(msg)
+
def _import_keys(self):
"""
Imports the user's key pair.
diff --git a/src/leap/bitmask/gui/eip_preferenceswindow.py b/src/leap/bitmask/gui/eip_preferenceswindow.py
index baf17395..530cd38d 100644
--- a/src/leap/bitmask/gui/eip_preferenceswindow.py
+++ b/src/leap/bitmask/gui/eip_preferenceswindow.py
@@ -98,9 +98,9 @@ class EIPPreferencesWindow(QtGui.QDialog):
self._backend.eip_get_initialized_providers(providers)
+ @QtCore.Slot(list)
def _load_providers_in_combo(self, providers):
"""
- SLOT
TRIGGERS:
Signaler.eip_get_initialized_providers
@@ -128,9 +128,9 @@ class EIPPreferencesWindow(QtGui.QDialog):
domain, QtCore.Qt.MatchStartsWith)
self.ui.cbProvidersGateway.setCurrentIndex(provider_index)
+ @QtCore.Slot(str)
def _save_selected_gateway(self, provider):
"""
- SLOT
TRIGGERS:
self.ui.pbSaveGateway.clicked
@@ -153,9 +153,9 @@ class EIPPreferencesWindow(QtGui.QDialog):
"Gateway settings for provider '{0}' saved.").format(provider)
self._set_providers_gateway_status(msg, success=True)
+ @QtCore.Slot(int)
def _populate_gateways(self, domain_idx):
"""
- SLOT
TRIGGERS:
self.ui.cbProvidersGateway.currentIndexChanged[unicode]
@@ -176,12 +176,15 @@ class EIPPreferencesWindow(QtGui.QDialog):
self._backend.eip_get_gateways_list(domain)
+ @QtCore.Slot(list)
def _update_gateways_list(self, gateways):
"""
- SLOT
TRIGGERS:
Signaler.eip_get_gateways_list
+ :param gateways: a list of gateways
+ :type gateways: list of unicode
+
Add the available gateways and select the one stored in configuration
file.
"""
@@ -214,9 +217,9 @@ class EIPPreferencesWindow(QtGui.QDialog):
self.ui.cbGateways.setCurrentIndex(index)
+ @QtCore.Slot()
def _gateways_list_error(self):
"""
- SLOT
TRIGGERS:
Signaler.eip_get_gateways_list_error
@@ -229,9 +232,9 @@ class EIPPreferencesWindow(QtGui.QDialog):
self.ui.pbSaveGateway.setEnabled(False)
self.ui.cbGateways.setEnabled(False)
+ @QtCore.Slot()
def _gateways_list_uninitialized(self):
"""
- SLOT
TRIGGERS:
Signaler.eip_uninitialized_provider
diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py
index f24d87c7..0d75b8e5 100644
--- a/src/leap/bitmask/gui/eip_status.py
+++ b/src/leap/bitmask/gui/eip_status.py
@@ -88,11 +88,12 @@ class EIPStatusWidget(QtGui.QWidget):
self.ui.btnUpload.clicked.connect(onclicked)
self.ui.btnDownload.clicked.connect(onclicked)
+ @QtCore.Slot()
def _on_VPN_status_clicked(self):
"""
- SLOT
- TRIGGER: self.ui.btnUpload.clicked
- self.ui.btnDownload.clicked
+ TRIGGERS:
+ self.ui.btnUpload.clicked
+ self.ui.btnDownload.clicked
Toggles between rate and total throughput display for vpn
status figures.
@@ -347,10 +348,11 @@ class EIPStatusWidget(QtGui.QWidget):
self.tr("Traffic is being routed in the clear"))
self.ui.lblEIPStatus.show()
+ @QtCore.Slot(dict)
def update_vpn_status(self, data=None):
"""
- SLOT
- TRIGGER: Signaler.eip_status_changed
+ TRIGGERS:
+ Signaler.eip_status_changed
Updates the download/upload labels based on the data provided by the
VPN thread.
@@ -381,14 +383,18 @@ class EIPStatusWidget(QtGui.QWidget):
self.ui.btnUpload.setText(upload_str)
self.ui.btnDownload.setText(download_str)
+ @QtCore.Slot(dict)
def update_vpn_state(self, vpn_state):
"""
- SLOT
- TRIGGER: Signaler.eip_state_changed
+ TRIGGERS:
+ Signaler.eip_state_changed
Updates the displayed VPN state based on the data provided by
the VPN thread.
+ :param vpn_state: the state of the VPN
+ :type vpn_state: dict
+
Emits:
If the vpn_state is connected, we emit EIPConnection.qtsigs.
connected_signal
diff --git a/src/leap/bitmask/gui/login.py b/src/leap/bitmask/gui/login.py
index 4a483c32..ac7ad878 100644
--- a/src/leap/bitmask/gui/login.py
+++ b/src/leap/bitmask/gui/login.py
@@ -259,12 +259,16 @@ class LoginWidget(QtGui.QWidget):
"""
self.ui.lnPassword.setFocus()
- def _current_provider_changed(self, param):
+ @QtCore.Slot(int)
+ def _current_provider_changed(self, idx):
"""
- SLOT
- TRIGGERS: self.ui.cmbProviders.currentIndexChanged
+ TRIGGERS:
+ self.ui.cmbProviders.currentIndexChanged
+
+ :param idx: the index of the new selected item
+ :type idx: int
"""
- if param == (self.ui.cmbProviders.count() - 1):
+ if idx == (self.ui.cmbProviders.count() - 1):
self.show_wizard.emit()
# Leave the previously selected provider in the combobox
prev_provider = 0
@@ -274,7 +278,7 @@ class LoginWidget(QtGui.QWidget):
self.ui.cmbProviders.setCurrentIndex(prev_provider)
self.ui.cmbProviders.blockSignals(False)
else:
- self._selected_provider_index = param
+ self._selected_provider_index = idx
def start_login(self):
"""
diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py
index 44a138e2..d3346780 100644
--- a/src/leap/bitmask/gui/mail_status.py
+++ b/src/leap/bitmask/gui/mail_status.py
@@ -184,10 +184,10 @@ class MailStatusWidget(QtGui.QWidget):
leap_assert_type(action_mail_status, QtGui.QAction)
self._action_mail_status = action_mail_status
+ @QtCore.Slot()
def set_soledad_failed(self):
"""
- SLOT
- TRIGGER:
+ TRIGGERS:
SoledadBootstrapper.soledad_failed
This method is called whenever soledad has a failure.
@@ -195,10 +195,10 @@ class MailStatusWidget(QtGui.QWidget):
msg = self.tr("There was an unexpected problem with Soledad.")
self._set_mail_status(msg, ready=-1)
+ @QtCore.Slot()
def set_soledad_invalid_auth_token(self):
"""
- SLOT
- TRIGGER:
+ TRIGGERS:
SoledadBootstrapper.soledad_invalid_token
This method is called when the auth token is invalid
@@ -250,10 +250,11 @@ class MailStatusWidget(QtGui.QWidget):
"""
self._soledad_event.emit(req)
+ @QtCore.Slot(object)
def _mail_handle_soledad_events_slot(self, req):
"""
- SLOT
- TRIGGER: _mail_handle_soledad_events
+ TRIGGERS:
+ _mail_handle_soledad_events
Reacts to an Soledad event
@@ -284,10 +285,11 @@ class MailStatusWidget(QtGui.QWidget):
"""
self._keymanager_event.emit(req)
+ @QtCore.Slot(object)
def _mail_handle_keymanager_events_slot(self, req):
"""
- SLOT
- TRIGGER: _mail_handle_keymanager_events
+ TRIGGERS:
+ _mail_handle_keymanager_events
Reacts to an KeyManager event
@@ -330,10 +332,11 @@ class MailStatusWidget(QtGui.QWidget):
"""
self._smtp_event.emit(req)
+ @QtCore.Slot(object)
def _mail_handle_smtp_events_slot(self, req):
"""
- SLOT
- TRIGGER: _mail_handle_smtp_events
+ TRIGGERS:
+ _mail_handle_smtp_events
Reacts to an SMTP event
@@ -364,10 +367,11 @@ class MailStatusWidget(QtGui.QWidget):
"""
self._imap_event.emit(req)
+ @QtCore.Slot(object)
def _mail_handle_imap_events_slot(self, req):
"""
- SLOT
- TRIGGER: _mail_handle_imap_events
+ TRIGGERS:
+ _mail_handle_imap_events
Reacts to an IMAP event
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index e5c11eb7..e4443434 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -457,10 +457,11 @@ class MainWindow(QtGui.QMainWindow):
self._backend_connected_signals = {}
+ @QtCore.Slot()
def _rejected_wizard(self):
"""
- SLOT
- TRIGGERS: self._wizard.rejected
+ TRIGGERS:
+ self._wizard.rejected
Called if the wizard has been cancelled or closed before
finishing.
@@ -481,12 +482,12 @@ class MainWindow(QtGui.QMainWindow):
if self._wizard_firstrun:
self._finish_init()
+ @QtCore.Slot()
def _launch_wizard(self):
"""
- SLOT
TRIGGERS:
- self._login_widget.show_wizard
- self.ui.action_wizard.triggered
+ self._login_widget.show_wizard
+ self.ui.action_wizard.triggered
Also called in first run.
@@ -509,11 +510,11 @@ class MainWindow(QtGui.QMainWindow):
self._wizard.finished.connect(self._wizard_finished)
self._settings.set_skip_first_run(True)
+ @QtCore.Slot()
def _wizard_finished(self):
"""
- SLOT
- TRIGGERS
- self._wizard.finished
+ TRIGGERS:
+ self._wizard.finished
Called when the wizard has finished.
"""
@@ -534,11 +535,11 @@ class MainWindow(QtGui.QMainWindow):
return h
return None
+ @QtCore.Slot()
def _show_logger_window(self):
"""
- SLOT
TRIGGERS:
- self.ui.action_show_logs.triggered
+ self.ui.action_show_logs.triggered
Displays the window with the history of messages logged until now
and displays the new ones on arrival.
@@ -555,9 +556,9 @@ class MainWindow(QtGui.QMainWindow):
else:
self._logger_window.setVisible(not self._logger_window.isVisible())
+ @QtCore.Slot()
def _show_AKM(self):
"""
- SLOT
TRIGGERS:
self.ui.action_advanced_key_management.triggered
@@ -565,16 +566,22 @@ class MainWindow(QtGui.QMainWindow):
"""
domain = self._login_widget.get_selected_provider()
logged_user = "{0}@{1}".format(self._logged_user, domain)
- self._akm = AdvancedKeyManagement(
- logged_user, self._keymanager, self._soledad)
- self._akm.show()
+ has_mx = True
+ if self._logged_user is not None:
+ provider_config = self._get_best_provider_config()
+ has_mx = provider_config.provides_mx()
+
+ akm = AdvancedKeyManagement(
+ self, has_mx, logged_user, self._keymanager, self._soledad)
+ akm.show()
+
+ @QtCore.Slot()
def _show_preferences(self):
"""
- SLOT
TRIGGERS:
- self.ui.btnPreferences.clicked (disabled for now)
- self.ui.action_preferences
+ self.ui.btnPreferences.clicked (disabled for now)
+ self.ui.action_preferences
Displays the preferences window.
"""
@@ -586,9 +593,9 @@ class MainWindow(QtGui.QMainWindow):
preferences.show()
preferences.preferences_saved.connect(self._update_eip_enabled_status)
+ @QtCore.Slot()
def _update_eip_enabled_status(self):
"""
- SLOT
TRIGGER:
PreferencesWindow.preferences_saved
@@ -622,12 +629,12 @@ class MainWindow(QtGui.QMainWindow):
return eip_enabled
+ @QtCore.Slot()
def _show_eip_preferences(self):
"""
- SLOT
TRIGGERS:
- self.ui.btnEIPPreferences.clicked
- self.ui.action_eip_preferences (disabled for now)
+ self.ui.btnEIPPreferences.clicked
+ self.ui.action_eip_preferences (disabled for now)
Displays the EIP preferences window.
"""
@@ -647,22 +654,27 @@ class MainWindow(QtGui.QMainWindow):
"""
self.new_updates.emit(req)
+ @QtCore.Slot(object)
def _react_to_new_updates(self, req):
"""
- SLOT
- TRIGGER: self._new_updates_available
+ TRIGGERS:
+ self.new_updates
Displays the new updates label and sets the updates_content
+
+ :param req: Request type
+ :type req: leap.common.events.events_pb2.SignalRequest
"""
self.moveToThread(QtCore.QCoreApplication.instance().thread())
self.ui.lblNewUpdates.setVisible(True)
self.ui.btnMore.setVisible(True)
self._updates_content = req.content
+ @QtCore.Slot()
def _updates_details(self):
"""
- SLOT
- TRIGGER: self.ui.btnMore.clicked
+ TRIGGERS:
+ self.ui.btnMore.clicked
Parses and displays the updates details
"""
@@ -686,11 +698,11 @@ class MainWindow(QtGui.QMainWindow):
self.tr("Updates available"),
msg)
+ @QtCore.Slot()
def _finish_init(self):
"""
- SLOT
TRIGGERS:
- self._wizard.accepted
+ self._wizard.accepted
Also called at the end of the constructor if not first run.
@@ -826,16 +838,21 @@ class MainWindow(QtGui.QMainWindow):
self._mail_status.set_systray(self._systray)
self._eip_status.set_systray(self._systray)
- hello = lambda: self._systray.showMessage(
- self.tr('Hello!'),
- self.tr('Bitmask has started in the tray.'))
- # we wait for the systray to be ready
- reactor.callLater(1, hello)
+ if self._start_hidden:
+ hello = lambda: self._systray.showMessage(
+ self.tr('Hello!'),
+ self.tr('Bitmask has started in the tray.'))
+ # we wait for the systray to be ready
+ reactor.callLater(1, hello)
+ @QtCore.Slot(int)
def _tray_activated(self, reason=None):
"""
- SLOT
- TRIGGER: self._systray.activated
+ TRIGGERS:
+ self._systray.activated
+
+ :param reason: the reason why the tray got activated.
+ :type reason: int
Displays the context menu from the tray icon
"""
@@ -862,10 +879,11 @@ class MainWindow(QtGui.QMainWindow):
visible = self.isVisible() and self.isActiveWindow()
self._action_visible.setText(get_action(visible))
+ @QtCore.Slot()
def _toggle_visible(self):
"""
- SLOT
- TRIGGER: self._action_visible.triggered
+ TRIGGERS:
+ self._action_visible.triggered
Toggles the window visibility
"""
@@ -909,10 +927,11 @@ class MainWindow(QtGui.QMainWindow):
if state is not None:
self.restoreState(state)
+ @QtCore.Slot()
def _about(self):
"""
- SLOT
- TRIGGERS: self.ui.action_about_leap.triggered
+ TRIGGERS:
+ self.ui.action_about_leap.triggered
Display the About Bitmask dialog
"""
@@ -936,10 +955,11 @@ class MainWindow(QtGui.QMainWindow):
"<a href='https://leap.se'>More about LEAP"
"</a>") % (VERSION, VERSION_HASH[:10], greet))
+ @QtCore.Slot()
def _help(self):
"""
- SLOT
- TRIGGERS: self.ui.action_help.triggered
+ TRIGGERS:
+ self.ui.action_help.triggered
Display the Bitmask help dialog.
"""
@@ -1036,10 +1056,11 @@ class MainWindow(QtGui.QMainWindow):
provider = self._login_widget.get_selected_provider()
self._backend.setup_provider(provider)
+ @QtCore.Slot(dict)
def _load_provider_config(self, data):
"""
- SLOT
- TRIGGER: self._backend.signaler.prov_download_provider_info
+ TRIGGERS:
+ self._backend.signaler.prov_download_provider_info
Once the provider config has been downloaded, this loads the
self._provider_config instance with it and starts the second
@@ -1054,8 +1075,9 @@ class MainWindow(QtGui.QMainWindow):
self._backend.provider_bootstrap(selected_provider)
else:
logger.error(data[self._backend.ERROR_KEY])
- self._login_widget.set_enabled(True)
+ self._login_problem_provider()
+ @QtCore.Slot()
def _login_problem_provider(self):
"""
Warns the user about a problem with the provider during login.
@@ -1064,11 +1086,11 @@ class MainWindow(QtGui.QMainWindow):
self.tr("Unable to login: Problem with provider"))
self._login_widget.set_enabled(True)
+ @QtCore.Slot()
def _login(self):
"""
- SLOT
TRIGGERS:
- self._login_widget.login
+ self._login_widget.login
Starts the login sequence. Which involves bootstrapping the
selected provider if the selection is valid (not empty), then
@@ -1092,9 +1114,9 @@ class MainWindow(QtGui.QMainWindow):
if self._login_widget.start_login():
self._download_provider_config()
+ @QtCore.Slot(unicode)
def _authentication_error(self, msg):
"""
- SLOT
TRIGGERS:
Signaler.srp_auth_error
Signaler.srp_auth_server_error
@@ -1110,11 +1132,11 @@ class MainWindow(QtGui.QMainWindow):
self._login_widget.set_enabled(True)
self.ui.action_create_new_account.setEnabled(True)
+ @QtCore.Slot()
def _cancel_login(self):
"""
- SLOT
TRIGGERS:
- self._login_widget.cancel_login
+ self._login_widget.cancel_login
Stops the login sequence.
"""
@@ -1134,9 +1156,9 @@ class MainWindow(QtGui.QMainWindow):
self._soledad_defer.cancel()
self._soledad_defer = None
+ @QtCore.Slot()
def _set_login_cancelled(self):
"""
- SLOT
TRIGGERS:
Signaler.prov_cancelled_setup fired by
self._backend.cancel_setup_provider()
@@ -1147,10 +1169,11 @@ class MainWindow(QtGui.QMainWindow):
self._login_widget.set_status(self.tr("Log in cancelled by the user."))
self._login_widget.set_enabled(True)
+ @QtCore.Slot(dict)
def _provider_config_loaded(self, data):
"""
- SLOT
- TRIGGER: self._backend.signaler.prov_check_api_certificate
+ TRIGGERS:
+ self._backend.signaler.prov_check_api_certificate
Once the provider configuration is loaded, this starts the SRP
authentication
@@ -1166,15 +1189,14 @@ class MainWindow(QtGui.QMainWindow):
domain = self._provider_config.get_domain()
self._backend.login(domain, username, password)
else:
- self._login_widget.set_status(
- "Unable to login: Problem with provider")
logger.error(data[self._backend.ERROR_KEY])
- self._login_widget.set_enabled(True)
+ self._login_problem_provider()
+ @QtCore.Slot()
def _authentication_finished(self):
"""
- SLOT
- TRIGGER: self._srp_auth.authentication_finished
+ TRIGGERS:
+ self._srp_auth.authentication_finished
Once the user is properly authenticated, try starting the EIP
service
@@ -1285,12 +1307,12 @@ class MainWindow(QtGui.QMainWindow):
###################################################################
# Service control methods: soledad
+ @QtCore.Slot(dict)
def _soledad_intermediate_stage(self, data):
# TODO missing param docstring
"""
- SLOT
TRIGGERS:
- self._soledad_bootstrapper.download_config
+ self._soledad_bootstrapper.download_config
If there was a problem, displays it, otherwise it does nothing.
This is used for intermediate bootstrapping stages, in case
@@ -1320,12 +1342,12 @@ class MainWindow(QtGui.QMainWindow):
logger.warning("Max number of soledad initialization "
"retries reached.")
+ @QtCore.Slot(dict)
def _soledad_bootstrapped_stage(self, data):
"""
- SLOT
TRIGGERS:
- self._soledad_bootstrapper.gen_key
- self._soledad_bootstrapper.local_only_ready
+ 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
@@ -1364,7 +1386,6 @@ class MainWindow(QtGui.QMainWindow):
@QtCore.Slot()
def _start_smtp_bootstrapping(self):
"""
- SLOT
TRIGGERS:
self.soledad_ready
"""
@@ -1385,7 +1406,6 @@ class MainWindow(QtGui.QMainWindow):
@QtCore.Slot()
def _stop_smtp_service(self):
"""
- SLOT
TRIGGERS:
self.logout
"""
@@ -1398,7 +1418,6 @@ class MainWindow(QtGui.QMainWindow):
@QtCore.Slot()
def _start_imap_service(self):
"""
- SLOT
TRIGGERS:
self.soledad_ready
"""
@@ -1428,7 +1447,6 @@ class MainWindow(QtGui.QMainWindow):
@QtCore.Slot()
def _fetch_incoming_mail(self):
"""
- SLOT
TRIGGERS:
self.mail_client_logged_in
"""
@@ -1438,7 +1456,6 @@ class MainWindow(QtGui.QMainWindow):
@QtCore.Slot()
def _stop_imap_service(self):
"""
- SLOT
TRIGGERS:
self.logout
"""
@@ -1487,9 +1504,9 @@ class MainWindow(QtGui.QMainWindow):
@QtCore.Slot()
def _on_eip_connection_connected(self):
"""
- SLOT
TRIGGERS:
self._eip_status.eip_connection_connected
+
Emits the EIPConnection.qtsigs.connected_signal
This is a little workaround for connecting the vpn-connected
@@ -1589,9 +1606,9 @@ class MainWindow(QtGui.QMainWindow):
self._backend.start_eip()
+ @QtCore.Slot()
def _on_eip_connection_aborted(self):
"""
- SLOT
TRIGGERS:
Signaler.eip_connection_aborted
"""
@@ -1667,7 +1684,6 @@ class MainWindow(QtGui.QMainWindow):
@QtCore.Slot()
def _stop_eip(self):
"""
- SLOT
TRIGGERS:
self._eip_connection.qtsigs.do_disconnect_signal (via state machine)
@@ -1697,7 +1713,6 @@ class MainWindow(QtGui.QMainWindow):
def _on_eip_network_unreachable(self):
# XXX Should move to EIP Conductor
"""
- SLOT
TRIGGERS:
self._eip_connection.qtsigs.network_unreachable
@@ -1711,7 +1726,7 @@ class MainWindow(QtGui.QMainWindow):
def _do_eip_restart(self):
# XXX Should move to EIP Conductor
"""
- SLOT
+ TRIGGERS:
self._eip_connection.qtsigs.process_restart
Restart the connection.
@@ -1729,9 +1744,9 @@ class MainWindow(QtGui.QMainWindow):
self._eip_status.set_eip_status("", error=error)
self._eip_status.set_eip_status_icon("error")
+ @QtCore.Slot(int)
def _eip_finished(self, exitCode):
"""
- SLOT
TRIGGERS:
Signaler.eip_process_finished
@@ -1794,8 +1809,6 @@ class MainWindow(QtGui.QMainWindow):
Start the EIP bootstrapping sequence if the client is configured to
do so.
"""
- provider_config = self._get_best_provider_config()
-
if self._provides_eip_and_enabled() and not self._already_started_eip:
# XXX this should be handled by the state machine.
self._eip_status.set_eip_status(
@@ -1822,10 +1835,11 @@ class MainWindow(QtGui.QMainWindow):
# eip will not start, so we start soledad anyway
self._maybe_run_soledad_setup_checks()
+ @QtCore.Slot(dict)
def _finish_eip_bootstrap(self, data):
"""
- SLOT
- TRIGGER: self._backend.signaler.eip_client_certificate_ready
+ TRIGGERS:
+ self._backend.signaler.eip_client_certificate_ready
Starts the VPN thread if the eip configuration is properly
loaded
@@ -1842,12 +1856,12 @@ class MainWindow(QtGui.QMainWindow):
# DO START EIP Connection!
self._eip_connection.qtsigs.do_connect_signal.emit()
+ @QtCore.Slot(dict)
def _eip_intermediate_stage(self, data):
# TODO missing param
"""
- SLOT
TRIGGERS:
- self._backend.signaler.eip_config_ready
+ self._backend.signaler.eip_config_ready
If there was a problem, displays it, otherwise it does nothing.
This is used for intermediate bootstrapping stages, in case
@@ -1889,8 +1903,8 @@ class MainWindow(QtGui.QMainWindow):
@QtCore.Slot()
def _logout(self):
"""
- SLOT
- TRIGGER: self._login_widget.logout
+ TRIGGERS:
+ self._login_widget.logout
Starts the logout sequence
"""
@@ -1907,10 +1921,11 @@ class MainWindow(QtGui.QMainWindow):
self._backend.logout()
self.logout.emit()
+ @QtCore.Slot()
def _logout_error(self):
"""
- SLOT
- TRIGGER: self._srp_auth.logout_error
+ TRIGGER:
+ self._srp_auth.logout_error
Inform the user about a logout error.
"""
@@ -1919,10 +1934,11 @@ class MainWindow(QtGui.QMainWindow):
self._login_widget.set_status(
self.tr("Something went wrong with the logout."))
+ @QtCore.Slot()
def _logout_ok(self):
"""
- SLOT
- TRIGGER: self._srp_auth.logout_ok
+ TRIGGER:
+ self._srp_auth.logout_ok
Switches the stackedWidget back to the login stage after
logging out
@@ -1934,15 +1950,14 @@ class MainWindow(QtGui.QMainWindow):
self._login_widget.logged_out()
self._mail_status.mail_state_disabled()
+ @QtCore.Slot(dict)
def _intermediate_stage(self, data):
# TODO this method name is confusing as hell.
"""
- SLOT
TRIGGERS:
- self._backend.signaler.prov_name_resolution
- self._backend.signaler.prov_https_connection
- self._backend.signaler.prov_download_ca_cert
- self._backend.signaler.eip_config_ready
+ self._backend.signaler.prov_name_resolution
+ self._backend.signaler.prov_https_connection
+ self._backend.signaler.prov_download_ca_cert
If there was a problem, displays it, otherwise it does nothing.
This is used for intermediate bootstrapping stages, in case
@@ -1950,10 +1965,8 @@ class MainWindow(QtGui.QMainWindow):
"""
passed = data[self._backend.PASSED_KEY]
if not passed:
- msg = self.tr("Unable to connect: Problem with provider")
- self._login_widget.set_status(msg)
- self._login_widget.set_enabled(True)
logger.error(data[self._backend.ERROR_KEY])
+ self._login_problem_provider()
#
# window handling methods
@@ -1967,9 +1980,9 @@ class MainWindow(QtGui.QMainWindow):
raise_window_ack()
self.raise_window.emit()
+ @QtCore.Slot()
def _do_raise_mainwindow(self):
"""
- SLOT
TRIGGERS:
self._on_raise_window_event
@@ -2033,9 +2046,10 @@ class MainWindow(QtGui.QMainWindow):
# first thing to do quitting, hide the mainwindow and show tooltip.
self.hide()
- self._systray.showMessage(
- self.tr('Quitting...'),
- self.tr('The app is quitting, please wait.'))
+ if self._systray is not None:
+ self._systray.showMessage(
+ self.tr('Quitting...'),
+ self.tr('The app is quitting, please wait.'))
# explicitly process events to display tooltip immediately
QtCore.QCoreApplication.processEvents()
diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py
index f6bd1ed3..014a0a4f 100644
--- a/src/leap/bitmask/gui/preferenceswindow.py
+++ b/src/leap/bitmask/gui/preferenceswindow.py
@@ -89,9 +89,9 @@ class PreferencesWindow(QtGui.QDialog):
self._select_provider_by_name(domain)
+ @QtCore.Slot()
def _is_logged_in(self):
"""
- SLOT
TRIGGERS:
Signaler.srp_status_logged_in
@@ -123,9 +123,9 @@ class PreferencesWindow(QtGui.QDialog):
self.ui.gbPasswordChange.setEnabled(pw_enabled)
+ @QtCore.Slot()
def _not_logged_in(self):
"""
- SLOT
TRIGGERS:
Signaler.srp_status_not_logged_in
@@ -136,9 +136,9 @@ class PreferencesWindow(QtGui.QDialog):
self._set_password_change_status(msg)
self.ui.gbPasswordChange.setEnabled(False)
+ @QtCore.Slot()
def set_soledad_ready(self):
"""
- SLOT
TRIGGERS:
parent.soledad_ready
@@ -183,9 +183,9 @@ class PreferencesWindow(QtGui.QDialog):
self.ui.leNewPassword2.setEnabled(not disable)
self.ui.pbChangePassword.setEnabled(not disable)
+ @QtCore.Slot()
def _change_password(self):
"""
- SLOT
TRIGGERS:
self.ui.pbChangePassword.clicked
@@ -207,11 +207,11 @@ class PreferencesWindow(QtGui.QDialog):
self._set_changing_password(True)
self._backend.change_password(current_password, new_password)
+ @QtCore.Slot()
def _change_password_ok(self):
"""
- SLOT
TRIGGERS:
- self._backend.signaler.srp_password_change_ok
+ self._backend.signaler.srp_password_change_ok
Callback used to display a successfully changed password.
"""
@@ -229,12 +229,12 @@ class PreferencesWindow(QtGui.QDialog):
self._clear_password_inputs()
self._set_changing_password(False)
+ @QtCore.Slot(unicode)
def _change_password_problem(self, msg):
"""
- SLOT
TRIGGERS:
- self._backend.signaler.srp_password_change_error
- self._backend.signaler.srp_password_change_badpw
+ self._backend.signaler.srp_password_change_error
+ self._backend.signaler.srp_password_change_badpw
Callback used to display an error on changing password.
@@ -287,10 +287,12 @@ class PreferencesWindow(QtGui.QDialog):
provider_index = self.ui.cbProvidersServices.findText(name)
self.ui.cbProvidersServices.setCurrentIndex(provider_index)
+ @QtCore.Slot(str, int)
def _service_selection_changed(self, service, state):
"""
- SLOT
- TRIGGER: service_checkbox.stateChanged
+ TRIGGERS:
+ service_checkbox.stateChanged
+
Adds the service to the state if the state is checked, removes
it otherwise
@@ -309,9 +311,9 @@ class PreferencesWindow(QtGui.QDialog):
# We hide the maybe-visible status label after a change
self.ui.lblProvidersServicesStatus.setVisible(False)
+ @QtCore.Slot(str)
def _populate_services(self, domain):
"""
- SLOT
TRIGGERS:
self.ui.cbProvidersServices.currentIndexChanged[unicode]
@@ -368,9 +370,9 @@ class PreferencesWindow(QtGui.QDialog):
logger.error("Something went wrong while trying to "
"load service %s" % (service,))
+ @QtCore.Slot(str)
def _save_enabled_services(self, provider):
"""
- SLOT
TRIGGERS:
self.ui.pbSaveServices.clicked
diff --git a/src/leap/bitmask/gui/twisted_main.py b/src/leap/bitmask/gui/twisted_main.py
index ece32ca2..f39d0bbe 100644
--- a/src/leap/bitmask/gui/twisted_main.py
+++ b/src/leap/bitmask/gui/twisted_main.py
@@ -22,9 +22,6 @@ import logging
from twisted.internet import error, reactor
from PySide import QtCore
-# Resist the temptation of putting the import reactor here,
-# it will raise an "reactor already imported" error.
-
logger = logging.getLogger(__name__)
@@ -32,7 +29,11 @@ def stop():
logger.debug("Really stoping all the things...")
QtCore.QCoreApplication.sendPostedEvents()
QtCore.QCoreApplication.flush()
- reactor.stop()
+ try:
+ reactor.stop()
+ logger.debug('Twisted reactor stopped')
+ except error.ReactorNotRunning:
+ logger.debug('Twisted reactor not running')
logger.debug("Done stopping all the things.")
@@ -43,8 +44,4 @@ def quit(app):
:param app: the main qt QApplication instance.
:type app: QtCore.QApplication
"""
- logger.debug('Stopping twisted reactor')
- try:
- reactor.callLater(0, stop)
- except error.ReactorNotRunning:
- logger.debug('Reactor not running')
+ reactor.callLater(0, stop)
diff --git a/src/leap/bitmask/gui/ui/advanced_key_management.ui b/src/leap/bitmask/gui/ui/advanced_key_management.ui
index 1112670f..3b567347 100644
--- a/src/leap/bitmask/gui/ui/advanced_key_management.ui
+++ b/src/leap/bitmask/gui/ui/advanced_key_management.ui
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AdvancedKeyManagement</class>
- <widget class="QWidget" name="AdvancedKeyManagement">
+ <widget class="QDialog" name="AdvancedKeyManagement">
<property name="geometry">
<rect>
<x>0</x>
diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py
index ebcee400..020a58e2 100644
--- a/src/leap/bitmask/gui/wizard.py
+++ b/src/leap/bitmask/gui/wizard.py
@@ -24,6 +24,7 @@ from functools import partial
from PySide import QtCore, QtGui
+from leap.bitmask.config import flags
from leap.bitmask.config.leapsettings import LeapSettings
from leap.bitmask.config.providerconfig import ProviderConfig
from leap.bitmask.provider import get_provider_path
@@ -145,8 +146,7 @@ class Wizard(QtGui.QWizard):
@QtCore.Slot()
def _wizard_finished(self):
"""
- SLOT
- TRIGGER:
+ TRIGGERS:
self.finished
This method is called when the wizard is accepted or rejected.
@@ -210,15 +210,19 @@ class Wizard(QtGui.QWizard):
def get_services(self):
return self._selected_services
- @QtCore.Slot()
+ @QtCore.Slot(unicode)
def _enable_check(self, reset=True):
"""
- SLOT
- TRIGGER:
+ TRIGGERS:
self.ui.lnProvider.textChanged
Enables/disables the 'check' button in the SELECT_PROVIDER_PAGE
depending on the lnProvider content.
+
+ :param reset: this contains the text of the line edit, and when is
+ called directly defines whether we want to reset the
+ checks.
+ :type reset: unicode or bool
"""
enabled = len(self.ui.lnProvider.text()) != 0
enabled = enabled or self.ui.rbExistingProvider.isChecked()
@@ -282,11 +286,11 @@ class Wizard(QtGui.QWizard):
# register button
self.ui.btnRegister.setVisible(visible)
+ @QtCore.Slot()
def _registration_finished(self):
"""
- SLOT
TRIGGERS:
- self._backend.signaler.srp_registration_finished
+ self._backend.signaler.srp_registration_finished
The registration has finished successfully, so we do some final steps.
"""
@@ -308,11 +312,11 @@ class Wizard(QtGui.QWizard):
self.page(self.REGISTER_USER_PAGE).set_completed()
self.button(QtGui.QWizard.BackButton).setEnabled(False)
+ @QtCore.Slot()
def _registration_failed(self):
"""
- SLOT
TRIGGERS:
- self._backend.signaler.srp_registration_failed
+ self._backend.signaler.srp_registration_failed
The registration has failed, so we report the problem.
"""
@@ -322,11 +326,11 @@ class Wizard(QtGui.QWizard):
self._set_register_status(error_msg, error=True)
self.ui.btnRegister.setEnabled(True)
+ @QtCore.Slot()
def _registration_taken(self):
"""
- SLOT
TRIGGERS:
- self._backend.signaler.srp_registration_taken
+ self._backend.signaler.srp_registration_taken
The requested username is taken, warn the user about that.
"""
@@ -358,7 +362,8 @@ class Wizard(QtGui.QWizard):
self.ui.lblProviderSelectStatus.setText("")
self._domain = None
self.button(QtGui.QWizard.NextButton).setEnabled(False)
- self.page(self.SELECT_PROVIDER_PAGE).set_completed(False)
+ self.page(self.SELECT_PROVIDER_PAGE).set_completed(
+ flags.SKIP_WIZARD_CHECKS)
def _reset_provider_setup(self):
"""
@@ -368,12 +373,12 @@ class Wizard(QtGui.QWizard):
self.ui.lblCheckCaFpr.setPixmap(None)
self.ui.lblCheckApiCert.setPixmap(None)
+ @QtCore.Slot()
def _check_provider(self):
"""
- SLOT
TRIGGERS:
- self.ui.btnCheck.clicked
- self.ui.lnProvider.returnPressed
+ self.ui.btnCheck.clicked
+ self.ui.lnProvider.returnPressed
Starts the checks for a given provider
"""
@@ -403,10 +408,10 @@ class Wizard(QtGui.QWizard):
self._provider_select_defer = self._backend.\
setup_provider(self._domain)
+ @QtCore.Slot(bool)
def _skip_provider_checks(self, skip):
"""
- SLOT
- Triggered:
+ TRIGGERS:
self.ui.rbExistingProvider.toggled
Allows the user to move to the next page without make any checks,
@@ -447,10 +452,11 @@ class Wizard(QtGui.QWizard):
label.setPixmap(self.ERROR_ICON)
logger.error(error)
+ @QtCore.Slot(dict)
def _name_resolution(self, data):
"""
- SLOT
- TRIGGER: self._backend.signaler.prov_name_resolution
+ TRIGGERS:
+ self._backend.signaler.prov_name_resolution
Sets the status for the name resolution check
"""
@@ -466,10 +472,11 @@ class Wizard(QtGui.QWizard):
self.ui.btnCheck.setEnabled(not passed)
self.ui.lnProvider.setEnabled(not passed)
+ @QtCore.Slot(dict)
def _https_connection(self, data):
"""
- SLOT
- TRIGGER: self._backend.signaler.prov_https_connection
+ TRIGGERS:
+ self._backend.signaler.prov_https_connection
Sets the status for the https connection check
"""
@@ -485,10 +492,11 @@ class Wizard(QtGui.QWizard):
self.ui.btnCheck.setEnabled(not passed)
self.ui.lnProvider.setEnabled(not passed)
+ @QtCore.Slot(dict)
def _download_provider_info(self, data):
"""
- SLOT
- TRIGGER: self._backend.signaler.prov_download_provider_info
+ TRIGGERS:
+ self._backend.signaler.prov_download_provider_info
Sets the status for the provider information download
check. Since this check is the last of this set, it also
@@ -519,10 +527,11 @@ class Wizard(QtGui.QWizard):
else:
self.ui.cbProviders.setEnabled(True)
+ @QtCore.Slot(dict)
def _download_ca_cert(self, data):
"""
- SLOT
- TRIGGER: self._backend.signaler.prov_download_ca_cert
+ TRIGGERS:
+ self._backend.signaler.prov_download_ca_cert
Sets the status for the download of the CA certificate check
"""
@@ -531,10 +540,11 @@ class Wizard(QtGui.QWizard):
if passed:
self.ui.lblCheckCaFpr.setPixmap(self.QUESTION_ICON)
+ @QtCore.Slot(dict)
def _check_ca_fingerprint(self, data):
"""
- SLOT
- TRIGGER: self._backend.signaler.prov_check_ca_fingerprint
+ TRIGGERS:
+ self._backend.signaler.prov_check_ca_fingerprint
Sets the status for the CA fingerprint check
"""
@@ -543,10 +553,11 @@ class Wizard(QtGui.QWizard):
if passed:
self.ui.lblCheckApiCert.setPixmap(self.QUESTION_ICON)
+ @QtCore.Slot(dict)
def _check_api_certificate(self, data):
"""
- SLOT
- TRIGGER: self._backend.signaler.prov_check_api_certificate
+ TRIGGERS:
+ self._backend.signaler.prov_check_api_certificate
Sets the status for the API certificate check. Also finishes
the provider bootstrapper thread since it's not needed anymore
@@ -556,10 +567,12 @@ class Wizard(QtGui.QWizard):
True, self.SETUP_PROVIDER_PAGE)
self._provider_setup_ok = True
+ @QtCore.Slot(str, int)
def _service_selection_changed(self, service, state):
"""
- SLOT
- TRIGGER: service_checkbox.stateChanged
+ TRIGGERS:
+ service_checkbox.stateChanged
+
Adds the service to the state if the state is checked, removes
it otherwise
@@ -604,12 +617,16 @@ class Wizard(QtGui.QWizard):
self.tr("Something went wrong while trying to "
"load service %s" % (service,)))
+ @QtCore.Slot(int)
def _current_id_changed(self, pageId):
"""
- SLOT
- TRIGGER: self.currentIdChanged
+ TRIGGERS:
+ self.currentIdChanged
Prepares the pages when they appear
+
+ :param pageId: the new current page id.
+ :type pageId: int
"""
if pageId == self.SELECT_PROVIDER_PAGE:
self._clear_register_widgets()
diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py
index 79f324dc..c1761afa 100644
--- a/src/leap/bitmask/services/mail/conductor.py
+++ b/src/leap/bitmask/services/mail/conductor.py
@@ -238,12 +238,11 @@ class SMTPControl(object):
self._smtp_port.stopListening()
self._smtp_service.doStop()
- @QtCore.Slot()
+ @QtCore.Slot(dict)
def smtp_bootstrapped_stage(self, data):
"""
- SLOT
TRIGGERS:
- self.smtp_bootstrapper.download_config
+ self.smtp_bootstrapper.download_config
If there was a problem, displays it, otherwise it does nothing.
This is used for intermediate bootstrapping stages, in case
diff --git a/src/leap/bitmask/util/leap_argparse.py b/src/leap/bitmask/util/leap_argparse.py
index 8aacc85d..84af4e8d 100644
--- a/src/leap/bitmask/util/leap_argparse.py
+++ b/src/leap/bitmask/util/leap_argparse.py
@@ -62,6 +62,10 @@ def build_parser():
parser.add_argument('-H', '--start-hidden', default=False,
action="store_true", dest="start_hidden",
help='Starts the application just in the taskbar.')
+ parser.add_argument('-S', '--skip-wizard-checks', default=False,
+ action="store_true", dest="skip_wizard_checks",
+ help='Skips the provider checks in the wizard (use '
+ 'for testing purposes only).')
# openvpn options
parser.add_argument('--openvpn-verbosity', nargs='?',