telepathy: Fix weak notification of TpContacts
authorPhilip Withnall <philip@tecnocode.co.uk>
Mon, 9 Jan 2012 14:47:02 +0000 (14:47 +0000)
committerPhilip Withnall <philip@tecnocode.co.uk>
Mon, 9 Jan 2012 14:47:58 +0000 (14:47 +0000)
By the time our weak notification callback was called, the TpContact’s
handle had been set to 0, which mucked things up for us.

Closes: https://bugzilla.gnome.org/show_bug.cgi?id=667535

NEWS
backends/telepathy/lib/tpf-persona-store.vala

diff --git a/NEWS b/NEWS
index ce61435..6f26078 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,8 @@ Bugs fixed:
 * Bug 657063 — Allow to pass a command to folks-inspect
 * Bug 667410 — A second instance of the aggregator only fetch a small subset of
   my contacts
+* Bug 667535 — persona created by tpf_persona_dup_for_contact() outlives its
+  TpContact
 
 API changes:
 * Add PostalAddress.is_empty() and Role.is_empty()
index f8e1ace..d5f76e9 100644 (file)
@@ -78,7 +78,10 @@ public class Tpf.PersonaStore : Folks.PersonaStore
   private HashSet<Persona> _persona_set;
   /* universal, contact owner handles (not channel-specific) */
   private HashMap<uint, Persona> _handle_persona_map;
-  private HashSet<Persona> _weakly_referenced_personas;
+  /* Map from weakly-referenced TpContacts to their original TpHandles;
+   * necessary because the handles get set to 0 before our weak_notify callback
+   * is called, and we need the handle to remove the contact. */
+  private HashMap<unowned Contact, uint> _weakly_referenced_contacts;
   private HashMap<Channel, HashSet<Persona>> _channel_group_personas_map;
   private HashMap<Channel, HashSet<uint>> _channel_group_incoming_adds;
   private HashMap<string, HashSet<Tpf.Persona>> _group_outgoing_adds;
@@ -517,18 +520,18 @@ public class Tpf.PersonaStore : Folks.PersonaStore
           this._conn = null;
         }
 
-      if (this._weakly_referenced_personas != null)
+      if (this._weakly_referenced_contacts != null)
         {
-          foreach (var p in this._weakly_referenced_personas)
+          var iter = this._weakly_referenced_contacts.map_iterator ();
+          while (iter.next () == true)
             {
-              if (p.contact != null)
-                {
-                  p.contact.weak_unref (this._contact_weak_notify_cb);
-                }
+              var contact = iter.get_key ();
+              contact.weak_unref (this._contact_weak_notify_cb);
             }
         }
 
-      this._weakly_referenced_personas = new HashSet<Persona> ();
+      this._weakly_referenced_contacts =
+          new HashMap<unowned Contact, uint> ();
 
       this._handle_persona_map = new HashMap<uint, Persona> ();
       this._channel_group_personas_map =
@@ -1555,8 +1558,8 @@ public class Tpf.PersonaStore : Folks.PersonaStore
         return;
 
       /* If we hold a weak ref. on the persona's TpContact, release that. */
-      if (this._weakly_referenced_personas.remove (persona) == true &&
-          persona.contact != null)
+      if (persona.contact != null &&
+          this._weakly_referenced_contacts.unset (persona.contact) == true)
         {
           persona.contact.weak_unref (this._contact_weak_notify_cb);
         }
@@ -1961,8 +1964,15 @@ public class Tpf.PersonaStore : Folks.PersonaStore
   private void _contact_weak_notify_cb (Object obj)
     {
       var c = obj as Contact;
-      this._ignore_by_handle (c.get_handle (), null, null,
-          GroupDetails.ChangeReason.NONE);
+      if (this._weakly_referenced_contacts != null)
+        {
+          Handle handle = this._weakly_referenced_contacts.get (c);
+          if (handle != 0)
+            {
+              this._ignore_by_handle ((!) handle, null, null,
+                  GroupDetails.ChangeReason.NONE);
+            }
+        }
     }
 
   internal Tpf.Persona? _ensure_persona_from_contact (Contact contact)
@@ -1999,7 +2009,7 @@ public class Tpf.PersonaStore : Folks.PersonaStore
 
       /* Weak ref. on the contact. */
       contact.weak_ref (this._contact_weak_notify_cb);
-      this._weakly_referenced_personas.add (persona);
+      this._weakly_referenced_contacts.set (contact, handle);
 
       /* Signal the addition of the new persona. */
       var personas = new HashSet<Persona> ();