diff --git a/extensions/Connection_Interface_Location.xml b/extensions/Connection_Interface_Location.xml
new file mode 100644
index 0000000..1e7bee4
--- /dev/null
+++ b/extensions/Connection_Interface_Location.xml
@@ -0,0 +1,330 @@
+<?xml version="1.0" ?>
+<node name="/Connection_Interface_Location"
+  xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
+  <tp:copyright>Copyright (C) 2008 Collabora Ltd.</tp:copyright>
+  <tp:copyright>Copyright (C) 2008 Nokia Corporation</tp:copyright>
+  <tp:license xmlns="http://www.w3.org/1999/xhtml">
+    <p>This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.</p>
+
+<p>This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.</p>
+
+<p>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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p>
+  </tp:license>
+  <interface name="org.freedesktop.Telepathy.Connection.Interface.Location.DRAFT"
+    tp:causes-havoc='experimental'>
+    <tp:requires interface="org.freedesktop.Telepathy.Connection"/>
+
+    <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+      <p>An interface on connections to support protocols which allow users to
+        publish their current geographical location, and subscribe to the
+        current location of their contacts.</p>
+
+      <p>This interface is geared strongly towards automatic propagation and
+        use of this information, so focuses on latitude, longitude and
+        altitude which can be determined by GPS, although provision is also
+        included for an optional human-readable description of locations. All
+        co-ordinate information is required to be relative to the WGS84
+        datum.</p>
+
+      <p>The information published through this interface is intended to have
+        the same scope as presence information, so will normally be made
+        available to those individuals on the user's "publish" contact list.
+        Even so, user interfaces should not automatically publish location
+        information without the consent of the user, and it is recommended
+        that an option is made available to reduce the accuracy of the
+        reported information to allow the user to maintain their privacy.</p>
+
+      <p>Location information is represented using the terminology of XMPP's
+        <a href="http://www.xmpp.org/extensions/xep-0080.html">XEP-0080</a>
+        or the XEP-0080-derived
+        <a href="http://geoclue.freedesktop.org/">Geoclue</a> API where
+        possible.</p>
+    </tp:docstring>
+
+    <tp:enum name="Location_Accuracy_Level" type="i">
+      <tp:docstring>
+        A location accuracy level. This should be kept in sync with
+        GeoclueAccuracyLevel in the Geoclue project.
+      </tp:docstring>
+
+      <tp:enumvalue suffix="None" value="0">
+        <tp:docstring>
+          The accuracy is unspecified.
+        </tp:docstring>
+      </tp:enumvalue>
+      <tp:enumvalue suffix="Country" value="1">
+        <tp:docstring>
+          The location indicates the contact's country.
+        </tp:docstring>
+      </tp:enumvalue>
+      <tp:enumvalue suffix="Region" value="2">
+        <tp:docstring>
+          The location indicates the contact's region within a country.
+        </tp:docstring>
+      </tp:enumvalue>
+      <tp:enumvalue suffix="Locality" value="3">
+        <tp:docstring>
+          The location indicates the contact's locality within a region
+          (e.g. the correct city).
+        </tp:docstring>
+      </tp:enumvalue>
+      <tp:enumvalue suffix="Postal_Code" value="4">
+        <tp:docstring>
+          The location indicates the correct postal code.
+        </tp:docstring>
+      </tp:enumvalue>
+      <tp:enumvalue suffix="Street" value="5">
+        <tp:docstring>
+          The location indicates the correct street.
+        </tp:docstring>
+      </tp:enumvalue>
+      <tp:enumvalue suffix="Detailed" value="6">
+        <tp:docstring>
+          The location's accuracy is given by the error, horizontal-error-m
+          and/or vertical-error-m keys.
+        </tp:docstring>
+      </tp:enumvalue>
+    </tp:enum>
+
+    <tp:mapping name="Location">
+      <tp:docstring>
+        A user's location, represented as an extensible mapping.
+      </tp:docstring>
+
+      <tp:member name="Key" type="s">
+        <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+
+          <p>Civic addresses are represented by the following well-known
+            keys (all of which have string values), which should be kept in
+            sync with those used in XEP-0080 and in the Geoclue project:</p>
+
+          <ul>
+            <li>countrycode - s: an ISO-3166-1 alpha-2 (two-letter) country
+              code, e.g. "us", "gb", "fr"</li>
+            <li>country - s: a country name in unspecified locale, e.g.
+              "USA"</li>
+            <li>region - s: an administrative region of the nation, such as a
+              state or province</li>
+            <li>locality - s: a locality within the administrative region, such
+              as a town or city</li>
+            <li>area - s: a named area such as a campus or neighborhood</li>
+            <li>postalcode - s: a code used for postal delivery</li>
+            <li>street - s: a thoroughfare within the locality, or a crossing of
+              two thoroughfares</li>
+          </ul>
+
+          <p>The following address keys are defined in XEP-0080 but not by
+            Geoclue, and are also allowed:</p>
+
+          <ul>
+            <li>building - s: a specific building on a street or in an area</li>
+            <li>floor - s: a particular floor in a building</li>
+            <li>room - s: a particular room in a building</li>
+            <li>text - s: any more specific information, e.g.
+              "Northwest corner of the lobby"</li>
+            <li>description - s: A natural-language name for or description of
+              the location, e.g. "Bill's house"</li>
+            <li>uri - s: a URI representing the location or pointing to more
+              information about it</li>
+          </ul>
+
+          <p>Positions are represented by the following well-known keys:</p>
+
+          <ul>
+            <li>lat - d: latitude in decimal degrees north, -90 to +90,
+              relative to the WGS-84 datum
+              <tp:rationale>
+                This is from XEP-0080; the XEP allows use of a different
+                datum, but recommends this one. We enforce sanity by requiring
+                a consistent datum: a minimal compliant implementation of this
+                specification in terms of XEP-0080 would simply ignore the
+                &lt;lat&gt; and &lt;lon&gt; elements if &lt;datum&gt; exists
+                and has a value other than WGS-84, while an advanced
+                implementation might correct for the different datum.
+              </tp:rationale>
+            </li>
+            <li>lon - d: Longitude in decimal degrees east, -180 to +180,
+              relative to the WGS-84 datum
+              <tp:rationale>
+                Same rationale as 'lat'
+              </tp:rationale>
+            </li>
+            <li>alt - d: altitude in metres above sea level (negative
+              if below sea level)
+              <tp:rationale>
+                This is from XEP-0080
+              </tp:rationale>
+            </li>
+            <li>accuracy-level - i (<tp:type>Location_Accuracy_Level</tp:type>):
+              an indication of accuracy, which SHOULD be omitted if it would be
+              Location_Accuracy_Level_None or
+              Location_Accuracy_Level_Detailed
+              <tp:rationale>
+                This is a struct field in GeoClue; the name is new in this
+                specification, and was chosen in an attempt to avoid clashing
+                with any future XEP-0080 terminology.
+              </tp:rationale>
+            </li>
+            <li>error - d: horizontal position error in arc-minutes (1/60
+              degree) if known
+              <tp:rationale>
+                This is from XEP-0080
+              </tp:rationale>
+            </li>
+            <li>vertical-error-m - d: vertical position error in metres if
+              known
+              <tp:rationale>
+                This exists as a struct field in GeoClue; the name is new
+                in this specification.
+              </tp:rationale>
+            </li>
+            <li>horizontal-error-m - d: horizontal position error in metres if
+              known
+              <tp:rationale>
+                This exists as a struct field in GeoClue; the name is new
+                in this specification.
+              </tp:rationale>
+            </li>
+          </ul>
+
+          <p>Velocities are represented by the following well-known keys:</p>
+
+          <ul>
+            <li>speed - d: speed in metres per second
+              <tp:rationale>
+                This is from XEP-0080
+              </tp:rationale>
+            </li>
+            <li>bearing - d: direction of movement in decimal degrees,
+              where North is 0 and East is 90
+              <tp:rationale>
+                This is from XEP-0080, and is equivalent to the struct field
+                called "direction" in GeoClue
+              </tp:rationale>
+            </li>
+            <li>climb - d: rate of change of 'alt' in metres per second
+              <tp:rationale>
+                This is a struct field in GeoClue; the name is new to this
+                specification, but seems uncontroversial
+              </tp:rationale>
+            </li>
+          </ul>
+
+          <p>Other well-known keys:</p>
+
+          <ul>
+            <li>timestamp - t (<tp:type>Unix_Timestamp64</tp:type>): the time
+              that the contact was at this location, in seconds since
+              1970-01-01T00:00:00Z (i.e. the beginning of 1970 in UTC)
+              <tp:rationale>
+                XEP-0080 uses an ISO 8601 string for this, but a number of
+                seconds since the epoch is probably easier to work with.
+              </tp:rationale>
+            </li>
+          </ul>
+        </tp:docstring>
+      </tp:member>
+
+      <tp:member name="Value" type="v">
+        <tp:docstring>
+          The value corresponding to the well-known key.
+        </tp:docstring>
+      </tp:member>
+    </tp:mapping>
+
+    <tp:mapping name="Contact_Locations" type="a{ua{sv}}">
+      <tp:member name="Contact" type="u" tp:type="Contact_Handle">
+      </tp:member>
+      <tp:member name="Location" type="a{sv}" tp:type="Location">
+      </tp:member>
+    </tp:mapping>
+
+    <method name="GetLocations" tp:name-for-bindings="Get_Locations">
+      <tp:docstring>
+        Return the current locations of the given contacts, if they are
+        already known. If any of the given contacts' locations are not known,
+        request their current locations, and later emit
+        <tp:member-ref>LocationUpdated</tp:member-ref> for them; the
+        <tp:member-ref>LocationUpdated</tp:member-ref> signal for contacts
+        whose location could not be determined will have an empty Location.
+      </tp:docstring>
+
+      <arg direction="in" name="Contacts" type="au" tp:type="Contact_Handle[]">
+        <tp:docstring>
+          The contacts whose locations should be returned or signalled.
+        </tp:docstring>
+      </arg>
+
+      <arg direction="out" name="Locations" type="a{ua{sv}}"
+        tp:type="Contact_Locations">
+        <tp:docstring>
+          The contacts' locations, if already known. Contacts whose locations
+          are not already known are omitted from the mapping; contacts known
+          to have no location information appear in the mapping with an empty
+          Location dictionary.
+        </tp:docstring>
+      </arg>
+    </method>
+
+    <signal name="LocationUpdated" tp:name-for-bindings="Location_Updated">
+      <tp:docstring>
+        Emitted when a contact's location changes or becomes known.
+      </tp:docstring>
+
+      <arg name="Contact" type="u" tp:type="Contact_Handle">
+        <tp:docstring>
+          The contact
+        </tp:docstring>
+      </arg>
+      <arg name="Location" type="a{sv}" tp:type="Location">
+        <tp:docstring>
+          The contact's location, or empty to indicate that nothing is known
+          about the contact's location.
+        </tp:docstring>
+      </arg>
+    </signal>
+
+    <method name="SetLocation" tp:name-for-bindings="SetLocation">
+      <tp:docstring>
+        Set the local user's own location.
+      </tp:docstring>
+
+      <arg direction="in" name="Location" type="a{sv}">
+        <tp:docstring>
+          The location to advertise. If the user wants to obscure their
+          exact location by reducing the precision or accuracy, clients
+          MUST do this themselves, rather than relying on the connection
+          manager to do so. Clients that interact with more than one
+          connection SHOULD advertise the same reduced-accuracy location
+          to all of them, so that contacts cannot obtain an undesirably
+          accurate location by assuming that random errors have been added
+          and averaging the locations advertised on multiple connections.
+        </tp:docstring>
+      </arg>
+    </method>
+
+    <property name="LocationAccessControlTypes" type="au" access="read"
+      tp:type="Rich_Presence_Access_Control_Type[]" tp:name-for-bindings="Location_Access_Control_Types">
+      <tp:docstring>The types of access control that are supported by this
+        connection.</tp:docstring>
+    </property>
+
+    <property name="LocationAccessControl" type="(uv)" access="readwrite"
+      tp:type="Rich_Presence_Access_Control" tp:name-for-bindings="Location_Access_Control">
+      <tp:docstring>The current access control mechanism and settings
+        for this connection. Before publishing location for the first time,
+        if this has not been set by a client, implementations SHOULD
+        set it to be as restrictive as possible (an empty whitelist, if
+        supported).</tp:docstring>
+    </property>
+  </interface>
+</node>
+<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index 408445f..b796f0c 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -11,6 +11,7 @@ EXTRA_DIST = \
     generic-types.xml \
     misc.xml \
     Channel_Handler.xml \
+    Connection_Interface_Location.xml \
     Stream_Engine.xml \
     Tube_Handler.xml \
     Channel_Type_File_Transfer.xml \
diff --git a/extensions/all.xml b/extensions/all.xml
index c9f4c0b..85d9dde 100644
--- a/extensions/all.xml
+++ b/extensions/all.xml
@@ -28,6 +28,18 @@
     from="Telepathy specification"/>
   <tp:external-type name="Tube_ID" type="u"
     from="Telepathy specification"/>
+
+  <!-- for localisation -->
+  <tp:external-type name="Rich_Presence_Access_Control_Type" type="u"
+    from="Telepathy specification"/>
+  <tp:external-type name="Rich_Presence_Access_Control" type="(uv)"
+    from="Telepathy specification"/>
+  <tp:external-type name="Unix_Timestamp64" type="t"
+    from="Telepathy specification"/>
+  <tp:external-type name="Unix_Timestamp" type="u"
+    from="Telepathy specification"/>
+  <tp:external-type name="String_String_Map" type="a{ss}"
+    from="Telepathy specification"/>
 </tp:generic-types>
 
 
diff --git a/extensions/misc.xml b/extensions/misc.xml
index fc96eff..263d679 100644
--- a/extensions/misc.xml
+++ b/extensions/misc.xml
@@ -11,5 +11,6 @@
 <xi:include href="Channel_Interface_Tube.xml" />
 <xi:include href="Channel_Type_DBus_Tube.xml" />
 <xi:include href="Channel_Type_Stream_Tube.xml" />
+<xi:include href="Connection_Interface_Location.xml"/>
 
 </tp:spec>
diff --git a/libempathy/Makefile.am b/libempathy/Makefile.am
index 559d869..506446f 100644
--- a/libempathy/Makefile.am
+++ b/libempathy/Makefile.am
@@ -77,6 +77,7 @@ libempathy_headers =				\
 	empathy-irc-network.h			\
 	empathy-irc-network-manager.h		\
 	empathy-irc-server.h			\
+	empathy-location.h			\
 	empathy-log-manager.h			\
 	empathy-message.h			\
 	empathy-status-presets.h		\
diff --git a/libempathy/empathy-contact-factory.c b/libempathy/empathy-contact-factory.c
index 412fd86..d6f5ef8 100644
--- a/libempathy/empathy-contact-factory.c
+++ b/libempathy/empathy-contact-factory.c
@@ -125,6 +125,18 @@ empathy_contact_factory_set_avatar (EmpathyContactFactory *factory,
 						      data, size, mime_type);
 }
 
+void
+empathy_contact_factory_set_location (EmpathyContactFactory *factory,
+				      McAccount             *account,
+				      GHashTable            *location)
+{
+	EmpathyTpContactFactory *tp_factory;
+
+	tp_factory = empathy_contact_factory_get_tp_factory (factory, account);
+
+	return empathy_tp_contact_factory_set_location (tp_factory, location);
+}
+
 static void
 contact_factory_finalize (GObject *object)
 {
diff --git a/libempathy/empathy-contact-factory.h b/libempathy/empathy-contact-factory.h
index 16df02b..fa7d34a 100644
--- a/libempathy/empathy-contact-factory.h
+++ b/libempathy/empathy-contact-factory.h
@@ -73,6 +73,9 @@ void                   empathy_contact_factory_set_avatar       (EmpathyContactF
 								 const gchar           *data,
 								 gsize                  size,
 								 const gchar           *mime_type);
+void                   empathy_contact_factory_set_location     (EmpathyContactFactory *factory,
+								 McAccount             *account,
+								 GHashTable            *location);
 
 G_END_DECLS
 
diff --git a/libempathy/empathy-contact.c b/libempathy/empathy-contact.c
index 0b7a140..cd84de8 100644
--- a/libempathy/empathy-contact.c
+++ b/libempathy/empathy-contact.c
@@ -57,6 +57,7 @@ typedef struct {
   guint hash;
   EmpathyContactReady ready;
   GList *ready_callbacks;
+  GHashTable *location;
 } EmpathyContactPriv;
 
 typedef struct {
@@ -87,7 +88,8 @@ enum
   PROP_HANDLE,
   PROP_CAPABILITIES,
   PROP_IS_USER,
-  PROP_READY
+  PROP_READY,
+  PROP_LOCATION
 };
 
 enum {
@@ -211,6 +213,14 @@ empathy_contact_class_init (EmpathyContactClass *class)
         EMPATHY_CONTACT_READY_NONE,
         G_PARAM_READABLE));
 
+  g_object_class_install_property (object_class,
+      PROP_LOCATION,
+      g_param_spec_boxed ("location",
+        "Contact location",
+        "Physical location of the contact",
+        G_TYPE_HASH_TABLE,
+        G_PARAM_READABLE));
+
   signals[PRESENCE_CHANGED] =
     g_signal_new ("presence-changed",
                   G_TYPE_FROM_CLASS (class),
@@ -236,6 +246,9 @@ empathy_contact_init (EmpathyContact *contact)
   /* Keep a ref to the factory to be sure it is not finalized while there is
    * still contacts alive. */
   priv->factory = empathy_contact_factory_dup_singleton ();
+  priv->location = g_hash_table_new_full (g_str_hash, g_str_equal,
+                       (GDestroyNotify) g_free,
+                       (GDestroyNotify) tp_g_value_slice_free);
 }
 
 static void
@@ -1116,3 +1129,48 @@ empathy_avatar_save_to_file (EmpathyAvatar *self,
   return g_file_set_contents (filename, self->data, self->len, error);
 }
 
+/**
+ * empathy_contact_get_location:
+ * @contact: the contact
+ *
+ * Returns the user's location if available.  The keys are defined in
+ * empathy-location.h. If the contact doesn't have location
+ * information, the GHashTable will be empthy.
+ *
+ * Returns: a #GHashTable of location values
+ */
+GHashTable *
+empathy_contact_get_location (EmpathyContact *contact)
+{
+  EmpathyContactPriv *priv;
+
+  g_return_val_if_fail (EMPATHY_CONTACT (contact), NULL);
+
+  priv = GET_PRIV (contact);
+
+  return priv->location;
+}
+
+/**
+ * empathy_contact_set_location:
+ * @contact: the contact
+ * @location: the location
+ *
+ * Sets the user's location based on the location #GHashTable passed.
+ */
+void 
+empathy_contact_set_location (EmpathyContact *contact,
+                              GHashTable *location)
+{
+  EmpathyContactPriv *priv;
+
+  g_return_if_fail (EMPATHY_CONTACT (contact));
+  g_return_if_fail (location != NULL);
+
+  priv = GET_PRIV (contact);
+
+  g_hash_table_unref (priv->location);
+
+  priv->location = g_hash_table_ref (location);
+  g_object_notify (G_OBJECT (contact), "location");
+}
diff --git a/libempathy/empathy-contact.h b/libempathy/empathy-contact.h
index 52c969f..ba0fe80 100644
--- a/libempathy/empathy-contact.h
+++ b/libempathy/empathy-contact.h
@@ -142,6 +142,10 @@ void empathy_avatar_unref (EmpathyAvatar *avatar);
 gboolean empathy_avatar_save_to_file (EmpathyAvatar *avatar,
     const gchar *filename, GError **error);
 
+GHashTable * empathy_contact_get_location (EmpathyContact *contact);
+void empathy_contact_set_location (EmpathyContact *contact,
+  GHashTable *location);
+
 G_END_DECLS
 
 #endif /* __EMPATHY_CONTACT_H__ */
diff --git a/libempathy/empathy-debug.c b/libempathy/empathy-debug.c
index ec72bfc..bcfa25d 100644
--- a/libempathy/empathy-debug.c
+++ b/libempathy/empathy-debug.c
@@ -45,6 +45,7 @@ static GDebugKey keys[] = {
   { "Irc", EMPATHY_DEBUG_IRC },
   { "Dispatcher", EMPATHY_DEBUG_DISPATCHER },
   { "Ft", EMPATHY_DEBUG_FT },
+  { "Location", EMPATHY_DEBUG_LOCATION },
   { "Other", EMPATHY_DEBUG_OTHER },
   { 0, }
 };
diff --git a/libempathy/empathy-debug.h b/libempathy/empathy-debug.h
index 8b68fd2..787264d 100644
--- a/libempathy/empathy-debug.h
+++ b/libempathy/empathy-debug.h
@@ -39,7 +39,8 @@ typedef enum
   EMPATHY_DEBUG_IRC = 1 << 5,
   EMPATHY_DEBUG_DISPATCHER = 1 << 6,
   EMPATHY_DEBUG_FT = 1 << 7,
-  EMPATHY_DEBUG_OTHER = 1 << 8,
+  EMPATHY_DEBUG_LOCATION = 1 << 8,
+  EMPATHY_DEBUG_OTHER = 1 << 9,
 } EmpathyDebugFlags;
 
 gboolean empathy_debug_flag_is_set (EmpathyDebugFlags flag);
diff --git a/libempathy/empathy-location.h b/libempathy/empathy-location.h
new file mode 100644
index 0000000..a43e2d3
--- /dev/null
+++ b/libempathy/empathy-location.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors: Pierre-Luc Beaudoin <pierre-luc.beaudoin@collabora.co.uk>
+ */
+
+#ifndef __EMPATHY_LOCATION_H__
+#define __EMPATHY_LOCATION_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define EMPATHY_LOCATION_COUNTRY_CODE "countrycode"
+#define EMPATHY_LOCATION_COUNTRY "country"
+#define EMPATHY_LOCATION_REGION "region"
+#define EMPATHY_LOCATION_LOCALITY "locality"
+#define EMPATHY_LOCATION_AREA "area"
+#define EMPATHY_LOCATION_POSTAL_CODE "postalcode"
+#define EMPATHY_LOCATION_STREET "street"
+#define EMPATHY_LOCATION_BUILDING "building"
+#define EMPATHY_LOCATION_FLOOR "floor"
+#define EMPATHY_LOCATION_ROOM "room"
+#define EMPATHY_LOCATION_TEXT "text"
+#define EMPATHY_LOCATION_DESCRIPTION "description"
+#define EMPATHY_LOCATION_URI "uri"
+#define EMPATHY_LOCATION_LAT "lat"
+#define EMPATHY_LOCATION_LON "lon"
+#define EMPATHY_LOCATION_ALT "alt"
+#define EMPATHY_LOCATION_ACCURACY_LEVEL "accuracy-level"
+#define EMPATHY_LOCATION_ERROR "error"
+#define EMPATHY_LOCATION_VERTICAL_ERROR_M "vertical-error-m"
+#define EMPATHY_LOCATION_HORIZONTAL_ERROR_M "horizontal-error-m"
+#define EMPATHY_LOCATION_SPEED "speed"
+#define EMPATHY_LOCATION_BEARING "bearing"
+#define EMPATHY_LOCATION_CLIMB "climb"
+#define EMPATHY_LOCATION_TIMESTAMP "timestamp"
+
+G_END_DECLS
+
+#endif /* __EMPATHY_LOCATION_H__ */
diff --git a/libempathy/empathy-tp-contact-factory.c b/libempathy/empathy-tp-contact-factory.c
index c407ea4..dd75388 100644
--- a/libempathy/empathy-tp-contact-factory.c
+++ b/libempathy/empathy-tp-contact-factory.c
@@ -223,6 +223,17 @@ tp_contact_factory_set_aliases_cb (TpConnection *connection,
 	}
 }
 
+static void 
+tp_contact_factory_set_location_cb (TpProxy *proxy,
+				    const GError *error,
+				    gpointer user_data,
+				    GObject *weak_object)
+{
+	if (error) {
+		DEBUG ("Error setting location: %s", error->message);
+	}
+}
+
 static void
 tp_contact_factory_request_aliases_cb (TpConnection *connection,
 				       const gchar  **contact_names,
@@ -595,6 +606,69 @@ tp_contact_factory_capabilities_changed_cb (TpConnection    *connection,
 	}
 }
 
+static void 
+update_location_for_each (gpointer key,
+                          gpointer value,
+                          gpointer user_data)
+{
+  GHashTable *location = (GHashTable*) user_data;
+    g_hash_table_insert (location, g_strdup(key), tp_g_value_slice_dup (value));
+}
+
+static void
+tp_contact_factory_location_updated_cb (TpProxy      *proxy,
+					guint         handle,
+					GHashTable   *location,
+					gpointer      user_data,
+					GObject      *weak_object)
+{
+	EmpathyTpContactFactory *tp_factory = EMPATHY_TP_CONTACT_FACTORY (weak_object);
+	EmpathyContact          *contact;
+        GHashTable              *new_location;
+
+	new_location = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+		(GDestroyNotify) tp_g_value_slice_free);
+
+	// Copy keys
+	g_hash_table_foreach (location, update_location_for_each, new_location);
+
+	contact = empathy_tp_contact_factory_get_from_handle (tp_factory, handle);
+	empathy_contact_set_location (contact, new_location);
+}
+
+static
+void 
+tp_contact_factory_get_location_for_each_cb (gpointer key,
+					     gpointer value,
+					     gpointer user_data)
+{
+	guint           handle = GPOINTER_TO_INT (key);
+	GHashTable     *location = (GHashTable*) (value);
+	EmpathyContact *contact;
+	EmpathyTpContactFactory *tp_factory = EMPATHY_TP_CONTACT_FACTORY (user_data);
+
+	contact = empathy_tp_contact_factory_get_from_handle (tp_factory, handle);
+	empathy_contact_set_location (contact, location);
+}
+
+static void
+tp_contact_factory_get_locations_cb (TpProxy      *proxy,
+				     GHashTable   *out_locations,
+				     const GError *error,
+				     gpointer      user_data,
+				     GObject      *tp_factory)
+{
+
+	if (error) {
+		DEBUG ("Failed to request handles: %s", error->message);
+		return;
+	}
+
+	g_hash_table_foreach (out_locations,
+		tp_contact_factory_get_location_for_each_cb,
+		tp_factory);
+}
+
 static void
 tp_contact_factory_request_everything (EmpathyTpContactFactory *tp_factory,
 				       const GArray            *handles)
@@ -638,6 +712,12 @@ tp_contact_factory_request_everything (EmpathyTpContactFactory *tp_factory,
 									tp_contact_factory_get_capabilities_cb,
 									NULL, NULL,
 									G_OBJECT (tp_factory));
+	emp_cli_connection_interface_location_call_get_locations (TP_PROXY (priv->connection),
+								  -1,
+								  handles,
+								  tp_contact_factory_get_locations_cb,
+								  NULL, NULL,
+								  G_OBJECT (tp_factory));
 }
 
 static void
@@ -770,6 +850,11 @@ tp_contact_factory_ready (EmpathyTpContactFactory *tp_factory)
 										  NULL, NULL,
 										  G_OBJECT (tp_factory),
 										  NULL);
+	emp_cli_connection_interface_location_connect_to_location_updated (TP_PROXY (priv->connection),
+									   tp_contact_factory_location_updated_cb,
+									   NULL, NULL,
+									   G_OBJECT (tp_factory),
+									   NULL);
 
 	/* Request needed info for all existing contacts */
 	handle_needed = g_array_new (TRUE, FALSE, sizeof (gchar*));
@@ -1094,7 +1179,7 @@ empathy_tp_contact_factory_get_from_id (EmpathyTpContactFactory *tp_factory,
 	if (priv->ready) {
 		const gchar *contact_ids[] = {id, NULL};
 		GList       *contacts;
-		
+
 		contacts = g_list_prepend (NULL, g_object_ref (contact));
 		tp_cli_connection_call_request_handles (priv->connection,
 							-1,
@@ -1291,6 +1376,24 @@ empathy_tp_contact_factory_set_avatar (EmpathyTpContactFactory *tp_factory,
 	}
 }
 
+void
+empathy_tp_contact_factory_set_location (EmpathyTpContactFactory *tp_factory,
+					 GHashTable              *location)
+{
+	EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
+
+	g_return_if_fail (EMPATHY_IS_TP_CONTACT_FACTORY (tp_factory));
+
+	DEBUG ("Setting location");
+
+	emp_cli_connection_interface_location_call_set_location (TP_PROXY (priv->connection),
+								-1,
+								location,
+								tp_contact_factory_set_location_cb,
+								NULL, NULL,
+								G_OBJECT (tp_factory));
+}
+
 gboolean
 empathy_tp_contact_factory_is_ready (EmpathyTpContactFactory *tp_factory)
 {
diff --git a/libempathy/empathy-tp-contact-factory.h b/libempathy/empathy-tp-contact-factory.h
index 92e7c29..9d8f715 100644
--- a/libempathy/empathy-tp-contact-factory.h
+++ b/libempathy/empathy-tp-contact-factory.h
@@ -66,7 +66,8 @@ void                     empathy_tp_contact_factory_set_avatar       (EmpathyTpC
 								      gsize                    size,
 								      const gchar             *mime_type);
 gboolean                 empathy_tp_contact_factory_is_ready         (EmpathyTpContactFactory *tp_factory);
-
+void                     empathy_tp_contact_factory_set_location     (EmpathyTpContactFactory *tp_factory,
+								      GHashTable              *location);
 G_END_DECLS
 
 #endif /* __EMPATHY_TP_CONTACT_FACTORY_H__ */
