Proposals for 3.0.0 API changes

Will Thompson will at
Mon Dec 31 12:09:08 EST 2007

On Mon, Dec 31, 2007 at 11:06:33AM -0500, Sadrul Habib Chowdhury wrote:
> Is there something that explains how telepathy-haze interacts with
> libpurple, e.g., how accounts are managed, plugin preferences are
> presented to the user etc.

Well, accounts and connections are presented to the user as
[o.f.Telepathy.Connections] as per the Telepathy [spec] (a PurpleAccount
is created and destroyed whenever a Telepathy.Connection is created or
destroyed, because account management is done by your Telepathy UI of
choice).  There's no Haze-specific document; I've been meaning to write
one, but haven't had time (and won't for a few weeks by the look of uni

(Plugin preferences aren't presented to the user, mainly because
libpurple plugins aren't presented to the user.  Plugins for connection
managers don't really make sense in the Telepathy world view.)


> > Ideally, requests and notifications would become special cases of
> > signals.  Consider the "%s requires plaintext authentication over an
> > unencrypted connection.  Allow this and continue authentication?"
> > requests in jabber/auth.c.  (Aside from the fact that this should
> > arguably be an account option,) this should emit a signal like
> > "allow-insecure-authentication" (using _emit_1 to prevent the callbacks
> Is it possible to have some simple and generic signals (e.g.,
> 'requesting-choice', 'requesting-input', 'requesting-fields' etc.)
> instead?

No, that's no better than the current situation.  I think the best way
to explain the problem is with an example.  Here's one involving
multi-user chats (which Haze doesn't actually do yet, partly due to this
problem and partly due to a lack of time).

First, some Telepathy background!  [Channels] are pretty much the
fundamental objects in the API.  Multi-user chats are represented as
[text channels] implementing the [Group interface].  When you are
invited to a chat, a channel is created for that chat and you are added
to the list of locally-pending members of that channel.  Moving yourself
from the pending list to the current member list serves to accept the
invitation, and removing yourself serves to decline it.

(When you've joined the chat, the members list shows who's in the chat;
the local pending list shows people who are awaiting authorization from
you to join; the remote pending list shows people who are awaiting
authorization to join but you don't have permission to give that
authorization.  (As an aside, you might notice that this is actually
also the API needed for privacy lists, such as authorizing people to see
your online status, and indeed the Group interface is used for this.))

[text channels]:
[Group interface]:

Now, here's the request made from serv_got_chat_invite() in server.c:

    g_snprintf(buf2, sizeof(buf2),
        _("%s has invited %s to the chat room %s\n"),
        who, purple_account_get_username(account), name);

    purple_request_accept_cancel(gc, NULL, _("Accept chat invitation?"), buf2,
                           PURPLE_DEFAULT_ACTION_NONE, account, who, NULL,
                           cid, G_CALLBACK(chat_invite_accept),

So when the request_action UiOp is called, Haze has no way to figure out
what it's being asked without a massive lookup table looking something

    if (strcmp (primary, _("Accept chat invitation?"))
        // * create a new muc
        // * add self to local_pending
        // * hook up accepting to the first callback (which we happen to
        //   know from reading server.c is "accept").
        // * hook up declining to the second.
    else if (strcmp (primary, _("SSL Certificate Verification")))

This is obviously not a good way to do things, and a request-choice
signal would be equally bad.  The point is that Haze doesn't know what
question is being asked.

Actually, if you look at the beginning of serv_got_chat_invite(), it
fires a chat-invited signal that actually doesn't solve the problem.  If
a handler for chat-invited returns >0, then the invitation is accepted;
if a handler returns <0, the invitation is declined.  But the signal
handler needs to make a decision immediately.  What's needed here (and
in many similar uses of the request API, hence why I want to standardize
this for libpurple 3) is a signal with a signature looking something

    gboolean (*chat_invited)(account, who, message, yes_cb, no_cb, cb_data)

emitted with _emit_return_1.  If a handler returns TRUE, then the
purple_request_accept_cancel should not be made, and the handler must
arrange for either yes_cb (cb_data) or no_cb (cb_data) to be called at
some point in the future.  This is exactly the same as the
purple_request_accept_cancel call, except that the UI knows what the
question actually is.

Of course, if a handler wants to accept or decline immediately, it just
calls yes_cb (cb_data) or no_cb (cb_data) immediately, just as
serv_got_chat_invite does right now.

This email is much longer than I intended it to be, but I hope it
clarifies the API I'm after, as well as the rationale behind it.

(Hrm.  It looks like I just made time to begin writing up how Haze maps
libpurple to the Telepathy API!)

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <>

More information about the Devel mailing list