[epiphany] downloads: Add content-type property to EphyDownload
- From: Carlos Garcia Campos <carlosgc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany] downloads: Add content-type property to EphyDownload
- Date: Mon, 26 Oct 2015 11:11:34 +0000 (UTC)
commit f379cfbae025b9c1fe667223cbcbffa893e30c0f
Author: Carlos Garcia Campos <cgarcia igalia com>
Date: Wed Oct 7 15:05:05 2015 +0200
downloads: Add content-type property to EphyDownload
This way it can be monitorized, instead of the caller deciding when to
ask for it during the whole download process. We first try to get it
when the server response is received. Then we try again when the
destination file has been created if the server didn't provide a valid
content type.
embed/ephy-download.c | 135 ++++++++++++++++++++++++------------
embed/ephy-download.h | 2 +-
lib/widgets/ephy-download-widget.c | 53 ++++++---------
3 files changed, 113 insertions(+), 77 deletions(-)
---
diff --git a/embed/ephy-download.c b/embed/ephy-download.c
index e1cc90e..4c29a94 100644
--- a/embed/ephy-download.c
+++ b/embed/ephy-download.c
@@ -47,7 +47,7 @@ struct _EphyDownloadPrivate
WebKitDownload *download;
char *destination;
- char *source;
+ char *content_type;
EphyDownloadActionType action;
guint32 start_time;
@@ -61,7 +61,8 @@ enum
PROP_DOWNLOAD,
PROP_DESTINATION,
PROP_ACTION,
- PROP_START_TIME
+ PROP_START_TIME,
+ PROP_CONTENT_TYPE
};
enum
@@ -96,6 +97,9 @@ ephy_download_get_property (GObject *object,
case PROP_START_TIME:
g_value_set_uint (value, ephy_download_get_start_time (download));
break;
+ case PROP_CONTENT_TYPE:
+ g_value_set_string (value, ephy_download_get_content_type (download));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -133,54 +137,16 @@ ephy_download_set_property (GObject *object,
* Gets content-type information for @download. If the server didn't
* provide a content type, the destination file is queried.
*
- * Returns: content-type for @download, must be freed with g_free()
+ * Returns: content-type for @download
**/
-char *
+const char *
ephy_download_get_content_type (EphyDownload *download)
{
- WebKitURIResponse *response;
- const char *destination_uri;
- GFile *destination;
- GFileInfo *info;
- char *content_type = NULL;
- GError *error = NULL;
-
- response = webkit_download_get_response (download->priv->download);
- if (response) {
- const char *mime_type = webkit_uri_response_get_mime_type (response);
-
- LOG ("ephy_download_get_content_type: WebKit mime type: %s", mime_type);
-
- if (mime_type) {
- content_type = g_content_type_from_mime_type (mime_type);
- if (content_type)
- return content_type;
- }
- }
-
- destination_uri = webkit_download_get_destination (download->priv->download);
- if (!destination_uri)
- return NULL;
-
- destination = g_file_new_for_uri (destination_uri);
- info = g_file_query_info (destination, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
- G_FILE_QUERY_INFO_NONE, NULL, &error);
- if (info) {
- content_type = g_strdup (g_file_info_get_content_type (info));
- LOG ("ephy_download_get_content_type: GIO: %s", content_type);
- g_object_unref (info);
- } else {
- LOG ("ephy_download_get_content_type: error getting file "
- "content-type: %s", error->message);
- g_error_free (error);
- }
-
- g_object_unref (destination);
+ g_return_val_if_fail (EPHY_IS_DOWNLOAD (download), NULL);
- return content_type;
+ return download->priv->content_type;
}
-
/* Helper function to decide what EphyDownloadActionType should be the
* default for the download. This implies that you want something to
* happen, this function will never return EPHY_DOWNLOAD_ACTION_NONE.
@@ -555,6 +521,7 @@ ephy_download_dispose (GObject *object)
}
g_clear_error(&priv->error);
+ g_clear_pointer (&priv->content_type, g_free);
G_OBJECT_CLASS (ephy_download_parent_class)->dispose (object);
}
@@ -634,6 +601,16 @@ ephy_download_class_init (EphyDownloadClass *klass)
G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (object_class, PROP_CONTENT_TYPE,
+ g_param_spec_string ("content-type",
+ "Content Type",
+ "The download content type",
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
/**
* EphyDownload::filename-suggested:
*
@@ -692,6 +669,25 @@ ephy_download_init (EphyDownload *download)
download->priv->start_time = gtk_get_current_event_time ();
}
+static void
+download_response_changed_cb (WebKitDownload *wk_download,
+ GParamSpec *spec,
+ EphyDownload *download)
+{
+ WebKitURIResponse *response;
+ const char *mime_type;
+
+ response = webkit_download_get_response (download->priv->download);
+ mime_type = webkit_uri_response_get_mime_type (response);
+ if (!mime_type)
+ return;
+
+ download->priv->content_type = g_content_type_from_mime_type (mime_type);
+ if (download->priv->content_type)
+ g_object_notify (G_OBJECT (download), "content-type");
+
+}
+
static gboolean
download_decide_destination_cb (WebKitDownload *wk_download,
const gchar *suggested_filename,
@@ -709,6 +705,51 @@ download_decide_destination_cb (WebKitDownload *wk_download,
}
static void
+download_created_destination_cb (WebKitDownload *wk_download,
+ const char *destination,
+ EphyDownload *download)
+{
+ char *filename;
+ char *content_type;
+ EphyDownloadPrivate *priv = download->priv;
+
+ if (priv->content_type && !g_content_type_is_unknown (priv->content_type))
+ return;
+
+ /* The server didn't provide a valid content type, let's try to guess it from the
+ * destination filename. We use g_content_type_guess() here instead of g_file_query_info(),
+ * because we are only using the filename to guess the content type, since it doesn't make
+ * sense to sniff the destination URI that will be empty until the download is completed.
+ * We can't use g_file_query_info() with the partial download file either, because it will
+ * always return application/x-partial-download based on the .wkdownload extension.
+ */
+ filename = g_filename_from_uri (destination, NULL, NULL);
+ if (!filename)
+ return;
+
+ content_type = g_content_type_guess (filename, NULL, 0, NULL);
+ g_free (filename);
+
+ if (g_content_type_is_unknown (content_type)) {
+ /* We could try to connect to received-data signal and sniff the contents when we have
+ * enough data written in the file, but I don't think it's worth it.
+ */
+ g_free (content_type);
+ return;
+ }
+
+ if (!priv->content_type ||
+ (priv->content_type && !g_content_type_equals (priv->content_type, content_type))) {
+ g_free (priv->content_type);
+ priv->content_type = content_type;
+ g_object_notify (G_OBJECT (download), "content-type");
+ return;
+ }
+
+ g_free (content_type);
+}
+
+static void
download_finished_cb (WebKitDownload *wk_download,
EphyDownload *download)
{
@@ -756,9 +797,15 @@ ephy_download_new (WebKitDownload *download)
ephy_download = g_object_new (EPHY_TYPE_DOWNLOAD, NULL);
+ g_signal_connect (download, "notify::response",
+ G_CALLBACK (download_response_changed_cb),
+ ephy_download);
g_signal_connect (download, "decide-destination",
G_CALLBACK (download_decide_destination_cb),
ephy_download);
+ g_signal_connect (download, "created-destination",
+ G_CALLBACK (download_created_destination_cb),
+ ephy_download);
g_signal_connect (download, "finished",
G_CALLBACK (download_finished_cb),
ephy_download);
diff --git a/embed/ephy-download.h b/embed/ephy-download.h
index d95190c..e6ca3ad 100644
--- a/embed/ephy-download.h
+++ b/embed/ephy-download.h
@@ -83,7 +83,7 @@ void ephy_download_set_destination_uri (EphyDownload *download,
WebKitDownload *ephy_download_get_webkit_download (EphyDownload *download);
const char *ephy_download_get_destination_uri (EphyDownload *download);
-char *ephy_download_get_content_type (EphyDownload *download);
+const char *ephy_download_get_content_type (EphyDownload *download);
guint32 ephy_download_get_start_time (EphyDownload *download);
diff --git a/lib/widgets/ephy-download-widget.c b/lib/widgets/ephy-download-widget.c
index 6734a5e..6b1da16 100644
--- a/lib/widgets/ephy-download-widget.c
+++ b/lib/widgets/ephy-download-widget.c
@@ -55,25 +55,6 @@ enum
PROP_DOWNLOAD
};
-static GIcon *
-get_gicon_from_download (EphyDownload *ephy_download)
-{
- char *content_type;
- GIcon *gicon;
-
- /* FIXME: this might do sync IO during downloads */
- content_type = ephy_download_get_content_type (ephy_download);
-
- if (content_type) {
- gicon = g_content_type_get_icon (content_type);
- g_free (content_type);
- } else {
- gicon = g_icon_new_for_string ("package-x-generic", NULL);
- }
-
- return gicon;
-}
-
static char *
get_destination_basename_from_download (EphyDownload *ephy_download)
{
@@ -163,15 +144,17 @@ download_clicked_cb (GtkButton *button,
static void
update_download_icon (EphyDownloadWidget *widget)
{
- GIcon *new_icon, *old_icon;
+ GIcon *icon;
+ const char *content_type;
- new_icon = get_gicon_from_download (widget->priv->download);
- gtk_image_get_gicon (GTK_IMAGE (widget->priv->icon), &old_icon, NULL);
- if (!g_icon_equal (new_icon, old_icon)) {
- gtk_image_set_from_gicon (GTK_IMAGE (widget->priv->icon), new_icon,
- GTK_ICON_SIZE_DIALOG);
- }
- g_object_unref (new_icon);
+ content_type = ephy_download_get_content_type (widget->priv->download);
+ if (content_type)
+ icon = g_content_type_get_icon (content_type);
+ else
+ icon = g_icon_new_for_string ("package-x-generic", NULL);
+
+ gtk_image_set_from_gicon (GTK_IMAGE (widget->priv->icon), icon, GTK_ICON_SIZE_DIALOG);
+ g_object_unref (icon);
}
static void
@@ -226,7 +209,6 @@ download_progress_cb (WebKitDownload *download,
EphyDownloadWidget *widget)
{
gdouble progress;
- int percentage;
WebKitURIResponse *response;
guint64 content_length;
guint64 received_length;
@@ -236,10 +218,6 @@ download_progress_cb (WebKitDownload *download,
return;
progress = webkit_download_get_estimated_progress (download);
- percentage = progress * 100;
- if (percentage % 10 == 0)
- update_download_icon (widget);
-
response = webkit_download_get_response (download);
content_length = webkit_uri_response_get_content_length (response);
received_length = webkit_download_get_received_data_length (download);
@@ -305,6 +283,14 @@ download_failed_cb (EphyDownload *download,
}
static void
+download_content_type_changed_cb (EphyDownload *download,
+ GParamSpec *spec,
+ EphyDownloadWidget *widget)
+{
+ update_download_icon (widget);
+}
+
+static void
widget_action_button_clicked_cb (EphyDownloadWidget *widget)
{
if (ephy_download_is_active (widget->priv->download)) {
@@ -490,6 +476,9 @@ ephy_download_widget_constructed (GObject *object)
g_signal_connect (priv->download, "error",
G_CALLBACK (download_failed_cb),
widget);
+ g_signal_connect (priv->download, "notify::content-type",
+ G_CALLBACK (download_content_type_changed_cb),
+ widget);
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]