diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/leap/bitmask/backend.py | 33 | ||||
| -rw-r--r-- | src/leap/bitmask/gui/mainwindow.py | 26 | ||||
| -rw-r--r-- | src/leap/bitmask/services/mail/conductor.py | 104 | ||||
| -rw-r--r-- | src/leap/bitmask/services/mail/imapcontroller.py | 98 | 
4 files changed, 172 insertions, 89 deletions
| diff --git a/src/leap/bitmask/backend.py b/src/leap/bitmask/backend.py index 327131b3..fd09929a 100644 --- a/src/leap/bitmask/backend.py +++ b/src/leap/bitmask/backend.py @@ -46,6 +46,8 @@ from leap.bitmask.services.eip.eipbootstrapper import EIPBootstrapper  from leap.bitmask.services.eip import vpnlauncher, vpnprocess  from leap.bitmask.services.eip import linuxvpnlauncher, darwinvpnlauncher +from leap.bitmask.services.mail import imap +  from leap.bitmask.services.soledad.soledadbootstrapper import \      SoledadBootstrapper @@ -632,6 +634,37 @@ class Soledad(object):              soledad.close() +class Mail(object): +    """ +    Interfaces with setup and launch of Mail. +    """ + +    zope.interface.implements(ILEAPComponent) + +    def __init__(self, signaler=None): +        """ +        Constructor for the Mail component. + +        :param signaler: Object in charge of handling communication +                         back to the frontend +        :type signaler: Signaler +        """ +        self.key = "mail" +        self._signaler = signaler + +    def start_smtp_service(self): +        pass + +    def start_imap_service(self, offline=False): +        pass + +    def stop_smtp_service(self): +        pass + +    def stop_imap_service(self): +        pass + +  class Authenticate(object):      """      Interfaces with setup and bootstrapping operations for a provider diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index cceb1efe..bf76f574 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -87,7 +87,6 @@ class MainWindow(QtGui.QMainWindow):      new_updates = QtCore.Signal(object)      raise_window = QtCore.Signal([])      soledad_ready = QtCore.Signal([]) -    mail_client_logged_in = QtCore.Signal([])      logout = QtCore.Signal([])      # We use this flag to detect abnormal terminations @@ -123,9 +122,6 @@ class MainWindow(QtGui.QMainWindow):          register(signal=proto.RAISE_WINDOW,                   callback=self._on_raise_window_event,                   reqcbk=lambda req, resp: None)  # make rpc call async -        register(signal=proto.IMAP_CLIENT_LOGIN, -                 callback=self._on_mail_client_logged_in, -                 reqcbk=lambda req, resp: None)  # make rpc call async          # end register leap events ####################################          self._quit_callback = quit_callback @@ -265,7 +261,6 @@ class MainWindow(QtGui.QMainWindow):          # XXX should connect to mail_conductor.start_mail_service instead          self.soledad_ready.connect(self._start_smtp_bootstrapping)          self.soledad_ready.connect(self._start_imap_service) -        self.mail_client_logged_in.connect(self._fetch_incoming_mail)          self.logout.connect(self._stop_imap_service)          self.logout.connect(self._stop_smtp_service) @@ -1373,7 +1368,7 @@ class MainWindow(QtGui.QMainWindow):          password = unicode(self._login_widget.get_password())          provider_domain = self._login_widget.get_selected_provider() -        if flags.OFFLINE is True: +        if flags.OFFLINE:              self._provisional_provider_config.load(                  provider.get_provider_path(provider_domain)) @@ -1455,34 +1450,19 @@ class MainWindow(QtGui.QMainWindow):          # in the mail state machine so it shows that imap is active          # (but not smtp since it's not yet ready for offline use)          start_fun = self._mail_conductor.start_imap_service -        if flags.OFFLINE is True: +        if flags.OFFLINE:              provider_domain = self._login_widget.get_selected_provider()              self._provider_config.load(                  provider.get_provider_path(provider_domain))          provides_mx = self._provider_config.provides_mx() -        if flags.OFFLINE is True and provides_mx: +        if flags.OFFLINE and provides_mx:              start_fun()              return          if self._provides_mx_and_enabled():              start_fun() -    def _on_mail_client_logged_in(self, req): -        """ -        Triggers qt signal when client login event is received. -        """ -        self.mail_client_logged_in.emit() - -    @QtCore.Slot() -    def _fetch_incoming_mail(self): -        """ -        TRIGGERS: -            self.mail_client_logged_in -        """ -        # TODO connect signal directly!!! -        self._mail_conductor.fetch_incoming_mail() -      @QtCore.Slot()      def _stop_imap_service(self):          """ diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py index b4e97ac1..aa22afe4 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -19,15 +19,15 @@ Mail Services Conductor  """  import logging -from zope.proxy import sameProxiedObjects +from twisted.internet import threads +from leap.bitmask.config import flags  from leap.bitmask.gui import statemachines  from leap.bitmask.services.mail import connection as mail_connection -from leap.bitmask.services.mail import imap  from leap.bitmask.services.mail.smtpbootstrapper import SMTPBootstrapper  from leap.bitmask.services.mail.smtpconfig import SMTPConfig +from leap.bitmask.services.mail.imapcontroller import IMAPController -from leap.common.check import leap_assert  from leap.common.events import events_pb2 as leap_events  from leap.common.events import register as leap_register @@ -39,15 +39,20 @@ class IMAPControl(object):      """      Methods related to IMAP control.      """ -    def __init__(self): +    def __init__(self, soledad, keymanager):          """          Initializes smtp variables. + +        :param soledad: a transparent proxy that eventually will point to a +                        Soledad Instance. +        :type soledad: zope.proxy.ProxyBase +        :param keymanager: a transparent proxy that eventually will point to a +                           Keymanager Instance. +        :type keymanager: zope.proxy.ProxyBase          """          self.imap_machine = None -        self.imap_service = None -        self.imap_port = None -        self.imap_factory = None          self.imap_connection = None +        self._imap_controller = IMAPController(soledad, keymanager)          leap_register(signal=leap_events.IMAP_SERVICE_STARTED,                        callback=self._handle_imap_events, @@ -55,10 +60,13 @@ class IMAPControl(object):          leap_register(signal=leap_events.IMAP_SERVICE_FAILED_TO_START,                        callback=self._handle_imap_events,                        reqcbk=lambda req, resp: None) +        leap_register(signal=leap_events.IMAP_CLIENT_LOGIN, +                      callback=self._handle_imap_events, +                      reqcbk=lambda req, resp: None)      def set_imap_connection(self, imap_connection):          """ -        Sets the imap connection to an initialized connection. +        Set the imap connection to an initialized connection.          :param imap_connection: an initialized imap connection          :type imap_connection: IMAPConnection instance. @@ -67,65 +75,23 @@ class IMAPControl(object):      def start_imap_service(self):          """ -        Starts imap service. +        Start imap service.          """ -        from leap.bitmask.config import flags - -        logger.debug('Starting imap service') -        leap_assert(not sameProxiedObjects(self._soledad, None), -                    "We need a non-null soledad for initializing imap service") -        leap_assert(not sameProxiedObjects(self._keymanager, None), -                    "We need a non-null keymanager for initializing imap " -                    "service") - -        offline = flags.OFFLINE -        self.imap_service, self.imap_port, \ -            self.imap_factory = imap.start_imap_service( -                self._soledad, -                self._keymanager, -                userid=self.userid, -                offline=offline) - -        if offline is False: -            logger.debug("Starting loop") -            self.imap_service.start_loop() +        threads.deferToThread(self._imap_controller.start_imap_service, +                              self.userid, flags.OFFLINE)      def stop_imap_service(self, cv):          """ -        Stops imap service (fetcher, factory and port). +        Stop imap service (fetcher, factory and port).          :param cv: A condition variable to which we can signal when imap                     indeed stops.          :type cv: threading.Condition          """          self.imap_connection.qtsigs.disconnecting_signal.emit() -        # TODO We should homogenize both services. -        if self.imap_service is not None: -            logger.debug('Stopping imap service.') -            # Stop the loop call in the fetcher -            self.imap_service.stop() -            self.imap_service = None -            # Stop listening on the IMAP port -            self.imap_port.stopListening() -            # Stop the protocol -            self.imap_factory.theAccount.closed = True -            self.imap_factory.doStop(cv) -        else: -            # main window does not have to wait because there's no service to -            # be stopped, so we release the condition variable -            cv.acquire() -            cv.notify() -            cv.release() - -    def fetch_incoming_mail(self): -        """ -        Fetches incoming mail. -        """ -        if self.imap_service: -            logger.debug('Client connected, fetching mail...') -            self.imap_service.fetch() - -    # handle events +        logger.debug('Stopping imap service.') + +        self._imap_controller.stop_imap_service(cv)      def _handle_imap_events(self, req):          """ @@ -135,25 +101,31 @@ class IMAPControl(object):          :type req: leap.common.events.events_pb2.SignalRequest          """          if req.event == leap_events.IMAP_SERVICE_STARTED: -            self.on_imap_connected() +            self._on_imap_connected()          elif req.event == leap_events.IMAP_SERVICE_FAILED_TO_START: -            self.on_imap_failed() +            self._on_imap_failed() +        elif req.event == leap_events.IMAP_CLIENT_LOGIN: +            self._on_mail_client_logged_in() -    # emit connection signals +    def _on_mail_client_logged_in(self): +        """ +        On mail client logged in, fetch incoming mail. +        """ +        self._controller.imap_service_fetch() -    def on_imap_connecting(self): +    def _on_imap_connecting(self):          """          Callback for IMAP connecting state.          """          self.imap_connection.qtsigs.connecting_signal.emit() -    def on_imap_connected(self): +    def _on_imap_connected(self):          """          Callback for IMAP connected state.          """          self.imap_connection.qtsigs.connected_signal.emit() -    def on_imap_failed(self): +    def _on_imap_failed(self):          """          Callback for IMAP failed state.          """ @@ -197,7 +169,8 @@ class SMTPControl(object):          :type download_if_needed: bool          """          self.smtp_connection.qtsigs.connecting_signal.emit() -        self.smtp_bootstrapper.start_smtp_service( +        threads.deferToThread( +            self.smtp_bootstrapper.start_smtp_service,              provider_config, self.smtp_config, self._keymanager,              self.userid, download_if_needed) @@ -258,12 +231,11 @@ class MailConductor(IMAPControl, SMTPControl):          :param soledad: a transparent proxy that eventually will point to a                          Soledad Instance.          :type soledad: zope.proxy.ProxyBase -          :param keymanager: a transparent proxy that eventually will point to a                             Keymanager Instance.          :type keymanager: zope.proxy.ProxyBase          """ -        IMAPControl.__init__(self) +        IMAPControl.__init__(self, soledad, keymanager)          SMTPControl.__init__(self)          self._soledad = soledad          self._keymanager = keymanager diff --git a/src/leap/bitmask/services/mail/imapcontroller.py b/src/leap/bitmask/services/mail/imapcontroller.py new file mode 100644 index 00000000..efca5867 --- /dev/null +++ b/src/leap/bitmask/services/mail/imapcontroller.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +# imapcontroller.py +# Copyright (C) 2013 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/>. +""" +IMAP service controller. +""" +import logging + +from leap.bitmask.services.mail import imap + + +logger = logging.getLogger(__name__) + + +class IMAPController(object): +    """ +    IMAP Controller. +    """ +    def __init__(self, soledad, keymanager): +        """ +        Initialize IMAP variables. + +        :param soledad: a transparent proxy that eventually will point to a +                        Soledad Instance. +        :type soledad: zope.proxy.ProxyBase +        :param keymanager: a transparent proxy that eventually will point to a +                           Keymanager Instance. +        :type keymanager: zope.proxy.ProxyBase +        """ +        self._soledad = soledad +        self._keymanager = keymanager + +        self.imap_service = None +        self.imap_port = None +        self.imap_factory = None + +    def start_imap_service(self, userid, offline=False): +        """ +        Start IMAP service. +        """ +        logger.debug('Starting imap service') + +        self.imap_service, self.imap_port, \ +            self.imap_factory = imap.start_imap_service( +                self._soledad, +                self._keymanager, +                userid=userid, +                offline=offline) + +        if offline is False: +            logger.debug("Starting loop") +            self.imap_service.start_loop() + +    def stop_imap_service(self, cv): +        """ +        Stop IMAP service (fetcher, factory and port). + +        :param cv: A condition variable to which we can signal when imap +                   indeed stops. +        :type cv: threading.Condition +        """ +        if self.imap_service is not None: +            # Stop the loop call in the fetcher +            self.imap_service.stop() +            self.imap_service = None + +            # Stop listening on the IMAP port +            self.imap_port.stopListening() + +            # Stop the protocol +            self.imap_factory.theAccount.closed = True +            self.imap_factory.doStop(cv) +        else: +            # Release the condition variable so the caller doesn't have to wait +            cv.acquire() +            cv.notify() +            cv.release() + +    def fetch_incoming_mail(self): +        """ +        Fetch incoming mail. +        """ +        if self.imap_service: +            logger.debug('Client connected, fetching mail...') +            self.imap_service.fetch() | 
