* Fixes a crash when removing accounts. Added by a code I commited today
[modest] / src / modest-tny-account-store.c
index da8e2c4..5d92d16 100644 (file)
@@ -103,8 +103,8 @@ static void    on_vfs_volume_unmounted     (GnomeVFSVolumeMonitor *volume_monito
                                            GnomeVFSVolume *volume, 
                                            gpointer user_data);
 
-static void    modest_tny_account_store_forget_password_in_memory (ModestTnyAccountStore *self, 
-                                                                  const gchar *server_account_name);
+static void    forget_password_in_memory (ModestTnyAccountStore *self, 
+                                         const gchar *server_account_name);
 
 static void    add_connection_specific_transport_accounts         (ModestTnyAccountStore *self);
 
@@ -300,6 +300,11 @@ static void
 account_disconnect (TnyAccount *account)
 {
        g_return_if_fail (account && TNY_IS_ACCOUNT(account));
+
+       if (TNY_IS_STORE_ACCOUNT (account) && 
+           !modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
+               return;
+
        tny_camel_account_set_online (TNY_CAMEL_ACCOUNT(account), FALSE, NULL, NULL);
 }
 
@@ -434,7 +439,7 @@ on_vfs_volume_unmounted(GnomeVFSVolumeMonitor *volume_monitor,
 }
 
 /**
- * modest_tny_account_store_forget_password_in_memory
+ * forget_password_in_memory
  * @self: a TnyAccountStore instance
  * @account: A server account.
  * 
@@ -442,9 +447,9 @@ on_vfs_volume_unmounted(GnomeVFSVolumeMonitor *volume_monitor,
  * For instance, this should be called when the user has changed the password in the account settings.
  */
 static void
-modest_tny_account_store_forget_password_in_memory (ModestTnyAccountStore *self, const gchar * server_account_name)
+forget_password_in_memory (ModestTnyAccountStore *self, 
+                          const gchar * server_account_name)
 {
-       /* printf ("DEBUG: %s\n", __FUNCTION__); */
        ModestTnyAccountStorePrivate *priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
 
        if (server_account_name && priv->password_hash) {
@@ -547,29 +552,47 @@ show_wrong_password_dialog (TnyAccount *account)
 static gchar*
 get_password (TnyAccount *account, const gchar * prompt_not_used, gboolean *cancel)
 {
-       const TnyAccountStore *account_store = NULL;
        ModestTnyAccountStore *self = NULL;
        ModestTnyAccountStorePrivate *priv;
        gchar *username = NULL;
        gchar *pwd = NULL;
        gpointer pwd_ptr = NULL;
        gboolean already_asked = FALSE;
+       const gchar *server_account_name;
+       gchar *url_string;
 
        g_return_val_if_fail (account, NULL);
        
        MODEST_DEBUG_BLOCK(
                g_debug ("%s: prompt (not shown) = %s\n", __FUNCTION__, prompt_not_used);
-       );
-       
-       /* Initialize the output parameter: */
-       if (cancel)
-               *cancel = FALSE;
-               
-       const gchar *server_account_name = tny_account_get_id (account);
-       account_store = TNY_ACCOUNT_STORE(g_object_get_data (G_OBJECT(account),
-                                                            "account_store"));
+       );              
+
+       /* Get a reference to myself */
+       self = MODEST_TNY_ACCOUNT_STORE (g_object_get_data (G_OBJECT(account), "account_store"));
+       priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
 
-       if (!server_account_name || !account_store) {
+       /* Ensure that we still have this account. It could happen
+          that a set_online was requested *before* removing an
+          account, and due to tinymail emits the get_password
+          function using a g_idle the account could be actually
+          removed *before* this function was really called */
+       url_string = tny_account_get_url_string (account);
+       if (url_string) {
+               TnyAccount *tmp_account;
+
+               tmp_account = tny_account_store_find_account (TNY_ACCOUNT_STORE (self), 
+                                                             url_string);
+               g_free (url_string);
+
+               if (!tmp_account) {
+                       *cancel = TRUE;
+                       return NULL;
+               }
+               g_object_unref (tmp_account);
+       }
+
+       server_account_name = tny_account_get_id (account);
+       if (!server_account_name || !self) {
                g_warning ("modest: %s: could not retrieve account_store for account %s",
                           __FUNCTION__, server_account_name ? server_account_name : "<NULL>");
                if (cancel)
@@ -577,9 +600,6 @@ get_password (TnyAccount *account, const gchar * prompt_not_used, gboolean *canc
                
                return NULL;
        }
-
-       self = MODEST_TNY_ACCOUNT_STORE (account_store);
-       priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
        
        /* This hash map stores passwords, including passwords that are not stored in gconf. */
        /* Is it in the hash? if it's already there, it must be wrong... */
@@ -665,14 +685,14 @@ get_password (TnyAccount *account, const gchar * prompt_not_used, gboolean *canc
                                                                                             server_account_name);
                        /* If the login has ever succeeded then show a specific message */
                        if (username_known)
-                               msg = _("ecdg_ib_set_password_incorrect");
+                               msg = dgettext ("hildon-common-strings", "ecdg_ib_set_password_incorrect");
                        else
                                msg = _("mcen_ib_username_pw_incorrect");
                        show_password_warning_only (msg);
                }
 
                /* Request password */
-               g_signal_emit (G_OBJECT(account_store), signals[PASSWORD_REQUESTED_SIGNAL], 0,
+               g_signal_emit (G_OBJECT (self), signals[PASSWORD_REQUESTED_SIGNAL], 0,
                               account_id, /* server_account_name */
                               &username, &pwd, cancel, &remember);
 
@@ -982,7 +1002,7 @@ modest_tny_account_store_get_accounts  (TnyAccountStore *self,
                tny_list_foreach (priv->transport_accounts, foreach_account_append_to_list, list);
                break;
        case TNY_ACCOUNT_STORE_STORE_ACCOUNTS:
-               tny_list_foreach (priv->store_accounts, foreach_account_append_to_list, list);
+               tny_list_foreach (priv->store_accounts, foreach_account_append_to_list, list);
                break;
        case TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS:
                tny_list_foreach (priv->transport_accounts, foreach_account_append_to_list, list);
@@ -1047,18 +1067,16 @@ modest_tny_account_store_alert (TnyAccountStore *self,
 {
        ModestTransportStoreProtocol proto =
                MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN; 
-       const gchar* server_name = NULL;
+       const gchar* server_name = "";
        gchar *prompt = NULL;
        gboolean retval;
 
-
-       g_return_val_if_fail (account, FALSE);
+       /* NOTE: account may be NULL in some cases */
        g_return_val_if_fail (error, FALSE);
        
        /* Get the server name: */
-       server_name = tny_account_get_hostname (account);
-
        if (account) {
+               server_name = tny_account_get_hostname (account);
                const gchar *proto_name = tny_account_get_proto (account);
                if (proto_name)
                        proto = modest_protocol_info_get_transport_store_protocol (proto_name);
@@ -1555,8 +1573,7 @@ create_tny_account (ModestTnyAccountStore *self,
        if (account) {
                /* Forget any cached password for the account, so that
                   we use a new account if any */
-               modest_tny_account_store_forget_password_in_memory (self, 
-                                                                   tny_account_get_id (account));
+               forget_password_in_memory (self, tny_account_get_id (account));
 
                /* Install a signal handler that will refresh the
                   account the first time it becomes online. Do this
@@ -1720,16 +1737,6 @@ on_account_disconnect_when_removing (TnyCamelAccount *account,
                                                                  "connection_status_changed");
        }
 
-       /* Remove it from the list of accounts */
-       if (TNY_IS_STORE_ACCOUNT (account))
-               tny_list_remove (priv->store_accounts, (GObject *) account);
-       else
-               tny_list_remove (priv->transport_accounts, (GObject *) account);
-
-       /* Notify the observers */
-       g_signal_emit (G_OBJECT (self), signals [ACCOUNT_REMOVED_SIGNAL], 
-                      0, account);
-
        /* Cancel all pending operations */
        tny_account_cancel (TNY_ACCOUNT (account));
        
@@ -1737,8 +1744,19 @@ on_account_disconnect_when_removing (TnyCamelAccount *account,
        g_object_unref (account);
 
        /* Clear the cache if it's an store account */
-       if (TNY_IS_STORE_ACCOUNT (account))
+       if (TNY_IS_STORE_ACCOUNT (account)) {
                tny_store_account_delete_cache (TNY_STORE_ACCOUNT (account));
+       } else if (TNY_IS_TRANSPORT_ACCOUNT (account)) {
+               ModestTnySendQueue* send_queue;
+               send_queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (account), FALSE);
+               if (send_queue) {
+                       if (modest_tny_send_queue_sending_in_progress (send_queue))
+                               tny_send_queue_cancel (TNY_SEND_QUEUE (send_queue),
+                                                      TNY_SEND_QUEUE_CANCEL_ACTION_REMOVE, 
+                                                      NULL);
+                       modest_runtime_remove_send_queue (TNY_TRANSPORT_ACCOUNT (account));
+               }
+       }
 }
 
 static void
@@ -1755,13 +1773,24 @@ on_account_removed (ModestAccountMgr *acc_mgr,
 
        /* Get the server and the transport account */
        store_account = 
-               modest_tny_account_store_get_server_account (self, account, TNY_ACCOUNT_TYPE_STORE);
+               modest_tny_account_store_get_server_account (self, account, 
+                                                            TNY_ACCOUNT_TYPE_STORE);
        transport_account = 
-               modest_tny_account_store_get_server_account (self, account, TNY_ACCOUNT_TYPE_TRANSPORT);
+               modest_tny_account_store_get_server_account (self, account,
+                                                            TNY_ACCOUNT_TYPE_TRANSPORT);
        
        /* If there was any problem creating the account, for example,
           with the configuration system this could not exist */
-       if (store_account) {
+       if (TNY_IS_STORE_ACCOUNT(store_account)) {
+               /* Forget any cached password for the account */
+               forget_password_in_memory (self, tny_account_get_id (store_account));
+
+               /* Remove it from the list of accounts and notify the
+                  observers. Do not need to wait for account
+                  disconnection */
+               tny_list_remove (priv->store_accounts, (GObject *) store_account);
+               g_signal_emit (G_OBJECT (self), signals [ACCOUNT_REMOVED_SIGNAL], 0, store_account);
+
                /* Cancel all pending operations */
                tny_account_cancel (TNY_ACCOUNT (store_account));
 
@@ -1771,24 +1800,42 @@ on_account_removed (ModestAccountMgr *acc_mgr,
                tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (store_account), FALSE,
                                              on_account_disconnect_when_removing, self);
        } else {
-               g_warning ("There is no store account for account %s\n", account);
+               g_warning ("%s: no store account for account %s\n", 
+                          __FUNCTION__, account);
        }
 
        /* If there was any problem creating the account, for example,
           with the configuration system this could not exist */
-       if (transport_account) {
+       if (TNY_IS_TRANSPORT_ACCOUNT(transport_account)) {
                TnyAccount *local_account = NULL;
                TnyFolder *outbox = NULL;
-               ModestTnyAccountStorePrivate *priv = NULL;
+
+               /* Forget any cached password for the account */
+               forget_password_in_memory (self, tny_account_get_id (transport_account));
+
+               /* Remove it from the list of accounts and notify the
+                  observers. Do not need to wait for account
+                  disconnection */
+               tny_list_remove (priv->transport_accounts, (GObject *) transport_account);
+               g_signal_emit (G_OBJECT (self), signals [ACCOUNT_REMOVED_SIGNAL], 0, transport_account);
        
                /* Remove the OUTBOX of the account from the global outbox */
-               priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
                outbox = g_hash_table_lookup (priv->outbox_of_transport, transport_account);
 
                if (TNY_IS_FOLDER (outbox)) {
+                       TnyAccount *outbox_account = tny_folder_get_account (outbox);
+
+                       if (outbox_account) {
+                               tny_list_remove (priv->store_accounts_outboxes, G_OBJECT (outbox_account));
+                               /* Remove existing emails to send */
+                               tny_store_account_delete_cache (TNY_STORE_ACCOUNT (outbox_account));
+                               g_object_unref (outbox_account);
+                       }
+
                        local_account = modest_tny_account_store_get_local_folders_account (self);
                        modest_tny_local_folders_account_remove_folder_from_outbox (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (local_account),
                                                                                    outbox);
+
                        g_hash_table_remove (priv->outbox_of_transport, transport_account);
 
                        /* Notify the change in the local account */
@@ -1805,7 +1852,8 @@ on_account_removed (ModestAccountMgr *acc_mgr,
                tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (transport_account), FALSE,
                                              on_account_disconnect_when_removing, self);
        } else {
-               g_warning ("There is no transport account for account %s\n", account);
+               g_warning ("%s: no transport account for account %s\n", 
+                          __FUNCTION__, account);
        }
 }
 
@@ -1934,7 +1982,7 @@ modest_tny_account_store_get_transport_account_from_outbox_header(ModestTnyAccou
        TnyIterator *acc_iter;
        ModestTnyAccountStorePrivate *priv;
        TnyTransportAccount *header_acc = NULL;
-       const gchar *msg_id;
+       gchar *msg_id;
 
        g_return_val_if_fail (MODEST_IS_TNY_ACCOUNT_STORE (self), NULL);
        g_return_val_if_fail (TNY_IS_HEADER (header), NULL);
@@ -1946,7 +1994,7 @@ modest_tny_account_store_get_transport_account_from_outbox_header(ModestTnyAccou
                TnyTransportAccount *account = TNY_TRANSPORT_ACCOUNT (tny_iterator_get_current (acc_iter));
                ModestTnySendQueue *send_queue;
                ModestTnySendQueueStatus status;
-               send_queue = modest_runtime_get_send_queue(TNY_TRANSPORT_ACCOUNT(account));
+               send_queue = modest_runtime_get_send_queue(TNY_TRANSPORT_ACCOUNT(account), TRUE);
                status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
                if (status != MODEST_TNY_SEND_QUEUE_UNKNOWN) {
                        header_acc = g_object_ref(account);
@@ -1955,6 +2003,7 @@ modest_tny_account_store_get_transport_account_from_outbox_header(ModestTnyAccou
                tny_iterator_next (acc_iter);
        }
        g_object_unref(acc_iter);
+       g_free (msg_id);
 
        /* New reference */
        return header_acc;
@@ -1972,9 +2021,10 @@ modest_tny_account_store_show_account_settings_dialog (ModestTnyAccountStore *se
        found = g_hash_table_lookup_extended (priv->account_settings_dialog_hash,
                                              account_name, NULL, (gpointer*)&dialog_as_gpointer);
 
-       if (found)
+       if (found) {
+               modest_account_settings_dialog_check_allow_changes ((ModestAccountSettingsDialog *) dialog_as_gpointer);
                return (GtkWidget *) dialog_as_gpointer;
-       else {
+       } else {
                ModestAccountSettings *settings;
                GtkWidget *dialog;
                dialog = (GtkWidget *) modest_account_settings_dialog_new ();
@@ -1982,6 +2032,7 @@ modest_tny_account_store_show_account_settings_dialog (ModestTnyAccountStore *se
                modest_account_settings_dialog_set_account (MODEST_ACCOUNT_SETTINGS_DIALOG (dialog), settings);
                g_object_unref (settings);
                modest_account_settings_dialog_switch_to_user_info (MODEST_ACCOUNT_SETTINGS_DIALOG (dialog));
+               modest_account_settings_dialog_check_allow_changes (MODEST_ACCOUNT_SETTINGS_DIALOG (dialog));
                modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
                
                g_hash_table_insert (priv->account_settings_dialog_hash, g_strdup (account_name), dialog);