X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fmoonshot-identity-manager-app.vala;h=b1e2400afdcea4f105234a01415012cfc141066c;hb=3be9164b4ef280f25b996238a135b2f29e95e8fb;hp=0838f66f0ba1b6069c8adb5e1651229c343b6646;hpb=1cef26ea4e2e7f1d5506470cd7675df4bbd08f6e;p=moonshot-ui.git diff --git a/src/moonshot-identity-manager-app.vala b/src/moonshot-identity-manager-app.vala index 0838f66..b1e2400 100644 --- a/src/moonshot-identity-manager-app.vala +++ b/src/moonshot-identity-manager-app.vala @@ -43,40 +43,62 @@ interface IIdentityManager : GLib.Object { } #endif + public class IdentityManagerApp { + public static MoonshotLogger logger = get_logger("IdentityManagerApp"); + public IdentityManagerModel model; public IdCard default_id_card; public bool explicitly_launched; public IdentityManagerView view; private MoonshotServer ipc_server; + private bool name_is_owned; + private bool show_requested; #if OS_MACOS - public OSXApplication osxApp; + public OSXApplication osxApp; // the signal handler function. // the current instance of our app class is passed in the // id_manager_app_instanceparameter - public static bool on_osx_open_files (OSXApplication osx_app_instance, - string file_name, - IdentityManagerApp id_manager_app_instance ) { - int added_cards = id_manager_app_instance.ipc_server.install_from_file(file_name); - return true; - } + public static bool on_osx_open_files(OSXApplication osx_app_instance, + string file_name, + IdentityManagerApp id_manager_app_instance ) { + int added_cards = id_manager_app_instance.ipc_server.install_from_file(file_name); + return true; + } #endif private const int WINDOW_WIDTH = 400; private const int WINDOW_HEIGHT = 500; + + + /** If we're successfully registered with DBus, then show the UI. Otherwise, wait until we're registered. */ public void show() { - if (view != null) view.make_visible(); + if (name_is_owned) { + if (view != null) { + view.make_visible(); + } + } + else { + show_requested = true; + } } - - public IdentityManagerApp (bool headless, bool use_flat_file_store) { + +#if LOG4VALA + // Call this from main() to ensure that the logger is initialized + internal IdentityManagerApp.dummy() {} +#endif + + public IdentityManagerApp(bool headless, bool use_flat_file_store) { use_flat_file_store |= UserForcesFlatFileStore(); + #if GNOME_KEYRING bool keyring_available = (!use_flat_file_store) && GnomeKeyring.is_available(); #else bool keyring_available = false; #endif + IIdentityCardStore.StoreType store_type; if (headless || use_flat_file_store || !keyring_available) store_type = IIdentityCardStore.StoreType.FLAT_FILE; @@ -91,30 +113,30 @@ public class IdentityManagerApp { if (!headless) view = new IdentityManagerView(this); - LinkedList card_list = model.get_card_list() ; + LinkedList card_list = model.get_card_list(); if (card_list.size > 0) this.default_id_card = card_list.last(); - init_ipc_server (); + init_ipc_server(); #if OS_MACOS - osxApp = OSXApplication.get_instance(); - // The 'correct' way of connrcting wont work in Mac OS with Vala 0.12 e.g. - // osxApp.ns_application_open_file.connect(install_from_file); + // The 'correct' way of connecting won't work in Mac OS with Vala 0.12; e.g. + // osxApp.ns_application_open_file.connect(install_from_file); // so we have to use this old way Signal.connect(osxApp, "NSApplicationOpenFile", (GLib.Callback)(on_osx_open_files), this); - #endif } - public bool add_identity (IdCard id, bool force_flat_file_store) { + public bool add_identity(IdCard id, bool force_flat_file_store) { if (view != null) return view.add_identity(id, force_flat_file_store); model.add_card(id, force_flat_file_store); return true; } - public void select_identity (IdentityRequest request) { + public void select_identity(IdentityRequest request) { + logger.trace("select_identity"); + IdCard identity = null; if (request.select_default) @@ -144,7 +166,7 @@ public class IdentityManagerApp { { if (request.service == srv) { - request.candidates.append (id); + request.candidates.append(id); continue; } } @@ -167,19 +189,19 @@ public class IdentityManagerApp { has_service = true; continue; } - services_list.append (srv); + services_list.append(srv); } if (!has_service) continue; - if (services_list.length () == 0) + if (services_list.length() == 0) { id.services = {}; continue; } - string[] services = new string[services_list.length ()]; + string[] services = new string[services_list.length()]; foreach (string srv in services_list) { services[i] = srv; @@ -191,16 +213,16 @@ public class IdentityManagerApp { } /* If there are no candidates we use the service matching rules */ - if ((identity==null) && (request.candidates.length () == 0)) + if ((identity == null) && (request.candidates.length() == 0)) { foreach (IdCard id in model.get_card_list()) { foreach (Rule rule in id.rules) { - if (!match_service_pattern (request.service, rule.pattern)) + if (!match_service_pattern(request.service, rule.pattern)) continue; - request.candidates.append (id); + request.candidates.append(id); if (rule.always_confirm == "true") confirm = true; @@ -220,10 +242,11 @@ public class IdentityManagerApp { identity.temporary = true; } if (identity == null) { - if (request.candidates.length () != 1) { + if (request.candidates.length() != 1) { + logger.trace("select_identity: Have %u candidates; user must make selection.".printf(request.candidates.length())); confirm = true; } else { - identity = request.candidates.nth_data (0); + identity = request.candidates.nth_data(0); } } @@ -231,7 +254,7 @@ public class IdentityManagerApp { { if (!explicitly_launched) show(); - view.queue_identity_request(request); + view.queue_identity_request(request); return; } } @@ -240,60 +263,60 @@ public class IdentityManagerApp { GLib.Idle.add( () => { if (view != null) { + logger.trace("select_identity (Idle handler): calling check_add_password"); identity = view.check_add_password(identity, request, model); } - request.return_identity (identity); + request.return_identity(identity); // The following occasionally causes the app to exit without sending the dbus // reply, so for now we just don't exit // if (!explicitly_launched) -// Idle.add( () => { Gtk.main_quit(); return false; } ); +// Idle.add(() => { Gtk.main_quit(); return false; } ); return false; } - ); + ); return; } - private bool match_service_pattern (string service, string pattern) - { - var pspec = new PatternSpec (pattern); - return pspec.match_string (service); + private bool match_service_pattern(string service, string pattern) { + var pspec = new PatternSpec(pattern); + return pspec.match_string(service); } #if IPC_MSRPC - private void init_ipc_server () - { + private void init_ipc_server() { // Errors will currently be sent via g_log - ie. to an // obtrusive message box, on Windows // - this.ipc_server = MoonshotServer.get_instance (); - MoonshotServer.start (this); + this.ipc_server = MoonshotServer.get_instance(); + MoonshotServer.start(this); } #elif IPC_DBUS_GLIB - private void init_ipc_server () - { + private void init_ipc_server() { try { - var conn = DBus.Bus.get (DBus.BusType.SESSION); - dynamic DBus.Object bus = conn.get_object ("org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus"); + var conn = DBus.Bus.get(DBus.BusType.SESSION); + dynamic DBus.Object bus = conn.get_object("org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus"); // try to register service in session bus - uint reply = bus.request_name ("org.janet.Moonshot", (uint) 0); + uint reply = bus.request_name("org.janet.Moonshot", (uint) 0); if (reply == DBus.RequestNameReply.PRIMARY_OWNER) { - this.ipc_server = new MoonshotServer (this); - conn.register_object ("/org/janet/moonshot", ipc_server); + this.ipc_server = new MoonshotServer(this); + logger.trace("init_ipc_server(IPC_DBUS_GLIB) : Constructed new MoonshotServer"); + conn.register_object("/org/janet/moonshot", ipc_server); } else { - bool shown=false; + logger.trace("init_ipc_server: reply != PRIMARY_OWNER"); + bool shown = false; GLib.Error e; - DBus.Object manager_proxy = conn.get_object ("org.janet.Moonshot", - "/org/janet/moonshot", - "org.janet.Moonshot"); + DBus.Object manager_proxy = conn.get_object("org.janet.Moonshot", + "/org/janet/moonshot", + "org.janet.Moonshot"); if (manager_proxy != null) manager_proxy.call("ShowUi", out e, GLib.Type.INVALID, typeof(bool), out shown, GLib.Type.INVALID); if (!shown) { - GLib.error ("Couldn't own name org.janet.Moonshot on dbus or show previously launched identity manager."); + GLib.error("Couldn't own name org.janet.Moonshot on dbus or show previously launched identity manager."); } else { stdout.printf("Showed previously launched identity manager.\n"); GLib.Process.exit(0); @@ -302,43 +325,103 @@ public class IdentityManagerApp { } catch (DBus.Error e) { - stderr.printf ("%s\n", e.message); + logger.trace("bus_acquired_cb"); + try { + conn.register_object ("/org/janet/moonshot", ipc_server); + } + catch (Error e) + { + stderr.printf ("%s\n", e.message); + logger.error("bus_acquired_cb: Caught error: " + e.message); + } } } #else - private void bus_acquired_cb (DBusConnection conn) - { + private void bus_acquired_cb(DBusConnection conn) { + logger.trace("bus_acquired_cb"); try { - conn.register_object ("/org/janet/moonshot", ipc_server); + conn.register_object("/org/janet/moonshot", ipc_server); } catch (Error e) { - stderr.printf ("%s\n", e.message); + this.ipc_server = new MoonshotServer (this); + logger.trace("init_ipc_server: Constructed new MoonshotServer"); + GLib.Bus.own_name (GLib.BusType.SESSION, + "org.janet.Moonshot", + GLib.BusNameOwnerFlags.NONE, + bus_acquired_cb, + (conn, name) => {logger.trace("init_ipc_server: name_acquired_closure");}, + (conn, name) => { + logger.trace("init_ipc_server: name_lost_closure"); + bool shown=false; + try { + IIdentityManager manager = Bus.get_proxy_sync (BusType.SESSION, name, "/org/janet/moonshot"); + shown = manager.show_ui(); + } catch (IOError e) { + logger.error("init_ipc_server.name_lost_closure: Caught error: "); + } + if (!shown) { + GLib.error ("Couldn't own name %s on dbus or show previously launched identity manager.", name); + logger.error("init_ipc_server.name_lost_closure: Couldn't own name %s on dbus or show previously launched identity manager".printf(name)); + } else { + logger.trace("init_ipc_server.name_lost_closure: Showed previously launched identity manager."); + stdout.printf("Showed previously launched identity manager.\n"); + GLib.Process.exit(0); + } + }); } } - private void init_ipc_server () - { - this.ipc_server = new MoonshotServer (this); - GLib.Bus.own_name (GLib.BusType.SESSION, - "org.janet.Moonshot", - GLib.BusNameOwnerFlags.NONE, - bus_acquired_cb, - (conn, name) => {}, - (conn, name) => { - bool shown=false; - try { - IIdentityManager manager = Bus.get_proxy_sync (BusType.SESSION, name, "/org/janet/moonshot"); - shown = manager.show_ui(); - } catch (IOError e) { - } - if (!shown) { - GLib.error ("Couldn't own name %s on dbus or show previously launched identity manager.", name); - } else { - stdout.printf("Showed previously launched identity manager.\n"); - GLib.Process.exit(0); - } - }); + private void init_ipc_server() { + this.ipc_server = new MoonshotServer(this); + bool shown = false; + GLib.Bus.own_name(GLib.BusType.SESSION, + "org.janet.Moonshot", + GLib.BusNameOwnerFlags.NONE, + bus_acquired_cb, + + // Name acquired callback: + (conn, name) => { + logger.trace(@"init_ipc_server: name_acquired_closure; show_requested=$show_requested"); + + name_is_owned = true; + + // Now that we know that we own the name, it's safe to show the UI. + if (show_requested) { + show(); + show_requested = false; + } + shown = true; + }, + + // Name lost callback: + (conn, name) => { + logger.trace("init_ipc_server: name_lost_closure"); + + // This callback usually means that another moonshot is already running. + // But it *might* mean that we lost the name for some other reason + // (though it's unclear to me yet what those reasons are.) + // Clearing these flags seems like a good idea for that case. -- dbreslau + name_is_owned = false; + show_requested = false; + + try { + if (!shown) { + IIdentityManager manager = Bus.get_proxy_sync(BusType.SESSION, name, "/org/janet/moonshot"); + shown = manager.show_ui(); + } + } catch (IOError e) { + logger.error("init_ipc_server.name_lost_closure: Caught IOError: " + e.message); + } + if (!shown) { + logger.error("init_ipc_server.name_lost_closure: Couldn't own name %s on dbus or show previously launched identity manager".printf(name)); + GLib.error("Couldn't own name %s on dbus or show previously launched identity manager.", name); + } else { + logger.trace("init_ipc_server.name_lost_closure: Showed previously launched identity manager."); + stdout.printf("Showed previously launched identity manager.\n"); + GLib.Process.exit(0); + } + }); } #endif } @@ -346,75 +429,83 @@ public class IdentityManagerApp { static bool explicitly_launched = true; static bool use_flat_file_store = false; const GLib.OptionEntry[] options = { - {"dbus-launched",0,GLib.OptionFlags.REVERSE,GLib.OptionArg.NONE, - ref explicitly_launched,"launch for dbus rpc use",null}, - {"flat-file-store",0,0,GLib.OptionArg.NONE, - ref use_flat_file_store,"force use of flat file identity store (used by default only for headless operation)",null}, + {"dbus-launched", 0, GLib.OptionFlags.REVERSE, GLib.OptionArg.NONE, + ref explicitly_launched, "launch for dbus rpc use", null}, + {"flat-file-store", 0, 0, GLib.OptionArg.NONE, + ref use_flat_file_store, "force use of flat file identity store (used by default only for headless operation)", null}, {null} }; -public static int main(string[] args){ +public static int main(string[] args) { + +#if LOG4VALA + new IdentityManagerApp.dummy(); +#endif + #if IPC_MSRPC - bool headless = false; + bool headless = false; #else - bool headless = GLib.Environment.get_variable("DISPLAY") == null; + bool headless = GLib.Environment.get_variable("DISPLAY") == null; #endif - if (headless) { - try { - var opt_context = new OptionContext(null); - opt_context.set_help_enabled (true); - opt_context.add_main_entries (options, null); - opt_context.parse(ref args); - } catch (OptionError e) { - stdout.printf(_("error: %s\n"),e.message); - stdout.printf(_("Run '%s --help' to see a full list of available options\n"), args[0]); - return -1; - } - explicitly_launched = false; - } else { - try { - if (!Gtk.init_with_args(ref args, _(""), options, null)) { - stdout.printf(_("unable to initialize window\n")); - return -1; - } - } catch (GLib.Error e) { - stdout.printf(_("error: %s\n"),e.message); - stdout.printf(_("Run '%s --help' to see a full list of available options\n"), args[0]); + if (headless) { + try { + var opt_context = new OptionContext(null); + opt_context.set_help_enabled(true); + opt_context.add_main_entries(options, null); + opt_context.parse(ref args); + } catch (OptionError e) { + stdout.printf(_("error: %s\n"),e.message); + stdout.printf(_("Run '%s --help' to see a full list of available options\n"), args[0]); + return -1; + } + explicitly_launched = false; + } else { + try { + if (!Gtk.init_with_args(ref args, _(""), options, null)) { + stdout.printf(_("unable to initialize window\n")); return -1; } - gtk_available = true; + } catch (GLib.Error e) { + stdout.printf(_("error: %s\n"),e.message); + stdout.printf(_("Run '%s --help' to see a full list of available options\n"), args[0]); + return -1; } + gtk_available = true; + } #if OS_WIN32 - // Force specific theme settings on Windows without requiring a gtkrc file - Gtk.Settings settings = Gtk.Settings.get_default (); - settings.set_string_property ("gtk-theme-name", "ms-windows", "moonshot"); - settings.set_long_property ("gtk-menu-images", 0, "moonshot"); + // Force specific theme settings on Windows without requiring a gtkrc file + Gtk.Settings settings = Gtk.Settings.get_default(); + settings.set_string_property("gtk-theme-name", "ms-windows", "moonshot"); + settings.set_long_property("gtk-menu-images", 0, "moonshot"); #endif - Intl.bindtextdomain (Config.GETTEXT_PACKAGE, Config.LOCALEDIR); - Intl.bind_textdomain_codeset (Config.GETTEXT_PACKAGE, "UTF-8"); - Intl.textdomain (Config.GETTEXT_PACKAGE); + Intl.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR); + Intl.bind_textdomain_codeset(Config.GETTEXT_PACKAGE, "UTF-8"); + Intl.textdomain(Config.GETTEXT_PACKAGE); + - - var app = new IdentityManagerApp(headless, use_flat_file_store); - app.explicitly_launched = explicitly_launched; + var app = new IdentityManagerApp(headless, use_flat_file_store); + IdentityManagerApp.logger.trace("Hi again from main()!"); + app.explicitly_launched = explicitly_launched; + IdentityManagerApp.logger.trace(@"main: explicitly_launched=$explicitly_launched"); - if (app.explicitly_launched) { - app.show(); - } + if (app.explicitly_launched) { + app.show(); + } - if (headless) { + if (headless) { #if !IPC_MSRPC - MainLoop loop = new MainLoop(); - loop.run(); + MainLoop loop = new MainLoop(); + loop.run(); #endif - } else { - Gtk.main(); - } - - return 0; } + else { + Gtk.main(); + } + + return 0; +}