aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2012-09-04 20:48:26 +0800
committerCarlos Garcia Campos <carlosgc@gnome.org>2012-09-06 16:25:09 +0800
commitb70fe20a489b0a89e4f8779551e87698434485a5 (patch)
tree08d63f5fce54bd741bea3279fab00ebd7ba65295
parent8712d1d951319e69dabae819d80700023cd920b8 (diff)
downloadgsoc2013-epiphany-b70fe20a489b0a89e4f8779551e87698434485a5.tar.gz
gsoc2013-epiphany-b70fe20a489b0a89e4f8779551e87698434485a5.tar.zst
gsoc2013-epiphany-b70fe20a489b0a89e4f8779551e87698434485a5.zip
ephy-snapshot-service: Split ephy_snapshot_service_get_snapshot_async()
ephy_snapshot_service_get_snapshot_async() receives an option web view parameter, that it's only used in case the snapshot is not the in the thumbnails cache. We can split the method into ephy_snapshot_service_get_snapshot_async() to get a snapshot from a web view and ephy_snapshot_service_get_snapshot_for_url_async() to get a snapshot from the cache. The former uses the latter to try first if the web view URI is in the cache. Patch includes other cleanups and fixes: - Add missing ephy_snapshot_service_save_snapshot_finish() - Add EphySnapshotServiceError to handle errors - Use GSimpleAsyncResult API instead of using GIOScheduler directly - Use different async data structs for every async operation https://bugzilla.gnome.org/show_bug.cgi?id=683327
-rw-r--r--lib/ephy-snapshot-service.c511
-rw-r--r--lib/ephy-snapshot-service.h76
-rw-r--r--lib/widgets/ephy-overview-store.c87
-rw-r--r--tests/ephy-snapshot-service-test.c8
4 files changed, 443 insertions, 239 deletions
diff --git a/lib/ephy-snapshot-service.c b/lib/ephy-snapshot-service.c
index 04b559035..d201a163f 100644
--- a/lib/ephy-snapshot-service.c
+++ b/lib/ephy-snapshot-service.c
@@ -40,34 +40,6 @@ struct _EphySnapshotServicePrivate
G_DEFINE_TYPE (EphySnapshotService, ephy_snapshot_service, G_TYPE_OBJECT)
-typedef struct {
- WebKitWebView *webview;
- char *url;
- time_t mtime;
- GdkPixbuf *snapshot;
- GCancellable *cancellable;
- GAsyncReadyCallback callback;
- gpointer user_data;
-} SnapshotOp;
-
-static gboolean ephy_snapshot_service_complete_async (SnapshotOp *op);
-static gboolean ephy_snapshot_service_take_from_webview (SnapshotOp *op);
-
-static void
-snapshot_op_free (SnapshotOp *op)
-{
- g_free (op->url);
-
- if (op->cancellable)
- g_object_unref (op->cancellable);
- if (op->webview)
- g_object_unref (op->webview);
- if (op->snapshot)
- g_object_unref (op->snapshot);
-
- g_slice_free (SnapshotOp, op);
-}
-
/* GObject boilerplate methods. */
static void
@@ -85,119 +57,147 @@ ephy_snapshot_service_init (EphySnapshotService *self)
self->priv->factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
}
-/* IO scheduler methods, used for IO. */
+typedef struct {
+ char *url;
+ time_t mtime;
-static GdkPixbuf *
-io_scheduler_get_cached_snapshot (EphySnapshotService *service,
- char *url, time_t mtime)
-{
GdkPixbuf *snapshot;
- char *uri;
+} SnapshotForURLAsyncData;
- uri = gnome_desktop_thumbnail_factory_lookup (service->priv->factory,
- url, mtime);
- if (uri == NULL)
- return NULL;
+static SnapshotForURLAsyncData *
+snapshot_for_url_async_data_new (const char *url,
+ time_t mtime)
+{
+ SnapshotForURLAsyncData *data;
- snapshot = gdk_pixbuf_new_from_file (uri, NULL);
- g_free (uri);
+ data = g_slice_new0 (SnapshotForURLAsyncData);
+ data->url = g_strdup (url);
+ data->mtime = mtime;
- return snapshot;
+ return data;
}
-static gboolean
-io_scheduler_try_cache_query (GIOSchedulerJob *job,
- GCancellable *cancellable,
- gpointer user_data)
+static void
+snapshot_for_url_async_data_free (SnapshotForURLAsyncData *data)
{
- SnapshotOp *op;
- EphySnapshotService *service = ephy_snapshot_service_get_default ();
- GSourceFunc func;
+ g_free (data->url);
+ g_clear_object (&data->snapshot);
- op = (SnapshotOp*) user_data;
+ g_slice_free (SnapshotForURLAsyncData, data);
+}
- if (g_cancellable_is_cancelled (op->cancellable)) {
- func = (GSourceFunc)ephy_snapshot_service_complete_async;
- goto out;
+static void
+get_snapshot_for_url_thread (GSimpleAsyncResult *result,
+ EphySnapshotService *service,
+ GCancellable *cancellable)
+{
+ SnapshotForURLAsyncData *data;
+ gchar *uri;
+ GError *error = NULL;
+
+ data = (SnapshotForURLAsyncData *)g_simple_async_result_get_op_res_gpointer (result);
+
+ uri = gnome_desktop_thumbnail_factory_lookup (service->priv->factory, data->url, data->mtime);
+ if (uri == NULL) {
+ g_simple_async_result_set_error (result,
+ EPHY_SNAPSHOT_SERVICE_ERROR,
+ EPHY_SNAPSHOT_SERVICE_ERROR_NOT_FOUND,
+ "Snapshot for url \"%s\" not found in cache", data->url);
+ return;
}
- op->snapshot = io_scheduler_get_cached_snapshot (service, op->url, op->mtime);
-
- /* If we do have a cached snapshot or we don't have a webview
- already, just complete early. */
- if (op->snapshot || !op->webview)
- func = (GSourceFunc)ephy_snapshot_service_complete_async;
- else
- func = (GSourceFunc)ephy_snapshot_service_take_from_webview;
+ data->snapshot = gdk_pixbuf_new_from_file (uri, &error);
+ if (data->snapshot == NULL) {
+ g_simple_async_result_set_error (result,
+ EPHY_SNAPSHOT_SERVICE_ERROR,
+ EPHY_SNAPSHOT_SERVICE_ERROR_INVALID,
+ "Error creating pixbuf for snapshot file \"%s\": %s",
+ uri, error->message);
+ g_error_free (error);
+ }
-out:
- g_io_scheduler_job_send_to_mainloop (job, func, op, NULL);
- return FALSE;
+ g_free (uri);
}
-static gboolean
-io_scheduler_save_thumbnail (GIOSchedulerJob *job,
- GCancellable *cancellable,
- gpointer user_data)
-{
- SnapshotOp *op;
- EphySnapshotService *service;
+typedef struct {
+ WebKitWebView *web_view;
+ time_t mtime;
+ GCancellable *cancellable;
- op = (SnapshotOp*) user_data;
- service = ephy_snapshot_service_get_default ();
- gnome_desktop_thumbnail_factory_save_thumbnail (service->priv->factory,
- op->snapshot,
- op->url,
- op->mtime);
+ GdkPixbuf *snapshot;
+} SnapshotAsyncData;
- g_io_scheduler_job_send_to_mainloop_async (job,
- (GSourceFunc)ephy_snapshot_service_complete_async,
- op, NULL);
+static SnapshotAsyncData *
+snapshot_async_data_new (WebKitWebView *web_view,
+ time_t mtime,
+ GCancellable *cancellable)
+{
+ SnapshotAsyncData *data;
- return FALSE;
-}
+ data = g_slice_new0 (SnapshotAsyncData);
+ data->web_view = g_object_ref (web_view);
+ data->mtime = mtime;
+ data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
-/* Methods that run in the mainloop. */
+ return data;
+}
-static gboolean
-ephy_snapshot_service_complete_async (SnapshotOp *op)
+static void
+snapshot_async_data_free (SnapshotAsyncData *data)
{
- GSimpleAsyncResult *res;
+ g_object_unref (data->web_view);
+ g_clear_object (&data->cancellable);
+ g_clear_object (&data->snapshot);
- res = g_simple_async_result_new (G_OBJECT (ephy_snapshot_service_get_default ()),
- op->callback,
- op->user_data,
- ephy_snapshot_service_complete_async);
- g_simple_async_result_set_check_cancellable (res, op->cancellable);
- g_simple_async_result_set_op_res_gpointer (res, op, (GDestroyNotify)snapshot_op_free);
- g_simple_async_result_complete (res);
- g_object_unref (res);
+ g_slice_free (SnapshotAsyncData, data);
+}
- return FALSE;
+static void
+snapshot_saved (EphySnapshotService *service,
+ GAsyncResult *result,
+ GSimpleAsyncResult *simple)
+{
+ ephy_snapshot_service_save_snapshot_finish (service, result, NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
}
static gboolean
-webview_retrieve_snapshot (SnapshotOp *op)
+retrieve_snapshot_from_web_view (GSimpleAsyncResult *result)
{
+ EphySnapshotService *service;
cairo_surface_t *surface;
+ SnapshotAsyncData *data;
+
+ data = (SnapshotAsyncData *)g_simple_async_result_get_op_res_gpointer (result);
#ifdef HAVE_WEBKIT2
/* FIXME: We need to add this API to WebKit2. */
surface = NULL;
#else
- surface = webkit_web_view_get_snapshot (WEBKIT_WEB_VIEW (op->webview));
+ surface = webkit_web_view_get_snapshot (data->web_view);
#endif
if (surface == NULL) {
- ephy_snapshot_service_complete_async (op);
+ g_simple_async_result_set_error (result,
+ EPHY_SNAPSHOT_SERVICE_ERROR,
+ EPHY_SNAPSHOT_SERVICE_ERROR_WEB_VIEW,
+ "%s", "Error getting snapshot from web view");
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+
return FALSE;
}
- op->snapshot = ephy_snapshot_service_crop_snapshot (surface);
+ data->snapshot = ephy_snapshot_service_crop_snapshot (surface);
cairo_surface_destroy (surface);
- g_io_scheduler_push_job ((GIOSchedulerJobFunc)io_scheduler_save_thumbnail,
- op, NULL, G_PRIORITY_LOW, NULL);
+ service = (EphySnapshotService *)g_async_result_get_source_object (G_ASYNC_RESULT (result));
+ ephy_snapshot_service_save_snapshot_async (service, data->snapshot,
+ webkit_web_view_get_uri (data->web_view),
+ data->mtime, data->cancellable,
+ (GAsyncReadyCallback)snapshot_saved, result);
+
return FALSE;
}
@@ -205,18 +205,18 @@ webview_retrieve_snapshot (SnapshotOp *op)
static void
webview_load_changed_cb (WebKitWebView *webview,
WebKitLoadEvent load_event,
- SnapshotOp *op)
+ GSimpleAsyncResult *result)
{
- switch (load_event) {
- case WEBKIT_LOAD_FINISHED:
- /* Load finished doesn't ensure that we actually have visible content yet,
- so hold a bit before retrieving the snapshot. */
- g_idle_add ((GSourceFunc) webview_retrieve_snapshot, op);
- /* Some pages might end up causing this condition to happen twice, so remove
- the handler in order to avoid calling the above idle function twice. */
- g_signal_handlers_disconnect_by_func (webview, webview_load_changed_cb, op);
- break;
- }
+ if (load_event != WEBKIT_LOAD_FINISHED)
+ return;
+
+ /* Load finished doesn't ensure that we actually have visible content yet,
+ so hold a bit before retrieving the snapshot. */
+ g_idle_add ((GSourceFunc) retrieve_snapshot_from_web_view, result);
+
+ /* Some pages might end up causing this condition to happen twice, so remove
+ the handler in order to avoid calling the above idle function twice. */
+ g_signal_handlers_disconnect_by_func (webview, webview_load_changed_cb, result);
}
static gboolean
@@ -224,9 +224,16 @@ webview_load_failed_cb (WebKitWebView *webview,
WebKitLoadEvent load_event,
const char failing_uri,
GError *error,
- SnapshotOp *op)
+ GSimpleAsyncResult *result)
{
- ephy_snapshot_service_complete_async (op);
+ g_signal_handlers_disconnect_by_func (webview, webview_load_changed_cb, result);
+ g_simple_async_result_set_error (result,
+ EPHY_SNAPSHOT_SERVICE_ERROR,
+ EPHY_SNAPSHOT_SERVICE_ERROR_WEB_VIEW,
+ "Error getting snapshot, web view failed to load: %s",
+ error->message);
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
return FALSE;
}
@@ -234,22 +241,23 @@ webview_load_failed_cb (WebKitWebView *webview,
static void
webview_load_status_changed_cb (WebKitWebView *webview,
GParamSpec *pspec,
- SnapshotOp *op)
+ GSimpleAsyncResult *result)
{
- WebKitLoadStatus status;
-
- status = webkit_web_view_get_load_status (webview);
-
- switch (status) {
+ switch (webkit_web_view_get_load_status (webview)) {
case WEBKIT_LOAD_FINISHED:
/* Load finished doesn't ensure that we actually have visible
content yet, so hold a bit before retrieving the snapshot. */
- g_idle_add ((GSourceFunc) webview_retrieve_snapshot, op);
- g_signal_handlers_disconnect_by_func (webview, webview_load_status_changed_cb, op);
+ g_idle_add ((GSourceFunc) retrieve_snapshot_from_web_view, result);
+ g_signal_handlers_disconnect_by_func (webview, webview_load_status_changed_cb, result);
break;
case WEBKIT_LOAD_FAILED:
- g_signal_handlers_disconnect_by_func (webview, webview_load_status_changed_cb, op);
- ephy_snapshot_service_complete_async (op);
+ g_signal_handlers_disconnect_by_func (webview, webview_load_status_changed_cb, result);
+ g_simple_async_result_set_error (result,
+ EPHY_SNAPSHOT_SERVICE_ERROR,
+ EPHY_SNAPSHOT_SERVICE_ERROR_WEB_VIEW,
+ "%s", "Error getting snapshot, web view failed to load");
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
break;
default:
break;
@@ -258,36 +266,83 @@ webview_load_status_changed_cb (WebKitWebView *webview,
#endif
static gboolean
-ephy_snapshot_service_take_from_webview (SnapshotOp *op)
+ephy_snapshot_service_take_from_webview (GSimpleAsyncResult *result)
{
- WebKitWebView *webview = op->webview;
+ SnapshotAsyncData *data;
- if (g_cancellable_is_cancelled (op->cancellable)) {
- ephy_snapshot_service_complete_async (op);
- return FALSE;
- }
+ data = (SnapshotAsyncData *)g_simple_async_result_get_op_res_gpointer (result);
#ifdef HAVE_WEBKIT2
- if (webkit_web_view_get_estimated_load_progress (WEBKIT_WEB_VIEW (webview))== 1.0)
- webview_retrieve_snapshot (op);
+ if (webkit_web_view_get_estimated_load_progress (WEBKIT_WEB_VIEW (data->web_view)) == 1.0)
+ retrieve_snapshot_from_web_view (result);
else {
- g_signal_connect (webview, "load-changed",
- G_CALLBACK (webview_load_changed_cb), op);
- g_signal_connect (webview, "load-failed",
- G_CALLBACK (webview_load_failed_cb), op);
+ g_signal_connect (data->web_view, "load-changed",
+ G_CALLBACK (webview_load_changed_cb), result);
+ g_signal_connect (data->web_view, "load-failed",
+ G_CALLBACK (webview_load_failed_cb), result);
}
#else
- if (webkit_web_view_get_load_status (webview) == WEBKIT_LOAD_FINISHED)
- webview_retrieve_snapshot (op);
+ if (webkit_web_view_get_load_status (data->web_view) == WEBKIT_LOAD_FINISHED)
+ retrieve_snapshot_from_web_view (result);
else
- g_signal_connect (webview, "notify::load-status",
+ g_signal_connect (data->web_view, "notify::load-status",
G_CALLBACK (webview_load_status_changed_cb),
- op);
+ result);
#endif
return FALSE;
}
+typedef struct {
+ GdkPixbuf *snapshot;
+ char *url;
+ time_t mtime;
+} SaveSnapshotAsyncData;
+
+static SaveSnapshotAsyncData *
+save_snapshot_async_data_new (GdkPixbuf *snapshot,
+ const char *url,
+ time_t mtime)
+{
+ SaveSnapshotAsyncData *data;
+
+ data = g_slice_new (SaveSnapshotAsyncData);
+ data->snapshot = g_object_ref (snapshot);
+ data->url = g_strdup (url);
+ data->mtime = mtime;
+
+ return data;
+}
+
+static void
+save_snapshot_async_data_free (SaveSnapshotAsyncData *data)
+{
+ g_object_unref (data->snapshot);
+ g_free (data->url);
+
+ g_slice_free (SaveSnapshotAsyncData, data);
+}
+
+static void
+save_snapshot_thread (GSimpleAsyncResult *result,
+ EphySnapshotService *service,
+ GCancellable *cancellable)
+{
+ SaveSnapshotAsyncData *data;
+
+ data = (SaveSnapshotAsyncData *)g_simple_async_result_get_op_res_gpointer (result);
+ gnome_desktop_thumbnail_factory_save_thumbnail (service->priv->factory,
+ data->snapshot,
+ data->url,
+ data->mtime);
+}
+
+GQuark
+ephy_snapshot_service_error_quark (void)
+{
+ return g_quark_from_static_string ("ephy-snapshot-service-error-quark");
+}
+
/**
* ephy_snapshot_service_get_default:
*
@@ -307,12 +362,104 @@ ephy_snapshot_service_get_default (void)
}
/**
- * ephy_snapshot_service_get_snapshot:
+ * ephy_snapshot_service_get_snapshot_for_url:
* @service: a #EphySnapshotService
* @url: the URL for which a snapshot is needed
* @mtime: @the last
* @callback: a #EphySnapshotServiceCallback
- * @userdata: user data to pass to @callback
+ * @user_data: user data to pass to @callback
+ *
+ * Schedules a query for a snapshot of @url. If there is an up-to-date
+ * snapshot in the cache, this will be retrieved.
+ *
+ **/
+void
+ephy_snapshot_service_get_snapshot_for_url_async (EphySnapshotService *service,
+ const char *url,
+ const time_t mtime,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+
+ g_return_if_fail (EPHY_IS_SNAPSHOT_SERVICE (service));
+ g_return_if_fail (url != NULL);
+
+ result = g_simple_async_result_new (G_OBJECT (service), callback, user_data,
+ ephy_snapshot_service_get_snapshot_for_url_async);
+
+ g_simple_async_result_set_op_res_gpointer (result,
+ snapshot_for_url_async_data_new (url, mtime),
+ (GDestroyNotify)snapshot_for_url_async_data_free);
+ g_simple_async_result_run_in_thread (result,
+ (GSimpleAsyncThreadFunc)get_snapshot_for_url_thread,
+ G_PRIORITY_LOW, cancellable);
+ g_object_unref (result);
+}
+
+/**
+ * ephy_snapshot_service_get_snapshot_for_url_finish:
+ * @service: a #EphySnapshotService
+ * @result: a #GAsyncResult
+ * @error: a location to store a #GError or %NULL
+ *
+ * Finishes the retrieval of a snapshot. Call from the
+ * #GAsyncReadyCallback passed to
+ * ephy_snapshot_service_get_snapshot_for_url_async().
+ *
+ * Returns: (transfer full): the snapshot.
+ **/
+GdkPixbuf *
+ephy_snapshot_service_get_snapshot_for_url_finish (EphySnapshotService *service,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ SnapshotForURLAsyncData *data;
+
+ g_return_val_if_fail (EPHY_IS_SNAPSHOT_SERVICE (service), NULL);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result,
+ G_OBJECT (service),
+ ephy_snapshot_service_get_snapshot_for_url_async),
+ NULL);
+
+ simple = (GSimpleAsyncResult *)result;
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return NULL;
+
+ data = (SnapshotForURLAsyncData *)g_simple_async_result_get_op_res_gpointer (simple);
+
+ return data->snapshot ? g_object_ref (data->snapshot) : NULL;
+}
+
+static void
+got_snapshot_for_url (EphySnapshotService *service,
+ GAsyncResult *result,
+ GSimpleAsyncResult *simple)
+{
+ SnapshotAsyncData *data;
+
+ data = (SnapshotAsyncData *)g_simple_async_result_get_op_res_gpointer (simple);
+ data->snapshot = ephy_snapshot_service_get_snapshot_for_url_finish (service, result, NULL);
+ if (data->snapshot) {
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ return;
+ }
+
+ ephy_snapshot_service_take_from_webview (simple);
+}
+
+/**
+ * ephy_snapshot_service_get_snapshot_async:
+ * @service: a #EphySnapshotService
+ * @web_view: the #WebKitWebView for which a snapshot is needed
+ * @mtime: @the last
+ * @callback: a #EphySnapshotServiceCallback
+ * @user_data: user data to pass to @callback
*
* Schedules a query for a snapshot of @url. If there is an up-to-date
* snapshot in the cache, this will be retrieved. Otherwise, this
@@ -321,30 +468,34 @@ ephy_snapshot_service_get_default (void)
**/
void
ephy_snapshot_service_get_snapshot_async (EphySnapshotService *service,
- WebKitWebView *webview,
- const char *url,
+ WebKitWebView *web_view,
const time_t mtime,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
- SnapshotOp *op;
+ GSimpleAsyncResult *result;
+ const char *uri;
g_return_if_fail (EPHY_IS_SNAPSHOT_SERVICE (service));
- g_return_if_fail (url != NULL);
-
- op = g_slice_alloc0 (sizeof(SnapshotOp));
- op->url = g_strdup (url);
- op->mtime = mtime;
- op->webview = webview ? g_object_ref (webview) : NULL;
- op->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
- op->callback = callback;
- op->user_data = user_data;
-
- /* Query for the snapshot from the cache using the IO scheduler, so
- that there is no UI blocking during the cache query. */
- g_io_scheduler_push_job (io_scheduler_try_cache_query,
- op, NULL, G_PRIORITY_LOW, NULL);
+ g_return_if_fail (WEBKIT_IS_WEB_VIEW (web_view));
+
+ result = g_simple_async_result_new (G_OBJECT (service), callback, user_data,
+ ephy_snapshot_service_get_snapshot_async);
+
+ g_simple_async_result_set_op_res_gpointer (result,
+ snapshot_async_data_new (web_view, mtime, cancellable),
+ (GDestroyNotify)snapshot_async_data_free);
+
+ /* Try to get the snapshot from the cache first if we have a URL */
+ uri = webkit_web_view_get_uri (web_view);
+ if (uri)
+ ephy_snapshot_service_get_snapshot_for_url_async (service,
+ uri, mtime, cancellable,
+ (GAsyncReadyCallback)got_snapshot_for_url,
+ result);
+ else
+ g_idle_add ((GSourceFunc)ephy_snapshot_service_take_from_webview, result);
}
/**
@@ -365,21 +516,22 @@ ephy_snapshot_service_get_snapshot_finish (EphySnapshotService *service,
GError **error)
{
GSimpleAsyncResult *simple;
- SnapshotOp *op;
+ SnapshotAsyncData *data;
+ g_return_val_if_fail (EPHY_IS_SNAPSHOT_SERVICE (service), NULL);
g_return_val_if_fail (g_simple_async_result_is_valid (result,
G_OBJECT (service),
- ephy_snapshot_service_complete_async),
+ ephy_snapshot_service_get_snapshot_async),
NULL);
- simple = (GSimpleAsyncResult *) result;
+ simple = (GSimpleAsyncResult *)result;
if (g_simple_async_result_propagate_error (simple, error))
return NULL;
- op = g_simple_async_result_get_op_res_gpointer (simple);
+ data = (SnapshotAsyncData *)g_simple_async_result_get_op_res_gpointer (simple);
- return op->snapshot ? g_object_ref (op->snapshot) : NULL;
+ return data->snapshot ? g_object_ref (data->snapshot) : NULL;
}
void
@@ -391,22 +543,35 @@ ephy_snapshot_service_save_snapshot_async (EphySnapshotService *service,
GAsyncReadyCallback callback,
gpointer user_data)
{
- SnapshotOp *op;
+ GSimpleAsyncResult *result;
g_return_if_fail (EPHY_IS_SNAPSHOT_SERVICE (service));
g_return_if_fail (GDK_IS_PIXBUF (snapshot));
g_return_if_fail (url != NULL);
- op = g_slice_alloc0 (sizeof(SnapshotOp));
- op->snapshot = g_object_ref (snapshot);
- op->url = g_strdup (url);
- op->mtime = mtime;
- op->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
- op->callback = callback;
- op->user_data = user_data;
+ result = g_simple_async_result_new (G_OBJECT (service), callback, user_data,
+ ephy_snapshot_service_save_snapshot_async);
+
+ g_simple_async_result_set_op_res_gpointer (result,
+ save_snapshot_async_data_new (snapshot, url, mtime),
+ (GDestroyNotify)save_snapshot_async_data_free);
+ g_simple_async_result_run_in_thread (result,
+ (GSimpleAsyncThreadFunc)save_snapshot_thread,
+ G_PRIORITY_LOW, cancellable);
+}
+
+gboolean
+ephy_snapshot_service_save_snapshot_finish (EphySnapshotService *service,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (EPHY_IS_SNAPSHOT_SERVICE (service), FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result,
+ G_OBJECT (service),
+ ephy_snapshot_service_save_snapshot_async),
+ FALSE);
- g_io_scheduler_push_job (io_scheduler_save_thumbnail,
- op, NULL, G_PRIORITY_LOW, NULL);
+ return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
}
GdkPixbuf *
diff --git a/lib/ephy-snapshot-service.h b/lib/ephy-snapshot-service.h
index deab02071..dacf21a63 100644
--- a/lib/ephy-snapshot-service.h
+++ b/lib/ephy-snapshot-service.h
@@ -39,6 +39,8 @@ G_BEGIN_DECLS
#define EPHY_IS_SNAPSHOT_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EPHY_TYPE_SNAPSHOT_SERVICE))
#define EPHY_SNAPSHOT_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EPHY_TYPE_SNAPSHOT_SERVICE, EphySnapshotServiceClass))
+#define EPHY_SNAPSHOT_SERVICE_ERROR (ephy_snapshot_service_error_quark())
+
typedef struct _EphySnapshotService EphySnapshotService;
typedef struct _EphySnapshotServiceClass EphySnapshotServiceClass;
typedef struct _EphySnapshotServicePrivate EphySnapshotServicePrivate;
@@ -56,38 +58,56 @@ struct _EphySnapshotServiceClass
GObjectClass parent_class;
};
+typedef enum {
+ EPHY_SNAPSHOT_SERVICE_ERROR_NOT_FOUND,
+ EPHY_SNAPSHOT_SERVICE_ERROR_WEB_VIEW,
+ EPHY_SNAPSHOT_SERVICE_ERROR_INVALID
+} EphySnapshotServiceError;
+
/* Values taken from the Web mockups. */
#define EPHY_THUMBNAIL_WIDTH 180
#define EPHY_THUMBNAIL_HEIGHT 135
-typedef void (* EphySnapshotServiceCallback) (GdkPixbuf *snapshot,
- gpointer user_data);
-
-GType ephy_snapshot_service_get_type (void) G_GNUC_CONST;
-
-EphySnapshotService *ephy_snapshot_service_get_default (void);
-
-void ephy_snapshot_service_get_snapshot_async (EphySnapshotService *service,
- WebKitWebView *webview,
- const char *url,
- const time_t mtime,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-
-GdkPixbuf * ephy_snapshot_service_get_snapshot_finish (EphySnapshotService *service,
- GAsyncResult *result,
- GError **error);
-
-void ephy_snapshot_service_save_snapshot_async (EphySnapshotService *service,
- GdkPixbuf *snapshot,
- const char *url,
- time_t mtime,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-
-GdkPixbuf* ephy_snapshot_service_crop_snapshot (cairo_surface_t *surface);
+GType ephy_snapshot_service_get_type (void) G_GNUC_CONST;
+GQuark ephy_snapshot_service_error_quark (void);
+
+EphySnapshotService *ephy_snapshot_service_get_default (void);
+
+void ephy_snapshot_service_get_snapshot_for_url_async (EphySnapshotService *service,
+ const char *url,
+ const time_t mtime,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GdkPixbuf *ephy_snapshot_service_get_snapshot_for_url_finish (EphySnapshotService *service,
+ GAsyncResult *result,
+ GError **error);
+
+void ephy_snapshot_service_get_snapshot_async (EphySnapshotService *service,
+ WebKitWebView *web_view,
+ const time_t mtime,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GdkPixbuf *ephy_snapshot_service_get_snapshot_finish (EphySnapshotService *service,
+ GAsyncResult *result,
+ GError **error);
+
+void ephy_snapshot_service_save_snapshot_async (EphySnapshotService *service,
+ GdkPixbuf *snapshot,
+ const char *url,
+ time_t mtime,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean ephy_snapshot_service_save_snapshot_finish (EphySnapshotService *service,
+ GAsyncResult *result,
+ GError **error);
+
+GdkPixbuf *ephy_snapshot_service_crop_snapshot (cairo_surface_t *surface);
G_END_DECLS
diff --git a/lib/widgets/ephy-overview-store.c b/lib/widgets/ephy-overview-store.c
index 312a24ffc..99ef2cf45 100644
--- a/lib/widgets/ephy-overview-store.c
+++ b/lib/widgets/ephy-overview-store.c
@@ -292,39 +292,60 @@ ephy_overview_store_set_default_icon_internal (EphyOverviewStore *store,
}
static void
+set_snapshot (EphyOverviewStore *store,
+ GdkPixbuf *snapshot,
+ GtkTreeRowReference *ref,
+ time_t timestamp)
+{
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ path = gtk_tree_row_reference_get_path (ref);
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path);
+ gtk_tree_path_free (path);
+
+ if (snapshot)
+ ephy_overview_store_set_snapshot_internal (store, &iter, snapshot, timestamp);
+ else
+ ephy_overview_store_set_default_icon_internal (store, &iter, store->priv->default_icon);
+
+ gtk_list_store_set (GTK_LIST_STORE (store), &iter,
+ EPHY_OVERVIEW_STORE_SNAPSHOT_CANCELLABLE, NULL,
+ -1);
+}
+
+static void
on_snapshot_retrieved_cb (GObject *object,
GAsyncResult *res,
PeekContext *ctx)
{
- EphyOverviewStore *store;
- GtkTreePath *path;
- GtkTreeIter iter;
GdkPixbuf *snapshot;
- GError *error = NULL;
snapshot = ephy_snapshot_service_get_snapshot_finish (EPHY_SNAPSHOT_SERVICE (object),
- res, &error);
-
- if (error) {
- g_error_free (error);
- error = NULL;
- } else {
- store = EPHY_OVERVIEW_STORE (gtk_tree_row_reference_get_model (ctx->ref));
- path = gtk_tree_row_reference_get_path (ctx->ref);
- gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path);
- gtk_tree_path_free (path);
- if (snapshot) {
- ephy_overview_store_set_snapshot_internal (store, &iter, snapshot, ctx->timestamp);
- g_object_unref (snapshot);
-
- } else {
- ephy_overview_store_set_default_icon_internal (store, &iter,
- store->priv->default_icon);
- }
- gtk_list_store_set (GTK_LIST_STORE (store), &iter,
- EPHY_OVERVIEW_STORE_SNAPSHOT_CANCELLABLE, NULL,
- -1);
- }
+ res, NULL);
+
+ set_snapshot (EPHY_OVERVIEW_STORE (gtk_tree_row_reference_get_model (ctx->ref)),
+ snapshot, ctx->ref, ctx->timestamp);
+ if (snapshot)
+ g_object_unref (snapshot);
+
+ peek_context_free (ctx);
+}
+
+static void
+on_snapshot_retrieved_for_url_cb (GObject *object,
+ GAsyncResult *res,
+ PeekContext *ctx)
+{
+ GdkPixbuf *snapshot;
+
+ snapshot = ephy_snapshot_service_get_snapshot_for_url_finish (EPHY_SNAPSHOT_SERVICE (object),
+ res, NULL);
+
+ set_snapshot (EPHY_OVERVIEW_STORE (gtk_tree_row_reference_get_model (ctx->ref)),
+ snapshot, ctx->ref, ctx->timestamp);
+ if (snapshot)
+ g_object_unref (snapshot);
peek_context_free (ctx);
}
@@ -341,10 +362,16 @@ history_service_url_cb (gpointer service,
ctx->timestamp = url->thumbnail_time;
- ephy_snapshot_service_get_snapshot_async (snapshot_service,
- ctx->webview, ctx->url, ctx->timestamp, ctx->cancellable,
- (GAsyncReadyCallback) on_snapshot_retrieved_cb,
- ctx);
+ if (ctx->webview)
+ ephy_snapshot_service_get_snapshot_async (snapshot_service,
+ ctx->webview, ctx->timestamp, ctx->cancellable,
+ (GAsyncReadyCallback) on_snapshot_retrieved_cb,
+ ctx);
+ else
+ ephy_snapshot_service_get_snapshot_for_url_async (snapshot_service,
+ ctx->url, ctx->timestamp, ctx->cancellable,
+ (GAsyncReadyCallback) on_snapshot_retrieved_for_url_cb,
+ ctx);
ephy_history_url_free (url);
}
diff --git a/tests/ephy-snapshot-service-test.c b/tests/ephy-snapshot-service-test.c
index 2ece2df1e..5c352e040 100644
--- a/tests/ephy-snapshot-service-test.c
+++ b/tests/ephy-snapshot-service-test.c
@@ -84,7 +84,6 @@ test_snapshot (void)
webkit_web_view_load_uri (webview, TEST_SERVER_URI);
ephy_snapshot_service_get_snapshot_async (service,
webview,
- TEST_SERVER_URI,
mtime,
NULL,
(GAsyncReadyCallback)on_snapshot_ready,
@@ -102,7 +101,6 @@ test_cached_snapshot (void)
webkit_web_view_load_uri (webview, TEST_SERVER_URI);
ephy_snapshot_service_get_snapshot_async (service,
webview,
- TEST_SERVER_URI,
mtime,
NULL,
(GAsyncReadyCallback)on_snapshot_ready,
@@ -121,7 +119,6 @@ test_many_snapshots (void)
webkit_web_view_load_uri (webview, TEST_SERVER_URI "/some");
ephy_snapshot_service_get_snapshot_async (service,
webview,
- TEST_SERVER_URI "/some",
mtime,
NULL,
(GAsyncReadyCallback)on_snapshot_ready,
@@ -131,7 +128,6 @@ test_many_snapshots (void)
webkit_web_view_load_uri (webview, TEST_SERVER_URI "/other");
ephy_snapshot_service_get_snapshot_async (service,
webview,
- TEST_SERVER_URI "/other",
mtime,
NULL,
(GAsyncReadyCallback)on_snapshot_ready,
@@ -141,7 +137,6 @@ test_many_snapshots (void)
webkit_web_view_load_uri (webview, TEST_SERVER_URI "/place");
ephy_snapshot_service_get_snapshot_async (service,
webview,
- TEST_SERVER_URI "/place",
mtime,
NULL,
(GAsyncReadyCallback)on_snapshot_ready,
@@ -160,7 +155,6 @@ test_snapshot_with_cancellable (void)
webkit_web_view_load_uri (webview, TEST_SERVER_URI "/and");
ephy_snapshot_service_get_snapshot_async (service,
webview,
- TEST_SERVER_URI "/and",
mtime,
cancellable,
(GAsyncReadyCallback)on_snapshot_ready,
@@ -180,7 +174,6 @@ test_already_cancelled_snapshot (void)
g_cancellable_cancel (cancellable);
ephy_snapshot_service_get_snapshot_async (service,
webview,
- TEST_SERVER_URI "/so",
mtime,
cancellable,
(GAsyncReadyCallback)on_snapshot_ready,
@@ -207,7 +200,6 @@ test_snapshot_and_timed_cancellation (void)
ephy_snapshot_service_get_snapshot_async (service,
webview,
- TEST_SERVER_URI "/on",
mtime,
cancellable,
(GAsyncReadyCallback)on_snapshot_ready,