29a03eb661d96311264b082f46b024fd4a51280c
diff --git a/src/window-commands.c b/src/window-commands.c
index 6494ea2..e103010 100644
--- a/src/window-commands.c
+++ b/src/window-commands.c
@@ -1,6 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  *  Copyright © 2000-2004 Marco Pesenti Gritti
+ *  Copyright © 2009 Collabora Ltd.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -595,29 +596,147 @@ window_cmd_view_zoom_normal (GtkAction *action,
 }
 
 static void
-save_source_completed_cb (EphyEmbedPersist *persist)
+save_temp_source_error_response_cb (GtkWidget *dialog, gint response_id, gpointer user_data)
 {
-	const char *dest;
-	guint32 user_time;
+	gtk_widget_destroy (dialog);
+}
+
+static void
+save_temp_source_write_display_error (GError *error, EphyEmbed *embed)
+{
+	EphyWebView *view;
+	GtkWidget *parent_window;
+	GtkWidget *dialog;
+
+	view = ephy_embed_get_web_view (embed);
+	parent_window = gtk_widget_get_toplevel (GTK_WIDGET (view));
+
+	if (!GTK_WIDGET_TOPLEVEL (parent_window))
+		parent_window = NULL;
+
+	dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (parent_window),
+						     GTK_DIALOG_DESTROY_WITH_PARENT,
+						     GTK_MESSAGE_ERROR,
+						     GTK_BUTTONS_CLOSE,
+						     _("<b>Failure creating temporary file.</b>"));
+
+	gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
+						    _("Saving the current page's contents to a "
+						      "temporary file for display was not possible:\n"
+						      "%s"), error->message);
+
+	g_signal_connect (dialog, "response", G_CALLBACK (save_temp_source_error_response_cb), NULL);
+
+	gtk_widget_show_all (dialog);
+}
+
+static void
+save_temp_source_close_cb (GOutputStream *ostream, GAsyncResult *result, GString *data)
+{
+	char *uri;
 	GFile *file;
+	GError *error = NULL;
 
-	user_time = ephy_embed_persist_get_user_time (persist);
-	dest = ephy_embed_persist_get_dest (persist);
-	g_return_if_fail (dest != NULL);
+	g_output_stream_close_finish (ostream, result, &error);
+	if (error) {
+		EphyEmbed *embed = (EphyEmbed*)g_object_get_data (G_OBJECT (ostream),
+								  "ephy-save-temp-source-embed");
+		save_temp_source_write_display_error (error, embed);
+		g_error_free (error);
+		return;
+	}
 
-	file = g_file_new_for_path (dest);
-	ephy_file_delete_on_exit (file);
+	uri = (char*)g_object_get_data (G_OBJECT (ostream), "ephy-save-temp-source-uri");
+	file = g_file_new_for_uri (uri);
+	ephy_file_launch_handler ("text/plain", file, gtk_get_current_event_time ());
 
-	ephy_file_launch_handler ("text/plain", file, user_time);
+	g_free (uri);
 	g_object_unref (file);
 }
 
 static void
+save_temp_source_write_cb (GOutputStream *ostream, GAsyncResult *result, GString *data)
+{
+	GError *error = NULL;
+	gssize written;
+
+	written = g_output_stream_write_finish (ostream, result, &error);
+	if (error) {
+		g_string_free (data, FALSE);
+		g_critical ("Unable to write to file: %s", error->message);
+		g_error_free (error);
+		return;
+	}
+
+	if (written == data->len) {
+		g_output_stream_close_async (ostream, G_PRIORITY_DEFAULT, NULL,
+					     (GAsyncReadyCallback)save_temp_source_close_cb,
+					     NULL);
+		return;
+	}
+
+	data->len -= written;
+	data->str += written;
+
+	g_output_stream_write_async (ostream,
+				     data->str, data->len,
+				     G_PRIORITY_DEFAULT, NULL,
+				     (GAsyncReadyCallback)save_temp_source_write_cb,
+				     data);
+}
+
+static void
+save_temp_source_replace_cb (GFile *file, GAsyncResult *result, EphyEmbed *embed)
+{
+	EphyWebView *view;
+	WebKitWebFrame *frame;
+	WebKitWebDataSource *data_source;
+	const GString *const_data;
+	GString *data;
+	GFileOutputStream *ostream;
+	GError *error = NULL;
+
+	ostream = g_file_replace_finish (file, result, &error);
+	if (error) {
+		EphyEmbed *embed = (EphyEmbed*)g_object_get_data (G_OBJECT (ostream),
+								  "ephy-save-temp-source-embed");
+		save_temp_source_write_display_error (error, embed);
+		g_error_free (error);
+		return;
+	}
+
+	g_object_set_data (G_OBJECT (ostream),
+			   "ephy-save-temp-source-uri",
+			   g_file_get_uri (file));
+
+	g_object_set_data (G_OBJECT (ostream),
+			   "ephy-save-temp-source-embed",
+			   embed);
+
+	view = ephy_embed_get_web_view (embed);
+	frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (view));
+	data_source = webkit_web_frame_get_data_source (frame);
+	const_data = webkit_web_data_source_get_data (data_source);
+
+	/* We create a new GString here because we need to make sure
+	 * we keep writing in case of partial writes */
+	data = g_string_sized_new (const_data->len);
+	data->str = const_data->str;
+	data->len = const_data->len;
+
+	g_output_stream_write_async (G_OUTPUT_STREAM (ostream),
+				     data->str, data->len,
+				     G_PRIORITY_DEFAULT, NULL,
+				     (GAsyncReadyCallback)save_temp_source_write_cb,
+				     data);
+}
+
+static void
 save_temp_source (EphyEmbed *embed,
 		  guint32 user_time)
 {
+	GFile *file;
 	char *tmp, *base;
-	EphyEmbedPersist *persist;
 	const char *static_temp_dir;
 
 	static_temp_dir = ephy_file_tmp_dir ();
@@ -634,20 +753,12 @@ save_temp_source (EphyEmbed *embed,
 		return;
 	}
 
-	persist = EPHY_EMBED_PERSIST
-		(g_object_new (EPHY_TYPE_EMBED_PERSIST, NULL));
-
-	ephy_embed_persist_set_embed (persist, embed);
-	ephy_embed_persist_set_flags (persist, EPHY_EMBED_PERSIST_COPY_PAGE |
-				      EPHY_EMBED_PERSIST_NO_VIEW);
-	ephy_embed_persist_set_dest (persist, tmp);
-	ephy_embed_persist_set_user_time (persist, user_time);
-
-	g_signal_connect (persist, "completed",
-			  G_CALLBACK (save_source_completed_cb), NULL);
-
-	ephy_embed_persist_save (persist);
-	g_object_unref (persist);
+	file = g_file_new_for_path (tmp);
+	g_file_replace_async (file, NULL, FALSE,
+			      G_FILE_CREATE_REPLACE_DESTINATION|G_FILE_CREATE_PRIVATE,
+			      G_PRIORITY_DEFAULT, NULL,
+			      (GAsyncReadyCallback)save_temp_source_replace_cb,
+			      embed);
 
 	g_free (tmp);
 }
