From e5214fb2992c1ef5d8bde63295d9f54dbb3daa24 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 17 Jul 2017 16:48:03 -0400 Subject: [PATCH] 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 e44281117..27a55246a 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -9,6 +9,7 @@ const Signals = imports.signals; const St = imports.gi.St; 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; @@ -61,6 +62,7 @@ var AuthPrompt = new Lang.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)); @@ -123,6 +125,28 @@ var AuthPrompt = new Lang.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; @@ -266,6 +290,21 @@ var AuthPrompt = new Lang.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(); @@ -394,6 +433,8 @@ var AuthPrompt = new Lang.Class({ clear() { this._entry.text = ''; this.stopSpinning(); + this._authList.clear(); + this._authList.actor.hide(); }, setPasswordChar(passwordChar) { @@ -409,12 +450,42 @@ var AuthPrompt = new Lang.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; @@ -450,6 +521,7 @@ var AuthPrompt = new Lang.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; @@ -465,7 +537,7 @@ var AuthPrompt = new Lang.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 65d9edf1a..912c0e0ca 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -418,6 +418,11 @@ var LoginDialog = new Lang.Class({ 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 f5f9d5e5d..04a0cb9bf 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -200,6 +200,10 @@ var ShellUserVerifier = new Lang.Class({ if (this._userVerifier) { this._userVerifier.run_dispose(); this._userVerifier = null; + if (this._userVerifierChoiceList) { + this._userVerifierChoiceList.run_dispose(); + this._userVerifierChoiceList = null; + } } }, @@ -227,6 +231,10 @@ var ShellUserVerifier = new Lang.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); @@ -367,6 +375,11 @@ var ShellUserVerifier = new Lang.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(); @@ -384,6 +397,11 @@ var ShellUserVerifier = new Lang.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(); @@ -397,6 +415,9 @@ var ShellUserVerifier = new Lang.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() { @@ -473,6 +494,13 @@ var ShellUserVerifier = new Lang.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 1adaf417e..b5272be20 100644 --- a/js/ui/unlockDialog.js +++ b/js/ui/unlockDialog.js @@ -51,7 +51,14 @@ var UnlockDialog = new Lang.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.17.1