Re: [Evolution-hackers] New 'eclient' branch in eds



On Mon, 2011-04-18 at 15:57 +0200, Milan Crha wrote: 
> I just created a new branch 'eclient' in eds [1] where is added my work
> on the new API which will deprecate EBook/ECal. It is following glib/gio
> async pattern and, I believe, makes things more coherent.

There's a few other weightier issues in the client-side APIs that I
wanted to address separately after getting the trivial stuff out of the
way.  Three topics:


1) There's no need for apps to use numeric IDs to track asynchronous
   operations; GCancellable fills that role.  GCancellable is the app's
   handle to the ongoing operation.  If the app wants to cancel an
   unfinished operation, it calls g_cancellable_cancel().

   The following functions should be dropped from the public API:

     e_client_cancel_op()
     e_client_register_op()
     e_client_unregister_op()

   All functions that kick off an asynchronous operation should return
   "void".  If you need to use numeric IDs to track D-Bus operations,
   do so internally.  Create an "e-client-private.h" if you need to.
   Don't expose it in the public API.


2) ECredentials is way too complex.  My intent for ECredentials was to
   have a self-contained authentication handling interface to avoid all
   the current nonsense with ECal and EBook where you have to always
   remember to connect to authentication signals and then implement the
   keyring lookup and user password prompting yourself.

   I probably didn't spell this out very well initially, but what I had
   in mind was a simple abstract interface to replace "auth-required"
   signals.

       struct _ECredentialsInterface {
           GTypeInterface parent_interface;

           void    (*get_password)       (ECredentials *credentials,
                                          EClient *client,
                                          GCancellable *cancellable,
                                          GAsyncReadyCallback callback,
                                          gpointer user_data);

           gchar * (get_password_finish) (ECredentials *credentials,
                                          GAsyncResult *result,
                                          GError **error);
       };

   Some kind of object implementing the ECredentials interface would be
   passed to the EClient as a construct property.  Then when EClient
   gets notified by the backend that authentication is required, it
   would simply call the get_password() method from an idle callback.
   Whatever implements the get_password() method should then handle the
   password lookup and, if necessary, user prompting, all by itself.

   The benefit here is that apps can simply pass some pre-packaged
   ECredentials implementation when creating calendar or address book
   connections and not have to worry about handling authentication
   beyond that.

   The ECredentials API you came up with would be one possible
   implementation of the raw ECredentials interface illustrated above.
   It should live in libedataserverui or maybe just in Evolution so it
   can run a password dialog or whatever other GTK-related things it
   may need to do.


3) The "new" functions for EClient classes should be asynchronous, and
   I'd like to drop the "open" functions:

      e_client_open()
      e_client_open_finish()
      e_client_open_sync()

   (Keeping the open() *class method* around might make sense to help
    make subclassing EClient easier.)

   I'd really like for establishing a D-Bus connection to the backend,
   connecting to a remote server, and authenticating via ECredentials to
   be *one* step for the app.  It either all works and you get back a
   fully connected and authenticated EClient object, or something fails
   and you get back NULL with a GError set.

   I want to avoid these weird in-between states where you're holding a
   client object but you haven't connected to the backend yet, or you
   failed to authenticate with the remoter server, etc.  It just makes
   life difficult and confusing for apps trying to figure what they're
   supposed to do in these cases.

   To that end, EClient should implement the GAsyncInitable interface
   from GIO, and create instances with g_async_initable_new_async()
   instead of g_object_new().

   http://developer.gnome.org/gio/unstable/GAsyncInitable.html

   The "new" function for ECalClient should be something like:

   void e_cal_client_new (ESource *source,
                          ECredentials *credentials,
                          ECalClientSourceType source_type,
                          GCancellable *cancellable,
                          GAsyncReadyCallback callback,
                          gpointer user_data);

   ECalClient * e_cal_client_new_finish (ESource *source,
                                         GAsyncResult *result,
                                         GError **error);

   Similarly for EBookClient.



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]