diff options
Diffstat (limited to 'src/leap/bitmask/gui/mainwindow.py')
| -rw-r--r-- | src/leap/bitmask/gui/mainwindow.py | 195 | 
1 files changed, 57 insertions, 138 deletions
| diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index f5631c69..dddd53da 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -24,6 +24,7 @@ import keyring  from PySide import QtCore, QtGui  from twisted.internet import threads +from zope.proxy import ProxyBase, setProxiedObject, sameProxiedObjects  from leap.bitmask import __version__ as VERSION  from leap.bitmask.config.leapsettings import LeapSettings @@ -39,18 +40,15 @@ from leap.bitmask.gui.mail_status import MailStatusWidget  from leap.bitmask.gui.wizard import Wizard  from leap.bitmask import provider -from leap.bitmask.provider.providerbootstrapper import ProviderBootstrapper -from leap.bitmask.services.eip.eipbootstrapper import EIPBootstrapper -from leap.bitmask.services.eip import eipconfig -# XXX: Soledad might not work out of the box in Windows, issue #2932 -from leap.bitmask.services.soledad.soledadbootstrapper import \ -    SoledadBootstrapper -from leap.bitmask.services.mail.smtpbootstrapper import SMTPBootstrapper -from leap.bitmask.services.mail import imap  from leap.bitmask.platform_init import IS_WIN, IS_MAC  from leap.bitmask.platform_init.initializers import init_platform +from leap.bitmask.provider.providerbootstrapper import ProviderBootstrapper +from leap.bitmask.services.mail import conductor as mail_conductor + +from leap.bitmask.services.eip import eipconfig  from leap.bitmask.services.eip import get_openvpn_management +from leap.bitmask.services.eip.eipbootstrapper import EIPBootstrapper  from leap.bitmask.services.eip.connection import EIPConnection  from leap.bitmask.services.eip.vpnprocess import VPN  from leap.bitmask.services.eip.vpnprocess import OpenVPNAlreadyRunning @@ -62,12 +60,12 @@ from leap.bitmask.services.eip.linuxvpnlauncher import EIPNoPkexecAvailable  from leap.bitmask.services.eip.linuxvpnlauncher import \      EIPNoPolkitAuthAgentAvailable  from leap.bitmask.services.eip.darwinvpnlauncher import EIPNoTunKextLoaded +from leap.bitmask.services.soledad.soledadbootstrapper import \ +    SoledadBootstrapper  from leap.bitmask.util.keyring_helpers import has_keyring  from leap.bitmask.util.leap_log_handler import LeapLogHandler -from leap.bitmask.services.mail.smtpconfig import SMTPConfig -  if IS_WIN:      from leap.bitmask.platform_init.locks import WindowsLock      from leap.bitmask.platform_init.locks import raise_window_ack @@ -93,10 +91,6 @@ class MainWindow(QtGui.QMainWindow):      # Keyring      KEYRING_KEY = "bitmask" -    # SMTP -    PORT_KEY = "port" -    IP_KEY = "ip_address" -      OPENVPN_SERVICE = "openvpn"      MX_SERVICE = "mx" @@ -257,10 +251,6 @@ class MainWindow(QtGui.QMainWindow):          self._soledad_bootstrapper.soledad_failed.connect(              self._mail_status.set_soledad_failed) -        self._smtp_bootstrapper = SMTPBootstrapper() -        self._smtp_bootstrapper.download_config.connect( -            self._smtp_bootstrapped_stage) -          self.ui.action_about_leap.triggered.connect(self._about)          self.ui.action_quit.triggered.connect(self.quit)          self.ui.action_wizard.triggered.connect(self._launch_wizard) @@ -307,12 +297,13 @@ class MainWindow(QtGui.QMainWindow):          # Services signals/slots connection          self.new_updates.connect(self._react_to_new_updates) + +        # 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.soledad_ready.connect(self._set_soledad_ready)          self.mail_client_logged_in.connect(self._fetch_incoming_mail)          self.logout.connect(self._stop_imap_service)          self.logout.connect(self._stop_smtp_service) -        self.logout.connect(self._mail_status.stopped_mail)          ################################# end Qt Signals connection ######## @@ -325,17 +316,18 @@ class MainWindow(QtGui.QMainWindow):          self._bypass_checks = bypass_checks -        self._soledad = None -        self._soledad_ready = False -        self._keymanager = None -        self._smtp_service = None -        self._smtp_port = None -        self._imap_service = None +        # We initialize Soledad and Keymanager instances as +        # transparent proxies, so we can pass the reference freely +        # around. +        self._soledad = ProxyBase(None) +        self._keymanager = ProxyBase(None)          self._login_defer = None          self._download_provider_defer = None -        self._smtp_config = SMTPConfig() +        self._mail_conductor = mail_conductor.MailConductor( +            self._soledad, self._keymanager) +        self._mail_conductor.connect_mail_signals(self._mail_status)          # Eip machine is a public attribute where the state machine for          # the eip connection will be available to the different components. @@ -347,6 +339,7 @@ class MainWindow(QtGui.QMainWindow):          self.eip_machine = None          # start event machines          self.start_eip_machine() +        self._mail_conductor.start_mail_machine(parent=self)          if self._first_run():              self._wizard_firstrun = True @@ -460,7 +453,7 @@ class MainWindow(QtGui.QMainWindow):          """          preferences_window = PreferencesWindow(self, self._srp_auth) -        if self._soledad_ready: +        if sameProxiedObjects(self._soledad, None):              preferences_window.set_soledad_ready(self._soledad)          else:              self.soledad_ready.connect( @@ -478,16 +471,6 @@ class MainWindow(QtGui.QMainWindow):          """          EIPPreferencesWindow(self).show() -    def _set_soledad_ready(self): -        """ -        SLOT -        TRIGGERS: -            self.soledad_ready - -        It sets the soledad object as ready to use. -        """ -        self._soledad_ready = True -      #      # updates      # @@ -803,6 +786,7 @@ class MainWindow(QtGui.QMainWindow):          provider configuration if it's not present, otherwise will          emit the corresponding signals inmediately          """ +        # XXX should rename this provider, name clash.          provider = self._login_widget.get_selected_provider()          pb = self._provider_bootstrapper @@ -823,6 +807,7 @@ class MainWindow(QtGui.QMainWindow):          :type data: dict          """          if data[self._provider_bootstrapper.PASSED_KEY]: +            # XXX should rename this provider, name clash.              provider = self._login_widget.get_selected_provider()              # If there's no loaded provider or @@ -1023,114 +1008,58 @@ class MainWindow(QtGui.QMainWindow):              logger.debug("ERROR on soledad bootstrapping:")              logger.error("%r" % data[self._soledad_bootstrapper.ERROR_KEY])              return -        else: -            logger.debug("Done bootstrapping Soledad") -            self._soledad = self._soledad_bootstrapper.soledad -            self._keymanager = self._soledad_bootstrapper.keymanager +        logger.debug("Done bootstrapping Soledad") + +        # Update the proxy objects to point to +        # the initialized instances. +        setProxiedObject(self._soledad, +                         self._soledad_bootstrapper.soledad) +        setProxiedObject(self._keymanager, +                         self._soledad_bootstrapper.keymanager)          # Ok, now soledad is ready, so we can allow other things that          # depend on soledad to start.          # this will trigger start_imap_service +        # and start_smtp_boostrapping          self.soledad_ready.emit() -        # TODO connect all these activations to the soledad_ready -        # signal so the logic is clearer to follow. - -        if self._provider_config.provides_mx() and \ -                self._enabled_services.count(self.MX_SERVICE) > 0: -            self._smtp_bootstrapper.run_smtp_setup_checks( -                self._provider_config, -                self._smtp_config, -                True) -      ###################################################################      # Service control methods: smtp -    def _smtp_bootstrapped_stage(self, data): +    @QtCore.Slot() +    def _start_smtp_bootstrapping(self):          """          SLOT          TRIGGERS: -          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 -        they fail. - -        :param data: result from the bootstrapping stage for Soledad -        :type data: dict -        """ -        passed = data[self._smtp_bootstrapper.PASSED_KEY] -        if not passed: -            logger.error(data[self._smtp_bootstrapper.ERROR_KEY]) -            return -        logger.debug("Done bootstrapping SMTP") -        self._check_smtp_config() - -    def _check_smtp_config(self): -        """ -        Checks smtp config and tries to download smtp client cert if needed. +            self.soledad_ready          """ -        hosts = self._smtp_config.get_hosts() -        # TODO handle more than one host and define how to choose -        if len(hosts) > 0: -            hostname = hosts.keys()[0] -            logger.debug("Using hostname %s for SMTP" % (hostname,)) -            host = hosts[hostname][self.IP_KEY].encode("utf-8") -            port = hosts[hostname][self.PORT_KEY] - -            client_cert = self._smtp_config.get_client_cert_path( +        # TODO for simmetry, this should be called start_smtp_service +        # (and delegate all the checks to the conductor) +        if self._provider_config.provides_mx() and \ +                self._enabled_services.count(self.MX_SERVICE) > 0: +            self._mail_conductor.smtp_bootstrapper.run_smtp_setup_checks(                  self._provider_config, -                about_to_download=True) - -            if not os.path.isfile(client_cert): -                self._smtp_bootstrapper._download_client_certificates() -            if os.path.isfile(client_cert): -                self._start_smtp_service(host, port, client_cert) -            else: -                logger.warning("Tried to download email client " -                               "certificate, but could not find any") - -        else: -            logger.warning("No smtp hosts configured") - -    def _start_smtp_service(self, host, port, cert): -        """ -        Starts the smtp service. -        """ -        # TODO Make the encrypted_only configurable -        # TODO pick local smtp port in a better way -        # TODO remove hard-coded port and let leap.mail set -        # the specific default. - -        from leap.mail.smtp import setup_smtp_relay -        self._smtp_service, self._smtp_port = setup_smtp_relay( -            port=2013, -            keymanager=self._keymanager, -            smtp_host=host, -            smtp_port=port, -            smtp_cert=cert, -            smtp_key=cert, -            encrypted_only=False) +                self._mail_conductor.smtp_config, +                download_if_needed=True) +    # XXX --- should remove from here, and connecte directly to the state +    # machine. +    @QtCore.Slot()      def _stop_smtp_service(self):          """          SLOT          TRIGGERS:              self.logout          """ -        # There is a subtle difference here: -        # we are stopping the factory for the smtp service here, -        # but in the imap case we are just stopping the fetcher. -        if self._smtp_service is not None: -            logger.debug('Stopping smtp service.') -            self._smtp_port.stopListening() -            self._smtp_service.doStop() +        # TODO call stop_mail_service +        self._mail_conductor.stop_smtp_service()      ###################################################################      # Service control methods: imap +    @QtCore.Slot()      def _start_imap_service(self):          """          SLOT @@ -1139,11 +1068,7 @@ class MainWindow(QtGui.QMainWindow):          """          if self._provider_config.provides_mx() and \                  self._enabled_services.count(self.MX_SERVICE) > 0: -            logger.debug('Starting imap service') - -            self._imap_service = imap.start_imap_service( -                self._soledad, -                self._keymanager) +            self._mail_conductor.start_imap_service()      def _on_mail_client_logged_in(self, req):          """ @@ -1151,30 +1076,25 @@ class MainWindow(QtGui.QMainWindow):          """          self.mail_client_logged_in.emit() +    @QtCore.Slot()      def _fetch_incoming_mail(self):          """          SLOT          TRIGGERS:              self.mail_client_logged_in          """ -        # TODO have a mutex over fetch operation. -        if self._imap_service: -            logger.debug('Client connected, fetching mail...') -            self._imap_service.fetch() +        # TODO connect signal directly!!! +        self._mail_conductor.fetch_incoming_mail() +    @QtCore.Slot()      def _stop_imap_service(self):          """          SLOT          TRIGGERS:              self.logout          """ -        # There is a subtle difference here: -        # we are just stopping the fetcher here, -        # but in the smtp case we are stopping the factory. -        # We should homogenize both services. -        if self._imap_service is not None: -            logger.debug('Stopping imap service.') -            self._imap_service.stop() +        # TODO call stop_mail_service +        self._mail_conductor.stop_imap_service()      # end service control methods (imap) @@ -1623,8 +1543,8 @@ class MainWindow(QtGui.QMainWindow):          if ok:              self._logged_user = None -              self._login_widget.logged_out() +            self._mail_status.mail_state_disabled()          else:              self._login_widget.set_login_status( @@ -1700,8 +1620,7 @@ class MainWindow(QtGui.QMainWindow):          """          logger.debug('About to quit, doing cleanup...') -        if self._imap_service is not None: -            self._imap_service.stop() +        self._mail_conductor.stop_imap_service()          if self._srp_auth is not None:              if self._srp_auth.get_session_id() is not None or \ | 
