Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"mesonbuild.configureOnOpen": false
}
13 changes: 13 additions & 0 deletions src/Application.vala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
*/

public class Ag.Application : Gtk.Application {
public static FPrintManager fingerprint_manager;

public Application () {
Object (
application_id: "io.elementary.PolkitAgent",
Expand All @@ -24,6 +26,17 @@ public class Ag.Application : Gtk.Application {

gtk_settings.gtk_application_prefer_dark_theme = granite_settings.prefers_color_scheme == DARK;

try {
Ag.Application.fingerprint_manager = Bus.get_proxy_sync (
BusType.SYSTEM,
"net.reactivated.Fprint",
"/net/reactivated/Fprint/Manager",
DBusProxyFlags.NONE
);
} catch (Error e) {
warning ("Unable to initialize Fingerprint Manager %s", e.message);
}

var agent = new Agent ();
try {
var subject = new Polkit.UnixSession.for_process_sync (Posix.getpid (), null);
Expand Down
20 changes: 19 additions & 1 deletion src/Interfaces.vala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2015-2016 elementary LLC.
* Copyright (C) 2015-2016 Ikey Doherty <[email protected]>
* Copyright (C) 2015-2016 Ikey Doherty <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand Down Expand Up @@ -38,4 +38,22 @@ namespace Ag {
public signal void end_session (uint flags);
public signal void cancel_end_session ();
}

[DBus (name = "net.reactivated.Fprint.Device")]
public interface FPrintDevice : GLib.Object {
[DBus (name = "name")]
public abstract string name { owned get; }
[DBus (name = "scan-type")]
public abstract string scan_type { owned get; }
[DBus (name = "finger-needed")]
public abstract bool finger_needed { owned get; }
[DBus (name = "finger-present")]
public abstract bool finger_present { owned get; }
public signal void verify_status (string result, bool done);
}

[DBus (name = "net.reactivated.Fprint.Manager")]
public interface FPrintManager : GLib.Object {
public abstract ObjectPath get_default_device () throws GLib.Error;
}
}
82 changes: 75 additions & 7 deletions src/PolkitDialog.vala
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ public class Ag.PolkitDialog : Granite.MessageDialog, PantheonWayland.ExtendedBe
private Polkit.Identity? pk_identity = null;
private unowned Cancellable cancellable;

private FPrintDevice fprint_device = null;
private bool fp_activation_polling = true;

private ulong error_signal_id;
private ulong request_signal_id;
private ulong info_signal_id;
Expand All @@ -42,8 +45,11 @@ public class Ag.PolkitDialog : Granite.MessageDialog, PantheonWayland.ExtendedBe

private Gtk.Revealer feedback_revealer;
private Gtk.Label password_label;
private Gtk.Label password_feedback;
private Gtk.Label auth_feedback;
private Gtk.Entry password_entry;
private Gtk.Revealer password_auth_revealer;
private Gtk.Image fingerprint_icon;
private Gtk.Revealer fingerprint_revealer;
private Gtk.ComboBox idents_combo;

public PolkitDialog (string message, string icon_name, string _cookie,
Expand All @@ -60,24 +66,62 @@ public class Ag.PolkitDialog : Granite.MessageDialog, PantheonWayland.ExtendedBe
primary_text = _("Authentication Required");
secondary_text = message;

try {
var device_path = Application.fingerprint_manager.get_default_device ();
fprint_device = GLib.Bus.get_proxy_sync (
GLib.BusType.SYSTEM,
"net.reactivated.Fprint",
device_path
);

fprint_device.verify_status.connect ((status) => {
switch (status) {
case "verify-no-match":
case "verify-retry-scan":
case "verify-disconnected":
feedback_revealer.reveal_child = true;
auth_feedback.label = _("Fingerprint authentication failed.");
break;
}
});
} catch (Error e) {
warning ("Failed to get default finger device: %s", e.message);
}

password_entry = new Gtk.Entry () {
activates_default = true,
hexpand = true,
input_purpose = PASSWORD,
visibility = false,
primary_icon_name = "dialog-password-symbolic",
primary_icon_tooltip_text = _("Password")
};

password_feedback = new Gtk.Label (null) {
auth_feedback = new Gtk.Label (null) {
justify = RIGHT,
max_width_chars = 40,
wrap = true,
xalign = 1
};
password_feedback.add_css_class (Granite.STYLE_CLASS_ERROR);
auth_feedback.add_css_class (Granite.STYLE_CLASS_ERROR);

feedback_revealer = new Gtk.Revealer () {
child = password_feedback
child = auth_feedback
};

password_auth_revealer = new Gtk.Revealer () {
child = password_entry,
};

fingerprint_icon = new Gtk.Image.from_icon_name ("fingerprint-symbolic") {
pixel_size = 64,
margin_end = 48,
halign = Gtk.Align.CENTER
};

fingerprint_revealer = new Gtk.Revealer () {
child = fingerprint_icon,
reveal_child = fprint_device != null && fprint_device.finger_needed
};

idents_combo = new Gtk.ComboBox () {
Expand All @@ -97,7 +141,8 @@ public class Ag.PolkitDialog : Granite.MessageDialog, PantheonWayland.ExtendedBe

var credentials_box = new Gtk.Box (VERTICAL, 6);
credentials_box.append (idents_combo);
credentials_box.append (password_entry);
credentials_box.append (password_auth_revealer);
credentials_box.append (fingerprint_revealer);
credentials_box.append (feedback_revealer);

image_icon = new ThemedIcon ("dialog-password");
Expand Down Expand Up @@ -134,6 +179,20 @@ public class Ag.PolkitDialog : Granite.MessageDialog, PantheonWayland.ExtendedBe
((Gdk.Toplevel) surface).inhibit_system_shortcuts (null);
}
});

look_for_fp_activation ();
}

private void look_for_fp_activation () {
fp_activation_polling = true;
Idle.add (() => {
if (fprint_device.finger_needed) {
fp_activation_polling = false;
fingerprint_revealer.reveal_child = true;
}

return fp_activation_polling;
});
}

private void update_idents () {
Expand Down Expand Up @@ -259,6 +318,7 @@ public class Ag.PolkitDialog : Granite.MessageDialog, PantheonWayland.ExtendedBe
private void on_pk_session_completed (bool authorized) {
if (!authorized || cancellable.is_cancelled ()) {
if (!canceling) {
password_auth_revealer.reveal_child = false;
on_pk_show_error (_("Authentication failed. Please try again."));
}

Expand All @@ -275,8 +335,15 @@ public class Ag.PolkitDialog : Granite.MessageDialog, PantheonWayland.ExtendedBe

private void on_pk_request (string request, bool echo_on) {
password_entry.visibility = echo_on;
if (!request.has_prefix ("Password:")) {
print ("Request: %s\n", request);
if (request.has_prefix ("Password:")) {
password_auth_revealer.reveal_child = true;
fp_activation_polling = false;
fingerprint_revealer.reveal_child = false;
} else {
password_label.label = request;
password_auth_revealer.reveal_child = false;
look_for_fp_activation ();
}
}

Expand Down Expand Up @@ -304,8 +371,9 @@ public class Ag.PolkitDialog : Granite.MessageDialog, PantheonWayland.ExtendedBe
if (repeat_count == 4) {
feedback_revealer.reveal_child = true;
password_entry.secondary_icon_name = "dialog-error-symbolic";
password_feedback.label = text;
auth_feedback.label = text;
sensitive = true;
look_for_fp_activation ();
disconnect (iterate);
return;
}
Expand Down