[epiphany/overview-2: 1/9] Add a service for snapshotting webpages



commit 5fd9fad5335a8a797fc3c828b41803a1faddc121
Author: Claudio Saavedra <csaavedra igalia com>
Date:   Tue Jan 24 14:25:29 2012 +0200

    Add a service for snapshotting webpages
    
    This service provides pixbufs for URLs while caching these locally as
    thumbnails. gnome-desktop-thumbnail is used to handle caching.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=668578

 configure.ac                |    2 +
 lib/Makefile.am             |    2 +
 lib/ephy-snapshot-service.c |  212 +++++++++++++++++++++++++++++++++++++++++++
 lib/ephy-snapshot-service.h |   70 ++++++++++++++
 4 files changed, 286 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 05768cd..a8ea998 100644
--- a/configure.ac
+++ b/configure.ac
@@ -89,6 +89,7 @@ LIBXML_REQUIRED=2.6.12
 LIBXSLT_REQUIRED=1.1.7
 WEBKIT_GTK_REQUIRED=1.7.3
 LIBSOUP_GNOME_REQUIRED=2.37.1
+GNOME_DESKTOP_REQUIRED=2.91.2
 GNOME_KEYRING_REQUIRED=2.26.0
 GSETTINGS_DESKTOP_SCHEMAS_REQUIRED=0.0.1
 LIBNOTIFY_REQUIRED=0.5.1
@@ -117,6 +118,7 @@ PKG_CHECK_MODULES([DEPENDENCIES], [
 		  libxslt >= $LIBXSLT_REQUIRED
 		  webkitgtk-3.0 >= $WEBKIT_GTK_REQUIRED
 		  libsoup-gnome-2.4 >= $LIBSOUP_GNOME_REQUIRED
+		  gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED
 		  gnome-keyring-1 >= $GNOME_KEYRING_REQUIRED
 		  gsettings-desktop-schemas >= $GSETTINGS_DESKTOP_SCHEMAS_REQUIRED
 		  libnotify >= $LIBNOTIFY_REQUIRED
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 0e4869a..0e36260 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -25,6 +25,7 @@ NOINST_H_FILES = \
 	ephy-signal-accumulator.h		\
 	ephy-smaps.h				\
 	ephy-string.h				\
+	ephy-snapshot-service.h			\
 	ephy-time-helpers.h			\
 	ephy-zoom.h
 
@@ -64,6 +65,7 @@ libephymisc_la_SOURCES = \
 	ephy-shlib-loader.c			\
 	ephy-signal-accumulator.c		\
 	ephy-smaps.c				\
+	ephy-snapshot-service.c			\
 	ephy-state.c				\
 	ephy-string.c				\
 	ephy-time-helpers.c			\
diff --git a/lib/ephy-snapshot-service.c b/lib/ephy-snapshot-service.c
new file mode 100644
index 0000000..52835c3
--- /dev/null
+++ b/lib/ephy-snapshot-service.c
@@ -0,0 +1,212 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ *  Copyright  2012 Igalia S.L.
+ *
+ *  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
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *  Author: Claudio Saavedra  <csaavedra igalia com>
+ */
+
+#include "config.h"
+#include "ephy-snapshot-service.h"
+
+#ifndef GNOME_DESKTOP_USE_UNSTABLE_API
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#endif
+#include <libgnome-desktop/gnome-desktop-thumbnail.h>
+
+#include <webkit/webkit.h>
+
+
+G_DEFINE_TYPE (EphySnapshotService, ephy_snapshot_service, G_TYPE_OBJECT)
+
+#define SNAPSHOT_SERVICE_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), EPHY_TYPE_SNAPSHOT_SERVICE, EphySnapshotServicePrivate))
+
+struct _EphySnapshotServicePrivate
+{
+  GnomeDesktopThumbnailFactory *factory;
+};
+
+static void
+ephy_snapshot_service_class_init (EphySnapshotServiceClass *klass)
+{
+  g_type_class_add_private (klass, sizeof (EphySnapshotServicePrivate));
+}
+
+static void
+ephy_snapshot_service_init (EphySnapshotService *self)
+{
+  self->priv = SNAPSHOT_SERVICE_PRIVATE (self);
+
+  self->priv->factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
+}
+
+/**
+ * ephy_snapshot_service_get_default:
+ *
+ * Gets the default instance of #EphySnapshotService.
+ *
+ * Returns: a #EphySnapshotService
+ **/
+EphySnapshotService *
+ephy_snapshot_service_get_default (void)
+{
+  static EphySnapshotService *service = NULL;
+
+  if (service == NULL)
+    service = g_object_new (EPHY_TYPE_SNAPSHOT_SERVICE, NULL);
+
+  return service;
+}
+
+typedef struct {
+  char *url;
+  time_t mtime;
+  EphySnapshotServiceCallback callback;
+  gpointer user_data;
+  GtkWidget *window;
+  GtkWidget *webview;
+} SnapshotRequest;
+
+static void
+request_free (SnapshotRequest *request)
+{
+  g_free (request->url);
+
+  if (request->window)
+    gtk_widget_destroy (request->window);
+
+  g_slice_free (SnapshotRequest, request);
+}
+
+static void
+finish_request (SnapshotRequest *request, GdkPixbuf *snapshot)
+{
+  if (request->callback)
+    request->callback (snapshot, request->user_data);
+
+  request_free (request);
+}
+
+static void
+webview_load_status_changed (WebKitWebView *webview,
+			     GParamSpec *pspec,
+			     SnapshotRequest *request)
+{
+  WebKitLoadStatus status;
+  GdkPixbuf *snapshot, *scaled;
+  EphySnapshotService *service;
+
+  status = webkit_web_view_get_load_status (webview);
+
+  if (status == WEBKIT_LOAD_FINISHED) {
+    service = ephy_snapshot_service_get_default ();
+    snapshot = gtk_offscreen_window_get_pixbuf (GTK_OFFSCREEN_WINDOW (request->window));
+    scaled = gnome_desktop_thumbnail_scale_down_pixbuf (snapshot, 250, 125);
+    gnome_desktop_thumbnail_factory_save_thumbnail (service->priv->factory,
+						    scaled,
+						    request->url,
+						    request->mtime);
+    g_object_unref (snapshot);
+    finish_request (request, scaled);
+  }
+}
+
+static GdkPixbuf *
+ephy_snapshot_service_get_snapshot_from_cache (EphySnapshotService *service,
+					       char *url, time_t mtime)
+{
+  GdkPixbuf *snapshot;
+  char *uri;
+
+  uri =  gnome_desktop_thumbnail_factory_lookup (service->priv->factory,
+						 url, mtime);
+  if (uri == NULL)
+    return NULL;
+
+  snapshot = gdk_pixbuf_new_from_file (uri, NULL);
+  g_free (uri);
+
+  return snapshot;
+}
+
+static gboolean
+process_request (SnapshotRequest *request)
+{
+  EphySnapshotService *service;
+  GdkPixbuf *snapshot;
+
+  service = ephy_snapshot_service_get_default ();
+  snapshot = ephy_snapshot_service_get_snapshot_from_cache (service,
+							    request->url,
+							    request->mtime);
+  if (snapshot) {
+    finish_request (request, snapshot);
+  } else {
+    GtkWidget *sw;
+    request->window = gtk_offscreen_window_new ();
+    request->webview = webkit_web_view_new ();
+    sw = gtk_scrolled_window_new (NULL, NULL);
+    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+				    GTK_POLICY_NEVER, GTK_POLICY_NEVER);
+    gtk_widget_set_size_request (sw, 800, 400);
+
+    g_signal_connect (request->webview, "notify::load-status",
+		      G_CALLBACK (webview_load_status_changed),
+		      request);
+    gtk_container_add (GTK_CONTAINER (request->window), sw);
+    gtk_container_add (GTK_CONTAINER (sw), request->webview);
+    gtk_widget_show_all (request->window);
+    webkit_web_view_load_uri (WEBKIT_WEB_VIEW (request->webview), request->url);
+  }
+
+  return FALSE;
+}
+
+/**
+ * ephy_snapshot_service_get_snapshot:
+ * @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
+ *
+ * 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
+ * the snapshot will be taken, cached, and retrieved.
+ *
+ **/
+void
+ephy_snapshot_service_get_snapshot (EphySnapshotService *service,
+                                    const char *url,
+				    const time_t mtime,
+                                    EphySnapshotServiceCallback callback,
+                                    gpointer userdata)
+{
+  SnapshotRequest *request;
+
+  g_return_if_fail (EPHY_IS_SNAPSHOT_SERVICE (service));
+  g_return_if_fail (url != NULL);
+
+  request = g_slice_alloc0 (sizeof(SnapshotRequest));
+
+  request->url = g_strdup (url);
+  request->callback = callback;
+  request->user_data = userdata;
+  request->mtime = mtime;
+
+  g_idle_add ((GSourceFunc) process_request, request);
+}
diff --git a/lib/ephy-snapshot-service.h b/lib/ephy-snapshot-service.h
new file mode 100644
index 0000000..2eb35c3
--- /dev/null
+++ b/lib/ephy-snapshot-service.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ *  Copyright  2012 Igalia S.L.
+ *
+ *  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
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *  Author: Claudio Saavedra  <csaavedra igalia com>
+ */
+
+#ifndef _EPHY_SNAPSHOT_SERVICE_H
+#define _EPHY_SNAPSHOT_SERVICE_H
+
+#include <gtk/gtk.h>
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_SNAPSHOT_SERVICE            (ephy_snapshot_service_get_type())
+#define EPHY_SNAPSHOT_SERVICE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_SNAPSHOT_SERVICE, EphySnapshotService))
+#define EPHY_SNAPSHOT_SERVICE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_SNAPSHOT_SERVICE, EphySnapshotServiceClass))
+#define EPHY_IS_SNAPSHOT_SERVICE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_SNAPSHOT_SERVICE))
+#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))
+
+typedef struct _EphySnapshotService        EphySnapshotService;
+typedef struct _EphySnapshotServiceClass   EphySnapshotServiceClass;
+typedef struct _EphySnapshotServicePrivate EphySnapshotServicePrivate;
+
+struct _EphySnapshotService
+{
+  GObject parent;
+
+  /*< private >*/
+  EphySnapshotServicePrivate *priv;
+};
+
+struct _EphySnapshotServiceClass
+{
+  GObjectClass parent_class;
+};
+
+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 (EphySnapshotService *service,
+							 const char *url,
+							 const time_t mtime,
+							 EphySnapshotServiceCallback callback,
+							 gpointer userdata);
+
+G_END_DECLS
+
+#endif /* _EPHY_SNAPSHOT_SERVICE_H */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]