示例#1
0
const gchar *
empathy_account_get_error_message (TpAccount *account,
    gboolean *user_requested)
{
  const gchar *dbus_error;
  const gchar *message;
  const GHashTable *details = NULL;
  TpConnectionStatusReason reason;

  dbus_error = tp_account_get_detailed_error (account, &details);

  if (user_requested != NULL)
    {
      if (tp_asv_get_boolean (details, "user-requested", NULL))
        *user_requested = TRUE;
      else
        *user_requested = FALSE;
    }

  message = empathy_dbus_error_name_get_default_message (dbus_error);
  if (message != NULL)
    return message;

  tp_account_get_connection_status (account, &reason);

  DEBUG ("Don't understand error '%s'; fallback to the status reason (%u)",
    dbus_error, reason);

  return empathy_status_reason_get_default_message (reason);
}
/**
 * empathy_server_sasl_handler_can_save_response_somewhere:
 * @self:
 *
 * Returns: %TRUE if the response can be saved somewhere, either the keyring
 *   or via Ch.I.CredentialsStorage
 */
gboolean
empathy_server_sasl_handler_can_save_response_somewhere (
    EmpathyServerSASLHandler *self)
{
  EmpathyServerSASLHandlerPriv *priv;
  gboolean may_save_response, may_save_response_valid;
  gboolean has_storage_iface;

  g_return_val_if_fail (EMPATHY_IS_SERVER_SASL_HANDLER (self), FALSE);

  priv = self->priv;

  /* determine if we are permitted to save the password locally */
  may_save_response = tp_asv_get_boolean (
      tp_channel_borrow_immutable_properties (priv->channel),
      TP_PROP_CHANNEL_INTERFACE_SASL_AUTHENTICATION_MAY_SAVE_RESPONSE,
      &may_save_response_valid);

  if (!may_save_response_valid)
    {
      DEBUG ("MaySaveResponse unknown, assuming TRUE");
      may_save_response = TRUE;
    }

  has_storage_iface = tp_proxy_has_interface_by_id (priv->channel,
      EMP_IFACE_QUARK_CHANNEL_INTERFACE_CREDENTIALS_STORAGE);

  return may_save_response || has_storage_iface;
}
static void
tp_tests_simple_channel_dispatcher_create_channel (
    TpSvcChannelDispatcher *dispatcher,
    const gchar *account,
    GHashTable *request,
    gint64 user_action_time,
    const gchar *preferred_handler,
    DBusGMethodInvocation *context)
{
  TpTestsSimpleChannelDispatcher *self = SIMPLE_CHANNEL_DISPATCHER (dispatcher);
  gchar *path;

  if (tp_asv_get_boolean (request, "CreateChannelFail", NULL))
    {
      /* Fail to create the channel */
      GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
          "Computer says no" };

      dbus_g_method_return_error (context, &error);
      return;
    }

  path = create_channel_request (self, account, request, user_action_time,
      preferred_handler);

  tp_svc_channel_dispatcher_return_from_create_channel (context, path);

  g_free (path);
}
gboolean hev_impathy_server_sasl_handler_can_save_response_somewhere(
			HevImpathyServerSASLHandler *self)
{
	HevImpathyServerSASLHandlerPrivate * priv = NULL;
	gboolean may_save_response = FALSE,
			 may_save_response_valid = FALSE;
	gboolean has_storage_iface = FALSE;

	g_debug("%s:%d[%s]", __FILE__, __LINE__, __FUNCTION__);

	g_return_if_fail(HEV_IS_IMPATHY_SERVER_SASL_HANDLER(self));

	priv = HEV_IMPATHY_SERVER_SASL_HANDLER_GET_PRIVATE(self);

	/* determine if we are permitted to save the password locally */
	may_save_response = tp_asv_get_boolean(
				tp_channel_borrow_immutable_properties(priv->channel),
				TP_PROP_CHANNEL_INTERFACE_SASL_AUTHENTICATION_MAY_SAVE_RESPONSE,
				&may_save_response_valid);

	if(!may_save_response_valid)
	{
		may_save_response = TRUE;
	}

#if 0 /* TODO */
	has_storage_iface = tp_proxy_has_interface_by_id(priv->channel,
				EMP_IFACE_QUARK_CHANNEL_INTERFACE_CREDENTIALS_STORAGE);
#endif

	return may_save_response || has_storage_iface;

}
static void
got_all_properties_cb (TpProxy *proxy,
    GHashTable *properties,
    const GError *error,
    gpointer user_data,
    GObject *weak_object)
{
  TpCallStream *self = (TpCallStream *) proxy;
  const gchar * const *interfaces;
  GHashTable *remote_members;
  GHashTable *identifiers;
  GHashTable *contacts;

  if (error != NULL)
    {
      DEBUG ("Could not get the call stream properties: %s", error->message);
      _tp_proxy_set_feature_prepared (proxy,
          TP_CALL_STREAM_FEATURE_CORE, FALSE);
      return;
    }

  self->priv->properties_retrieved = TRUE;

  interfaces = tp_asv_get_boxed (properties,
      "Interfaces", G_TYPE_STRV);
  remote_members = tp_asv_get_boxed (properties,
      "RemoteMembers", TP_HASH_TYPE_CONTACT_SENDING_STATE_MAP),
  identifiers = tp_asv_get_boxed (properties,
      "RemoteMemberIdentifiers", TP_HASH_TYPE_HANDLE_IDENTIFIER_MAP);
  self->priv->local_sending_state = tp_asv_get_uint32 (properties,
      "LocalSendingState", NULL);
  self->priv->can_request_receiving = tp_asv_get_boolean (properties,
      "CanRequestReceiving", NULL);

  tp_proxy_add_interfaces ((TpProxy *) self, interfaces);

  contacts = _tp_call_members_convert_table (self->priv->connection,
      remote_members, identifiers);
  update_remote_members (self, contacts, NULL);
  g_hash_table_unref (contacts);

  _tp_proxy_set_feature_prepared (proxy, TP_CALL_STREAM_FEATURE_CORE, TRUE);
}
gboolean
empathy_tp_streamed_media_has_initial_video (EmpathyTpStreamedMedia *self)
{
  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (self);
  GHashTable *props;
  gboolean initial_video;
  gboolean valid;

  if (priv->channel == NULL)
    return FALSE;

  g_object_get (priv->channel, "channel-properties", &props, NULL);

  initial_video = tp_asv_get_boolean (props,
    TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA ".InitialVideo", &valid);
  if (!valid)
    initial_video = FALSE;

  g_hash_table_unref (props);
  return initial_video;
}
static void
on_channel_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
{
    TpChannel *tp_chan = TP_CHANNEL (source_object);
    McdChannel *channel, **channel_ptr = user_data;
    McdChannelPrivate *priv;
    gboolean requested, valid;
    GError *error = NULL;

    if (!tp_proxy_prepare_finish (tp_chan, result, &error))
    {
        DEBUG ("failed to prepare channel: %s", error->message);
        g_clear_error (&error);
        return;
    }

    channel = *channel_ptr;
    if (channel)
	g_object_remove_weak_pointer ((GObject *)channel,
				      (gpointer)channel_ptr);
    g_slice_free (McdChannel *, channel_ptr);
    if (error)
    {
        DEBUG ("got error: %s", error->message);
	return;
    }

    if (!channel) return;

    DEBUG ("channel %p is ready", channel);
    priv = channel->priv;
    requested = tp_asv_get_boolean
        (tp_channel_borrow_immutable_properties (tp_chan),
         TP_IFACE_CHANNEL ".Requested", &valid);
    if (valid)
        priv->outgoing = requested;
}
static void
_mcd_channel_setup (McdChannel *channel, McdChannelPrivate *priv)
{
    McdChannel **channel_ptr;
    GHashTable *properties;

    channel_ptr = g_slice_alloc (sizeof (McdChannel *));
    *channel_ptr = channel;
    g_object_add_weak_pointer ((GObject *)channel, (gpointer)channel_ptr);
    tp_proxy_prepare_async (priv->tp_chan, NULL, on_channel_ready, channel_ptr);

    g_signal_connect (priv->tp_chan, "invalidated",
		      G_CALLBACK (proxy_destroyed), channel);

    properties = tp_channel_borrow_immutable_properties (priv->tp_chan);
    if (properties)
    {
        gboolean requested, valid = FALSE;
        requested = tp_asv_get_boolean
            (properties, TP_IFACE_CHANNEL ".Requested", &valid);
        if (valid)
            priv->outgoing = requested;
    }
}
void
empathy_server_sasl_handler_provide_password (
    EmpathyServerSASLHandler *handler,
    const gchar *password,
    gboolean remember)
{
  EmpathyServerSASLHandlerPriv *priv;
  GArray *array;
  gboolean may_save_response, may_save_response_valid;

  g_return_if_fail (EMPATHY_IS_SERVER_SASL_HANDLER (handler));

  priv = handler->priv;

  array = g_array_sized_new (TRUE, FALSE,
      sizeof (gchar), strlen (password));

  g_array_append_vals (array, password, strlen (password));

  DEBUG ("Calling StartMechanismWithData with our password");

  tp_cli_channel_interface_sasl_authentication_call_start_mechanism_with_data (
      priv->channel, -1, "X-TELEPATHY-PASSWORD", array,
      start_mechanism_with_data_cb, NULL, NULL, G_OBJECT (handler));

  g_array_unref (array);

  DEBUG ("%sremembering the password", remember ? "" : "not ");

  /* determine if we are permitted to save the password locally */
  may_save_response = tp_asv_get_boolean (
      tp_channel_borrow_immutable_properties (priv->channel),
      TP_PROP_CHANNEL_INTERFACE_SASL_AUTHENTICATION_MAY_SAVE_RESPONSE,
      &may_save_response_valid);

  if (!may_save_response_valid)
    {
      DEBUG ("MaySaveResponse unknown, assuming TRUE");
      may_save_response = TRUE;
    }

  if (remember)
    {
      if (may_save_response)
        {
          g_free (priv->password);

          /* We'll save the password if we manage to connect */
          priv->password = g_strdup (password);
          priv->save_password = TRUE;
        }
      else if (tp_proxy_has_interface_by_id (priv->channel,
            EMP_IFACE_QUARK_CHANNEL_INTERFACE_CREDENTIALS_STORAGE))
        {
          DEBUG ("Channel implements Ch.I.CredentialsStorage");
        }
      else
        {
          DEBUG ("Asked to remember password, but doing so is not permitted");
        }
    }

  if (!may_save_response)
    {
      /* delete any password present, it shouldn't be there */
      empathy_keyring_delete_account_password_async (priv->account, NULL, NULL);
    }

  /* Additionally, if we implement Ch.I.CredentialsStorage, inform that
   * whether we want to remember the password */
  if (tp_proxy_has_interface_by_id (priv->channel,
        EMP_IFACE_QUARK_CHANNEL_INTERFACE_CREDENTIALS_STORAGE))
    {
      emp_cli_channel_interface_credentials_storage_call_store_credentials (
          TP_PROXY (priv->channel), -1, remember, NULL, NULL, NULL, NULL);
    }
}
static gboolean
rakia_media_manager_requestotron (TpChannelManager *manager,
                                  gpointer request_token,
                                  GHashTable *request_properties,
                                  RequestMethod method)
{
  RakiaMediaManager *self = RAKIA_MEDIA_MANAGER (manager);
  RakiaMediaManagerPrivate *priv = RAKIA_MEDIA_MANAGER_GET_PRIVATE (self);
  TpBaseConnection *conn = (TpBaseConnection *) priv->conn;
  TpHandleType handle_type;
  TpHandle handle;
  RakiaSipSession *session;
  RakiaCallChannel *channel = NULL;
  GError *error = NULL;
  GSList *request_tokens;
  gboolean valid = FALSE;
  gboolean initial_audio = FALSE;
  gboolean initial_video = FALSE;
  TpHandle self_handle = tp_base_connection_get_self_handle (conn);

  /* Supported modes of operation:
   * - RequestChannel(Contact, n) where n != 0:
   *     channel has TargetHandle=n;
   *     n is in remote pending;
   *     call is started when caller calls RequestStreams.
   * - CreateChannel({THT: Contact, TH: n}):
   *     channel has TargetHandle=n
   *     n is not in the group interface at all
   *     call is started when caller calls RequestStreams.
   * - EnsureChannel({THT: Contact, TH: n}):
   *     look for a channel whose peer is n, and return that if found with
   *       whatever properties and group membership it has;
   *     otherwise the same as into CreateChannel
   */

  if (tp_strdiff (tp_asv_get_string (request_properties,
          TP_PROP_CHANNEL_CHANNEL_TYPE),
        TP_IFACE_CHANNEL_TYPE_CALL))
    return FALSE;

  if (tp_asv_get_boolean (request_properties,
          TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, &valid) && valid)
    initial_audio = TRUE;
  if (tp_asv_get_boolean (request_properties,
          TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, &valid) && valid)
    initial_audio = TRUE;

  if (!initial_audio && !initial_video)
    return FALSE;

  handle_type = tp_asv_get_uint32 (request_properties,
      TP_IFACE_CHANNEL ".TargetHandleType", NULL);

  handle = tp_asv_get_uint32 (request_properties,
      TP_IFACE_CHANNEL ".TargetHandle", NULL);

  if (handle_type != TP_HANDLE_TYPE_CONTACT)
    return FALSE;

  g_assert (handle != 0);

  if (tp_channel_manager_asv_has_unknown_properties (request_properties,
          media_channel_fixed_properties, named_channel_allowed_properties,
          &error))
    goto error;

  /* Calls to self are problematic in terms of StreamedMedia channel
   * interface and its semantically required Group member changes;
   * we disable them until a better API is available through
   * Call channel type */
  if (handle == self_handle)
    {
      g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
          "Cannot call self");
      goto error;
    }

  if (method == METHOD_ENSURE)
    {
      guint i;
      TpHandle peer = 0;

      for (i = 0; i < priv->channels->len; i++)
        {
          channel = g_ptr_array_index (priv->channels, i);
          g_object_get (channel, "peer", &peer, NULL);

          if (peer == handle)
            {
              tp_channel_manager_emit_request_already_satisfied (self,
                  request_token, TP_EXPORTABLE_CHANNEL (channel));
              return TRUE;
            }
        }
    }

  session = new_session (self, NULL, handle);
  channel = new_call_channel (self, self_handle, handle,
      request_properties, session);
  g_object_unref (session);

  request_tokens = g_slist_prepend (NULL, request_token);
  tp_channel_manager_emit_new_channel (self,
      TP_EXPORTABLE_CHANNEL (channel), request_tokens);
  g_slist_free (request_tokens);

  return TRUE;

error:
  tp_channel_manager_emit_request_failed (self, request_token,
      error->domain, error->code, error->message);
  g_error_free (error);
  return TRUE;
}
/**
 * new_call_channel
 *
 * Creates a new empty RakiaCallChannel.
 */
static RakiaCallChannel *
new_call_channel (RakiaMediaManager *fac,
                   TpHandle initiator,
                   TpHandle maybe_peer,
                   GHashTable *request_properties,
                   RakiaSipSession *session)
{
  RakiaMediaManagerPrivate *priv = RAKIA_MEDIA_MANAGER_GET_PRIVATE (fac);
  RakiaCallChannel *chan = NULL;
  gchar *object_path;
  gboolean initial_audio = FALSE;
  gboolean initial_video = FALSE;
  gboolean immutable_streams = FALSE;
  const gchar *dtmf_initial_tones = NULL;
  const gchar *initial_audio_name = NULL;
  const gchar *initial_video_name = NULL;
  TpHandle self_handle = tp_base_connection_get_self_handle (priv->conn);

  g_assert (initiator != 0);

  object_path = g_strdup_printf ("%s/CallChannel%u",
      tp_base_connection_get_object_path (priv->conn), priv->channel_index++);

  DEBUG("channel object path %s", object_path);

  if (request_properties != NULL)
    {
      initial_audio = tp_asv_get_boolean (request_properties,
          TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, NULL);
      initial_video = tp_asv_get_boolean (request_properties,
          TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, NULL);
      initial_audio_name = tp_asv_get_string (request_properties,
          TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO_NAME);
      initial_video_name = tp_asv_get_string (request_properties,
          TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO_NAME);
      dtmf_initial_tones = tp_asv_get_string (request_properties,
          TP_PROP_CHANNEL_INTERFACE_DTMF_INITIAL_TONES);
    }

  g_object_get (priv->conn,
      "immutable-streams", &immutable_streams,
      NULL);

  chan = g_object_new (RAKIA_TYPE_CALL_CHANNEL,
                       "connection", priv->conn,
                       "object-path", object_path,
                       "handle", maybe_peer,
                       "initiator-handle", initiator,
                       "initial-audio", initial_audio,
                       "initial-video", initial_video,
                       "initial-audio-name", initial_audio_name,
                       "initial-video-name", initial_video_name,
                       "initial-transport", TP_STREAM_TRANSPORT_TYPE_RAW_UDP,
                       "mutable-contents", !immutable_streams,
                       "initial-tones", dtmf_initial_tones,
                       "sip-session", session,
                       "stun-server", priv->stun_server ? priv->stun_server :
                       "",
                       "stun-port", priv->stun_port,
                       "requested", (initiator == self_handle),
                       NULL);

  g_free (object_path);


  g_signal_connect (chan, "closed", G_CALLBACK (call_channel_closed_cb), fac);

  g_ptr_array_add (priv->channels, chan);

  tp_base_channel_register (TP_BASE_CHANNEL (chan));

  return chan;
}
void hev_impathy_server_sasl_handler_provide_password(
			HevImpathyServerSASLHandler *self,
			const gchar *password, gboolean remember)
{
	HevImpathyServerSASLHandlerPrivate * priv = NULL;
	GArray *array = NULL;
	gboolean may_save_response = FALSE,
			 may_save_response_valid = FALSE;

	g_debug("%s:%d[%s]", __FILE__, __LINE__, __FUNCTION__);

	g_return_if_fail(HEV_IS_IMPATHY_SERVER_SASL_HANDLER(self));

	priv = HEV_IMPATHY_SERVER_SASL_HANDLER_GET_PRIVATE(self);

	array = g_array_sized_new(TRUE, FALSE,
				sizeof(gchar), strlen(password));

	g_array_append_vals(array, password, strlen(password));

	tp_cli_channel_interface_sasl_authentication_call_start_mechanism_with_data(
				priv->channel, -1, "X-TELEPATHY-PASSWORD", array,
				start_mechanism_with_data_handler, NULL, NULL, G_OBJECT(self));

	g_array_unref(array);

	/* determine if we are permitted to save the password locally */
	may_save_response = tp_asv_get_boolean(
				tp_channel_borrow_immutable_properties(priv->channel),
				TP_PROP_CHANNEL_INTERFACE_SASL_AUTHENTICATION_MAY_SAVE_RESPONSE,
				&may_save_response_valid);

	if(!may_save_response_valid)
	{
		may_save_response = TRUE;
	}

	if(remember)
	{
		if(may_save_response)
		{
			g_free(priv->password);

			/* We'll save the password if we manage to connect */
			priv->password = g_strdup(password);
			priv->save_password = TRUE;
		}
#if 0 /* TODO */
		else if(tp_proxy_has_interface_by_id(priv->channel,
						EMP_IFACE_QUARK_CHANNEL_INTERFACE_CREDENTIALS_STORAGE))
		{
		}
		else
		{
		}
#endif
	}

	if(!may_save_response)
	{
		/* delete any password present, it shouldn't be there */
		hev_impathy_keyring_delete_account_password_async(priv->account,
					NULL, NULL);
	}

#if 0 /* TODO */
	/* Additionally, if we implement Ch.I.CredentialsStorage, inform that
	 * whether we want to remember the password. */
	if(tp_proxy_has_interface_by_id(priv->channel,
					EMP_IFACE_QUARK_CHANNEL_INTERFACE_CREDENTIALS_STORAGE))
	{
		emp_cli_channel_interface_credentials_storage_call_store_credentials(
					TP_PROXY(priv->channel), -1, remember, NULL, NULL, NULL, NULL);
	}
#endif
}
static void
on_call_channel_get_all_properties_cb (TpProxy *proxy,
    GHashTable *properties,
    const GError *error,
    gpointer user_data,
    GObject *weak_object)
{
  TpyCallChannel *self = TPY_CALL_CHANNEL (proxy);
  GSimpleAsyncResult *result = user_data;
  GHashTable *hash_table;
  GPtrArray *contents;
  guint i;

  if (error != NULL)
    {
      g_warning ("Could not get the channel properties: %s", error->message);
      g_simple_async_result_set_from_error (result, error);
      goto out;
    }

  self->priv->state = tp_asv_get_uint32 (properties,
      "CallState", NULL);
  self->priv->flags = tp_asv_get_uint32 (properties,
      "CallFlags", NULL);
  self->priv->initial_audio = tp_asv_get_boolean (properties,
      "InitialAudio", NULL);
  self->priv->initial_video = tp_asv_get_boolean (properties,
      "InitialVideo", NULL);

  hash_table = tp_asv_get_boxed (properties,
      "CallStateDetails", TP_HASH_TYPE_STRING_VARIANT_MAP);
  if (hash_table != NULL)
    self->priv->details = g_boxed_copy (TP_HASH_TYPE_STRING_VARIANT_MAP,
        hash_table);

  hash_table = tp_asv_get_boxed (properties,
      "CallMembers", TPY_HASH_TYPE_CALL_MEMBER_MAP);
  update_call_members (self, hash_table, NULL);

  contents = tp_asv_get_boxed (properties,
      "Contents", TP_ARRAY_TYPE_OBJECT_PATH_LIST);

  for (i = 0; i < contents->len; i++)
    {
      const gchar *content_path = g_ptr_array_index (contents, i);
      TpyCallContent *content;

      DEBUG ("Content added: %s", content_path);

      content = g_object_new (TPY_TYPE_CALL_CONTENT,
              "bus-name", tp_proxy_get_bus_name (self),
              "dbus-daemon", tp_proxy_get_dbus_daemon (self),
              "dbus-connection", tp_proxy_get_dbus_connection (self),
              "object-path", content_path,
              NULL);

      if (content == NULL)
        {
          g_warning ("Could not create a CallContent for path %s", content_path);

          g_simple_async_result_set_error (result, TP_ERRORS, TP_ERROR_CONFUSED,
              "Could not create a CallContent for path %s", content_path);
          goto out;
        }

      g_ptr_array_add (self->priv->contents, content);

      tp_g_signal_connect_object (content, "notify::ready",
        G_CALLBACK (on_content_ready_cb), self, 0);
    }

  g_signal_emit (self, _signals[MEMBERS_CHANGED], 0, self->priv->members);

  self->priv->properties_retrieved = TRUE;

  maybe_go_to_ready (self);

out:
  /* TODO; ideally we should get rid of the ready property and complete once
   * all the contents have been prepared. Or maybe that should be another
   * feature? */
  g_simple_async_result_complete (result);
}
示例#14
0
static void
empathy_account_update (EmpathyAccount *account,
    GHashTable *properties)
{
  EmpathyAccountPriv *priv = GET_PRIV (account);
  GValueArray *arr;
  TpConnectionStatus old_s = priv->connection_status;
  gboolean presence_changed = FALSE;

  if (g_hash_table_lookup (properties, "ConnectionStatus") != NULL)
    priv->connection_status =
      tp_asv_get_int32 (properties, "ConnectionStatus", NULL);

  if (g_hash_table_lookup (properties, "ConnectionStatusReason") != NULL)
    priv->reason = tp_asv_get_int32 (properties,
      "ConnectionStatusReason", NULL);

  if (g_hash_table_lookup (properties, "CurrentPresence") != NULL)
    {
      presence_changed = TRUE;
      arr = tp_asv_get_boxed (properties, "CurrentPresence",
        TP_STRUCT_TYPE_SIMPLE_PRESENCE);
      priv->presence = g_value_get_uint (g_value_array_get_nth (arr, 0));

      g_free (priv->status);
      priv->status = g_value_dup_string (g_value_array_get_nth (arr, 1));

      g_free (priv->message);
      priv->message = g_value_dup_string (g_value_array_get_nth (arr, 2));
    }

  if (g_hash_table_lookup (properties, "DisplayName") != NULL)
    {
      g_free (priv->display_name);
      priv->display_name =
        g_strdup (tp_asv_get_string (properties, "DisplayName"));
      g_object_notify (G_OBJECT (account), "display-name");
    }

  if (g_hash_table_lookup (properties, "Icon") != NULL)
    {
      const gchar *icon_name;

      icon_name = tp_asv_get_string (properties, "Icon");

      g_free (priv->icon_name);

      if (EMP_STR_EMPTY (icon_name))
        priv->icon_name = empathy_protocol_icon_name (priv->proto_name);
      else
        priv->icon_name = g_strdup (icon_name);
    }

  if (g_hash_table_lookup (properties, "Enabled") != NULL)
    {
      gboolean enabled = tp_asv_get_boolean (properties, "Enabled", NULL);
      if (priv->enabled != enabled)
        {
          priv->enabled = enabled;
          g_object_notify (G_OBJECT (account), "enabled");
        }
    }

  if (g_hash_table_lookup (properties, "Valid") != NULL)
    priv->valid = tp_asv_get_boolean (properties, "Valid", NULL);

  if (g_hash_table_lookup (properties, "Parameters") != NULL)
    {
      GHashTable *parameters;

      parameters = tp_asv_get_boxed (properties, "Parameters",
        TP_HASH_TYPE_STRING_VARIANT_MAP);

      if (priv->parameters != NULL)
        g_hash_table_unref (priv->parameters);

      priv->parameters = g_boxed_copy (TP_HASH_TYPE_STRING_VARIANT_MAP,
        parameters);
    }

  if (!priv->ready)
    {
      priv->ready = TRUE;
      g_object_notify (G_OBJECT (account), "ready");
    }

  if (priv->connection_status != old_s)
    {
      if (priv->connection_status == TP_CONNECTION_STATUS_CONNECTED)
        {
          GTimeVal val;
          g_get_current_time (&val);

          priv->connect_time = val.tv_sec;
        }

      g_signal_emit (account, signals[STATUS_CHANGED], 0,
        old_s, priv->connection_status, priv->reason);

      g_object_notify (G_OBJECT (account), "connection-status");
      g_object_notify (G_OBJECT (account), "connection-status-reason");
    }

  if (presence_changed)
    {
      g_signal_emit (account, signals[PRESENCE_CHANGED], 0,
        priv->presence, priv->status, priv->message);
      g_object_notify (G_OBJECT (account), "presence");
      g_object_notify (G_OBJECT (account), "status");
      g_object_notify (G_OBJECT (account), "status-message");
    }

  if (g_hash_table_lookup (properties, "Connection") != NULL)
    {
      const gchar *conn_path =
        tp_asv_get_object_path (properties, "Connection");

      _empathy_account_set_connection (account, conn_path);
    }
}