[geary/wip/713247-tls] Infrastructure for bubbling up TLS warnings to client application



commit 16b217ff548cb210c398ae97815a2de9023e0a9e
Author: Jim Nelson <jim yorba org>
Date:   Tue Aug 26 14:29:50 2014 -0700

    Infrastructure for bubbling up TLS warnings to client application

 src/CMakeLists.txt                                 |    1 +
 src/client/accounts/account-dialog.vala            |    3 +-
 src/client/application/geary-controller.vala       |   12 ++-
 src/client/application/secret-mediator.vala        |   20 ++--
 src/client/dialogs/password-dialog.vala            |    2 +-
 src/engine/api/geary-account-information.vala      |  140 ++++++++++++--------
 src/engine/api/geary-credentials-mediator.vala     |   19 ---
 src/engine/api/geary-endpoint.vala                 |   42 ++++--
 src/engine/api/geary-engine.vala                   |   20 +++-
 src/engine/api/geary-service.vala                  |   25 ++++
 src/engine/imap-db/outbox/smtp-outbox-folder.vala  |    6 +-
 .../gmail/imap-engine-gmail-account.vala           |   38 ++----
 .../imap-engine/imap-engine-generic-account.vala   |    4 +-
 .../outlook/imap-engine-outlook-account.vala       |   38 ++----
 .../yahoo/imap-engine-yahoo-account.vala           |   38 ++----
 15 files changed, 226 insertions(+), 182 deletions(-)
---
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7e8a6e1..9330c53 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -40,6 +40,7 @@ engine/api/geary-named-flags.vala
 engine/api/geary-progress-monitor.vala
 engine/api/geary-search-folder.vala
 engine/api/geary-search-query.vala
+engine/api/geary-service.vala
 engine/api/geary-service-provider.vala
 engine/api/geary-special-folder-type.vala
 
diff --git a/src/client/accounts/account-dialog.vala b/src/client/accounts/account-dialog.vala
index b64df13..b32bce4 100644
--- a/src/client/accounts/account-dialog.vala
+++ b/src/client/accounts/account-dialog.vala
@@ -92,8 +92,7 @@ public class AccountDialog : Gtk.Dialog {
             return;
         
         try {
-            yield account.get_passwords_async(Geary.CredentialsMediator.ServiceFlag.IMAP |
-                Geary.CredentialsMediator.ServiceFlag.SMTP);
+            yield account.get_passwords_async(Geary.ServiceFlag.IMAP | Geary.ServiceFlag.SMTP);
         } catch (Error err) {
             debug("Unable to fetch password(s) for account: %s", err.message);
         }
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index 2c4b4f8..b6b3446 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -177,6 +177,7 @@ public class GearyController : Geary.BaseObject {
         
         Geary.Engine.instance.account_available.connect(on_account_available);
         Geary.Engine.instance.account_unavailable.connect(on_account_unavailable);
+        Geary.Engine.instance.tls_warnings_detected.connect(on_tls_warnings_detected);
         
         // Connect to various UI signals.
         main_window.conversation_list_view.conversations_selected.connect(on_conversations_selected);
@@ -499,6 +500,11 @@ public class GearyController : Geary.BaseObject {
         close_account(get_account_instance(account_information));
     }
     
+    private void on_tls_warnings_detected(Geary.AccountInformation account_information,
+        Geary.Endpoint endpoint, Geary.Endpoint.SecurityType security, TlsConnection cx,
+        Geary.Service service, TlsCertificateFlags warnings) {
+    }
+    
     private void create_account() {
         Geary.AccountInformation? account_information = request_account_information(null);
         if (account_information != null)
@@ -566,8 +572,8 @@ public class GearyController : Geary.BaseObject {
             }
             
             real_account_information.store_async.begin(cancellable);
-            do_update_stored_passwords_async.begin(Geary.CredentialsMediator.ServiceFlag.IMAP |
-                Geary.CredentialsMediator.ServiceFlag.SMTP, real_account_information);
+            do_update_stored_passwords_async.begin(Geary.ServiceFlag.IMAP | Geary.ServiceFlag.SMTP,
+                real_account_information);
             
             debug("Successfully validated account information");
         }
@@ -635,7 +641,7 @@ public class GearyController : Geary.BaseObject {
         return new_info;
     }
     
-    private async void do_update_stored_passwords_async(Geary.CredentialsMediator.ServiceFlag services,
+    private async void do_update_stored_passwords_async(Geary.ServiceFlag services,
         Geary.AccountInformation account_information) {
         try {
             yield account_information.update_stored_passwords_async(services);
diff --git a/src/client/application/secret-mediator.vala b/src/client/application/secret-mediator.vala
index b06224d..e1ed1ae 100644
--- a/src/client/application/secret-mediator.vala
+++ b/src/client/application/secret-mediator.vala
@@ -8,12 +8,12 @@
 public class SecretMediator : Geary.CredentialsMediator, Object {
     private const string OLD_GEARY_USERNAME_PREFIX = "org.yorba.geary username:";
     
-    private string get_key_name(Geary.CredentialsMediator.Service service, string user) {
+    private string get_key_name(Geary.Service service, string user) {
         switch (service) {
-            case Service.IMAP:
+            case Geary.Service.IMAP:
                 return "org.yorba.geary imap_username:" + user;
             
-            case Service.SMTP:
+            case Geary.Service.SMTP:
                 return "org.yorba.geary smtp_username:" + user;
             
             default:
@@ -21,12 +21,12 @@ public class SecretMediator : Geary.CredentialsMediator, Object {
         }
     }
 
-    private Geary.Credentials get_credentials(Geary.CredentialsMediator.Service service, 
Geary.AccountInformation account_information) {
+    private Geary.Credentials get_credentials(Geary.Service service, Geary.AccountInformation 
account_information) {
         switch (service) {
-            case Service.IMAP:
+            case Geary.Service.IMAP:
                 return account_information.imap_credentials;
 
-            case Service.SMTP:
+            case Geary.Service.SMTP:
                 return account_information.smtp_credentials;
 
             default:
@@ -49,7 +49,7 @@ public class SecretMediator : Geary.CredentialsMediator, Object {
     }
     
     public virtual async string? get_password_async(
-        Geary.CredentialsMediator.Service service, Geary.AccountInformation account_information, 
Cancellable? cancellable = null)
+        Geary.Service service, Geary.AccountInformation account_information, Cancellable? cancellable = null)
         throws Error {
         string key_name = get_key_name(service, account_information.email);
         string? password = yield Secret.password_lookup(Secret.SCHEMA_COMPAT_NETWORK, cancellable,
@@ -77,7 +77,7 @@ public class SecretMediator : Geary.CredentialsMediator, Object {
     }
     
     public virtual async void set_password_async(
-        Geary.CredentialsMediator.Service service, Geary.AccountInformation account_information,
+        Geary.Service service, Geary.AccountInformation account_information,
         Cancellable? cancellable = null) throws Error {
         string key_name = get_key_name(service, account_information.email);
         Geary.Credentials credentials = get_credentials(service, account_information);
@@ -89,7 +89,7 @@ public class SecretMediator : Geary.CredentialsMediator, Object {
     }
     
     public virtual async void clear_password_async(
-        Geary.CredentialsMediator.Service service, Geary.AccountInformation account_information, 
Cancellable? cancellable = null)
+        Geary.Service service, Geary.AccountInformation account_information, Cancellable? cancellable = null)
         throws Error {
         // delete new-style and old-style locations
         Geary.Credentials credentials = get_credentials(service, account_information);
@@ -104,7 +104,7 @@ public class SecretMediator : Geary.CredentialsMediator, Object {
             OLD_GEARY_USERNAME_PREFIX + credentials.user);
     }
     
-    public virtual async bool prompt_passwords_async(Geary.CredentialsMediator.ServiceFlag services,
+    public virtual async bool prompt_passwords_async(Geary.ServiceFlag services,
         Geary.AccountInformation account_information,
         out string? imap_password, out string? smtp_password,
         out bool imap_remember_password, out bool smtp_remember_password) throws Error {
diff --git a/src/client/dialogs/password-dialog.vala b/src/client/dialogs/password-dialog.vala
index 96296fd..8ca620d 100644
--- a/src/client/dialogs/password-dialog.vala
+++ b/src/client/dialogs/password-dialog.vala
@@ -24,7 +24,7 @@ public class PasswordDialog {
     public bool remember_password { get; private set; }
     
     public PasswordDialog(bool smtp, Geary.AccountInformation account_information,
-        Geary.CredentialsMediator.ServiceFlag password_flags) {
+        Geary.ServiceFlag password_flags) {
         Gtk.Builder builder = GearyApplication.instance.create_builder("password-dialog.glade");
         
         dialog = (Gtk.Dialog) builder.get_object("PasswordDialog");
diff --git a/src/engine/api/geary-account-information.vala b/src/engine/api/geary-account-information.vala
index c00dbb8..50bf1e7 100644
--- a/src/engine/api/geary-account-information.vala
+++ b/src/engine/api/geary-account-information.vala
@@ -105,6 +105,11 @@ public class Geary.AccountInformation : BaseObject {
     public bool save_drafts { get; set; default = true; }
     
     private bool _save_sent_mail = true;
+    private Endpoint? imap_endpoint = null;
+    private Endpoint? smtp_endpoint = null;
+    
+    public signal void tls_warnings_detected(Endpoint endpoint, Endpoint.SecurityType security,
+        TlsConnection cx, Service service, TlsCertificateFlags warnings);
     
     // Used to create temporary AccountInformation objects.  (Note that these cannot be saved.)
     public AccountInformation.temp_copy(AccountInformation copy) {
@@ -179,6 +184,14 @@ public class Geary.AccountInformation : BaseObject {
         }
     }
     
+    ~AccountInformation() {
+        if (imap_endpoint != null)
+            imap_endpoint.tls_warnings_detected.disconnect(on_imap_tls_warnings_detected);
+        
+        if (smtp_endpoint != null)
+            smtp_endpoint.tls_warnings_detected.disconnect(on_smtp_tls_warnings_detected);
+    }
+    
     // Copies all data from the "from" object into this one.
     public void copy_from(AccountInformation from) {
         real_name = from.real_name;
@@ -287,19 +300,19 @@ public class Geary.AccountInformation : BaseObject {
      *
      * If force_request is set to true, a prompt will appear regardless.
      */
-    public async bool fetch_passwords_async(CredentialsMediator.ServiceFlag services,
+    public async bool fetch_passwords_async(ServiceFlag services,
         bool force_request = false) throws Error {
         if (force_request) {
             // Delete the current password(s).
             if (services.has_imap()) {
                 yield Geary.Engine.instance.authentication_mediator.clear_password_async(
-                    CredentialsMediator.Service.IMAP, this);
+                    Service.IMAP, this);
                 
                 if (imap_credentials != null)
                     imap_credentials.pass = null;
             } else if (services.has_smtp()) {
                 yield Geary.Engine.instance.authentication_mediator.clear_password_async(
-                    CredentialsMediator.Service.SMTP, this);
+                    Service.SMTP, this);
                 
                 if (smtp_credentials != null)
                     smtp_credentials.pass = null;
@@ -308,14 +321,14 @@ public class Geary.AccountInformation : BaseObject {
         
         // Only call get_passwords on anything that hasn't been set
         // (incorrectly) previously.
-        CredentialsMediator.ServiceFlag get_services = 0;
+        ServiceFlag get_services = 0;
         if (services.has_imap() && !imap_credentials.is_complete())
-            get_services |= CredentialsMediator.ServiceFlag.IMAP;
+            get_services |= ServiceFlag.IMAP;
         
         if (services.has_smtp() && smtp_credentials != null && !smtp_credentials.is_complete())
-            get_services |= CredentialsMediator.ServiceFlag.SMTP;
+            get_services |= ServiceFlag.SMTP;
         
-        CredentialsMediator.ServiceFlag unset_services = services;
+        ServiceFlag unset_services = services;
         if (get_services != 0)
             unset_services = yield get_passwords_async(get_services);
         else
@@ -352,31 +365,28 @@ public class Geary.AccountInformation : BaseObject {
      * prompt_passwords_async() on the return value), or 0 if all were
      * retrieved.
      */
-    public async CredentialsMediator.ServiceFlag get_passwords_async(
-        CredentialsMediator.ServiceFlag services) throws Error {
+    public async ServiceFlag get_passwords_async(ServiceFlag services) throws Error {
         check_mediator_instance();
         
         CredentialsMediator mediator = Geary.Engine.instance.authentication_mediator;
-        CredentialsMediator.ServiceFlag failed_services = 0;
+        ServiceFlag failed_services = 0;
         
         if (services.has_imap()) {
-            string? imap_password = yield mediator.get_password_async(
-                CredentialsMediator.Service.IMAP, this);
+            string? imap_password = yield mediator.get_password_async(Service.IMAP, this);
             
             if (imap_password != null)
                 set_imap_password(imap_password);
              else
-                failed_services |= CredentialsMediator.ServiceFlag.IMAP;
+                failed_services |= ServiceFlag.IMAP;
         }
         
         if (services.has_smtp() && smtp_credentials != null) {
-            string? smtp_password = yield mediator.get_password_async(
-                CredentialsMediator.Service.SMTP, this);
+            string? smtp_password = yield mediator.get_password_async(Service.SMTP, this);
             
             if (smtp_password != null)
                 set_smtp_password(smtp_password);
             else
-                failed_services |= CredentialsMediator.ServiceFlag.SMTP;
+                failed_services |= ServiceFlag.SMTP;
         }
         
         return failed_services;
@@ -390,15 +400,14 @@ public class Geary.AccountInformation : BaseObject {
      * whether the user proceeded normally (false if they tried to cancel the
      * prompt).
      */
-    public async bool prompt_passwords_async(
-        CredentialsMediator.ServiceFlag services) throws Error {
+    public async bool prompt_passwords_async(ServiceFlag services) throws Error {
         check_mediator_instance();
         
         string? imap_password, smtp_password;
         bool imap_remember_password, smtp_remember_password;
         
         if (smtp_credentials == null)
-            services &= ~CredentialsMediator.ServiceFlag.SMTP;
+            services &= ~ServiceFlag.SMTP;
         
         if (!yield Geary.Engine.instance.authentication_mediator.prompt_passwords_async(
             services, this, out imap_password, out smtp_password,
@@ -424,43 +433,42 @@ public class Geary.AccountInformation : BaseObject {
      * Use the Engine's authentication mediator to set or clear the passwords
      * for the given services in the key store.
      */
-    public async void update_stored_passwords_async(
-        CredentialsMediator.ServiceFlag services) throws Error {
+    public async void update_stored_passwords_async(ServiceFlag services) throws Error {
         check_mediator_instance();
         
         CredentialsMediator mediator = Geary.Engine.instance.authentication_mediator;
         
         if (services.has_imap()) {
-            if (imap_remember_password) {
-                yield mediator.set_password_async(
-                    CredentialsMediator.Service.IMAP, this);
-            } else {
-                yield mediator.clear_password_async(
-                    CredentialsMediator.Service.IMAP, this);
-            }
+            if (imap_remember_password)
+                yield mediator.set_password_async(Service.IMAP, this);
+            else
+                yield mediator.clear_password_async(Service.IMAP, this);
         }
         
         if (services.has_smtp() && smtp_credentials != null) {
-            if (smtp_remember_password) {
-                yield mediator.set_password_async(
-                    CredentialsMediator.Service.SMTP, this);
-            } else {
-                yield mediator.clear_password_async(
-                    CredentialsMediator.Service.SMTP, this);
-            }
+            if (smtp_remember_password)
+                yield mediator.set_password_async(Service.SMTP, this);
+            else
+                yield mediator.clear_password_async(Service.SMTP, this);
         }
     }
     
     public Endpoint get_imap_endpoint() {
+        if (imap_endpoint != null)
+            return imap_endpoint;
+        
         switch (service_provider) {
             case ServiceProvider.GMAIL:
-                return ImapEngine.GmailAccount.IMAP_ENDPOINT;
+                imap_endpoint = ImapEngine.GmailAccount.generate_imap_endpoint();
+            break;
             
             case ServiceProvider.YAHOO:
-                return ImapEngine.YahooAccount.IMAP_ENDPOINT;
+                imap_endpoint = ImapEngine.YahooAccount.generate_imap_endpoint();
+            break;
             
             case ServiceProvider.OUTLOOK:
-                return ImapEngine.OutlookAccount.IMAP_ENDPOINT;
+                imap_endpoint = ImapEngine.OutlookAccount.generate_imap_endpoint();
+            break;
             
             case ServiceProvider.OTHER:
                 Endpoint.Flags imap_flags = Endpoint.Flags.GRACEFUL_DISCONNECT;
@@ -469,24 +477,40 @@ public class Geary.AccountInformation : BaseObject {
                 if (default_imap_server_starttls)
                     imap_flags |= Endpoint.Flags.STARTTLS;
                 
-                return new Endpoint(default_imap_server_host, default_imap_server_port,
+                imap_endpoint = new Endpoint(default_imap_server_host, default_imap_server_port,
                     imap_flags, Imap.ClientConnection.RECOMMENDED_TIMEOUT_SEC);
+            break;
             
             default:
                 assert_not_reached();
         }
+        
+        imap_endpoint.tls_warnings_detected.connect(on_imap_tls_warnings_detected);
+        
+        return imap_endpoint;
     }
-
+    
+    private void on_imap_tls_warnings_detected(Endpoint endpoint, Endpoint.SecurityType security,
+        TlsConnection cx, TlsCertificateFlags warnings) {
+        tls_warnings_detected(endpoint, security, cx, Service.IMAP, warnings);
+    }
+    
     public Endpoint get_smtp_endpoint() {
+        if (smtp_endpoint != null)
+            return smtp_endpoint;
+        
         switch (service_provider) {
             case ServiceProvider.GMAIL:
-                return ImapEngine.GmailAccount.SMTP_ENDPOINT;
+                smtp_endpoint = ImapEngine.GmailAccount.generate_smtp_endpoint();
+            break;
             
             case ServiceProvider.YAHOO:
-                return ImapEngine.YahooAccount.SMTP_ENDPOINT;
+                smtp_endpoint = ImapEngine.YahooAccount.generate_smtp_endpoint();
+            break;
             
             case ServiceProvider.OUTLOOK:
-                return ImapEngine.OutlookAccount.SMTP_ENDPOINT;
+                smtp_endpoint = ImapEngine.OutlookAccount.generate_smtp_endpoint();
+            break;
             
             case ServiceProvider.OTHER:
                 Endpoint.Flags smtp_flags = Endpoint.Flags.GRACEFUL_DISCONNECT;
@@ -495,12 +519,22 @@ public class Geary.AccountInformation : BaseObject {
                 if (default_smtp_server_starttls)
                     smtp_flags |= Endpoint.Flags.STARTTLS;
                 
-                return new Endpoint(default_smtp_server_host, default_smtp_server_port,
+                smtp_endpoint = new Endpoint(default_smtp_server_host, default_smtp_server_port,
                     smtp_flags, Smtp.ClientConnection.DEFAULT_TIMEOUT_SEC);
+            break;
             
             default:
                 assert_not_reached();
         }
+        
+        smtp_endpoint.tls_warnings_detected.connect(on_smtp_tls_warnings_detected);
+        
+        return smtp_endpoint;
+    }
+    
+    private void on_smtp_tls_warnings_detected(Endpoint endpoint, Endpoint.SecurityType security,
+        TlsConnection cx, TlsCertificateFlags warnings) {
+        tls_warnings_detected(endpoint, security, cx, Service.SMTP, warnings);
     }
     
     private Geary.FolderPath? build_folder_path(Gee.List<string>? parts) {
@@ -646,26 +680,21 @@ public class Geary.AccountInformation : BaseObject {
         }
     }
     
-    public async void clear_stored_passwords_async(
-        CredentialsMediator.ServiceFlag services) throws Error {
+    public async void clear_stored_passwords_async(ServiceFlag services) throws Error {
         Error? return_error = null;
         check_mediator_instance();
         CredentialsMediator mediator = Geary.Engine.instance.authentication_mediator;
         
         try {
-            if (services.has_imap()) {
-                yield mediator.clear_password_async(
-                    CredentialsMediator.Service.IMAP, this);
-            }
+            if (services.has_imap())
+                yield mediator.clear_password_async(Service.IMAP, this);
         } catch (Error e) {
             return_error = e;
         }
         
         try {
-            if (services.has_smtp() && smtp_credentials != null) {
-                yield mediator.clear_password_async(
-                    CredentialsMediator.Service.SMTP, this);
-            }
+            if (services.has_smtp() && smtp_credentials != null)
+                yield mediator.clear_password_async(Service.SMTP, this);
         } catch (Error e) {
             return_error = e;
         }
@@ -685,8 +714,7 @@ public class Geary.AccountInformation : BaseObject {
         }
         
         try {
-            yield clear_stored_passwords_async(CredentialsMediator.ServiceFlag.IMAP
-                | CredentialsMediator.ServiceFlag.SMTP);
+            yield clear_stored_passwords_async(ServiceFlag.IMAP | ServiceFlag.SMTP);
         } catch (Error e) {
             debug("Error clearing SMTP password: %s", e.message);
         }
diff --git a/src/engine/api/geary-credentials-mediator.vala b/src/engine/api/geary-credentials-mediator.vala
index fa6b683..9d1cdc1 100644
--- a/src/engine/api/geary-credentials-mediator.vala
+++ b/src/engine/api/geary-credentials-mediator.vala
@@ -5,25 +5,6 @@
  */
 
 public interface Geary.CredentialsMediator : Object {
-    public enum Service {
-        IMAP,
-        SMTP;
-    }
-    
-    [Flags]
-    public enum ServiceFlag {
-        IMAP,
-        SMTP;
-        
-        public bool has_imap() {
-            return (this & IMAP) == IMAP;
-        }
-        
-        public bool has_smtp() {
-            return (this & SMTP) == SMTP;
-        }
-    }
-    
     /**
      * Query the key store for the password of the given username for the given
      * service.  Return null if the password wasn't in the key store, or the
diff --git a/src/engine/api/geary-endpoint.vala b/src/engine/api/geary-endpoint.vala
index bf0ab51..c8226d7 100644
--- a/src/engine/api/geary-endpoint.vala
+++ b/src/engine/api/geary-endpoint.vala
@@ -26,6 +26,12 @@ public class Geary.Endpoint : BaseObject {
         }
     }
     
+    public enum SecurityType {
+        NONE,
+        SSL,
+        STARTTLS
+    }
+    
     public enum AttemptStarttls {
         YES,
         NO,
@@ -36,6 +42,7 @@ public class Geary.Endpoint : BaseObject {
     public Flags flags { get; private set; }
     public uint timeout_sec { get; private set; }
     public TlsCertificateFlags tls_validation_flags { get; set; default = TlsCertificateFlags.VALIDATE_ALL; }
+    public TlsCertificateFlags tls_validation_warnings { get; private set; default = 0; }
     public bool force_ssl3 { get; set; default = false; }
     
     public bool is_ssl { get {
@@ -47,6 +54,10 @@ public class Geary.Endpoint : BaseObject {
     } }
     
     private SocketClient? socket_client = null;
+    private bool tls_warnings_accepted = false;
+    
+    public signal void tls_warnings_detected(SecurityType security, TlsConnection cx,
+        TlsCertificateFlags tls_warnings);
     
     public Endpoint(string host_specifier, uint16 default_port, Flags flags, uint timeout_sec) {
         this.remote_address = new NetworkAddress(host_specifier, default_port);
@@ -54,30 +65,30 @@ public class Geary.Endpoint : BaseObject {
         this.timeout_sec = timeout_sec;
     }
     
-    public SocketClient get_socket_client() {
+    private SocketClient get_socket_client() {
         if (socket_client != null)
             return socket_client;
-
+        
         socket_client = new SocketClient();
-
+        
         if (is_ssl) {
             socket_client.set_tls(true);
             socket_client.set_tls_validation_flags(tls_validation_flags);
             socket_client.event.connect(on_socket_client_event);
         }
-
+        
         socket_client.set_timeout(timeout_sec);
-
+        
         return socket_client;
     }
 
     public async SocketConnection connect_async(Cancellable? cancellable = null) throws Error {
         SocketConnection cx = yield get_socket_client().connect_async(remote_address, cancellable);
-
+        
         TcpConnection? tcp = cx as TcpConnection;
         if (tcp != null)
             tcp.set_graceful_disconnect(flags.is_all_set(Flags.GRACEFUL_DISCONNECT));
-
+        
         return cx;
     }
     
@@ -110,20 +121,27 @@ public class Geary.Endpoint : BaseObject {
     }
     
     private bool on_accept_starttls_certificate(TlsConnection cx, TlsCertificate cert, TlsCertificateFlags 
flags) {
-        return report_tls_warnings("STARTTLS", flags);
+        return report_tls_warnings(SecurityType.STARTTLS, cx, flags);
     }
     
     private bool on_accept_ssl_certificate(TlsConnection cx, TlsCertificate cert, TlsCertificateFlags flags) 
{
-        return report_tls_warnings("SSL", flags);
+        return report_tls_warnings(SecurityType.SSL, cx, flags);
     }
     
-    private bool report_tls_warnings(string cx_type, TlsCertificateFlags warnings) {
+    private bool report_tls_warnings(SecurityType security, TlsConnection cx, TlsCertificateFlags warnings) {
         // TODO: Report or verify flags with user, but for now merely log for informational/debugging
         // reasons and accede
-        message("%s TLS warnings connecting to %s: %Xh (%s)", cx_type, to_string(), warnings,
+        message("%s TLS warnings connecting to %s: %Xh (%s)", security.to_string(), to_string(), warnings,
             tls_flags_to_string(warnings));
         
-        return true;
+        tls_validation_warnings = warnings;
+        
+        if (tls_warnings_accepted)
+            return true;
+        
+        tls_warnings_detected(security, cx, warnings);
+        
+        return false;
     }
     
     private string tls_flags_to_string(TlsCertificateFlags flags) {
diff --git a/src/engine/api/geary-engine.vala b/src/engine/api/geary-engine.vala
index 0491af6..006c692 100644
--- a/src/engine/api/geary-engine.vala
+++ b/src/engine/api/geary-engine.vala
@@ -80,7 +80,11 @@ public class Geary.Engine : BaseObject {
      * Fired when an account is deleted.
      */
     public signal void account_removed(AccountInformation account);
-
+    
+    public signal void tls_warnings_detected(Geary.AccountInformation account_information,
+        Endpoint endpoint, Endpoint.SecurityType security, TlsConnection cx, Service service,
+        TlsCertificateFlags warnings);
+    
     private Engine() {
     }
     
@@ -239,6 +243,8 @@ public class Geary.Engine : BaseObject {
         if (!options.is_all_set(ValidationOption.CHECK_CONNECTIONS))
             return error_code;
         
+        account.tls_warnings_detected.connect(on_tls_warnings_detected);
+        
         // validate IMAP, which requires logging in and establishing an AUTHORIZED cx state
         Geary.Imap.ClientSession? imap_session = new Imap.ClientSession(account.get_imap_endpoint());
         try {
@@ -293,6 +299,8 @@ public class Geary.Engine : BaseObject {
             smtp_session = null;
         }
         
+        account.tls_warnings_detected.disconnect(on_tls_warnings_detected);
+        
         return error_code;
     }
     
@@ -352,8 +360,11 @@ public class Geary.Engine : BaseObject {
         accounts.set(account.email, account);
 
         if (!already_added) {
+            account.tls_warnings_detected.connect(on_tls_warnings_detected);
+            
             if (created)
                 account_added(account);
+            
             account_available(account);
         }
     }
@@ -372,6 +383,8 @@ public class Geary.Engine : BaseObject {
         }
         
         if (accounts.unset(account.email)) {
+            account.tls_warnings_detected.disconnect(on_tls_warnings_detected);
+            
             // Removal *MUST* be done in the following order:
             // 1. Send the account-unavailable signal.
             account_unavailable(account);
@@ -386,5 +399,10 @@ public class Geary.Engine : BaseObject {
             account_instances.unset(account.email);
         }
     }
+    
+    private void on_tls_warnings_detected(AccountInformation account_information, Endpoint endpoint,
+        Endpoint.SecurityType security, TlsConnection cx, Service service, TlsCertificateFlags warnings) {
+        tls_warnings_detected(account_information, endpoint, security, cx, service, warnings);
+    }
 }
 
diff --git a/src/engine/api/geary-service.vala b/src/engine/api/geary-service.vala
new file mode 100644
index 0000000..679e9d1
--- /dev/null
+++ b/src/engine/api/geary-service.vala
@@ -0,0 +1,25 @@
+/* Copyright 2014 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later).  See the COPYING file in this distribution.
+ */
+
+public enum Geary.Service {
+    IMAP,
+    SMTP;
+}
+
+[Flags]
+public enum Geary.ServiceFlag {
+    IMAP,
+    SMTP;
+    
+    public bool has_imap() {
+        return (this & IMAP) == IMAP;
+    }
+    
+    public bool has_smtp() {
+        return (this & SMTP) == SMTP;
+    }
+}
+
diff --git a/src/engine/imap-db/outbox/smtp-outbox-folder.vala 
b/src/engine/imap-db/outbox/smtp-outbox-folder.vala
index 22c82f4..f994786 100644
--- a/src/engine/imap-db/outbox/smtp-outbox-folder.vala
+++ b/src/engine/imap-db/outbox/smtp-outbox-folder.vala
@@ -197,8 +197,7 @@ private class Geary.SmtpOutboxFolder : Geary.AbstractLocalFolder, Geary.FolderSu
             if (_account.information.smtp_credentials != null &&
                 !_account.information.smtp_credentials.is_complete()) {
                 try {
-                    yield _account.information.get_passwords_async(
-                        CredentialsMediator.ServiceFlag.SMTP);
+                    yield _account.information.get_passwords_async(ServiceFlag.SMTP);
                 } catch (Error e) {
                     debug("SMTP password fetch error: %s", e.message);
                 }
@@ -236,8 +235,7 @@ private class Geary.SmtpOutboxFolder : Geary.AbstractLocalFolder, Geary.FolderSu
                     // At this point we may already have a password in memory -- but it's incorrect.
                     // Delete the current password, prompt the user for a new one, and try again.
                     try {
-                        if (yield _account.information.fetch_passwords_async(
-                            CredentialsMediator.ServiceFlag.SMTP, true))
+                        if (yield _account.information.fetch_passwords_async(ServiceFlag.SMTP, true))
                             report = false;
                     } catch (Error e) {
                         debug("Error prompting for SMTP password: %s", e.message);
diff --git a/src/engine/imap-engine/gmail/imap-engine-gmail-account.vala 
b/src/engine/imap-engine/gmail/imap-engine-gmail-account.vala
index 9ad9a29..d409efc 100644
--- a/src/engine/imap-engine/gmail/imap-engine-gmail-account.vala
+++ b/src/engine/imap-engine/gmail/imap-engine-gmail-account.vala
@@ -5,31 +5,21 @@
  */
 
 private class Geary.ImapEngine.GmailAccount : Geary.ImapEngine.GenericAccount {
-    private static Geary.Endpoint? _imap_endpoint = null;
-    public static Geary.Endpoint IMAP_ENDPOINT { get {
-        if (_imap_endpoint == null) {
-            _imap_endpoint = new Geary.Endpoint(
-                "imap.gmail.com",
-                Imap.ClientConnection.DEFAULT_PORT_SSL,
-                Geary.Endpoint.Flags.SSL | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
-                Imap.ClientConnection.RECOMMENDED_TIMEOUT_SEC);
-        }
-        
-        return _imap_endpoint;
-    } }
+    public static Geary.Endpoint generate_imap_endpoint() {
+        return new Geary.Endpoint(
+            "imap.gmail.com",
+            Imap.ClientConnection.DEFAULT_PORT_SSL,
+            Geary.Endpoint.Flags.SSL | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
+            Imap.ClientConnection.RECOMMENDED_TIMEOUT_SEC);
+    }
     
-    private static Geary.Endpoint? _smtp_endpoint = null;
-    public static Geary.Endpoint SMTP_ENDPOINT { get {
-        if (_smtp_endpoint == null) {
-            _smtp_endpoint = new Geary.Endpoint(
-                "smtp.gmail.com",
-                Smtp.ClientConnection.DEFAULT_PORT_SSL,
-                Geary.Endpoint.Flags.SSL | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
-                Smtp.ClientConnection.DEFAULT_TIMEOUT_SEC);
-        }
-        
-        return _smtp_endpoint;
-    } }
+    public static Geary.Endpoint generate_smtp_endpoint() {
+        return new Geary.Endpoint(
+            "smtp.gmail.com",
+            Smtp.ClientConnection.DEFAULT_PORT_SSL,
+            Geary.Endpoint.Flags.SSL | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
+            Smtp.ClientConnection.DEFAULT_TIMEOUT_SEC);
+    }
     
     public GmailAccount(string name, Geary.AccountInformation account_information,
         Imap.Account remote, ImapDB.Account local) {
diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala 
b/src/engine/imap-engine/imap-engine-generic-account.vala
index 4ffd268..92fef95 100644
--- a/src/engine/imap-engine/imap-engine-generic-account.vala
+++ b/src/engine/imap-engine/imap-engine-generic-account.vala
@@ -122,7 +122,7 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
         // IMAP password before attempting a connection.  This might have to be
         // reworked when we allow passwordless logins.
         if (!information.imap_credentials.is_complete())
-            yield information.fetch_passwords_async(Geary.CredentialsMediator.ServiceFlag.IMAP);
+            yield information.fetch_passwords_async(ServiceFlag.IMAP);
         
         try {
             yield local.open_async(information.settings_dir, Engine.instance.resource_dir.get_child("sql"),
@@ -853,7 +853,7 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
     
     private async void do_login_failed_async(Geary.Credentials? credentials) {
         try {
-            if (yield information.fetch_passwords_async(CredentialsMediator.ServiceFlag.IMAP, true))
+            if (yield information.fetch_passwords_async(ServiceFlag.IMAP, true))
                 return;
         } catch (Error e) {
             debug("Error prompting for IMAP password: %s", e.message);
diff --git a/src/engine/imap-engine/outlook/imap-engine-outlook-account.vala 
b/src/engine/imap-engine/outlook/imap-engine-outlook-account.vala
index c40d0ea..d8ef8d6 100644
--- a/src/engine/imap-engine/outlook/imap-engine-outlook-account.vala
+++ b/src/engine/imap-engine/outlook/imap-engine-outlook-account.vala
@@ -5,31 +5,21 @@
  */
 
 private class Geary.ImapEngine.OutlookAccount : Geary.ImapEngine.GenericAccount {
-    private static Geary.Endpoint? _imap_endpoint = null;
-    public static Geary.Endpoint IMAP_ENDPOINT { get {
-        if (_imap_endpoint == null) {
-            _imap_endpoint = new Geary.Endpoint(
-                "imap-mail.outlook.com",
-                Imap.ClientConnection.DEFAULT_PORT_SSL,
-                Geary.Endpoint.Flags.SSL | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
-                Imap.ClientConnection.RECOMMENDED_TIMEOUT_SEC);
-        }
-        
-        return _imap_endpoint;
-    } }
+    public static Geary.Endpoint generate_imap_endpoint() {
+        return new Geary.Endpoint(
+            "imap-mail.outlook.com",
+            Imap.ClientConnection.DEFAULT_PORT_SSL,
+            Geary.Endpoint.Flags.SSL | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
+            Imap.ClientConnection.RECOMMENDED_TIMEOUT_SEC);
+    }
     
-    private static Geary.Endpoint? _smtp_endpoint = null;
-    public static Geary.Endpoint SMTP_ENDPOINT { get {
-        if (_smtp_endpoint == null) {
-            _smtp_endpoint = new Geary.Endpoint(
-                "smtp-mail.outlook.com",
-                Smtp.ClientConnection.DEFAULT_PORT_STARTTLS,
-                Geary.Endpoint.Flags.STARTTLS | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
-                Smtp.ClientConnection.DEFAULT_TIMEOUT_SEC);
-        }
-        
-        return _smtp_endpoint;
-    } }
+    public static Geary.Endpoint generate_smtp_endpoint() {
+        return new Geary.Endpoint(
+            "smtp-mail.outlook.com",
+            Smtp.ClientConnection.DEFAULT_PORT_STARTTLS,
+            Geary.Endpoint.Flags.STARTTLS | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
+            Smtp.ClientConnection.DEFAULT_TIMEOUT_SEC);
+    }
     
     public OutlookAccount(string name, AccountInformation account_information, Imap.Account remote,
         ImapDB.Account local) {
diff --git a/src/engine/imap-engine/yahoo/imap-engine-yahoo-account.vala 
b/src/engine/imap-engine/yahoo/imap-engine-yahoo-account.vala
index 01a3086..dafc993 100644
--- a/src/engine/imap-engine/yahoo/imap-engine-yahoo-account.vala
+++ b/src/engine/imap-engine/yahoo/imap-engine-yahoo-account.vala
@@ -5,31 +5,21 @@
  */
 
 private class Geary.ImapEngine.YahooAccount : Geary.ImapEngine.GenericAccount {
-    private static Geary.Endpoint? _imap_endpoint = null;
-    public static Geary.Endpoint IMAP_ENDPOINT { get {
-        if (_imap_endpoint == null) {
-            _imap_endpoint = new Geary.Endpoint(
-                "imap.mail.yahoo.com",
-                Imap.ClientConnection.DEFAULT_PORT_SSL,
-                Geary.Endpoint.Flags.SSL | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
-                Imap.ClientConnection.RECOMMENDED_TIMEOUT_SEC);
-        }
-        
-        return _imap_endpoint;
-    } }
+    public static Geary.Endpoint generate_imap_endpoint() {
+        return new Geary.Endpoint(
+            "imap.mail.yahoo.com",
+            Imap.ClientConnection.DEFAULT_PORT_SSL,
+            Geary.Endpoint.Flags.SSL | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
+            Imap.ClientConnection.RECOMMENDED_TIMEOUT_SEC);
+    }
     
-    private static Geary.Endpoint? _smtp_endpoint = null;
-    public static Geary.Endpoint SMTP_ENDPOINT { get {
-        if (_smtp_endpoint == null) {
-            _smtp_endpoint = new Geary.Endpoint(
-                "smtp.mail.yahoo.com",
-                Smtp.ClientConnection.DEFAULT_PORT_SSL,
-                Geary.Endpoint.Flags.SSL | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
-                Smtp.ClientConnection.DEFAULT_TIMEOUT_SEC);
-        }
-        
-        return _smtp_endpoint;
-    } }
+    public static Geary.Endpoint generate_smtp_endpoint() {
+        return new Geary.Endpoint(
+            "smtp.mail.yahoo.com",
+            Smtp.ClientConnection.DEFAULT_PORT_SSL,
+            Geary.Endpoint.Flags.SSL | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
+            Smtp.ClientConnection.DEFAULT_TIMEOUT_SEC);
+    }
     
     private static Gee.HashMap<Geary.FolderPath, Geary.SpecialFolderType>? special_map = null;
     



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]