Rearchitect the Shell to have a components system

Components are pieces of the shell code that can be added/removed
at runtime, like extension, but are tied more directly to a session
mode. The session polkit agent, the network agent, autorun/automount,
are all components, keyring, recorder and telepathy client are all
now copmonents.

https://bugzilla.gnome.org/show_bug.cgi?id=683156
This commit is contained in:
Jasper St. Pierre 2012-09-02 22:23:50 -03:00
parent ca2e09fe8b
commit 2a800e4ce0
13 changed files with 313 additions and 271 deletions

View File

@ -1,3 +1,4 @@
NULL =
EXTRA_DIST = misc/config.js.in EXTRA_DIST = misc/config.js.in
CLEANFILES = misc/config.js CLEANFILES = misc/config.js
@ -37,8 +38,6 @@ nobase_dist_js_DATA = \
ui/altTab.js \ ui/altTab.js \
ui/appDisplay.js \ ui/appDisplay.js \
ui/appFavorites.js \ ui/appFavorites.js \
ui/automountManager.js \
ui/autorunManager.js \
ui/boxpointer.js \ ui/boxpointer.js \
ui/calendar.js \ ui/calendar.js \
ui/checkBox.js \ ui/checkBox.js \
@ -47,15 +46,14 @@ nobase_dist_js_DATA = \
ui/dateMenu.js \ ui/dateMenu.js \
ui/dnd.js \ ui/dnd.js \
ui/endSessionDialog.js \ ui/endSessionDialog.js \
ui/environment.js \
ui/extensionSystem.js \ ui/extensionSystem.js \
ui/extensionDownloader.js \ ui/extensionDownloader.js \
ui/environment.js \
ui/flashspot.js \ ui/flashspot.js \
ui/ibusCandidatePopup.js\ ui/ibusCandidatePopup.js\
ui/grabHelper.js \ ui/grabHelper.js \
ui/iconGrid.js \ ui/iconGrid.js \
ui/keyboard.js \ ui/keyboard.js \
ui/keyringPrompt.js \
ui/layout.js \ ui/layout.js \
ui/lightbox.js \ ui/lightbox.js \
ui/lookingGlass.js \ ui/lookingGlass.js \
@ -64,7 +62,6 @@ nobase_dist_js_DATA = \
ui/main.js \ ui/main.js \
ui/messageTray.js \ ui/messageTray.js \
ui/modalDialog.js \ ui/modalDialog.js \
ui/networkAgent.js \
ui/sessionMode.js \ ui/sessionMode.js \
ui/shellEntry.js \ ui/shellEntry.js \
ui/shellMountOperation.js \ ui/shellMountOperation.js \
@ -74,7 +71,6 @@ nobase_dist_js_DATA = \
ui/panelMenu.js \ ui/panelMenu.js \
ui/placeDisplay.js \ ui/placeDisplay.js \
ui/pointerWatcher.js \ ui/pointerWatcher.js \
ui/polkitAuthenticationAgent.js \
ui/popupMenu.js \ ui/popupMenu.js \
ui/remoteSearch.js \ ui/remoteSearch.js \
ui/runDialog.js \ ui/runDialog.js \
@ -90,7 +86,6 @@ nobase_dist_js_DATA = \
ui/status/power.js \ ui/status/power.js \
ui/status/volume.js \ ui/status/volume.js \
ui/status/bluetooth.js \ ui/status/bluetooth.js \
ui/telepathyClient.js \
ui/tweener.js \ ui/tweener.js \
ui/unlockDialog.js \ ui/unlockDialog.js \
ui/userMenu.js \ ui/userMenu.js \
@ -102,4 +97,13 @@ nobase_dist_js_DATA = \
ui/workspaceThumbnail.js \ ui/workspaceThumbnail.js \
ui/workspacesView.js \ ui/workspacesView.js \
ui/workspaceSwitcherPopup.js \ ui/workspaceSwitcherPopup.js \
ui/xdndHandler.js ui/xdndHandler.js \
ui/components/__init__.js \
ui/components/autorunManager.js \
ui/components/automountManager.js \
ui/components/networkAgent.js \
ui/components/polkitAgent.js \
ui/components/recorder.js \
ui/components/telepathyClient.js \
ui/components/keyring.js \
$(NULL)

View File

@ -0,0 +1,61 @@
const Lang = imports.lang;
const Main = imports.ui.main;
const ComponentManager = new Lang.Class({
Name: 'ComponentManager',
_init: function() {
this._allComponents = {};
this._enabledComponents = [];
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
this._sessionUpdated();
},
_sessionUpdated: function() {
let newEnabledComponents = Main.sessionMode.components;
newEnabledComponents.filter(Lang.bind(this, function(name) {
return this._enabledComponents.indexOf(name) == -1;
})).forEach(Lang.bind(this, function(name) {
this._enableComponent(name);
}));
this._enabledComponents.filter(Lang.bind(this, function(name) {
return newEnabledComponents.indexOf(name) == -1;
})).forEach(Lang.bind(this, function(name) {
this._disableComponent(name);
}));
this._enabledComponents = newEnabledComponents;
},
_importComponent: function(name) {
let module = imports.ui.components[name];
return module.Component;
},
_ensureComponent: function(name) {
let component = this._allComponents[name];
if (component)
return component;
let constructor = this._importComponent(name);
component = new constructor();
this._allComponents[name] = component;
return component;
},
_enableComponent: function(name) {
let component = this._ensureComponent(name);
component.enable();
},
_disableComponent: function(name) {
let component = this._allComponents[name];
if (component == null)
return;
component.disable();
}
});

View File

@ -34,28 +34,30 @@ const AutomountManager = new Lang.Class({
this._inhibited = false; this._inhibited = false;
this._loginManager = LoginManager.getLoginManager(); this._loginManager = LoginManager.getLoginManager();
Main.screenShield.connect('lock-status-changed', Lang.bind(this, this._lockStatusChanged));
this._volumeMonitor = Gio.VolumeMonitor.get(); this._volumeMonitor = Gio.VolumeMonitor.get();
},
this._volumeMonitor.connect('volume-added', enable: function() {
Lang.bind(this, this._volumeAddedId = this._volumeMonitor.connect('volume-added', Lang.bind(this, this._onVolumeAdded));
this._onVolumeAdded)); this._volumeRemovedId = this._volumeMonitor.connect('volume-removed', Lang.bind(this, this._onVolumeRemoved));
this._volumeMonitor.connect('volume-removed', this._driveConnectedId = this._volumeMonitor.connect('drive-connected', Lang.bind(this, this._onDriveConnected));
Lang.bind(this, this._driveDisconnectedId = this._volumeMonitor.connect('drive-disconnected', Lang.bind(this, this._onDriveDisconnected));
this._onVolumeRemoved)); this._driveEjectButtonId = this._volumeMonitor.connect('drive-eject-button', Lang.bind(this, this._onDriveEjectButton));
this._volumeMonitor.connect('drive-connected',
Lang.bind(this,
this._onDriveConnected));
this._volumeMonitor.connect('drive-disconnected',
Lang.bind(this,
this._onDriveDisconnected));
this._volumeMonitor.connect('drive-eject-button',
Lang.bind(this,
this._onDriveEjectButton));
Mainloop.idle_add(Lang.bind(this, this._startupMountAll)); this._mountAllId = Mainloop.idle_add(Lang.bind(this, this._startupMountAll));
},
disable: function() {
this._volumeMonitor.disconnect(this._volumeAddedId);
this._volumeMonitor.disconnect(this._volumeRemovedId);
this._volumeMonitor.disconnect(this._driveConnectedId);
this._volumeMonitor.disconnect(this._driveDisconnectedId);
this._volumeMonitor.disconnect(this._driveEjectButtonId);
if (this._mountAllId > 0) {
Mainloop.source_remove(this._mountAllId);
this._mountAllId = 0;
}
}, },
_InhibitorsChanged: function(object, senderName, [inhibtor]) { _InhibitorsChanged: function(object, senderName, [inhibtor]) {
@ -68,17 +70,6 @@ const AutomountManager = new Lang.Class({
})); }));
}, },
_lockStatusChanged: function(shield, locked) {
if (!locked) {
this._volumeQueue.forEach(Lang.bind(this, function(volume) {
this._checkAndMountVolume(volume);
}));
}
// clear the queue anyway
this._volumeQueue = [];
},
_startupMountAll: function() { _startupMountAll: function() {
let volumes = this._volumeMonitor.get_volumes(); let volumes = this._volumeMonitor.get_volumes();
volumes.forEach(Lang.bind(this, function(volume) { volumes.forEach(Lang.bind(this, function(volume) {
@ -87,6 +78,7 @@ const AutomountManager = new Lang.Class({
allowAutorun: false }); allowAutorun: false });
})); }));
this._mountAllId = 0;
return false; return false;
}, },
@ -96,9 +88,6 @@ const AutomountManager = new Lang.Class({
if (!this._loginManager.sessionActive) if (!this._loginManager.sessionActive)
return; return;
if (Main.screenShield.locked)
return;
global.play_theme_sound(0, 'device-added-media'); global.play_theme_sound(0, 'device-added-media');
}, },
@ -108,9 +97,6 @@ const AutomountManager = new Lang.Class({
if (!this._loginManager.sessionActive) if (!this._loginManager.sessionActive)
return; return;
if (Main.screenShield.locked)
return;
global.play_theme_sound(0, 'device-removed-media'); global.play_theme_sound(0, 'device-removed-media');
}, },
@ -159,13 +145,6 @@ const AutomountManager = new Lang.Class({
// don't attempt automount // don't attempt automount
if (!this._loginManager.sessionActive) if (!this._loginManager.sessionActive)
return; return;
if (Main.screenShield.locked) {
if (this._volumeQueue.indexOf(volume) == -1)
this._volumeQueue.push(volume);
return;
}
} }
if (this._inhibited) if (this._inhibited)
@ -259,3 +238,4 @@ const AutomountManager = new Lang.Class({
}); });
} }
}); });
const Component = AutomountManager;

View File

@ -147,18 +147,25 @@ const AutorunManager = new Lang.Class({
this._volumeMonitor = Gio.VolumeMonitor.get(); this._volumeMonitor = Gio.VolumeMonitor.get();
this._volumeMonitor.connect('mount-added', this._transDispatcher = new AutorunTransientDispatcher(this);
Lang.bind(this, },
this._onMountAdded));
this._volumeMonitor.connect('mount-removed',
Lang.bind(this,
this._onMountRemoved));
this._transDispatcher = new AutorunTransientDispatcher(); enable: function() {
this._createResidentSource(); this._residentSource = new AutorunResidentSource(this);
this._scanMounts();
this._mountAddedId = this._volumeMonitor.connect('mount-added', Lang.bind(this, this._onMountAdded));
this._mountRemovedId = this._volumeMonitor.connect('mount-removed', Lang.bind(this, this._onMountRemoved));
},
disable: function() {
this._residentSource.destroy();
this._volumeMonitor.disconnect(this._mountAddedId);
this._volumeMonitor.disconnect(this._mountRemovedId);
},
_scanMounts: function() {
let mounts = this._volumeMonitor.get_mounts(); let mounts = this._volumeMonitor.get_mounts();
mounts.forEach(Lang.bind(this, function (mount) { mounts.forEach(Lang.bind(this, function (mount) {
let discoverer = new ContentTypeDiscoverer(Lang.bind (this, let discoverer = new ContentTypeDiscoverer(Lang.bind (this,
function (mount, apps) { function (mount, apps) {
@ -169,13 +176,6 @@ const AutorunManager = new Lang.Class({
})); }));
}, },
_createResidentSource: function() {
this._residentSource = new AutorunResidentSource();
this._residentSource.connect('destroy',
Lang.bind(this,
this._createResidentSource));
},
_onMountAdded: function(monitor, mount) { _onMountAdded: function(monitor, mount) {
// don't do anything if our session is not the currently // don't do anything if our session is not the currently
// active one // active one
@ -260,13 +260,14 @@ const AutorunResidentSource = new Lang.Class({
Name: 'AutorunResidentSource', Name: 'AutorunResidentSource',
Extends: MessageTray.Source, Extends: MessageTray.Source,
_init: function() { _init: function(manager) {
this.parent(_("Removable Devices"), 'media-removable'); this.parent(_("Removable Devices"), 'media-removable');
this.showInLockScreen = false; this.showInLockScreen = false;
this._mounts = []; this._mounts = [];
this._notification = new AutorunResidentNotification(this); this._notification = new AutorunResidentNotification(this._manager, this);
this._manager = manager;
}, },
addMount: function(mount, apps) { addMount: function(mount, apps) {
@ -316,7 +317,7 @@ const AutorunResidentNotification = new Lang.Class({
Name: 'AutorunResidentNotification', Name: 'AutorunResidentNotification',
Extends: MessageTray.Notification, Extends: MessageTray.Notification,
_init: function(source) { _init: function(manager, source) {
this.parent(source, source.title, null, { customContent: true }); this.parent(source, source.title, null, { customContent: true });
// set the notification as resident // set the notification as resident
@ -324,6 +325,7 @@ const AutorunResidentNotification = new Lang.Class({
this._layout = new St.BoxLayout ({ style_class: 'hotplug-resident-box', this._layout = new St.BoxLayout ({ style_class: 'hotplug-resident-box',
vertical: true }); vertical: true });
this._manager = manager;
this.addActor(this._layout, this.addActor(this._layout,
{ x_expand: true, { x_expand: true,
@ -382,11 +384,11 @@ const AutorunResidentNotification = new Lang.Class({
// now connect signals // now connect signals
mountButton.connect('clicked', Lang.bind(this, function(actor, event) { mountButton.connect('clicked', Lang.bind(this, function(actor, event) {
startAppForMount(apps[0], mount); this._manager.startAppForMount(apps[0], mount);
})); }));
ejectButton.connect('clicked', Lang.bind(this, function() { ejectButton.connect('clicked', Lang.bind(this, function() {
Main.autorunManager.ejectMount(mount); this._manager.ejectMount(mount);
})); }));
return item; return item;
@ -396,7 +398,8 @@ const AutorunResidentNotification = new Lang.Class({
const AutorunTransientDispatcher = new Lang.Class({ const AutorunTransientDispatcher = new Lang.Class({
Name: 'AutorunTransientDispatcher', Name: 'AutorunTransientDispatcher',
_init: function() { _init: function(manager) {
this._manager = manager;
this._sources = []; this._sources = [];
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA }); this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
}, },
@ -439,7 +442,7 @@ const AutorunTransientDispatcher = new Lang.Class({
return; return;
// add a new source // add a new source
this._sources.push(new AutorunTransientSource(mount, apps)); this._sources.push(new AutorunTransientSource(this._manager, mount, apps));
}, },
addMount: function(mount, apps, contentTypes) { addMount: function(mount, apps, contentTypes) {
@ -492,13 +495,14 @@ const AutorunTransientSource = new Lang.Class({
Name: 'AutorunTransientSource', Name: 'AutorunTransientSource',
Extends: MessageTray.Source, Extends: MessageTray.Source,
_init: function(mount, apps) { _init: function(manager, mount, apps) {
this._manager = manager;
this.mount = mount; this.mount = mount;
this.apps = apps; this.apps = apps;
this.parent(mount.get_name()); this.parent(mount.get_name());
this._notification = new AutorunTransientNotification(this); this._notification = new AutorunTransientNotification(this._manager, this);
// add ourselves as a source, and popup the notification // add ourselves as a source, and popup the notification
Main.messageTray.add(this); Main.messageTray.add(this);
@ -515,9 +519,10 @@ const AutorunTransientNotification = new Lang.Class({
Name: 'AutorunTransientNotification', Name: 'AutorunTransientNotification',
Extends: MessageTray.Notification, Extends: MessageTray.Notification,
_init: function(source) { _init: function(manager, source) {
this.parent(source, source.title, null, { customContent: true }); this.parent(source, source.title, null, { customContent: true });
this._manager = manager;
this._box = new St.BoxLayout({ style_class: 'hotplug-transient-box', this._box = new St.BoxLayout({ style_class: 'hotplug-transient-box',
vertical: true }); vertical: true });
this.addActor(this._box); this.addActor(this._box);
@ -586,10 +591,11 @@ const AutorunTransientNotification = new Lang.Class({
style_class: 'hotplug-notification-item' }); style_class: 'hotplug-notification-item' });
button.connect('clicked', Lang.bind(this, function() { button.connect('clicked', Lang.bind(this, function() {
Main.autorunManager.ejectMount(this._mount); this._manager.ejectMount(this._mount);
})); }));
return button; return button;
} }
}); });
const Component = AutorunManager;

View File

@ -192,23 +192,35 @@ const KeyringDialog = new Lang.Class({
}, },
_onContinueButton: function() { _onContinueButton: function() {
this.prompt.complete() this.prompt.complete();
}, },
_onCancelButton: function() { _onCancelButton: function() {
this.prompt.cancel() this.prompt.cancel();
}, },
}); });
function init() { const KeyringPrompter = new Lang.Class({
prompter = new Gcr.SystemPrompter(); Name: 'KeyringPrompter',
prompter.connect('new-prompt', function(prompter) {
let dialog = new KeyringDialog();
return dialog.prompt;
});
let connection = Gio.DBus.session; _init: function() {
prompter.register(connection); this._prompter = new Gcr.SystemPrompter();
Gio.bus_own_name_on_connection (connection, 'org.gnome.keyring.SystemPrompter', this._prompter.connect('new-prompt', function(prompter) {
Gio.BusNameOwnerFlags.REPLACE, null, null); let dialog = new KeyringDialog();
} return dialog.prompt;
});
this._dbusId = null;
},
enable: function() {
this._prompter.register(Gio.DBus.session);
this._dbusId = Gio.DBus.session.own_name('org.gnome.keyring.SystemPrompter',
Gio.BusNameOwnerFlags.REPLACE, null, null);
},
disable: function() {
Gio.DBus.session.unown_name(this._dbusId);
}
});
const Component = KeyringPrompter;

View File

@ -1,23 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/*
* Copyright 2011 Giovanni Campagna <scampa.giovanni@gmail.com>
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
*/
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
@ -603,7 +584,7 @@ const NetworkAgent = new Lang.Class({
Name: 'NetworkAgent', Name: 'NetworkAgent',
_init: function() { _init: function() {
this._native = new Shell.NetworkAgent({ auto_register: true, this._native = new Shell.NetworkAgent({ auto_register: false,
identifier: 'org.gnome.Shell.NetworkAgent' }); identifier: 'org.gnome.Shell.NetworkAgent' });
this._dialogs = { }; this._dialogs = { };
@ -613,6 +594,14 @@ const NetworkAgent = new Lang.Class({
this._native.connect('cancel-request', Lang.bind(this, this._cancelRequest)); this._native.connect('cancel-request', Lang.bind(this, this._cancelRequest));
}, },
enable: function() {
this._native.register();
},
disable: function() {
this._native.unregister();
},
_newRequest: function(agent, requestId, connection, settingName, hints, flags) { _newRequest: function(agent, requestId, connection, settingName, hints, flags) {
if (settingName == 'vpn') { if (settingName == 'vpn') {
this._vpnRequest(requestId, connection, hints, flags); this._vpnRequest(requestId, connection, hints, flags);
@ -702,3 +691,4 @@ const NetworkAgent = new Lang.Class({
} }
} }
}); });
const Component = NetworkAgent;

View File

@ -1,24 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/*
* Copyright 2010 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: David Zeuthen <davidz@redhat.com>
*/
const Lang = imports.lang; const Lang = imports.lang;
const Signals = imports.signals; const Signals = imports.signals;
@ -33,6 +13,7 @@ const Mainloop = imports.mainloop;
const Polkit = imports.gi.Polkit; const Polkit = imports.gi.Polkit;
const PolkitAgent = imports.gi.PolkitAgent; const PolkitAgent = imports.gi.PolkitAgent;
const Components = imports.ui.components;
const ModalDialog = imports.ui.modalDialog; const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry; const ShellEntry = imports.ui.shellEntry;
const UserMenu = imports.ui.userMenu; const UserMenu = imports.ui.userMenu;
@ -336,11 +317,20 @@ const AuthenticationAgent = new Lang.Class({
Name: 'AuthenticationAgent', Name: 'AuthenticationAgent',
_init: function() { _init: function() {
this._currentDialog = null;
this._isCompleting = false;
this._handle = null;
this._native = new Shell.PolkitAuthenticationAgent(); this._native = new Shell.PolkitAuthenticationAgent();
this._native.connect('initiate', Lang.bind(this, this._onInitiate)); this._native.connect('initiate', Lang.bind(this, this._onInitiate));
this._native.connect('cancel', Lang.bind(this, this._onCancel)); this._native.connect('cancel', Lang.bind(this, this._onCancel));
this._currentDialog = null; },
this._isCompleting = false;
enable: function() {
this._native.register();
},
disable: function() {
this._native.unregister();
}, },
_onInitiate: function(nativeAgent, actionId, message, iconName, cookie, userNames) { _onInitiate: function(nativeAgent, actionId, message, iconName, cookie, userNames) {
@ -398,6 +388,4 @@ const AuthenticationAgent = new Lang.Class({
} }
}); });
function init() { const Component = AuthenticationAgent;
let agent = new AuthenticationAgent();
}

View File

@ -0,0 +1,58 @@
const Lang = imports.lang;
const Gio = imports.gi.Gio;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Recorder = new Lang.Class({
Name: 'Recorder',
_init: function() {
this._recorderSettings = new Gio.Settings({ schema: 'org.gnome.shell.recorder' });
this._desktopLockdownSettings = new Gio.Settings({ schema: 'org.gnome.desktop.lockdown' });
this._bindingSettings = new Gio.Settings({ schema: 'org.gnome.shell.keybindings' });
this._recorder = null;
},
enable: function() {
global.display.add_keybinding('toggle-recording',
this._bindingSettings,
Meta.KeyBindingFlags.NONE, Lang.bind(this, this._toggleRecorder));
},
disable: function() {
global.display.remove_keybinding('toggle-recording');
},
_ensureRecorder: function() {
if (this._recorder == null)
this._recorder = new Shell.Recorder({ stage: global.stage });
return this._recorder;
},
_toggleRecorder: function() {
let recorder = this._ensureRecorder();
if (recorder.is_recording()) {
recorder.close();
Meta.enable_unredirect_for_screen(global.screen);
} else if (!desktopLockdownSettings.get_boolean('disable-save-to-disk')) {
// read the parameters from GSettings always in case they have changed
recorder.set_framerate(recorderSettings.get_int('framerate'));
/* Translators: this is a filename used for screencast recording */
// xgettext:no-c-format
recorder.set_filename(_("Screencast from %d %t") + '.' + recorderSettings.get_string('file-extension'));
let pipeline = recorderSettings.get_string('pipeline');
if (!pipeline.match(/^\s*$/))
recorder.set_pipeline(pipeline);
else
recorder.set_pipeline(null);
Meta.disable_unredirect_for_screen(global.screen);
recorder.record();
}
}
});
const Component = Recorder;

View File

@ -63,10 +63,10 @@ function makeMessageFromTplEvent(event) {
}; };
} }
const Client = new Lang.Class({ const TelepathyClient = new Lang.Class({
Name: 'Client', Name: 'TelepathyClient',
_init : function() { _init: function() {
// channel path -> ChatSource // channel path -> ChatSource
this._chatSources = {}; this._chatSources = {};
this._chatState = Tp.ChannelChatState.ACTIVE; this._chatState = Tp.ChannelChatState.ACTIVE;
@ -89,9 +89,9 @@ const Client = new Lang.Class({
// channel matching its filters is detected. // channel matching its filters is detected.
// The second argument, recover, means _observeChannels will be run // The second argument, recover, means _observeChannels will be run
// for any existing channel as well. // for any existing channel as well.
this._tpClient = new Shell.TpClient({ 'account-manager': this._accountManager, this._tpClient = new Shell.TpClient({ name: 'GnomeShell',
'name': 'GnomeShell', account_manager: this._accountManager,
'uniquify-name': true }) uniquify_name: true });
this._tpClient.set_observe_channels_func( this._tpClient.set_observe_channels_func(
Lang.bind(this, this._observeChannels)); Lang.bind(this, this._observeChannels));
this._tpClient.set_approve_channels_func( this._tpClient.set_approve_channels_func(
@ -99,6 +99,10 @@ const Client = new Lang.Class({
this._tpClient.set_handle_channels_func( this._tpClient.set_handle_channels_func(
Lang.bind(this, this._handleChannels)); Lang.bind(this, this._handleChannels));
// Watch subscription requests and connection errors
this._subscriptionSource = null;
this._accountSource = null;
// Workaround for gjs not supporting GPtrArray in signals. // Workaround for gjs not supporting GPtrArray in signals.
// See BGO bug #653941 for context. // See BGO bug #653941 for context.
this._tpClient.set_contact_list_changed_func( this._tpClient.set_contact_list_changed_func(
@ -108,21 +112,26 @@ const Client = new Lang.Class({
// needed // needed
this._tpClient.set_delegated_channels_callback( this._tpClient.set_delegated_channels_callback(
Lang.bind(this, this._delegatedChannelsCb)); Lang.bind(this, this._delegatedChannelsCb));
},
enable: function() {
try { try {
this._tpClient.register(); this._tpClient.register();
} catch (e) { } catch (e) {
throw new Error('Couldn\'t register Telepathy client. Error: \n' + e); throw new Error('Couldn\'t register Telepathy client. Error: \n' + e);
} }
// Watch subscription requests and connection errors this._accountManagerValidityChangedId = this._accountManager.connect('account-validity-changed',
this._subscriptionSource = null; Lang.bind(this, this._accountValidityChanged));
this._accountSource = null;
this._accountManager.connect('account-validity-changed', if (!this._accountManager.is_prepared(Tp.AccountManager.get_feature_quark_core()))
Lang.bind(this, this._accountValidityChanged)); this._accountManager.prepare_async(null, Lang.bind(this, this._accountManagerPrepared));
},
this._accountManager.prepare_async(null, Lang.bind(this, this._accountManagerPrepared)); disable: function() {
this._tpClient.unregister();
this._accountManager.disconnect(this._accountManagerValidityChangedId);
this._accountManagerValidityChangedId = 0;
}, },
_observeChannels: function(observer, account, conn, channels, _observeChannels: function(observer, account, conn, channels,
@ -1399,3 +1408,4 @@ const AccountNotification = new Lang.Class({
this.parent(); this.parent();
} }
}); });
const Component = TelepathyClient;

View File

@ -10,12 +10,9 @@ const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const St = imports.gi.St; const St = imports.gi.St;
const AutomountManager = imports.ui.automountManager; const Components = imports.ui.components;
const AutorunManager = imports.ui.autorunManager;
const CtrlAltTab = imports.ui.ctrlAltTab; const CtrlAltTab = imports.ui.ctrlAltTab;
const EndSessionDialog = imports.ui.endSessionDialog; const EndSessionDialog = imports.ui.endSessionDialog;
const PolkitAuthenticationAgent = imports.ui.polkitAuthenticationAgent;
const KeyringPrompt = imports.ui.keyringPrompt;
const Environment = imports.ui.environment; const Environment = imports.ui.environment;
const ExtensionSystem = imports.ui.extensionSystem; const ExtensionSystem = imports.ui.extensionSystem;
const ExtensionDownloader = imports.ui.extensionDownloader; const ExtensionDownloader = imports.ui.extensionDownloader;
@ -27,7 +24,6 @@ const PlaceDisplay = imports.ui.placeDisplay;
const RunDialog = imports.ui.runDialog; const RunDialog = imports.ui.runDialog;
const Layout = imports.ui.layout; const Layout = imports.ui.layout;
const LookingGlass = imports.ui.lookingGlass; const LookingGlass = imports.ui.lookingGlass;
const NetworkAgent = imports.ui.networkAgent;
const NotificationDaemon = imports.ui.notificationDaemon; const NotificationDaemon = imports.ui.notificationDaemon;
const WindowAttentionHandler = imports.ui.windowAttentionHandler; const WindowAttentionHandler = imports.ui.windowAttentionHandler;
const ScreenShield = imports.ui.screenShield; const ScreenShield = imports.ui.screenShield;
@ -35,7 +31,6 @@ const Scripting = imports.ui.scripting;
const SessionMode = imports.ui.sessionMode; const SessionMode = imports.ui.sessionMode;
const ShellDBus = imports.ui.shellDBus; const ShellDBus = imports.ui.shellDBus;
const ShellMountOperation = imports.ui.shellMountOperation; const ShellMountOperation = imports.ui.shellMountOperation;
const TelepathyClient = imports.ui.telepathyClient;
const UnlockDialog = imports.ui.unlockDialog; const UnlockDialog = imports.ui.unlockDialog;
const WindowManager = imports.ui.windowManager; const WindowManager = imports.ui.windowManager;
const Magnifier = imports.ui.magnifier; const Magnifier = imports.ui.magnifier;
@ -45,8 +40,7 @@ const Util = imports.misc.util;
const OVERRIDES_SCHEMA = 'org.gnome.shell.overrides'; const OVERRIDES_SCHEMA = 'org.gnome.shell.overrides';
const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2266bbff); const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2266bbff);
let automountManager = null; let componentManager = null;
let autorunManager = null;
let panel = null; let panel = null;
let overview = null; let overview = null;
let runDialog = null; let runDialog = null;
@ -56,9 +50,7 @@ let messageTray = null;
let screenShield = null; let screenShield = null;
let notificationDaemon = null; let notificationDaemon = null;
let windowAttentionHandler = null; let windowAttentionHandler = null;
let telepathyClient = null;
let ctrlAltTabManager = null; let ctrlAltTabManager = null;
let recorder = null;
let sessionMode = null; let sessionMode = null;
let shellDBusService = null; let shellDBusService = null;
let shellMountOpDBusService = null; let shellMountOpDBusService = null;
@ -70,7 +62,6 @@ let magnifier = null;
let xdndHandler = null; let xdndHandler = null;
let keyboard = null; let keyboard = null;
let layoutManager = null; let layoutManager = null;
let networkAgent = null;
let _startDate; let _startDate;
let _defaultCssStylesheet = null; let _defaultCssStylesheet = null;
let _cssStylesheet = null; let _cssStylesheet = null;
@ -78,19 +69,6 @@ let _overridesSettings = null;
let background = null; let background = null;
function createUserSession() {
telepathyClient = new TelepathyClient.Client();
automountManager = new AutomountManager.AutomountManager();
autorunManager = new AutorunManager.AutorunManager();
networkAgent = new NetworkAgent.NetworkAgent();
_initRecorder();
}
function createGDMSession() {
screenShield.showDialog();
}
function createGDMLoginDialog(parentActor) { function createGDMLoginDialog(parentActor) {
// We do this this here instead of at the top to prevent GDM // We do this this here instead of at the top to prevent GDM
// related code from getting loaded in normal user sessions // related code from getting loaded in normal user sessions
@ -105,47 +83,8 @@ function createSessionUnlockDialog(parentActor) {
return [dialog, false]; return [dialog, false];
} }
function createInitialSetupSession() {
networkAgent = new NetworkAgent.NetworkAgent();
}
function _initRecorder() {
let recorderSettings = new Gio.Settings({ schema: 'org.gnome.shell.recorder' });
let desktopLockdownSettings = new Gio.Settings({ schema: 'org.gnome.desktop.lockdown' });
let bindingSettings = new Gio.Settings({ schema: 'org.gnome.shell.keybindings' });
global.display.add_keybinding('toggle-recording',
bindingSettings,
Meta.KeyBindingFlags.NONE, function() {
if (recorder == null) {
recorder = new Shell.Recorder({ stage: global.stage });
}
if (recorder.is_recording()) {
recorder.close();
Meta.enable_unredirect_for_screen(global.screen);
} else if (!desktopLockdownSettings.get_boolean('disable-save-to-disk')) {
// read the parameters from GSettings always in case they have changed
recorder.set_framerate(recorderSettings.get_int('framerate'));
/* Translators: this is a filename used for screencast recording */
// xgettext:no-c-format
recorder.set_filename(_("Screencast from %d %t") + '.' + recorderSettings.get_string('file-extension'));
let pipeline = recorderSettings.get_string('pipeline');
if (!pipeline.match(/^\s*$/))
recorder.set_pipeline(pipeline);
else
recorder.set_pipeline(null);
Meta.disable_unredirect_for_screen(global.screen);
recorder.record();
}
});
}
function _sessionUpdated() { function _sessionUpdated() {
Meta.keybindings_set_custom_handler('panel-run-dialog', sessionMode.hasRunDialog ? openRunDialog : null); Meta.keybindings_set_custom_handler('panel-run-dialog', sessionMode.hasRunDialog ? openRunDialog : null);
loadTheme();
} }
function start() { function start() {
@ -219,8 +158,7 @@ function start() {
keyboard = new Keyboard.Keyboard(); keyboard = new Keyboard.Keyboard();
notificationDaemon = new NotificationDaemon.NotificationDaemon(); notificationDaemon = new NotificationDaemon.NotificationDaemon();
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler(); windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
componentManager = new Components.ComponentManager();
sessionMode.createSession();
layoutManager.init(); layoutManager.init();
keyboard.init(); keyboard.init();
@ -238,12 +176,6 @@ function start() {
// initiate logouts. // initiate logouts.
EndSessionDialog.init(); EndSessionDialog.init();
// Attempt to become a PolicyKit authentication agent
PolkitAuthenticationAgent.init()
// Become a prompter for gnome keyring
KeyringPrompt.init();
_startDate = new Date(); _startDate = new Date();
global.stage.connect('captured-event', _globalKeyPressHandler); global.stage.connect('captured-event', _globalKeyPressHandler);

View File

@ -17,8 +17,8 @@ const _modes = {
hasRunDialog: false, hasRunDialog: false,
hasWorkspaces: false, hasWorkspaces: false,
hasWindows: false, hasWindows: false,
createSession: Main.createGDMSession,
createUnlockDialog: Main.createGDMLoginDialog, createUnlockDialog: Main.createGDMLoginDialog,
components: [],
panel: { panel: {
left: [], left: [],
center: ['dateMenu'], center: ['dateMenu'],
@ -36,6 +36,7 @@ const _modes = {
hasRunDialog: false, hasRunDialog: false,
hasWorkspaces: false, hasWorkspaces: false,
hasWindows: false, hasWindows: false,
components: ['networkAgent', 'polkitAgent', 'telepathyClient'],
panel: { panel: {
left: ['userMenu'], left: ['userMenu'],
center: [], center: [],
@ -50,7 +51,7 @@ const _modes = {
allowKeybindingsWhenModal: false, allowKeybindingsWhenModal: false,
hasRunDialog: false, hasRunDialog: false,
hasWorkspaces: false, hasWorkspaces: false,
createSession: Main.createInitialSetupSession, components: ['keyring'],
panel: { panel: {
left: [], left: [],
center: ['dateMenu'], center: ['dateMenu'],
@ -66,8 +67,9 @@ const _modes = {
hasRunDialog: true, hasRunDialog: true,
hasWorkspaces: true, hasWorkspaces: true,
hasWindows: true, hasWindows: true,
createSession: Main.createUserSession,
createUnlockDialog: Main.createSessionUnlockDialog, createUnlockDialog: Main.createSessionUnlockDialog,
components: ['networkAgent', 'polkitAgent', 'telepathyClient',
'keyring', 'recorder', 'autorunManager', 'automountManager'],
panel: { panel: {
left: ['activities', 'appMenu'], left: ['activities', 'appMenu'],
center: ['dateMenu'], center: ['dateMenu'],
@ -112,8 +114,6 @@ const SessionMode = new Lang.Class({
let params = _modes[this.currentMode]; let params = _modes[this.currentMode];
params = Params.parse(params, _modes[DEFAULT_MODE]); params = Params.parse(params, _modes[DEFAULT_MODE]);
this._createSession = params.createSession;
delete params.createSession;
this._createUnlockDialog = params.createUnlockDialog; this._createUnlockDialog = params.createUnlockDialog;
delete params.createUnlockDialog; delete params.createUnlockDialog;
@ -121,11 +121,6 @@ const SessionMode = new Lang.Class({
this.emit('updated'); this.emit('updated');
}, },
createSession: function() {
if (this._createSession)
this._createSession();
},
createUnlockDialog: function() { createUnlockDialog: function() {
if (this._createUnlockDialog) if (this._createUnlockDialog)
return this._createUnlockDialog.apply(this, arguments); return this._createUnlockDialog.apply(this, arguments);

View File

@ -62,8 +62,9 @@ struct _ShellPolkitAuthenticationAgent {
PolkitAgentListener parent_instance; PolkitAgentListener parent_instance;
GList *scheduled_requests; GList *scheduled_requests;
AuthRequest *current_request; AuthRequest *current_request;
gpointer handle;
}; };
/* Signals */ /* Signals */
@ -93,55 +94,40 @@ static gboolean initiate_authentication_finish (PolkitAgentListener *listener,
GAsyncResult *res, GAsyncResult *res,
GError **error); GError **error);
static void void
shell_polkit_authentication_agent_init (ShellPolkitAuthenticationAgent *agent) shell_polkit_authentication_agent_init (ShellPolkitAuthenticationAgent *agent)
{ {
gpointer handle; }
void
shell_polkit_authentication_agent_register (ShellPolkitAuthenticationAgent *agent,
GError **error_out)
{
GError *error = NULL;
PolkitSubject *subject; PolkitSubject *subject;
GError *error;
subject = NULL;
error = NULL;
subject = polkit_unix_session_new_for_process_sync (getpid (), subject = polkit_unix_session_new_for_process_sync (getpid (),
NULL, /* GCancellable* */ NULL, /* GCancellable* */
&error); &error);
if (subject == NULL) if (subject == NULL)
{ {
if (error) /* polkit version 104 and older don't properly set error on failure */ if (error == NULL) /* polkit version 104 and older don't properly set error on failure */
{ error = g_error_new (POLKIT_ERROR, POLKIT_ERROR_FAILED,
g_warning ("Error getting session for the process we are in: %s (%s %d)", "PolKit failed to properly get our session");
error->message,
g_quark_to_string (error->domain),
error->code);
g_error_free (error);
}
else
{
g_warning ("Error getting session for the process we are in");
}
goto out; goto out;
} }
handle = polkit_agent_listener_register (POLKIT_AGENT_LISTENER (agent), agent->handle = polkit_agent_listener_register (POLKIT_AGENT_LISTENER (agent),
POLKIT_AGENT_REGISTER_FLAGS_NONE, POLKIT_AGENT_REGISTER_FLAGS_NONE,
subject, subject,
NULL, /* use default object path */ NULL, /* use default object path */
NULL, /* GCancellable */ NULL, /* GCancellable */
&error); &error);
if (handle == NULL)
{
g_warning ("Error registering polkit authentication agent: %s (%s %d)",
error->message,
g_quark_to_string (error->domain),
error->code);
g_error_free (error);
goto out;
}
/* We don't need to register so skip saving handle */
out: out:
if (error != NULL)
g_propagate_error (error_out, error);
if (subject != NULL) if (subject != NULL)
g_object_unref (subject); g_object_unref (subject);
} }
@ -149,12 +135,8 @@ shell_polkit_authentication_agent_init (ShellPolkitAuthenticationAgent *agent)
static void static void
shell_polkit_authentication_agent_finalize (GObject *object) shell_polkit_authentication_agent_finalize (GObject *object)
{ {
/* ShellPolkitAuthenticationAgent *agent = SHELL_POLKIT_AUTHENTICATION_AGENT (object); */ ShellPolkitAuthenticationAgent *agent = SHELL_POLKIT_AUTHENTICATION_AGENT (object);
shell_polkit_authentication_agent_unregister (agent);
/* Specifically left empty since the object stays alive forever - if code
* is reused it would need to free outstanding requests etc.
*/
G_OBJECT_CLASS (shell_polkit_authentication_agent_parent_class)->finalize (object); G_OBJECT_CLASS (shell_polkit_authentication_agent_parent_class)->finalize (object);
} }
@ -325,6 +307,27 @@ on_request_cancelled (GCancellable *cancellable,
g_idle_add (handle_cancelled_in_idle, request); g_idle_add (handle_cancelled_in_idle, request);
} }
static void
auth_request_dismiss (AuthRequest *request)
{
auth_request_complete (request, TRUE);
}
void
shell_polkit_authentication_agent_unregister (ShellPolkitAuthenticationAgent *agent)
{
if (agent->scheduled_requests != NULL)
{
g_list_foreach (agent->scheduled_requests, (GFunc)auth_request_dismiss, NULL);
agent->scheduled_requests = NULL;
}
if (agent->current_request != NULL)
auth_request_dismiss (agent->current_request);
polkit_agent_listener_unregister (agent->handle);
agent->handle = NULL;
}
static void maybe_process_next_request (ShellPolkitAuthenticationAgent *agent); static void maybe_process_next_request (ShellPolkitAuthenticationAgent *agent);
static void static void

View File

@ -27,6 +27,9 @@ GType shell_polkit_authentication_agent_get_type (void
ShellPolkitAuthenticationAgent *shell_polkit_authentication_agent_new (void); ShellPolkitAuthenticationAgent *shell_polkit_authentication_agent_new (void);
void shell_polkit_authentication_agent_complete (ShellPolkitAuthenticationAgent *agent, void shell_polkit_authentication_agent_complete (ShellPolkitAuthenticationAgent *agent,
gboolean dismissed); gboolean dismissed);
void shell_polkit_authentication_agent_register (ShellPolkitAuthenticationAgent *agent,
GError **error_out);
void shell_polkit_authentication_agent_unregister (ShellPolkitAuthenticationAgent *agent);
G_END_DECLS G_END_DECLS