[evince/wip/chpe/load-fd: 29/31] libview: Add EvJobLoad class to load from file descriptor




commit ff6994ac3a931910a215eee81e8ab3f311878fbb
Author: Christian Persch <chpe src gnome org>
Date:   Wed Dec 1 21:25:02 2021 +0100

    libview: Add EvJobLoad class to load from file descriptor

 help/reference/libview/libevview-sections.txt |  10 +
 libview/ev-jobs.c                             | 305 +++++++++++++++++++++++++-
 libview/ev-jobs.h                             |  58 +++++
 3 files changed, 371 insertions(+), 2 deletions(-)
---
diff --git a/help/reference/libview/libevview-sections.txt b/help/reference/libview/libevview-sections.txt
index 2f8f6e6ef..5b0bb6451 100644
--- a/help/reference/libview/libevview-sections.txt
+++ b/help/reference/libview/libevview-sections.txt
@@ -131,6 +131,8 @@ EvJobLoadStream
 EvJobLoadStreamClass
 EvJobLoadGFile
 EvJobLoadGFileClass
+EvJobLoadFd
+EvJobLoadFdClass
 EvJobSave
 EvJobSaveClass
 EvJobFind
@@ -173,12 +175,20 @@ ev_job_load_set_uri
 ev_job_load_set_password
 ev_job_load_stream_new
 ev_job_load_stream_set_stream
+ev_job_load_stream_set_mime_type
 ev_job_load_stream_set_load_flags
 ev_job_load_stream_set_password
 ev_job_load_gfile_new
 ev_job_load_gfile_set_gfile
 ev_job_load_gfile_set_load_flags
 ev_job_load_gfile_set_password
+ev_job_load_fd_new
+ev_job_load_fd_new_take
+ev_job_load_fd_set_fd
+ev_job_load_fd_take_fd
+ev_job_load_fd_set_set_mime_type
+ev_job_load_fd_set_load_flags
+ev_job_load_fd_set_password
 ev_job_save_new
 ev_job_find_new
 ev_job_find_get_n_results
diff --git a/libview/ev-jobs.c b/libview/ev-jobs.c
index e52e49c81..5b23d1d23 100644
--- a/libview/ev-jobs.c
+++ b/libview/ev-jobs.c
@@ -43,6 +43,13 @@
 #include <glib/gstdio.h>
 #include <glib/gi18n-lib.h>
 #include <unistd.h>
+#include <fcntl.h>
+
+typedef struct _EvJobLoadStreamPrivate EvJobLoadStreamPrivate;
+struct _EvJobLoadStreamPrivate
+{
+        char *mime_type;
+};
 
 static void ev_job_init                   (EvJob                 *job);
 static void ev_job_class_init             (EvJobClass            *class);
@@ -100,8 +107,9 @@ G_DEFINE_TYPE (EvJobPageData, ev_job_page_data, EV_TYPE_JOB)
 G_DEFINE_TYPE (EvJobThumbnail, ev_job_thumbnail, EV_TYPE_JOB)
 G_DEFINE_TYPE (EvJobFonts, ev_job_fonts, EV_TYPE_JOB)
 G_DEFINE_TYPE (EvJobLoad, ev_job_load, EV_TYPE_JOB)
-G_DEFINE_TYPE (EvJobLoadStream, ev_job_load_stream, EV_TYPE_JOB)
+G_DEFINE_TYPE_WITH_PRIVATE (EvJobLoadStream, ev_job_load_stream, EV_TYPE_JOB)
 G_DEFINE_TYPE (EvJobLoadGFile, ev_job_load_gfile, EV_TYPE_JOB)
+G_DEFINE_TYPE (EvJobLoadFd, ev_job_load_fd, EV_TYPE_JOB)
 G_DEFINE_TYPE (EvJobSave, ev_job_save, EV_TYPE_JOB)
 G_DEFINE_TYPE (EvJobFind, ev_job_find, EV_TYPE_JOB)
 G_DEFINE_TYPE (EvJobLayers, ev_job_layers, EV_TYPE_JOB)
@@ -1198,12 +1206,15 @@ static void
 ev_job_load_stream_dispose (GObject *object)
 {
         EvJobLoadStream *job = EV_JOB_LOAD_STREAM (object);
+        EvJobLoadStreamPrivate *priv = ev_job_load_stream_get_instance_private (job);
 
         if (job->stream) {
                 g_object_unref (job->stream);
                 job->stream = NULL;
         }
 
+        g_free (priv->mime_type);
+        priv->mime_type = NULL;
         g_free (job->password);
         job->password = NULL;
 
@@ -1214,6 +1225,7 @@ static gboolean
 ev_job_load_stream_run (EvJob *job)
 {
         EvJobLoadStream *job_load_stream = EV_JOB_LOAD_STREAM (job);
+        EvJobLoadStreamPrivate *priv = ev_job_load_stream_get_instance_private (job_load_stream);
         GError *error = NULL;
 
         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
@@ -1242,7 +1254,7 @@ ev_job_load_stream_run (EvJob *job)
                                          &error);
         } else {
                 job->document = ev_document_factory_get_document_for_stream (job_load_stream->stream,
-                                                                             NULL /* mime-type FIXME? */,
+                                                                             priv->mime_type,
                                                                              job_load_stream->flags,
                                                                              job->cancellable,
                                                                              &error);
@@ -1296,6 +1308,19 @@ ev_job_load_stream_set_stream (EvJobLoadStream *job,
         job->stream = stream;
 }
 
+void
+ev_job_load_stream_set_mime_type (EvJobLoadStream    *job,
+                                  const char         *mime_type)
+{
+        EvJobLoadStreamPrivate *priv;
+
+        g_return_if_fail (EV_IS_JOB_LOAD_STREAM (job));
+
+        priv = ev_job_load_stream_get_instance_private (job);
+        g_free (priv->mime_type);
+        priv->mime_type = g_strdup (mime_type);
+}
+
 void
 ev_job_load_stream_set_load_flags (EvJobLoadStream    *job,
                                    EvDocumentLoadFlags flags)
@@ -1462,6 +1487,282 @@ ev_job_load_gfile_set_password (EvJobLoadGFile *job,
         g_free (old_password);
 }
 
+/* EvJobLoadFd */
+
+/**
+ * EvJobLoadFd:
+ *
+ * A job class to load a #EvDocument from a file descriptor
+ * referring to a regular file.
+ *
+ * Since: 3.30
+ */
+
+static int
+ev_dupfd (int fd,
+          GError **error)
+{
+        int new_fd;
+
+        new_fd = fcntl (fd, F_DUPFD_CLOEXEC, 3);
+        if (new_fd == -1) {
+                int errsv = errno;
+                g_set_error_literal (error, G_FILE_ERROR, g_file_error_from_errno (errsv),
+                                     g_strerror (errsv));
+        }
+
+        return new_fd;
+}
+
+static void
+ev_job_load_fd_init (EvJobLoadFd *job)
+{
+        job->flags = EV_DOCUMENT_LOAD_FLAG_NONE;
+        job->fd = -1;
+
+        EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
+}
+
+static void
+ev_job_load_fd_dispose (GObject *object)
+{
+        EvJobLoadFd *job = EV_JOB_LOAD_FD (object);
+
+        if (job->fd != -1) {
+                close (job->fd);
+                job->fd = -1;
+        }
+
+        g_free (job->mime_type);
+        job->mime_type = NULL;
+        g_free (job->password);
+        job->password = NULL;
+
+        G_OBJECT_CLASS (ev_job_load_fd_parent_class)->dispose (object);
+}
+
+static gboolean
+ev_job_load_fd_run (EvJob *job)
+{
+        EvJobLoadFd *job_load_fd = EV_JOB_LOAD_FD (job);
+        GError *error = NULL;
+        int fd;
+
+        if (job_load_fd->fd == -1) {
+                g_set_error_literal (&error, G_FILE_ERROR, G_FILE_ERROR_BADF,
+                                     "Invalid file descriptor");
+                goto out;
+        }
+
+        /* We need to dup the FD here since we may need to pass it again
+         * to ev_document_load_fd() if the document is encrypted,
+         * and the previous call to it consumes the FD.
+         */
+        fd = ev_dupfd (job_load_fd->fd, &error);
+        if (fd == -1)
+                goto out;
+
+        ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
+
+        ev_document_fc_mutex_lock ();
+
+        /* This job may already have a document even if the job didn't complete
+           because, e.g., a password is required - if so, just reload_fd rather than
+           creating a new instance */
+
+        if (job->document) {
+
+                if (job_load_fd->password) {
+                        ev_document_security_set_password (EV_DOCUMENT_SECURITY (job->document),
+                                                           job_load_fd->password);
+                }
+
+                job->failed = FALSE;
+                job->finished = FALSE;
+                g_clear_error (&job->error);
+
+                ev_document_load_fd (job->document,
+                                     fd,
+                                     job_load_fd->flags,
+                                     job->cancellable,
+                                     &error);
+                fd = -1; /* consumed */
+        } else {
+                job->document = ev_document_factory_get_document_for_fd (fd,
+                                                                         job_load_fd->mime_type,
+                                                                         job_load_fd->flags,
+                                                                         job->cancellable,
+                                                                         &error);
+                fd = -1; /* consumed */
+        }
+
+        ev_document_fc_mutex_unlock ();
+
+ out:
+        if (error) {
+                ev_job_failed_from_error (job, error);
+                g_error_free (error);
+        } else {
+                ev_job_succeeded (job);
+        }
+
+        return FALSE;
+}
+
+static void
+ev_job_load_fd_class_init (EvJobLoadFdClass *class)
+{
+        GObjectClass *oclass = G_OBJECT_CLASS (class);
+        EvJobClass   *job_class = EV_JOB_CLASS (class);
+
+        oclass->dispose = ev_job_load_fd_dispose;
+        job_class->run = ev_job_load_fd_run;
+}
+
+/**
+ * ev_job_load_fd_new:
+ * @fd: (transfer none):
+ * @mime_type:
+ * @flags:
+ * @error: (nullable): a location to store a #GError, or %NULL
+ *
+ * Creates a new #EvJobLoadFd for @fd. If duplicating @fd fails,
+ * returns %NULL with @error filled in.
+ *
+ * Returns: (tranfer full): the new #EvJobLoadFd, or %NULL
+ *
+ * Since: 3.30
+ */
+EvJob *
+ev_job_load_fd_new (int                 fd,
+                    const char         *mime_type,
+                    EvDocumentLoadFlags flags,
+                    GError            **error)
+{
+        EvJobLoadFd *job;
+
+        job = g_object_new (EV_TYPE_JOB_LOAD_FD, NULL);
+        if (!ev_job_load_fd_set_fd (job, fd, error)) {
+                g_object_unref (job);
+                return NULL;
+        }
+
+        ev_job_load_fd_set_mime_type (job, mime_type);
+        ev_job_load_fd_set_load_flags (job, flags);
+
+        return EV_JOB (job);
+}
+
+/**
+ * ev_job_load_new_take:
+ * @fd: (transfer full):
+ * @mime_type:
+ * @flags:
+ *
+ * Creates a new #EvJobLoadFd for @fd.
+ * Note that the job takes ownership of @fd; you must not do anything
+ * with it afterwards.
+ *
+ * Returns: (tranfer full): the new #EvJobLoadFd
+ *
+ * Since: 3.30
+ */
+EvJob *
+ev_job_load_fd_new_take (int                 fd,
+                         const char         *mime_type,
+                         EvDocumentLoadFlags flags)
+{
+        EvJobLoadFd *job;
+
+        job = g_object_new (EV_TYPE_JOB_LOAD_FD, NULL);
+        ev_job_load_fd_take_fd (job, fd);
+        ev_job_load_fd_set_mime_type (job, mime_type);
+        ev_job_load_fd_set_load_flags (job, flags);
+
+        return EV_JOB (job);
+}
+
+/**
+ * ev_job_load_fd_set_fd:
+ * @job:
+ * @fd: (transfer none):
+ * @error: (nullable): a location to store a #GError, or %NULL
+ *
+ * Sets @fd as the file descriptor in @job. If duplicating @fd fails,
+ * returns %FALSE with @error filled in.
+ *
+ * Returns: %TRUE if the file descriptor could be set
+ *
+ * Since: 3.30
+ */
+gboolean
+ev_job_load_fd_set_fd (EvJobLoadFd *job,
+                       int          fd,
+                       GError     **error)
+{
+        g_return_val_if_fail (EV_IS_JOB_LOAD_FD (job), FALSE);
+        g_return_val_if_fail (fd != -1, FALSE);
+
+        job->fd = ev_dupfd (fd, error);
+        return job->fd != -1;
+}
+
+/**
+ * ev_job_load_fd_set_fd:
+ * @job:
+ * @fd: (transfer full):
+ *
+ * Sets @fd as the file descriptor in @job.
+ * Note that @job takes ownership of @fd; you must not do anything
+ * with it afterwards.
+ *
+ * Since: 3.30
+ */
+void
+ev_job_load_fd_take_fd (EvJobLoadFd *job,
+                        int          fd)
+{
+        g_return_if_fail (EV_IS_JOB_LOAD_FD (job));
+        g_return_if_fail (fd != -1);
+
+        job->fd = fd;
+}
+
+void
+ev_job_load_fd_set_mime_type (EvJobLoadFd *job,
+                              const char  *mime_type)
+{
+        g_return_if_fail (EV_IS_JOB_LOAD_FD (job));
+        g_return_if_fail (mime_type != NULL);
+
+        g_free (job->mime_type);
+        job->mime_type = g_strdup (mime_type);
+}
+
+void
+ev_job_load_fd_set_load_flags (EvJobLoadFd    *job,
+                                   EvDocumentLoadFlags flags)
+{
+        g_return_if_fail (EV_IS_JOB_LOAD_FD (job));
+
+        job->flags = flags;
+}
+
+void
+ev_job_load_fd_set_password (EvJobLoadFd *job,
+                                 const char *password)
+{
+        char *old_password;
+
+        ev_debug_message (DEBUG_JOBS, NULL);
+
+        g_return_if_fail (EV_IS_JOB_LOAD_FD (job));
+
+        old_password = job->password;
+        job->password = g_strdup (password);
+        g_free (old_password);
+}
+
 /* EvJobSave */
 static void
 ev_job_save_init (EvJobSave *job)
diff --git a/libview/ev-jobs.h b/libview/ev-jobs.h
index dda9778d3..04bfda0e7 100644
--- a/libview/ev-jobs.h
+++ b/libview/ev-jobs.h
@@ -66,6 +66,9 @@ typedef struct _EvJobLoadStreamClass EvJobLoadStreamClass;
 typedef struct _EvJobLoadGFile EvJobLoadGFile;
 typedef struct _EvJobLoadGFileClass EvJobLoadGFileClass;
 
+typedef struct _EvJobLoadFd EvJobLoadFd;
+typedef struct _EvJobLoadFdClass EvJobLoadFdClass;
+
 typedef struct _EvJobSave EvJobSave;
 typedef struct _EvJobSaveClass EvJobSaveClass;
 
@@ -159,6 +162,13 @@ typedef struct _EvJobPrintClass EvJobPrintClass;
 #define EV_IS_JOB_LOAD_GFILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_JOB_LOAD_GFILE))
 #define EV_JOB_LOAD_GFILE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_JOB_LOAD_GFILE, 
EvJobLoadGFileClass))
 
+#define EV_TYPE_JOB_LOAD_FD            (ev_job_load_fd_get_type())
+#define EV_JOB_LOAD_FD(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), EV_TYPE_JOB_LOAD_FD, EvJobLoadFd))
+#define EV_IS_JOB_LOAD_FD(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EV_TYPE_JOB_LOAD_FD))
+#define EV_JOB_LOAD_FD_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_JOB_LOAD_FD, 
EvJobLoadFdClass))
+#define EV_IS_JOB_LOAD_FD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_JOB_LOAD_FD))
+#define EV_JOB_LOAD_FD_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_JOB_LOAD_FD, 
EvJobLoadFdClass))
+
 #define EV_TYPE_JOB_SAVE            (ev_job_save_get_type())
 #define EV_JOB_SAVE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), EV_TYPE_JOB_SAVE, EvJobSave))
 #define EV_IS_JOB_SAVE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EV_TYPE_JOB_SAVE))
@@ -416,6 +426,21 @@ struct _EvJobLoadGFileClass
         EvJobClass parent_class;
 };
 
+struct _EvJobLoadFd
+{
+        EvJob parent;
+
+        char *mime_type;
+        char *password;
+        int fd;
+        EvDocumentLoadFlags flags;
+};
+
+struct _EvJobLoadFdClass
+{
+        EvJobClass parent_class;
+};
+
 struct _EvJobSave
 {
        EvJob parent;
@@ -610,6 +635,9 @@ EV_PUBLIC
 void            ev_job_load_stream_set_stream     (EvJobLoadStream    *job,
                                                    GInputStream       *stream);
 EV_PUBLIC
+void            ev_job_load_stream_set_mime_type  (EvJobLoadStream    *job,
+                                                   const char         *mime_type);
+EV_PUBLIC
 void            ev_job_load_stream_set_load_flags (EvJobLoadStream    *job,
                                                    EvDocumentLoadFlags flags);
 EV_PUBLIC
@@ -632,6 +660,36 @@ EV_PUBLIC
 void            ev_job_load_gfile_set_password    (EvJobLoadGFile     *job,
                                                    const gchar        *password);
 
+
+/* EvJobLoadFd */
+EV_PUBLIC
+GType           ev_job_load_fd_get_type       (void) G_GNUC_CONST;
+EV_PUBLIC
+EvJob          *ev_job_load_fd_new            (int                 fd,
+                                               const char         *mime_type,
+                                               EvDocumentLoadFlags flags,
+                                               GError            **error);
+EV_PUBLIC
+EvJob          *ev_job_load_fd_new_take       (int                 fd,
+                                               const char         *mime_type,
+                                               EvDocumentLoadFlags flags);
+EV_PUBLIC
+gboolean        ev_job_load_fd_set_fd         (EvJobLoadFd        *job,
+                                               int                 fd,
+                                               GError            **error);
+EV_PUBLIC
+void            ev_job_load_fd_take_fd        (EvJobLoadFd        *job,
+                                               int                 fd);
+EV_PUBLIC
+void            ev_job_load_fd_set_mime_type  (EvJobLoadFd        *job,
+                                               const char         *mime_type);
+EV_PUBLIC
+void            ev_job_load_fd_set_load_flags (EvJobLoadFd        *job,
+                                               EvDocumentLoadFlags flags);
+EV_PUBLIC
+void            ev_job_load_fd_set_password   (EvJobLoadFd        *job,
+                                               const gchar        *password);
+
 /* EvJobSave */
 EV_PUBLIC
 GType           ev_job_save_get_type      (void) G_GNUC_CONST;


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