diff options
author | kali <kali@katsi> | 2014-07-27 19:00:37 -0500 |
---|---|---|
committer | kali <kali@katsi> | 2014-08-01 15:40:04 -0500 |
commit | 3b469a2c006381ba9e56c1de92be4e87ad67e51b (patch) | |
tree | c3f52f9b7f19f1e0f9b176fe935a9e6e31324e2f /src/leap/bitmask/gui | |
parent | 3b02e227cfa48074739eb4f6634a436e65923b61 (diff) |
Add cancel button for EIP connection.
Closes: #4035
This falls in the "quick" workaround category.
A proper state machine that extends the four basic connection states
is hence needed. We have to accomodate design to have a
connection-oriented state machine in the backend (I would favor a
twisted protocol for this), and a more lightweight one that conducts
the gui-level changes (ie, change the actions / buttons / labels
accordingly).
Since this "cancel" functionality has been long postponed, I chose
to do one more ugly hack here, that is, show and hide dance with a
button that just calls the bitmask-root to kill the vpn process. It
should work well enough until we get to the reorganization needed for a
clean process control for eip.
Diffstat (limited to 'src/leap/bitmask/gui')
-rw-r--r-- | src/leap/bitmask/gui/eip_status.py | 45 | ||||
-rw-r--r-- | src/leap/bitmask/gui/mainwindow.py | 64 | ||||
-rw-r--r-- | src/leap/bitmask/gui/ui/eip_status.ui | 41 |
3 files changed, 106 insertions, 44 deletions
diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py index a707050a..f283b148 100644 --- a/src/leap/bitmask/gui/eip_status.py +++ b/src/leap/bitmask/gui/eip_status.py @@ -70,8 +70,11 @@ class EIPStatusWidget(QtGui.QWidget): self.ui.eip_bandwidth.hide() self.hide_fw_down_button() + self.hide_eip_cancel_button() self.ui.btnFwDown.clicked.connect( self._on_fw_down_button_clicked) + self.ui.btnEipCancel.clicked.connect( + self._on_eip_cancel_button_clicked) # Set the EIP status icons self.CONNECTING_ICON = None @@ -88,6 +91,7 @@ class EIPStatusWidget(QtGui.QWidget): self._provider = "" self.is_restart = False self.is_cold_start = True + self.user_cancelled = False self.missing_helpers = False @@ -285,6 +289,8 @@ class EIPStatusWidget(QtGui.QWidget): Triggered when the app activates eip. Disables the start/stop button. """ + # XXX hack -- we show the cancel button instead. + self.ui.btnEipStartStop.hide() self.set_startstop_enabled(False) msg = self.tr("Encrypted Internet is starting") self.set_eip_message(msg) @@ -295,6 +301,9 @@ class EIPStatusWidget(QtGui.QWidget): Triggered when a default provider_config has not been found. Disables the start button and adds instructions to the user. """ + # XXX this name is unfortunate. "disable" is also applied to a + # pushbutton being grayed out. + 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. @@ -327,6 +336,7 @@ class EIPStatusWidget(QtGui.QWidget): """ # logger.debug('Showing EIP start button') self.eip_button.show() + self.hide_eip_cancel_button() # Restore the eip action menu menu = self._systray.contextMenu() @@ -420,6 +430,28 @@ class EIPStatusWidget(QtGui.QWidget): self.set_eip_message(msg) self.set_eip_status("") + def hide_eip_cancel_button(self): + """ + Hide eip-cancel button. + """ + self.ui.btnEipCancel.hide() + + def show_eip_cancel_button(self): + """ + Show eip-cancel button. + """ + self.ui.btnEipCancel.show() + self.user_cancelled = False + + def _on_eip_cancel_button_clicked(self): + """ + Call backend to kill the openvpn process with root privileges. + """ + self.eip_conductor.cancelled = True + self.eip_conductor._backend.bitmask_root_vpn_down() + self.user_cancelled = True + self.hide_eip_cancel_button() + @QtCore.Slot(dict) def eip_stopped(self, restart=False, failed=False): """ @@ -433,6 +465,11 @@ class EIPStatusWidget(QtGui.QWidget): self._reset_traffic_rates() self.ui.eip_bandwidth.hide() + if self.user_cancelled: + self.eip_conductor._backend.tear_fw_down() + self.eip_button.show() + failed = False + # This is assuming the firewall works correctly, but we should test fw # status positively. # Or better call it from the conductor... @@ -447,6 +484,7 @@ class EIPStatusWidget(QtGui.QWidget): msg = failed_msg else: msg = clear_traffic + self.set_eip_message(msg) self.ui.lblEIPStatus.show() self.show() @@ -523,16 +561,19 @@ class EIPStatusWidget(QtGui.QWidget): self.eipconnection.qtsigs.connected_signal.emit() self._on_eip_connected() self.is_cold_start = False + self.hide_eip_cancel_button() + self.eip_button.show() # XXX should lookup vpn_state map in EIPConnection elif vpn_state == "AUTH": self.set_eip_status(self.tr("Authenticating...")) + + # XXX should be handled by a future state machine instead. + self.show_eip_cancel_button() # we wipe up any previous error info in the EIP message # when we detect vpn authentication is happening msg = self.tr("Encrypted Internet is starting") self.set_eip_message(msg) - # on the first-run path, we hadn't showed the button yet. - self.eip_button.show() elif vpn_state == "GET_CONFIG": self.set_eip_status(self.tr("Retrieving configuration...")) elif vpn_state == "WAIT": diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 46f0928f..25bda305 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -166,6 +166,9 @@ class MainWindow(QtGui.QMainWindow): self._disable_eip_missing_helpers) self.ui.eipLayout.addWidget(self._eip_status) + + # XXX we should get rid of the circular refs + # conductor <-> status, right now keeping state on the widget ifself. self._eip_conductor.add_eip_widget(self._eip_status) self._eip_conductor.connect_signals() @@ -180,6 +183,7 @@ class MainWindow(QtGui.QMainWindow): self.eip_needs_login.connect(self._eip_status.disable_eip_start) self.eip_needs_login.connect(self._disable_eip_start_action) + # XXX all this info about state should move to eip conductor too self._already_started_eip = False self._trying_to_start_eip = False @@ -561,7 +565,7 @@ class MainWindow(QtGui.QMainWindow): TRIGGERS: self.ui.action_show_logs.triggered - Displays the window with the history of messages logged until now + Display the window with the history of messages logged until now and displays the new ones on arrival. """ if self._logger_window is None: @@ -582,7 +586,7 @@ class MainWindow(QtGui.QMainWindow): TRIGGERS: self.ui.action_advanced_key_management.triggered - Displays the Advanced Key Management dialog. + Display the Advanced Key Management dialog. """ domain = self._login_widget.get_selected_provider() logged_user = "{0}@{1}".format(self._logged_user, domain) @@ -604,7 +608,7 @@ class MainWindow(QtGui.QMainWindow): self.ui.btnPreferences.clicked (disabled for now) self.ui.action_preferences - Displays the preferences window. + Display the preferences window. """ user = self._logged_user domain = self._login_widget.get_selected_provider() @@ -722,7 +726,7 @@ class MainWindow(QtGui.QMainWindow): self.ui.btnEIPPreferences.clicked self.ui.action_eip_preferences (disabled for now) - Displays the EIP preferences window. + Display the EIP preferences window. """ domain = self._login_widget.get_selected_provider() pref = EIPPreferencesWindow(self, domain, @@ -748,7 +752,7 @@ class MainWindow(QtGui.QMainWindow): TRIGGERS: self.new_updates - Displays the new updates label and sets the updates_content + Display the new updates label and sets the updates_content :param req: Request type :type req: leap.common.events.events_pb2.SignalRequest @@ -963,7 +967,7 @@ class MainWindow(QtGui.QMainWindow): :param reason: the reason why the tray got activated. :type reason: int - Displays the context menu from the tray icon + Display the context menu from the tray icon """ self._update_hideshow_menu() @@ -977,7 +981,7 @@ class MainWindow(QtGui.QMainWindow): def _update_hideshow_menu(self): """ - Updates the Hide/Show main window menu text based on the + Update the Hide/Show main window menu text based on the visibility of the window. """ get_action = lambda visible: ( @@ -994,7 +998,7 @@ class MainWindow(QtGui.QMainWindow): TRIGGERS: self._action_visible.triggered - Toggles the window visibility + Toggle the window visibility """ visible = self.isVisible() and self.isActiveWindow() @@ -1022,7 +1026,7 @@ class MainWindow(QtGui.QMainWindow): def _center_window(self): """ - Centers the mainwindow based on the desktop geometry + Center the main window based on the desktop geometry """ geometry = self._settings.get_geometry() state = self._settings.get_windowstate() @@ -1124,7 +1128,7 @@ class MainWindow(QtGui.QMainWindow): def changeEvent(self, e): """ - Reimplements the changeEvent method to minimize to tray + Reimplementation of changeEvent method to minimize to tray """ if not IS_MAC and \ QtGui.QSystemTrayIcon.isSystemTrayAvailable() and \ @@ -1158,7 +1162,7 @@ class MainWindow(QtGui.QMainWindow): def _first_run(self): """ - Returns True if there are no configured providers. False otherwise + Return True if there are no configured providers. False otherwise :rtype: bool """ @@ -1169,7 +1173,7 @@ class MainWindow(QtGui.QMainWindow): def _download_provider_config(self): """ - Starts the bootstrapping sequence. It will download the + Start the bootstrapping sequence. It will download the provider configuration if it's not present, otherwise will emit the corresponding signals inmediately """ @@ -1199,8 +1203,9 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _login_problem_provider(self): """ - Warns the user about a problem with the provider during login. + Warn the user about a problem with the provider during login. """ + # XXX triggers? self._login_widget.set_status( self.tr("Unable to login: Problem with provider")) self._login_widget.set_enabled(True) @@ -1211,7 +1216,7 @@ class MainWindow(QtGui.QMainWindow): TRIGGERS: self._login_widget.login - Starts the login sequence. Which involves bootstrapping the + Start the login sequence. Which involves bootstrapping the selected provider if the selection is valid (not empty), then start the SRP authentication, and as the last step bootstrapping the EIP service @@ -1256,7 +1261,7 @@ class MainWindow(QtGui.QMainWindow): TRIGGERS: self._login_widget.cancel_login - Stops the login sequence. + Stop the login sequence. """ logger.debug("Cancelling log in.") self._cancel_ongoing_defers() @@ -1280,7 +1285,7 @@ class MainWindow(QtGui.QMainWindow): Signaler.prov_cancelled_setup fired by self._backend.provider_cancel_setup() - This method re-enables the login widget and display a message for + Re-enable the login widget and display a message for the cancelled operation. """ self._login_widget.set_status(self.tr("Log in cancelled by the user.")) @@ -1340,7 +1345,7 @@ class MainWindow(QtGui.QMainWindow): def _start_eip_bootstrap(self): """ - Changes the stackedWidget index to the EIP status one and + Change the stackedWidget index to the EIP status one and triggers the eip bootstrapping. """ @@ -1384,7 +1389,7 @@ class MainWindow(QtGui.QMainWindow): def _provides_mx_and_enabled(self): """ - Defines if the current provider provides mx and if we have it enabled. + Define if the current provider provides mx and if we have it enabled. :returns: True if provides and is enabled, False otherwise :rtype: bool @@ -1401,7 +1406,7 @@ class MainWindow(QtGui.QMainWindow): def _provides_eip_and_enabled(self): """ - Defines if the current provider provides eip and if we have it enabled. + Define if the current provider provides eip and if we have it enabled. :returns: True if provides and is enabled, False otherwise :rtype: bool @@ -1503,14 +1508,14 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def _disable_eip_start_action(self): """ - Disables the EIP start action in the systray menu. + Disable the EIP start action in the systray menu. """ self._action_eip_startstop.setEnabled(False) @QtCore.Slot() def _enable_eip_start_action(self): """ - Enables the EIP start action in the systray menu. + Enable the EIP start action in the systray menu. """ self._action_eip_startstop.setEnabled(True) self._eip_status.enable_eip_start() @@ -1567,7 +1572,7 @@ class MainWindow(QtGui.QMainWindow): def _try_autostart_eip(self): """ - Tries to autostart EIP + Try to autostart EIP. """ settings = self._settings default_provider = settings.get_defaultprovider() @@ -1587,6 +1592,8 @@ class MainWindow(QtGui.QMainWindow): :param autostart: we are autostarting EIP when this is True :type autostart: bool """ + # XXX should move to EIP conductor. + # during autostart we assume that the provider provides EIP if autostart: should_start = EIP_SERVICE in self._enabled_services @@ -1606,6 +1613,12 @@ class MainWindow(QtGui.QMainWindow): self._enable_eip_start_action() self._eip_status.set_eip_status( self.tr("Starting...")) + self._eip_status.show_eip_cancel_button() + + # We were disabling the button, but now that we have + # a cancel button we just hide it. It will be visible + # when the connection is completed successfully. + self._eip_status.eip_button.hide() self._eip_status.eip_button.setEnabled(False) domain = self._login_widget.get_selected_provider() @@ -1680,7 +1693,7 @@ class MainWindow(QtGui.QMainWindow): TRIGGERS: self._login_widget.logout - Starts the logout sequence + Start the logout sequence """ self._cancel_ongoing_defers() @@ -1708,7 +1721,7 @@ class MainWindow(QtGui.QMainWindow): TRIGGER: self._srp_auth.logout_ok - Switches the stackedWidget back to the login stage after + Switch the stackedWidget back to the login stage after logging out """ self._login_widget.done_logout() @@ -1729,7 +1742,7 @@ class MainWindow(QtGui.QMainWindow): self._backend.signaler.prov_https_connection self._backend.signaler.prov_download_ca_cert - If there was a problem, displays it, otherwise it does nothing. + If there was a problem, display it, otherwise it does nothing. This is used for intermediate bootstrapping stages, in case they fail. """ @@ -1783,6 +1796,7 @@ class MainWindow(QtGui.QMainWindow): imap_stopped = lambda: self._remove_service('imap') self._leap_signaler.imap_stopped.connect(imap_stopped) + # XXX change name, already used in conductor. eip_stopped = lambda: self._remove_service('eip') self._leap_signaler.eip_stopped.connect(eip_stopped) diff --git a/src/leap/bitmask/gui/ui/eip_status.ui b/src/leap/bitmask/gui/ui/eip_status.ui index 7216bb0a..e0996620 100644 --- a/src/leap/bitmask/gui/ui/eip_status.ui +++ b/src/leap/bitmask/gui/ui/eip_status.ui @@ -28,13 +28,26 @@ <property name="verticalSpacing"> <number>0</number> </property> - <item row="0" column="4"> + <item row="0" column="5"> <widget class="QPushButton" name="btnEipStartStop"> <property name="text"> <string>Turn On</string> </property> </widget> </item> + <item row="1" column="2"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>0</height> + </size> + </property> + </spacer> + </item> <item row="0" column="0"> <widget class="QLabel" name="label"> <property name="maximumSize"> @@ -86,7 +99,7 @@ </property> </widget> </item> - <item row="0" column="5"> + <item row="0" column="6"> <widget class="QLabel" name="lblVPNStatusIcon"> <property name="maximumSize"> <size> @@ -105,20 +118,7 @@ </property> </widget> </item> - <item row="1" column="2"> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>0</height> - </size> - </property> - </spacer> - </item> - <item row="2" column="2" colspan="4"> + <item row="2" column="2" colspan="5"> <widget class="QWidget" name="eip_bandwidth" native="true"> <layout class="QHBoxLayout" name="horizontalLayout"> <property name="spacing"> @@ -239,7 +239,7 @@ </layout> </widget> </item> - <item row="0" column="3"> + <item row="0" column="4"> <widget class="QPushButton" name="btnFwDown"> <property name="text"> <string>Turn Off</string> @@ -253,6 +253,13 @@ </property> </widget> </item> + <item row="0" column="3"> + <widget class="QPushButton" name="btnEipCancel"> + <property name="text"> + <string>Cancel</string> + </property> + </widget> + </item> </layout> </item> </layout> |