Compare commits
	
		
			2 Commits
		
	
	
		
			wip/exalm/
			...
			wip/rstrod
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					9f925cf78d | ||
| 
						 | 
					1fcb59104d | 
							
								
								
									
										190
									
								
								js/gdm/authList.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								js/gdm/authList.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,190 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2017 Red Hat, Inc
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 2, or (at your option)
 | 
			
		||||
 * any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
 | 
			
		||||
const _SCROLL_ANIMATION_TIME = 0.5;
 | 
			
		||||
 | 
			
		||||
const AuthListItem = new Lang.Class({
 | 
			
		||||
    Name: 'AuthListItem',
 | 
			
		||||
 | 
			
		||||
    _init: function(key, text) {
 | 
			
		||||
        this.key = key;
 | 
			
		||||
        let label = new St.Label({ style_class: 'auth-list-item-label',
 | 
			
		||||
                                   y_align: Clutter.ActorAlign.CENTER });
 | 
			
		||||
        label.text = text;
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
 | 
			
		||||
                                     button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                     can_focus: true,
 | 
			
		||||
                                     child: label,
 | 
			
		||||
                                     reactive: true,
 | 
			
		||||
                                     x_align: St.Align.START,
 | 
			
		||||
                                     x_fill: true });
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('key-focus-in', () => {
 | 
			
		||||
            this._setSelected(true);
 | 
			
		||||
        });
 | 
			
		||||
        this.actor.connect('key-focus-out', () => {
 | 
			
		||||
            this._setSelected(false);
 | 
			
		||||
        });
 | 
			
		||||
        this.actor.connect('notify::hover', () => {
 | 
			
		||||
            this._setSelected(this.actor.hover);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('clicked', Lang.bind(this, this._onClicked));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onClicked: function() {
 | 
			
		||||
        this.emit('activate');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setSelected: function(selected) {
 | 
			
		||||
        if (selected) {
 | 
			
		||||
            this.actor.add_style_pseudo_class('selected');
 | 
			
		||||
            this.actor.grab_key_focus();
 | 
			
		||||
        } else {
 | 
			
		||||
            this.actor.remove_style_pseudo_class('selected');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(AuthListItem.prototype);
 | 
			
		||||
 | 
			
		||||
const AuthList = new Lang.Class({
 | 
			
		||||
    Name: 'AuthList',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
 | 
			
		||||
        this.actor.set_policy(Gtk.PolicyType.NEVER,
 | 
			
		||||
                              Gtk.PolicyType.AUTOMATIC);
 | 
			
		||||
 | 
			
		||||
        this._box = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                       style_class: 'login-dialog-user-list',
 | 
			
		||||
                                       pseudo_class: 'expanded' });
 | 
			
		||||
 | 
			
		||||
        this.actor.add_actor(this._box);
 | 
			
		||||
        this._items = {};
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('key-focus-in', Lang.bind(this, this._moveFocusToItems));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _moveFocusToItems: function() {
 | 
			
		||||
        let hasItems = Object.keys(this._items).length > 0;
 | 
			
		||||
 | 
			
		||||
        if (!hasItems)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (global.stage.get_key_focus() != this.actor)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let focusSet = this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
 | 
			
		||||
        if (!focusSet) {
 | 
			
		||||
            Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
 | 
			
		||||
                this._moveFocusToItems();
 | 
			
		||||
                return false;
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onItemActivated: function(activatedItem) {
 | 
			
		||||
        this.emit('activate', activatedItem.key);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    scrollToItem: function(item) {
 | 
			
		||||
        let box = item.actor.get_allocation_box();
 | 
			
		||||
 | 
			
		||||
        let adjustment = this.actor.get_vscroll_bar().get_adjustment();
 | 
			
		||||
 | 
			
		||||
        let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
 | 
			
		||||
        Tweener.removeTweens(adjustment);
 | 
			
		||||
        Tweener.addTween (adjustment,
 | 
			
		||||
                          { value: value,
 | 
			
		||||
                            time: _SCROLL_ANIMATION_TIME,
 | 
			
		||||
                            transition: 'easeOutQuad' });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    jumpToItem: function(item) {
 | 
			
		||||
        let box = item.actor.get_allocation_box();
 | 
			
		||||
 | 
			
		||||
        let adjustment = this.actor.get_vscroll_bar().get_adjustment();
 | 
			
		||||
 | 
			
		||||
        let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
 | 
			
		||||
 | 
			
		||||
        adjustment.set_value(value);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getItem: function(key) {
 | 
			
		||||
        let item = this._items[key];
 | 
			
		||||
 | 
			
		||||
        if (!item)
 | 
			
		||||
            return null;
 | 
			
		||||
 | 
			
		||||
        return item;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addItem: function(key, text) {
 | 
			
		||||
        this.removeItem(key);
 | 
			
		||||
 | 
			
		||||
        let item = new AuthListItem(key, text);
 | 
			
		||||
        this._box.add(item.actor, { x_fill: true });
 | 
			
		||||
 | 
			
		||||
        this._items[key] = item;
 | 
			
		||||
 | 
			
		||||
        item.connect('activate',
 | 
			
		||||
                     Lang.bind(this, this._onItemActivated));
 | 
			
		||||
 | 
			
		||||
        // Try to keep the focused item front-and-center
 | 
			
		||||
        item.actor.connect('key-focus-in',
 | 
			
		||||
                           Lang.bind(this,
 | 
			
		||||
                                     function() {
 | 
			
		||||
                                         this.scrollToItem(item);
 | 
			
		||||
                                     }));
 | 
			
		||||
 | 
			
		||||
        this._moveFocusToItems();
 | 
			
		||||
 | 
			
		||||
        this.emit('item-added', item);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    removeItem: function(key) {
 | 
			
		||||
        let item = this._items[key];
 | 
			
		||||
 | 
			
		||||
        if (!item)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        item.actor.destroy();
 | 
			
		||||
        delete this._items[key];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    numItems: function() {
 | 
			
		||||
        return Object.keys(this._items).length;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    clear: function() {
 | 
			
		||||
        this._box.destroy_all_children();
 | 
			
		||||
        this._items = {};
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(AuthList.prototype);
 | 
			
		||||
@@ -8,6 +8,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 Params = imports.misc.params;
 | 
			
		||||
@@ -57,6 +58,7 @@ var AuthPrompt = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._userVerifier.connect('ask-question', Lang.bind(this, this._onAskQuestion));
 | 
			
		||||
        this._userVerifier.connect('show-message', Lang.bind(this, this._onShowMessage));
 | 
			
		||||
        this._userVerifier.connect('show-choice-list', Lang.bind(this, this._onShowChoiceList));
 | 
			
		||||
        this._userVerifier.connect('verification-failed', Lang.bind(this, this._onVerificationFailed));
 | 
			
		||||
        this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete));
 | 
			
		||||
        this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
 | 
			
		||||
@@ -117,6 +119,17 @@ var AuthPrompt = new Lang.Class({
 | 
			
		||||
        this._message.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
 | 
			
		||||
        this.actor.add(this._message, { x_fill: false, x_align: St.Align.START, y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        this._authList = new AuthList.AuthList();
 | 
			
		||||
        this._authList.connect('activate', (list, key) => {
 | 
			
		||||
            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._buttonBox = new St.BoxLayout({ style_class: 'login-dialog-button-box',
 | 
			
		||||
                                             vertical: false });
 | 
			
		||||
        this.actor.add(this._buttonBox,
 | 
			
		||||
@@ -222,6 +235,21 @@ var AuthPrompt = new Lang.Class({
 | 
			
		||||
        this.emit('prompted');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onShowChoiceList: function(userVerifier, serviceName, choiceList) {
 | 
			
		||||
        if (this._queryingService)
 | 
			
		||||
            this.clear();
 | 
			
		||||
 | 
			
		||||
        this._queryingService = serviceName;
 | 
			
		||||
 | 
			
		||||
        if (this._preemptiveAnswer)
 | 
			
		||||
            this._preemptiveAnswer = null;
 | 
			
		||||
 | 
			
		||||
        this.nextButton.label = _("Next");
 | 
			
		||||
        this.setChoiceList(choiceList);
 | 
			
		||||
        this.updateSensitivity(true);
 | 
			
		||||
        this.emit('prompted');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onOVirtUserAuthenticated: function() {
 | 
			
		||||
        if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
 | 
			
		||||
            this.reset();
 | 
			
		||||
@@ -350,6 +378,8 @@ var AuthPrompt = new Lang.Class({
 | 
			
		||||
    clear: function() {
 | 
			
		||||
        this._entry.text = '';
 | 
			
		||||
        this.stopSpinning();
 | 
			
		||||
        this._authList.clear();
 | 
			
		||||
        this._authList.actor.hide();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setPasswordChar: function(passwordChar) {
 | 
			
		||||
@@ -360,12 +390,25 @@ var AuthPrompt = new Lang.Class({
 | 
			
		||||
    setQuestion: function(question) {
 | 
			
		||||
        this._label.set_text(question);
 | 
			
		||||
 | 
			
		||||
        this._authList.actor.hide();
 | 
			
		||||
        this._label.show();
 | 
			
		||||
        this._entry.show();
 | 
			
		||||
 | 
			
		||||
        this._entry.grab_key_focus();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setChoiceList: function(choiceList) {
 | 
			
		||||
        this._label.hide();
 | 
			
		||||
        this._entry.hide();
 | 
			
		||||
 | 
			
		||||
        this._authList.clear();
 | 
			
		||||
        for (let key in choiceList) {
 | 
			
		||||
            let text = choiceList[key];
 | 
			
		||||
            this._authList.addItem(key, text);
 | 
			
		||||
        }
 | 
			
		||||
        this._authList.actor.show();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getAnswer: function() {
 | 
			
		||||
        let text;
 | 
			
		||||
 | 
			
		||||
@@ -416,7 +459,7 @@ var AuthPrompt = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateSensitivity: function(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;
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -199,6 +199,8 @@ var ShellUserVerifier = new Lang.Class({
 | 
			
		||||
        if (this._userVerifier) {
 | 
			
		||||
            this._userVerifier.run_dispose();
 | 
			
		||||
            this._userVerifier = null;
 | 
			
		||||
            this._userVerifierChoiceList.run_dispose();
 | 
			
		||||
            this._userVerifierChoiceList = null;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -226,6 +228,10 @@ var ShellUserVerifier = new Lang.Class({
 | 
			
		||||
        this._oVirtCredentialsManager = null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    selectChoice: function(serviceName, key) {
 | 
			
		||||
        this._userVerifierChoiceList.call_select_choice(serviceName, key, this._cancellable, null);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    answerQuery: function(serviceName, answer) {
 | 
			
		||||
        if (!this.hasPendingMessages) {
 | 
			
		||||
            this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null);
 | 
			
		||||
@@ -365,6 +371,8 @@ var ShellUserVerifier = new Lang.Class({
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._userVerifierChoiceList = client.get_user_verifier_choice_list();
 | 
			
		||||
 | 
			
		||||
        this.reauthenticating = true;
 | 
			
		||||
        this._connectSignals();
 | 
			
		||||
        this._beginVerification();
 | 
			
		||||
@@ -382,6 +390,8 @@ var ShellUserVerifier = new Lang.Class({
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._userVerifierChoiceList = client.get_user_verifier_choice_list();
 | 
			
		||||
 | 
			
		||||
        this._connectSignals();
 | 
			
		||||
        this._beginVerification();
 | 
			
		||||
        this._hold.release();
 | 
			
		||||
@@ -395,6 +405,9 @@ var ShellUserVerifier = new Lang.Class({
 | 
			
		||||
        this._userVerifier.connect('conversation-stopped', Lang.bind(this, this._onConversationStopped));
 | 
			
		||||
        this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
 | 
			
		||||
        this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete));
 | 
			
		||||
 | 
			
		||||
        if (this._userVerifierChoiceList)
 | 
			
		||||
            this._userVerifierChoiceList.connect('choice-query', Lang.bind(this, this._onChoiceListQuery));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getForegroundService: function() {
 | 
			
		||||
@@ -464,6 +477,13 @@ var ShellUserVerifier = new Lang.Class({
 | 
			
		||||
            this._startService(FINGERPRINT_SERVICE_NAME);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onChoiceListQuery: function(client, serviceName, list) {
 | 
			
		||||
        if (!this.serviceIsForeground(serviceName))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.emit('show-choice-list', serviceName, list.deep_unpack());
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onInfo: function(client, serviceName, info) {
 | 
			
		||||
        if (this.serviceIsForeground(serviceName)) {
 | 
			
		||||
            this._queueMessage(info, MessageType.INFO);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<gresources>
 | 
			
		||||
  <gresource prefix="/org/gnome/shell">
 | 
			
		||||
    <file>gdm/authList.js</file>
 | 
			
		||||
    <file>gdm/authPrompt.js</file>
 | 
			
		||||
    <file>gdm/batch.js</file>
 | 
			
		||||
    <file>gdm/fingerprint.js</file>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user