Commit be6422f3 authored by Sam Thursfield's avatar Sam Thursfield
Browse files

Merge branch 'wip/carlosg/sandboxed-notifiers' into 'master'

Fixes to change notifications in the sandbox

Closes #287

See merge request !373
parents 5dc1ac2c 85724dda
Pipeline #259709 passed with stages
in 7 minutes and 16 seconds
......@@ -83,6 +83,10 @@ struct _TrackerDataManager {
GHashTable *transaction_graphs;
GHashTable *graphs;
/* Cached remote connections */
GMutex connections_lock;
GHashTable *cached_connections;
gchar *status;
};
......@@ -142,6 +146,7 @@ static void
tracker_data_manager_init (TrackerDataManager *manager)
{
manager->generation = 1;
g_mutex_init (&manager->connections_lock);
}
GQuark
......@@ -3829,7 +3834,7 @@ tracker_data_manager_initable_init (GInitable *initable,
manager->update_cache_size,
busy_callback, manager,
G_OBJECT (manager),
manager->ontologies,
manager,
&internal_error);
if (!manager->db_manager) {
g_propagate_error (error, internal_error);
......@@ -4484,6 +4489,8 @@ tracker_data_manager_dispose (GObject *object)
g_clear_object (&manager->db_manager);
}
g_clear_pointer (&manager->cached_connections, g_hash_table_unref);
G_OBJECT_CLASS (tracker_data_manager_parent_class)->dispose (object);
}
......@@ -4496,6 +4503,7 @@ tracker_data_manager_finalize (GObject *object)
g_clear_object (&manager->data_update);
g_clear_pointer (&manager->graphs, g_hash_table_unref);
g_free (manager->status);
g_mutex_clear (&manager->connections_lock);
G_OBJECT_CLASS (tracker_data_manager_parent_class)->finalize (object);
}
......@@ -4963,3 +4971,88 @@ tracker_data_manager_expand_prefix (TrackerDataManager *manager,
return TRUE;
}
TrackerSparqlConnection *
tracker_data_manager_get_remote_connection (TrackerDataManager *data_manager,
const gchar *uri,
GError **error)
{
TrackerSparqlConnection *connection = NULL;
GError *inner_error = NULL;
gchar *uri_scheme = NULL;
g_mutex_lock (&data_manager->connections_lock);
if (!data_manager->cached_connections) {
data_manager->cached_connections =
g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_object_unref);
}
connection = g_hash_table_lookup (data_manager->cached_connections, uri);
if (!connection) {
uri_scheme = g_uri_parse_scheme (uri);
if (g_strcmp0 (uri_scheme, "dbus") == 0) {
gchar *bus_name, *object_path;
GDBusConnection *dbus_connection;
GBusType bus_type;
if (!tracker_util_parse_dbus_uri (uri,
&bus_type,
&bus_name, &object_path)) {
g_set_error (&inner_error,
TRACKER_SPARQL_ERROR,
TRACKER_SPARQL_ERROR_PARSE,
"Failed to parse uri '%s'",
uri);
goto fail;
}
if (!g_dbus_is_name (bus_name)) {
g_set_error (&inner_error,
TRACKER_SPARQL_ERROR,
TRACKER_SPARQL_ERROR_PARSE,
"Invalid bus name '%s'",
bus_name);
goto fail;
}
dbus_connection = g_bus_get_sync (bus_type, NULL, &inner_error);
if (!dbus_connection)
goto fail;
connection = tracker_sparql_connection_bus_new (bus_name, object_path,
dbus_connection, &inner_error);
g_free (bus_name);
g_free (object_path);
if (!connection)
goto fail;
} else if (g_strcmp0 (uri_scheme, "http") == 0) {
connection = tracker_sparql_connection_remote_new (uri);
}
if (!connection) {
g_set_error (&inner_error,
TRACKER_SPARQL_ERROR,
TRACKER_SPARQL_ERROR_UNSUPPORTED,
"Unsupported uri '%s'",
uri);
goto fail;
}
g_hash_table_insert (data_manager->cached_connections,
g_strdup (uri),
connection);
}
fail:
g_mutex_unlock (&data_manager->connections_lock);
g_free (uri_scheme);
if (inner_error)
g_propagate_error (error, inner_error);
return connection;
}
......@@ -112,6 +112,9 @@ gboolean tracker_data_manager_expand_prefix (TrackerDataManager *ma
GHashTable *prefix_map,
gchar **prefix,
gchar **expanded);
TrackerSparqlConnection * tracker_data_manager_get_remote_connection (TrackerDataManager *data_manager,
const gchar *uri,
GError **error);
G_END_DECLS
......
......@@ -3754,10 +3754,10 @@ tracker_db_interface_get_is_used (TrackerDBInterface *db_interface)
gboolean
tracker_db_interface_init_vtabs (TrackerDBInterface *db_interface,
TrackerOntologies *ontologies)
gpointer vtab_data)
{
tracker_vtab_triples_init (db_interface->db, ontologies);
tracker_vtab_service_init (db_interface->db, ontologies);
tracker_vtab_triples_init (db_interface->db, vtab_data);
tracker_vtab_service_init (db_interface->db, vtab_data);
return TRUE;
}
......
......@@ -59,7 +59,7 @@ gboolean tracker_db_interface_sqlite_wal_checkpoint (TrackerD
gboolean blocking,
GError **error);
gboolean tracker_db_interface_init_vtabs (TrackerDBInterface *interface,
TrackerOntologies *ontologies);
gpointer vtab_data);
void tracker_db_interface_sqlite_fts_delete_table (TrackerDBInterface *interface,
const gchar *database);
......
......@@ -35,12 +35,12 @@
typedef struct {
sqlite3 *db;
TrackerDataManager *data_manager;
} TrackerServiceModule;
typedef struct {
struct sqlite3_vtab parent;
TrackerServiceModule *module;
GHashTable *cached_connections;
GList *cursors;
} TrackerServiceVTab;
......@@ -86,7 +86,6 @@ tracker_service_vtab_free (gpointer data)
{
TrackerServiceVTab *vtab = data;
g_hash_table_unref (vtab->cached_connections);
g_list_free (vtab->cursors);
g_free (vtab);
}
......@@ -119,10 +118,6 @@ service_create (sqlite3 *db,
vtab = g_new0 (TrackerServiceVTab, 1);
vtab->module = module;
vtab->cached_connections = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
g_object_unref);
str = g_string_new ("CREATE TABLE x(\n");
......@@ -295,10 +290,11 @@ service_filter (sqlite3_vtab_cursor *vtab_cursor,
{
TrackerServiceCursor *cursor = (TrackerServiceCursor *) vtab_cursor;
const ConstraintData *constraints = (const ConstraintData *) idx_str;
TrackerServiceVTab *vtab = cursor->vtab;
TrackerServiceModule *module = vtab->module;
TrackerSparqlConnection *connection;
TrackerSparqlStatement *statement;
GHashTable *names = NULL, *values = NULL;
gchar *uri_scheme = NULL;
GError *error = NULL;
gint i;
......@@ -360,64 +356,11 @@ service_filter (sqlite3_vtab_cursor *vtab_cursor,
goto fail;
}
connection = g_hash_table_lookup (cursor->vtab->cached_connections,
cursor->service);
if (!connection) {
uri_scheme = g_uri_parse_scheme (cursor->service);
if (g_strcmp0 (uri_scheme, "dbus") == 0) {
gchar *bus_name, *object_path;
GDBusConnection *dbus_connection;
GBusType bus_type;
if (!tracker_util_parse_dbus_uri (cursor->service,
&bus_type,
&bus_name, &object_path)) {
g_set_error (&error,
TRACKER_SPARQL_ERROR,
TRACKER_SPARQL_ERROR_PARSE,
"Failed to parse uri '%s'",
cursor->service);
goto fail;
}
if (!g_dbus_is_name (bus_name)) {
g_set_error (&error,
TRACKER_SPARQL_ERROR,
TRACKER_SPARQL_ERROR_PARSE,
"Invalid bus name '%s'",
bus_name);
goto fail;
}
dbus_connection = g_bus_get_sync (bus_type, NULL, &error);
if (!dbus_connection)
goto fail;
connection = tracker_sparql_connection_bus_new (bus_name, object_path,
dbus_connection, &error);
g_free (bus_name);
g_free (object_path);
if (!connection)
goto fail;
} else if (g_strcmp0 (uri_scheme, "http") == 0) {
connection = tracker_sparql_connection_remote_new (cursor->service);
}
if (!connection) {
g_set_error (&error,
TRACKER_SPARQL_ERROR,
TRACKER_SPARQL_ERROR_UNSUPPORTED,
"Unsupported uri '%s'",
cursor->service);
goto fail;
}
g_hash_table_insert (cursor->vtab->cached_connections,
g_strdup (cursor->service),
connection);
}
connection = tracker_data_manager_get_remote_connection (module->data_manager,
cursor->service,
&error);
if (!connection)
goto fail;
statement = tracker_sparql_connection_query_statement (connection,
cursor->query,
......@@ -440,14 +383,11 @@ service_filter (sqlite3_vtab_cursor *vtab_cursor,
if (error)
goto fail;
g_free (uri_scheme);
return SQLITE_OK;
fail:
g_clear_pointer (&names, g_hash_table_unref);
g_clear_pointer (&values, g_hash_table_unref);
g_free (uri_scheme);
if (cursor->silent) {
cursor->finished = TRUE;
......@@ -566,8 +506,8 @@ service_rowid (sqlite3_vtab_cursor *vtab_cursor,
}
void
tracker_vtab_service_init (sqlite3 *db,
TrackerOntologies *ontologies)
tracker_vtab_service_init (sqlite3 *db,
TrackerDataManager *data_manager)
{
TrackerServiceModule *module;
static const sqlite3_module service_module = {
......@@ -598,6 +538,7 @@ tracker_vtab_service_init (sqlite3 *db,
module = g_new0 (TrackerServiceModule, 1);
module->db = db;
module->data_manager = data_manager;
sqlite3_create_module_v2 (db, "tracker_service", &service_module,
module, tracker_service_module_free);
}
......@@ -19,12 +19,12 @@
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#include <sqlite3.h>
#include "tracker-ontologies.h"
#include "tracker-data-manager.h"
#ifndef __TRACKER_VTAB_SERVICE_H__
#define __TRACKER_VTAB_SERVICE_H__
void tracker_vtab_service_init (sqlite3 *db,
TrackerOntologies *ontologies);
void tracker_vtab_service_init (sqlite3 *db,
TrackerDataManager *data_manager);
#endif /* __TRACKER_VTAB_SERVICE_H__ */
......@@ -20,6 +20,7 @@
*/
#include "config.h"
#include "tracker-ontologies.h"
#include "tracker-vtab-triples.h"
/* Define some constraints for older SQLite, we will never get
......@@ -594,10 +595,11 @@ triples_rowid (sqlite3_vtab_cursor *vtab_cursor,
}
void
tracker_vtab_triples_init (sqlite3 *db,
TrackerOntologies *ontologies)
tracker_vtab_triples_init (sqlite3 *db,
TrackerDataManager *data_manager)
{
TrackerTriplesModule *module;
TrackerOntologies *ontologies;
static const sqlite3_module triples_module = {
2, /* version */
NULL, /* create(), null because this is an eponymous-only table */
......@@ -626,6 +628,7 @@ tracker_vtab_triples_init (sqlite3 *db,
module = g_new0 (TrackerTriplesModule, 1);
module->db = db;
ontologies = tracker_data_manager_get_ontologies (data_manager);
g_set_object (&module->ontologies, ontologies);
sqlite3_create_module_v2 (db, "tracker_triples", &triples_module,
module, tracker_triples_module_free);
......
......@@ -19,12 +19,12 @@
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#include <sqlite3.h>
#include "tracker-ontologies.h"
#include "tracker-data-manager.h"
#ifndef __TRACKER_VTAB_TRIPLES_H__
#define __TRACKER_VTAB_TRIPLES_H__
void tracker_vtab_triples_init (sqlite3 *db,
TrackerOntologies *ontologies);
void tracker_vtab_triples_init (sqlite3 *db,
TrackerDataManager *data_manager);
#endif /* __TRACKER_VTAB_TRIPLES_H__ */
......@@ -24,6 +24,7 @@
#include "tracker-direct-batch.h"
#include "tracker-direct-statement.h"
#include "libtracker-sparql/tracker-private.h"
#include <libtracker-common/tracker-utils.h>
#include <libtracker-data/tracker-data.h>
#include <libtracker-data/tracker-sparql.h>
#include <libtracker-sparql/tracker-notifier-private.h>
......@@ -1176,6 +1177,46 @@ tracker_direct_connection_create_batch (TrackerSparqlConnection *connection)
return tracker_direct_batch_new (connection);
}
static gboolean
tracker_direct_connection_lookup_dbus_service (TrackerSparqlConnection *connection,
const gchar *dbus_name,
const gchar *dbus_path,
gchar **name,
gchar **path)
{
TrackerDirectConnectionPrivate *priv;
TrackerDirectConnection *conn;
TrackerSparqlConnection *remote;
GError *error = NULL;
gchar *uri;
conn = TRACKER_DIRECT_CONNECTION (connection);
priv = tracker_direct_connection_get_instance_private (conn);
uri = tracker_util_build_dbus_uri (G_BUS_TYPE_SESSION,
dbus_name, dbus_path);
remote = tracker_data_manager_get_remote_connection (priv->data_manager,
uri, &error);
if (error) {
g_warning ("Error getting remote connection '%s': %s", uri, error->message);
g_error_free (error);
}
g_free (uri);
if (!remote)
return FALSE;
if (!g_object_class_find_property (G_OBJECT_GET_CLASS (remote), "bus-name"))
return FALSE;
g_object_get (remote,
"bus-name", name,
"bus-object-path", path,
NULL);
return TRUE;
}
static void
tracker_direct_connection_class_init (TrackerDirectConnectionClass *klass)
{
......@@ -1210,6 +1251,7 @@ tracker_direct_connection_class_init (TrackerDirectConnectionClass *klass)
sparql_connection_class->update_resource_async = tracker_direct_connection_update_resource_async;
sparql_connection_class->update_resource_finish = tracker_direct_connection_update_resource_finish;
sparql_connection_class->create_batch = tracker_direct_connection_create_batch;
sparql_connection_class->lookup_dbus_service = tracker_direct_connection_lookup_dbus_service;
props[PROP_FLAGS] =
g_param_spec_flags ("flags",
......
......@@ -93,6 +93,29 @@ tracker_sparql_connection_class_init (TrackerSparqlConnectionClass *klass)
object_class->dispose = tracker_sparql_connection_dispose;
}
gboolean
tracker_sparql_connection_lookup_dbus_service (TrackerSparqlConnection *connection,
const gchar *dbus_name,
const gchar *dbus_path,
gchar **name,
gchar **path)
{
TrackerSparqlConnectionClass *connection_class;
g_return_val_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection), FALSE);
g_return_val_if_fail (dbus_name != NULL, FALSE);
connection_class = TRACKER_SPARQL_CONNECTION_GET_CLASS (connection);
if (!connection_class->lookup_dbus_service)
return FALSE;
return TRACKER_SPARQL_CONNECTION_GET_CLASS (connection)->lookup_dbus_service (connection,
dbus_name,
dbus_path,
name,
path);
}
/* The constructor functions are defined in the libtracker-sparql-backend, but
* documented here. */
......
......@@ -50,6 +50,7 @@
#include "tracker-private.h"
#include "tracker-sparql-enum-types.h"
#include <libtracker-common/tracker-common.h>
#include <direct/tracker-direct.h>
typedef struct _TrackerNotifierPrivate TrackerNotifierPrivate;
typedef struct _TrackerNotifierSubscription TrackerNotifierSubscription;
......@@ -811,6 +812,7 @@ tracker_notifier_signal_subscribe (TrackerNotifier *notifier,
{
TrackerNotifierSubscription *subscription;
TrackerNotifierPrivate *priv;
gchar *dbus_name = NULL, *dbus_path = NULL, *full_graph = NULL;
g_return_val_if_fail (TRACKER_IS_NOTIFIER (notifier), 0);
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
......@@ -821,16 +823,32 @@ tracker_notifier_signal_subscribe (TrackerNotifier *notifier,
if (!object_path)
object_path = DEFAULT_OBJECT_PATH;
if (graph) {
TrackerNamespaceManager *namespaces;
namespaces = tracker_sparql_connection_get_namespace_manager (priv->connection);
if (namespaces) {
full_graph = tracker_namespace_manager_expand_uri (namespaces,
graph);
}
}
tracker_sparql_connection_lookup_dbus_service (priv->connection,
service,
object_path,
&dbus_name,
&dbus_path);
subscription = tracker_notifier_subscription_new (notifier, connection,
service, object_path);
subscription->handler_id =
g_dbus_connection_signal_subscribe (connection,
service,
dbus_name ? dbus_name : service,
"org.freedesktop.Tracker3.Endpoint",
"GraphUpdated",
object_path,
graph,
dbus_path ? dbus_path : object_path,
full_graph ? full_graph : graph,
G_DBUS_SIGNAL_FLAGS_NONE,
graph_updated_cb,
subscription, NULL);
......@@ -839,6 +857,10 @@ tracker_notifier_signal_subscribe (TrackerNotifier *notifier,
GUINT_TO_POINTER (subscription->handler_id),
subscription);
g_free (dbus_name);
g_free (dbus_path);
g_free (full_graph);
return subscription->handler_id;
}
......
......@@ -106,6 +106,12 @@ struct _TrackerSparqlConnectionClass
GAsyncResult *res,
GError **error);
TrackerBatch * (* create_batch) (TrackerSparqlConnection *connection);
gboolean (* lookup_dbus_service) (TrackerSparqlConnection *connection,
const gchar *dbus_name,
const gchar *dbus_path,
gchar **name,
gchar **path);
};
typedef struct _TrackerSparqlCursorClass TrackerSparqlCursorClass;
......@@ -262,6 +268,12 @@ struct _TrackerSerializerClass {
GInputStreamClass parent_class;
};
gboolean
tracker_sparql_connection_lookup_dbus_service (TrackerSparqlConnection *connection,
const gchar *dbus_name,
const gchar *dbus_path,
gchar **name,
gchar **path);
void tracker_sparql_cursor_set_connection (TrackerSparqlCursor *cursor,
TrackerSparqlConnection *connection);
GError * _translate_internal_error (GError *error);
......
......@@ -92,6 +92,26 @@ tracker_portal_endpoint_filter_graph (TrackerEndpointDBus *endpoint_dbus,
return FALSE;
} else if (g_strcmp0 (graph_name, endpoint->graphs[i]) == 0) {
return FALSE;
} else {
TrackerNamespaceManager *namespaces;
gchar *expanded;
/* We may have been given a prefixed name instead of an
* URI, expand it in order to check with the given graph.
*
* FIXME: This is not going to work for prefixes outside
* the well-known namespaces.
*/
namespaces = tracker_namespace_manager_get_default ();
expanded = tracker_namespace_manager_expand_uri (namespaces,
endpoint->graphs[i]);
if (g_strcmp0 (graph_name, expanded) == 0) {
g_free (expanded);
return FALSE;
}
g_free (expanded);
}
}
......
......@@ -210,6 +210,7 @@ class TrackerPortalTest(ut.TestCase):
extra_env = {}
extra_env['TRACKER_TEST_PORTAL_FLATPAK_INFO'] = cfg.TEST_PORTAL_FLATPAK_INFO
self.loop = trackertestutils.mainloop.MainLoop()
self.message_queues = {}
self.connections = {}
self.sandbox = trackertestutils.helpers.TrackerDBusSandbox(
......@@ -219,6 +220,7 @@ class TrackerPortalTest(ut.TestCase):
self.bus = self.sandbox.get_session_bus_connection()
self.dbus_address = self.sandbox.get_session_bus_address()
os.environ['DBUS_SESSION_BUS_ADDRESS'] = self.dbus_address
try:
log.info("Starting portal")
......@@ -272,6 +274,13 @@ class TrackerPortalTest(ut.TestCase):
return store.query(sparql)