Add UnlockDialog for unlocking the screen shield
When the screenshield is deactivated, instead of going back to the session immediately, prompt the user for authentication. This essentially reinstates what used to be provided by gnome-screensaver.
This commit is contained in:
parent
9dfd805be2
commit
17044adf96
@ -92,6 +92,7 @@ nobase_dist_js_DATA = \
|
||||
ui/status/bluetooth.js \
|
||||
ui/telepathyClient.js \
|
||||
ui/tweener.js \
|
||||
ui/unlockDialog.js \
|
||||
ui/userMenu.js \
|
||||
ui/viewSelector.js \
|
||||
ui/wanda.js \
|
||||
|
@ -39,8 +39,8 @@ const Main = imports.ui.main;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
const _PASSWORD_SERVICE_NAME = 'gdm-password';
|
||||
const _FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
|
||||
const PASSWORD_SERVICE_NAME = 'gdm-password';
|
||||
const FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
|
||||
const _FADE_ANIMATION_TIME = 0.16;
|
||||
const _RESIZE_ANIMATION_TIME = 0.25;
|
||||
const _SCROLL_ANIMATION_TIME = 2.0;
|
||||
@ -749,7 +749,7 @@ const LoginDialog = new Lang.Class({
|
||||
this._userManager = AccountsService.UserManager.get_default()
|
||||
this._greeterClient = GdmGreeter.Server.new_for_greeter_sync(null);
|
||||
|
||||
this._greeterClient.call_start_conversation_sync(_PASSWORD_SERVICE_NAME, null);
|
||||
this._greeterClient.call_start_conversation_sync(PASSWORD_SERVICE_NAME, null);
|
||||
|
||||
this._greeterClient.connect('reset',
|
||||
Lang.bind(this, this._onReset));
|
||||
@ -895,7 +895,7 @@ const LoginDialog = new Lang.Class({
|
||||
this._haveFingerprintReader = true;
|
||||
|
||||
if (this._haveFingerprintReader)
|
||||
this._greeterClient.call_start_conversation(_FINGERPRINT_SERVICE_NAME);
|
||||
this._greeterClient.call_start_conversation_sync(FINGERPRINT_SERVICE_NAME, null);
|
||||
}));
|
||||
},
|
||||
|
||||
@ -914,7 +914,7 @@ const LoginDialog = new Lang.Class({
|
||||
},
|
||||
|
||||
_onReset: function(client, serviceName) {
|
||||
this._greeterClient.call_start_conversation_sync(_PASSWORD_SERVICE_NAME, null);
|
||||
this._greeterClient.call_start_conversation_sync(PASSWORD_SERVICE_NAME, null);
|
||||
this._startFingerprintConversationIfNeeded();
|
||||
|
||||
let tasks = [this._hidePrompt,
|
||||
@ -950,7 +950,7 @@ const LoginDialog = new Lang.Class({
|
||||
// We don't display fingerprint messages, because they
|
||||
// have words like UPEK in them. Instead we use the messages
|
||||
// as a cue to display our own message.
|
||||
if (serviceName == _FINGERPRINT_SERVICE_NAME &&
|
||||
if (serviceName == FINGERPRINT_SERVICE_NAME &&
|
||||
this._haveFingerprintReader &&
|
||||
(!this._promptFingerprintMessage.visible ||
|
||||
this._promptFingerprintMessage.opacity != 255)) {
|
||||
@ -959,7 +959,7 @@ const LoginDialog = new Lang.Class({
|
||||
return;
|
||||
}
|
||||
|
||||
if (serviceName != _PASSWORD_SERVICE_NAME)
|
||||
if (serviceName != PASSWORD_SERVICE_NAME)
|
||||
return;
|
||||
Main.notifyError(info);
|
||||
},
|
||||
@ -967,7 +967,7 @@ const LoginDialog = new Lang.Class({
|
||||
_onProblem: function(client, serviceName, problem) {
|
||||
// we don't want to show auth failed messages to
|
||||
// users who haven't enrolled their fingerprint.
|
||||
if (serviceName != _PASSWORD_SERVICE_NAME)
|
||||
if (serviceName != PASSWORD_SERVICE_NAME)
|
||||
return;
|
||||
Main.notifyError(problem);
|
||||
},
|
||||
@ -1088,7 +1088,7 @@ const LoginDialog = new Lang.Class({
|
||||
},
|
||||
_onInfoQuery: function(client, serviceName, question) {
|
||||
// We only expect questions to come from the main auth service
|
||||
if (serviceName != _PASSWORD_SERVICE_NAME)
|
||||
if (serviceName != PASSWORD_SERVICE_NAME)
|
||||
return;
|
||||
|
||||
this._promptEntry.set_text('');
|
||||
@ -1098,7 +1098,7 @@ const LoginDialog = new Lang.Class({
|
||||
|
||||
_onSecretInfoQuery: function(client, serviceName, secretQuestion) {
|
||||
// We only expect secret requests to come from the main auth service
|
||||
if (serviceName != _PASSWORD_SERVICE_NAME)
|
||||
if (serviceName != PASSWORD_SERVICE_NAME)
|
||||
return;
|
||||
|
||||
this._promptEntry.set_text('');
|
||||
@ -1236,9 +1236,9 @@ const LoginDialog = new Lang.Class({
|
||||
// if the password service fails, then cancel everything.
|
||||
// But if, e.g., fingerprint fails, still give
|
||||
// password authentication a chance to succeed
|
||||
if (serviceName == _PASSWORD_SERVICE_NAME) {
|
||||
if (serviceName == PASSWORD_SERVICE_NAME) {
|
||||
this._greeterClient.call_cancel_sync(null);
|
||||
} else if (serviceName == _FINGERPRINT_SERVICE_NAME) {
|
||||
} else if (serviceName == FINGERPRINT_SERVICE_NAME) {
|
||||
_fadeOutActor(this._promptFingerprintMessage);
|
||||
}
|
||||
},
|
||||
@ -1261,7 +1261,7 @@ const LoginDialog = new Lang.Class({
|
||||
this._fadeOutLogo]),
|
||||
|
||||
function() {
|
||||
this._greeterClient.call_begin_verification_sync(_PASSWORD_SERVICE_NAME, null);
|
||||
this._greeterClient.call_begin_verification_sync(PASSWORD_SERVICE_NAME, null);
|
||||
}];
|
||||
|
||||
let batch = new Batch.ConsecutiveBatch(this, tasks);
|
||||
@ -1320,7 +1320,7 @@ const LoginDialog = new Lang.Class({
|
||||
|
||||
function() {
|
||||
let userName = activatedItem.user.get_user_name();
|
||||
this._greeterClient.call_begin_verification_for_user_sync(_PASSWORD_SERVICE_NAME,
|
||||
this._greeterClient.call_begin_verification_for_user_sync(PASSWORD_SERVICE_NAME,
|
||||
userName, null);
|
||||
|
||||
if (this._haveFingerprintReader)
|
||||
|
@ -494,7 +494,7 @@ function loadTheme() {
|
||||
|
||||
let theme = new St.Theme ({ application_stylesheet: cssStylesheet });
|
||||
|
||||
if (global.session_type == Shell.SessionType.GDM)
|
||||
// FIXME: merge back into main stylesheet
|
||||
theme.load_stylesheet(_gdmCssStylesheet);
|
||||
|
||||
if (previousTheme) {
|
||||
|
@ -8,7 +8,7 @@ const St = imports.gi.St;
|
||||
|
||||
const GnomeSession = imports.misc.gnomeSession;
|
||||
const Lightbox = imports.ui.lightbox;
|
||||
const LoginDialog = imports.gdm.loginDialog;
|
||||
const UnlockDialog = imports.ui.unlockDialog;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
|
||||
@ -43,8 +43,7 @@ const ScreenShield = new Lang.Class({
|
||||
let constraint = new Clutter.BindConstraint({ source: global.stage,
|
||||
coordinate: Clutter.BindCoordinate.POSITION | Clutter.BindCoordinate.SIZE });
|
||||
this._group.add_constraint(constraint);
|
||||
this._group.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
|
||||
this._group.connect('button-press-event', Lang.bind(this, this._onButtonPressEvent));
|
||||
|
||||
this._lightbox = new Lightbox.Lightbox(this._group,
|
||||
{ inhibitEvents: true, fadeInTime: 10, fadeFactor: 1 });
|
||||
this._background = Meta.BackgroundActor.new_for_screen(global.screen);
|
||||
@ -66,6 +65,8 @@ const ScreenShield = new Lang.Class({
|
||||
if (lightboxWasShown && this._settings.get_boolean(LOCK_ENABLED_KEY)) {
|
||||
this._background.show();
|
||||
this._background.raise_top();
|
||||
|
||||
this._showUnlockDialog();
|
||||
} else {
|
||||
this._popModal();
|
||||
}
|
||||
@ -79,13 +80,30 @@ const ScreenShield = new Lang.Class({
|
||||
this._background.hide();
|
||||
},
|
||||
|
||||
_onKeyPressEvent: function(object, keyPressEvent) {
|
||||
log("in _onKeyPressEvent - lock is enabled: " + this._settings.get_boolean(LOCK_ENABLED_KEY));
|
||||
this._popModal();
|
||||
_showUnlockDialog: function() {
|
||||
if (this._dialog)
|
||||
return;
|
||||
|
||||
this._dialog = new UnlockDialog.UnlockDialog();
|
||||
this._dialog.connect('failed', Lang.bind(this, this._onUnlockFailed));
|
||||
this._dialog.connect('unlocked', Lang.bind(this, this._onUnlockSucceded));
|
||||
|
||||
this._dialog.open(global.get_current_time());
|
||||
},
|
||||
|
||||
_onButtonPressEvent: function(object, buttonPressEvent) {
|
||||
log("in _onButtonPressEvent - lock is enabled: " + this._settings.get_boolean(LOCK_ENABLED_KEY));
|
||||
_onUnlockFailed: function() {
|
||||
// FIXME: for now, on failure we just destroy the dialog and create a new
|
||||
// one (this is what gnome-screensaver does)
|
||||
// in the future, we may want to go back to the lock screen instead
|
||||
|
||||
this._dialog.destroy();
|
||||
this._dialog = null;
|
||||
|
||||
this._showUnlockDialog();
|
||||
},
|
||||
|
||||
_onUnlockSucceded: function() {
|
||||
this._dialog.destroy();
|
||||
this._popModal();
|
||||
},
|
||||
});
|
||||
|
363
js/ui/unlockDialog.js
Normal file
363
js/ui/unlockDialog.js
Normal file
@ -0,0 +1,363 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const AccountsService = imports.gi.AccountsService;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GdmGreeter = imports.gi.GdmGreeter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Signals = imports.signals;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
|
||||
const Fprint = imports.gdm.fingerprint;
|
||||
const GdmLoginDialog = imports.gdm.loginDialog;
|
||||
|
||||
function _fadeInActor(actor) {
|
||||
if (actor.opacity == 255 && actor.visible)
|
||||
return;
|
||||
|
||||
actor.show();
|
||||
let [minHeight, naturalHeight] = actor.get_preferred_height(-1);
|
||||
|
||||
actor.opacity = 0;
|
||||
actor.set_height(0);
|
||||
Tweener.addTween(actor,
|
||||
{ opacity: 255,
|
||||
height: naturalHeight,
|
||||
time: _FADE_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: function() {
|
||||
this.set_height(-1);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function _fadeOutActor(actor) {
|
||||
if (!actor.visible || actor.opacity == 0) {
|
||||
actor.opacity = 0;
|
||||
actor.hide();
|
||||
}
|
||||
|
||||
Tweener.addTween(actor,
|
||||
{ opacity: 0,
|
||||
height: 0,
|
||||
time: _FADE_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: function() {
|
||||
this.hide();
|
||||
this.set_height(-1);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// A widget showing the user avatar and name
|
||||
const UserWidget = new Lang.Class({
|
||||
Name: 'UserWidget',
|
||||
|
||||
_init: function(user) {
|
||||
this._user = user;
|
||||
|
||||
this.actor = new St.BoxLayout({ style_class: 'status-chooser',
|
||||
vertical: false,
|
||||
reactive: false
|
||||
});
|
||||
|
||||
this._iconBin = new St.Bin({ style_class: 'status-chooser-user-icon' });
|
||||
this.actor.add(this._iconBin,
|
||||
{ x_fill: true,
|
||||
y_fill: true });
|
||||
|
||||
this._label = new St.Label({ style_class: 'login-dialog-prompt-label',
|
||||
// FIXME:
|
||||
style: 'text-align: right' });
|
||||
this.actor.add(this._label,
|
||||
{ expand: true,
|
||||
x_fill: true,
|
||||
y_fill: true
|
||||
});
|
||||
|
||||
this._userLoadedId = this._user.connect('notify::is-loaded',
|
||||
Lang.bind(this,
|
||||
this._updateUser));
|
||||
this._userChangedId = this._user.connect('changed',
|
||||
Lang.bind(this,
|
||||
this._updateUser));
|
||||
this.actor.connect('notify::mapped', Lang.bind(this, function() {
|
||||
if (this.actor.mapped)
|
||||
this._updateUser();
|
||||
}));
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
// clean up signal handlers
|
||||
if (this._userLoadedId != 0) {
|
||||
this._user.disconnect(this._userLoadedId);
|
||||
this._userLoadedId = 0;
|
||||
}
|
||||
|
||||
if (this._userChangedId != 0) {
|
||||
this._user.disconnect(this._userChangedId);
|
||||
this._userChangedId = 0;
|
||||
}
|
||||
|
||||
this.actor.destroy();
|
||||
},
|
||||
|
||||
_updateUser: function() {
|
||||
let iconFile = null;
|
||||
if (this._user.is_loaded) {
|
||||
this._label.text = this._user.get_real_name();
|
||||
iconFile = this._user.get_icon_file();
|
||||
if (!GLib.file_test(iconFile, GLib.FileTest.EXISTS))
|
||||
iconFile = null;
|
||||
} else {
|
||||
this._label.text = "";
|
||||
}
|
||||
|
||||
if (iconFile)
|
||||
this._setIconFromFile(iconFile);
|
||||
else
|
||||
this._setIconFromName('avatar-default');
|
||||
},
|
||||
|
||||
// XXX: a GFileIcon instead?
|
||||
_setIconFromFile: function(iconFile) {
|
||||
this._iconBin.set_style('background-image: url("' + iconFile + '");' +
|
||||
'background-size: contain;');
|
||||
this._iconBin.child = null;
|
||||
},
|
||||
|
||||
_setIconFromName: function(iconName) {
|
||||
this._iconBin.set_style(null);
|
||||
|
||||
if (iconName != null) {
|
||||
let icon = new St.Icon({ icon_name: iconName,
|
||||
icon_type: St.IconType.SYMBOLIC,
|
||||
icon_size: DIALOG_ICON_SIZE });
|
||||
this._iconBin.child = icon;
|
||||
this._iconBin.show();
|
||||
} else {
|
||||
this._iconBin.child = null;
|
||||
this._iconBin.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const UnlockDialog = new Lang.Class({
|
||||
Name: 'UnlockDialog',
|
||||
Extends: ModalDialog.ModalDialog,
|
||||
|
||||
_init: function() {
|
||||
this.parent({ shellReactive: true,
|
||||
styleClass: 'login-dialog' });
|
||||
|
||||
this._userManager = AccountsService.UserManager.get_default();
|
||||
this._userName = GLib.get_user_name();
|
||||
this._user = this._userManager.get_user(this._userName);
|
||||
|
||||
this._greeterClient = GdmGreeter.Server.new_for_display_sync(null, null);
|
||||
|
||||
this._greeterClient.call_start_conversation_sync(GdmLoginDialog.PASSWORD_SERVICE_NAME, null);
|
||||
|
||||
this._greeterClient.connect('reset',
|
||||
Lang.bind(this, this._onReset));
|
||||
this._greeterClient.connect('ready',
|
||||
Lang.bind(this, this._onReady));
|
||||
this._greeterClient.connect('info',
|
||||
Lang.bind(this, this._onInfo));
|
||||
this._greeterClient.connect('problem',
|
||||
Lang.bind(this, this._onProblem));
|
||||
this._greeterClient.connect('info-query',
|
||||
Lang.bind(this, this._onInfoQuery));
|
||||
this._greeterClient.connect('secret-info-query',
|
||||
Lang.bind(this, this._onSecretInfoQuery));
|
||||
this._greeterClient.connect('session-opened',
|
||||
Lang.bind(this, this._onSessionOpened));
|
||||
this._greeterClient.connect('conversation-stopped',
|
||||
Lang.bind(this, this._onConversationStopped));
|
||||
|
||||
this._fprintManager = new Fprint.FprintManager();
|
||||
this._startFingerprintConversationIfNeeded();
|
||||
|
||||
this._userWidget = new UserWidget(this._user);
|
||||
this.contentLayout.add_actor(this._userWidget.actor);
|
||||
|
||||
this._promptLayout = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout',
|
||||
vertical: false
|
||||
});
|
||||
|
||||
this._promptLabel = new St.Label({ style_class: 'login-dialog-prompt-label' });
|
||||
this._promptLayout.add(this._promptLabel,
|
||||
{ expand: false,
|
||||
x_fill: true,
|
||||
y_fill: true,
|
||||
x_align: St.Align.START });
|
||||
|
||||
this._promptEntry = new St.Entry({ style_class: 'login-dialog-prompt-entry',
|
||||
can_focus: true });
|
||||
this._promptLayout.add(this._promptEntry,
|
||||
{ expand: true,
|
||||
x_fill: true,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START });
|
||||
|
||||
this.contentLayout.add_actor(this._promptLayout);
|
||||
|
||||
// Translators: this message is shown below the password entry field
|
||||
// to indicate the user can swipe their finger instead
|
||||
this._promptFingerprintMessage = new St.Label({ text: _("(or swipe finger)"),
|
||||
style_class: 'login-dialog-prompt-fingerprint-message' });
|
||||
this._promptFingerprintMessage.hide();
|
||||
this.contentLayout.add_actor(this._promptFingerprintMessage);
|
||||
|
||||
this._okButton = { label: _("Unlock"),
|
||||
action: Lang.bind(this, this._doUnlock),
|
||||
key: Clutter.KEY_Return,
|
||||
};
|
||||
this.setButtons([this._okButton]);
|
||||
|
||||
this._updateOkButton(true);
|
||||
},
|
||||
|
||||
_updateOkButton: function(sensitive) {
|
||||
this._okButton.button.reactive = sensitive;
|
||||
this._okButton.button.can_focus = sensitive;
|
||||
if (sensitive)
|
||||
this._okButton.button.remove_style_pseudo_class('disabled');
|
||||
else
|
||||
this._okButton.button.add_style_pseudo_class('disabled');
|
||||
},
|
||||
|
||||
_onReset: function() {
|
||||
// I'm not sure this is emitted for external greeters...
|
||||
|
||||
this._greeterClient.call_start_conversation_sync(GdmLoginDialog.PASSWORD_SERVICE_NAME, null);
|
||||
this._startFingerprintConversationIfNeeded();
|
||||
},
|
||||
|
||||
_startFingerprintConversationIfNeeded: function() {
|
||||
this._haveFingerprintReader = false;
|
||||
|
||||
// FIXME: the greeter has a GSettings key for disabling fingerprint auth
|
||||
|
||||
this._fprintManager.GetDefaultDeviceRemote(Lang.bind(this,
|
||||
function(device, error) {
|
||||
if (!error && device)
|
||||
this._haveFingerprintReader = true;
|
||||
|
||||
if (this._haveFingerprintReader)
|
||||
this._greeterClient.call_start_conversation_sync(GdmLoginDialog.FINGERPRINT_SERVICE_NAME, null);
|
||||
}));
|
||||
},
|
||||
|
||||
_onReady: function(greeter, serviceName) {
|
||||
greeter.call_begin_verification_for_user_sync(serviceName, this._userName, null);
|
||||
},
|
||||
|
||||
_onInfo: function(greeter, serviceName, info) {
|
||||
// We don't display fingerprint messages, because they
|
||||
// have words like UPEK in them. Instead we use the messages
|
||||
// as a cue to display our own message.
|
||||
if (serviceName == GdmLoginDialog.FINGERPRINT_SERVICE_NAME &&
|
||||
this._haveFingerprintReader &&
|
||||
(!this._promptFingerprintMessage.visible ||
|
||||
this._promptFingerprintMessage.opacity != 255)) {
|
||||
|
||||
_fadeInActor(this._promptFingerprintMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
if (serviceName != GdmLoginDialog.PASSWORD_SERVICE_NAME)
|
||||
return;
|
||||
Main.notify(info);
|
||||
},
|
||||
|
||||
_onProblem: function(client, serviceName, problem) {
|
||||
// we don't want to show auth failed messages to
|
||||
// users who haven't enrolled their fingerprint.
|
||||
if (serviceName != GdmLoginDialog.PASSWORD_SERVICE_NAME)
|
||||
return;
|
||||
Main.notifyError(problem);
|
||||
},
|
||||
|
||||
_onInfoQuery: function(client, serviceName, question) {
|
||||
// We only expect questions to come from the main auth service
|
||||
if (serviceName != GdmLoginDialog.PASSWORD_SERVICE_NAME)
|
||||
return;
|
||||
|
||||
this._promptLabel.text = question;
|
||||
this._promptEntry.text = '';
|
||||
this._promptEntry.clutter_text.set_password_char('');
|
||||
|
||||
this._currentQuery = serviceName;
|
||||
this._updateOkButton(true);
|
||||
},
|
||||
|
||||
_onSecretInfoQuery: function(client, serviceName, secretQuestion) {
|
||||
// We only expect secret requests to come from the main auth service
|
||||
if (serviceName != GdmLoginDialog.PASSWORD_SERVICE_NAME)
|
||||
return;
|
||||
|
||||
this._promptLabel.text = secretQuestion;
|
||||
this._promptEntry.text = '';
|
||||
this._promptEntry.clutter_text.set_password_char('\u25cf');
|
||||
|
||||
this._currentQuery = serviceName;
|
||||
this._updateOkButton(true);
|
||||
},
|
||||
|
||||
_doUnlock: function() {
|
||||
if (!this._currentQuery)
|
||||
return;
|
||||
|
||||
let query = this._currentQuery;
|
||||
this._currentQuery = null;
|
||||
|
||||
this._updateOkButton(false);
|
||||
|
||||
this._greeterClient.call_answer_query_sync(query, this._promptEntry.text, null);
|
||||
},
|
||||
|
||||
_onConversationStopped: function(client, serviceName) {
|
||||
// if the password service fails, then cancel everything.
|
||||
// But if, e.g., fingerprint fails, still give
|
||||
// password authentication a chance to succeed
|
||||
if (serviceName == GdmLoginDialog.PASSWORD_SERVICE_NAME) {
|
||||
this._greeterClient.call_cancel_sync(null);
|
||||
this.emit('failed');
|
||||
} else if (serviceName == GdmLoginDialog.FINGERPRINT_SERVICE_NAME) {
|
||||
_fadeOutActor(this._promptFingerprintMessage);
|
||||
}
|
||||
},
|
||||
|
||||
_onSessionOpened: function(client, serviceName) {
|
||||
// For external greeters, SessionOpened means we succeded
|
||||
// in the authentication process
|
||||
|
||||
// Close the greeter proxy
|
||||
this._greeterClient.run_dispose();
|
||||
this._greeterClient = null;
|
||||
|
||||
this.emit('unlocked');
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
if (this._greeterClient) {
|
||||
this._greeterClient.run_dispose();
|
||||
this._greeterClient = null;
|
||||
}
|
||||
|
||||
this.parent();
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
this._greeterClient.call_cancel_sync(null);
|
||||
|
||||
this.destroy();
|
||||
},
|
||||
});
|
Loading…
Reference in New Issue
Block a user