shell-screenshot: Only allow one screenshot request at a time per sender
We currently allow infinite number of screenshot requests to be active at the same time, which can "dos" the system and cause OOM. So fail subsequent requests for the same sender when a screenshot operation is already running. https://bugzilla.gnome.org/show_bug.cgi?id=737456
This commit is contained in:
@@ -65,9 +65,41 @@ const ScreenshotService = new Lang.Class({
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreenshotIface, this);
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/Screenshot');
|
||||
|
||||
this._screenShooter = new Map();
|
||||
|
||||
Gio.DBus.session.own_name('org.gnome.Shell.Screenshot', Gio.BusNameOwnerFlags.REPLACE, null, null);
|
||||
},
|
||||
|
||||
_createScreenshot: function(invocation) {
|
||||
let sender = invocation.get_sender();
|
||||
if (this._screenShooter.has(sender)) {
|
||||
invocation.return_value(GLib.Variant.new('(bs)', [false, '']));
|
||||
return null;
|
||||
}
|
||||
|
||||
let shooter = new Shell.Screenshot();
|
||||
shooter._watchNameId =
|
||||
Gio.bus_watch_name(Gio.BusType.SESSION, sender, 0, null,
|
||||
Lang.bind(this, this._onNameVanished));
|
||||
|
||||
this._screenShooter.set(sender, shooter);
|
||||
|
||||
return shooter;
|
||||
},
|
||||
|
||||
_onNameVanished: function(connection, name) {
|
||||
this._removeShooterForSender(name);
|
||||
},
|
||||
|
||||
_removeShooterForSender: function(sender) {
|
||||
let shooter = this._screenShooter.get(sender);
|
||||
if (!shooter)
|
||||
return;
|
||||
|
||||
Gio.bus_unwatch_name(shooter._watchNameId);
|
||||
this._screenShooter.delete(sender);
|
||||
},
|
||||
|
||||
_checkArea: function(x, y, width, height) {
|
||||
return x >= 0 && y >= 0 &&
|
||||
width > 0 && height > 0 &&
|
||||
@@ -76,9 +108,15 @@ const ScreenshotService = new Lang.Class({
|
||||
},
|
||||
|
||||
_onScreenshotComplete: function(obj, result, area, filenameUsed, flash, invocation) {
|
||||
if (flash && result) {
|
||||
let flashspot = new Flashspot(area);
|
||||
flashspot.fire();
|
||||
if (result) {
|
||||
if (flash) {
|
||||
let flashspot = new Flashspot(area);
|
||||
flashspot.fire(Lang.bind(this, function() {
|
||||
this._removeShooterForSender(invocation.get_sender());
|
||||
}));
|
||||
}
|
||||
else
|
||||
this._removeShooterForSender(invocation.get_sender());
|
||||
}
|
||||
|
||||
let retval = GLib.Variant.new('(bs)', [result, filenameUsed]);
|
||||
@@ -112,7 +150,9 @@ const ScreenshotService = new Lang.Class({
|
||||
"Invalid params");
|
||||
return;
|
||||
}
|
||||
let screenshot = new Shell.Screenshot();
|
||||
let screenshot = this._createScreenshot(invocation);
|
||||
if (!screenshot)
|
||||
return;
|
||||
screenshot.screenshot_area (x, y, width, height, filename,
|
||||
Lang.bind(this, this._onScreenshotComplete,
|
||||
flash, invocation));
|
||||
@@ -120,7 +160,9 @@ const ScreenshotService = new Lang.Class({
|
||||
|
||||
ScreenshotWindowAsync : function (params, invocation) {
|
||||
let [include_frame, include_cursor, flash, filename] = params;
|
||||
let screenshot = new Shell.Screenshot();
|
||||
let screenshot = this._createScreenshot(invocation);
|
||||
if (!screenshot)
|
||||
return;
|
||||
screenshot.screenshot_window (include_frame, include_cursor, filename,
|
||||
Lang.bind(this, this._onScreenshotComplete,
|
||||
flash, invocation));
|
||||
@@ -128,7 +170,9 @@ const ScreenshotService = new Lang.Class({
|
||||
|
||||
ScreenshotAsync : function (params, invocation) {
|
||||
let [include_cursor, flash, filename] = params;
|
||||
let screenshot = new Shell.Screenshot();
|
||||
let screenshot = this._createScreenshot(invocation);
|
||||
if (!screenshot)
|
||||
return;
|
||||
screenshot.screenshot(include_cursor, filename,
|
||||
Lang.bind(this, this._onScreenshotComplete,
|
||||
flash, invocation));
|
||||
@@ -302,7 +346,7 @@ const Flashspot = new Lang.Class({
|
||||
this.actor.set_position(area.x, area.y);
|
||||
},
|
||||
|
||||
fire: function() {
|
||||
fire: function(doneCallback) {
|
||||
this.actor.show();
|
||||
this.actor.opacity = 255;
|
||||
Tweener.addTween(this.actor,
|
||||
@@ -310,6 +354,8 @@ const Flashspot = new Lang.Class({
|
||||
time: FLASHSPOT_ANIMATION_OUT_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this, function() {
|
||||
if (doneCallback)
|
||||
doneCallback();
|
||||
this.destroy();
|
||||
})
|
||||
});
|
||||
|
Reference in New Issue
Block a user