From 66af7de6d6557736b455c0bcf62503f4da433cb8 Mon Sep 17 00:00:00 2001 From: Cosimo Cecchi Date: Tue, 19 Jun 2012 20:22:26 -0400 Subject: [PATCH] automount: re-use the same dialog when passphrase doesn't match Wait until the completion of the mount operation before dismissing the passphrase dialog, so in case it fails, we can re-use the same dialog with an error message (like e.g. PolicyKit auth dialogs) instead of showing a brand new one. https://bugzilla.gnome.org/show_bug.cgi?id=674962 --- js/ui/automountManager.js | 35 +++++++++++----- js/ui/shellMountOperation.js | 79 +++++++++++++++++++++++------------- 2 files changed, 75 insertions(+), 39 deletions(-) diff --git a/js/ui/automountManager.js b/js/ui/automountManager.js index e3db54f0b..d6cc3b76f 100644 --- a/js/ui/automountManager.js +++ b/js/ui/automountManager.js @@ -238,7 +238,7 @@ const AutomountManager = new Lang.Class({ if (params.useMountOp) { let operation = new ShellMountOperation.ShellMountOperation(volume); - this._mountVolume(volume, operation.mountOp, params.allowAutorun); + this._mountVolume(volume, operation, params.allowAutorun); } else { this._mountVolume(volume, null, params.allowAutorun); } @@ -248,7 +248,10 @@ const AutomountManager = new Lang.Class({ if (allowAutorun) this._allowAutorun(volume); - volume.mount(0, operation, null, + let mountOp = operation ? operation.mountOp : null; + volume._operation = operation; + + volume.mount(0, mountOp, null, Lang.bind(this, this._onVolumeMounted)); }, @@ -257,15 +260,17 @@ const AutomountManager = new Lang.Class({ try { volume.mount_finish(res); + this._closeOperation(volume); } catch (e) { - let string = e.toString(); - - // FIXME: needs proper error code handling instead of this - // See https://bugzilla.gnome.org/show_bug.cgi?id=591480 - if (string.indexOf('No key available with this passphrase') != -1) + // FIXME: we will always get G_IO_ERROR_FAILED from the gvfs udisks + // backend in this case, see + // https://bugs.freedesktop.org/show_bug.cgi?id=51271 + if (e.message.indexOf('No key available with this passphrase') != -1) { this._reaskPassword(volume); - else - log('Unable to mount volume ' + volume.get_name() + ': ' + string); + } else { + log('Unable to mount volume ' + volume.get_name() + ': ' + e.toString()); + this._closeOperation(volume); + } } }, @@ -277,8 +282,16 @@ const AutomountManager = new Lang.Class({ }, _reaskPassword: function(volume) { - let operation = new ShellMountOperation.ShellMountOperation(volume, { reaskPassword: true }); - this._mountVolume(volume, operation.mountOp); + let existingDialog = volume._operation ? volume._operation.borrowDialog() : null; + let operation = + new ShellMountOperation.ShellMountOperation(volume, + { existingDialog: existingDialog }); + this._mountVolume(volume, operation); + }, + + _closeOperation: function(volume) { + if (volume._operation) + volume._operation.close(); }, _allowAutorun: function(volume) { diff --git a/js/ui/shellMountOperation.js b/js/ui/shellMountOperation.js index 528a398bd..805ce6043 100644 --- a/js/ui/shellMountOperation.js +++ b/js/ui/shellMountOperation.js @@ -99,11 +99,11 @@ const ShellMountOperation = new Lang.Class({ Name: 'ShellMountOperation', _init: function(source, params) { - params = Params.parse(params, { reaskPassword: false }); - - this._reaskPassword = params.reaskPassword; + params = Params.parse(params, { existingDialog: null }); this._dialog = null; + this._dialogId = 0; + this._existingDialog = params.existingDialog; this._processesDialog = null; this.mountOp = new Shell.MountOperation(); @@ -115,21 +115,29 @@ const ShellMountOperation = new Lang.Class({ this.mountOp.connect('show-processes-2', Lang.bind(this, this._onShowProcesses2)); this.mountOp.connect('aborted', - Lang.bind(this, this._onAborted)); + Lang.bind(this, this.close)); this._gicon = source.get_icon(); }, + _closeExistingDialog: function() { + if (!this._existingDialog) + return; + + this._existingDialog.close(global.get_current_time()); + this._existingDialog = null; + }, + _onAskQuestion: function(op, message, choices) { + this._closeExistingDialog(); this._dialog = new ShellMountQuestionDialog(this._gicon); - this._dialog.connect('response', + this._dialogId = this._dialog.connect('response', Lang.bind(this, function(object, choice) { this.mountOp.set_choice(choice); this.mountOp.reply(Gio.MountOperationResult.HANDLED); - this._dialog.close(global.get_current_time()); - this._dialog = null; + this.close(); })); this._dialog.update(message, choices); @@ -137,11 +145,15 @@ const ShellMountOperation = new Lang.Class({ }, _onAskPassword: function(op, message) { - this._dialog = new ShellMountPasswordDialog( - message, this._gicon, this._reaskPassword); + if (this._existingDialog) { + this._dialog = this._existingDialog; + this._dialog.reaskPassword(); + } else { + this._dialog = new ShellMountPasswordDialog(message, this._gicon); + } - this._dialog.connect('response', Lang.bind(this, - function(object, choice, password, remember) { + this._dialogId = this._dialog.connect('response', Lang.bind(this, + function(object, choice, password, remember) { if (choice == '-1') { this.mountOp.reply(Gio.MountOperationResult.ABORTED); } else { @@ -153,16 +165,13 @@ const ShellMountOperation = new Lang.Class({ this.mountOp.set_password(password); this.mountOp.reply(Gio.MountOperationResult.HANDLED); } - - this._dialog.close(global.get_current_time()); - this._dialog = null; })); this._dialog.open(global.get_current_time()); }, - _onAborted: function(op) { - if (!this._dialog) - return; + close: function(op) { + this._closeExistingDialog(); + this._processesDialog = null; if (this._dialog) { this._dialog.close(global.get_current_time()); @@ -171,6 +180,8 @@ const ShellMountOperation = new Lang.Class({ }, _onShowProcesses2: function(op) { + this._closeExistingDialog(); + let processes = op.get_show_processes_pids(); let choices = op.get_show_processes_choices(); let message = op.get_show_processes_message(); @@ -179,7 +190,7 @@ const ShellMountOperation = new Lang.Class({ this._processesDialog = new ShellProcessesDialog(this._gicon); this._dialog = this._processesDialog; - this._processesDialog.connect('response', + this._dialogId = this._processesDialog.connect('response', Lang.bind(this, function(object, choice) { if (choice == -1) { this.mountOp.reply(Gio.MountOperationResult.ABORTED); @@ -188,14 +199,22 @@ const ShellMountOperation = new Lang.Class({ this.mountOp.reply(Gio.MountOperationResult.HANDLED); } - this._processesDialog.close(global.get_current_time()); - this._dialog = null; + this.close(); })); this._processesDialog.open(global.get_current_time()); } this._processesDialog.update(message, processes, choices); }, + + borrowDialog: function() { + if (this._dialogId != 0) { + this._dialog.disconnect(this._dialogId); + this._dialogId = 0; + } + + return this._dialog; + } }); const ShellMountQuestionDialog = new Lang.Class({ @@ -248,7 +267,7 @@ const ShellMountPasswordDialog = new Lang.Class({ Name: 'ShellMountPasswordDialog', Extends: ModalDialog.ModalDialog, - _init: function(message, gicon, reaskPassword) { + _init: function(message, gicon) { let strings = message.split('\n'); this.parent({ styleClass: 'prompt-dialog' }); @@ -300,13 +319,12 @@ const ShellMountPasswordDialog = new Lang.Class({ this._passwordBox.add(this._passwordEntry, {expand: true }); this.setInitialKeyFocus(this._passwordEntry); - if (reaskPassword) { - this._errorMessageLabel = new St.Label({ style_class: 'prompt-dialog-error-label', - text: _("Sorry, that didn\'t work. Please try again.") }); - this._errorMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; - this._errorMessageLabel.clutter_text.line_wrap = true; - this._messageBox.add(this._errorMessageLabel); - } + this._errorMessageLabel = new St.Label({ style_class: 'prompt-dialog-error-label', + text: _("Sorry, that didn\'t work. Please try again.") }); + this._errorMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; + this._errorMessageLabel.clutter_text.line_wrap = true; + this._errorMessageLabel.hide(); + this._messageBox.add(this._errorMessageLabel); this._rememberChoice = new CheckBox.CheckBox(); this._rememberChoice.getLabelActor().text = _("Remember Passphrase"); @@ -324,6 +342,11 @@ const ShellMountPasswordDialog = new Lang.Class({ this.setButtons(buttons); }, + reaskPassword: function() { + this._passwordEntry.set_text(''); + this._errorMessageLabel.show(); + }, + _onCancelButton: function() { this.emit('response', -1, '', false); },