mirror of
https://github.com/edu4rdshl/Strata.git
synced 2026-07-17 23:24:46 +00:00
fix: extension lifecycle leaks, image allowlist, generic image label
Audit fixes for the extension: - Track and disconnect the changed::excluded-apps GSettings handler in disable() (it was the one connection whose id was never captured). - Track the _stopDaemon 1.5s force-kill timer and cancel any leftover on enable(), so the source can't outlive a disable->enable cycle. - Guard the exclusion-path delete with _proxy?.DeleteItemAsync. - Mirror the daemon's image allowlist (drop avif/svg) in _pickMime. - Show a generic "Image" label for all image rows instead of singling out PNG; the thumbnail identifies the image and the on-clipboard format (often PNG even for a copied GIF/WebP) is an implementation detail. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
e7b0392d92
commit
332ec4064a
2 changed files with 21 additions and 7 deletions
|
|
@ -62,10 +62,16 @@ export default class StrataExtension extends Extension {
|
|||
enable() {
|
||||
this._shuttingDown = false;
|
||||
this._daemonRestartAttempts = 0;
|
||||
// Cancel any pending force-kill timer left over from a previous disable
|
||||
// (enable→disable→enable within 1.5s) so it can't outlive this cycle.
|
||||
if (this._daemonKillTimerId) {
|
||||
GLib.Source.remove(this._daemonKillTimerId);
|
||||
this._daemonKillTimerId = null;
|
||||
}
|
||||
|
||||
this._settings = this.getSettings();
|
||||
this._excludedApps = this._settings.get_strv('excluded-apps');
|
||||
this._settings.connect('changed::excluded-apps', () => {
|
||||
this._excludedAppsChangedId = this._settings.connect('changed::excluded-apps', () => {
|
||||
this._excludedApps = this._settings.get_strv('excluded-apps');
|
||||
});
|
||||
|
||||
|
|
@ -119,6 +125,10 @@ export default class StrataExtension extends Extension {
|
|||
for (const id of this._configChangedIds) this._settings.disconnect(id);
|
||||
this._configChangedIds = null;
|
||||
}
|
||||
if (this._excludedAppsChangedId && this._settings) {
|
||||
this._settings.disconnect(this._excludedAppsChangedId);
|
||||
this._excludedAppsChangedId = null;
|
||||
}
|
||||
this._panel?.destroy();
|
||||
this._panel = null;
|
||||
this._indicator?.destroy();
|
||||
|
|
@ -229,8 +239,7 @@ export default class StrataExtension extends Extension {
|
|||
const PREFERRED = [
|
||||
// Raster images (size-capped at MAX_IMAGE).
|
||||
'image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/webp',
|
||||
'image/bmp', 'image/tiff', 'image/avif', 'image/x-icon',
|
||||
'image/svg+xml',
|
||||
'image/bmp', 'image/tiff', 'image/x-icon',
|
||||
// Plain text (UTF-8 preferred, then locale, then X11 legacy aliases).
|
||||
// Ranked above rich-text so editors that expose both text/plain and
|
||||
// text/html give us raw source, not styled markup.
|
||||
|
|
@ -374,8 +383,10 @@ export default class StrataExtension extends Extension {
|
|||
// Graceful shutdown via D-Bus first.
|
||||
this._proxy?.ShutdownRemote(() => {});
|
||||
} catch (_) {}
|
||||
// Give it 1.5s then force-terminate.
|
||||
GLib.timeout_add(GLib.PRIORITY_LOW, 1500, () => {
|
||||
// Give it 1.5s then force-terminate. Track the source so a re-enable
|
||||
// within that window can cancel it (see enable()).
|
||||
this._daemonKillTimerId = GLib.timeout_add(GLib.PRIORITY_LOW, 1500, () => {
|
||||
this._daemonKillTimerId = null;
|
||||
try { daemonToStop.send_signal(15); } catch (_) {} // SIGTERM
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
|
|
@ -532,7 +543,7 @@ export default class StrataExtension extends Extension {
|
|||
// Exclusion check - no clipboard I/O, just string comparison.
|
||||
if (this._isExcluded(this._currentFocusedApp)) {
|
||||
try {
|
||||
await this._proxy.DeleteItemAsync(id);
|
||||
await this._proxy?.DeleteItemAsync(id);
|
||||
} catch (e) {
|
||||
// ignore - item may already be gone
|
||||
}
|
||||
|
|
|
|||
|
|
@ -224,7 +224,10 @@ export const ClipboardItem = GObject.registerClass({
|
|||
let subText = '';
|
||||
|
||||
if (mimeType.startsWith('image/')) {
|
||||
mainText = mimeType === 'image/png' ? 'PNG image' : 'Image';
|
||||
// Generic label - the thumbnail identifies the image, and the
|
||||
// on-clipboard format (often PNG even for a copied GIF/WebP) is an
|
||||
// implementation detail that misleads more than it informs.
|
||||
mainText = 'Image';
|
||||
} else if (isUrl(preview)) {
|
||||
mainText = preview.trim();
|
||||
try {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue