[gnome-shell/hotplug: 16/21] mount-operation: implement ask-password for mounting encrypted volumes



commit bb1bca679a2f902d3e97f9dadbc17568efe9cf2d
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Thu Jun 23 17:48:20 2011 -0400

    mount-operation: implement ask-password for mounting encrypted volumes

 data/theme/gnome-shell.css   |    4 ++
 js/ui/automountManager.js    |   18 ++++++-
 js/ui/shellMountOperation.js |  109 ++++++++++++++++++++++++++++++++++++++++-
 src/shell-mount-operation.c  |   11 ++++
 4 files changed, 136 insertions(+), 6 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 4a15fd6..84c4086 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -1661,6 +1661,10 @@ StTooltip StLabel {
     icon-size: 32px;
 }
 
+.mount-password-reask {
+    color: red;
+}
+
 .show-processes-dialog,
 .mount-question-dialog {
     spacing: 24px;
diff --git a/js/ui/automountManager.js b/js/ui/automountManager.js
index d475a8c..9b32cc9 100644
--- a/js/ui/automountManager.js
+++ b/js/ui/automountManager.js
@@ -226,7 +226,7 @@ AutomountManager.prototype = {
             return;
         }
 
-        let operation = new ShellMountOperation.ShellMountOperation(volume)
+        let operation = new ShellMountOperation.ShellMountOperation(volume);
         this._mountVolume(volume, operation.mountOp);
     },
 
@@ -241,8 +241,15 @@ AutomountManager.prototype = {
         try {
             volume.mount_finish(res);
         } catch (e) {
-            log('Unable to mount volume ' + volume.get_name() + ': ' +
-                e.toString());
+            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)
+                this._reaskPassword(volume);
+            else
+                log('Unable to mount volume ' + volume.get_name() + ': ' + string);
+
             return;
         }
     },
@@ -254,6 +261,11 @@ AutomountManager.prototype = {
             });
     },
 
+    _reaskPassword: function(volume) {
+        let operation = new ShellMountOperation.ShellMountOperation(volume, { reaskPassword: true });
+        this._mountVolume(volume, operation.mountOp);        
+    },
+
     _allowAutorun: function(volume) {
         volume.allowAutorun = true;
     },
diff --git a/js/ui/shellMountOperation.js b/js/ui/shellMountOperation.js
index 2185bb0..2c07fca 100644
--- a/js/ui/shellMountOperation.js
+++ b/js/ui/shellMountOperation.js
@@ -8,7 +8,10 @@ const Pango = imports.gi.Pango;
 const St = imports.gi.St;
 const Shell = imports.gi.Shell;
 
+const Main = imports.ui.main;
+const MessageTray = imports.ui.messageTray;
 const ModalDialog = imports.ui.modalDialog;
+const Params = imports.misc.params;
 
 /* ------ Common Utils ------- */
 
@@ -86,12 +89,15 @@ ListItem.prototype = {
 };
 Signals.addSignalMethods(ListItem.prototype);
 
-function ShellMountOperation(source) {
-    this._init(source);
+function ShellMountOperation(source, params) {
+    this._init(source, params);
 }
 
 ShellMountOperation.prototype = {
-    _init: function(source) {
+    _init: function(source, params) {
+        params = Params.parse(params, { reaskPassword: false });
+
+        this._reaskPassword = params.reaskPassword;
         this._initMountOp();
         this._initIcon(source);
     },
@@ -101,6 +107,8 @@ ShellMountOperation.prototype = {
 
         this.mountOp.connect('ask-question',
                              Lang.bind(this, this._onAskQuestion));
+        this.mountOp.connect('ask-password',
+                             Lang.bind(this, this._onAskPassword));
         this.mountOp.connect('show-processes-2',
                              Lang.bind(this, this._onShowProcesses2));
         this.mountOp.connect('aborted',
@@ -129,6 +137,29 @@ ShellMountOperation.prototype = {
         questionDialog.open(global.get_current_time());
     },
 
+    _onAskPassword: function(op, message) {
+        this._notificationShowing = true;
+        this._source = new ShellMountPasswordSource(message, this._icon, this._reaskPassword);
+
+        this._source.connect('password-ready',
+                             Lang.bind(this, function(source, password) {
+                                 this.mountOp.set_password(password);
+                                 this.mountOp.reply(Gio.MountOperationResult.HANDLED);
+
+                                 this._notificationShowing = false;
+                                 this._source.destroy();
+                             }));
+
+        this._source.connect('destroy',
+                             Lang.bind(this, function() {
+                                 if (!this._notificationShowing)
+                                     return;
+
+                                 this._notificationShowing = false;
+                                 this.mountOp.reply(Gio.MountOperationResult.ABORTED);
+                             }));
+    },
+
     _onAborted: function(op) {
         if (!this._dialog)
             return;
@@ -216,6 +247,78 @@ ShellMountQuestionDialog.prototype = {
 }
 Signals.addSignalMethods(ShellMountQuestionDialog.prototype);
 
+function ShellMountPasswordSource(message, icon, reaskPassword) {
+    this._init(message, icon, reaskPassword);
+}
+
+ShellMountPasswordSource.prototype = {
+    __proto__: MessageTray.Source.prototype,
+
+    _init: function(message, icon, reaskPassword) {
+        let strings = message.split('\n');
+        MessageTray.Source.prototype._init.call(this, strings[0]);
+
+        this._notification = new ShellMountPasswordNotification(this, strings, icon, reaskPassword);
+
+        // add ourselves as a source, and popup the notification
+        Main.messageTray.add(this);
+        this.notify(this._notification);
+    },
+}
+Signals.addSignalMethods(ShellMountPasswordSource.prototype);
+
+function ShellMountPasswordNotification(source, strings, icon, reaskPassword) {
+    this._init(source, strings, icon, reaskPassword);
+}
+
+ShellMountPasswordNotification.prototype = {
+    __proto__: MessageTray.Notification.prototype,
+
+    _init: function(source, strings, icon, reaskPassword) {
+        MessageTray.Notification.prototype._init.call(this, source,
+                                                      strings[0], null,
+                                                      { customContent: true,
+                                                        icon: icon });
+
+        // set the notification to transient and urgent, so that it
+        // expands out
+        this.setTransient(true);
+        this.setUrgency(MessageTray.Urgency.CRITICAL);
+
+        if (strings[1])
+            this.addBody(strings[1]);
+
+        this._buildUI(reaskPassword);
+    },
+
+    _buildUI: function(reaskPassword) {
+        if (reaskPassword) {
+            let label = new St.Label({ style_class: 'mount-password-reask',
+                                       text: _("Wrong password, please try again") });
+
+            this.addActor(label);
+        }
+
+        this._responseEntry = new St.Entry({ style_class: 'mount-password-entry',
+                                             can_focus: true });
+        this.setActionArea(this._responseEntry);
+
+        this._responseEntry.clutter_text.connect('activate',
+                                                 Lang.bind(this, this._onEntryActivated));
+        this._responseEntry.clutter_text.set_password_char('\u25cf'); // â U+25CF BLACK CIRCLE
+
+        this._responseEntry.grab_key_focus();
+    },
+
+    _onEntryActivated: function() {
+        let text = this._responseEntry.get_text();
+        if (text == '')
+            return;
+
+        this.source.emit('password-ready', text);
+    }
+}
+
 function ShellProcessesDialog(icon) {
     this._init(icon);
 }
diff --git a/src/shell-mount-operation.c b/src/shell-mount-operation.c
index 4d03f51..9f172ed 100644
--- a/src/shell-mount-operation.c
+++ b/src/shell-mount-operation.c
@@ -57,6 +57,16 @@ shell_mount_operation_init (ShellMountOperation *self)
 }
 
 static void
+shell_mount_operation_ask_password (GMountOperation   *op,
+                                    const char        *message,
+                                    const char        *default_user,
+                                    const char        *default_domain,
+                                    GAskPasswordFlags  flags)
+{
+  /* do nothing */
+}
+
+static void
 shell_mount_operation_ask_question (GMountOperation *op,
                                     const char      *message,
                                     const char      *choices[])
@@ -115,6 +125,7 @@ shell_mount_operation_class_init (ShellMountOperationClass *klass)
   mclass = G_MOUNT_OPERATION_CLASS (klass);
   mclass->show_processes = shell_mount_operation_show_processes;
   mclass->ask_question = shell_mount_operation_ask_question;
+  mclass->ask_password = shell_mount_operation_ask_password;
 
   oclass = G_OBJECT_CLASS (klass);
   oclass->finalize = shell_mount_operation_finalize;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]