From c3ab03f8721ea96df6ac91c0393ed13ba750ab7e Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 17 Jul 2017 16:48:03 -0400 Subject: [PATCH 2/2] gdmUtil: enable support for GDM's ChoiceList PAM extension This commit hooks up support for GDM's ChoiceList PAM extension. --- js/gdm/authPrompt.js | 74 ++++++++++++++++++++++++++++++++++++++++++- js/gdm/loginDialog.js | 5 +++ js/gdm/util.js | 28 ++++++++++++++++ js/ui/unlockDialog.js | 9 +++++- 4 files changed, 114 insertions(+), 2 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js index cf77b3f26..71069e93b 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -4,6 +4,7 @@ const { Clutter, GLib, Pango, Shell, St } = imports.gi; const Signals = imports.signals; const Animation = imports.ui.animation; +const AuthList = imports.gdm.authList; const Batch = imports.gdm.batch; const GdmUtil = imports.gdm.util; const Meta = imports.gi.Meta; @@ -54,6 +55,7 @@ var AuthPrompt = class { this._userVerifier.connect('ask-question', this._onAskQuestion.bind(this)); this._userVerifier.connect('show-message', this._onShowMessage.bind(this)); + this._userVerifier.connect('show-choice-list', this._onShowChoiceList.bind(this)); this._userVerifier.connect('verification-failed', this._onVerificationFailed.bind(this)); this._userVerifier.connect('verification-complete', this._onVerificationComplete.bind(this)); this._userVerifier.connect('reset', this._onReset.bind(this)); @@ -116,6 +118,28 @@ var AuthPrompt = class { this.actor.add(this._timedLoginIndicator); + this._authList = new AuthList.AuthList(); + this._authList.connect('activate', (list, key) => { + this._authList.actor.reactive = false; + Tweener.addTween(this._authList.actor, + { opacity: 0, + time: MESSAGE_FADE_OUT_ANIMATION_TIME, + transition: 'easeOutQuad', + onComplete: () => { + this._authList.clear(); + this._authList.actor.hide(); + this._userVerifier.selectChoice(this._queryingService, key); + + } + }); + }); + this._authList.actor.hide(); + this.actor.add(this._authList.actor, + { expand: true, + x_fill: true, + y_fill: false, + x_align: St.Align.START }); + this._message = new St.Label({ opacity: 0, styleClass: 'login-dialog-message' }); this._message.clutter_text.line_wrap = true; @@ -258,6 +282,21 @@ var AuthPrompt = class { this.emit('prompted'); } + _onShowChoiceList(userVerifier, serviceName, promptMessage, choiceList) { + if (this._queryingService) + this.clear(); + + this._queryingService = serviceName; + + if (this._preemptiveAnswer) + this._preemptiveAnswer = null; + + this.nextButton.label = _("Next"); + this.setChoiceList(promptMessage, choiceList); + this.updateSensitivity(true); + this.emit('prompted'); + } + _onOVirtUserAuthenticated() { if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED) this.reset(); @@ -386,6 +425,8 @@ var AuthPrompt = class { clear() { this._entry.text = ''; this.stopSpinning(); + this._authList.clear(); + this._authList.actor.hide(); } setPasswordChar(passwordChar) { @@ -401,12 +442,42 @@ var AuthPrompt = class { this._label.set_text(question); + this._authList.actor.hide(); this._label.show(); this._entry.show(); this._entry.grab_key_focus(); } + _fadeInChoiceList() { + this._authList.actor.opacity = 0; + this._authList.actor.show(); + this._authList.actor.reactive = false; + Tweener.addTween(this._authList.actor, + { opacity: 255, + time: MESSAGE_FADE_OUT_ANIMATION_TIME, + transition: 'easeOutQuad', + onComplete: () => { + this._authList.actor.reactive = true; + } + }); + } + + setChoiceList(promptMessage, choiceList) { + this._authList.clear(); + this._authList.label.text = promptMessage; + for (let key in choiceList) { + let text = choiceList[key]; + this._authList.addItem(key, text); + } + + this._label.hide(); + this._entry.hide(); + if (this._message.text == "") + this._message.hide(); + this._fadeInChoiceList(); + } + getAnswer() { let text; @@ -442,6 +513,7 @@ var AuthPrompt = class { else this._message.remove_style_class_name('login-dialog-message-hint'); + this._message.show(); if (message) { Tweener.removeTweens(this._message); this._message.text = message; @@ -457,7 +529,7 @@ var AuthPrompt = class { } updateSensitivity(sensitive) { - this._updateNextButtonSensitivity(sensitive && (this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING)); + this._updateNextButtonSensitivity(sensitive && !this._authList.actor.visible && (this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING)); this._entry.reactive = sensitive; this._entry.clutter_text.editable = sensitive; } diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js index 9aaa013d8..942f5a0e5 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -406,6 +406,11 @@ var LoginDialog = GObject.registerClass({ this._userManager = AccountsService.UserManager.get_default() this._gdmClient = new Gdm.Client(); + try { + this._gdmClient.set_enabled_extensions([Gdm.UserVerifierChoiceList.interface_info().name]); + } catch(e) { + } + this._settings = new Gio.Settings({ schema_id: GdmUtil.LOGIN_SCREEN_SCHEMA }); this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY, diff --git a/js/gdm/util.js b/js/gdm/util.js index 6e940d2ab..9e249139d 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -192,6 +192,10 @@ var ShellUserVerifier = class { if (this._userVerifier) { this._userVerifier.run_dispose(); this._userVerifier = null; + if (this._userVerifierChoiceList) { + this._userVerifierChoiceList.run_dispose(); + this._userVerifierChoiceList = null; + } } } @@ -219,6 +223,10 @@ var ShellUserVerifier = class { this._oVirtCredentialsManager = null; } + selectChoice(serviceName, key) { + this._userVerifierChoiceList.call_select_choice(serviceName, key, this._cancellable, null); + } + answerQuery(serviceName, answer) { if (!this.hasPendingMessages) { this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null); @@ -362,6 +370,11 @@ var ShellUserVerifier = class { return; } + if (client.get_user_verifier_choice_list) + this._userVerifierChoiceList = client.get_user_verifier_choice_list(); + else + this._userVerifierChoiceList = null; + this.reauthenticating = true; this._connectSignals(); this._beginVerification(); @@ -379,6 +392,11 @@ var ShellUserVerifier = class { return; } + if (client.get_user_verifier_choice_list) + this._userVerifierChoiceList = client.get_user_verifier_choice_list(); + else + this._userVerifierChoiceList = null; + this._connectSignals(); this._beginVerification(); this._hold.release(); @@ -392,6 +410,9 @@ var ShellUserVerifier = class { this._userVerifier.connect('conversation-stopped', this._onConversationStopped.bind(this)); this._userVerifier.connect('reset', this._onReset.bind(this)); this._userVerifier.connect('verification-complete', this._onVerificationComplete.bind(this)); + + if (this._userVerifierChoiceList) + this._userVerifierChoiceList.connect('choice-query', this._onChoiceListQuery.bind(this)); } _getForegroundService() { @@ -468,6 +489,13 @@ var ShellUserVerifier = class { this._startService(FINGERPRINT_SERVICE_NAME); } + _onChoiceListQuery(client, serviceName, promptMessage, list) { + if (!this.serviceIsForeground(serviceName)) + return; + + this.emit('show-choice-list', serviceName, promptMessage, list.deep_unpack()); + } + _onInfo(client, serviceName, info) { if (this.serviceIsForeground(serviceName)) { this._queueMessage(info, MessageType.INFO); diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js index 5c9d46021..4b0470f4b 100644 --- a/js/ui/unlockDialog.js +++ b/js/ui/unlockDialog.js @@ -33,7 +33,14 @@ var UnlockDialog = class { y_expand: true }); this.actor.add_child(this._promptBox); - this._authPrompt = new AuthPrompt.AuthPrompt(new Gdm.Client(), AuthPrompt.AuthPromptMode.UNLOCK_ONLY); + this._gdmClient = new Gdm.Client(); + + try { + this._gdmClient.set_enabled_extensions([Gdm.UserVerifierChoiceList.interface_info().name]); + } catch(e) { + } + + this._authPrompt = new AuthPrompt.AuthPrompt(this._gdmClient, AuthPrompt.AuthPromptMode.UNLOCK_ONLY); this._authPrompt.connect('failed', this._fail.bind(this)); this._authPrompt.connect('cancelled', this._fail.bind(this)); this._authPrompt.connect('reset', this._onReset.bind(this)); -- 2.21.0