aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2012-10-08 17:19:01 +0800
committerCarlos Garcia Campos <cgarcia@igalia.com>2013-01-09 00:38:01 +0800
commit12415ad405dc6a9bcc42bd693d22c9b857e9bab3 (patch)
tree16d65bfdc561fe20971de92b9ef8cc76b099a6d1
parentd7e638c985039dc4521273846bbbac7295564b87 (diff)
downloadgsoc2013-epiphany-12415ad405dc6a9bcc42bd693d22c9b857e9bab3.tar
gsoc2013-epiphany-12415ad405dc6a9bcc42bd693d22c9b857e9bab3.tar.gz
gsoc2013-epiphany-12415ad405dc6a9bcc42bd693d22c9b857e9bab3.tar.bz2
gsoc2013-epiphany-12415ad405dc6a9bcc42bd693d22c9b857e9bab3.tar.lz
gsoc2013-epiphany-12415ad405dc6a9bcc42bd693d22c9b857e9bab3.tar.xz
gsoc2013-epiphany-12415ad405dc6a9bcc42bd693d22c9b857e9bab3.tar.zst
gsoc2013-epiphany-12415ad405dc6a9bcc42bd693d22c9b857e9bab3.zip
ephy-session: Load the session asynchronously
Make ephy_session_load() asynchronous and add ephy_session_load_from_stream() to replace ephy_session_load_from_string(). Use a xml sax parser now that is fed from a GInputStream. https://bugzilla.gnome.org/show_bug.cgi?id=681782
-rw-r--r--src/ephy-session.c689
-rw-r--r--src/ephy-session.h54
-rw-r--r--tests/ephy-session-test.c37
3 files changed, 558 insertions, 222 deletions
diff --git a/src/ephy-session.c b/src/ephy-session.c
index 044b75414..36008054d 100644
--- a/src/ephy-session.c
+++ b/src/ephy-session.c
@@ -351,7 +351,7 @@ session_command_dispatch (EphySession *session)
session_command_autoresume (session, cmd->user_time);
break;
case EPHY_SESSION_CMD_LOAD_SESSION:
- ephy_session_load (session, cmd->arg, cmd->user_time);
+ ephy_session_load (session, cmd->arg, cmd->user_time, NULL, NULL, NULL);
break;
case EPHY_SESSION_CMD_OPEN_URIS:
session_command_open_uris (session, cmd->args, cmd->arg, cmd->user_time);
@@ -768,7 +768,7 @@ out:
}
static void
-confirm_before_recover (EphyWindow* window, char* url, char* title)
+confirm_before_recover (EphyWindow *window, const char *url, const char *title)
{
EphyEmbed *embed;
@@ -781,266 +781,563 @@ confirm_before_recover (EphyWindow* window, char* url, char* title)
EPHY_WEB_VIEW_ERROR_PAGE_CRASH, NULL);
}
-static void
-parse_embed (xmlNodePtr child,
- EphyWindow *window,
- EphySession *session)
+static void
+restore_geometry (GtkWindow *window,
+ GdkRectangle *geometry)
{
- while (child != NULL)
+ if (geometry->x >= 0 && geometry->y >= 0)
+ {
+ gtk_window_move (window, geometry->x, geometry->y);
+ }
+
+ if (geometry->width > 0 && geometry->height > 0)
+ {
+ gtk_window_set_default_size (window, geometry->width, geometry->height);
+ }
+}
+
+typedef struct {
+ EphySession *session;
+ guint32 user_time;
+
+ EphyWindow *window;
+ gboolean is_first_window;
+ gint active_tab;
+
+ gboolean is_first_tab;
+} SessionParserContext;
+
+static SessionParserContext *
+session_parser_context_new (EphySession *session,
+ guint32 user_time)
+{
+ SessionParserContext *context;
+
+ context = g_slice_new0 (SessionParserContext);
+ context->session = g_object_ref (session);
+ context->user_time = user_time;
+ context->is_first_window = TRUE;
+
+ return context;
+}
+
+static void
+session_parser_context_free (SessionParserContext *context)
+{
+ g_object_unref (context->session);
+
+ g_slice_free (SessionParserContext, context);
+}
+
+static void
+session_parse_window (SessionParserContext *context,
+ const gchar **names,
+ const gchar **values)
+{
+ GdkRectangle geometry = { -1, -1, 0, 0 };
+ guint i;
+
+ context->window = ephy_window_new ();
+
+ for (i = 0; names[i]; i++)
{
- if (strcmp ((char *) child->name, "embed") == 0)
+ gulong int_value;
+
+ if (strcmp (names[i], "x") == 0)
{
- xmlChar *url, *attr;
- char *recover_url;
- gboolean was_loading;
-
- g_return_if_fail (window != NULL);
-
- /* Check if that tab wasn't fully loaded yet
- * when the session crashed. */
- attr = xmlGetProp (child, (const xmlChar *) "loading");
- was_loading = attr != NULL &&
- xmlStrEqual (attr, (const xmlChar *) "true");
- xmlFree (attr);
-
- url = xmlGetProp (child, (const xmlChar *) "url");
- if (url == NULL)
- continue;
-
- /* In the case that crash happens before we receive the URL from the server, this will
- open an about:blank tab. See http://bugzilla.gnome.org/show_bug.cgi?id=591294
- Otherwise, if the web was fully loaded, it is reloaded again. */
- if (!was_loading ||
- strcmp ((const char *) url, "about:blank") == 0 ||
- strcmp ((const char *) url, "about:overview") == 0)
- {
- recover_url = (char *) url;
-
- ephy_shell_new_tab (ephy_shell_get_default (),
- window, NULL, recover_url,
- EPHY_NEW_TAB_IN_EXISTING_WINDOW |
- EPHY_NEW_TAB_OPEN_PAGE |
- EPHY_NEW_TAB_APPEND_LAST);
- }
- else if (was_loading)
- {
- /* Shows a message to the user that warns that this page was
- loading during crash and make Epiphany crash again,
- in this case we know the URL. */
- xmlChar* title = xmlGetProp (child, (const xmlChar *) "title");
-
- confirm_before_recover (window, (char*) url, (char*) title);
-
- if (title)
- xmlFree (title);
- }
+ ephy_string_to_int (values[i], &int_value);
+ geometry.x = int_value;
+ }
+ else if (strcmp (names[i], "y") == 0)
+ {
+ ephy_string_to_int (values[i], &int_value);
+ geometry.y = int_value;
+ }
+ else if (strcmp (names[i], "width") == 0)
+ {
+ ephy_string_to_int (values[i], &int_value);
+ geometry.width = int_value;
+ }
+ else if (strcmp (names[i], "height") == 0)
+ {
+ ephy_string_to_int (values[i], &int_value);
+ geometry.height = int_value;
+ }
+ else if (strcmp (names[i], "role") == 0)
+ {
+ gtk_window_set_role (GTK_WINDOW (context->window), values[i]);
+ }
+ else if (strcmp (names[i], "active-tab") == 0)
+ {
+ ephy_string_to_int (values[i], &int_value);
+ context->active_tab = int_value;
+ }
+ }
+
+ restore_geometry (GTK_WINDOW (context->window), &geometry);
+ ephy_gui_window_update_user_time (GTK_WIDGET (context->window), context->user_time);
+}
+
+static void
+session_parse_embed (SessionParserContext *context,
+ const gchar **names,
+ const gchar **values)
+{
+ const char *url = NULL;
+ const char *title = NULL;
+ gboolean was_loading = FALSE;
+ gboolean is_blank_page = FALSE;
+ guint i;
- xmlFree (url);
+ for (i = 0; names[i]; i++)
+ {
+ if (strcmp (names[i], "url") == 0)
+ {
+ url = values[i];
+ is_blank_page = (strcmp (url, "about:blank") == 0 ||
+ strcmp (url, "about:overview") == 0);
}
+ else if (strcmp (names[i], "title") == 0)
+ {
+ title = values[i];
+ }
+ else if (strcmp (names[i], "loading") == 0)
+ {
+ was_loading = strcmp (values[i], "true") == 0;
+ }
+ }
- child = child->next;
+ /* In the case that crash happens before we receive the URL from the server,
+ * this will open an about:blank tab.
+ * See http://bugzilla.gnome.org/show_bug.cgi?id=591294
+ * Otherwise, if the web was fully loaded, it is reloaded again.
+ */
+ if (!was_loading || is_blank_page)
+ {
+ ephy_shell_new_tab (ephy_shell_get_default (),
+ context->window, NULL, url,
+ EPHY_NEW_TAB_IN_EXISTING_WINDOW |
+ EPHY_NEW_TAB_OPEN_PAGE |
+ EPHY_NEW_TAB_APPEND_LAST);
+ }
+ else if (was_loading && url != NULL)
+ {
+ /* Shows a message to the user that warns that this page was
+ * loading during crash and make Epiphany crash again,
+ * in this case we know the URL.
+ */
+ confirm_before_recover (context->window, url, title);
}
}
static void
-restore_geometry (GtkWindow *window,
- xmlNodePtr node)
+session_start_element (GMarkupParseContext *ctx,
+ const gchar *element_name,
+ const gchar **names,
+ const gchar **values,
+ gpointer user_data,
+ GError **error)
+{
+ SessionParserContext *context = (SessionParserContext *)user_data;
+
+ if (strcmp (element_name, "window") == 0)
+ {
+ session_parse_window (context, names, values);
+ context->is_first_tab = TRUE;
+ }
+ else if (strcmp (element_name, "embed") == 0)
+ {
+ session_parse_embed (context, names, values);
+ }
+}
+
+static void
+session_end_element (GMarkupParseContext *ctx,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+ SessionParserContext *context = (SessionParserContext *)user_data;
+
+ if (strcmp (element_name, "window") == 0)
+ {
+ GtkWidget *notebook;
+
+ notebook = ephy_window_get_notebook (context->window);
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), context->active_tab);
+
+ if (ephy_embed_shell_get_mode (ephy_embed_shell_get_default ()) != EPHY_EMBED_SHELL_MODE_TEST)
+ {
+ EphyEmbed *active_child;
+
+ active_child = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (context->window));
+ gtk_widget_grab_focus (GTK_WIDGET (active_child));
+ gtk_widget_show (GTK_WIDGET (context->window));
+ }
+
+ context->window = NULL;
+ context->active_tab = 0;
+ context->is_first_window = FALSE;
+ }
+ else if (strcmp (element_name, "embed") == 0)
+ {
+ context->is_first_tab = FALSE;
+ }
+}
+
+static const GMarkupParser session_parser = {
+ session_start_element,
+ session_end_element,
+ NULL,
+ NULL,
+ NULL
+};
+
+typedef struct {
+ EphyShell *shell;
+ GMarkupParseContext *parser;
+ GCancellable *cancellable;
+ char buffer[1024];
+} LoadFromStreamAsyncData;
+
+static LoadFromStreamAsyncData *
+load_from_stream_async_data_new (GMarkupParseContext *parser,
+ GCancellable *cancellable)
+{
+ LoadFromStreamAsyncData *data;
+
+ data = g_slice_new (LoadFromStreamAsyncData);
+ data->shell = g_object_ref (ephy_shell_get_default ());
+ data->parser = parser;
+ data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+
+ return data;
+}
+
+static void
+load_from_stream_async_data_free (LoadFromStreamAsyncData *data)
+{
+ g_object_unref (data->shell);
+ g_markup_parse_context_free (data->parser);
+ g_clear_object (&data->cancellable);
+
+ g_slice_free (LoadFromStreamAsyncData, data);
+}
+
+static void
+load_stream_complete (GSimpleAsyncResult *simple)
+{
+ EphySession *session;
+
+ g_simple_async_result_complete (simple);
+
+ session = EPHY_SESSION (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
+ session->priv->dont_save = FALSE;
+
+ ephy_session_save (session, SESSION_STATE);
+ g_object_unref (session);
+
+ g_object_unref (simple);
+
+ g_application_release (G_APPLICATION (ephy_shell_get_default ()));
+}
+
+static void
+load_stream_complete_error (GSimpleAsyncResult *simple,
+ GError *error)
{
- xmlChar *tmp;
- gulong x = 0, y = 0, width = 0, height = 0;
- gboolean success = TRUE;
-
- g_return_if_fail (window != NULL);
-
- tmp = xmlGetProp (node, (xmlChar *) "x");
- success &= ephy_string_to_int ((char *) tmp, &x);
- xmlFree (tmp);
- tmp = xmlGetProp (node, (xmlChar *) "y");
- success &= ephy_string_to_int ((char *) tmp, &y);
- xmlFree (tmp);
- tmp = xmlGetProp (node, (xmlChar *) "width");
- success &= ephy_string_to_int ((char *) tmp, &width);
- xmlFree (tmp);
- tmp = xmlGetProp (node, (xmlChar *) "height");
- success &= ephy_string_to_int ((char *) tmp, &height);
- xmlFree (tmp);
-
- if (success)
+ EphySession *session;
+ LoadFromStreamAsyncData *data;
+ SessionParserContext *context;
+
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+
+ session = EPHY_SESSION (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
+ session->priv->dont_save = FALSE;
+ /* If the session fails to load for whatever reason,
+ * delete the file and open an empty window.
+ */
+ session_delete (session, SESSION_STATE);
+
+ data = g_simple_async_result_get_op_res_gpointer (simple);
+ context = (SessionParserContext *)g_markup_parse_context_get_user_data (data->parser);
+ ephy_session_queue_command (session,
+ EPHY_SESSION_CMD_MAYBE_OPEN_WINDOW,
+ NULL, NULL, context->user_time, FALSE);
+ g_object_unref (session);
+
+ g_object_unref (simple);
+
+ g_application_release (G_APPLICATION (ephy_shell_get_default ()));
+}
+
+static void
+load_stream_read_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GInputStream *stream = G_INPUT_STREAM (object);
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+ LoadFromStreamAsyncData *data;
+ gssize bytes_read;
+ GError *error = NULL;
+
+ bytes_read = g_input_stream_read_finish (stream, result, &error);
+ if (bytes_read < 0)
{
- tmp = xmlGetProp (node, (xmlChar *)"role");
- if (tmp != NULL)
+ load_stream_complete_error (simple, error);
+
+ return;
+ }
+
+ data = g_simple_async_result_get_op_res_gpointer (simple);
+ if (bytes_read == 0)
+ {
+ if (!g_markup_parse_context_end_parse (data->parser, &error))
+ {
+ load_stream_complete_error (simple, error);
+ }
+ else
{
- gtk_window_set_role (GTK_WINDOW (window), (const char *)tmp);
- xmlFree (tmp);
+ load_stream_complete (simple);
}
- gtk_window_move (window, x, y);
- gtk_window_set_default_size (window, width, height);
+ return;
+ }
+
+ if (!g_markup_parse_context_parse (data->parser, data->buffer, bytes_read, &error))
+ {
+ load_stream_complete_error (simple, error);
+
+ return;
}
+
+ g_input_stream_read_async (stream, data->buffer, sizeof (data->buffer),
+ G_PRIORITY_HIGH, data->cancellable,
+ load_stream_read_cb, simple);
}
/**
- * ephy_session_load_from_string:
+ * ephy_session_load_from_stream:
* @session: an #EphySession
- * @session_data: a string with the session data to load
- * @length: the length of @session_data, or -1 to assume %NULL terminated
+ * @stream: a #GInputStream to read the session data from
* @user_time: a user time, or 0
- *
- * Loads the session described in @session_data, restoring windows and
- * their state.
- *
- * Returns: TRUE if at least a window has been opened
+ * @cancellable: (allow-none): optional #GCancellable object, or %NULL
+ * @callback: (scope async): a #GAsyncReadyCallback to call when the
+ * request is satisfied
+ * @user_data: (closure): the data to pass to callback function
+ *
+ * Asynchronously loads the session reading the session data from @stream,
+ * restoring windows and their state.
+ *
+ * When the operation is finished, @callback will be called. You can
+ * then call ephy_session_load_from_stream_finish() to get the result of
+ * the operation.
**/
-gboolean
-ephy_session_load_from_string (EphySession *session,
- const char *session_data,
- gssize length,
- guint32 user_time)
+void
+ephy_session_load_from_stream (EphySession *session,
+ GInputStream *stream,
+ guint32 user_time,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- EphySessionPrivate *priv;
- EphyShell *shell;
- xmlDocPtr doc;
- xmlNodePtr child;
- EphyWindow *window;
- GtkWidget *widget = NULL;
- gboolean retval;
+ GSimpleAsyncResult *result;
+ SessionParserContext *context;
+ GMarkupParseContext *parser;
+ LoadFromStreamAsyncData *data;
- g_return_val_if_fail (EPHY_IS_SESSION (session), FALSE);
- g_return_val_if_fail (session_data, FALSE);
+ g_return_if_fail (EPHY_IS_SESSION (session));
+ g_return_if_fail (G_IS_INPUT_STREAM (stream));
- priv = session->priv;
+ g_application_hold (G_APPLICATION (ephy_shell_get_default ()));
- /* If length is -1 assume the data is a NULL-terminated, UTF-8
- * encoded string. */
- if (length == -1)
- length = g_utf8_strlen (session_data, -1);
+ session->priv->dont_save = TRUE;
- doc = xmlParseMemory (session_data, (int)length);
+ result = g_simple_async_result_new (G_OBJECT (session), callback, user_data, ephy_session_load_from_stream);
- if (doc == NULL)
- {
- /* If the session fails to load for whatever reason,
- * delete the file and open an empty window. */
- session_delete (session, SESSION_STATE);
- ephy_session_queue_command (session,
- EPHY_SESSION_CMD_MAYBE_OPEN_WINDOW,
- NULL, NULL, user_time, FALSE);
- return FALSE;
- }
+ context = session_parser_context_new (session, user_time);
+ parser = g_markup_parse_context_new (&session_parser, 0, context, (GDestroyNotify)session_parser_context_free);
+ data = load_from_stream_async_data_new (parser, cancellable);
+ g_simple_async_result_set_op_res_gpointer (result, data, (GDestroyNotify)load_from_stream_async_data_free);
- shell = g_object_ref (ephy_shell_get_default ());
+ g_input_stream_read_async (stream, data->buffer, sizeof (data->buffer), G_PRIORITY_HIGH, cancellable,
+ load_stream_read_cb, result);
+}
- priv->dont_save = TRUE;
+/**
+ * ephy_session_load_from_stream_finish:
+ * @session: an #EphySession
+ * @result: a #GAsyncResult
+ * @error: a #GError
+ *
+ * Finishes an async session load operation started with
+ * ephy_session_load_from_stream().
+ *
+ * Returns: %TRUE if at least a window has been opened
+ **/
+gboolean
+ephy_session_load_from_stream_finish (EphySession *session,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
- child = xmlDocGetRootElement (doc);
+ g_return_val_if_fail (EPHY_IS_SESSION (session), FALSE);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
- /* skip the session node */
- child = child->children;
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == ephy_session_load_from_stream);
- while (child != NULL)
- {
- if (xmlStrEqual (child->name, (const xmlChar *) "window"))
- {
- xmlChar *tmp;
- EphyEmbed *active_child;
-
- window = ephy_window_new ();
-
- widget = GTK_WIDGET (window);
- restore_geometry (GTK_WINDOW (widget), child);
+ return !g_simple_async_result_propagate_error (simple, error);
+}
- ephy_gui_window_update_user_time (widget, user_time);
+typedef struct {
+ guint32 user_time;
+ GCancellable *cancellable;
+} LoadAsyncData;
- /* Now add the tabs */
- parse_embed (child->children, window, session);
+static LoadAsyncData *
+load_async_data_new (guint32 user_time,
+ GCancellable *cancellable)
+{
+ LoadAsyncData *data;
- /* Set focus to something sane */
- tmp = xmlGetProp (child, (xmlChar *) "active-tab");
- if (tmp != NULL)
- {
- gboolean success;
- gulong active_tab;
-
- success = ephy_string_to_int ((char *) tmp, &active_tab);
- xmlFree (tmp);
- if (success)
- {
- GtkWidget *notebook;
- notebook = ephy_window_get_notebook (window);
- gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), active_tab);
- }
- }
+ data = g_slice_new (LoadAsyncData);
+ data->user_time = user_time;
+ data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
- if (ephy_embed_shell_get_mode (ephy_embed_shell_get_default ()) != EPHY_EMBED_SHELL_MODE_TEST)
- {
- active_child = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
- gtk_widget_grab_focus (GTK_WIDGET (active_child));
- gtk_widget_show (widget);
- }
- }
+ return data;
+}
- child = child->next;
- }
+static void
+load_async_data_free (LoadAsyncData *data)
+{
+ g_clear_object (&data->cancellable);
- xmlFreeDoc (doc);
+ g_slice_free (LoadAsyncData, data);
+}
- priv->dont_save = FALSE;
+static void
+load_from_stream_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ EphySession *session = EPHY_SESSION (object);
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+ GError *error = NULL;
- ephy_session_save (session, SESSION_STATE);
+ if (!ephy_session_load_from_stream_finish (session, result, &error))
+ {
+ g_simple_async_result_take_error (simple, error);
+ }
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
- retval = ephy_shell_get_n_windows (shell) > 0;
+static void
+session_read_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GFileInputStream *stream;
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+ GError *error = NULL;
- g_object_unref (shell);
+ stream = g_file_read_finish (G_FILE (object), result, &error);
+ if (stream)
+ {
+ EphySession *session;
+ LoadAsyncData *data;
+
+ session = EPHY_SESSION (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
+ data = g_simple_async_result_get_op_res_gpointer (simple);
+ ephy_session_load_from_stream (session, G_INPUT_STREAM (stream), data->user_time,
+ data->cancellable, load_from_stream_cb, simple);
+ g_object_unref (stream);
+ g_object_unref (session);
+ }
+ else
+ {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ }
- return retval;
+ g_application_release (G_APPLICATION (ephy_shell_get_default ()));
}
/**
* ephy_session_load:
- * @session: a #EphySession
+ * @session: an #EphySession
* @filename: the path of the source file
- * @user_time: a user_time, or 0
+ * @user_time: a user time, or 0
+ * @cancellable: (allow-none): optional #GCancellable object, or %NULL
+ * @callback: (scope async): a #GAsyncReadyCallback to call when the
+ * request is satisfied
+ * @user_data: (closure): the data to pass to callback function
*
- * Load a session from disk, restoring the windows and their state
+ * Asynchronously loads the session reading the session data from @filename,
+ * restoring windows and their state.
*
- * Return value: TRUE if at least a window has been opened
+ * When the operation is finished, @callback will be called. You can
+ * then call ephy_session_load_finish() to get the result of
+ * the operation.
**/
-gboolean
+void
ephy_session_load (EphySession *session,
const char *filename,
- guint32 user_time)
+ guint32 user_time,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
GFile *save_to_file;
- char *save_to_path;
- gboolean ret_value;
- char *contents;
- gsize length;
- GError *error = NULL;
+ GSimpleAsyncResult *result;
+ LoadAsyncData *data;
- g_return_val_if_fail (EPHY_IS_SESSION (session), FALSE);
- g_return_val_if_fail (filename, FALSE);
+ g_return_if_fail (EPHY_IS_SESSION (session));
+ g_return_if_fail (filename);
LOG ("ephy_sesion_load %s", filename);
+ g_application_hold (G_APPLICATION (ephy_shell_get_default ()));
+
+ result = g_simple_async_result_new (G_OBJECT (session), callback, user_data, ephy_session_load);
+
save_to_file = get_session_file (filename);
- save_to_path = g_file_get_path (save_to_file);
+ data = load_async_data_new (user_time, cancellable);
+ g_simple_async_result_set_op_res_gpointer (result, data, (GDestroyNotify)load_async_data_free);
+ g_file_read_async (save_to_file, G_PRIORITY_HIGH, cancellable, session_read_cb, result);
g_object_unref (save_to_file);
+}
- if (!g_file_get_contents (save_to_path, &contents, &length, &error))
- {
- LOG ("Could not load session, error reading session file: %s", error->message);
- g_error_free (error);
- g_free (save_to_path);
-
- return FALSE;
- }
+/**
+ * ephy_session_load_finish:
+ * @session: an #EphySession
+ * @result: a #GAsyncResult
+ * @error: a #GError
+ *
+ * Finishes an async session load operation started with
+ * ephy_session_load().
+ *
+ * Returns: %TRUE if at least a window has been opened
+ **/
+gboolean
+ephy_session_load_finish (EphySession *session,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
- ret_value = ephy_session_load_from_string (session, contents, length, user_time);
+ g_return_val_if_fail (EPHY_IS_SESSION (session), FALSE);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
- g_free (contents);
- g_free (save_to_path);
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == ephy_session_load);
- return ret_value;
+ return !g_simple_async_result_propagate_error (simple, error);
}
/**
diff --git a/src/ephy-session.h b/src/ephy-session.h
index 89b7316d7..6ab4d389f 100644
--- a/src/ephy-session.h
+++ b/src/ephy-session.h
@@ -67,28 +67,38 @@ struct _EphySessionClass
GObjectClass parent_class;
};
-GType ephy_session_get_type (void);
-
-gboolean ephy_session_save (EphySession *session,
- const char *filename);
-
-gboolean ephy_session_load (EphySession *session,
- const char *filename,
- guint32 user_time);
-
-gboolean ephy_session_load_from_string (EphySession *session,
- const char *session_data,
- gssize length,
- guint32 user_time);
-
-void ephy_session_close (EphySession *session);
-
-void ephy_session_queue_command (EphySession *session,
- EphySessionCommand op,
- const char *arg,
- const char **args,
- guint32 user_time,
- gboolean priority);
+GType ephy_session_get_type (void);
+
+gboolean ephy_session_save (EphySession *session,
+ const char *filename);
+
+void ephy_session_load (EphySession *session,
+ const char *filename,
+ guint32 user_time,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean ephy_session_load_finish (EphySession *session,
+ GAsyncResult *result,
+ GError **error);
+void ephy_session_load_from_stream (EphySession *session,
+ GInputStream *stream,
+ guint32 user_time,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean ephy_session_load_from_stream_finish (EphySession *session,
+ GAsyncResult *result,
+ GError **error);
+
+void ephy_session_close (EphySession *session);
+
+void ephy_session_queue_command (EphySession *session,
+ EphySessionCommand op,
+ const char *arg,
+ const char **args,
+ guint32 user_time,
+ gboolean priority);
G_END_DECLS
diff --git a/tests/ephy-session-test.c b/tests/ephy-session-test.c
index b69403f85..c8d2dc792 100644
--- a/tests/ephy-session-test.c
+++ b/tests/ephy-session-test.c
@@ -42,6 +42,35 @@ const char *session_data =
"</window>"
"</session>";
+static gboolean load_stream_retval;
+
+static void
+load_from_stream_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GMainLoop *loop = (GMainLoop *)user_data;
+
+ load_stream_retval = ephy_session_load_from_stream_finish (EPHY_SESSION (object), result, NULL);
+ g_main_loop_quit (loop);
+}
+
+static gboolean
+load_session_from_string (EphySession *session,
+ const char *data)
+{
+ GMainLoop *loop;
+ GInputStream *stream;
+
+ loop = g_main_loop_new (NULL, FALSE);
+ stream = g_memory_input_stream_new_from_data (data, -1, NULL);
+ ephy_session_load_from_stream (session, stream, 0, NULL, load_from_stream_cb, loop);
+ g_main_loop_run (loop);
+ g_main_loop_unref (loop);
+
+ return load_stream_retval;
+}
+
static void
test_ephy_session_load (void)
{
@@ -54,7 +83,7 @@ test_ephy_session_load (void)
session = EPHY_SESSION (ephy_shell_get_session (ephy_shell_get_default ()));
g_assert (session);
- ret = ephy_session_load_from_string (session, session_data, -1, 0);
+ ret = load_session_from_string (session, session_data);
g_assert (ret);
l = ephy_shell_get_windows (ephy_shell_get_default ());
@@ -89,7 +118,7 @@ test_ephy_session_load_empty_session (void)
session = EPHY_SESSION (ephy_shell_get_session (ephy_shell_get_default ()));
g_assert (session);
- ret = ephy_session_load_from_string (session, session_data_empty, -1, 0);
+ ret = load_session_from_string (session, session_data_empty);
g_assert (ret == FALSE);
/* Loading the session should have failed, but we should still get
@@ -139,7 +168,7 @@ test_ephy_session_load_many_windows (void)
session = EPHY_SESSION (ephy_shell_get_session (ephy_shell_get_default ()));
g_assert (session);
- ret = ephy_session_load_from_string (session, session_data_many_windows, -1, 0);
+ ret = load_session_from_string (session, session_data_many_windows);
g_assert (ret);
l = ephy_shell_get_windows (ephy_shell_get_default ());
@@ -174,7 +203,7 @@ open_uris_after_loading_session (const char** uris, int final_num_windows)
user_time = gdk_x11_display_get_user_time (gdk_display_get_default ());
- ret = ephy_session_load_from_string (session, session_data_many_windows, -1, 0);
+ ret = load_session_from_string (session, session_data_many_windows);
g_assert (ret);
l = ephy_shell_get_windows (ephy_shell_get_default ());