summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.rst30
-rw-r--r--changes/4035_add-eip-cancel-button1
-rw-r--r--changes/5870_bitmask-prevent-system-logout-on-linux1
-rw-r--r--changes/add-backend-alive-check1
-rw-r--r--changes/add-frontend-alive-check2
-rw-r--r--changes/add-linux-autostart1
-rw-r--r--changes/bug-5949_pastebin-does-not-work1
-rw-r--r--changes/bug_5939_wait-for-eip-to-autologin1
-rw-r--r--changes/bug_5955_fix-vpnlauncher-error-ui1
-rw-r--r--changes/bug_logger-hangs-quit1
-rw-r--r--changes/bug_set-standalone-flags-for-baseconfig1
-rw-r--r--changes/bug_show_hide_improved1
-rw-r--r--changes/bug_use-smaller-window-to-fit-lower-resolutions1
-rw-r--r--changes/disable-user-pass-remembering1
-rw-r--r--changes/enable-child-process-in-backend1
-rw-r--r--changes/feature_restrict-certificates-permissions1
-rw-r--r--changes/minor-ui-adjustments1
-rw-r--r--relnotes.txt20
-rw-r--r--src/leap/bitmask/gui/login.py75
-rw-r--r--src/leap/bitmask/gui/mainwindow.py153
-rw-r--r--src/leap/bitmask/gui/providers.py114
-rw-r--r--src/leap/bitmask/gui/ui/login.ui25
-rw-r--r--src/leap/bitmask/gui/ui/mainwindow.ui39
-rw-r--r--src/leap/bitmask/platform_init/initializers.py1
-rw-r--r--src/leap/bitmask/util/credentials.py4
25 files changed, 291 insertions, 187 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index e8d24c95..c47e531a 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -6,6 +6,36 @@ History
2014
====
+0.6.1 August 15 -- the "knock knock knocking on beta's door" release:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+- Add checks to ensure that the backend is alive or notify the
+ user. Related to #5873.
+- Stop the backend if the frontend process does not exist any more and
+ backend is not a daemon. Related to #5873.
+- Add autostart on Linux. Closes #4989.
+- Pressing ESC on 'install helper files' defaults to No. Closes #5819.
+- Replace twisted thread with QThread and get pastebin send
+ working. Closes #5949.
+- Wait until EIP is up to autologin. Closes #5939
+- Fix the handling of vpn launcher errors in the UI. Closes: #5955
+- Fix logger window blocking the bitmask quit().
+- Set the standalone value for BaseConfig according to the global
+ flags.
+- Improve Hide and Show Window behavior on Ubuntu. Fixes #5511.
+- Use smaller height on the window so it fits better on smaller
+ resolutions. Closes #5722.
+- Disable daemon mode when we run the backend so we can spawn child
+ processes on it.
+- Restrict access to the zmq certificates folder.
+- Stop the services if the selected provider is changed. Related to
+ #4704. Closes #5912, #5554.
+- Minor adjustments to the layout of UI elements. Fixes #5514, #5515,
+ #5510.
+- Moved provider selection dropdown menu to be at the top of the main
+ windowUse same user/password restrictions as in the webapp. Closes
+ #5894.
+
0.6.0 July 18 -- the "nothing to see here" release:
+++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/changes/4035_add-eip-cancel-button b/changes/4035_add-eip-cancel-button
deleted file mode 100644
index ea63f8a4..00000000
--- a/changes/4035_add-eip-cancel-button
+++ /dev/null
@@ -1 +0,0 @@
-- Add a button for cancelling ongoing EIP connection. Closes: #4035
diff --git a/changes/5870_bitmask-prevent-system-logout-on-linux b/changes/5870_bitmask-prevent-system-logout-on-linux
deleted file mode 100644
index 6feba46c..00000000
--- a/changes/5870_bitmask-prevent-system-logout-on-linux
+++ /dev/null
@@ -1 +0,0 @@
-- Bitmask on linux prevents session logout. Closes #5870.
diff --git a/changes/add-backend-alive-check b/changes/add-backend-alive-check
deleted file mode 100644
index 40e12978..00000000
--- a/changes/add-backend-alive-check
+++ /dev/null
@@ -1 +0,0 @@
-- Add checks to ensure that the backend is alive or notify the user. Related to #5873.
diff --git a/changes/add-frontend-alive-check b/changes/add-frontend-alive-check
deleted file mode 100644
index 54f88798..00000000
--- a/changes/add-frontend-alive-check
+++ /dev/null
@@ -1,2 +0,0 @@
-- Stop the backend if the frontend process does not exist any more and backend
- is not a daemon. Related to #5873.
diff --git a/changes/add-linux-autostart b/changes/add-linux-autostart
deleted file mode 100644
index 44b175bc..00000000
--- a/changes/add-linux-autostart
+++ /dev/null
@@ -1 +0,0 @@
-- Add autostart on Linux. Closes #4989.
diff --git a/changes/bug-5949_pastebin-does-not-work b/changes/bug-5949_pastebin-does-not-work
deleted file mode 100644
index aa983184..00000000
--- a/changes/bug-5949_pastebin-does-not-work
+++ /dev/null
@@ -1 +0,0 @@
-- Replace twisted thread with QThread and get pastebin send working. Closes #5949.
diff --git a/changes/bug_5939_wait-for-eip-to-autologin b/changes/bug_5939_wait-for-eip-to-autologin
deleted file mode 100644
index 5dec8331..00000000
--- a/changes/bug_5939_wait-for-eip-to-autologin
+++ /dev/null
@@ -1 +0,0 @@
-- Wait until EIP is up to autologin. Closes #5939
diff --git a/changes/bug_5955_fix-vpnlauncher-error-ui b/changes/bug_5955_fix-vpnlauncher-error-ui
deleted file mode 100644
index d322288e..00000000
--- a/changes/bug_5955_fix-vpnlauncher-error-ui
+++ /dev/null
@@ -1 +0,0 @@
-- Fix the handling of vpn launcher errors in the UI. Closes: #5955
diff --git a/changes/bug_logger-hangs-quit b/changes/bug_logger-hangs-quit
deleted file mode 100644
index b76f6218..00000000
--- a/changes/bug_logger-hangs-quit
+++ /dev/null
@@ -1 +0,0 @@
-- Fix logger window blocking the bitmask quit().
diff --git a/changes/bug_set-standalone-flags-for-baseconfig b/changes/bug_set-standalone-flags-for-baseconfig
deleted file mode 100644
index bf84d3e8..00000000
--- a/changes/bug_set-standalone-flags-for-baseconfig
+++ /dev/null
@@ -1 +0,0 @@
-- Set the standalone value for BaseConfig according to the global flags.
diff --git a/changes/bug_show_hide_improved b/changes/bug_show_hide_improved
deleted file mode 100644
index 39472074..00000000
--- a/changes/bug_show_hide_improved
+++ /dev/null
@@ -1 +0,0 @@
-- Improve Hide and Show Window behavior on Ubuntu. Fixes #5511. \ No newline at end of file
diff --git a/changes/bug_use-smaller-window-to-fit-lower-resolutions b/changes/bug_use-smaller-window-to-fit-lower-resolutions
deleted file mode 100644
index d9df69ae..00000000
--- a/changes/bug_use-smaller-window-to-fit-lower-resolutions
+++ /dev/null
@@ -1 +0,0 @@
-- Use smaller height on the window so it fits better on smaller resolutions. Closes #5722.
diff --git a/changes/disable-user-pass-remembering b/changes/disable-user-pass-remembering
deleted file mode 100644
index 45411001..00000000
--- a/changes/disable-user-pass-remembering
+++ /dev/null
@@ -1 +0,0 @@
-- Temporarily disable username/password remembering to avoid keyring issues. Related to #4190.
diff --git a/changes/enable-child-process-in-backend b/changes/enable-child-process-in-backend
deleted file mode 100644
index 1b6f246e..00000000
--- a/changes/enable-child-process-in-backend
+++ /dev/null
@@ -1 +0,0 @@
-- Disable daemon mode when we run the backend so we can spawn child processes on it.
diff --git a/changes/feature_restrict-certificates-permissions b/changes/feature_restrict-certificates-permissions
deleted file mode 100644
index 6bd6c015..00000000
--- a/changes/feature_restrict-certificates-permissions
+++ /dev/null
@@ -1 +0,0 @@
-- Restrict access to the zmq certificates folder.
diff --git a/changes/minor-ui-adjustments b/changes/minor-ui-adjustments
deleted file mode 100644
index 33e27964..00000000
--- a/changes/minor-ui-adjustments
+++ /dev/null
@@ -1 +0,0 @@
-- minor adjustments to the layout of UI elements (#5514, #5515, #5510).
diff --git a/relnotes.txt b/relnotes.txt
index 925db87d..183d1f86 100644
--- a/relnotes.txt
+++ b/relnotes.txt
@@ -1,8 +1,8 @@
-ANNOUNCING Bitmask, the Internet Encryption Toolkit, release 0.6.0
+ANNOUNCING Bitmask, the Internet Encryption Toolkit, release 0.6.1
The LEAP team is pleased to announce the immediate availability of
-version 0.6.0 of Bitmask, the Internet Encryption Toolkit, codename
-"nothing to see here".
+version 0.6.1 of Bitmask, the Internet Encryption Toolkit, codename
+"knock knock knocking on beta's door".
https://downloads.leap.se/client/
@@ -43,11 +43,13 @@ NOT trust your life to it.
WHAT CAN THIS VERSION OF BITMASK DO FOR ME?
-Bitmask 0.6.0 improves how email encryption/decryption works
-internally to improve speed and CPU consumption. This release also
-merges a big refactor we've been working on for some time, which will
-give us room for a lot of improvements in the near future. You can
-refer to the CHANGELOG for the meat.
+Bitmask 0.6.1 is the new stable version of the client after the big
+refactor, with a little face lift of the UI while we were at
+it. Encrypted Email is still not stable though, so don't use it for
+high security. Encrypted Internet is the first service we are calling
+stable, although its security level is just a bit higher than plain
+OpenSSL, so use accordingly. You can refer to the CHANGELOG for the
+meat.
Encrypted Internet on Linux now helps you don't shoot yourself in the
foot by leaking traffic outside of the secure connection it
@@ -106,6 +108,6 @@ beyond any border.
The LEAP team,
-July 18, 2014
+August 15, 2014
Somewhere in the middle of the intertubes.
EOF
diff --git a/src/leap/bitmask/gui/login.py b/src/leap/bitmask/gui/login.py
index 8e0a3a15..2a79fafd 100644
--- a/src/leap/bitmask/gui/login.py
+++ b/src/leap/bitmask/gui/login.py
@@ -43,10 +43,6 @@ class LoginWidget(QtGui.QWidget):
cancel_login = QtCore.Signal()
logout = QtCore.Signal()
- # Emitted when the user selects "Other..." in the provider
- # combobox or click "Create Account"
- show_wizard = QtCore.Signal()
-
MAX_STATUS_WIDTH = 40
# Keyring
@@ -64,7 +60,6 @@ class LoginWidget(QtGui.QWidget):
QtGui.QWidget.__init__(self, parent)
self._settings = settings
- self._selected_provider_index = -1
self.ui = Ui_LoginWidget()
self.ui.setupUi(self)
@@ -80,9 +75,6 @@ class LoginWidget(QtGui.QWidget):
self.ui.lnUser.returnPressed.connect(self._focus_password)
- self.ui.cmbProviders.currentIndexChanged.connect(
- self._current_provider_changed)
-
self.ui.btnLogout.clicked.connect(
self.logout)
@@ -111,35 +103,6 @@ class LoginWidget(QtGui.QWidget):
enable = True if state == QtCore.Qt.Checked else False
self._settings.set_remember(enable)
- def set_providers(self, provider_list):
- """
- Set the provider list to provider_list plus an "Other..." item
- that triggers the wizard
-
- :param provider_list: list of providers
- :type provider_list: list of str
- """
- self.ui.cmbProviders.blockSignals(True)
- self.ui.cmbProviders.clear()
- self.ui.cmbProviders.addItems(provider_list + [self.tr("Other...")])
- self.ui.cmbProviders.blockSignals(False)
-
- def select_provider_by_name(self, name):
- """
- Given a provider name/domain, it selects it in the combobox
-
- :param name: name or domain for the provider
- :type name: str
- """
- provider_index = self.ui.cmbProviders.findText(name)
- self.ui.cmbProviders.setCurrentIndex(provider_index)
-
- def get_selected_provider(self):
- """
- Returns the selected provider in the combobox
- """
- return self.ui.cmbProviders.currentText()
-
def set_remember(self, value):
"""
Checks the remember user and password checkbox
@@ -217,7 +180,6 @@ class LoginWidget(QtGui.QWidget):
self.ui.lnUser.setEnabled(enabled)
self.ui.lnPassword.setEnabled(enabled)
self.ui.chkRemember.setEnabled(enabled and has_keyring())
- self.ui.cmbProviders.setEnabled(enabled)
self._set_cancel(not enabled)
@@ -258,41 +220,20 @@ class LoginWidget(QtGui.QWidget):
"""
self.ui.lnPassword.setFocus()
- @QtCore.Slot(int)
- def _current_provider_changed(self, idx):
- """
- TRIGGERS:
- self.ui.cmbProviders.currentIndexChanged
-
- :param idx: the index of the new selected item
- :type idx: int
- """
- if idx == (self.ui.cmbProviders.count() - 1):
- self.show_wizard.emit()
- # Leave the previously selected provider in the combobox
- prev_provider = 0
- if self._selected_provider_index != -1:
- prev_provider = self._selected_provider_index
- self.ui.cmbProviders.blockSignals(True)
- self.ui.cmbProviders.setCurrentIndex(prev_provider)
- self.ui.cmbProviders.blockSignals(False)
- else:
- self._selected_provider_index = idx
-
- def start_login(self):
+ def start_login(self, provider):
"""
Setups the login widgets for actually performing the login and
performs some basic checks.
+ :param provider: the domain of the current provider
+ :type provider: unicode str
:returns: True if everything's good to go, False otherwise
:rtype: bool
"""
username = self.get_user()
password = self.get_password()
- provider = self.get_selected_provider()
- self._enabled_services = self._settings.get_enabled_services(
- self.get_selected_provider())
+ self._enabled_services = self._settings.get_enabled_services(provider)
if len(provider) == 0:
self.set_status(
@@ -331,14 +272,16 @@ class LoginWidget(QtGui.QWidget):
% (e,))
return True
- def logged_in(self):
+ def logged_in(self, provider):
"""
Sets the widgets to the logged in state
+
+ :param provider: the domain of the current provider
+ :type provider: unicode str
"""
self.ui.login_widget.hide()
self.ui.logged_widget.show()
- self.ui.lblUser.setText(make_address(
- self.get_user(), self.get_selected_provider()))
+ self.ui.lblUser.setText(make_address(self.get_user(), provider))
if flags.OFFLINE is False:
self.logged_in_signal.emit()
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index 0518350e..8ce7f2fc 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -45,6 +45,7 @@ from leap.bitmask.gui.mail_status import MailStatusWidget
from leap.bitmask.gui.preferenceswindow import PreferencesWindow
from leap.bitmask.gui.systray import SysTray
from leap.bitmask.gui.wizard import Wizard
+from leap.bitmask.gui.providers import Providers
from leap.bitmask.platform_init import IS_WIN, IS_MAC, IS_LINUX
from leap.bitmask.platform_init.initializers import init_platform
@@ -148,14 +149,18 @@ class MainWindow(QtGui.QMainWindow):
self._mail_status = MailStatusWidget(self)
self.ui.mailLayout.addWidget(self._mail_status)
+ # Provider List
+ self._providers = Providers(self.ui.cmbProviders)
+
# Qt Signal Connections #####################################
# TODO separate logic from ui signals.
self._login_widget.login.connect(self._login)
self._login_widget.cancel_login.connect(self._cancel_login)
- self._login_widget.show_wizard.connect(self._launch_wizard)
self._login_widget.logout.connect(self._logout)
+ self._providers.connect_provider_changed(self._on_provider_changed)
+
# EIP Control redux #########################################
self._eip_conductor = eip_conductor.EIPConductor(
self._settings, self._backend, self._leap_signaler)
@@ -174,6 +179,8 @@ class MainWindow(QtGui.QMainWindow):
self._eip_conductor.connect_signals()
self._eip_conductor.qtsigs.connected_signal.connect(
self._on_eip_connection_connected)
+ self._eip_conductor.qtsigs.disconnected_signal.connect(
+ self._on_eip_connection_disconnected)
self._eip_conductor.qtsigs.connected_signal.connect(
self._maybe_run_soledad_setup_checks)
@@ -187,7 +194,6 @@ class MainWindow(QtGui.QMainWindow):
self._already_started_eip = False
self._trying_to_start_eip = False
- self._already_started_eip = False
self._soledad_started = False
# This is created once we have a valid provider config
@@ -214,8 +220,9 @@ class MainWindow(QtGui.QMainWindow):
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)
+ self._on_provider_changed)
self.ui.action_advanced_key_management.triggered.connect(
self._show_AKM)
@@ -502,7 +509,6 @@ class MainWindow(QtGui.QMainWindow):
def _launch_wizard(self):
"""
TRIGGERS:
- self._login_widget.show_wizard
self.ui.action_wizard.triggered
Also called in first run.
@@ -576,7 +582,7 @@ class MainWindow(QtGui.QMainWindow):
Display the Advanced Key Management dialog.
"""
- domain = self._login_widget.get_selected_provider()
+ domain = self._providers.get_selected_provider()
logged_user = "{0}@{1}".format(self._logged_user, domain)
details = self._provider_details
@@ -599,7 +605,7 @@ class MainWindow(QtGui.QMainWindow):
Display the preferences window.
"""
user = self._logged_user
- domain = self._login_widget.get_selected_provider()
+ domain = self._providers.get_selected_provider()
mx_provided = False
if self._provider_details is not None:
mx_provided = MX_SERVICE in self._provider_details['services']
@@ -716,7 +722,7 @@ class MainWindow(QtGui.QMainWindow):
Display the EIP preferences window.
"""
- domain = self._login_widget.get_selected_provider()
+ domain = self._providers.get_selected_provider()
pref = EIPPreferencesWindow(self, domain,
self._backend, self._leap_signaler)
pref.show()
@@ -793,7 +799,7 @@ class MainWindow(QtGui.QMainWindow):
# XXX: May be this can be divided into two methods?
providers = self._settings.get_configured_providers()
- self._login_widget.set_providers(providers)
+ self._providers.set_providers(providers)
self._show_systray()
if not self._start_hidden:
@@ -809,12 +815,12 @@ class MainWindow(QtGui.QMainWindow):
# select the configured provider in the combo box
domain = self._wizard.get_domain()
- self._login_widget.select_provider_by_name(domain)
+ self._providers.select_provider_by_name(domain)
self._login_widget.set_remember(self._wizard.get_remember())
self._enabled_services = list(self._wizard.get_services())
self._settings.set_enabled_services(
- self._login_widget.get_selected_provider(),
+ self._providers.get_selected_provider(),
self._enabled_services)
if possible_username is not None:
self._login_widget.set_user(possible_username)
@@ -831,7 +837,7 @@ class MainWindow(QtGui.QMainWindow):
domain = self._settings.get_provider()
if domain is not None:
- self._login_widget.select_provider_by_name(domain)
+ self._providers.select_provider_by_name(domain)
if not self._settings.get_remember():
# nothing to do here
@@ -894,11 +900,7 @@ class MainWindow(QtGui.QMainWindow):
"""
Set the login label to reflect offline status.
"""
- provider = ""
- if not self._logged_in_offline:
- provider = self.ui.lblLoginProvider.text()
-
- self.ui.lblLoginProvider.setText(provider + self.tr(" (offline mode)"))
+ # TODO: figure out what widget to use for this. Maybe the window title?
#
# systray
@@ -1062,17 +1064,19 @@ class MainWindow(QtGui.QMainWindow):
help_url = "<p><a href='https://{0}'>{0}</a></p>".format(
self.tr("bitmask.net/help"))
- lang = QtCore.QLocale.system().name().replace('_','-')
+ lang = QtCore.QLocale.system().name().replace('_', '-')
thunderbird_extension_url = \
"https://addons.mozilla.org/{0}/" \
"thunderbird/addon/bitmask/".format(lang)
email_quick_reference = self.tr("Email quick reference")
- thunderbird_text = self.tr("For Thunderbird, you can use the "
+ thunderbird_text = self.tr(
+ "For Thunderbird, you can use the "
"Bitmask extension. Search for \"Bitmask\" in the add-on "
"manager or download it from <a href='{0}'>"
"addons.mozilla.org</a>.".format(thunderbird_extension_url))
- manual_text = self.tr("Alternately, you can manually configure "
+ manual_text = self.tr(
+ "Alternately, you can manually configure "
"your mail client to use Bitmask Email with these options:")
manual_imap = self.tr("IMAP: localhost, port {0}".format(IMAP_PORT))
manual_smtp = self.tr("SMTP: localhost, port {0}".format(smtp_port))
@@ -1089,8 +1093,8 @@ class MainWindow(QtGui.QMainWindow):
"<li>&nbsp;{5}</li>"
"<li>&nbsp;{6}</li>"
"</ul></p>").format(email_quick_reference, thunderbird_text,
- manual_text, manual_imap, manual_smtp,
- manual_username, manual_password)
+ manual_text, manual_imap, manual_smtp,
+ manual_username, manual_password)
QtGui.QMessageBox.about(self, self.tr("Bitmask Help"), msg)
def _needs_update(self):
@@ -1156,7 +1160,7 @@ class MainWindow(QtGui.QMainWindow):
emit the corresponding signals inmediately
"""
self._disconnect_scheduled_login()
- domain = self._login_widget.get_selected_provider()
+ domain = self._providers.get_selected_provider()
self._backend.provider_setup(provider=domain)
@QtCore.Slot(dict)
@@ -1173,7 +1177,7 @@ class MainWindow(QtGui.QMainWindow):
:type data: dict
"""
if data[PASSED_KEY]:
- selected_provider = self._login_widget.get_selected_provider()
+ selected_provider = self._providers.get_selected_provider()
self._backend.provider_bootstrap(provider=selected_provider)
else:
logger.error(data[ERROR_KEY])
@@ -1201,7 +1205,8 @@ class MainWindow(QtGui.QMainWindow):
eip_sigs = self._eip_conductor.qtsigs
eip_sigs.connected_signal.connect(self._download_provider_config)
eip_sigs.disconnected_signal.connect(self._download_provider_config)
- eip_sigs.connection_aborted_signal.connect(self._download_provider_config)
+ eip_sigs.connection_aborted_signal.connect(
+ self._download_provider_config)
eip_sigs.connection_died_signal.connect(self._download_provider_config)
def _disconnect_scheduled_login(self):
@@ -1211,17 +1216,63 @@ class MainWindow(QtGui.QMainWindow):
try:
eip_sigs = self._eip_conductor.qtsigs
eip_sigs.connected_signal.disconnect(
- self._download_provider_config)
+ self._download_provider_config)
eip_sigs.disconnected_signal.disconnect(
- self._download_provider_config)
+ self._download_provider_config)
eip_sigs.connection_aborted_signal.disconnect(
- self._download_provider_config)
+ self._download_provider_config)
eip_sigs.connection_died_signal.disconnect(
- self._download_provider_config)
+ self._download_provider_config)
except Exception:
# signal not connected
pass
+ @QtCore.Slot(object)
+ def _on_provider_changed(self, wizard=True):
+ """
+ TRIGGERS:
+ self._providers._provider_changed
+ self.ui.action_create_new_account.triggered
+
+ Ask the user if really wants to change provider since a services stop
+ is required for that action.
+
+ :param wizard: whether the 'other...' option was picked or not.
+ :type wizard: bool
+ """
+ # TODO: we should handle the case that EIP is autostarting since we
+ # won't get a warning until EIP has fully started.
+ # TODO: we need to add a check for the mail status (smtp/imap/soledad)
+ something_runing = (self._logged_user is not None or
+ self._already_started_eip)
+ if not something_runing:
+ if wizard:
+ self._launch_wizard()
+ return
+
+ title = self.tr("Stop services")
+ text = "<b>" + self.tr("Do you want to stop all services?") + "</b>"
+ informative_text = self.tr("In order to change the provider, the "
+ "running services needs to be stopped.")
+
+ msg = QtGui.QMessageBox(self)
+ msg.setWindowTitle(title)
+ msg.setText(text)
+ msg.setInformativeText(informative_text)
+ msg.setStandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
+ msg.setDefaultButton(QtGui.QMessageBox.No)
+ msg.setIcon(QtGui.QMessageBox.Warning)
+ res = msg.exec_()
+
+ if res == QtGui.QMessageBox.Yes:
+ self._stop_services()
+ self._eip_conductor.qtsigs.do_disconnect_signal.emit()
+ if wizard:
+ self._launch_wizard()
+ else:
+ if not wizard:
+ # if wizard, the widget restores itself
+ self._providers.restore_previous_provider()
@QtCore.Slot()
def _login(self):
@@ -1235,19 +1286,18 @@ class MainWindow(QtGui.QMainWindow):
bootstrapping the EIP service
"""
# 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.
+ provider = self._providers.get_selected_provider()
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._login_widget.logged_in(provider)
self._logged_in_offline = True
self._set_label_offline()
self.offline_mode_bypass_login.emit()
else:
self.ui.action_create_new_account.setEnabled(False)
- if self._login_widget.start_login():
+ if self._login_widget.start_login(provider):
if self._trying_to_start_eip:
self._schedule_login()
else:
@@ -1327,7 +1377,7 @@ class MainWindow(QtGui.QMainWindow):
self._show_hide_unsupported_services()
- domain = self._login_widget.get_selected_provider()
+ domain = self._providers.get_selected_provider()
self._backend.user_login(provider=domain,
username=username, password=password)
else:
@@ -1347,7 +1397,7 @@ class MainWindow(QtGui.QMainWindow):
self._logged_user = self._login_widget.get_user()
user = self._logged_user
- domain = self._login_widget.get_selected_provider()
+ domain = self._providers.get_selected_provider()
full_user_id = make_address(user, domain)
self._mail_conductor.userid = full_user_id
self._start_eip_bootstrap()
@@ -1370,9 +1420,8 @@ class MainWindow(QtGui.QMainWindow):
triggers the eip bootstrapping.
"""
- self._login_widget.logged_in()
- domain = self._login_widget.get_selected_provider()
- self.ui.lblLoginProvider.setText(domain)
+ domain = self._providers.get_selected_provider()
+ self._login_widget.logged_in(domain)
self._enabled_services = self._settings.get_enabled_services(domain)
@@ -1394,7 +1443,7 @@ class MainWindow(QtGui.QMainWindow):
and enabled.
This is triggered right after the provider has been set up.
"""
- domain = self._login_widget.get_selected_provider()
+ domain = self._providers.get_selected_provider()
lang = QtCore.QLocale.system().name()
self._backend.provider_get_details(domain=domain, lang=lang)
@@ -1415,7 +1464,7 @@ class MainWindow(QtGui.QMainWindow):
:returns: True if provides and is enabled, False otherwise
:rtype: bool
"""
- domain = self._login_widget.get_selected_provider()
+ domain = self._providers.get_selected_provider()
enabled_services = self._settings.get_enabled_services(domain)
mx_enabled = MX_SERVICE in enabled_services
@@ -1432,7 +1481,7 @@ class MainWindow(QtGui.QMainWindow):
:returns: True if provides and is enabled, False otherwise
:rtype: bool
"""
- domain = self._login_widget.get_selected_provider()
+ domain = self._providers.get_selected_provider()
enabled_services = self._settings.get_enabled_services(domain)
eip_enabled = EIP_SERVICE in enabled_services
@@ -1453,7 +1502,7 @@ class MainWindow(QtGui.QMainWindow):
username = self._login_widget.get_user()
password = unicode(self._login_widget.get_password())
- provider_domain = self._login_widget.get_selected_provider()
+ provider_domain = self._providers.get_selected_provider()
if flags.OFFLINE:
full_user_id = make_address(username, provider_domain)
@@ -1469,7 +1518,7 @@ class MainWindow(QtGui.QMainWindow):
password=password, uuid=uuid)
else:
if self._logged_user is not None:
- domain = self._login_widget.get_selected_provider()
+ domain = self._providers.get_selected_provider()
self._backend.soledad_bootstrap(username=username,
domain=domain,
password=password)
@@ -1553,7 +1602,7 @@ class MainWindow(QtGui.QMainWindow):
"""
self._already_started_eip = True
- domain = self._login_widget.get_selected_provider()
+ domain = self._providers.get_selected_provider()
self._settings.set_defaultprovider(domain)
self._backend.eip_get_gateway_country_code(domain=domain)
@@ -1562,6 +1611,16 @@ class MainWindow(QtGui.QMainWindow):
self._backend.eip_check_dns(domain=domain)
@QtCore.Slot()
+ def _on_eip_connection_disconnected(self):
+ """
+ TRIGGERS:
+ self._eip_conductor.qtsigs.disconnected_signal
+
+ Set the eip status to not started.
+ """
+ self._already_started_eip = False
+
+ @QtCore.Slot()
def _set_eip_provider(self, country_code=None):
"""
TRIGGERS:
@@ -1570,7 +1629,7 @@ class MainWindow(QtGui.QMainWindow):
Set the current provider and country code in the eip status widget.
"""
- domain = self._login_widget.get_selected_provider()
+ domain = self._providers.get_selected_provider()
self._eip_status.set_provider(domain, country_code)
@QtCore.Slot()
@@ -1578,7 +1637,7 @@ class MainWindow(QtGui.QMainWindow):
"""
Trigger this if we don't have a working DNS resolver.
"""
- domain = self._login_widget.get_selected_provider()
+ domain = self._providers.get_selected_provider()
msg = self.tr(
"The server at {0} can't be found, because the DNS lookup "
"failed. DNS is the network service that translates a "
@@ -1642,7 +1701,7 @@ class MainWindow(QtGui.QMainWindow):
self._eip_status.eip_button.hide()
self._eip_status.eip_button.setEnabled(False)
- domain = self._login_widget.get_selected_provider()
+ domain = self._providers.get_selected_provider()
self._backend.eip_setup(provider=domain)
self._already_started_eip = True
@@ -1733,7 +1792,6 @@ class MainWindow(QtGui.QMainWindow):
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."))
@@ -1747,7 +1805,6 @@ class MainWindow(QtGui.QMainWindow):
logging out
"""
self._login_widget.done_logout()
- self.ui.lblLoginProvider.setText(self.tr("Login"))
self._logged_user = None
self._login_widget.logged_out()
diff --git a/src/leap/bitmask/gui/providers.py b/src/leap/bitmask/gui/providers.py
new file mode 100644
index 00000000..b3eb8620
--- /dev/null
+++ b/src/leap/bitmask/gui/providers.py
@@ -0,0 +1,114 @@
+# -*- coding: utf-8 -*-
+#
+# 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
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+"""
+An instance of class Providers, held by mainwindow, is responsible for
+managing the current provider and the combobox provider list.
+"""
+
+from collections import deque
+from PySide import QtCore
+
+
+class Providers(QtCore.QObject):
+
+ # Emitted when the user changes the provider combobox index. The object
+ # parameter is actually a boolean value that is True if "Other..." was
+ # selected, False otherwse
+ _provider_changed = QtCore.Signal(object)
+
+ def __init__(self, providers_combo):
+ """
+ :param providers_combo: combo widget that lists providers
+ :type providers_combo: QWidget
+ """
+ QtCore.QObject.__init__(self)
+ self._providers_indexes = deque(maxlen=2) # previous and current
+ self._providers_indexes.append(-1)
+ self._combo = providers_combo
+ self._combo.currentIndexChanged.connect(
+ self._current_provider_changed)
+
+ def set_providers(self, provider_list):
+ """
+ Set the provider list to provider_list plus an "Other..." item
+ that triggers the wizard
+
+ :param provider_list: list of providers
+ :type provider_list: list of str
+ """
+ self._combo.blockSignals(True)
+ self._combo.clear()
+ self._combo.addItems(provider_list + [self.tr("Other...")])
+ self._combo.blockSignals(False)
+
+ def select_provider_by_name(self, name):
+ """
+ Given a provider name/domain, it selects it in the combobox
+
+ :param name: name or domain for the provider
+ :type name: unicode str
+ """
+ provider_index = self._combo.findText(name)
+ self._providers_indexes.append(provider_index)
+
+ # block the signals during a combobox change since we don't want to
+ # trigger the default signal that makes the UI ask the user for
+ # confirmation
+ self._combo.blockSignals(True)
+ self._combo.setCurrentIndex(provider_index)
+ self._combo.blockSignals(False)
+
+ def get_selected_provider(self):
+ """
+ Returns the selected provider in the combobox
+
+ :rtype: unicode str
+ """
+ return self._combo.currentText()
+
+ def connect_provider_changed(self, callback):
+ """
+ Connects callback to provider_changed signal
+ """
+ self._provider_changed.connect(callback)
+
+ def restore_previous_provider(self):
+ """
+ Set as selected provider the one that was selected previously.
+ """
+ prev_provider = self._providers_indexes.popleft()
+ self._providers_indexes.append(prev_provider)
+ self._combo.blockSignals(True)
+ self._combo.setCurrentIndex(prev_provider)
+ self._combo.blockSignals(False)
+
+ @QtCore.Slot(int)
+ def _current_provider_changed(self, idx):
+ """
+ TRIGGERS:
+ self._combo.currentIndexChanged
+
+ :param idx: the index of the new selected item
+ :type idx: int
+ """
+ self._providers_indexes.append(idx)
+ is_wizard = idx == (self._combo.count() - 1)
+ self._provider_changed.emit(is_wizard)
+ if is_wizard:
+ self.restore_previous_provider()
diff --git a/src/leap/bitmask/gui/ui/login.ui b/src/leap/bitmask/gui/ui/login.ui
index 26decc6d..bfd5f9c0 100644
--- a/src/leap/bitmask/gui/ui/login.ui
+++ b/src/leap/bitmask/gui/ui/login.ui
@@ -69,17 +69,7 @@
<property name="rightMargin">
<number>24</number>
</property>
- <item row="0" column="0">
- <widget class="QLabel" name="label_4">
- <property name="text">
- <string>&lt;b&gt;Provider:&lt;/b&gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
+ <item row="3" column="1">
<widget class="QPushButton" name="btnLogin">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
@@ -92,7 +82,7 @@
</property>
</widget>
</item>
- <item row="3" column="1">
+ <item row="2" column="1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="chkRemember">
@@ -116,10 +106,7 @@
</item>
</layout>
</item>
- <item row="0" column="1">
- <widget class="QComboBox" name="cmbProviders"/>
- </item>
- <item row="1" column="0">
+ <item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>&lt;b&gt;Username:&lt;/b&gt;</string>
@@ -129,10 +116,10 @@
</property>
</widget>
</item>
- <item row="1" column="1">
+ <item row="0" column="1">
<widget class="QLineEdit" name="lnUser"/>
</item>
- <item row="2" column="0">
+ <item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>&lt;b&gt;Password:&lt;/b&gt;</string>
@@ -142,7 +129,7 @@
</property>
</widget>
</item>
- <item row="2" column="1">
+ <item row="1" column="1">
<widget class="QLineEdit" name="lnPassword">
<property name="inputMask">
<string/>
diff --git a/src/leap/bitmask/gui/ui/mainwindow.ui b/src/leap/bitmask/gui/ui/mainwindow.ui
index 5dc48f29..92c13d15 100644
--- a/src/leap/bitmask/gui/ui/mainwindow.ui
+++ b/src/leap/bitmask/gui/ui/mainwindow.ui
@@ -75,7 +75,7 @@
<x>0</x>
<y>0</y>
<width>524</width>
- <height>589</height>
+ <height>540</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@@ -86,7 +86,7 @@
<number>0</number>
</property>
<item>
- <widget class="QFrame" name="frame">
+ <widget class="QFrame" name="providerFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -97,29 +97,16 @@
<bool>false</bool>
</property>
<property name="styleSheet">
- <string notr="true">background-color: rgba(0,0,0,20); border-bottom: 1px solid rgba(0,0,0,30);</string>
+ <string notr="true">QFrame#providerFrame {background-color: rgba(0,0,0,20); border-bottom: 1px solid rgba(0,0,0,30);}</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
- <property name="leftMargin">
- <number>24</number>
- </property>
- <property name="rightMargin">
- <number>24</number>
- </property>
<item>
- <widget class="QLabel" name="lblLoginProvider">
+ <widget class="QComboBox" name="cmbProviders">
<property name="font">
<font>
- <weight>75</weight>
- <bold>true</bold>
+ <pointsize>12</pointsize>
</font>
</property>
- <property name="styleSheet">
- <string notr="true">background-color: rgba(255, 255, 255, 0); border: none;</string>
- </property>
- <property name="text">
- <string>Please Log In</string>
- </property>
</widget>
</item>
</layout>
@@ -186,7 +173,7 @@
<item>
<layout class="QVBoxLayout" name="mailLayout">
<property name="spacing">
- <number>-1</number>
+ <number>6</number>
</property>
<property name="margin">
<number>12</number>
@@ -224,18 +211,18 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="styleSheet">
- <string notr="true">background-color: rgba(0,0,0,20); border-top: 1px solid rgba(0,0,0,30);</string>
- </property>
<property name="minimumSize">
<size>
<width>0</width>
<height>16</height>
</size>
</property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">background-color: rgba(0,0,0,20); border-top: 1px solid rgba(0,0,0,30);</string>
+ </property>
</widget>
</item>
</layout>
@@ -319,7 +306,7 @@
<x>0</x>
<y>0</y>
<width>524</width>
- <height>21</height>
+ <height>25</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
diff --git a/src/leap/bitmask/platform_init/initializers.py b/src/leap/bitmask/platform_init/initializers.py
index e4d6f9b3..f56b9330 100644
--- a/src/leap/bitmask/platform_init/initializers.py
+++ b/src/leap/bitmask/platform_init/initializers.py
@@ -106,6 +106,7 @@ def get_missing_helpers_dialog():
msg.setStandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
msg.addButton("No, don't ask again", QtGui.QMessageBox.RejectRole)
msg.setDefaultButton(QtGui.QMessageBox.Yes)
+ msg.setEscapeButton(QtGui.QMessageBox.No)
return msg
diff --git a/src/leap/bitmask/util/credentials.py b/src/leap/bitmask/util/credentials.py
index 07ded17b..757ce10c 100644
--- a/src/leap/bitmask/util/credentials.py
+++ b/src/leap/bitmask/util/credentials.py
@@ -21,7 +21,7 @@ Credentials utilities
from PySide import QtCore, QtGui
WEAK_PASSWORDS = ("123456", "qweasd", "qwerty", "password")
-USERNAME_REGEX = r"^[A-Za-z][A-Za-z\d_\-\.]+[A-Za-z\d]$"
+USERNAME_REGEX = r"^[a-z][a-z\d_\-\.]+[a-z\d]$"
USERNAME_VALIDATOR = QtGui.QRegExpValidator(QtCore.QRegExp(USERNAME_REGEX))
@@ -69,7 +69,7 @@ def password_checks(username, password, password2):
if message is None and not password:
message = _tr("You can't use an empty password")
- if message is None and len(password) < 6:
+ if message is None and len(password) < 8:
message = _tr("Password too short")
if message is None and password in WEAK_PASSWORDS: