[Bug 34228] Implement API for requesting channels and handling them yourself

bugzilla-daemon at freedesktop.org bugzilla-daemon at freedesktop.org
Mon Feb 28 19:07:37 CET 2011


https://bugs.freedesktop.org/show_bug.cgi?id=34228

--- Comment #2 from Olli Salli <ollisal at gmail.com> 2011-02-28 10:07:36 PST ---
Ok, so my 2 cents on how this should be implemented follow.

So, the requirements boil down to:
 1) It's possible to request a channel from the Channel Dispatcher using a
Tp::Account and handle it without explicitly being a Handler - as easily as one
could (incorrectly) request a channel directly from the Connection
 2) The resulting channel, contacts in it and any connection proxy created for
the channel should all be pre-existing instances on the Account's factories, or
if there isn't any, created and made ready accordingly to the factory settings
 3) We need to still adhere to the spec, in particular:
   a) the Client.Handler.HandledChannels property needs to always have the
channels handled by any Handler on the same D-Bus connection / unique name
(note that this is not service / client name specific, but *unique* connection
name). I think this is already guaranteed via a static map in the Handler
adaptor though, but check for this in the unit test please.
   b) if somebody else ensures a channel matching one we're already handling
via this API, the CD will invoke HandleChannels again to tell us to bring our
window/tab/whatever for the channel to the foreground
   c) we shouldn't affect any other Handlers by e.g. hijacking Channels they're
expecting

Not requiring being a Handler (requirement 1) implies that you don't
necessarily have to be any kind of Client at all, which would imply we don't
want to require an existing ClientRegistrar to be passed to this API, or to be
in existence at all.

Also, the factory requirement (requirement 2) means that even though there
would be a ClientRegistrar in existence already, we couldn't necessarily use
it, as it might have different factories from the ones in the Account (which is
sadly true for many existing applications which haven't grasped the awesomeness
of the ClientRegistrar::create(AccountManager) method yet).

Therefore, we have to create a ClientRegistrar internally ourselves for the
purposes of just requesting and handling this single channel. This is fine
efficiency-wise: Creating a ClientRegistrar is actually almost free as it
doesn't do any D-Bus traffic or connect to any signals etc. Being able to do
this is why I wanted us to drop the ClientRegistrar singleton guarantee for
tp-qt 0.5.

So, the request and handle PendingOperation would first of all create a
ClientRegistrar, then generate a unique client name for that request only
(suggestion: use the PID and a static variable incremented for each request),
and register a Handler with an empty filter on the created ClientRegistrar.
Empty filter, because PreferredHandler bypasses handler filters, and we don't
want any other channels (req 3c).

However, creating a ClientRegistrar currently requires one to pass in an
AccountFactory. This is not really needed for our case, as the only account
ever required to be created is the Account the request is made on. Hence I
think the cleanest way to do this, rather than having a separate code path
inside ClientRegistrar for having an AccountFactory or not, would be to just
make a fake AccountFactory which just always returns the Account the request
was made through (but compares the object paths and warns if they differ or
something, this'd indicate some madness in the Channel Dispatcher with it
giving us a channel for a different account).

Having done that, the request and handle PendingOp would then Proceed the
ChannelRequest, just as for a normal "request and forget" request.

At some point the channel comes in. Our hidden ClientRegistrar and Handler then
construct the relevant Channel and Connection proxy for us according to the
factory settings. At this point, we should finish, and give the resulting
Channel to whoever requested it.

However, the fun doesn't stop there. To be able to fulfill req 3b, we need to
continue being a Handler with the same client name for as long as the channel
is in existence. We also need some way to signal the application about the
reinvocation.

Therefore, we need an additional QObject, let's call it HandledChannelNotifier
or somesuch, which just has a handledAgain() signal, and which is kept alive as
long as the Channel is alive (and not invalidated). As long as the notifier is
alive, it should keep the handler registered too. So, it should receive the
shared pointers to the ClientRegistrar and the ownership of the Handler from
the original request and handle PendingOperation when it finishes.

Needless to say, no matter if it takes quite a few hours, this all needs a
proper regression test :) One should obviously cut corners in implementing the
fake channel dispatcher required for this, though. The one in the
AccountChannelDispatcher test shouldn't require too much modification, except
for testing the re-handling case (req 3b).

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.



More information about the telepathy-bugs mailing list