| Server IP : 85.112.90.236 / Your IP : 192.168.1.26 Web Server : Apache System : Linux 85-112-90-236.cprapid.com 6.12.0-211.7.3.el10_2.x86_64 #1 SMP PREEMPT_DYNAMIC Tue May 19 12:46:58 EDT 2026 x86_64 User : ftechme ( 1002) PHP Version : 8.2.32 Disable Function : exec,passthru,shell_exec,system MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /usr/share/gnome-shell/ |
Upload File : |
GVariant � (
ε�� � v � 3 ��$0 3 L < @ ,\ @ v H �H� L $ KP� $ L ( , 6�| , v @ �1 ��;� �1 L 2 2 ��\ 2 v 2 4 �� 4 v 4 oC '� g oC v �C "K �P�� "K v @K �S �m�� �S v �S �h Ե �����h L �h �h ���� �h
v �h =o �Q =o L Do Ho C� Ho
v Xo Az �Q� Az L Lz Tz �H�7 Tz v hz ǡ �*!� ǡ v С �� �ag� �� v �� Q� B�;� Q� L T� l� ]Lp l� L t� �� extensionsService.js � import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import Shew from 'gi://Shew';
import {ExtensionPrefsDialog} from './extensionPrefsDialog.js';
import {ServiceImplementation} from './dbusService.js';
import {deserializeExtension} from './misc/extensionUtils.js';
import {loadInterfaceXML} from './misc/dbusUtils.js';
const ExtensionsIface = loadInterfaceXML('org.gnome.Shell.Extensions');
const ExtensionsProxy = Gio.DBusProxy.makeProxyWrapper(ExtensionsIface);
class ExtensionManager {
#extensions = new Map();
createExtensionObject(serialized) {
const extension = deserializeExtension(serialized);
this.#extensions.set(extension.uuid, extension);
return extension;
}
lookup(uuid) {
return this.#extensions.get(uuid);
}
}
export const extensionManager = new ExtensionManager();
export const ExtensionsService = class extends ServiceImplementation {
constructor() {
super(ExtensionsIface, '/org/gnome/Shell/Extensions');
this._proxy = new ExtensionsProxy(Gio.DBus.session,
'org.gnome.Shell', '/org/gnome/Shell');
this._proxy.connectSignal('ExtensionStateChanged',
(proxy, sender, params) => {
this._dbusImpl.emit_signal('ExtensionStateChanged',
new GLib.Variant('(sa{sv})', params));
});
this._proxy.connect('g-properties-changed', () => {
this._dbusImpl.emit_property_changed('UserExtensionsEnabled',
new GLib.Variant('b', this._proxy.UserExtensionsEnabled));
});
}
get ShellVersion() {
return this._proxy.ShellVersion;
}
get UserExtensionsEnabled() {
return this._proxy.UserExtensionsEnabled;
}
set UserExtensionsEnabled(enable) {
this._proxy.UserExtensionsEnabled = enable;
}
async ListExtensionsAsync(params, invocation) {
try {
const res = await this._proxy.ListExtensionsAsync(...params);
invocation.return_value(new GLib.Variant('(a{sa{sv}})', res));
} catch (error) {
this._handleError(invocation, error);
}
}
async GetExtensionInfoAsync(params, invocation) {
try {
const res = await this._proxy.GetExtensionInfoAsync(...params);
invocation.return_value(new GLib.Variant('(a{sv})', res));
} catch (error) {
this._handleError(invocation, error);
}
}
async GetExtensionErrorsAsync(params, invocation) {
try {
const res = await this._proxy.GetExtensionErrorsAsync(...params);
invocation.return_value(new GLib.Variant('(as)', res));
} catch (error) {
this._handleError(invocation, error);
}
}
async InstallRemoteExtensionAsync(params, invocation) {
try {
const res = await this._proxy.InstallRemoteExtensionAsync(...params);
invocation.return_value(new GLib.Variant('(s)', res));
} catch (error) {
this._handleError(invocation, error);
}
}
async UninstallExtensionAsync(params, invocation) {
try {
const res = await this._proxy.UninstallExtensionAsync(...params);
invocation.return_value(new GLib.Variant('(b)', res));
} catch (error) {
this._handleError(invocation, error);
}
}
async EnableExtensionAsync(params, invocation) {
try {
const res = await this._proxy.EnableExtensionAsync(...params);
invocation.return_value(new GLib.Variant('(b)', res));
} catch (error) {
this._handleError(invocation, error);
}
}
async DisableExtensionAsync(params, invocation) {
try {
const res = await this._proxy.DisableExtensionAsync(...params);
invocation.return_value(new GLib.Variant('(b)', res));
} catch (error) {
this._handleError(invocation, error);
}
}
LaunchExtensionPrefsAsync([uuid], invocation) {
this.OpenExtensionPrefsAsync([uuid, '', {}], invocation);
}
async OpenExtensionPrefsAsync(params, invocation) {
const [uuid, parentWindow, options] = params;
try {
if (this._prefsDialog)
throw new Error('Already showing a prefs dialog');
const [serialized] = await this._proxy.GetExtensionInfoAsync(uuid);
const extension = extensionManager.createExtensionObject(serialized);
this._prefsDialog = new ExtensionPrefsDialog(extension);
this._prefsDialog.connect('loaded',
() => this._prefsDialog.show());
this._prefsDialog.connect('realize', () => {
let externalWindow = null;
if (parentWindow)
externalWindow = Shew.ExternalWindow.new_from_handle(parentWindow);
if (externalWindow)
externalWindow.set_parent_of(this._prefsDialog.get_surface());
});
if (options.modal)
this._prefsDialog.modal = options.modal.get_boolean();
this._prefsDialog.connect('close-request', () => {
delete this._prefsDialog;
this.release();
return false;
});
this.hold();
invocation.return_value(null);
} catch (error) {
this._handleError(invocation, error);
}
}
async CheckForUpdatesAsync(params, invocation) {
try {
await this._proxy.CheckForUpdatesAsync(...params);
invocation.return_value(null);
} catch (error) {
this._handleError(invocation, error);
}
}
};
(uuay)gnome/ prefs.js� import Adw from 'gi://Adw';
import GObject from 'gi://GObject';
import {ExtensionBase, GettextWrapper} from './sharedInternals.js';
import {extensionManager} from '../extensionsService.js';
export class ExtensionPreferences extends ExtensionBase {
static lookupByUUID(uuid) {
return extensionManager.lookup(uuid)?.stateObj ?? null;
}
static defineTranslationFunctions(url) {
const wrapper = new GettextWrapper(this, url);
return wrapper.defineTranslationFunctions();
}
/**
* Get the single widget that implements
* the extension's preferences.
*
* @returns {Gtk.Widget|Promise<Gtk.Widget>}
*/
getPreferencesWidget() {
throw new GObject.NotImplementedError();
}
/**
* Fill the preferences window with preferences.
*
* The default implementation adds the widget
* returned by getPreferencesWidget().
*
* @param {Adw.PreferencesWindow} window - the preferences window
* @returns {Promise<void>}
*/
async fillPreferencesWindow(window) {
const widget = await this.getPreferencesWidget();
const page = this._wrapWidget(widget);
window.add(page);
}
_wrapWidget(widget) {
if (widget instanceof Adw.PreferencesPage)
return widget;
const page = new Adw.PreferencesPage();
if (widget instanceof Adw.PreferencesGroup) {
page.add(widget);
return page;
}
const group = new Adw.PreferencesGroup();
group.add(widget);
page.add(group);
return page;
}
}
export const {
gettext, ngettext, pgettext,
} = ExtensionPreferences.defineTranslationFunctions();
(uuay)Extensions/ org/ extensionUtils.js � // Common utils for the extension system, the extensions D-Bus service
// and the Extensions app
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
export const ExtensionType = {
SYSTEM: 1,
PER_USER: 2,
};
/**
* @enum {number}
*/
export const ExtensionState = {
ACTIVE: 1,
INACTIVE: 2,
ERROR: 3,
OUT_OF_DATE: 4,
DOWNLOADING: 5,
INITIALIZED: 6,
DEACTIVATING: 7,
ACTIVATING: 8,
// Used as an error state for operations on unknown extensions,
// should never be in a real extensionMeta object.
UNINSTALLED: 99,
};
const SERIALIZED_PROPERTIES = [
'type',
'state',
'enabled',
'path',
'error',
'hasPrefs',
'hasUpdate',
'canChange',
'sessionModes',
];
/**
* Serialize extension into an object that can be used
* in a vardict {GLib.Variant}
*
* @param {object} extension - an extension object
* @returns {object}
*/
export function serializeExtension(extension) {
let obj = {...extension.metadata};
SERIALIZED_PROPERTIES.forEach(prop => {
obj[prop] = extension[prop];
});
function packValue(val) {
let type;
switch (typeof val) {
case 'string':
type = 's';
break;
case 'number':
type = 'd';
break;
case 'boolean':
type = 'b';
break;
case 'object':
if (Array.isArray(val)) {
type = 'av';
val = val.map(v => packValue(v));
} else {
type = 'a{sv}';
let res = {};
for (let key in val) {
let packed = packValue(val[key]);
if (packed)
res[key] = packed;
}
val = res;
}
break;
default:
return null;
}
return GLib.Variant.new(type, val);
}
return packValue(obj).deepUnpack();
}
/**
* Deserialize an unpacked variant into an extension object
*
* @param {object} variant - an unpacked {GLib.Variant}
* @returns {object}
*/
export function deserializeExtension(variant) {
let res = {metadata: {}};
for (let prop in variant) {
let val = variant[prop].recursiveUnpack();
if (SERIALIZED_PROPERTIES.includes(prop))
res[prop] = val;
else
res.metadata[prop] = val;
}
// add the 2 additional properties to create a valid extension object, as createExtensionObject()
res.uuid = res.metadata.uuid;
res.dir = Gio.File.new_for_path(res.path);
return res;
}
/**
* Load extension metadata from directory
*
* @param {string} uuid of the extension
* @param {GioFile} dir to load metadata from
* @returns {object}
*/
export function loadExtensionMetadata(uuid, dir) {
const dirName = dir.get_basename();
if (dirName !== uuid)
throw new Error(`Directory name "${dirName}" does not match UUID "${uuid}"`);
const metadataFile = dir.get_child('metadata.json');
if (!metadataFile.query_exists(null))
throw new Error('Missing metadata.json');
let metadataContents, success_;
try {
[success_, metadataContents] = metadataFile.load_contents(null);
metadataContents = new TextDecoder().decode(metadataContents);
} catch (e) {
throw new Error(`Failed to load metadata.json: ${e}`);
}
let meta;
try {
meta = JSON.parse(metadataContents);
} catch (e) {
throw new Error(`Failed to parse metadata.json: ${e}`);
}
const requiredProperties = [{
prop: 'uuid',
typeName: 'string',
}, {
prop: 'name',
typeName: 'string',
}, {
prop: 'description',
typeName: 'string',
}, {
prop: 'shell-version',
typeName: 'string array',
typeCheck: v => Array.isArray(v) && v.length > 0 && v.every(e => typeof e === 'string'),
}];
for (let i = 0; i < requiredProperties.length; i++) {
const {
prop, typeName, typeCheck = v => typeof v === typeName,
} = requiredProperties[i];
if (!meta[prop])
throw new Error(`missing "${prop}" property in metadata.json`);
if (!typeCheck(meta[prop]))
throw new Error(`property "${prop}" is not of type ${typeName}`);
}
if (uuid !== meta.uuid)
throw new Error(`UUID "${meta.uuid}" from metadata.json does not match directory name "${uuid}"`);
return meta;
}
(uuay)ui/
main.js � import Adw from 'gi://Adw?version=1';
import GObject from 'gi://GObject';
const pkg = imports.package;
import {DBusService} from './dbusService.js';
import {ExtensionsService} from './extensionsService.js';
/** @returns {void} */
export async function main() {
Adw.init();
pkg.initFormat();
GObject.gtypeNameBasedOnJSPath = true;
const service = new DBusService(
'org.gnome.Shell.Extensions',
new ExtensionsService());
await service.runAsync();
}
(uuay)extensionPrefsDialog.js ? import Adw from 'gi://Adw?version=1';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=4.0';
import {gettext as _} from 'gettext';
import {formatError} from './misc/errorUtils.js';
export class ExtensionPrefsDialog extends Adw.PreferencesWindow {
static [GObject.GTypeName] = 'ExtensionPrefsDialog';
static [GObject.signals] = {
'loaded': {},
};
static {
GObject.registerClass(this);
}
constructor(extension) {
super({
title: extension.metadata.name,
search_enabled: false,
});
this._extension = extension;
this._loadPrefs().catch(e => {
this._showErrorPage(e);
logError(e, 'Failed to open preferences');
}).finally(() => this.emit('loaded'));
}
async _loadPrefs() {
const {dir, path, metadata} = this._extension;
const prefsJs = dir.get_child('prefs.js');
const prefsModule = await import(prefsJs.get_uri());
const prefsObj = new prefsModule.default({...metadata, dir, path});
this._extension.stateObj = prefsObj;
await prefsObj.fillPreferencesWindow(this);
if (!this.visible_page)
throw new Error('Extension did not provide any UI');
}
set titlebar(w) {
this.set_titlebar(w);
}
set_titlebar() {
// intercept fatal libadwaita error, show error page instead
GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this._showErrorPage(
new Error('set_titlebar() is not supported for Adw.Window'));
return GLib.SOURCE_REMOVE;
});
}
destroy() {
this._showErrorPage(
new Error('destroy() breaks tracking open dialogs, use close() if you must'));
}
_showErrorPage(e) {
while (this.visible_page)
this.remove(this.visible_page);
this.set_title(_('Extension Error'));
this.add(new ExtensionPrefsErrorPage(this._extension, e));
}
}
class ExtensionPrefsErrorPage extends Adw.PreferencesPage {
static [GObject.GTypeName] = 'ExtensionPrefsErrorPage';
static [Gtk.template] =
'resource:///org/gnome/Shell/Extensions/ui/extension-error-page.ui';
static [Gtk.internalChildren] = [
'descriptionLabel',
'errorView',
];
static {
GObject.registerClass(this);
this.install_action('page.copy-error',
null,
self => {
const clipboard = self.get_display().get_clipboard();
clipboard.set(self._errorMarkdown);
});
}
constructor(extension, error) {
super();
const {uuid, name, url} = extension.metadata;
let label =
/* Translators: %s is an extension name */
_('Unable to display the settings for “%s”.')
.format(GLib.markup_escape_text(name, -1));
if (url) {
/* Translators: Link label in the phrase "Information about this
problem may be available on the extension website" */
const linkLabel = _('extension website');
label += ' ';
/* Translators: %s is "extension website" */
label += _('Information about this problem may be available on the %s.')
.format(`<a href="${url}">${linkLabel}</a>`);
}
this._descriptionLabel.set({label});
const formattedError = formatError(error);
this._errorView.buffer.text = formattedError;
// markdown for pasting in gitlab issues
let lines = [
`The settings of extension ${uuid} had an error:`,
'```',
formattedError.replace(/\n$/, ''), // remove trailing newline
'```',
'',
];
this._errorMarkdown = lines.join('\n');
}
}
(uuay)dbusUtils.js � import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import * as Config from './config.js';
let _ifaceResource = null;
/**
* @private
*/
function _ensureIfaceResource() {
if (_ifaceResource)
return;
// don't use global.datadir so the method is usable from tests/tools
let dir = GLib.getenv('GNOME_SHELL_DATADIR') || Config.PKGDATADIR;
let path = `${dir}/gnome-shell-dbus-interfaces.gresource`;
_ifaceResource = Gio.Resource.load(path);
_ifaceResource._register();
}
/**
* @param {string} iface the interface name
* @returns {string | null} the XML string or null if it is not found
*/
export function loadInterfaceXML(iface) {
_ensureIfaceResource();
let uri = `resource:///org/gnome/shell/dbus-interfaces/${iface}.xml`;
let f = Gio.File.new_for_uri(uri);
try {
let [ok_, bytes] = f.load_contents(null);
return new TextDecoder().decode(bytes);
} catch {
log(`Failed to load D-Bus interface ${iface}`);
}
return null;
}
/**
* @param {string} iface the interface name
* @param {string} ifaceFile the interface filename
* @returns {string | null} the XML string or null if it is not found
*/
export function loadSubInterfaceXML(iface, ifaceFile) {
let xml = loadInterfaceXML(ifaceFile);
if (!xml)
return null;
let ifaceStartTag = `<interface name="${iface}">`;
let ifaceStopTag = '</interface>';
let ifaceStartIndex = xml.indexOf(ifaceStartTag);
let ifaceEndIndex = xml.indexOf(ifaceStopTag, ifaceStartIndex + 1) + ifaceStopTag.length;
let xmlHeader = '<!DOCTYPE node PUBLIC\n' +
'\'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\'\n' +
'\'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\'>\n' +
'<node>\n';
let xmlFooter = '</node>';
return (
xmlHeader +
xml.substring(ifaceStartIndex, ifaceEndIndex) +
xmlFooter);
}
(uuay)extension-error-page.ui X <?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ExtensionPrefsErrorPage" parent="AdwPreferencesPage">
<child>
<object class="AdwPreferencesGroup">
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="descriptionLabel">
<property name="justify">center</property>
<property name="wrap">True</property>
<property name="use-markup">True</property>
</object>
</child>
<child>
<object class="AdwPreferencesGroup">
<property name="title" translatable="yes">Error Details</property>
<child type="header-suffix">
<object class="GtkButton">
<property name="receives-default">True</property>
<property name="action-name">page.copy-error</property>
<property name="has-frame">False</property>
<property name="icon-name">edit-copy-symbolic</property>
<property name="tooltip-text" translatable="yes">Copy Error</property>
</object>
</child>
<child>
<object class="GtkTextView" id="errorView">
<property name="monospace">True</property>
<property name="editable">False</property>
<property name="wrap-mode">word</property>
<property name="left-margin">12</property>
<property name="right-margin">12</property>
<property name="top-margin">12</property>
<property name="bottom-margin">12</property>
<style>
<class name="card"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>
(uuay)dbusService.js import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import {programArgs} from 'system';
import './misc/dbusErrors.js';
const Signals = imports.signals;
const IDLE_SHUTDOWN_TIME = 2; // s
export class ServiceImplementation {
constructor(info, objectPath) {
this._objectPath = objectPath;
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(info, this);
this._injectTracking('return_dbus_error');
this._injectTracking('return_error_literal');
this._injectTracking('return_gerror');
this._injectTracking('return_value');
this._injectTracking('return_value_with_unix_fd_list');
this._senders = new Map();
this._holdCount = 0;
// Bail out when not running under gnome-shell
Gio.DBus.watch_name(Gio.BusType.SESSION,
'org.gnome.Shell',
Gio.BusNameWatcherFlags.NONE,
(c, name, owner) => (this._shellName = owner),
() => {
this._shellName = null;
// For auto-shutdown services, delay shutting
// down in case the shell reappears
if (this._autoShutdown)
this._queueShutdownCheck();
else
this.emit('shutdown');
});
this._hasSignals = this._dbusImpl.get_info().signals.length > 0;
this._shutdownTimeoutId = 0;
// subclasses may override this to disable automatic shutdown
this._autoShutdown = true;
this._queueShutdownCheck();
}
// subclasses may override this to own additional names
register() {
}
export() {
this._dbusImpl.export(Gio.DBus.session, this._objectPath);
}
unexport() {
this._dbusImpl.unexport();
}
hold() {
this._holdCount++;
}
release() {
if (this._holdCount === 0) {
logError(new Error('Unmatched call to release()'));
return;
}
this._holdCount--;
if (this._holdCount === 0)
this._queueShutdownCheck();
}
/**
* Complete @invocation with an appropriate error if @error is set;
* useful for implementing early returns from method implementations.
*
* @param {Gio.DBusMethodInvocation}
* @param {Error}
*
* @returns {bool} - true if @invocation was completed
*/
_handleError(invocation, error) {
if (error === null)
return false;
if (error instanceof GLib.Error) {
Gio.DBusError.strip_remote_error(error);
invocation.return_gerror(error);
} else {
let name = error.name;
if (!name.includes('.')) // likely a normal JS error
name = `org.gnome.gjs.JSError.${name}`;
invocation.return_dbus_error(name, error.message);
}
return true;
}
_maybeShutdown() {
if (!this._autoShutdown)
return;
if (GLib.getenv('SHELL_DBUS_PERSIST'))
return;
if (this._shellName && this._holdCount > 0)
return;
this.emit('shutdown');
}
_queueShutdownCheck() {
if (this._shutdownTimeoutId)
GLib.source_remove(this._shutdownTimeoutId);
this._shutdownTimeoutId = GLib.timeout_add_seconds(
GLib.PRIORITY_DEFAULT, IDLE_SHUTDOWN_TIME,
() => {
this._shutdownTimeoutId = 0;
this._maybeShutdown();
return GLib.SOURCE_REMOVE;
});
}
_trackSender(sender) {
if (this._senders.has(sender))
return;
if (sender === this._shellName)
return; // don't track the shell
this.hold();
this._senders.set(sender,
this._dbusImpl.get_connection().watch_name(
sender,
Gio.BusNameWatcherFlags.NONE,
null,
() => this._untrackSender(sender)));
}
_untrackSender(sender) {
const id = this._senders.get(sender);
if (id)
this._dbusImpl.get_connection().unwatch_name(id);
if (this._senders.delete(sender))
this.release();
}
_injectTracking(methodName) {
const {prototype} = Gio.DBusMethodInvocation;
const origMethod = prototype[methodName];
const that = this;
prototype[methodName] = function (...args) {
origMethod.apply(this, args);
if (that._hasSignals)
that._trackSender(this.get_sender());
that._queueShutdownCheck();
};
}
}
Signals.addSignalMethods(ServiceImplementation.prototype);
export class DBusService {
constructor(name, service) {
this._name = name;
this._service = service;
this._loop = new GLib.MainLoop(null, false);
this._service.connect('shutdown', () => this._loop.quit());
}
async runAsync() {
this._service.register();
let flags = Gio.BusNameOwnerFlags.ALLOW_REPLACEMENT;
if (programArgs.includes('--replace'))
flags |= Gio.BusNameOwnerFlags.REPLACE;
Gio.DBus.own_name(Gio.BusType.SESSION,
this._name,
flags,
() => this._service.export(),
null,
() => this._loop.quit());
await this._loop.runAsync();
}
}
(uuay)/ dbusErrors.js 5 import GLib from 'gi://GLib';
import Gio from 'gi://Gio';
function camelcase(str) {
const words = str.toLowerCase().split('_');
return words.map(w => `${w.at(0).toUpperCase()}${w.substring(1)}`).join('');
}
function decamelcase(str) {
return str.replace(/(.)([A-Z])/g, '$1-$2');
}
function registerErrorDomain(domain, errorEnum, prefix = 'org.gnome.Shell') {
const domainName =
`shell-${decamelcase(domain).toLowerCase()}-error`;
const quark = GLib.quark_from_string(domainName);
for (const [name, code] of Object.entries(errorEnum)) {
Gio.dbus_error_register_error(quark,
code, `${prefix}.${domain}.Error.${camelcase(name)}`);
}
return quark;
}
export const ModalDialogError = {
UNKNOWN_TYPE: 0,
GRAB_FAILED: 1,
};
export const ModalDialogErrors =
registerErrorDomain('ModalDialog', ModalDialogError);
export const NotificationError = {
INVALID_APP: 0,
};
export const NotificationErrors =
registerErrorDomain('Notifications', NotificationError, 'org.gtk');
export const ExtensionError = {
INFO_DOWNLOAD_FAILED: 0,
DOWNLOAD_FAILED: 1,
EXTRACT_FAILED: 2,
ENABLE_FAILED: 3,
NOT_ALLOWED: 4,
};
export const ExtensionErrors =
registerErrorDomain('Extensions', ExtensionError);
export const ScreencastError = {
ALL_PIPELINES_FAILED: 0,
PIPELINE_ERROR: 1,
SAVE_TO_DISK_DISABLED: 2,
ALREADY_RECORDING: 3,
RECORDER_ERROR: 4,
SERVICE_CRASH: 5,
OUT_OF_DISK_SPACE: 6,
};
export const ScreencastErrors =
registerErrorDomain('Screencast', ScreencastError);
(uuay)Shell/ errorUtils.js �
// Common code for displaying errors to the user in various dialogs
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
function formatSyntaxErrorLocation(error) {
const {fileName = '<unknown>', lineNumber = 0, columnNumber = 0} = error;
return ` @ ${fileName}:${lineNumber}:${columnNumber}`;
}
function formatExceptionStack(error) {
const {stack} = error;
if (!stack)
return '\n\n(No stack trace)';
const indentedStack = stack.split('\n').map(line => ` ${line}`).join('\n');
return `\n\nStack trace:\n${indentedStack}`;
}
function formatExceptionWithCause(error, seenCauses, showStack) {
let fmt = showStack ? formatExceptionStack(error) : '';
const {cause} = error;
if (!cause)
return fmt;
fmt += `\nCaused by: ${cause}`;
if (cause !== null && typeof cause === 'object') {
if (seenCauses.has(cause))
return fmt; // avoid recursion
seenCauses.add(cause);
fmt += formatExceptionWithCause(cause, seenCauses);
}
return fmt;
}
/**
* Formats a thrown exception into a string, including the stack, taking the
* location where a SyntaxError was thrown into account.
*
* @param {Error} error The error to format
* @param {object} options Formatting options
* @param {boolean} options.showStack Whether to show the stack trace (default
* true)
* @returns {string} The formatted string
*/
export function formatError(error, {showStack = true} = {}) {
try {
let fmt = `${error}`;
if (error === null || typeof error !== 'object')
return fmt;
if (error instanceof SyntaxError) {
fmt += formatSyntaxErrorLocation(error);
if (showStack)
fmt += formatExceptionStack(error);
return fmt;
}
const seenCauses = new Set([error]);
fmt += formatExceptionWithCause(error, seenCauses, showStack);
return fmt;
} catch (e) {
return `(could not display error: ${e})`;
}
}
/**
* Logs a stack trace for `error` with an optional prefix, unless the error
* matches `Gio.IOErrorEnum.CANCELLED`.
*
* @param {Error} error - the error to log
* @param {string?} prefix - optional prefix for the message
*
* @returns {boolean} whether the error was logged
*/
export function logErrorUnlessCancelled(error, prefix) {
if (error instanceof GLib.Error && Gio.DBusError.is_remote_error(error)) {
const errorName = Gio.DBusError.get_remote_error(error);
Gio.DBusError.strip_remote_error(error);
error = Gio.DBusError.new_for_dbus_error(errorName, error.message);
}
if (error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return false;
logError(error, prefix);
return true;
}
(uuay)extensions/ sharedInternals.js O'