* Fixes a crash when removing accounts. Added by a code I commited today
[modest] / src / dbus_api / modest-dbus-callbacks.c
index b0c4f04..24cd7a8 100644 (file)
@@ -464,6 +464,13 @@ on_open_message_performer (gboolean canceled,
        } else {
                folder = tny_store_account_find_folder (TNY_STORE_ACCOUNT (account), uri, NULL);
        }
+
+
+       if (!folder) {
+               g_idle_add (notify_msg_not_found_in_idle, NULL);
+               goto frees;
+       }
+       
        if (modest_tny_folder_is_local_folder (folder) &&
            (modest_tny_folder_get_local_or_mmc_folder_type (folder) == TNY_FOLDER_TYPE_DRAFTS)) {
                is_draft = TRUE;
@@ -620,60 +627,99 @@ on_open_message (GArray * arguments, gpointer data, osso_rpc_t * retval)
        return osso_retval;
 }
 
+static void 
+on_remove_msgs_finished (ModestMailOperation *mail_op,
+                        gpointer user_data)
+{      
+       TnyHeader *header;
+       ModestWindow *main_win = NULL, *msg_view = NULL;
+       ModestHeaderView *header_view;
+
+       header = (TnyHeader *) user_data;
+
+       /* Get the main window if exists */
+       main_win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
+                                                     FALSE); /* don't create */
+       if (!main_win) {
+               g_object_unref (header);
+               return;
+       }
+
+       if (modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr(),
+                                                     header, &msg_view)) {
+               if (MODEST_IS_MSG_VIEW_WINDOW (msg_view))
+                       modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (msg_view));
+       }       
+       g_object_unref (header);
+
+       /* Refilter the header view explicitly */
+       header_view = (ModestHeaderView *)
+               modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(main_win),
+                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
+       if (header_view && MODEST_IS_HEADER_VIEW (header_view))
+               modest_header_view_refilter (header_view);
+}
+
 static gboolean
 on_idle_delete_message (gpointer user_data)
 {
-       TnyList *headers = NULL;
+       TnyList *headers = NULL, *tmp_headers = NULL;
        TnyFolder *folder = NULL;
        TnyIterator *iter = NULL; 
        TnyHeader *header = NULL, *msg_header = NULL;
        TnyMsg *msg = NULL;
        TnyAccount *account = NULL;
-       const char *uri = NULL, *uid = NULL;
-       gint res = 0;
+       const char *uri = NULL;
+       gchar *uid = NULL;
        ModestMailOperation *mail_op = NULL;
-       ModestWindow *main_win = NULL, *msg_view = NULL;
+       ModestWindow *main_win = NULL;
 
        uri = (char *) user_data;
        
        msg = find_message_by_url (uri, &account);
+       if (account)
+               g_object_unref (account);
 
        if (!msg) {
                g_warning ("%s: Could not find message '%s'", __FUNCTION__, uri);
                g_idle_add (notify_error_in_dbus_callback, NULL);
-               return OSSO_ERROR; 
+               return FALSE; 
        }
        
        main_win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
                                                      FALSE); /* don't create */
        
-       msg_header = tny_msg_get_header (msg);
-       uid = tny_header_get_uid (msg_header);
        folder = tny_msg_get_folder (msg);
-
        if (!folder) {
                g_warning ("%s: Could not find folder (uri:'%s')", __FUNCTION__, uri);
                g_object_unref (msg);
                g_idle_add (notify_error_in_dbus_callback, NULL);
-               return OSSO_ERROR; 
+               return FALSE; 
        }
 
+       /* Get UID */
+       msg_header = tny_msg_get_header (msg);
+       uid = tny_header_dup_uid (msg_header);
+       g_object_unref (msg);
+       g_object_unref (msg_header);
+
        headers = tny_simple_list_new ();
        tny_folder_get_headers (folder, headers, TRUE, NULL);
        iter = tny_list_create_iterator (headers);
-       header = NULL;
 
        while (!tny_iterator_is_done (iter)) {
-               const char *cur_id = NULL;
+               gchar *cur_id = NULL;
 
                header = TNY_HEADER (tny_iterator_get_current (iter));
                if (header)
-                       cur_id = tny_header_get_uid (header);
+                       cur_id = tny_header_dup_uid (header);
                
                if (cur_id && uid && g_str_equal (cur_id, uid)) {
+                       g_free (cur_id);
                        /* g_debug ("Found corresponding header from folder"); */
                        break;
                }
+               g_free (cur_id);
 
                if (header) {
                        g_object_unref (header);
@@ -682,80 +728,43 @@ on_idle_delete_message (gpointer user_data)
                
                tny_iterator_next (iter);
        }
-
+       g_free (uid);
        g_object_unref (iter);
-       iter = NULL;
        g_object_unref (headers);
-       headers = NULL;
-       
-       g_object_unref (msg_header);
-       msg_header = NULL;
-       g_object_unref (msg);
-       msg = NULL;
 
        if (header == NULL) {
                if (folder)
                        g_object_unref (folder);
                g_idle_add (notify_error_in_dbus_callback, NULL);                       
-               return OSSO_ERROR;
+               return FALSE;
        }
                
-       res = OSSO_OK;
-
        /* This is a GDK lock because we are an idle callback and
         * the code below is or does Gtk+ code */
        gdk_threads_enter (); /* CHECKED */
 
        mail_op = modest_mail_operation_new (main_win ? G_OBJECT(main_win) : NULL);
        modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
-       modest_mail_operation_remove_msg (mail_op, header, FALSE);
+
+       g_signal_connect (G_OBJECT (mail_op),
+                         "operation-finished",
+                         G_CALLBACK (on_remove_msgs_finished),
+                         g_object_ref (header));
+
+       tmp_headers = tny_simple_list_new ();
+       tny_list_append (tmp_headers, (GObject *) header);
+
+       modest_mail_operation_remove_msgs (mail_op, tmp_headers, FALSE);
+
+       g_object_unref (tmp_headers);
        g_object_unref (G_OBJECT (mail_op));
-       
-       if (main_win) { /* no need if there's no window */ 
-               if (modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr(),
-                                                             header, &msg_view)) {
-                       if (MODEST_IS_MSG_VIEW_WINDOW (msg_view))
-                               modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (msg_view));
-               }
-       }
        gdk_threads_leave (); /* CHECKED */
        
+       /* Clean */
        if (header)
                g_object_unref (header);
        
-       if (folder) {
-               /* Trick: do a poke status in order to speed up the signaling
-                  of observers.
-                  A delete via the menu does this, in do_headers_action(), 
-                  though I don't know why.
-                */
-               tny_folder_poke_status (folder);
-       
-               g_object_unref (folder);
-       }
-       
-       if (account)
-               g_object_unref (account);
-               
-       /* Refilter the header view explicitly, to make sure that 
-        * deleted emails are really removed from view. 
-        * (They are not really deleted until contact is made with the server, 
-        * so they would appear with a strike-through until then):
-        */
-       if (main_win) { /* only needed when there's a mainwindow / UI */
-
-               /* This is a GDK lock because we are an idle callback and
-                * the code below is or does Gtk+ code */
-               gdk_threads_enter (); /* CHECKED */
-               ModestHeaderView *header_view = (ModestHeaderView *)
-                       modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(main_win),
-                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
-               if (header_view && MODEST_IS_HEADER_VIEW (header_view))
-                       modest_header_view_refilter (header_view);
-               gdk_threads_leave ();
-       }
-       
-       return res;
+       return FALSE;
 }
 
 
@@ -837,7 +846,7 @@ on_dbus_method_dump_send_queues (DBusConnection *con, DBusMessage *message)
                if (TNY_IS_ACCOUNT(acc)) {
                        gchar *tmp, *url = tny_account_get_url_string (acc);
                        ModestTnySendQueue *sendqueue =
-                               modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT(acc));
+                               modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT(acc), TRUE);
                        gchar *queue_str = modest_tny_send_queue_to_string (sendqueue);
                        
                        tmp = g_strdup_printf ("%s[%s]: '%s': %s\n%s",
@@ -866,8 +875,11 @@ on_dbus_method_dump_send_queues (DBusConnection *con, DBusMessage *message)
                dbus_connection_flush (con);
                dbus_message_unref (reply);
        }
-       
        g_free (str);
+
+       /* Let modest die */
+       g_idle_add (notify_error_in_dbus_callback, NULL);
+
        return OSSO_OK;
 }
 
@@ -903,9 +915,12 @@ on_dbus_method_dump_operation_queue (DBusConnection *con, DBusMessage *message)
                dbus_connection_send (con, reply, &serial);
                dbus_connection_flush (con);
                dbus_message_unref (reply);
-       }
-       
+       }       
        g_free (str);
+
+       /* Let modest die */
+       g_idle_add (notify_error_in_dbus_callback, NULL);
+
        return OSSO_OK;
 }
 
@@ -940,8 +955,9 @@ on_dbus_method_dump_accounts (DBusConnection *con, DBusMessage *message)
                        TNY_ACCOUNT_TYPE_STORE);
                if (TNY_IS_ACCOUNT(acc)) {
                        gchar *tmp, *url = tny_account_get_url_string (acc);
-                       tmp = g_strdup_printf ("%sstore    : '%s': %s\n",
-                                              str, tny_account_get_id (acc), url);
+                       tmp = g_strdup_printf ("%sstore    : '%s': %s (refs: %d)\n",
+                                              str, tny_account_get_id (acc), url, 
+                                              ((GObject*)acc)->ref_count-1);
                        g_free (str);
                        str = tmp;
                        g_free (url);
@@ -954,8 +970,9 @@ on_dbus_method_dump_accounts (DBusConnection *con, DBusMessage *message)
                        TNY_ACCOUNT_TYPE_TRANSPORT);
                if (TNY_IS_ACCOUNT(acc)) {
                        gchar *tmp, *url = tny_account_get_url_string (acc);
-                       tmp = g_strdup_printf ("%stransport: '%s': %s\n",
-                                              str, tny_account_get_id (acc), url);
+                       tmp = g_strdup_printf ("%stransport: '%s': %s (refs: %d)\n",
+                                              str, tny_account_get_id (acc), url, 
+                                              ((GObject*)acc)->ref_count-1);
                        g_free (str);
                        str = tmp;
                        g_free (url);
@@ -977,20 +994,29 @@ on_dbus_method_dump_accounts (DBusConnection *con, DBusMessage *message)
                dbus_connection_send (con, reply, &serial);
                dbus_connection_flush (con);
                dbus_message_unref (reply);
-       }
-       
+       }       
        g_free (str);
-       return OSSO_OK;
-}
-
 
+       /* Let modest die */
+       g_idle_add (notify_error_in_dbus_callback, NULL);
 
+       return OSSO_OK;
+}
 
-static gint 
-on_send_receive(GArray *arguments, gpointer data, osso_rpc_t * retval)
-{      
+static void
+on_send_receive_performer(gboolean canceled, 
+                         GError *err,
+                         GtkWindow *parent_window,
+                         TnyAccount *account,
+                         gpointer user_data)
+{
        ModestConnectedVia connect_when;
 
+       if (err || canceled) {
+               g_idle_add (notify_error_in_dbus_callback, NULL);
+               return;
+       }
+
        connect_when = modest_conf_get_int (modest_runtime_get_conf (), 
                                            MODEST_CONF_UPDATE_WHEN_CONNECTED_BY, NULL);
        
@@ -999,9 +1025,23 @@ on_send_receive(GArray *arguments, gpointer data, osso_rpc_t * retval)
           same as the one specified by the user */
        if (connect_when == MODEST_CONNECTED_VIA_ANY ||
            connect_when == modest_platform_get_current_connection ()) {
-               /* Use g_idle to context-switch into the application's thread: */
-               g_idle_add(on_idle_send_receive, NULL);
+               g_idle_add (on_idle_send_receive, NULL);
+       } else {
+               /* We need this to allow modest to finish */
+               g_idle_add (notify_error_in_dbus_callback, NULL);
        }
+}
+
+
+static gint 
+on_send_receive(GArray *arguments, gpointer data, osso_rpc_t * retval)
+{      
+       TnyDevice *device = modest_runtime_get_device ();
+
+       if (!tny_device_is_online (device))
+               modest_platform_connect_and_perform (NULL, FALSE, NULL, on_send_receive_performer, NULL);
+       else
+               on_send_receive_performer (FALSE, NULL, NULL, NULL, NULL);
        
        return OSSO_OK;
 }
@@ -1239,12 +1279,42 @@ search_result_to_message (DBusMessage *reply,
        return reply;
 }
 
+typedef struct
+{
+       DBusConnection *con;
+       DBusMessage *message;
+       ModestSearch *search;
+} SearchHelper;
+
+static void
+search_all_cb (GList *hits, gpointer user_data)
+{
+       DBusMessage  *reply;
+       SearchHelper *helper = (SearchHelper *) user_data;
+
+       reply = dbus_message_new_method_return (helper->message);
+
+       if (reply) {
+               dbus_uint32_t serial = 0;
+               
+               search_result_to_message (reply, hits);
+
+               dbus_connection_send (helper->con, reply, &serial);
+               dbus_connection_flush (helper->con);
+               dbus_message_unref (reply);
+       }
+
+       /* Free the helper */
+       dbus_message_unref (helper->message);
+       modest_search_free (helper->search);
+       g_slice_free (ModestSearch, helper->search);
+       g_slice_free (SearchHelper, helper);
+}
 
 static void
 on_dbus_method_search (DBusConnection *con, DBusMessage *message)
 {
        ModestDBusSearchFlags dbus_flags;
-       DBusMessage  *reply = NULL;
        dbus_bool_t  res;
        dbus_int64_t sd_v;
        dbus_int64_t ed_v;
@@ -1254,9 +1324,9 @@ on_dbus_method_search (DBusConnection *con, DBusMessage *message)
        const char *query;
        time_t start_date;
        time_t end_date;
-       GList *hits;
-
+       ModestSearch *search;
        DBusError error;
+
        dbus_error_init (&error);
 
        sd_v = ed_v = 0;
@@ -1276,96 +1346,77 @@ on_dbus_method_search (DBusConnection *con, DBusMessage *message)
        start_date = (time_t) sd_v;
        end_date = (time_t) ed_v;
 
-       ModestSearch search;
-       memset (&search, 0, sizeof (search));
+       search = g_slice_new0 (ModestSearch);
        
-       /* Remember what folder we are searching in:
-        *
-        * Note that we don't copy the strings, 
-        * because this struct will only be used for the lifetime of this function.
-        */
        if (folder && g_str_has_prefix (folder, "MAND:")) {
-               search.folder = folder + strlen ("MAND:");
+               search->folder = g_strdup (folder + strlen ("MAND:"));
        } else if (folder && g_str_has_prefix (folder, "USER:")) {
-               search.folder = folder + strlen ("USER:");
+               search->folder = g_strdup (folder + strlen ("USER:"));
        } else if (folder && g_str_has_prefix (folder, "MY:")) {
-               search.folder = folder + strlen ("MY:");
+               search->folder = g_strdup (folder + strlen ("MY:"));
        } else {
-               search.folder = folder;
+               search->folder = g_strdup (folder);
        }
 
    /* Remember the text to search for: */
 #ifdef MODEST_HAVE_OGS
-       search.query  = query;
+       search->query  = g_strdup (query);
 #endif
 
        /* Other criteria: */
-       search.start_date = start_date;
-       search.end_date  = end_date;
-       search.flags  = 0;
+       search->start_date = start_date;
+       search->end_date  = end_date;
+       search->flags = 0;
 
        /* Text to serach for in various parts of the message: */
        if (dbus_flags & MODEST_DBUS_SEARCH_SUBJECT) {
-               search.flags |= MODEST_SEARCH_SUBJECT;
-               search.subject = query;
+               search->flags |= MODEST_SEARCH_SUBJECT;
+               search->subject = g_strdup (query);
        }
 
        if (dbus_flags & MODEST_DBUS_SEARCH_SENDER) {
-               search.flags |=  MODEST_SEARCH_SENDER;
-               search.from = query;
+               search->flags |=  MODEST_SEARCH_SENDER;
+               search->from = g_strdup (query);
        }
 
        if (dbus_flags & MODEST_DBUS_SEARCH_RECIPIENT) {
-               search.flags |= MODEST_SEARCH_RECIPIENT; 
-               search.recipient = query;
+               search->flags |= MODEST_SEARCH_RECIPIENT; 
+               search->recipient = g_strdup (query);
        }
 
        if (dbus_flags & MODEST_DBUS_SEARCH_BODY) {
-               search.flags |=  MODEST_SEARCH_BODY; 
-               search.body = query;
+               search->flags |=  MODEST_SEARCH_BODY; 
+               search->body = g_strdup (query);
        }
 
        if (sd_v > 0) {
-               search.flags |= MODEST_SEARCH_BEFORE;
-               search.start_date = start_date;
+               search->flags |= MODEST_SEARCH_BEFORE;
+               search->start_date = start_date;
        }
 
        if (ed_v > 0) {
-               search.flags |= MODEST_SEARCH_AFTER;
-               search.end_date = end_date;
+               search->flags |= MODEST_SEARCH_AFTER;
+               search->end_date = end_date;
        }
 
        if (size_v > 0) {
-               search.flags |= MODEST_SEARCH_SIZE;
-               search.minsize = size_v;
+               search->flags |= MODEST_SEARCH_SIZE;
+               search->minsize = size_v;
        }
 
 #ifdef MODEST_HAVE_OGS
-       search.flags |= MODEST_SEARCH_USE_OGS;
-       g_debug ("%s: Starting search for %s", __FUNCTION__, search.query);
+       search->flags |= MODEST_SEARCH_USE_OGS;
+       g_debug ("%s: Starting search for %s", __FUNCTION__, search->query);
 #endif
 
-       /* Note that this currently gets folders and messages from the servers, 
-        * which can take a long time. libmodest_dbus_client_search() can timeout, 
-        * reporting no results, if this takes a long time: */
-       hits = modest_search_all_accounts (&search);
-
-       reply = dbus_message_new_method_return (message);
-
-       search_result_to_message (reply, hits);
-
-       if (reply == NULL) {
-               g_warning ("%s: Could not create reply.", __FUNCTION__);
-       }
-
-       if (reply) {
-               dbus_uint32_t serial = 0;
-               dbus_connection_send (con, reply, &serial);
-       dbus_connection_flush (con);
-       dbus_message_unref (reply);
-       }
+       SearchHelper *helper = g_slice_new (SearchHelper);
+       helper->search = search;
+       dbus_message_ref (message);
+       helper->message = message;
+       helper->con = con;
 
-       g_list_free (hits);
+       /* Search asynchronously */
+       modest_search_all_accounts (search, search_all_cb, helper);
 }
 
 
@@ -1670,6 +1721,25 @@ on_dbus_method_get_folders (DBusConnection *con, DBusMessage *message)
 }
 
 
+static void
+reply_empty_results (DBusConnection *con, DBusMessage *msg)
+{
+       DBusMessage *reply = dbus_message_new_method_return (msg);
+       if (reply) {
+               dbus_uint32_t serial = 0;
+               /* we simply return an empty list, otherwise
+                  global-search gets confused */
+               search_result_to_message (reply, NULL);
+
+               dbus_connection_send (con, reply, &serial);
+               dbus_connection_flush (con);
+               dbus_message_unref (reply);
+       } else
+               g_warning ("%s: failed to send reply",
+                       __FUNCTION__);
+}
+
+
 /** This D-Bus handler is used when the main osso-rpc 
  * D-Bus handler has not handled something.
  * We use this for D-Bus methods that need to use more complex types 
@@ -1685,8 +1755,19 @@ modest_dbus_req_filter (DBusConnection *con,
        if (dbus_message_is_method_call (message,
                                         MODEST_DBUS_IFACE,
                                         MODEST_DBUS_METHOD_SEARCH)) {
-               on_dbus_method_search (con, message);
-               handled = TRUE;                         
+               
+       /* don't try to search when there not enough mem */
+               if (modest_platform_check_memory_low (NULL)) {
+                       g_warning ("%s: not enough memory for searching",
+                                  __FUNCTION__);
+                       reply_empty_results (con, message);
+                       handled = TRUE;
+
+               } else {
+                       on_dbus_method_search (con, message);
+                       handled = TRUE;
+               }
+                               
        } else if (dbus_message_is_method_call (message,
                                                MODEST_DBUS_IFACE,
                                                MODEST_DBUS_METHOD_GET_FOLDERS)) {
@@ -1742,7 +1823,7 @@ notify_error_in_dbus_callback (gpointer user_data)
 static gboolean
 notify_msg_not_found_in_idle (gpointer user_data)
 {
-       modest_platform_run_information_dialog (NULL, _("mail_ni_ui_folder_get_msg_folder_error"));
+       modest_platform_run_information_dialog (NULL, _("mail_ni_ui_folder_get_msg_folder_error"), FALSE);
 
        return FALSE;
 }