summaryrefslogtreecommitdiff
path: root/src/leap
diff options
context:
space:
mode:
Diffstat (limited to 'src/leap')
-rw-r--r--src/leap/bitmask/gui/statuspanel.py245
-rw-r--r--src/leap/bitmask/gui/ui/statuspanel.ui220
-rw-r--r--src/leap/bitmask/services/eip/tests/test_providerbootstrapper.py19
-rw-r--r--src/leap/bitmask/services/eip/tests/test_vpngatewayselector.py15
-rw-r--r--src/leap/bitmask/services/soledad/soledadbootstrapper.py2
-rw-r--r--src/leap/bitmask/util/tests/test_streamtologger.py4
6 files changed, 445 insertions, 60 deletions
diff --git a/src/leap/bitmask/gui/statuspanel.py b/src/leap/bitmask/gui/statuspanel.py
index eb731927..9352eb04 100644
--- a/src/leap/bitmask/gui/statuspanel.py
+++ b/src/leap/bitmask/gui/statuspanel.py
@@ -28,7 +28,9 @@ from PySide import QtCore, QtGui
from leap.bitmask.services.eip.vpnprocess import VPNManager
from leap.bitmask.platform_init import IS_WIN, IS_LINUX
from leap.bitmask.util import first
-from leap.common.check import leap_assert_type
+from leap.common.check import leap_assert, leap_assert_type
+from leap.common.events import register
+from leap.common.events import events_pb2 as proto
from ui_statuspanel import Ui_StatusPanel
@@ -116,6 +118,14 @@ class StatusPanelWidget(QtGui.QWidget):
RATE_STR = "%14.2f KB/s"
TOTAL_STR = "%14.2f Kb"
+ MAIL_OFF_ICON = ":/images/mail-unlocked.png"
+ MAIL_ON_ICON = ":/images/mail-locked.png"
+
+ _soledad_event = QtCore.Signal(object)
+ _smtp_event = QtCore.Signal(object)
+ _imap_event = QtCore.Signal(object)
+ _keymanager_event = QtCore.Signal(object)
+
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
@@ -143,6 +153,73 @@ class StatusPanelWidget(QtGui.QWidget):
self._set_traffic_rates()
self._make_status_clickable()
+ register(signal=proto.KEYMANAGER_LOOKING_FOR_KEY,
+ callback=self._mail_handle_keymanager_events,
+ reqcbk=lambda req, resp: None)
+
+ register(signal=proto.KEYMANAGER_KEY_FOUND,
+ callback=self._mail_handle_keymanager_events,
+ reqcbk=lambda req, resp: None)
+
+ # register(signal=proto.KEYMANAGER_KEY_NOT_FOUND,
+ # callback=self._mail_handle_keymanager_events,
+ # reqcbk=lambda req, resp: None)
+
+ register(signal=proto.KEYMANAGER_STARTED_KEY_GENERATION,
+ callback=self._mail_handle_keymanager_events,
+ reqcbk=lambda req, resp: None)
+
+ register(signal=proto.KEYMANAGER_FINISHED_KEY_GENERATION,
+ callback=self._mail_handle_keymanager_events,
+ reqcbk=lambda req, resp: None)
+
+ register(signal=proto.KEYMANAGER_DONE_UPLOADING_KEYS,
+ callback=self._mail_handle_keymanager_events,
+ reqcbk=lambda req, resp: None)
+
+ register(signal=proto.SOLEDAD_DONE_DOWNLOADING_KEYS,
+ callback=self._mail_handle_soledad_events,
+ reqcbk=lambda req, resp: None)
+
+ register(signal=proto.SOLEDAD_DONE_UPLOADING_KEYS,
+ callback=self._mail_handle_soledad_events,
+ reqcbk=lambda req, resp: None)
+
+ register(signal=proto.SMTP_SERVICE_STARTED,
+ callback=self._mail_handle_smtp_events,
+ reqcbk=lambda req, resp: None)
+
+ register(signal=proto.SMTP_SERVICE_FAILED_TO_START,
+ callback=self._mail_handle_smtp_events,
+ reqcbk=lambda req, resp: None)
+
+ register(signal=proto.IMAP_SERVICE_STARTED,
+ callback=self._mail_handle_imap_events,
+ reqcbk=lambda req, resp: None)
+
+ register(signal=proto.IMAP_SERVICE_FAILED_TO_START,
+ callback=self._mail_handle_imap_events,
+ reqcbk=lambda req, resp: None)
+
+ register(signal=proto.IMAP_UNREAD_MAIL,
+ callback=self._mail_handle_imap_events,
+ reqcbk=lambda req, resp: None)
+
+ self._set_long_mail_status("")
+ self.ui.lblUnread.setVisible(False)
+
+ self._smtp_started = False
+ self._imap_started = False
+
+ self._soledad_event.connect(
+ self._mail_handle_soledad_events_slot)
+ self._imap_event.connect(
+ self._mail_handle_imap_events_slot)
+ self._smtp_event.connect(
+ self._mail_handle_smtp_events_slot)
+ self._keymanager_event.connect(
+ self._mail_handle_keymanager_events_slot)
+
def _make_status_clickable(self):
"""
Makes upload and download figures clickable.
@@ -460,3 +537,169 @@ class StatusPanelWidget(QtGui.QWidget):
def set_provider(self, provider):
self.ui.lblProvider.setText(provider)
+
+ def _mail_handle_soledad_events(self, req):
+ """
+ Callback for ...
+
+ :param req: Request type
+ :type req: leap.common.events.events_pb2.SignalRequest
+ """
+ self._soledad_event.emit(req)
+
+ def _mail_handle_soledad_events_slot(self, req):
+ """
+ SLOT
+ TRIGGER: _mail_handle_soledad_events
+
+ Reacts to an Soledad event
+
+ :param req: Request type
+ :type req: leap.common.events.events_pb2.SignalRequest
+ """
+ self.ui.lblMailStatus.setText(self.tr("Starting..."))
+
+ ext_status = ""
+
+ if req.event == proto.SOLEDAD_DONE_UPLOADING_KEYS:
+ ext_status = self.tr("Soledad has started...")
+ elif req.event == proto.SOLEDAD_DONE_DOWNLOADING_KEYS:
+ ext_status = self.tr("Soledad is starting, please wait...")
+ else:
+ leap_assert(False,
+ "Don't know how to handle this state: %s"
+ % (req.event))
+
+ self._set_long_mail_status(ext_status)
+
+ def _mail_handle_keymanager_events(self, req):
+ """
+ Callback for the KeyManager events
+
+ :param req: Request type
+ :type req: leap.common.events.events_pb2.SignalRequest
+ """
+ self._keymanager_event.emit(req)
+
+ def _mail_handle_keymanager_events_slot(self, req):
+ """
+ SLOT
+ TRIGGER: _mail_handle_keymanager_events
+
+ Reacts to an KeyManager event
+
+ :param req: Request type
+ :type req: leap.common.events.events_pb2.SignalRequest
+ """
+ self.ui.lblMailStatus.setText(self.tr("Starting..."))
+
+ ext_status = ""
+
+ if req.event == proto.KEYMANAGER_LOOKING_FOR_KEY:
+ ext_status = self.tr("Looking for key for this user")
+ elif req.event == proto.KEYMANAGER_KEY_FOUND:
+ ext_status = self.tr("Found key! Starting mail...")
+ # elif req.event == proto.KEYMANAGER_KEY_NOT_FOUND:
+ # ext_status = self.tr("Key not found!")
+ elif req.event == proto.KEYMANAGER_STARTED_KEY_GENERATION:
+ ext_status = self.tr("Generating new key, please wait...")
+ elif req.event == proto.KEYMANAGER_FINISHED_KEY_GENERATION:
+ ext_status = self.tr("Finished generating key!")
+ elif req.event == proto.KEYMANAGER_DONE_UPLOADING_KEYS:
+ ext_status = self.tr("Starting mail...")
+ else:
+ leap_assert(False,
+ "Don't know how to handle this state: %s"
+ % (req.event))
+
+ self._set_long_mail_status(ext_status)
+
+ def _mail_handle_smtp_events(self, req):
+ """
+ Callback for the SMTP events
+
+ :param req: Request type
+ :type req: leap.common.events.events_pb2.SignalRequest
+ """
+ self._smtp_event.emit(req)
+
+ def _mail_handle_smtp_events_slot(self, req):
+ """
+ SLOT
+ TRIGGER: _mail_handle_smtp_events
+
+ Reacts to an SMTP event
+
+ :param req: Request type
+ :type req: leap.common.events.events_pb2.SignalRequest
+ """
+ ext_status = ""
+
+ if req.event == proto.SMTP_SERVICE_STARTED:
+ ext_status = self.tr("SMTP has started...")
+ self._smtp_started = True
+ if self._smtp_started and self._imap_started:
+ self.ui.lblMailStatus.setText(self.tr("ON"))
+ self.ui.lblMailIcon.setPixmap(QtGui.QPixmap(self.MAIL_ON_ICON))
+ self.ui.lblMailIcon.setPixmap(
+ QtGui.QPixmap(":/images/mail-locked.png"))
+ ext_status = ""
+ elif req.event == proto.SMTP_SERVICE_FAILED_TO_START:
+ ext_status = self.tr("SMTP failed to start, check the logs.")
+ self.ui.lblMailStatus.setText(self.tr("Failed"))
+ else:
+ leap_assert(False,
+ "Don't know how to handle this state: %s"
+ % (req.event))
+
+ self._set_long_mail_status(ext_status)
+
+ def _mail_handle_imap_events(self, req):
+ """
+ Callback for the IMAP events
+
+ :param req: Request type
+ :type req: leap.common.events.events_pb2.SignalRequest
+ """
+ self._imap_event.emit(req)
+
+ def _mail_handle_imap_events_slot(self, req):
+ """
+ SLOT
+ TRIGGER: _mail_handle_imap_events
+
+ Reacts to an IMAP event
+
+ :param req: Request type
+ :type req: leap.common.events.events_pb2.SignalRequest
+ """
+ ext_status = None
+
+ if req.event == proto.IMAP_SERVICE_STARTED:
+ ext_status = self.tr("IMAP has started...")
+ self._imap_started = True
+ if self._smtp_started and self._imap_started:
+ self.ui.lblMailStatus.setText(self.tr("ON"))
+ self.ui.lblMailIcon.setPixmap(QtGui.QPixmap(self.MAIL_ON_ICON))
+ ext_status = ""
+ elif req.event == proto.IMAP_SERVICE_FAILED_TO_START:
+ ext_status = self.tr("IMAP failed to start, check the logs.")
+ self.ui.lblMailStatus.setText(self.tr("Failed"))
+ elif req.event == proto.IMAP_UNREAD_MAIL:
+ if self._smtp_started and self._imap_started:
+ self.ui.lblUnread.setText(
+ self.tr("%s Unread Emails") % (req.content))
+ self.ui.lblUnread.setVisible(req.content != "0")
+ self.ui.lblMailStatus.setText(self.tr("ON"))
+ self.ui.lblMailIcon.setPixmap(QtGui.QPixmap(self.MAIL_ON_ICON))
+ else:
+ leap_assert(False,
+ "Don't know how to handle this state: %s"
+ % (req.event))
+
+ if ext_status is not None:
+ self._set_long_mail_status(ext_status)
+
+ def _set_long_mail_status(self, ext_status):
+ self.ui.lblLongMailStatus.setText(ext_status)
+ self.ui.grpMailStatus.setVisible(len(ext_status) > 0)
diff --git a/src/leap/bitmask/gui/ui/statuspanel.ui b/src/leap/bitmask/gui/ui/statuspanel.ui
index 39992e1a..d77af1da 100644
--- a/src/leap/bitmask/gui/ui/statuspanel.ui
+++ b/src/leap/bitmask/gui/ui/statuspanel.ui
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>384</width>
+ <width>470</width>
<height>477</height>
</rect>
</property>
@@ -36,36 +36,40 @@
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout">
- <item row="0" column="1">
- <layout class="QHBoxLayout" name="eip_controls">
- <item>
- <widget class="QLabel" name="label">
+ <item row="5" column="1">
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="1" column="0" colspan="3">
+ <widget class="QLabel" name="lblUnread">
<property name="text">
- <string>Encrypted Internet: </string>
+ <string>0 Unread Emails</string>
</property>
</widget>
</item>
- <item>
- <widget class="QLabel" name="lblEIPStatus">
+ <item row="0" column="1">
+ <widget class="QLabel" name="lblMailStatus">
<property name="styleSheet">
<string notr="true">font: bold;</string>
</property>
<property name="text">
- <string>Off</string>
- </property>
- <property name="textFormat">
- <enum>Qt::AutoText</enum>
+ <string>Disabled</string>
</property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
</property>
- <property name="wordWrap">
- <bool>false</bool>
+ <property name="text">
+ <string>Encrypted Mail:</string>
</property>
</widget>
</item>
- <item>
- <spacer name="horizontalSpacer">
+ <item row="0" column="2">
+ <spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@@ -77,50 +81,21 @@
</property>
</spacer>
</item>
- <item>
- <widget class="QPushButton" name="btnEipStartStop">
- <property name="text">
- <string>Turn On</string>
+ <item row="2" column="0" colspan="3">
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
</property>
- </widget>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>1</height>
+ </size>
+ </property>
+ </spacer>
</item>
</layout>
</item>
- <item row="2" column="0">
- <spacer name="verticalSpacer_2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Preferred</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>0</width>
- <height>11</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="0" column="0" rowspan="2">
- <widget class="QLabel" name="lblVPNStatusIcon">
- <property name="maximumSize">
- <size>
- <width>64</width>
- <height>64</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="pixmap">
- <pixmap resource="../../../../../data/resources/icons.qrc">:/images/light/64/network-eip-down.png</pixmap>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="eip_bandwidth">
<property name="spacing">
@@ -242,6 +217,85 @@
</item>
</layout>
</item>
+ <item row="2" column="0">
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Preferred</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>11</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="0" rowspan="2">
+ <widget class="QLabel" name="lblVPNStatusIcon">
+ <property name="maximumSize">
+ <size>
+ <width>64</width>
+ <height>64</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="pixmap">
+ <pixmap resource="../../../../../data/resources/icons.qrc">:/images/light/64/network-eip-down.png</pixmap>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0" rowspan="2">
+ <widget class="QLabel" name="lblMailIcon">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>64</width>
+ <height>64</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>64</width>
+ <height>999</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="pixmap">
+ <pixmap resource="../../../../../data/resources/icons.qrc">:/images/mail-unlocked.png</pixmap>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0" colspan="2">
+ <widget class="QGroupBox" name="grpMailStatus">
+ <property name="title">
+ <string/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLabel" name="lblLongMailStatus">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
<item row="3" column="0" colspan="2">
<widget class="QGroupBox" name="globalStatusBox">
<property name="enabled">
@@ -264,6 +318,56 @@
</layout>
</widget>
</item>
+ <item row="0" column="1">
+ <layout class="QHBoxLayout" name="eip_controls">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Encrypted Internet: </string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lblEIPStatus">
+ <property name="styleSheet">
+ <string notr="true">font: bold;</string>
+ </property>
+ <property name="text">
+ <string>Off</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::AutoText</enum>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnEipStartStop">
+ <property name="text">
+ <string>Turn On</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
</layout>
</widget>
</item>
diff --git a/src/leap/bitmask/services/eip/tests/test_providerbootstrapper.py b/src/leap/bitmask/services/eip/tests/test_providerbootstrapper.py
index 6c5c6e57..b0685676 100644
--- a/src/leap/bitmask/services/eip/tests/test_providerbootstrapper.py
+++ b/src/leap/bitmask/services/eip/tests/test_providerbootstrapper.py
@@ -444,6 +444,25 @@ class ProviderBootstrapperActiveTest(unittest.TestCase):
self.assertFalse(ProviderConfig.save.called)
@mock.patch(
+ 'leap.bitmask.config.providerconfig.ProviderConfig.get_domain',
+ lambda x: where('testdomain.com'))
+ def test_download_provider_info_not_modified_and_no_cacert(self):
+ self._setup_provider_config_with("1", tempfile.mkdtemp())
+ self._setup_providerbootstrapper(True)
+ provider_path = self._produce_dummy_provider_json()
+
+ # set mtime to something really new
+ os.utime(provider_path, (-1, time.time()))
+
+ with mock.patch.object(
+ ProviderConfig, 'get_api_uri',
+ return_value="https://localhost:%s" % (self.https_port,)):
+ self.pb._download_provider_info()
+ # we check that it doesn't save the provider
+ # config, because it's new enough
+ self.assertFalse(ProviderConfig.save.called)
+
+ @mock.patch(
'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path',
lambda x: where('cacert.pem'))
def test_download_provider_info_modified(self):
diff --git a/src/leap/bitmask/services/eip/tests/test_vpngatewayselector.py b/src/leap/bitmask/services/eip/tests/test_vpngatewayselector.py
index f9a177a9..36f8a076 100644
--- a/src/leap/bitmask/services/eip/tests/test_vpngatewayselector.py
+++ b/src/leap/bitmask/services/eip/tests/test_vpngatewayselector.py
@@ -19,6 +19,7 @@ tests for vpngatewayselector
"""
import unittest
+import time
from leap.bitmask.services.eip.eipconfig import EIPConfig, VPNGatewaySelector
from leap.common.testing.basetest import BaseLeapTest
@@ -128,5 +129,19 @@ class VPNGatewaySelectorTest(BaseLeapTest):
self.assertEqual(gateways, [ips[4], ips[2], ips[3], ips[1]])
+class VPNGatewaySelectorDSTTest(VPNGatewaySelectorTest):
+ """
+ VPNGatewaySelector's tests.
+ It uses the opposite value of the current DST.
+ """
+ def setUp(self):
+ self._original_daylight = time.daylight
+ time.daylight = not time.daylight
+ VPNGatewaySelectorTest.setUp(self)
+
+ def tearDown(self):
+ VPNGatewaySelectorTest.tearDown(self)
+ time.daylight = self._original_daylight
+
if __name__ == "__main__":
unittest.main()
diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
index b973418e..2419fc0d 100644
--- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py
+++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
@@ -35,7 +35,7 @@ from leap.common.check import leap_assert, leap_assert_type
from leap.common.files import get_mtime
from leap.keymanager import KeyManager, openpgp
from leap.keymanager.errors import KeyNotFound
-from leap.soledad import Soledad
+from leap.soledad.client import Soledad
logger = logging.getLogger(__name__)
diff --git a/src/leap/bitmask/util/tests/test_streamtologger.py b/src/leap/bitmask/util/tests/test_streamtologger.py
index c4e55b3a..fc97b794 100644
--- a/src/leap/bitmask/util/tests/test_streamtologger.py
+++ b/src/leap/bitmask/util/tests/test_streamtologger.py
@@ -117,6 +117,10 @@ class StreamToLoggerTest(BaseLeapTest):
self.assertEqual(log, message)
self.assertEqual(log_level, logging.ERROR)
+ def test_twisted_log(self):
+ from twisted.python import log
+ log.startLogging(sys.stdout)
+
if __name__ == "__main__":
unittest.main(verbosity=2)