diff --git a/src/empathy-debug-window.c b/src/empathy-debug-window.c
index 97cda47..6c4c3ad 100644
--- a/src/empathy-debug-window.c
+++ b/src/empathy-debug-window.c
@@ -79,12 +79,15 @@ enum
   NUM_COLS_LEVEL
 };
 
+guint save_all_pending_calls;
+
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyDebugWindow)
 typedef struct
 {
   /* Toolbar items */
   GtkWidget *chooser;
   GtkToolItem *save_button;
+  GtkToolItem *save_all_button;
   GtkToolItem *copy_button;
   GtkToolItem *clear_button;
   GtkToolItem *pause_button;
@@ -229,54 +232,71 @@ debug_window_cache_new_message (EmpathyDebugWindow *debug_window,
 }
 
 static void
+split_domain_category (const gchar *domain_category,
+    gchar **domain_ptr,
+    gchar **category_ptr)
+{
+  if (g_strrstr (domain_category, "/"))
+    {
+      gchar **parts = g_strsplit (domain_category, "/", 2);
+      *domain_ptr = g_strdup (parts[0]);
+      *category_ptr = g_strdup (parts[1]);
+      g_strfreev (parts);
+    }
+  else
+    {
+      *domain_ptr = g_strdup (domain_category);
+      *category_ptr = g_strdup ("");
+    }
+}
+
+typedef enum
+{
+  UPDATE_CACHE = 1<<0,
+  UPDATE_UI = 1<<1,
+} MessageUpdateFlags;
+
+static void
 debug_window_add_message (EmpathyDebugWindow *debug_window,
-    gboolean should_cache,
+    MessageUpdateFlags update_flags,
     gdouble timestamp,
     const gchar *domain_category,
     guint level,
     const gchar *message)
 {
-  EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window);
-  gchar *domain, *category;
-  GtkTreeIter iter;
-  gchar *string;
-
-  if (should_cache)
+  if (update_flags & UPDATE_CACHE)
     debug_window_cache_new_message (debug_window, timestamp, domain_category,
         level, message);
 
-  if (g_strrstr (domain_category, "/"))
+  if (update_flags & UPDATE_UI)
     {
-      gchar **parts = g_strsplit (domain_category, "/", 2);
-      domain = g_strdup (parts[0]);
-      category = g_strdup (parts[1]);
-      g_strfreev (parts);
-    }
-  else
-    {
-      domain = g_strdup (domain_category);
-      category = g_strdup ("");
-    }
+      EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window);
+      gchar *domain, *category;
+      GtkTreeIter iter;
+      gchar *string;
 
-  if (g_str_has_suffix (message, "\n"))
-    string = g_strchomp (g_strdup (message));
-  else
-    string = g_strdup (message);
+      split_domain_category (domain_category, &domain, &category);
 
+      if (g_str_has_suffix (message, "\n"))
+        string = g_strchomp (g_strdup (message));
+      else
+        string = g_strdup (message);
 
-  gtk_list_store_append (priv->store, &iter);
-  gtk_list_store_set (priv->store, &iter,
-      COL_DEBUG_TIMESTAMP, timestamp,
-      COL_DEBUG_DOMAIN, domain,
-      COL_DEBUG_CATEGORY, category,
-      COL_DEBUG_LEVEL_STRING, log_level_to_string (level),
-      COL_DEBUG_MESSAGE, string,
-      COL_DEBUG_LEVEL_VALUE, level,
-      -1);
 
-  g_free (string);
-  g_free (domain);
-  g_free (category);
+      gtk_list_store_append (priv->store, &iter);
+      gtk_list_store_set (priv->store, &iter,
+          COL_DEBUG_TIMESTAMP, timestamp,
+          COL_DEBUG_DOMAIN, domain,
+          COL_DEBUG_CATEGORY, category,
+          COL_DEBUG_LEVEL_STRING, log_level_to_string (level),
+          COL_DEBUG_MESSAGE, string,
+          COL_DEBUG_LEVEL_VALUE, level,
+          -1);
+
+      g_free (string);
+      g_free (domain);
+      g_free (category);
+    }
 }
 
 static void
@@ -288,10 +308,8 @@ debug_window_new_debug_message_cb (TpProxy *proxy,
     gpointer user_data,
     GObject *weak_object)
 {
-  EmpathyDebugWindow *debug_window = (EmpathyDebugWindow *) user_data;
-
-  debug_window_add_message (debug_window, TRUE, timestamp, domain, level,
-      message);
+  debug_window_add_message (EMPATHY_DEBUG_WINDOW (weak_object),
+      GPOINTER_TO_UINT (user_data), timestamp, domain, level, message);
 }
 
 static void
@@ -317,6 +335,7 @@ debug_window_set_toolbar_sensitivity (EmpathyDebugWindow *debug_window,
   GtkWidget *vbox = gtk_bin_get_child (GTK_BIN (debug_window));
 
   gtk_widget_set_sensitive (GTK_WIDGET (priv->save_button), sensitive);
+  gtk_widget_set_sensitive (GTK_WIDGET (priv->save_all_button), sensitive);
   gtk_widget_set_sensitive (GTK_WIDGET (priv->copy_button), sensitive);
   gtk_widget_set_sensitive (GTK_WIDGET (priv->clear_button), sensitive);
   gtk_widget_set_sensitive (GTK_WIDGET (priv->pause_button), sensitive);
@@ -341,16 +360,93 @@ debug_window_set_toolbar_sensitivity (EmpathyDebugWindow *debug_window,
     }
 }
 
+static gchar *
+debug_window_format_timestamp (gdouble timestamp)
+{
+  struct tm *tstruct;
+  char time_str[32];
+  gint ms;
+  time_t sec;
+  gchar *text;
+
+  ms = (int) ((timestamp - (int) timestamp)*1e6);
+  sec = (long) timestamp;
+  tstruct = localtime ((time_t *) &sec);
+  if (!strftime (time_str, sizeof (time_str), "%x %T", tstruct))
+    {
+      DEBUG ("Failed to format timestamp: %e", timestamp);
+      time_str[0] = '\0';
+    }
+
+  text = g_strdup_printf ("%s.%d", time_str, ms);
+
+  return text;
+}
+
 static void
-debug_window_get_messages_cb (TpProxy *proxy,
+save_one_service_from_cache (const gchar *name,
+    GList *messages,
+    GFileOutputStream *output_stream)
+{
+  GList *l;
+
+  DEBUG ("Writing log messages for service:%s to file", name);
+
+  if (messages == NULL)
+      return;
+
+  for (l = messages; l != NULL; l = l->next)
+    {
+      gchar *domain, *category, *time_str, *line, *level_upper;
+      GError *error = NULL;
+      DebugMessage *dm = l->data;
+
+      split_domain_category (dm->domain, &domain, &category);
+
+      level_upper = g_ascii_strup (log_level_to_string (dm->level), -1);
+
+      time_str = debug_window_format_timestamp (dm->timestamp);
+
+      line = g_strdup_printf ("%s%s%s-%s: %s: %s\n",
+          domain, EMP_STR_EMPTY (category) ? "" : "/",
+          category, level_upper, time_str, dm->message);
+
+      g_free (time_str);
+
+      g_output_stream_write (G_OUTPUT_STREAM (output_stream), line,
+          strlen (line), NULL, &error);
+
+      if (error != NULL)
+        {
+          DEBUG ("Failed to write CM %s debug data to file: %s", name, error->message);
+          g_error_free (error);
+        }
+
+      g_free (line);
+      g_free (level_upper);
+      g_free (domain);
+      g_free (category);
+    }
+}
+
+typedef struct
+{
+  EmpathyDebugWindow *debug_window;
+  GFileOutputStream *output_stream;
+} DebugWindowGetMessagesData;
+
+static void
+debug_window_get_messages (TpProxy *proxy,
     const GPtrArray *messages,
     const GError *error,
     gpointer user_data,
-    GObject *weak_object)
+    const gchar *name,
+    MessageUpdateFlags update_flags)
 {
-  EmpathyDebugWindow *debug_window = (EmpathyDebugWindow *) user_data;
+  DebugWindowGetMessagesData *window_n_outstream =
+      (DebugWindowGetMessagesData *) user_data;
+  EmpathyDebugWindow *debug_window = window_n_outstream->debug_window;
   EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window);
-  gchar *name;
   GList *old_messages;
   guint i;
 
@@ -363,7 +459,6 @@ debug_window_get_messages_cb (TpProxy *proxy,
 
   debug_window_set_toolbar_sensitivity (debug_window, TRUE);
 
-  name = get_active_service_name (debug_window);
   old_messages = g_hash_table_lookup (priv->cache, name);
 
   /* we call get_messages either when a new CM is added or
@@ -376,11 +471,12 @@ debug_window_get_messages_cb (TpProxy *proxy,
       debug_message_list_free (old_messages);
     }
 
+  /* Adding each message in messages to cache and/or UI store */
   for (i = 0; i < messages->len; i++)
     {
       GValueArray *values = g_ptr_array_index (messages, i);
 
-      debug_window_add_message (debug_window, TRUE,
+      debug_window_add_message (debug_window, update_flags,
           g_value_get_double (g_value_array_get_nth (values, 0)),
           g_value_get_string (g_value_array_get_nth (values, 1)),
           g_value_get_uint (g_value_array_get_nth (values, 2)),
@@ -388,21 +484,84 @@ debug_window_get_messages_cb (TpProxy *proxy,
     }
 
   /* Connect to NewDebugMessage */
-  priv->new_debug_message_signal = emp_cli_debug_connect_to_new_debug_message (
-      proxy, debug_window_new_debug_message_cb, debug_window,
-      NULL, NULL, NULL);
+  priv->new_debug_message_signal =
+      emp_cli_debug_connect_to_new_debug_message (proxy,
+      debug_window_new_debug_message_cb, GUINT_TO_POINTER (update_flags),
+      NULL, G_OBJECT (debug_window), NULL);
+
+  if (window_n_outstream->output_stream != NULL)
+    {
+      if (save_all_pending_calls == 1)
+        {
+    	  /* Time to print logs for all services to output stream */
+    	  GError *error2 = NULL;
+
+          g_hash_table_foreach (priv->cache,
+              (GHFunc) save_one_service_from_cache,
+              window_n_outstream->output_stream);
+
+          g_output_stream_close (G_OUTPUT_STREAM
+              (window_n_outstream->output_stream), NULL, &error2);
+          if (error2 != NULL)
+            {
+              DEBUG ("Could not close the file output stream: %s",
+                  error2->message);
+              g_error_free (error2);
+            }
+
+          g_object_unref (window_n_outstream->output_stream);
+          g_slice_free (DebugWindowGetMessagesData, window_n_outstream);
+        }
+      else
+        {
+          save_all_pending_calls--;
+        }
+    }
+  else
+    {
+      g_slice_free (DebugWindowGetMessagesData, window_n_outstream);
+    }
 
   /* Set Enabled as appropriate */
   debug_window_set_enabled (debug_window, !priv->paused);
 }
 
 static void
+debug_window_get_messages_cb (TpProxy *proxy,
+    const GPtrArray *messages,
+    const GError *error,
+    gpointer user_data,
+    GObject *weak_object)
+{
+  const gchar *name = tp_proxy_get_bus_name (proxy);
+  MessageUpdateFlags update_flags = UPDATE_CACHE | UPDATE_UI;
+
+  debug_window_get_messages (proxy, messages, error,
+      user_data, name, update_flags);
+}
+
+static void
+debug_window_get_all_services_messages_cb (TpProxy *proxy,
+    const GPtrArray *messages,
+    const GError *error,
+    gpointer user_data,
+    GObject *weak_object)
+{
+  const gchar *name = tp_proxy_get_bus_name (proxy);
+  MessageUpdateFlags update_flags = UPDATE_CACHE;
+
+  debug_window_get_messages (proxy, messages, error,
+      user_data, name, update_flags);
+}
+
+static void
 debug_window_add_log_messages_from_cache (EmpathyDebugWindow *debug_window,
     const gchar *name)
 {
   GList *messages, *l;
   DebugMessage *dm;
   EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window);
+  MessageUpdateFlags update_flags;
 
   DEBUG ("Adding logs from cache for CM %s", name);
 
@@ -411,12 +570,13 @@ debug_window_add_log_messages_from_cache (EmpathyDebugWindow *debug_window,
   if (messages == NULL)
     return;
 
+  update_flags = UPDATE_UI;
   for (l = messages; l != NULL; l = l->next)
     {
       dm = l->data;
 
-      debug_window_add_message (debug_window, FALSE, dm->timestamp,
-          dm->domain, dm->level, dm->message);
+      debug_window_add_message (debug_window, update_flags,
+          dm->timestamp, dm->domain, dm->level, dm->message);
     }
 }
 
@@ -434,41 +594,15 @@ proxy_invalidated_cb (TpProxy *proxy,
 }
 
 static void
-debug_window_service_chooser_changed_cb (GtkComboBox *chooser,
-    EmpathyDebugWindow *debug_window)
+create_proxy_to_get_messages (DebugWindowGetMessagesData *data,
+    GtkTreeIter *iter,
+    emp_cli_debug_callback_for_get_messages get_messages_cb)
 {
-  EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window);
+  EmpathyDebugWindowPriv *priv = GET_PRIV (data->debug_window);
   TpDBusDaemon *dbus;
-  GError *error = NULL;
-  gchar *bus_name, *name = NULL;
   TpProxy *proxy;
-  GtkTreeIter iter;
-  gboolean gone;
-
-  if (!gtk_combo_box_get_active_iter (chooser, &iter))
-    {
-      DEBUG ("No CM is selected");
-      if (gtk_tree_model_iter_n_children (
-          GTK_TREE_MODEL (priv->service_store), NULL) > 0)
-        {
-          gtk_combo_box_set_active (chooser, 0);
-        }
-      return;
-    }
-
-  gtk_list_store_clear (priv->store);
-
-  gtk_tree_model_get (GTK_TREE_MODEL (priv->service_store), &iter,
-      COL_NAME, &name, COL_GONE, &gone, -1);
-
-  if (gone)
-    {
-      debug_window_add_log_messages_from_cache (debug_window, name);
-      g_free (name);
-      return;
-    }
-
-  g_free (name);
+  GError *error = NULL;
+  gchar *bus_name = NULL;
 
   dbus = tp_dbus_daemon_dup (&error);
 
@@ -477,7 +611,7 @@ debug_window_service_chooser_changed_cb (GtkComboBox *chooser,
       DEBUG ("Failed at duping the dbus daemon: %s", error->message);
     }
 
-  gtk_tree_model_get (GTK_TREE_MODEL (priv->service_store), &iter,
+  gtk_tree_model_get (GTK_TREE_MODEL (priv->service_store), iter,
       COL_UNIQUE_NAME, &bus_name, -1);
   proxy = g_object_new (TP_TYPE_PROXY,
       "bus-name", bus_name,
@@ -488,7 +622,7 @@ debug_window_service_chooser_changed_cb (GtkComboBox *chooser,
 
   /* Disable debug signalling */
   if (priv->proxy != NULL)
-    debug_window_set_enabled (debug_window, FALSE);
+    debug_window_set_enabled (data->debug_window, FALSE);
 
   /* Disconnect from previous NewDebugMessage signal */
   if (priv->new_debug_message_signal != NULL)
@@ -508,14 +642,57 @@ debug_window_service_chooser_changed_cb (GtkComboBox *chooser,
   tp_proxy_add_interface_by_id (priv->proxy, emp_iface_quark_debug ());
 
   emp_cli_debug_call_get_messages (priv->proxy, -1,
-      debug_window_get_messages_cb, debug_window, NULL, NULL);
+      get_messages_cb, data, NULL, NULL);
 
   priv->invalid_signal_id = g_signal_connect (proxy, "invalidated",
-      G_CALLBACK (proxy_invalidated_cb), debug_window);
+      G_CALLBACK (proxy_invalidated_cb), data->debug_window);
 
   g_object_unref (dbus);
 }
 
+static void
+debug_window_service_chooser_changed_cb (GtkComboBox *chooser,
+    EmpathyDebugWindow *debug_window)
+{
+  EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window);
+  gchar *name = NULL;
+  GtkTreeIter iter;
+  gboolean gone;
+  DebugWindowGetMessagesData *data;
+
+  if (!gtk_combo_box_get_active_iter (chooser, &iter))
+    {
+      DEBUG ("No CM is selected");
+      if (gtk_tree_model_iter_n_children (
+          GTK_TREE_MODEL (priv->service_store), NULL) > 0)
+        {
+          gtk_combo_box_set_active (chooser, 0);
+        }
+      return;
+    }
+
+  gtk_list_store_clear (priv->store);
+
+  gtk_tree_model_get (GTK_TREE_MODEL (priv->service_store), &iter,
+      COL_NAME, &name, COL_GONE, &gone, -1);
+
+  if (gone)
+    {
+      debug_window_add_log_messages_from_cache (debug_window, name);
+      g_free (name);
+      return;
+    }
+
+  g_free (name);
+
+  data = g_slice_new0 (DebugWindowGetMessagesData);
+
+  data->debug_window = debug_window;
+  data->output_stream = NULL;
+  create_proxy_to_get_messages (data, &iter,
+      debug_window_get_messages_cb);
+}
+
 typedef struct
 {
   const gchar *name;
@@ -1067,29 +1244,6 @@ debug_window_button_press_event_cb (GtkTreeView *view,
   return FALSE;
 }
 
-static gchar *
-debug_window_format_timestamp (gdouble timestamp)
-{
-  struct tm *tstruct;
-  char time_str[32];
-  gint ms;
-  time_t sec;
-  gchar *text;
-
-  ms = (int) ((timestamp - (int) timestamp)*1e6);
-  sec = (long) timestamp;
-  tstruct = localtime ((time_t *) &sec);
-  if (!strftime (time_str, sizeof (time_str), "%x %T", tstruct))
-    {
-      DEBUG ("Failed to format timestamp: %e", timestamp);
-      time_str[0] = '\0';
-    }
-
-  text = g_strdup_printf ("%s.%d", time_str, ms);
-
-  return text;
-}
-
 static void
 debug_window_time_formatter (GtkTreeViewColumn *tree_column,
     GtkCellRenderer *cell,
@@ -1109,113 +1263,130 @@ debug_window_time_formatter (GtkTreeViewColumn *tree_column,
   g_free (time_str);
 }
 
-static gboolean
-debug_window_store_filter_foreach (GtkTreeModel *model,
-    GtkTreePath *path,
-    GtkTreeIter *iter,
-    gpointer user_data)
+static GFileOutputStream *
+get_file_output_stream (const char *filename)
 {
-  GFileOutputStream *output_stream = (GFileOutputStream *) user_data;
-  gchar *domain, *category, *message, *level_str, *level_upper;
-  gdouble timestamp;
-  gchar *line, *time_str;
+  GFile *gfile = NULL;
   GError *error = NULL;
-  gboolean out = FALSE;
+  GFileOutputStream *output_stream = NULL;
 
-  gtk_tree_model_get (model, iter,
-      COL_DEBUG_TIMESTAMP, &timestamp,
-      COL_DEBUG_DOMAIN, &domain,
-      COL_DEBUG_CATEGORY, &category,
-      COL_DEBUG_LEVEL_STRING, &level_str,
-      COL_DEBUG_MESSAGE, &message,
-      -1);
+  gfile = g_file_new_for_path (filename);
+  output_stream = g_file_replace (gfile, NULL, FALSE,
+      G_FILE_CREATE_NONE, NULL, &error);
 
-  level_upper = g_ascii_strup (level_str, -1);
+  if (error != NULL)
+    {
+      DEBUG ("Failed to open file for writing: %s", error->message);
+      g_error_free (error);
+    }
 
-  time_str = debug_window_format_timestamp (timestamp);
+  g_object_unref (gfile);
+  return output_stream;
+}
 
-  line = g_strdup_printf ("%s%s%s-%s: %s: %s\n",
-      domain, EMP_STR_EMPTY (category) ? "" : "/",
-      category, level_upper, time_str, message);
+static void
+debug_window_save_file_chooser_response_cb (GtkDialog *dialog,
+    gint response_id,
+    EmpathyDebugWindow *debug_window)
+{
+  EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window);
+  GList *messages;
+  gchar *filename = NULL;
+  const gchar *name;
+  GFileOutputStream *output_stream = NULL;
 
-  g_free (time_str);
+  if (response_id != GTK_RESPONSE_ACCEPT)
+    goto finally;
 
-  g_output_stream_write (G_OUTPUT_STREAM (output_stream), line,
-      strlen (line), NULL, &error);
+  /* getting cached message list for active service */
+  name = get_active_service_name (debug_window);
+  messages = g_hash_table_lookup (priv->cache, name);
 
-  if (error != NULL)
+  /* getting output stream */
+  filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+
+  DEBUG ("Saving log for CM %s in %s",name, filename);
+
+  output_stream = get_file_output_stream (filename);
+  if (output_stream == NULL)
     {
-      DEBUG ("Failed to write to file: %s", error->message);
-      g_error_free (error);
-      out = TRUE;
+      goto finally;
     }
 
-  g_free (line);
-  g_free (level_upper);
-  g_free (level_str);
-  g_free (domain);
-  g_free (category);
-  g_free (message);
+  /* writing list to output stream */
+  save_one_service_from_cache (name, messages, output_stream);
+
+finally:
+  if (output_stream != NULL)
+    g_object_unref (output_stream);
+
+  g_free (filename);
 
-  return out;
+  gtk_widget_destroy (GTK_WIDGET (dialog));
 }
 
 static void
-debug_window_save_file_chooser_response_cb (GtkDialog *dialog,
+debug_window_save_all_file_chooser_response_cb (GtkDialog *dialog,
     gint response_id,
     EmpathyDebugWindow *debug_window)
 {
   EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window);
   gchar *filename = NULL;
-  GFile *gfile = NULL;
+  GtkTreeIter iter;
   GFileOutputStream *output_stream = NULL;
-  GError *error = NULL;
+  DebugWindowGetMessagesData *data;
 
   if (response_id != GTK_RESPONSE_ACCEPT)
-    goto OUT;
+    goto finally;
 
+  /* Getting output stream */
   filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
 
-  DEBUG ("Saving log as %s", filename);
-
-  gfile = g_file_new_for_path (filename);
-  output_stream = g_file_replace (gfile, NULL, FALSE,
-      G_FILE_CREATE_NONE, NULL, &error);
+  DEBUG ("Saving logs for all services in %s", filename);
 
-  if (error != NULL)
+  output_stream = get_file_output_stream (filename);
+  if (output_stream == NULL)
     {
-      DEBUG ("Failed to open file for writing: %s", error->message);
-      g_error_free (error);
-      goto OUT;
+      goto finally;
     }
 
-  gtk_tree_model_foreach (priv->store_filter,
-      debug_window_store_filter_foreach, output_stream);
+  /* Loading cache with messages for each service */
+  data = g_slice_new (DebugWindowGetMessagesData);
 
-OUT:
-  if (gfile != NULL)
-    g_object_unref (gfile);
+  data->debug_window = debug_window;
+  data->output_stream = output_stream;
 
-  if (output_stream != NULL)
-    g_object_unref (output_stream);
+  save_all_pending_calls = 0;
 
-  if (filename != NULL)
-    g_free (filename);
+  if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->service_store),
+      &iter))
+  while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->service_store),
+      &iter))
+    {
+      create_proxy_to_get_messages (data, &iter,
+          debug_window_get_all_services_messages_cb);
+      save_all_pending_calls++;
+    }
+
+finally:
+  g_free (filename);
 
   gtk_widget_destroy (GTK_WIDGET (dialog));
 }
 
 static void
-debug_window_save_clicked_cb (GtkToolButton *tool_button,
+create_save_file_chooser (gchar *title,
+    gchar *name,
+    GCallback file_chooser_response_cb,
     EmpathyDebugWindow *debug_window)
 {
   GtkWidget *file_chooser;
-  gchar *name, *tmp = NULL;
+  gchar *tmp = NULL;
   char time_str[32];
   time_t t;
   struct tm *tm_s;
 
-  file_chooser = gtk_file_chooser_dialog_new (_("Save"),
+  file_chooser = gtk_file_chooser_dialog_new (_(title),
       GTK_WINDOW (debug_window), GTK_FILE_CHOOSER_ACTION_SAVE,
       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
       GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
@@ -1228,8 +1399,6 @@ debug_window_save_clicked_cb (GtkToolButton *tool_button,
   gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (file_chooser),
       g_get_tmp_dir ());
 
-  name = get_active_service_name (debug_window);
-
   t = time (NULL);
   tm_s = localtime (&t);
   if (tm_s != NULL)
@@ -1240,18 +1409,38 @@ debug_window_save_clicked_cb (GtkToolButton *tool_button,
 
   if (tmp == NULL)
     tmp = g_strdup_printf ("%s.log", name);
-  g_free (name);
 
   gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (file_chooser), tmp);
   g_free (tmp);
 
   g_signal_connect (file_chooser, "response",
-      G_CALLBACK (debug_window_save_file_chooser_response_cb),
+      file_chooser_response_cb,
       debug_window);
 
   gtk_widget_show (file_chooser);
 }
 
+static void
+debug_window_save_clicked_cb (GtkToolButton *tool_button,
+    EmpathyDebugWindow *debug_window)
+{
+  gchar *name;
+  name = get_active_service_name (debug_window);
+
+  create_save_file_chooser("Save", name,
+      G_CALLBACK (debug_window_save_file_chooser_response_cb), debug_window);
+}
+
+static void
+debug_window_save_all_clicked_cb (GtkToolButton *tool_button,
+    EmpathyDebugWindow *debug_window)
+{
+  gchar *name = "empathy_debug_full";
+
+  create_save_file_chooser("Save all", name,
+      G_CALLBACK (debug_window_save_all_file_chooser_response_cb), debug_window);
+}
+
 static gboolean
 debug_window_copy_model_foreach (GtkTreeModel *model,
     GtkTreePath *path,
@@ -1441,6 +1630,17 @@ am_prepared_cb (GObject *am,
   gtk_tool_item_set_is_important (GTK_TOOL_ITEM (priv->save_button), TRUE);
   gtk_toolbar_insert (GTK_TOOLBAR (toolbar), priv->save_button, -1);
 
+  /* Save all */
+  image = gtk_image_new_from_stock (GTK_STOCK_SAVE,
+      GTK_ICON_SIZE_MENU);
+  gtk_widget_show (image);
+  priv->save_all_button = gtk_tool_button_new (image, _("Save all"));
+  g_signal_connect (priv->save_all_button, "clicked",
+      G_CALLBACK (debug_window_save_all_clicked_cb), object);
+  gtk_widget_show (GTK_WIDGET (priv->save_all_button));
+  gtk_tool_item_set_is_important (GTK_TOOL_ITEM (priv->save_all_button), TRUE);
+  gtk_toolbar_insert (GTK_TOOLBAR (toolbar), priv->save_all_button, -1);
+
   /* Copy */
   priv->copy_button = gtk_tool_button_new_from_stock (GTK_STOCK_COPY);
   g_signal_connect (priv->copy_button, "clicked",
