2011-09-28 13:16:26 +00:00
|
|
|
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
2011-06-22 20:43:16 +00:00
|
|
|
|
|
2012-06-19 22:12:11 +00:00
|
|
|
|
const Clutter = imports.gi.Clutter;
|
2011-06-22 20:43:16 +00:00
|
|
|
|
const Lang = imports.lang;
|
|
|
|
|
const Signals = imports.signals;
|
|
|
|
|
const Gio = imports.gi.Gio;
|
2012-06-20 21:23:34 +00:00
|
|
|
|
const GLib = imports.gi.GLib;
|
2011-06-22 20:43:16 +00:00
|
|
|
|
const Gtk = imports.gi.Gtk;
|
|
|
|
|
const Pango = imports.gi.Pango;
|
|
|
|
|
const St = imports.gi.St;
|
|
|
|
|
const Shell = imports.gi.Shell;
|
|
|
|
|
|
2012-06-19 22:12:11 +00:00
|
|
|
|
const CheckBox = imports.ui.checkBox;
|
2017-07-15 04:03:55 +00:00
|
|
|
|
const Dialog = imports.ui.dialog;
|
2011-07-12 15:29:49 +00:00
|
|
|
|
const Main = imports.ui.main;
|
|
|
|
|
const MessageTray = imports.ui.messageTray;
|
2011-06-22 20:43:16 +00:00
|
|
|
|
const ModalDialog = imports.ui.modalDialog;
|
2011-07-12 15:29:49 +00:00
|
|
|
|
const Params = imports.misc.params;
|
2012-06-19 22:12:11 +00:00
|
|
|
|
const ShellEntry = imports.ui.shellEntry;
|
2011-06-22 20:43:16 +00:00
|
|
|
|
|
2017-07-18 17:47:27 +00:00
|
|
|
|
var LIST_ITEM_ICON_SIZE = 48;
|
2011-06-22 20:43:16 +00:00
|
|
|
|
|
2012-11-15 20:57:15 +00:00
|
|
|
|
const REMEMBER_MOUNT_PASSWORD_KEY = 'remember-mount-password';
|
|
|
|
|
|
2011-07-12 15:44:08 +00:00
|
|
|
|
/* ------ Common Utils ------- */
|
2011-06-22 20:43:16 +00:00
|
|
|
|
function _setLabelText(label, text) {
|
|
|
|
|
if (text) {
|
|
|
|
|
label.set_text(text);
|
|
|
|
|
label.show();
|
|
|
|
|
} else {
|
|
|
|
|
label.set_text('');
|
|
|
|
|
label.hide();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-12 15:44:08 +00:00
|
|
|
|
function _setButtonsForChoices(dialog, choices) {
|
|
|
|
|
let buttons = [];
|
|
|
|
|
|
|
|
|
|
for (let idx = 0; idx < choices.length; idx++) {
|
|
|
|
|
let button = idx;
|
|
|
|
|
buttons.unshift({ label: choices[idx],
|
2017-12-02 00:27:35 +00:00
|
|
|
|
action: () => { dialog.emit('response', button); }
|
|
|
|
|
});
|
2011-07-12 15:44:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dialog.setButtons(buttons);
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-15 04:03:55 +00:00
|
|
|
|
function _setLabelsForMessage(content, message) {
|
2011-07-12 15:44:08 +00:00
|
|
|
|
let labels = message.split('\n');
|
|
|
|
|
|
2017-07-15 04:03:55 +00:00
|
|
|
|
content.title = labels.shift();
|
|
|
|
|
content.body = labels.join('\n');
|
2011-07-12 15:44:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-06-19 20:31:24 +00:00
|
|
|
|
function _createIcon(gicon) {
|
|
|
|
|
return new St.Icon({ gicon: gicon,
|
|
|
|
|
style_class: 'shell-mount-operation-icon' })
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-12 15:44:08 +00:00
|
|
|
|
/* -------------------------------------------------------- */
|
|
|
|
|
|
2017-07-18 17:41:25 +00:00
|
|
|
|
var ListItem = new Lang.Class({
|
2011-11-20 17:56:27 +00:00
|
|
|
|
Name: 'ListItem',
|
2011-06-22 20:43:16 +00:00
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_init(app) {
|
2011-06-22 20:43:16 +00:00
|
|
|
|
this._app = app;
|
|
|
|
|
|
|
|
|
|
let layout = new St.BoxLayout({ vertical: false});
|
|
|
|
|
|
2017-07-15 06:53:34 +00:00
|
|
|
|
this.actor = new St.Button({ style_class: 'mount-dialog-app-list-item',
|
2011-06-22 20:43:16 +00:00
|
|
|
|
can_focus: true,
|
|
|
|
|
child: layout,
|
|
|
|
|
reactive: true,
|
|
|
|
|
x_align: St.Align.START,
|
|
|
|
|
x_fill: true });
|
|
|
|
|
|
|
|
|
|
this._icon = this._app.create_icon_texture(LIST_ITEM_ICON_SIZE);
|
|
|
|
|
|
2017-07-15 06:53:34 +00:00
|
|
|
|
let iconBin = new St.Bin({ style_class: 'mount-dialog-app-list-item-icon',
|
2011-06-22 20:43:16 +00:00
|
|
|
|
child: this._icon });
|
|
|
|
|
layout.add(iconBin);
|
|
|
|
|
|
|
|
|
|
this._nameLabel = new St.Label({ text: this._app.get_name(),
|
2017-07-15 06:53:34 +00:00
|
|
|
|
style_class: 'mount-dialog-app-list-item-name' });
|
2011-06-22 20:43:16 +00:00
|
|
|
|
let labelBin = new St.Bin({ y_align: St.Align.MIDDLE,
|
|
|
|
|
child: this._nameLabel });
|
|
|
|
|
layout.add(labelBin);
|
|
|
|
|
|
2017-12-02 00:27:35 +00:00
|
|
|
|
this.actor.connect('clicked', this._onClicked.bind(this));
|
2011-06-22 20:43:16 +00:00
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_onClicked() {
|
2011-06-22 20:43:16 +00:00
|
|
|
|
this.emit('activate');
|
2011-08-11 09:35:23 +00:00
|
|
|
|
this._app.activate();
|
2011-06-22 20:43:16 +00:00
|
|
|
|
}
|
2011-11-20 17:56:27 +00:00
|
|
|
|
});
|
2011-06-22 20:43:16 +00:00
|
|
|
|
Signals.addSignalMethods(ListItem.prototype);
|
|
|
|
|
|
2017-07-18 17:41:25 +00:00
|
|
|
|
var ShellMountOperation = new Lang.Class({
|
2011-11-20 17:56:27 +00:00
|
|
|
|
Name: 'ShellMountOperation',
|
2011-06-22 20:43:16 +00:00
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_init(source, params) {
|
2012-06-20 00:22:26 +00:00
|
|
|
|
params = Params.parse(params, { existingDialog: null });
|
2011-07-12 15:29:49 +00:00
|
|
|
|
|
2011-07-12 15:44:08 +00:00
|
|
|
|
this._dialog = null;
|
2012-06-20 00:22:26 +00:00
|
|
|
|
this._dialogId = 0;
|
|
|
|
|
this._existingDialog = params.existingDialog;
|
2011-06-22 20:43:16 +00:00
|
|
|
|
this._processesDialog = null;
|
|
|
|
|
|
|
|
|
|
this.mountOp = new Shell.MountOperation();
|
|
|
|
|
|
|
|
|
|
this.mountOp.connect('ask-question',
|
2017-12-02 00:27:35 +00:00
|
|
|
|
this._onAskQuestion.bind(this));
|
2011-06-22 20:43:16 +00:00
|
|
|
|
this.mountOp.connect('ask-password',
|
2017-12-02 00:27:35 +00:00
|
|
|
|
this._onAskPassword.bind(this));
|
2011-06-22 20:43:16 +00:00
|
|
|
|
this.mountOp.connect('show-processes-2',
|
2017-12-02 00:27:35 +00:00
|
|
|
|
this._onShowProcesses2.bind(this));
|
2011-06-22 20:43:16 +00:00
|
|
|
|
this.mountOp.connect('aborted',
|
2017-12-02 00:27:35 +00:00
|
|
|
|
this.close.bind(this));
|
2012-07-10 01:58:12 +00:00
|
|
|
|
this.mountOp.connect('show-unmount-progress',
|
2017-12-02 00:27:35 +00:00
|
|
|
|
this._onShowUnmountProgress.bind(this));
|
2011-06-22 20:43:16 +00:00
|
|
|
|
|
2012-06-19 20:31:24 +00:00
|
|
|
|
this._gicon = source.get_icon();
|
2011-06-22 20:43:16 +00:00
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_closeExistingDialog() {
|
2012-06-20 00:22:26 +00:00
|
|
|
|
if (!this._existingDialog)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-06-20 20:12:40 +00:00
|
|
|
|
this._existingDialog.close();
|
2012-06-20 00:22:26 +00:00
|
|
|
|
this._existingDialog = null;
|
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_onAskQuestion(op, message, choices) {
|
2012-06-20 00:22:26 +00:00
|
|
|
|
this._closeExistingDialog();
|
2012-06-19 20:31:24 +00:00
|
|
|
|
this._dialog = new ShellMountQuestionDialog(this._gicon);
|
2011-07-12 15:44:08 +00:00
|
|
|
|
|
2017-10-31 00:38:18 +00:00
|
|
|
|
this._dialogId = this._dialog.connect('response',
|
|
|
|
|
(object, choice) => {
|
2012-06-20 20:14:02 +00:00
|
|
|
|
this.mountOp.set_choice(choice);
|
|
|
|
|
this.mountOp.reply(Gio.MountOperationResult.HANDLED);
|
2011-07-12 15:44:08 +00:00
|
|
|
|
|
2012-06-20 20:14:02 +00:00
|
|
|
|
this.close();
|
2017-10-31 00:38:18 +00:00
|
|
|
|
});
|
2011-07-12 15:44:08 +00:00
|
|
|
|
|
|
|
|
|
this._dialog.update(message, choices);
|
2012-06-20 20:12:40 +00:00
|
|
|
|
this._dialog.open();
|
2011-06-22 20:43:16 +00:00
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_onAskPassword(op, message, defaultUser, defaultDomain, flags) {
|
2012-06-20 00:22:26 +00:00
|
|
|
|
if (this._existingDialog) {
|
|
|
|
|
this._dialog = this._existingDialog;
|
|
|
|
|
this._dialog.reaskPassword();
|
|
|
|
|
} else {
|
2012-06-20 21:23:34 +00:00
|
|
|
|
this._dialog = new ShellMountPasswordDialog(message, this._gicon, flags);
|
2012-06-20 00:22:26 +00:00
|
|
|
|
}
|
2012-06-19 22:12:11 +00:00
|
|
|
|
|
2017-10-31 00:38:18 +00:00
|
|
|
|
this._dialogId = this._dialog.connect('response',
|
|
|
|
|
(object, choice, password, remember) => {
|
2012-06-20 21:23:34 +00:00
|
|
|
|
if (choice == -1) {
|
2012-06-19 22:12:11 +00:00
|
|
|
|
this.mountOp.reply(Gio.MountOperationResult.ABORTED);
|
|
|
|
|
} else {
|
|
|
|
|
if (remember)
|
|
|
|
|
this.mountOp.set_password_save(Gio.PasswordSave.PERMANENTLY);
|
|
|
|
|
else
|
|
|
|
|
this.mountOp.set_password_save(Gio.PasswordSave.NEVER);
|
|
|
|
|
|
|
|
|
|
this.mountOp.set_password(password);
|
|
|
|
|
this.mountOp.reply(Gio.MountOperationResult.HANDLED);
|
|
|
|
|
}
|
2017-10-31 00:38:18 +00:00
|
|
|
|
});
|
2012-06-20 20:12:40 +00:00
|
|
|
|
this._dialog.open();
|
2011-06-22 20:43:16 +00:00
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
close(op) {
|
2012-06-20 00:22:26 +00:00
|
|
|
|
this._closeExistingDialog();
|
|
|
|
|
this._processesDialog = null;
|
2011-07-12 15:44:08 +00:00
|
|
|
|
|
2012-06-19 20:41:39 +00:00
|
|
|
|
if (this._dialog) {
|
2012-06-20 20:12:40 +00:00
|
|
|
|
this._dialog.close();
|
2012-06-19 20:41:39 +00:00
|
|
|
|
this._dialog = null;
|
|
|
|
|
}
|
2012-07-10 01:58:12 +00:00
|
|
|
|
|
|
|
|
|
if (this._notifier) {
|
|
|
|
|
this._notifier.done();
|
|
|
|
|
this._notifier = null;
|
|
|
|
|
}
|
2011-06-22 20:43:16 +00:00
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_onShowProcesses2(op) {
|
2012-06-20 00:22:26 +00:00
|
|
|
|
this._closeExistingDialog();
|
|
|
|
|
|
2011-06-22 20:43:16 +00:00
|
|
|
|
let processes = op.get_show_processes_pids();
|
|
|
|
|
let choices = op.get_show_processes_choices();
|
|
|
|
|
let message = op.get_show_processes_message();
|
|
|
|
|
|
|
|
|
|
if (!this._processesDialog) {
|
2012-06-19 20:31:24 +00:00
|
|
|
|
this._processesDialog = new ShellProcessesDialog(this._gicon);
|
2011-07-12 15:44:08 +00:00
|
|
|
|
this._dialog = this._processesDialog;
|
|
|
|
|
|
2017-10-31 00:38:18 +00:00
|
|
|
|
this._dialogId = this._processesDialog.connect('response',
|
|
|
|
|
(object, choice) => {
|
2012-06-20 20:14:02 +00:00
|
|
|
|
if (choice == -1) {
|
|
|
|
|
this.mountOp.reply(Gio.MountOperationResult.ABORTED);
|
|
|
|
|
} else {
|
|
|
|
|
this.mountOp.set_choice(choice);
|
|
|
|
|
this.mountOp.reply(Gio.MountOperationResult.HANDLED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.close();
|
2017-10-31 00:38:18 +00:00
|
|
|
|
});
|
2012-06-20 20:12:40 +00:00
|
|
|
|
this._processesDialog.open();
|
2011-06-22 20:43:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._processesDialog.update(message, processes, choices);
|
|
|
|
|
},
|
2012-06-20 00:22:26 +00:00
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_onShowUnmountProgress(op, message, timeLeft, bytesLeft) {
|
2012-07-10 01:58:12 +00:00
|
|
|
|
if (!this._notifier)
|
|
|
|
|
this._notifier = new ShellUnmountNotifier();
|
|
|
|
|
|
|
|
|
|
if (bytesLeft == 0)
|
|
|
|
|
this._notifier.done(message);
|
|
|
|
|
else
|
|
|
|
|
this._notifier.show(message);
|
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
borrowDialog() {
|
2012-06-20 00:22:26 +00:00
|
|
|
|
if (this._dialogId != 0) {
|
|
|
|
|
this._dialog.disconnect(this._dialogId);
|
|
|
|
|
this._dialogId = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this._dialog;
|
|
|
|
|
}
|
2011-11-20 17:56:27 +00:00
|
|
|
|
});
|
2011-06-22 20:43:16 +00:00
|
|
|
|
|
2017-07-18 17:41:25 +00:00
|
|
|
|
var ShellUnmountNotifier = new Lang.Class({
|
2012-07-10 01:58:12 +00:00
|
|
|
|
Name: 'ShellUnmountNotifier',
|
|
|
|
|
Extends: MessageTray.Source,
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_init() {
|
2012-05-30 13:58:37 +00:00
|
|
|
|
this.parent('', 'media-removable');
|
2012-07-10 01:58:12 +00:00
|
|
|
|
|
|
|
|
|
this._notification = null;
|
|
|
|
|
Main.messageTray.add(this);
|
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
show(message) {
|
2012-07-10 01:58:12 +00:00
|
|
|
|
let [header, text] = message.split('\n', 2);
|
|
|
|
|
|
|
|
|
|
if (!this._notification) {
|
|
|
|
|
this._notification = new MessageTray.Notification(this, header, text);
|
|
|
|
|
this._notification.setTransient(true);
|
|
|
|
|
this._notification.setUrgency(MessageTray.Urgency.CRITICAL);
|
|
|
|
|
} else {
|
|
|
|
|
this._notification.update(header, text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.notify(this._notification);
|
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
done(message) {
|
2012-07-10 01:58:12 +00:00
|
|
|
|
if (this._notification) {
|
|
|
|
|
this._notification.destroy();
|
|
|
|
|
this._notification = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (message) {
|
|
|
|
|
let notification = new MessageTray.Notification(this, message, null);
|
|
|
|
|
notification.setTransient(true);
|
|
|
|
|
|
|
|
|
|
this.notify(notification);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2017-07-18 17:41:25 +00:00
|
|
|
|
var ShellMountQuestionDialog = new Lang.Class({
|
2011-11-20 15:32:59 +00:00
|
|
|
|
Name: 'ShellMountQuestionDialog',
|
|
|
|
|
Extends: ModalDialog.ModalDialog,
|
2011-07-12 15:44:08 +00:00
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_init(icon) {
|
2017-07-15 06:53:34 +00:00
|
|
|
|
this.parent({ styleClass: 'mount-dialog' });
|
2011-07-12 15:44:08 +00:00
|
|
|
|
|
2017-07-15 04:03:55 +00:00
|
|
|
|
this._content = new Dialog.MessageDialogContent({ icon });
|
|
|
|
|
this.contentLayout.add(this._content, { x_fill: true, y_fill: false });
|
2011-07-12 15:44:08 +00:00
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
update(message, choices) {
|
2017-07-15 04:03:55 +00:00
|
|
|
|
_setLabelsForMessage(this._content, message);
|
2011-07-12 15:44:08 +00:00
|
|
|
|
_setButtonsForChoices(this, choices);
|
|
|
|
|
}
|
2011-11-20 15:32:59 +00:00
|
|
|
|
});
|
2011-07-12 15:44:08 +00:00
|
|
|
|
Signals.addSignalMethods(ShellMountQuestionDialog.prototype);
|
|
|
|
|
|
2017-07-18 17:41:25 +00:00
|
|
|
|
var ShellMountPasswordDialog = new Lang.Class({
|
2012-06-19 22:12:11 +00:00
|
|
|
|
Name: 'ShellMountPasswordDialog',
|
|
|
|
|
Extends: ModalDialog.ModalDialog,
|
2011-07-12 15:29:49 +00:00
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_init(message, icon, flags) {
|
2011-07-12 15:29:49 +00:00
|
|
|
|
let strings = message.split('\n');
|
2017-07-15 04:03:55 +00:00
|
|
|
|
let title = strings.shift() || null;
|
|
|
|
|
let body = strings.shift() || null;
|
2012-06-19 22:12:11 +00:00
|
|
|
|
this.parent({ styleClass: 'prompt-dialog' });
|
|
|
|
|
|
2017-07-15 04:03:55 +00:00
|
|
|
|
let content = new Dialog.MessageDialogContent({ icon, title, body });
|
|
|
|
|
this.contentLayout.add_actor(content);
|
2011-07-12 15:29:49 +00:00
|
|
|
|
|
2012-08-27 23:02:16 +00:00
|
|
|
|
this._passwordBox = new St.BoxLayout({ vertical: false, style_class: 'prompt-dialog-password-box' });
|
2017-07-15 04:03:55 +00:00
|
|
|
|
content.messageBox.add(this._passwordBox);
|
2011-07-12 15:29:49 +00:00
|
|
|
|
|
2012-06-19 22:12:11 +00:00
|
|
|
|
this._passwordLabel = new St.Label(({ style_class: 'prompt-dialog-password-label',
|
2012-08-28 01:16:08 +00:00
|
|
|
|
text: _("Password") }));
|
2012-08-27 23:02:16 +00:00
|
|
|
|
this._passwordBox.add(this._passwordLabel, { y_fill: false, y_align: St.Align.MIDDLE });
|
2011-07-12 15:29:49 +00:00
|
|
|
|
|
2012-06-19 22:12:11 +00:00
|
|
|
|
this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
|
|
|
|
|
text: "",
|
|
|
|
|
can_focus: true});
|
|
|
|
|
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
|
2017-12-02 00:27:35 +00:00
|
|
|
|
this._passwordEntry.clutter_text.connect('activate', this._onEntryActivate.bind(this));
|
2012-06-19 22:12:11 +00:00
|
|
|
|
this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
|
|
|
|
|
this._passwordBox.add(this._passwordEntry, {expand: true });
|
|
|
|
|
this.setInitialKeyFocus(this._passwordEntry);
|
2011-07-12 15:29:49 +00:00
|
|
|
|
|
2012-06-20 00:22:26 +00:00
|
|
|
|
this._errorMessageLabel = new St.Label({ style_class: 'prompt-dialog-error-label',
|
2016-09-29 22:00:13 +00:00
|
|
|
|
text: _("Sorry, that didn’t work. Please try again.") });
|
2012-06-20 00:22:26 +00:00
|
|
|
|
this._errorMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
|
|
|
|
this._errorMessageLabel.clutter_text.line_wrap = true;
|
|
|
|
|
this._errorMessageLabel.hide();
|
2017-07-15 04:03:55 +00:00
|
|
|
|
content.messageBox.add(this._errorMessageLabel);
|
2011-07-12 15:29:49 +00:00
|
|
|
|
|
2012-06-20 21:23:34 +00:00
|
|
|
|
if (flags & Gio.AskPasswordFlags.SAVING_SUPPORTED) {
|
|
|
|
|
this._rememberChoice = new CheckBox.CheckBox();
|
2012-08-28 01:16:08 +00:00
|
|
|
|
this._rememberChoice.getLabelActor().text = _("Remember Password");
|
2012-11-15 20:57:15 +00:00
|
|
|
|
this._rememberChoice.actor.checked =
|
|
|
|
|
global.settings.get_boolean(REMEMBER_MOUNT_PASSWORD_KEY);
|
2017-07-15 04:03:55 +00:00
|
|
|
|
content.messageBox.add(this._rememberChoice.actor);
|
2012-06-20 21:23:34 +00:00
|
|
|
|
} else {
|
|
|
|
|
this._rememberChoice = null;
|
|
|
|
|
}
|
2011-07-12 15:29:49 +00:00
|
|
|
|
|
2012-06-19 22:12:11 +00:00
|
|
|
|
let buttons = [{ label: _("Cancel"),
|
2017-12-02 00:27:35 +00:00
|
|
|
|
action: this._onCancelButton.bind(this),
|
2012-06-19 22:12:11 +00:00
|
|
|
|
key: Clutter.Escape
|
|
|
|
|
},
|
|
|
|
|
{ label: _("Unlock"),
|
2017-12-02 00:27:35 +00:00
|
|
|
|
action: this._onUnlockButton.bind(this),
|
2012-07-19 13:32:59 +00:00
|
|
|
|
default: true
|
2012-06-19 22:12:11 +00:00
|
|
|
|
}];
|
2011-07-12 15:29:49 +00:00
|
|
|
|
|
2012-06-19 22:12:11 +00:00
|
|
|
|
this.setButtons(buttons);
|
2011-07-12 15:29:49 +00:00
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
reaskPassword() {
|
2012-06-20 00:22:26 +00:00
|
|
|
|
this._passwordEntry.set_text('');
|
|
|
|
|
this._errorMessageLabel.show();
|
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_onCancelButton() {
|
2012-06-19 22:12:11 +00:00
|
|
|
|
this.emit('response', -1, '', false);
|
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_onUnlockButton() {
|
2012-06-19 22:12:11 +00:00
|
|
|
|
this._onEntryActivate();
|
|
|
|
|
},
|
2011-07-12 15:29:49 +00:00
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_onEntryActivate() {
|
2012-11-15 20:57:15 +00:00
|
|
|
|
global.settings.set_boolean(REMEMBER_MOUNT_PASSWORD_KEY,
|
|
|
|
|
this._rememberChoice && this._rememberChoice.actor.checked);
|
2012-06-19 22:12:11 +00:00
|
|
|
|
this.emit('response', 1,
|
|
|
|
|
this._passwordEntry.get_text(),
|
2012-06-20 21:23:34 +00:00
|
|
|
|
this._rememberChoice &&
|
2012-06-19 22:12:11 +00:00
|
|
|
|
this._rememberChoice.actor.checked);
|
2011-07-12 15:29:49 +00:00
|
|
|
|
}
|
2011-11-20 15:12:02 +00:00
|
|
|
|
});
|
2011-07-12 15:29:49 +00:00
|
|
|
|
|
2017-07-18 17:41:25 +00:00
|
|
|
|
var ShellProcessesDialog = new Lang.Class({
|
2011-11-20 15:32:59 +00:00
|
|
|
|
Name: 'ShellProcessesDialog',
|
|
|
|
|
Extends: ModalDialog.ModalDialog,
|
2011-06-22 20:43:16 +00:00
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_init(icon) {
|
2017-07-15 06:53:34 +00:00
|
|
|
|
this.parent({ styleClass: 'mount-dialog' });
|
2011-06-22 20:43:16 +00:00
|
|
|
|
|
2017-07-15 04:03:55 +00:00
|
|
|
|
this._content = new Dialog.MessageDialogContent({ icon });
|
|
|
|
|
this.contentLayout.add(this._content, { x_fill: true, y_fill: false });
|
2011-06-22 20:43:16 +00:00
|
|
|
|
|
2017-07-15 06:53:34 +00:00
|
|
|
|
let scrollView = new St.ScrollView({ style_class: 'mount-dialog-app-list'});
|
2011-06-22 20:43:16 +00:00
|
|
|
|
scrollView.set_policy(Gtk.PolicyType.NEVER,
|
|
|
|
|
Gtk.PolicyType.AUTOMATIC);
|
|
|
|
|
this.contentLayout.add(scrollView,
|
|
|
|
|
{ x_fill: true,
|
|
|
|
|
y_fill: true });
|
|
|
|
|
scrollView.hide();
|
|
|
|
|
|
|
|
|
|
this._applicationList = new St.BoxLayout({ vertical: true });
|
2012-07-19 00:15:04 +00:00
|
|
|
|
scrollView.add_actor(this._applicationList);
|
2011-06-22 20:43:16 +00:00
|
|
|
|
|
2017-10-31 00:38:18 +00:00
|
|
|
|
this._applicationList.connect('actor-added', () => {
|
|
|
|
|
if (this._applicationList.get_n_children() == 1)
|
|
|
|
|
scrollView.show();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this._applicationList.connect('actor-removed', () => {
|
|
|
|
|
if (this._applicationList.get_n_children() == 0)
|
|
|
|
|
scrollView.hide();
|
|
|
|
|
});
|
2011-06-22 20:43:16 +00:00
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_setAppsForPids(pids) {
|
2011-06-22 20:43:16 +00:00
|
|
|
|
// remove all the items
|
2012-02-16 18:27:09 +00:00
|
|
|
|
this._applicationList.destroy_all_children();
|
2011-06-22 20:43:16 +00:00
|
|
|
|
|
2017-10-31 00:38:18 +00:00
|
|
|
|
pids.forEach(pid => {
|
2011-06-22 20:43:16 +00:00
|
|
|
|
let tracker = Shell.WindowTracker.get_default();
|
|
|
|
|
let app = tracker.get_app_from_pid(pid);
|
|
|
|
|
|
|
|
|
|
if (!app)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
let item = new ListItem(app);
|
|
|
|
|
this._applicationList.add(item.actor, { x_fill: true });
|
|
|
|
|
|
2017-10-31 00:38:18 +00:00
|
|
|
|
item.connect('activate', () => {
|
|
|
|
|
// use -1 to indicate Cancel
|
|
|
|
|
this.emit('response', -1);
|
|
|
|
|
});
|
|
|
|
|
});
|
2011-06-22 20:43:16 +00:00
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
update(message, processes, choices) {
|
2011-06-22 20:43:16 +00:00
|
|
|
|
this._setAppsForPids(processes);
|
2017-07-15 04:03:55 +00:00
|
|
|
|
_setLabelsForMessage(this._content, message);
|
2011-07-12 15:44:08 +00:00
|
|
|
|
_setButtonsForChoices(this, choices);
|
2011-06-22 20:43:16 +00:00
|
|
|
|
}
|
2011-11-20 15:32:59 +00:00
|
|
|
|
});
|
2011-08-11 09:35:23 +00:00
|
|
|
|
Signals.addSignalMethods(ShellProcessesDialog.prototype);
|
2012-06-20 21:23:34 +00:00
|
|
|
|
|
2013-10-24 21:51:58 +00:00
|
|
|
|
const GnomeShellMountOpIface = '<node> \
|
|
|
|
|
<interface name="org.Gtk.MountOperationHandler"> \
|
|
|
|
|
<method name="AskPassword"> \
|
|
|
|
|
<arg type="s" direction="in" name="object_id"/> \
|
|
|
|
|
<arg type="s" direction="in" name="message"/> \
|
|
|
|
|
<arg type="s" direction="in" name="icon_name"/> \
|
|
|
|
|
<arg type="s" direction="in" name="default_user"/> \
|
|
|
|
|
<arg type="s" direction="in" name="default_domain"/> \
|
|
|
|
|
<arg type="u" direction="in" name="flags"/> \
|
|
|
|
|
<arg type="u" direction="out" name="response"/> \
|
|
|
|
|
<arg type="a{sv}" direction="out" name="response_details"/> \
|
|
|
|
|
</method> \
|
|
|
|
|
<method name="AskQuestion"> \
|
|
|
|
|
<arg type="s" direction="in" name="object_id"/> \
|
|
|
|
|
<arg type="s" direction="in" name="message"/> \
|
|
|
|
|
<arg type="s" direction="in" name="icon_name"/> \
|
|
|
|
|
<arg type="as" direction="in" name="choices"/> \
|
|
|
|
|
<arg type="u" direction="out" name="response"/> \
|
|
|
|
|
<arg type="a{sv}" direction="out" name="response_details"/> \
|
|
|
|
|
</method> \
|
|
|
|
|
<method name="ShowProcesses"> \
|
|
|
|
|
<arg type="s" direction="in" name="object_id"/> \
|
|
|
|
|
<arg type="s" direction="in" name="message"/> \
|
|
|
|
|
<arg type="s" direction="in" name="icon_name"/> \
|
|
|
|
|
<arg type="ai" direction="in" name="application_pids"/> \
|
|
|
|
|
<arg type="as" direction="in" name="choices"/> \
|
|
|
|
|
<arg type="u" direction="out" name="response"/> \
|
|
|
|
|
<arg type="a{sv}" direction="out" name="response_details"/> \
|
|
|
|
|
</method> \
|
|
|
|
|
<method name="Close"/> \
|
|
|
|
|
</interface> \
|
|
|
|
|
</node>';
|
2012-06-20 21:23:34 +00:00
|
|
|
|
|
2017-07-18 17:47:27 +00:00
|
|
|
|
var ShellMountOperationType = {
|
2012-06-20 21:23:34 +00:00
|
|
|
|
NONE: 0,
|
|
|
|
|
ASK_PASSWORD: 1,
|
|
|
|
|
ASK_QUESTION: 2,
|
|
|
|
|
SHOW_PROCESSES: 3
|
|
|
|
|
};
|
|
|
|
|
|
2017-07-18 17:41:25 +00:00
|
|
|
|
var GnomeShellMountOpHandler = new Lang.Class({
|
2012-06-20 21:23:34 +00:00
|
|
|
|
Name: 'GnomeShellMountOpHandler',
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_init() {
|
2012-06-20 21:23:34 +00:00
|
|
|
|
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellMountOpIface, this);
|
|
|
|
|
this._dbusImpl.export(Gio.DBus.session, '/org/gtk/MountOperationHandler');
|
|
|
|
|
Gio.bus_own_name_on_connection(Gio.DBus.session, 'org.gtk.MountOperationHandler',
|
|
|
|
|
Gio.BusNameOwnerFlags.REPLACE, null, null);
|
|
|
|
|
|
|
|
|
|
this._dialog = null;
|
|
|
|
|
this._volumeMonitor = Gio.VolumeMonitor.get();
|
|
|
|
|
|
|
|
|
|
this._ensureEmptyRequest();
|
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_ensureEmptyRequest() {
|
2012-06-20 21:23:34 +00:00
|
|
|
|
this._currentId = null;
|
|
|
|
|
this._currentInvocation = null;
|
|
|
|
|
this._currentType = ShellMountOperationType.NONE;
|
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_clearCurrentRequest(response, details) {
|
2012-06-20 21:23:34 +00:00
|
|
|
|
if (this._currentInvocation) {
|
|
|
|
|
this._currentInvocation.return_value(
|
|
|
|
|
GLib.Variant.new('(ua{sv})', [response, details]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._ensureEmptyRequest();
|
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_setCurrentRequest(invocation, id, type) {
|
2012-06-20 21:23:34 +00:00
|
|
|
|
let oldId = this._currentId;
|
|
|
|
|
let oldType = this._currentType;
|
|
|
|
|
let requestId = id + '@' + invocation.get_sender();
|
|
|
|
|
|
|
|
|
|
this._clearCurrentRequest(Gio.MountOperationResult.UNHANDLED, {});
|
|
|
|
|
|
|
|
|
|
this._currentInvocation = invocation;
|
|
|
|
|
this._currentId = requestId;
|
|
|
|
|
this._currentType = type;
|
|
|
|
|
|
|
|
|
|
if (this._dialog && (oldId == requestId) && (oldType == type))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_closeDialog() {
|
2012-06-20 21:23:34 +00:00
|
|
|
|
if (this._dialog) {
|
|
|
|
|
this._dialog.close();
|
|
|
|
|
this._dialog = null;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
|
_createGIcon(iconName) {
|
2012-06-20 21:23:34 +00:00
|
|
|
|
let realIconName = iconName ? iconName : 'drive-harddisk';
|
|
|
|
|
return new Gio.ThemedIcon({ name: realIconName,
|
|
|
|
|
use_default_fallbacks: true });
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* AskPassword:
|
|
|
|
|
* @id: an opaque ID identifying the object for which the operation is requested
|
|
|
|
|
* The ID must be unique in the context of the calling process.
|
|
|
|
|
* @message: the message to display
|
|
|
|
|
* @icon_name: the name of an icon to display
|
|
|
|
|
* @default_user: the default username for display
|
|
|
|
|
* @default_domain: the default domain for display
|
|
|
|
|
* @flags: a set of GAskPasswordFlags
|
|
|
|
|
* @response: a GMountOperationResult
|
|
|
|
|
* @response_details: a dictionary containing the response details as
|
|
|
|
|
* entered by the user. The dictionary MAY contain the following properties:
|
|
|
|
|
* - "password" -> (s): a password to be used to complete the mount operation
|
|
|
|
|
* - "password_save" -> (u): a GPasswordSave
|
|
|
|
|
*
|
|
|
|
|
* The dialog will stay visible until clients call the Close() method, or
|
|
|
|
|
* another dialog becomes visible.
|
|
|
|
|
* Calling AskPassword again for the same id will have the effect to clear
|
|
|
|
|
* the existing dialog and update it with a message indicating the previous
|
|
|
|
|
* attempt went wrong.
|
|
|
|
|
*/
|
2017-10-31 00:03:21 +00:00
|
|
|
|
AskPasswordAsync(params, invocation) {
|
2012-06-20 21:23:34 +00:00
|
|
|
|
let [id, message, iconName, defaultUser, defaultDomain, flags] = params;
|
|
|
|
|
|
|
|
|
|
if (this._setCurrentRequest(invocation, id, ShellMountOperationType.ASK_PASSWORD)) {
|
|
|
|
|
this._dialog.reaskPassword();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._closeDialog();
|
|
|
|
|
|
|
|
|
|
this._dialog = new ShellMountPasswordDialog(message, this._createGIcon(iconName), flags);
|
2017-10-31 00:38:18 +00:00
|
|
|
|
this._dialog.connect('response',
|
|
|
|
|
(object, choice, password, remember) => {
|
2012-06-20 21:23:34 +00:00
|
|
|
|
let details = {};
|
|
|
|
|
let response;
|
|
|
|
|
|
|
|
|
|
if (choice == -1) {
|
|
|
|
|
response = Gio.MountOperationResult.ABORTED;
|
|
|
|
|
} else {
|
|
|
|
|
response = Gio.MountOperationResult.HANDLED;
|
|
|
|
|
|
|
|
|
|
let passSave = remember ? Gio.PasswordSave.PERMANENTLY : Gio.PasswordSave.NEVER;
|
|
|
|
|
details['password_save'] = GLib.Variant.new('u', passSave);
|
|
|
|
|
details['password'] = GLib.Variant.new('s', password);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._clearCurrentRequest(response, details);
|
2017-10-31 00:38:18 +00:00
|
|
|
|
});
|
2012-06-20 21:23:34 +00:00
|
|
|
|
this._dialog.open();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* AskQuestion:
|
|
|
|
|
* @id: an opaque ID identifying the object for which the operation is requested
|
|
|
|
|
* The ID must be unique in the context of the calling process.
|
|
|
|
|
* @message: the message to display
|
|
|
|
|
* @icon_name: the name of an icon to display
|
|
|
|
|
* @choices: an array of choice strings
|
|
|
|
|
* GetResponse:
|
|
|
|
|
* @response: a GMountOperationResult
|
|
|
|
|
* @response_details: a dictionary containing the response details as
|
|
|
|
|
* entered by the user. The dictionary MAY contain the following properties:
|
|
|
|
|
* - "choice" -> (i): the chosen answer among the array of strings passed in
|
|
|
|
|
*
|
|
|
|
|
* The dialog will stay visible until clients call the Close() method, or
|
|
|
|
|
* another dialog becomes visible.
|
|
|
|
|
* Calling AskQuestion again for the same id will have the effect to clear
|
|
|
|
|
* update the dialog with the new question.
|
|
|
|
|
*/
|
2017-10-31 00:03:21 +00:00
|
|
|
|
AskQuestionAsync(params, invocation) {
|
2012-06-20 21:23:34 +00:00
|
|
|
|
let [id, message, iconName, choices] = params;
|
|
|
|
|
|
|
|
|
|
if (this._setCurrentRequest(invocation, id, ShellMountOperationType.ASK_QUESTION)) {
|
|
|
|
|
this._dialog.update(message, choices);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._closeDialog();
|
|
|
|
|
|
|
|
|
|
this._dialog = new ShellMountQuestionDialog(this._createGIcon(iconName), message);
|
2017-10-31 00:38:18 +00:00
|
|
|
|
this._dialog.connect('response', (object, choice) => {
|
|
|
|
|
this._clearCurrentRequest(Gio.MountOperationResult.HANDLED,
|
|
|
|
|
{ choice: GLib.Variant.new('i', choice) });
|
|
|
|
|
});
|
2012-06-20 21:23:34 +00:00
|
|
|
|
|
|
|
|
|
this._dialog.update(message, choices);
|
|
|
|
|
this._dialog.open();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* ShowProcesses:
|
|
|
|
|
* @id: an opaque ID identifying the object for which the operation is requested
|
|
|
|
|
* The ID must be unique in the context of the calling process.
|
|
|
|
|
* @message: the message to display
|
|
|
|
|
* @icon_name: the name of an icon to display
|
|
|
|
|
* @application_pids: the PIDs of the applications to display
|
|
|
|
|
* @choices: an array of choice strings
|
|
|
|
|
* @response: a GMountOperationResult
|
|
|
|
|
* @response_details: a dictionary containing the response details as
|
|
|
|
|
* entered by the user. The dictionary MAY contain the following properties:
|
|
|
|
|
* - "choice" -> (i): the chosen answer among the array of strings passed in
|
|
|
|
|
*
|
|
|
|
|
* The dialog will stay visible until clients call the Close() method, or
|
|
|
|
|
* another dialog becomes visible.
|
|
|
|
|
* Calling ShowProcesses again for the same id will have the effect to clear
|
|
|
|
|
* the existing dialog and update it with the new message and the new list
|
|
|
|
|
* of processes.
|
|
|
|
|
*/
|
2017-10-31 00:03:21 +00:00
|
|
|
|
ShowProcessesAsync(params, invocation) {
|
2012-06-20 21:23:34 +00:00
|
|
|
|
let [id, message, iconName, applicationPids, choices] = params;
|
|
|
|
|
|
|
|
|
|
if (this._setCurrentRequest(invocation, id, ShellMountOperationType.SHOW_PROCESSES)) {
|
|
|
|
|
this._dialog.update(message, applicationPids, choices);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._closeDialog();
|
|
|
|
|
|
|
|
|
|
this._dialog = new ShellProcessesDialog(this._createGIcon(iconName));
|
2017-10-31 00:38:18 +00:00
|
|
|
|
this._dialog.connect('response', (object, choice) => {
|
|
|
|
|
let response;
|
|
|
|
|
let details = {};
|
|
|
|
|
|
|
|
|
|
if (choice == -1) {
|
|
|
|
|
response = Gio.MountOperationResult.ABORTED;
|
|
|
|
|
} else {
|
|
|
|
|
response = Gio.MountOperationResult.HANDLED;
|
|
|
|
|
details['choice'] = GLib.Variant.new('i', choice);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._clearCurrentRequest(response, details);
|
|
|
|
|
});
|
2012-06-20 21:23:34 +00:00
|
|
|
|
|
|
|
|
|
this._dialog.update(message, applicationPids, choices);
|
|
|
|
|
this._dialog.open();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Close:
|
|
|
|
|
*
|
|
|
|
|
* Closes a dialog previously opened by AskPassword, AskQuestion or ShowProcesses.
|
|
|
|
|
* If no dialog is open, does nothing.
|
|
|
|
|
*/
|
2017-10-31 00:03:21 +00:00
|
|
|
|
Close(params, invocation) {
|
2012-06-20 21:23:34 +00:00
|
|
|
|
this._clearCurrentRequest(Gio.MountOperationResult.UNHANDLED, {});
|
|
|
|
|
this._closeDialog();
|
|
|
|
|
}
|
|
|
|
|
});
|