[kdbus] Do not set body message if signature field is empty
[platform/upstream/glib.git] / gio / gdelayedsettingsbackend.c
index fd166a1..22a42eb 100644 (file)
@@ -12,9 +12,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  *
  * Author: Ryan Lortie <desrt@desrt.ca>
  */
 struct _GDelayedSettingsBackendPrivate
 {
   GSettingsBackend *backend;
-  GStaticMutex lock;
+  GMutex lock;
   GTree *delayed;
 
   GMainContext *owner_context;
   gpointer owner;
 };
 
-G_DEFINE_TYPE (GDelayedSettingsBackend,
-               g_delayed_settings_backend,
-               G_TYPE_SETTINGS_BACKEND)
+G_DEFINE_TYPE_WITH_PRIVATE (GDelayedSettingsBackend,
+                            g_delayed_settings_backend,
+                            G_TYPE_SETTINGS_BACKEND)
 
 static gboolean
 invoke_notify_unapplied (gpointer data)
@@ -56,7 +54,7 @@ g_delayed_settings_backend_notify_unapplied (GDelayedSettingsBackend *delayed)
   GMainContext *target_context;
   GObject *target;
 
-  g_static_mutex_lock (&delayed->priv->lock);
+  g_mutex_lock (&delayed->priv->lock);
   if (delayed->priv->owner)
     {
       target_context = delayed->priv->owner_context;
@@ -67,24 +65,10 @@ g_delayed_settings_backend_notify_unapplied (GDelayedSettingsBackend *delayed)
       target_context = NULL;
       target = NULL;
     }
-  g_static_mutex_unlock (&delayed->priv->lock);
+  g_mutex_unlock (&delayed->priv->lock);
 
   if (target != NULL)
-    {
-      if (g_settings_backend_get_active_context () != target_context)
-        {
-          GSource *source;
-
-          source = g_idle_source_new ();
-          g_source_set_priority (source, G_PRIORITY_DEFAULT);
-          g_source_set_callback (source, invoke_notify_unapplied,
-                                 target, g_object_unref);
-          g_source_attach (source, target_context);
-          g_source_unref (source);
-        }
-      else
-        invoke_notify_unapplied (target);
-    }
+    g_main_context_invoke (target_context, invoke_notify_unapplied, target);
 }
 
 
@@ -99,7 +83,7 @@ g_delayed_settings_backend_read (GSettingsBackend   *backend,
 
   if (!default_value)
     {
-      g_static_mutex_lock (&delayed->priv->lock);
+      g_mutex_lock (&delayed->priv->lock);
       if (g_tree_lookup_extended (delayed->priv->delayed, key, NULL, &result))
         {
           /* NULL in the tree means we should consult the default value */
@@ -108,7 +92,7 @@ g_delayed_settings_backend_read (GSettingsBackend   *backend,
           else
             default_value = TRUE;
         }
-      g_static_mutex_unlock (&delayed->priv->lock);
+      g_mutex_unlock (&delayed->priv->lock);
     }
 
   if (result == NULL)
@@ -118,6 +102,32 @@ g_delayed_settings_backend_read (GSettingsBackend   *backend,
   return result;
 }
 
+static GVariant *
+g_delayed_settings_backend_read_user_value (GSettingsBackend   *backend,
+                                            const gchar        *key,
+                                            const GVariantType *expected_type)
+{
+  GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
+  gboolean value_found = FALSE;
+  gpointer result = NULL;
+
+  /* If we find an explicit NULL in our changeset then we want to return
+   * NULL (because the user value has been reset).
+   *
+   * Otherwise, chain up.
+   */
+  g_mutex_lock (&delayed->priv->lock);
+  value_found = g_tree_lookup_extended (delayed->priv->delayed, key, NULL, &result);
+  if (result)
+    g_variant_ref (result);
+  g_mutex_unlock (&delayed->priv->lock);
+
+  if (value_found)
+    return result;
+
+  return g_settings_backend_read_user_value (delayed->priv->backend, key, expected_type);
+}
+
 static gboolean
 g_delayed_settings_backend_write (GSettingsBackend *backend,
                                   const gchar      *key,
@@ -127,11 +137,11 @@ g_delayed_settings_backend_write (GSettingsBackend *backend,
   GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
   gboolean was_empty;
 
-  g_static_mutex_lock (&delayed->priv->lock);
+  g_mutex_lock (&delayed->priv->lock);
   was_empty = g_tree_nnodes (delayed->priv->delayed) == 0;
   g_tree_insert (delayed->priv->delayed, g_strdup (key),
                  g_variant_ref_sink (value));
-  g_static_mutex_unlock (&delayed->priv->lock);
+  g_mutex_unlock (&delayed->priv->lock);
 
   g_settings_backend_changed (backend, key, origin_tag);
 
@@ -151,18 +161,18 @@ add_to_tree (gpointer key,
 }
 
 static gboolean
-g_delayed_settings_backend_write_keys (GSettingsBackend *backend,
+g_delayed_settings_backend_write_tree (GSettingsBackend *backend,
                                        GTree            *tree,
                                        gpointer          origin_tag)
 {
   GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
   gboolean was_empty;
 
-  g_static_mutex_lock (&delayed->priv->lock);
+  g_mutex_lock (&delayed->priv->lock);
   was_empty = g_tree_nnodes (delayed->priv->delayed) == 0;
 
   g_tree_foreach (tree, add_to_tree, delayed->priv->delayed);
-  g_static_mutex_unlock (&delayed->priv->lock);
+  g_mutex_unlock (&delayed->priv->lock);
 
   g_settings_backend_changed_tree (backend, tree, origin_tag);
 
@@ -189,24 +199,16 @@ g_delayed_settings_backend_reset (GSettingsBackend *backend,
   GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
   gboolean was_empty;
 
-  g_static_mutex_lock (&delayed->priv->lock);
+  g_mutex_lock (&delayed->priv->lock);
   was_empty = g_tree_nnodes (delayed->priv->delayed) == 0;
   g_tree_insert (delayed->priv->delayed, g_strdup (key), NULL);
-  g_static_mutex_unlock (&delayed->priv->lock);
+  g_mutex_unlock (&delayed->priv->lock);
 
   if (was_empty)
     g_delayed_settings_backend_notify_unapplied (delayed);
 }
 
 static void
-g_delayed_settings_backend_reset_path (GSettingsBackend *backend,
-                                       const gchar      *path,
-                                       gpointer          origin_tag)
-{
-  /* deal with this... */
-}
-
-static void
 g_delayed_settings_backend_subscribe (GSettingsBackend *backend,
                                       const char       *name)
 {
@@ -251,12 +253,12 @@ g_delayed_settings_backend_apply (GDelayedSettingsBackend *delayed)
       gboolean success;
       GTree *tmp;
 
-      g_static_mutex_lock (&delayed->priv->lock);
+      g_mutex_lock (&delayed->priv->lock);
       tmp = delayed->priv->delayed;
       delayed->priv->delayed = g_settings_backend_create_tree ();
-      success = g_settings_backend_write_keys (delayed->priv->backend,
+      success = g_settings_backend_write_tree (delayed->priv->backend,
                                                tmp, delayed->priv);
-      g_static_mutex_unlock (&delayed->priv->lock);
+      g_mutex_unlock (&delayed->priv->lock);
 
       if (!success)
         g_settings_backend_changed_tree (G_SETTINGS_BACKEND (delayed),
@@ -275,10 +277,10 @@ g_delayed_settings_backend_revert (GDelayedSettingsBackend *delayed)
     {
       GTree *tmp;
 
-      g_static_mutex_lock (&delayed->priv->lock);
+      g_mutex_lock (&delayed->priv->lock);
       tmp = delayed->priv->delayed;
       delayed->priv->delayed = g_settings_backend_create_tree ();
-      g_static_mutex_unlock (&delayed->priv->lock);
+      g_mutex_unlock (&delayed->priv->lock);
       g_settings_backend_changed_tree (G_SETTINGS_BACKEND (delayed), tmp, NULL);
       g_tree_unref (tmp);
 
@@ -288,8 +290,8 @@ g_delayed_settings_backend_revert (GDelayedSettingsBackend *delayed)
 
 /* change notification */
 static void
-delayed_backend_changed (GSettingsBackend *backend,
-                         GObject          *target,
+delayed_backend_changed (GObject          *target,
+                         GSettingsBackend *backend,
                          const gchar      *key,
                          gpointer          origin_tag)
 {
@@ -301,11 +303,11 @@ delayed_backend_changed (GSettingsBackend *backend,
 }
 
 static void
-delayed_backend_keys_changed (GSettingsBackend    *backend,
-                              GObject             *target,
+delayed_backend_keys_changed (GObject             *target,
+                              GSettingsBackend    *backend,
                               const gchar         *path,
-                              const gchar * const *items,
-                              gpointer             origin_tag)
+                              gpointer             origin_tag,
+                              const gchar * const *items)
 {
   GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (target);
 
@@ -315,8 +317,8 @@ delayed_backend_keys_changed (GSettingsBackend    *backend,
 }
 
 static void
-delayed_backend_path_changed (GSettingsBackend *backend,
-                              GObject          *target,
+delayed_backend_path_changed (GObject          *target,
+                              GSettingsBackend *backend,
                               const gchar      *path,
                               gpointer          origin_tag)
 {
@@ -328,20 +330,25 @@ delayed_backend_path_changed (GSettingsBackend *backend,
 }
 
 static void
-delayed_backend_writable_changed (GSettingsBackend *backend,
-                                  GObject          *target,
+delayed_backend_writable_changed (GObject          *target,
+                                  GSettingsBackend *backend,
                                   const gchar      *key)
 {
   GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (target);
   gboolean last_one = FALSE;
 
-  g_static_mutex_lock (&delayed->priv->lock);
+  g_mutex_lock (&delayed->priv->lock);
 
-  if (g_tree_lookup (delayed->priv->delayed, key) &&
+  if (g_tree_lookup (delayed->priv->delayed, key) != NULL &&
       !g_settings_backend_get_writable (delayed->priv->backend, key))
     {
       /* drop the key from our changeset if it just became read-only.
        * no need to signal since the writable change below implies it.
+       *
+       * note that the item in the tree may very well be set to NULL in
+       * the case that the user stored a reset.  we intentionally don't
+       * drop the key in this case since a reset will always succeed
+       * (even against a non-writable key).
        */
       g_tree_remove (delayed->priv->delayed, key);
 
@@ -349,7 +356,7 @@ delayed_backend_writable_changed (GSettingsBackend *backend,
       last_one = g_tree_nnodes (delayed->priv->delayed) == 0;
     }
 
-  g_static_mutex_unlock (&delayed->priv->lock);
+  g_mutex_unlock (&delayed->priv->lock);
 
   if (last_one)
     g_delayed_settings_backend_notify_unapplied (delayed);
@@ -380,15 +387,15 @@ check_prefix (gpointer key,
 }
 
 static void
-delayed_backend_path_writable_changed (GSettingsBackend *backend,
-                                       GObject          *target,
+delayed_backend_path_writable_changed (GObject          *target,
+                                       GSettingsBackend *backend,
                                        const gchar      *path)
 {
   GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (target);
   gboolean last_one = FALSE;
   gsize n_keys;
 
-  g_static_mutex_lock (&delayed->priv->lock);
+  g_mutex_lock (&delayed->priv->lock);
 
   n_keys = g_tree_nnodes (delayed->priv->delayed);
 
@@ -400,9 +407,12 @@ delayed_backend_path_writable_changed (GSettingsBackend *backend,
       /* collect a list of possibly-affected keys (ie: matching the path) */
       g_tree_foreach (delayed->priv->delayed, check_prefix, &state);
 
-      /* drop the keys that have been affected */
+      /* drop the keys that have been affected.
+       *
+       * don't drop 'reset' keys (see above) */
       for (i = 0; i < state.index; i++)
-        if (!g_settings_backend_get_writable (delayed->priv->backend,
+        if (g_tree_lookup (delayed->priv->delayed, state.keys[i]) != NULL &&
+            !g_settings_backend_get_writable (delayed->priv->backend,
                                               state.keys[i]))
           g_tree_remove (delayed->priv->delayed, state.keys[i]);
 
@@ -411,7 +421,7 @@ delayed_backend_path_writable_changed (GSettingsBackend *backend,
       last_one = g_tree_nnodes (delayed->priv->delayed) == 0;
     }
 
-  g_static_mutex_unlock (&delayed->priv->lock);
+  g_mutex_unlock (&delayed->priv->lock);
 
   if (last_one)
     g_delayed_settings_backend_notify_unapplied (delayed);
@@ -425,7 +435,7 @@ g_delayed_settings_backend_finalize (GObject *object)
 {
   GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (object);
 
-  g_static_mutex_free (&delayed->priv->lock);
+  g_mutex_clear (&delayed->priv->lock);
   g_object_unref (delayed->priv->backend);
   g_tree_unref (delayed->priv->delayed);
 
@@ -442,13 +452,11 @@ g_delayed_settings_backend_class_init (GDelayedSettingsBackendClass *class)
   GSettingsBackendClass *backend_class = G_SETTINGS_BACKEND_CLASS (class);
   GObjectClass *object_class = G_OBJECT_CLASS (class);
 
-  g_type_class_add_private (class, sizeof (GDelayedSettingsBackendPrivate));
-
   backend_class->read = g_delayed_settings_backend_read;
+  backend_class->read_user_value = g_delayed_settings_backend_read_user_value;
   backend_class->write = g_delayed_settings_backend_write;
-  backend_class->write_keys = g_delayed_settings_backend_write_keys;
+  backend_class->write_tree = g_delayed_settings_backend_write_tree;
   backend_class->reset = g_delayed_settings_backend_reset;
-  backend_class->reset_path = g_delayed_settings_backend_reset_path;
   backend_class->get_writable = g_delayed_settings_backend_get_writable;
   backend_class->subscribe = g_delayed_settings_backend_subscribe;
   backend_class->unsubscribe = g_delayed_settings_backend_unsubscribe;
@@ -460,12 +468,9 @@ g_delayed_settings_backend_class_init (GDelayedSettingsBackendClass *class)
 static void
 g_delayed_settings_backend_init (GDelayedSettingsBackend *delayed)
 {
-  delayed->priv =
-    G_TYPE_INSTANCE_GET_PRIVATE (delayed, G_TYPE_DELAYED_SETTINGS_BACKEND,
-                                 GDelayedSettingsBackendPrivate);
-
+  delayed->priv = g_delayed_settings_backend_get_instance_private (delayed);
   delayed->priv->delayed = g_settings_backend_create_tree ();
-  g_static_mutex_init (&delayed->priv->lock);
+  g_mutex_init (&delayed->priv->lock);
 }
 
 static void
@@ -474,10 +479,10 @@ g_delayed_settings_backend_disown (gpointer  data,
 {
   GDelayedSettingsBackend *delayed = data;
 
-  g_static_mutex_lock (&delayed->priv->lock);
+  g_mutex_lock (&delayed->priv->lock);
   delayed->priv->owner_context = NULL;
   delayed->priv->owner = NULL;
-  g_static_mutex_unlock (&delayed->priv->lock);
+  g_mutex_unlock (&delayed->priv->lock);
 }
 
 GDelayedSettingsBackend *
@@ -485,6 +490,13 @@ g_delayed_settings_backend_new (GSettingsBackend *backend,
                                 gpointer          owner,
                                 GMainContext     *owner_context)
 {
+  static GSettingsListenerVTable vtable = {
+    delayed_backend_changed,
+    delayed_backend_path_changed,
+    delayed_backend_keys_changed,
+    delayed_backend_writable_changed,
+    delayed_backend_path_writable_changed
+  };
   GDelayedSettingsBackend *delayed;
 
   delayed = g_object_new (G_TYPE_DELAYED_SETTINGS_BACKEND, NULL);
@@ -494,12 +506,8 @@ g_delayed_settings_backend_new (GSettingsBackend *backend,
 
   g_object_weak_ref (owner, g_delayed_settings_backend_disown, delayed);
 
-  g_settings_backend_watch (delayed->priv->backend, G_OBJECT (delayed), NULL,
-                            delayed_backend_changed,
-                            delayed_backend_path_changed,
-                            delayed_backend_keys_changed,
-                            delayed_backend_writable_changed,
-                            delayed_backend_path_writable_changed);
+  g_settings_backend_watch (delayed->priv->backend,
+                            &vtable, G_OBJECT (delayed), NULL);
 
   return delayed;
 }