[shotwell] Put authenticators into separate library



commit a3b6e0f6f73069ad2472ffa68f36f77adadd0485
Author: Jens Georg <mail jensge org>
Date:   Mon Feb 6 19:08:31 2017 +0100

    Put authenticators into separate library

 Makefile.am                                        |    3 +
 authenticator.am                                   |   52 ++++++
 configure.ac                                       |   28 ++++
 .../shotwell}/FacebookPublishingAuthenticator.vala |   13 +-
 .../shotwell}/FlickrPublishingAuthenticator.vala   |  172 +++++++++++++++++++-
 .../shotwell/ShotwellAuthenticatorFactory.vala     |   33 ++++
 .../shotwell}/flickr_pin_entry_pane.ui             |    0
 .../org.gnome.Shotwell.Authenticator.gresource.xml |    6 +
 .../shotwell-publishing/FacebookPublishing.vala    |    4 +-
 plugins/shotwell-publishing/FlickrPublishing.vala  |   25 +---
 .../org.gnome.Shotwell.Publishing.gresource.xml    |    1 -
 publish.am                                         |   12 +-
 src/plugins/PublishingInterfaces.vala              |    7 +-
 13 files changed, 317 insertions(+), 39 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 4568e29..93b929b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -131,6 +131,9 @@ include $(top_srcdir)/common.am
 include $(top_srcdir)/shotwell.am
 include $(top_srcdir)/thumbnailer.am
 
+# Authenticators
+include $(top_srcdir)/authenticator.am
+
 # Plugins
 include $(top_srcdir)/publish.am
 
diff --git a/authenticator.am b/authenticator.am
new file mode 100644
index 0000000..442ad5b
--- /dev/null
+++ b/authenticator.am
@@ -0,0 +1,52 @@
+lib_LTLIBRARIES += plugins/authenticator/libshotwell-authenticator.la
+
+dist_noinst_DATA += \
+       plugins/authenticator/shotwell/flickr_pin_entry_pane.ui
+
+plugins_authenticator_libshotwell_authenticator_la_SOURCES = \
+       $(abs_top_srcdir)/plugins/shotwell-plugin-common.vapi
+
+plugins_authenticator_libshotwell_authenticator_la_VALAFLAGS = \
+       $(COMMON_VALAFLAGS) \
+       --library shotwell-authenticator \
+       --vapi=plugins/authenticator/shotwell-authenticator.vapi \
+       --header=plugins/authenticator/shotwell-authenticator.h \
+       --pkg shotwell-plugin-dev-1.0 \
+       $(AUTHENTICATOR_PACKAGES) \
+       --vapidir $(abs_top_srcdir)/plugins
+
+plugins_authenticator_libshotwell_authenticator_la_LIBADD = \
+       $(AUTHENTICATOR_LIBS) \
+       $(top_builddir)/plugins/common/libshotwell-plugin-common.la
+
+plugins_authenticator_libshotwell_authenticator_la_CFLAGS = \
+       $(COMMON_CFLAGS) \
+       $(AUTHENTICATOR_CFLAGS) \
+       -I $(top_srcdir)/plugins \
+       -DPLUGIN_RESOURCE_PATH='"/org/gnome/Shotwell/Authenticator"'
+
+## Resource handling
+
+nodist_plugins_authenticator_libshotwell_authenticator_la_SOURCES = \
+       plugins/authenticator/resource.c
+MOSTLYCLEANFILES += plugins/authenticator/resource.c
+
+AUTHENTICATOR_RESOURCE_DEPS = $(shell $(GLIB_COMPILE_RESOURCES) \
+               --sourcedir=$(AUTHENTICATOR_RESOURCE_SOURCEDIR) \
+               --generate-dependencies $(AUTHENTICATOR_SHOTWELL_RESOURCE_FILE))
+
+plugins/authenticator/resource.c: $(AUTHENTICATOR_RESOURCE_DEPS) $(AUTHENTICATOR_RESOURCE_FILE)
+       $(AM_V_GEN)$(GLIB_COMPILE_RESOURCES) \
+               --target=$@ \
+               --sourcedir=$(AUTHENTICATOR_RESOURCE_SOURCEDIR) \
+               --generate $(AUTHENTICATOR_RESOURCE_FILE)
+
+if AUTHENTICATOR_SHOTWELL
+AUTHENTICATOR_RESOURCE_FILE := 
$(abs_top_srcdir)/plugins/authenticator/shotwell/org.gnome.Shotwell.Authenticator.gresource.xml
+AUTHENTICATOR_RESOURCE_SOURCEDIR := $(abs_top_srcdir)/plugins/authenticator/shotwell
+
+plugins_authenticator_libshotwell_authenticator_la_SOURCES += \
+       plugins/authenticator/shotwell/ShotwellAuthenticatorFactory.vala \
+       plugins/authenticator/shotwell/FacebookPublishingAuthenticator.vala \
+       plugins/authenticator/shotwell/FlickrPublishingAuthenticator.vala
+endif
diff --git a/configure.ac b/configure.ac
index d50b58f..e41b006 100644
--- a/configure.ac
+++ b/configure.ac
@@ -81,6 +81,25 @@ VALAFLAGS="-g"
 AC_SUBST([VALAFLAGS])
 
 dnl ***********************************************************************
+dnl Check for authenticator
+dnl ***********************************************************************
+AC_ARG_WITH([authenticator],
+            AS_HELP_STRING([--with-authenticator=@<:@shotwell,goa,uoa@:>@]
+                           [Which authentication back-end to use (defaul: shotwell)]),
+                           [with_authenticator=$withval],
+                           [with_authenticator=shotwell])
+AS_IF([test "x$with_authenticator" != "xshotwell" &&
+       test "x$with_authenticator" != "xgoa" &&
+       test "x$with_authenticator" != "xuoa"],
+            [AC_MSG_NOTICE([Unknown authenticator $[]with_authenticator, using shotwell])
+             with_authenticator="shotwell"
+            ])
+
+AM_CONDITIONAL([AUTHENTICATOR_SHOTWELL],[test "x$with_authenticator" = "xshotwell"])
+AM_CONDITIONAL([AUTHENTICATOR_GOA],[test "x$with_authenticator" = "xgoa"])
+AM_CONDITIONAL([AUTHENTICATOR_UOA],[test "x$with_authenticator" = "xuoa"])
+
+dnl ***********************************************************************
 dnl Check for required packages
 dnl ***********************************************************************
 PKG_CHECK_MODULES(SHOTWELL, [
@@ -118,6 +137,14 @@ PKG_CHECK_MODULES(PUBLISHING, [gobject-2.0 glib-2.0 gexiv2 json-glib-1.0
 PKG_CHECK_MODULES(TRANSITIONS, [gobject-2.0 cairo gio-2.0 gdk-pixbuf-2.0
                                 gdk-3.0])
 
+AS_IF([test "x$with_authenticator" = "xshotwell"],
+      [
+        PKG_CHECK_MODULES(AUTHENTICATOR, [gobject-2.0 glib-2.0 libsoup-2.4
+                                          webkit2gtk-4.0 gee-0.8 gtk+-3.0
+                                          libxml-2.0])
+        AC_SUBST(AUTHENTICATOR_PACKAGES, ["--pkg webkit2gtk-4.0 --pkg gtk+-3.0 --pkg libsoup-2.4 --pkg 
gee-0.8 --pkg libxml-2.0"])
+      ])
+
 dnl ***********************************************************************
 dnl Unity support
 dnl ***********************************************************************
@@ -199,4 +226,5 @@ echo "  Prefix ............................... : ${prefix}"
 echo "  Libdir ............................... : ${libdir}"
 echo "  Unity support ........................ : ${HAVE_UNITY}"
 echo "  Additional publishing plugins ........ : ${HAVE_EXTRA_PLUGINS}"
+echo "  Authentication library ................: ${with_authenticator}"
 echo ""
diff --git a/plugins/shotwell-publishing/FacebookPublishingAuthenticator.vala 
b/plugins/authenticator/shotwell/FacebookPublishingAuthenticator.vala
similarity index 96%
rename from plugins/shotwell-publishing/FacebookPublishingAuthenticator.vala
rename to plugins/authenticator/shotwell/FacebookPublishingAuthenticator.vala
index ba9c6a7..4aa4fa4 100644
--- a/plugins/shotwell-publishing/FacebookPublishingAuthenticator.vala
+++ b/plugins/authenticator/shotwell/FacebookPublishingAuthenticator.vala
@@ -4,10 +4,13 @@
  * (version 2.1 or later).  See the COPYING file in this distribution.
  */
 
-namespace Publishing.Facebook {
+using Shotwell;
+using Shotwell.Plugins;
+
+namespace Publishing.Authenticator.Shotwell.Facebook {
     private const string APPLICATION_ID = "1612018629063184";
 
-    private class WebAuthenticationPane : Shotwell.Plugins.Common.WebAuthenticationPane {
+    private class WebAuthenticationPane : Common.WebAuthenticationPane {
         private static bool cache_dirty = false;
 
         public signal void login_succeeded(string success_url);
@@ -154,9 +157,9 @@ namespace Publishing.Facebook {
         }
     }
 
-    public class FacebookAuthenticator : Spit.Publishing.Authenticator, GLib.Object {
+    internal class Facebook : Spit.Publishing.Authenticator, GLib.Object {
         private Spit.Publishing.PluginHost host;
-        private Publishing.Facebook.WebAuthenticationPane web_auth_pane = null;
+        private Publishing.Authenticator.Shotwell.Facebook.WebAuthenticationPane web_auth_pane = null;
         private GLib.HashTable<string, Variant> params;
 
         private const string SERVICE_WELCOME_MESSAGE =
@@ -165,7 +168,7 @@ namespace Publishing.Facebook {
     _("You have already logged in and out of Facebook during this Shotwell session.\nTo continue publishing 
to Facebook, quit and restart Shotwell, then try publishing again.");
 
         /* Interface functions */
-        public FacebookAuthenticator(Spit.Publishing.PluginHost host) {
+        public Facebook(Spit.Publishing.PluginHost host) {
             this.host = host;
             this.params = new GLib.HashTable<string, Variant>(str_hash, str_equal);
         }
diff --git a/plugins/shotwell-publishing/FlickrPublishingAuthenticator.vala 
b/plugins/authenticator/shotwell/FlickrPublishingAuthenticator.vala
similarity index 66%
rename from plugins/shotwell-publishing/FlickrPublishingAuthenticator.vala
rename to plugins/authenticator/shotwell/FlickrPublishingAuthenticator.vala
index 1bf930b..006987c 100644
--- a/plugins/shotwell-publishing/FlickrPublishingAuthenticator.vala
+++ b/plugins/authenticator/shotwell/FlickrPublishingAuthenticator.vala
@@ -4,7 +4,175 @@
  * (version 2.1 or later).  See the COPYING file in this distribution.
  */
 
-namespace Publishing.Authenticator {
+namespace Publishing.Flickr {
+    internal const string ENDPOINT_URL = "https://api.flickr.com/services/rest";;
+    internal const string EXPIRED_SESSION_ERROR_CODE = "98";
+    internal const string ENCODE_RFC_3986_EXTRA = "!*'();:@&=+$,/?%#[] \\";
+
+    internal class Transaction : Publishing.RESTSupport.Transaction {
+        public Transaction(Session session, Publishing.RESTSupport.HttpMethod method =
+                Publishing.RESTSupport.HttpMethod.POST) {
+            base(session, method);
+
+            add_argument("oauth_nonce", session.get_oauth_nonce());
+            add_argument("oauth_signature_method", "HMAC-SHA1");
+            add_argument("oauth_version", "1.0");
+            add_argument("oauth_callback", "oob");
+            add_argument("oauth_timestamp", session.get_oauth_timestamp());
+            add_argument("oauth_consumer_key", session.get_consumer_key());
+        }
+
+        public Transaction.with_uri(Session session, string uri,
+                Publishing.RESTSupport.HttpMethod method = Publishing.RESTSupport.HttpMethod.POST) {
+            base.with_endpoint_url(session, uri, method);
+
+            add_argument("oauth_nonce", session.get_oauth_nonce());
+            add_argument("oauth_signature_method", "HMAC-SHA1");
+            add_argument("oauth_version", "1.0");
+            add_argument("oauth_callback", "oob");
+            add_argument("oauth_timestamp", session.get_oauth_timestamp());
+            add_argument("oauth_consumer_key", session.get_consumer_key());
+        }
+
+        public override void execute() throws Spit.Publishing.PublishingError {
+            ((Session) get_parent_session()).sign_transaction(this);
+
+            base.execute();
+        }
+    }
+
+    internal class Session : Publishing.RESTSupport.Session {
+        private string? request_phase_token = null;
+        private string? request_phase_token_secret = null;
+        private string? access_phase_token = null;
+        private string? access_phase_token_secret = null;
+        private string? username = null;
+        private string? consumer_key = null;
+        private string? consumer_secret = null;
+
+        public Session() {
+            base();
+        }
+
+        public override bool is_authenticated() {
+            return (access_phase_token != null && access_phase_token_secret != null &&
+                    username != null);
+        }
+
+        public void set_api_credentials(string consumer_key, string consumer_secret) {
+            this.consumer_key = consumer_key;
+            this.consumer_secret = consumer_secret;
+        }
+
+        public void sign_transaction(Publishing.RESTSupport.Transaction txn) {
+            string http_method = txn.get_method().to_string();
+
+            debug("signing transaction with parameters:");
+            debug("HTTP method = " + http_method);
+
+            Publishing.RESTSupport.Argument[] base_string_arguments = txn.get_arguments();
+
+            Publishing.RESTSupport.Argument[] sorted_args =
+                Publishing.RESTSupport.Argument.sort(base_string_arguments);
+
+            string arguments_string = "";
+            for (int i = 0; i < sorted_args.length; i++) {
+                arguments_string += (sorted_args[i].key + "=" + sorted_args[i].value);
+                if (i < sorted_args.length - 1)
+                    arguments_string += "&";
+            }
+
+            string? signing_key = null;
+            if (access_phase_token_secret != null) {
+                debug("access phase token secret available; using it as signing key");
+
+                signing_key = consumer_secret + "&" + access_phase_token_secret;
+            } else if (request_phase_token_secret != null) {
+                debug("request phase token secret available; using it as signing key");
+
+                signing_key = consumer_secret + "&" + request_phase_token_secret;
+            } else {
+                debug("neither access phase nor request phase token secrets available; using API " +
+                        "key as signing key");
+
+                signing_key = consumer_secret + "&";
+            }
+
+            string signature_base_string = http_method + "&" + Soup.URI.encode(
+                    txn.get_endpoint_url(), ENCODE_RFC_3986_EXTRA) + "&" +
+                Soup.URI.encode(arguments_string, ENCODE_RFC_3986_EXTRA);
+
+            debug("signature base string = '%s'", signature_base_string);
+
+            debug("signing key = '%s'", signing_key);
+
+            // compute the signature
+            string signature = RESTSupport.hmac_sha1(signing_key, signature_base_string);
+            signature = Soup.URI.encode(signature, ENCODE_RFC_3986_EXTRA);
+
+            debug("signature = '%s'", signature);
+
+            txn.add_argument("oauth_signature", signature);
+        }
+
+        public void set_request_phase_credentials(string token, string secret) {
+            this.request_phase_token = token;
+            this.request_phase_token_secret = secret;
+        }
+
+        public void set_access_phase_credentials(string token, string secret, string username) {
+            this.access_phase_token = token;
+            this.access_phase_token_secret = secret;
+            this.username = username;
+
+            authenticated();
+        }
+
+        public string get_oauth_nonce() {
+            TimeVal currtime = TimeVal();
+            currtime.get_current_time();
+
+            return Checksum.compute_for_string(ChecksumType.MD5, currtime.tv_sec.to_string() +
+                    currtime.tv_usec.to_string());
+        }
+
+        public string get_oauth_timestamp() {
+            return GLib.get_real_time().to_string().substring(0, 10);
+        }
+
+        public string get_consumer_key() {
+            assert(consumer_key != null);
+            return consumer_key;
+        }
+
+        public string get_request_phase_token() {
+            assert(request_phase_token != null);
+            return request_phase_token;
+        }
+
+        public string get_request_phase_token_secret() {
+            assert(request_phase_token_secret != null);
+            return request_phase_token_secret;
+        }
+
+        public string get_access_phase_token() {
+            assert(access_phase_token != null);
+            return access_phase_token;
+        }
+
+        public string get_access_phase_token_secret() {
+            assert(access_phase_token_secret != null);
+            return access_phase_token_secret;
+        }
+
+        public string get_username() {
+            assert(is_authenticated());
+            return username;
+        }
+    }
+}
+
+namespace Publishing.Authenticator.Shotwell.Flickr {
     internal const string API_KEY = "60dd96d4a2ad04888b09c9e18d82c26f";
     internal const string API_SECRET = "d0960565e03547c1";
 
@@ -82,7 +250,7 @@ namespace Publishing.Authenticator {
     }
 
 
-    public class Flickr : GLib.Object, Spit.Publishing.Authenticator {
+    internal class Flickr : GLib.Object, Spit.Publishing.Authenticator {
         private GLib.HashTable<string, Variant> params;
         private Publishing.Flickr.Session session;
         private Spit.Publishing.PluginHost host;
diff --git a/plugins/authenticator/shotwell/ShotwellAuthenticatorFactory.vala 
b/plugins/authenticator/shotwell/ShotwellAuthenticatorFactory.vala
new file mode 100644
index 0000000..d804440
--- /dev/null
+++ b/plugins/authenticator/shotwell/ShotwellAuthenticatorFactory.vala
@@ -0,0 +1,33 @@
+namespace Publishing.Authenticator {
+    public class Factory : Spit.Publishing.AuthenticatorFactory, Object {
+        private static Factory instance = null;
+
+        public static Factory get_instance() {
+            if (Factory.instance == null) {
+                Factory.instance = new Factory();
+            }
+
+            return Factory.instance;
+        }
+
+        public GLib.List<string> get_available_authenticators() {
+            var list = new GLib.List<string>();
+            list.append ("flickr");
+            list.append ("facebook");
+
+            return list;
+        }
+
+        public Spit.Publishing.Authenticator? create(string provider,
+                                                     Spit.Publishing.PluginHost host) {
+            switch (provider) {
+                case "flickr":
+                    return new Shotwell.Flickr.Flickr(host);
+                case "facebook":
+                    return new Shotwell.Facebook.Facebook(host);
+                default:
+                    return null;
+            }
+        }
+    }
+}
diff --git a/plugins/shotwell-publishing/flickr_pin_entry_pane.ui 
b/plugins/authenticator/shotwell/flickr_pin_entry_pane.ui
similarity index 100%
rename from plugins/shotwell-publishing/flickr_pin_entry_pane.ui
rename to plugins/authenticator/shotwell/flickr_pin_entry_pane.ui
diff --git a/plugins/authenticator/shotwell/org.gnome.Shotwell.Authenticator.gresource.xml 
b/plugins/authenticator/shotwell/org.gnome.Shotwell.Authenticator.gresource.xml
new file mode 100644
index 0000000..c40e700
--- /dev/null
+++ b/plugins/authenticator/shotwell/org.gnome.Shotwell.Authenticator.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/org/gnome/Shotwell/Authenticator">
+      <file>flickr_pin_entry_pane.ui</file>
+  </gresource>
+</gresources>
diff --git a/plugins/shotwell-publishing/FacebookPublishing.vala 
b/plugins/shotwell-publishing/FacebookPublishing.vala
index 3e1345e..d57c1bd 100644
--- a/plugins/shotwell-publishing/FacebookPublishing.vala
+++ b/plugins/shotwell-publishing/FacebookPublishing.vala
@@ -186,7 +186,9 @@ public class FacebookPublisher : Spit.Publishing.Publisher, GLib.Object {
         this.host = host;
 
         this.publishing_params = new PublishingParameters();
-        this.authenticator = new Publishing.Facebook.FacebookAuthenticator(host);
+        this.authenticator =
+            Publishing.Authenticator.Factory.get_instance().create("facebook",
+                    host);
 
         this.graph_session = new GraphSession();
         graph_session.authenticated.connect(on_session_authenticated);
diff --git a/plugins/shotwell-publishing/FlickrPublishing.vala 
b/plugins/shotwell-publishing/FlickrPublishing.vala
index 7478778..6ba3cb8 100644
--- a/plugins/shotwell-publishing/FlickrPublishing.vala
+++ b/plugins/shotwell-publishing/FlickrPublishing.vala
@@ -98,7 +98,7 @@ public class FlickrPublisher : Spit.Publishing.Publisher, GLib.Object {
     private bool was_started = false;
     private Session session = null;
     private PublishingOptionsPane publishing_options_pane = null;
-    private Publishing.Authenticator.Flickr authenticator;
+    private Spit.Publishing.Authenticator authenticator = null;
    
     private PublishingParameters parameters = null;
 
@@ -109,7 +109,7 @@ public class FlickrPublisher : Spit.Publishing.Publisher, GLib.Object {
         this.host = host;
         this.session = new Session();
         this.parameters = new PublishingParameters();
-        this.authenticator = new Publishing.Authenticator.Flickr (host);
+        this.authenticator = Publishing.Authenticator.Factory.get_instance().create("flickr", host);
 
         this.authenticator.authenticated.connect(on_session_authenticated);
     }
@@ -663,8 +663,6 @@ private class UploadTransaction : Publishing.RESTSupport.UploadTransaction {
 }
 
 internal class Session : Publishing.RESTSupport.Session {
-    private string? request_phase_token = null;
-    private string? request_phase_token_secret = null;
     private string? access_phase_token = null;
     private string? access_phase_token_secret = null;
     private string? username = null;
@@ -735,10 +733,6 @@ internal class Session : Publishing.RESTSupport.Session {
             debug("access phase token secret available; using it as signing key");
 
             signing_key = consumer_secret + "&" + access_phase_token_secret;
-        } else if (request_phase_token_secret != null) {
-            debug("request phase token secret available; using it as signing key");
-
-            signing_key = consumer_secret + "&" + request_phase_token_secret;
         } else {
             debug("neither access phase nor request phase token secrets available; using API " +
                 "key as signing key");
@@ -766,11 +760,6 @@ internal class Session : Publishing.RESTSupport.Session {
             txn.add_argument("oauth_signature", signature);
     }
     
-    public void set_request_phase_credentials(string token, string secret) {
-        this.request_phase_token = token;
-        this.request_phase_token_secret = secret;
-    }
-    
     public void set_access_phase_credentials(string token, string secret, string username) {
         this.access_phase_token = token;
         this.access_phase_token_secret = secret;
@@ -795,16 +784,6 @@ internal class Session : Publishing.RESTSupport.Session {
         assert(consumer_key != null);
         return consumer_key;
     }
-    
-    public string get_request_phase_token() {
-        assert(request_phase_token != null);
-        return request_phase_token;
-    }
-
-    public string get_request_phase_token_secret() {
-        assert(request_phase_token_secret != null);
-        return request_phase_token_secret;
-    }
 
     public string get_access_phase_token() {
         assert(access_phase_token != null);
diff --git a/plugins/shotwell-publishing/org.gnome.Shotwell.Publishing.gresource.xml 
b/plugins/shotwell-publishing/org.gnome.Shotwell.Publishing.gresource.xml
index af3baad..b09902e 100644
--- a/plugins/shotwell-publishing/org.gnome.Shotwell.Publishing.gresource.xml
+++ b/plugins/shotwell-publishing/org.gnome.Shotwell.Publishing.gresource.xml
@@ -7,7 +7,6 @@
       <file>piwigo.png</file>
       <file>youtube.png</file>
       <file>facebook_publishing_options_pane.ui</file>
-      <file>flickr_pin_entry_pane.ui</file>
       <file>flickr_publishing_options_pane.ui</file>
       <file>picasa_publishing_options_pane.ui</file>
       <file>piwigo_authentication_pane.ui</file>
diff --git a/publish.am b/publish.am
index a5c2d87..9736191 100644
--- a/publish.am
+++ b/publish.am
@@ -7,7 +7,6 @@ dist_noinst_DATA += \
        plugins/shotwell-publishing/piwigo.png \
        plugins/shotwell-publishing/youtube.png \
        plugins/shotwell-publishing/facebook_publishing_options_pane.ui \
-       plugins/shotwell-publishing/flickr_pin_entry_pane.ui \
        plugins/shotwell-publishing/flickr_publishing_options_pane.ui \
        plugins/shotwell-publishing/picasa_publishing_options_pane.ui \
        plugins/shotwell-publishing/piwigo_authentication_pane.ui \
@@ -19,13 +18,12 @@ dist_noinst_DATA += \
 plugins_shotwell_publishing_shotwell_publishing_la_SOURCES = \
        plugins/shotwell-publishing/shotwell-publishing.vala \
        plugins/shotwell-publishing/FacebookPublishing.vala \
-       plugins/shotwell-publishing/FacebookPublishingAuthenticator.vala \
        plugins/shotwell-publishing/PicasaPublishing.vala \
        plugins/shotwell-publishing/FlickrPublishing.vala \
-       plugins/shotwell-publishing/FlickrPublishingAuthenticator.vala \
        plugins/shotwell-publishing/YouTubePublishing.vala \
        plugins/shotwell-publishing/PiwigoPublishing.vala \
-       plugins/shotwell-plugin-common.vapi
+       plugins/shotwell-plugin-common.vapi \
+       plugins/authenticator/shotwell-authenticator.vapi
 
 nodist_plugins_shotwell_publishing_shotwell_publishing_la_SOURCES = \
        plugins/shotwell-publishing/resource.c
@@ -63,11 +61,13 @@ plugins_shotwell_publishing_shotwell_publishing_la_CFLAGS = \
        $(COMMON_CFLAGS) \
        -DGCR_API_SUBJECT_TO_CHANGE \
        $(PUBLISHING_CFLAGS) \
-       -I $(top_srcdir)/plugins
+       -I $(top_srcdir)/plugins \
+       -I $(top_srcdir)/plugins/authenticator
 
 plugins_shotwell_publishing_shotwell_publishing_la_LDFLAGS = \
        $(SHOTWELL_PLUGIN_LDFLAGS)
 
 plugins_shotwell_publishing_shotwell_publishing_la_LIBADD = \
        $(PUBLISHING_LIBS) \
-       $(top_builddir)/plugins/common/libshotwell-plugin-common.la
+       $(top_builddir)/plugins/common/libshotwell-plugin-common.la \
+       $(top_builddir)/plugins/authenticator/libshotwell-authenticator.la
diff --git a/src/plugins/PublishingInterfaces.vala b/src/plugins/PublishingInterfaces.vala
index 7695bab..3015452 100644
--- a/src/plugins/PublishingInterfaces.vala
+++ b/src/plugins/PublishingInterfaces.vala
@@ -621,8 +621,13 @@ public interface Authenticator : Object {
 }
 
 public interface AuthenticatorFactory : Object {
+    // By contract, every AuthenticatorFactory implementation needs to have a
+    // static get_instance() method. Unfortunately this is not expressable in
+    // Vala.
+
     public abstract GLib.List<string> get_available_authenticators();
-    public abstract Authenticator? create(string provider);
+    public abstract Authenticator? create(string provider,
+            Spit.Publishing.PluginHost host);
 }
 
 }


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