/pidgin/main: fb32647ef2f3: PurpleImage: better reference manage...
Tomasz Wasilczyk
twasilczyk at pidgin.im
Fri Apr 11 16:53:30 EDT 2014
Changeset: fb32647ef2f32a0bc4e9643b5883ed7937f44120
Author: Tomasz Wasilczyk <twasilczyk at pidgin.im>
Date: 2014-04-11 22:53 +0200
Branch: default
URL: https://hg.pidgin.im/pidgin/main/rev/fb32647ef2f3
Description:
PurpleImage: better reference management
diffstat:
libpurple/image-store.c | 26 ++++++++++++++++++++++++++
libpurple/image-store.h | 3 +++
libpurple/image.c | 1 +
pidgin/gtkwebview.c | 46 ++++++++++++++++++++++++++++++----------------
pidgin/gtkwebviewtoolbar.c | 21 +++++----------------
5 files changed, 65 insertions(+), 32 deletions(-)
diffs (214 lines):
diff --git a/libpurple/image-store.c b/libpurple/image-store.c
--- a/libpurple/image-store.c
+++ b/libpurple/image-store.c
@@ -23,6 +23,7 @@
#include "eventloop.h"
#include "glibcompat.h"
+#include "util.h"
#define TEMP_IMAGE_TIMEOUT 5
@@ -157,6 +158,31 @@ purple_image_store_get(guint id)
return g_hash_table_lookup(id_to_image, GINT_TO_POINTER(id));
}
+PurpleImage *
+purple_image_store_get_from_uri(const gchar *uri)
+{
+ guint64 longid;
+ guint id;
+ gchar *endptr;
+
+ if (!purple_str_has_prefix(uri, PURPLE_IMAGE_STORE_PROTOCOL))
+ return NULL;
+
+ uri += sizeof(PURPLE_IMAGE_STORE_PROTOCOL) - 1;
+ if (uri[0] == '-')
+ return NULL;
+
+ longid = g_ascii_strtoull(uri, &endptr, 10);
+ if (endptr[0] != '\0')
+ return NULL;
+
+ id = longid;
+ if (id != longid)
+ return NULL;
+
+ return purple_image_store_get(id);
+}
+
void
_purple_image_store_init(void)
{
diff --git a/libpurple/image-store.h b/libpurple/image-store.h
--- a/libpurple/image-store.h
+++ b/libpurple/image-store.h
@@ -53,6 +53,9 @@ purple_image_store_add_temporary(PurpleI
PurpleImage *
purple_image_store_get(guint id);
+PurpleImage *
+purple_image_store_get_from_uri(const gchar *uri);
+
void
_purple_image_store_init(void);
diff --git a/libpurple/image.c b/libpurple/image.c
--- a/libpurple/image.c
+++ b/libpurple/image.c
@@ -163,6 +163,7 @@ purple_image_new_from_file(const gchar *
g_return_val_if_fail(g_file_test(path, G_FILE_TEST_EXISTS), NULL);
img = g_object_new(PURPLE_TYPE_IMAGE, NULL);
+ purple_image_set_friendly_filename(img, path);
priv = PURPLE_IMAGE_GET_PRIVATE(img);
priv->path = g_strdup(path);
diff --git a/pidgin/gtkwebview.c b/pidgin/gtkwebview.c
--- a/pidgin/gtkwebview.c
+++ b/pidgin/gtkwebview.c
@@ -111,9 +111,6 @@ typedef struct _PidginWebViewPriv {
/* WebKit inspector */
WebKitWebView *inspector_view;
GtkWindow *inspector_win;
-
- /* Resources cache */
- GHashTable *loaded_images;
} PidginWebViewPriv;
/******************************************************************************
@@ -125,6 +122,14 @@ static WebKitWebViewClass *parent_class
static GRegex *smileys_re = NULL;
static GRegex *empty_html_re = NULL;
+/* Resources cache.
+ *
+ * It's global, because gtkwebkit calls "resource-load-finished" only once
+ * for each static resource.
+ */
+static GHashTable *globally_loaded_images = NULL;
+guint globally_loaded_images_refcnt = 0;
+
/******************************************************************************
* Helpers
@@ -208,10 +213,9 @@ static void
webview_resource_loaded(WebKitWebView *web_view, WebKitWebFrame *web_frame,
WebKitWebResource *web_resource, gpointer user_data)
{
- PidginWebViewPriv *priv = PIDGIN_WEBVIEW_GET_PRIVATE(web_view);
const gchar *uri;
GString *data;
- PurpleImage *image;
+ PurpleImage *image = NULL;
if (!purple_str_has_caseprefix(
webkit_web_resource_get_mime_type(web_resource), "image/"))
@@ -220,20 +224,23 @@ webview_resource_loaded(WebKitWebView *w
}
uri = webkit_web_resource_get_uri(web_resource);
- if (g_hash_table_lookup(priv->loaded_images, uri))
+ if (g_hash_table_lookup(globally_loaded_images, uri))
return;
data = webkit_web_resource_get_data(web_resource);
if (data->len == 0)
return;
- /* TODO: we could avoid copying data, if uri is a
- * PURPLE_IMAGE_STORE_PROTOCOL */
- image = purple_image_new_from_data(
- g_memdup(data->str, data->len), data->len);
- g_return_if_fail(image != NULL);
+ image = purple_image_store_get_from_uri(uri);
+ if (image) {
+ g_object_ref(image);
+ } else {
+ image = purple_image_new_from_data(
+ g_memdup(data->str, data->len), data->len);
+ g_return_if_fail(image != NULL);
+ }
- g_hash_table_insert(priv->loaded_images, g_strdup(uri), image);
+ g_hash_table_insert(globally_loaded_images, g_strdup(uri), image);
}
static PurpleImage *
@@ -243,7 +250,7 @@ webview_resource_get_loaded(WebKitWebVie
g_return_val_if_fail(priv != NULL, NULL);
- return g_hash_table_lookup(priv->loaded_images, uri);
+ return g_hash_table_lookup(globally_loaded_images, uri);
}
static void
@@ -1117,7 +1124,11 @@ pidgin_webview_finalize(GObject *webview
}
g_queue_free(priv->load_queue);
- g_hash_table_destroy(priv->loaded_images);
+ if (--globally_loaded_images_refcnt == 0) {
+ g_assert(globally_loaded_images != NULL);
+ g_hash_table_destroy(globally_loaded_images);
+ globally_loaded_images = NULL;
+ }
G_OBJECT_CLASS(parent_class)->finalize(G_OBJECT(webview));
}
@@ -1298,8 +1309,11 @@ pidgin_webview_init(PidginWebView *webvi
g_signal_connect(G_OBJECT(inspector), "show-window",
G_CALLBACK(webview_inspector_show), webview);
- priv->loaded_images = g_hash_table_new_full(g_str_hash, g_str_equal,
- g_free, g_object_unref);
+ if (globally_loaded_images_refcnt++ == 0) {
+ g_assert(globally_loaded_images == NULL);
+ globally_loaded_images = g_hash_table_new_full(g_str_hash,
+ g_str_equal, g_free, g_object_unref);
+ }
}
GType
diff --git a/pidgin/gtkwebviewtoolbar.c b/pidgin/gtkwebviewtoolbar.c
--- a/pidgin/gtkwebviewtoolbar.c
+++ b/pidgin/gtkwebviewtoolbar.c
@@ -608,10 +608,7 @@ static void
do_insert_image_cb(GtkWidget *widget, int response, PidginWebViewToolbar *toolbar)
{
PidginWebViewToolbarPriv *priv = PIDGIN_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar);
- gchar *filename = NULL, *buf;
- char *filedata;
- size_t size;
- GError *error = NULL;
+ gchar *filename = NULL;
PurpleImage *img;
if (response == GTK_RESPONSE_ACCEPT)
@@ -623,20 +620,12 @@ do_insert_image_cb(GtkWidget *widget, in
if (filename == NULL)
return;
- if (!g_file_get_contents(filename, &filedata, &size, &error)) {
- purple_notify_error(NULL, NULL, error->message, NULL, NULL);
-
- g_error_free(error);
- g_free(filename);
-
- return;
- }
-
- img = purple_image_new_from_data(filedata, size);
- purple_image_set_friendly_filename(img, filename);
+ img = purple_image_new_from_file(filename, TRUE);
if (!img) {
- buf = g_strdup_printf(_("Failed to store image: %s\n"), filename);
+ gchar *buf = g_strdup_printf(_("Failed to store image: %s"),
+ filename);
+
purple_notify_error(NULL, NULL, buf, NULL, NULL);
g_free(buf);
More information about the Commits
mailing list