[nautilus/sam/tracker-3: 4/7] Use Tracker Miners inside Flatpak when not available on the host




commit b409c15a5ab8f008bcff1d2dd4461890252c252f
Author: Sam Thursfield <sam afuera me uk>
Date:   Sat Aug 1 17:25:27 2020 +0200

    Use Tracker Miners inside Flatpak when not available on the host
    
    This means the Nautilus flatpak will be able to use Tracker on systems
    which don't have Tracker 3 available on the host. It comes at a cost of
    increased resource consumption inside the Flatpak due running an extra
    indexer process there.

 data/meson.build                                   |   1 +
 data/tracker/meson.build                           |  31 ++++++
 ...nome.Nautilus.Tracker3.Miner.Extract.service.in |   7 ++
 ....gnome.Nautilus.Tracker3.Miner.Files.service.in |   7 ++
 data/tracker/org.gnome.Nautilus.domain.rule.in     |  21 ++++
 meson.build                                        |   2 +-
 src/nautilus-batch-rename-utilities.c              |   5 +-
 src/nautilus-search-engine-tracker.c               |   9 +-
 src/nautilus-tag-manager.c                         |  68 ++++++------
 src/nautilus-tracker-utilities.c                   | 120 +++++++++++++++++++++
 src/nautilus-tracker-utilities.h                   |   6 +-
 11 files changed, 236 insertions(+), 41 deletions(-)
---
diff --git a/data/meson.build b/data/meson.build
index e51ed50b1..9a4e2ff52 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -139,3 +139,4 @@ if appstream_util.found()
 endif
 
 subdir('ontology')
+subdir('tracker')
diff --git a/data/tracker/meson.build b/data/tracker/meson.build
new file mode 100644
index 000000000..5320af164
--- /dev/null
+++ b/data/tracker/meson.build
@@ -0,0 +1,31 @@
+# Files needed for running Tracker inside the Flatpak sandbox, for systems
+# which don't have a suitable version of Tracker in the host OS.
+#
+# We must export the .service files from the sandbox so they work on the
+# session bus. This means the Tracker domain name must correspond with the
+# application ID.
+
+domain_ontologies_dir = get_option('datadir') / 'tracker3' / 'domain-ontologies'
+dbus_services_dir = get_option('datadir') / 'dbus-1' / 'services'
+
+tracker_domain_config = configuration_data()
+tracker_domain_config.set('application_id', application_id)
+tracker_domain_config.set('domain_rule', get_option('prefix') / domain_ontologies_dir / application_id + 
'.domain.rule')
+
+configure_file(
+  input: 'org.gnome.Nautilus.domain.rule.in',
+  output: application_id + '.domain.rule',
+  configuration: tracker_domain_config,
+  install_dir: domain_ontologies_dir)
+
+configure_file(
+  input: 'org.gnome.Nautilus.Tracker3.Miner.Extract.service.in',
+  output: application_id + '.Tracker3.Miner.Extract.service',
+  configuration: tracker_domain_config,
+  install_dir: dbus_services_dir)
+
+configure_file(
+  input: 'org.gnome.Nautilus.Tracker3.Miner.Files.service.in',
+  output: application_id + '.Tracker3.Miner.Files.service',
+  configuration: tracker_domain_config,
+  install_dir: dbus_services_dir)
diff --git a/data/tracker/org.gnome.Nautilus.Tracker3.Miner.Extract.service.in 
b/data/tracker/org.gnome.Nautilus.Tracker3.Miner.Extract.service.in
new file mode 100644
index 000000000..eb7a87aa6
--- /dev/null
+++ b/data/tracker/org.gnome.Nautilus.Tracker3.Miner.Extract.service.in
@@ -0,0 +1,7 @@
+[D-BUS Service]
+Name=@application_id@.Tracker3.Miner.Extract
+Exec=/app/libexec/tracker-extract-3 --domain-ontology @domain_rule@
+
+# Miner details needed for tracker-control
+Path=/org/freedesktop/Tracker3/Miner/Extract
+NameSuffix=Miner.Files
diff --git a/data/tracker/org.gnome.Nautilus.Tracker3.Miner.Files.service.in 
b/data/tracker/org.gnome.Nautilus.Tracker3.Miner.Files.service.in
new file mode 100644
index 000000000..4fa7371d1
--- /dev/null
+++ b/data/tracker/org.gnome.Nautilus.Tracker3.Miner.Files.service.in
@@ -0,0 +1,7 @@
+[D-BUS Service]
+Name=@application_id@.Tracker3.Miner.Files
+Exec=/app/libexec/tracker-miner-fs-3 --domain-ontology @domain_rule@ --initial-sleep 0
+
+# Miner details needed for tracker-control
+Path=/org/freedesktop/Tracker3/Miner/Files
+NameSuffix=Miner.Files
diff --git a/data/tracker/org.gnome.Nautilus.domain.rule.in b/data/tracker/org.gnome.Nautilus.domain.rule.in
new file mode 100644
index 000000000..ec0808e30
--- /dev/null
+++ b/data/tracker/org.gnome.Nautilus.domain.rule.in
@@ -0,0 +1,21 @@
+# This defines a private Tracker domain for Nautilus.
+#
+# It's used to run the Tracker indexer inside a Flatpak sandbox, when Nautilus
+# is running on a host that doesn't have a suitable version of Tracker
+# installed.
+
+[DomainOntology]
+# Location for the Tracker database
+CacheLocation=$XDG_CACHE_HOME/nautilus/miner/files
+
+# Name of the ontology to use, must be one located in
+# $(sharedir)/tracker/ontologies
+OntologyName=nepomuk
+
+# DBus name for the owner (not optional). Tracker will use
+# the domain as the prefix of the DBus name for all the
+# services related to this domain ontology.
+Domain=@application_id@
+
+# List of miners we expect to run in this domain.
+Miners=Miner.Files;Miner.Extract
diff --git a/meson.build b/meson.build
index bb36b8a20..c33c0c5e7 100644
--- a/meson.build
+++ b/meson.build
@@ -6,7 +6,7 @@ project('nautilus', 'c',
   #  * Update GTK-based codes over src/gtk/gtk-code-generator.sh
   version: '3.37.91',
 
-  meson_version: '>= 0.47.0',
+  meson_version: '>= 0.49.0',
   license: 'GPL3+'
 )
 
diff --git a/src/nautilus-batch-rename-utilities.c b/src/nautilus-batch-rename-utilities.c
index b6cea25fa..0412a172e 100644
--- a/src/nautilus-batch-rename-utilities.c
+++ b/src/nautilus-batch-rename-utilities.c
@@ -19,6 +19,7 @@
 #include "nautilus-batch-rename-dialog.h"
 #include "nautilus-batch-rename-utilities.h"
 #include "nautilus-file.h"
+#include "nautilus-tracker-utilities.h"
 
 #include <glib.h>
 #include <gtk/gtk.h>
@@ -63,8 +64,6 @@ enum
     ALBUM_NAME_INDEX,
 } QueryMetadata;
 
-#define TRACKER_MINER_FS_BUSNAME "org.freedesktop.Tracker3.Miner.Files"
-
 static void on_cursor_callback (GObject      *object,
                                 GAsyncResult *result,
                                 gpointer      user_data);
@@ -1119,7 +1118,7 @@ check_metadata_for_selection (NautilusBatchRenameDialog *dialog,
 
     g_string_append (query, "} ORDER BY ASC(nie:contentCreated(?content))");
 
-    connection = tracker_sparql_connection_bus_new (TRACKER_MINER_FS_BUSNAME, NULL, NULL, &error);
+    connection = nautilus_tracker_get_miner_fs_connection (&error);
     if (!connection)
     {
         if (error)
diff --git a/src/nautilus-search-engine-tracker.c b/src/nautilus-search-engine-tracker.c
index 77a9193c1..099e1f471 100644
--- a/src/nautilus-search-engine-tracker.c
+++ b/src/nautilus-search-engine-tracker.c
@@ -25,6 +25,7 @@
 #include "nautilus-search-engine-private.h"
 #include "nautilus-search-hit.h"
 #include "nautilus-search-provider.h"
+#include "nautilus-tracker-utilities.h"
 #define DEBUG_FLAG NAUTILUS_DEBUG_SEARCH
 #include "nautilus-debug.h"
 
@@ -55,8 +56,6 @@ enum
     LAST_PROP
 };
 
-#define TRACKER_MINER_FS_BUSNAME "org.freedesktop.Tracker3.Miner.Files"
-
 static void nautilus_search_provider_init (NautilusSearchProviderInterface *iface);
 
 G_DEFINE_TYPE_WITH_CODE (NautilusSearchEngineTracker,
@@ -79,8 +78,9 @@ finalize (GObject *object)
     }
 
     g_clear_object (&tracker->query);
-    g_clear_object (&tracker->connection);
     g_queue_free_full (tracker->hits_pending, g_object_unref);
+    /* This is a singleton, no need to unref. */
+    tracker->connection = NULL;
 
     G_OBJECT_CLASS (nautilus_search_engine_tracker_parent_class)->finalize (object);
 }
@@ -597,8 +597,7 @@ nautilus_search_engine_tracker_init (NautilusSearchEngineTracker *engine)
 
     engine->hits_pending = g_queue_new ();
 
-    engine->connection = tracker_sparql_connection_bus_new (TRACKER_MINER_FS_BUSNAME, NULL, NULL, &error);
-
+    engine->connection = nautilus_tracker_get_miner_fs_connection (&error);
     if (error)
     {
         g_warning ("Could not establish a connection to Tracker: %s", error->message);
diff --git a/src/nautilus-tag-manager.c b/src/nautilus-tag-manager.c
index 8009e6ca9..e21749a10 100644
--- a/src/nautilus-tag-manager.c
+++ b/src/nautilus-tag-manager.c
@@ -21,6 +21,7 @@
 #include "nautilus-file.h"
 #include "nautilus-file-undo-operations.h"
 #include "nautilus-file-undo-manager.h"
+#include "nautilus-tracker-utilities.h"
 #define DEBUG_FLAG NAUTILUS_DEBUG_TAG_MANAGER
 #include "nautilus-debug.h"
 
@@ -35,6 +36,7 @@ struct _NautilusTagManager
     gboolean tracker_ok;
     TrackerSparqlConnection *local;
     TrackerSparqlConnection *miner_fs;
+    const gchar *miner_fs_busname;
     TrackerNotifier *notifier;
 
     TrackerSparqlStatement *query_starred_files;
@@ -81,14 +83,12 @@ enum
     LAST_SIGNAL
 };
 
-#define TRACKER_MINER_FS_BUSNAME "org.freedesktop.Tracker3.Miner.Files"
-
 #define QUERY_STARRED_FILES \
     "SELECT ?file_url ?content_id " \
     "{ " \
     "    ?content_urn a nautilus:FileReference ; " \
     "        nautilus:starred true . " \
-    "    SERVICE <dbus:" TRACKER_MINER_FS_BUSNAME "> { " \
+    "    SERVICE <dbus:%s> { " \
     "        ?content_urn nie:isStoredAs ?file_url . " \
     "        BIND (tracker:id (?content_urn) AS ?content_id) " \
     "    } " \
@@ -97,7 +97,7 @@ enum
 #define QUERY_UPDATED_FILE_URL \
     "SELECT ?file_url EXISTS { ?content_urn nautilus:starred true } AS ?starred" \
     "{ " \
-    "    SERVICE <dbus:" TRACKER_MINER_FS_BUSNAME "> { " \
+    "    SERVICE <dbus:%s> { " \
     "        ?content_urn nie:isStoredAs ?file_url . " \
     "        FILTER (tracker:id(?content_urn) = ~id) " \
     "    }" \
@@ -432,14 +432,15 @@ nautilus_tag_manager_delete_tag (NautilusTagManager *self,
                                  GList              *selection,
                                  GString            *query)
 {
-    g_string_append (query,
-                     "DELETE { "
-                     "    ?content_urn a nautilus:FileReference ; "
-                     "        nautilus:starred true . "
-                     "} "
-                     "WHERE { "
-                     "  SERVICE <dbus:" TRACKER_MINER_FS_BUSNAME "> { "
-                     "    ?content_urn nie:isStoredAs ?file_url . ");
+    g_string_append_printf (query,
+                            "DELETE { "
+                            "    ?content_urn a nautilus:FileReference ; "
+                            "        nautilus:starred true . "
+                            "} "
+                            "WHERE { "
+                            "  SERVICE <dbus:%s> { "
+                            "    ?content_urn nie:isStoredAs ?file_url . ",
+                            self->miner_fs_busname);
 
     query = add_selection_filter (selection, query);
 
@@ -453,13 +454,14 @@ nautilus_tag_manager_insert_tag (NautilusTagManager *self,
                                  GList              *selection,
                                  GString            *query)
 {
-    g_string_append (query,
-                     "INSERT { "
-                     "    ?content_urn a nautilus:FileReference . "
-                     "        ?content_urn nautilus:starred true . "
-                     "} WHERE { "
-                     "  SERVICE <dbus:" TRACKER_MINER_FS_BUSNAME "> { "
-                     "    ?content_urn nie:isStoredAs ?file_url . ");
+    g_string_append_printf (query,
+                            "INSERT { "
+                            "    ?content_urn a nautilus:FileReference . "
+                            "        ?content_urn nautilus:starred true . "
+                            "} WHERE { "
+                            "  SERVICE <dbus:%s> { "
+                            "    ?content_urn nie:isStoredAs ?file_url . ",
+                            self->miner_fs_busname);
 
     query = add_selection_filter (selection, query);
 
@@ -570,11 +572,13 @@ nautilus_tag_manager_get_file_ids_for_urls (NautilusTagManager *self,
 {
     GString *query;
 
-    query = g_string_new ("SELECT ?file_url ?content_id "
-                          "WHERE { "
-                          "  SERVICE <dbus:" TRACKER_MINER_FS_BUSNAME "> { "
-                          "    ?content_urn nie:isStoredAs ?file_url . "
-                          "    BIND (tracker:id (?content_urn) AS ?content_id) ");
+    query = g_string_new ("");
+    g_string_append_printf (query, "SELECT ?file_url ?content_id "
+                            "WHERE { "
+                            "  SERVICE <dbus:%s> { "
+                            "    ?content_urn nie:isStoredAs ?file_url . "
+                            "    BIND (tracker:id (?content_urn) AS ?content_id) ",
+                            self->miner_fs_busname);
 
     query = add_selection_filter (selection, query);
 
@@ -890,6 +894,7 @@ setup_tracker_connections (NautilusTagManager  *self,
                            GError             **error)
 {
     const gchar *datadir;
+    gchar *query_with_busname;
     g_autofree gchar *store_path = NULL;
     g_autofree gchar *ontology_path = NULL;
     g_autoptr (GFile) store = NULL;
@@ -917,31 +922,32 @@ setup_tracker_connections (NautilusTagManager  *self,
     }
 
     /* Connect to Tracker filesystem index to follow file renames. */
-    self->miner_fs = tracker_sparql_connection_bus_new (TRACKER_MINER_FS_BUSNAME,
-                                                        NULL,
-                                                        NULL,
-                                                        error);
-
+    self->miner_fs = nautilus_tracker_get_miner_fs_connection (error);
     if (*error)
     {
         return FALSE;
     }
+    self->miner_fs_busname = nautilus_tracker_get_miner_fs_busname (NULL);
 
     /* Prepare reusable queries. */
+    query_with_busname = g_strdup_printf (QUERY_UPDATED_FILE_URL, self->miner_fs_busname);
     self->query_updated_file_url = tracker_sparql_connection_query_statement (self->local,
-                                                                              QUERY_UPDATED_FILE_URL,
+                                                                              query_with_busname,
                                                                               cancellable,
                                                                               error);
+    g_free (query_with_busname);
 
     if (*error)
     {
         return FALSE;
     }
 
+    query_with_busname = g_strdup_printf (QUERY_STARRED_FILES, self->miner_fs_busname);
     self->query_starred_files = tracker_sparql_connection_query_statement (self->local,
-                                                                           QUERY_STARRED_FILES,
+                                                                           query_with_busname,
                                                                            cancellable,
                                                                            error);
+    g_free (query_with_busname);
 
     if (*error)
     {
diff --git a/src/nautilus-tracker-utilities.c b/src/nautilus-tracker-utilities.c
index b220df4bd..4c408942e 100644
--- a/src/nautilus-tracker-utilities.c
+++ b/src/nautilus-tracker-utilities.c
@@ -18,12 +18,132 @@
  * SPDX-License-Identifier: GPL-3.0-or-later
  */
 
+#include "config.h"
 #include "nautilus-tracker-utilities.h"
 #include "nautilus-global-preferences.h"
 
 #define TRACKER_KEY_RECURSIVE_DIRECTORIES "index-recursive-directories"
 #define TRACKER_KEY_SINGLE_DIRECTORIES "index-single-directories"
 
+/* Shared global connection to Tracker Miner FS */
+static const gchar *tracker_miner_fs_busname = NULL;
+static TrackerSparqlConnection *tracker_miner_fs_connection = NULL;
+static GError *tracker_miner_fs_error = NULL;
+
+static gboolean
+get_host_tracker_miner_fs (GError **error)
+{
+    const gchar *busname = "org.freedesktop.Tracker3.Miner.Files";
+
+    g_message ("Connecting to %s", busname);
+    tracker_miner_fs_connection = tracker_sparql_connection_bus_new (busname, NULL, NULL, error);
+    if (*error)
+    {
+        g_warning ("Unable to create connection for session-wide Tracker indexer: %s", (*error)->message);
+        return FALSE;
+    }
+
+    tracker_miner_fs_busname = busname;
+    return TRUE;
+}
+
+static gboolean
+start_local_tracker_miner_fs (GError **error)
+{
+    const gchar *busname = APPLICATION_ID ".Tracker3.Miner.Files";
+
+    g_message ("Starting %s", busname);
+    tracker_miner_fs_connection = tracker_sparql_connection_bus_new (busname, NULL, NULL, error);
+    if (*error)
+    {
+        g_critical ("Could not start local Tracker indexer at %s: %s", busname, (*error)->message);
+        return FALSE;
+    }
+
+    tracker_miner_fs_busname = busname;
+    return TRUE;
+}
+
+static gboolean
+inside_flatpak (void)
+{
+    return g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS);
+}
+
+static void
+setup_tracker_miner_fs_connection (void)
+{
+    static gsize tried_tracker_init = FALSE;
+
+    if (g_once_init_enter (&tried_tracker_init))
+    {
+        gboolean success;
+
+        success = get_host_tracker_miner_fs (&tracker_miner_fs_error);
+
+        if (!success && inside_flatpak ())
+        {
+            g_clear_error (&tracker_miner_fs_error);
+            success = start_local_tracker_miner_fs (&tracker_miner_fs_error);
+        }
+
+        g_once_init_leave (&tried_tracker_init, TRUE);
+    }
+}
+
+/**
+ * nautilus_tracker_get_miner_fs_connection:
+ * @error: return location for a #GError
+ *
+ * This function returns a global singleton #TrackerSparqlConnection, or %NULL
+ * if we couldn't connect to Tracker Miner FS.
+ *
+ * The first time you call it, this function will block while trying to connect.
+ * This may take some time if starting Tracker Miners from a Flatpak bundle.
+ *
+ * The returned object is a globally shared singleton which should NOT be
+ * unreffed.
+ *
+ * Returns: a #TrackerSparqlConnection, or %NULL
+ */
+TrackerSparqlConnection *
+nautilus_tracker_get_miner_fs_connection (GError **error)
+{
+    setup_tracker_miner_fs_connection ();
+
+    if (tracker_miner_fs_error && error)
+    {
+        *error = g_error_copy (tracker_miner_fs_error);
+    }
+
+    return tracker_miner_fs_connection;
+}
+
+/**
+ * nautilus_tracker_get_miner_fs_busname:
+ * @error: return location for a #GError
+ *
+ * This function returns a DBus name that can be used to talk to
+ * tracker-miner-fs, or %NULL if there is no Tracker Miner FS available.
+ *
+ * The first time you call it, this function will block while trying to connect.
+ * This may take some time if starting Tracker Miners from a Flatpak bundle.
+ *
+ * Returns: a string
+ */
+const gchar *
+nautilus_tracker_get_miner_fs_busname (GError **error)
+{
+    setup_tracker_miner_fs_connection ();
+
+    if (tracker_miner_fs_error && error)
+    {
+        *error = g_error_copy (tracker_miner_fs_error);
+    }
+
+    return tracker_miner_fs_busname;
+}
+
 static GFile *
 location_from_tracker_dir (const gchar *value)
 {
diff --git a/src/nautilus-tracker-utilities.h b/src/nautilus-tracker-utilities.h
index f509c3005..d4b2eba0c 100644
--- a/src/nautilus-tracker-utilities.h
+++ b/src/nautilus-tracker-utilities.h
@@ -22,5 +22,9 @@
 #pragma once
 
 #include <gio/gio.h>
+#include <libtracker-sparql/tracker-sparql.h>
 
-gboolean nautilus_tracker_directory_is_tracked (GFile *directory);
+TrackerSparqlConnection * nautilus_tracker_get_miner_fs_connection (GError **error);
+const gchar *             nautilus_tracker_get_miner_fs_busname    (GError **error);
+
+gboolean  nautilus_tracker_directory_is_tracked (GFile *directory);


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