diff options
Diffstat (limited to 'src/Application.vala')
-rw-r--r-- | src/Application.vala | 109 |
1 files changed, 106 insertions, 3 deletions
diff --git a/src/Application.vala b/src/Application.vala index 59bae36..d9edcaf 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -4,7 +4,75 @@ * (version 2.1 or later). See the COPYING file in this distribution. */ +[DBus(name = "org.gnome.Shotwell.Authenticate")] +public interface AuthenticationReceiver : Object { + public abstract void callback(string url) throws DBusError, IOError; +} + +[DBus(name = "org.gnome.Shotwell.Authenticate")] +internal class AuthenticatorReceiverApp : Gtk.Application, AuthenticationReceiver { + private Gee.HashMap<string, Spit.Publishing.AuthenticatedCallback> + pending_auth_requests = new Gee.HashMap<string, Spit.Publishing.AuthenticatedCallback>(); + + public AuthenticatorReceiverApp() { + Object(application_id: "org.gnome.Shotwell", flags: GLib.ApplicationFlags.HANDLES_OPEN | + GLib.ApplicationFlags.HANDLES_COMMAND_LINE); + } + public override bool dbus_register(DBusConnection connection, string object_path) throws Error { + try { + connection.register_object(object_path, this); + } catch (IOError e) { + warning("Failed to register authentication helper on session connection: %s", e.message); + } + return true; + } + + + internal void register_auth_callback(string cookie, Spit.Publishing.AuthenticatedCallback cb) { + pending_auth_requests[cookie] = cb; + } + + internal void unregister_auth_callback(string cookie) { + pending_auth_requests.unset(cookie); + } + + public void callback(string callback_url) throws DBusError, IOError { + try { + var uri = Uri.parse(callback_url, UriFlags.NONE); + debug("Got authentication callback uri: %s", callback_url); + // See if something is waiting for a pending authentication + var query = uri.get_query(); + if (query == null || query == "") { + debug("Callback does not have parameters. Not accepting"); + + return; + } + var uri_params = Uri.parse_params(uri.get_query()); + if ("sw_auth_cookie" in uri_params) { + var cookie = uri_params["sw_auth_cookie"]; + if (pending_auth_requests.has_key(cookie)) { + pending_auth_requests[cookie].authenticated(uri_params); + LibraryWindow.get_app().present(); + } else { + debug("No call-back registered for cookie %s, probably user cancelled", cookie); + } + } else if (uri.get_scheme().has_prefix("com.googleusercontent.apps")) { + if (pending_auth_requests.has_key(uri.get_scheme())) { + pending_auth_requests[uri.get_scheme()].authenticated(uri_params); + } else { + debug("No call-back registered for cookie %s, probably user cancelled", uri.get_scheme()); + } + } + } catch (Error error) { + warning("Got invalid authentication call-back: %s", callback_url); + } + } +} + public class Application { + public interface AuthCallback : Object { + public abstract void authenticated(HashTable<string, string> params); + } private static Application instance = null; private Gtk.Application system_app = null; private int system_app_run_retval = 0; @@ -36,20 +104,21 @@ public class Application { private bool running = false; private bool exiting_fired = false; + Gee.HashMap<string, AuthCallback> pending_auth_requests = new Gee.HashMap<string, AuthCallback>(); + private Application(bool is_direct) { if (is_direct) { // we allow multiple instances of ourself in direct mode, so DON'T // attempt to be unique. We don't request any command-line handling // here because this is processed elsewhere, and we don't need to handle // command lines from remote instances, since we don't care about them. - system_app = new Gtk.Application("org.gnome.Shotwell-direct", GLib.ApplicationFlags.HANDLES_OPEN | + system_app = new Gtk.Application("org.gnome.Shotwell-Viewer", GLib.ApplicationFlags.HANDLES_OPEN | GLib.ApplicationFlags.NON_UNIQUE); } else { // we've been invoked in library mode; set up for uniqueness and handling // of incoming command lines from remote instances (needed for getting // storage device and camera mounts). - system_app = new Gtk.Application("org.gnome.Shotwell", GLib.ApplicationFlags.HANDLES_OPEN | - GLib.ApplicationFlags.HANDLES_COMMAND_LINE); + system_app = new AuthenticatorReceiverApp(); } // GLib will assert if we don't do this... @@ -63,12 +132,46 @@ public class Application { if (!direct) { system_app.command_line.connect(on_command_line); + var action = new SimpleAction("authenticated", VariantType.STRING); + system_app.add_action(action); + action.activate.connect((a, p) => { + try { + var uri = Uri.parse(p.get_string(), UriFlags.NONE); + debug("Got authentication callback uri: %s", p.get_string()); + // See if something is waiting for a pending authentication + var uri_params = Uri.parse_params(uri.get_query()); + if ("sw_auth_cookie" in uri_params) { + var cookie = uri_params["sw_auth_cookie"]; + if (pending_auth_requests.has_key(cookie)) { + pending_auth_requests[cookie].authenticated(uri_params); + } else { + debug("No call-back registered for cookie %s, probably user cancelled", cookie); + } + } + } catch (Error error) { + warning("Got invalid authentication call-back: %s", p.get_string()); + } + }); } system_app.activate.connect(on_activated); system_app.startup.connect(on_activated); } + public static void register_auth_callback(string cookie, Spit.Publishing.AuthenticatedCallback cb) { + var instance = get_instance(); + if (!instance.direct) { + ((AuthenticatorReceiverApp)instance.system_app).register_auth_callback(cookie, cb); + } + } + + public static void unregister_auth_callback(string cookie) { + var instance = get_instance(); + if (!instance.direct) { + ((AuthenticatorReceiverApp)instance.system_app).unregister_auth_callback(cookie); + } + } + public static double get_scale() { var instance = get_instance().system_app; unowned GLib.List<Gtk.Window> windows = instance.get_windows(); |