Chrome, Xfce и очень страшное кино
Сейчас вы снова убедитесь, что знание С сопоставимо с навыками выживания и самообороны. Поскольку в современном мире корпораций и победившего киберпанка на простых пользователей всем давно насрать.
Отдыхаем хорошо
Как и все нормальные люди, я временами смотрю фильмы, сериалы и длинные видео на ноутбуке и чтобы тот случайно не ушел в сон во время просмотра — включаю на нем «режим презентации».
Поскольку последние годы все кино переместилось в веб, большую часть времени смотрю не программой-видеоплеером, а с помощью браузера Chrome/Chromium.
После одного из его обновлений, стал замечать, что браузер оборзел научился самостоятельно перехватывать и засыпание ноутбука и блокировку экрана и запуск скринсейвера во время просмотра видео, без всяких «режимов презентации».
Затем такое поведение началось на обычных сайтах — без видимого видео или аудио-контента.
Без каких-либо сообщений, запросов и подтверждений.
Затем ноутбук впервые разрядился в ноль, будучи оставленным с открытой страницей сайта, ни suspend ни hibernate не сработали.
После пятой по счету подставы с перехватом управления, я окончально огорчился с такой наглости, достал топор компилятор и стал изучать проблему настоящим образом.
Изучение проблемы
Первым делом я полез в поисковики, дабы убедиться что проблема действительно массовая и известная:
Хотя в статье речь пойдет о Xfce, аналогичным обазом ведут себя и все остальные «большие» окружения — KDE, Gnome, Cinnamon и так далее:
Отдельная шутка юмора — попытка втащить поддержку такого поведения в.. Sway:
Monitor dbus and inhibit swayidle when Firefox or Chromium request it
Но любители тайловых оконных менеджеров это вообще отдельная раса, понять мотивы которой обычным людям не дано.
Разумеется по этой проблеме есть давно заведенный в трекере баг, с длиннющей перепиской, с приложенными дампами памяти и техническими деталями, открытый уже 11 лет:
Как видите у бага стоит низкий приоритет и до сих пор не назначен ответственный, ниже станет понятно почему.
Помимо бага в публичном трекере Ubuntu, где тусуются в основном простые пользователи, есть не менее эпичный тикет, висящий с 2013 года уже в трекере самого Chromium:
Если прокрутить в самый низ страницы с тикетом, можно заметить статус «Fixed» и битую ссылку на коммит, суть которого — легализация специального API для управления блокировкой экрана и засыпанием.. прямо бл#ть из JavaScript-кода на странице!
// The wake lock sentinel.
let wakeLock = null;
// Function that attempts to request a screen wake lock.
const requestWakeLock = async () => {
try {
wakeLock = await navigator.wakeLock.request();
wakeLock.addEventListener('release', () => {
console.log('Screen Wake Lock released:', wakeLock.released);
});
console.log('Screen Wake Lock released:', wakeLock.released);
} catch (err) {
console.error(`${err.name}, ${err.message}`);
}
};
// Request a screen wake lock…
await requestWakeLock();
// …and release it again after 5s.
window.setTimeout(() => {
wakeLock.release();
wakeLock = null;
}, 5000);теперь любая вебмакака, верстающая порносайты, может с помощью специального кода на странице заставить браузер Chrome заблокировать засыпание вашего ноутбука.
И защитить вас от такой педерастии может лишь знание языка С и эта замечательная статья, аминь.
Механизм пенетрации
Прежде чем карать и патчить очередную оборзевшую программу, стоит рассказать широкой аудитории как вся эта кухня вообще работает, хотя-бы для осознания печальных реалий.
Есть такая неведомая хня штука в Linux-системах под названием systemd:
systemd is a suite of basic building blocks for a Linux system. It provides a system and service manager that runs as PID 1 and starts the rest of the system.
Столь расплывчатое описание, взятое с официального сайта, существует ввиду того что авторы — откровенные рептилоиды такого рода системные сервисы крайне непросто описать простыми словами, доступными обывателю.
Для примера, вот так выглядит набор системных сервисов Windows:
Как видите, ни один из этих сервисов не поддается интерпретации простыми пользователями.
Собственно мало чего по этой теме смогут рассказать даже программисты на Windows, самый частый ответ на вопросы по системным сервисам выглядит как:
в душе не #бу, отстань
У этого замечательного systemd с недавних пор появился «сказочный» функционал, для перехвата управления процессами засыпания и выключения системы:
systemd 183 and newer include a logic to inhibit system shutdowns and sleep states. This is implemented as part of systemd-logind.daemon(8)
Отключаемый, разумеется.
Только с последствиями, вроде сломанного процесса автоматического засыпания из менеджеров управления питанием.
И риском загнуть систему целиком при обновлении, поскольку менеджеры пакетов выставляют подобную блокировку при установке пакетов.
Можете конечно попробовать заблокировать механизм inhibit в systemd, но все последствия — на вас и вашей совести.Мы же пойдем немного другим, менее радикальным путем.
Этой командой можно посмотреть список запущенных перехватчиков:
systemd-inhibit --list
В моей системе (Linux Manjaro) это выглядит следующим образом:
Зато есть xfce4-power-manager — менеджер управления питанием из Xfce, который принимает входящие inhibit-запросы и решает что делать дальше.
Остальные сервисы обрабатывают только события засыпания (sleep).
Так что наша цель это именно xfce4-power-manager, а не что-то другое, именно туда мы сейчас и залезем, для нанесения правок.
xfce4-power-manager
Это по большей части фоновое приложение, запускаемое автоматически при старте среды Xfce.
Однако в отличие от прошлого поциента тут все же есть некоторый интерфейс, взаимодействие с пользователем происходит с помощью иконки в трее:
По нажатию правой кнопки мыши появится меню, со списком приложений, которые в данный момент перехватывают управление питанием:
Так что виновник за весь этот электронный беспредел четко определен.
Кровавый патчинг
Исходники находятся в основном репозитории Xfce, исправляемая версия должна совпадать с установленной локально, чтобы не словить феерические проблемы совместимости.
Я использовал версию 4.20, установленную на момент написания статьи.
Место предстоящей правки — файл xfpm-inhibit.c, в который вынесена вся логика по обработке этих перехватов (inhibit).
Нас интересует метод xfpm_inhibit_inhibit,строка 370, где начинается обработка входящего запроса на перехват управления.Код метода небольшой, поэтому привожу его целиком:
static gboolean
xfpm_inhibit_inhibit (XfpmInhibit *inhibit,
GDBusMethodInvocation *invocation,
const gchar *IN_appname,
const gchar *IN_reason,
gpointer user_data)
{
const gchar *sender;
guint cookie;
if (IN_appname == NULL || IN_reason == NULL)
{
g_dbus_method_invocation_return_error (invocation,
XFPM_ERROR,
XFPM_ERROR_INVALID_ARGUMENTS,
_("Invalid arguments"));
return TRUE;
}
sender = g_dbus_method_invocation_get_sender (invocation);
cookie = xfpm_inhibit_add_application (inhibit, IN_appname, sender);
XFPM_DEBUG ("Inhibit send application name=%s reason=%s sender=%s",
IN_appname, IN_reason, sender);
xfpm_inhibit_has_inhibit_changed (inhibit);
xfpm_dbus_monitor_add_unique_name (inhibit->priv->monitor,
G_BUS_TYPE_SESSION, sender);
xfpm_power_management_inhibit_complete_inhibit (user_data,
invocation, cookie);
return TRUE;
}Обратите внимание на вызов метода XFPM_DEBUG, содержащего отладочное сообщение — все эти сообщения становятся видны только если запустить xfce4-power-manager с ключом --debug.
Именно так я и нашел место будущей правки, увидев в консоли:
xfpm_inhibit_inhibit(): Inhibit send application name=/usr/lib/chromium/chromium reason=Video Wake Lock sender=:1.459
- есть единственная точка входа (метод) в менеджере управления питанием, с которой начинается регистрация перехватчика управления;
- метод принимает на вход название приложения (полный путь), посягнувшего на перехват управления.
Думаю не надо иметь высшее техническое образование, чтобы догадаться как будет выглядеть финальное решение:
if (strstr(IN_appname,"chrom") != NULL ) {
XFPM_DEBUG ("Fuck you chrome!");
return TRUE;
}метод strstr проверяет есть ли слово «chrom» в названии приложения, которое отправило запрос на перехват управления питанием, если оно там есть — происходит немедленный выход из этого метода и запрос игнорируется.
Вот так, всего лишь 4 строчки на С, вставленные в нужном месте, сразу после проверки на пустоту обламывают рога оборзевшему браузеру, созданному мировой корпорацией зла, которая решила что «мы знаем как лучше».
Так это выглядит после наложения моего кровавого патча:
Сборка
Теперь поговорим о печальном — о сборке всего этого цирка с конями.
Проект xfce4-power-manager это уже существенная часть Xfce, чтобы собрать его из исходников и заставить работать — придется постараться.
Во-первых, не стоит забирать исходники непосредственно из репозитория, поскольку в проекте используется кодогенерация и в этом случае придется заниматься еще и ею.
Лучше и проще скачать готовый архив со специально подготовленными исходниками релизной версии.
Напоминаю что мы патчим версию 4.20.
Во-вторых, придется установить в систему довольно много библиотек и средств разработки:
- A working GNU toolchain
- Gtk+ and Glib headers, in some distributions called the -devel packages
- Xfce 4.20 requires Gtk+ 3.24 and Glib-2.0 >= 2.72 (See also: 4.20 dependencies)
- gdk-pixbuf-2.0 >= 2.42.8
- gobject-introspection >= 1.72
Но и это еще не все, вот тут внизу страницы есть специальная таблица со списком зависимостей между компонентами, которые тоже придется установить.
Распаковываем скачанный архив с исходниками и запускаем скрипт configure:
tar xvjf ~/Downloads/xfce4-power-manager-4.20.0.tar.bz2 cd fce4-power-manager-4.20.0 ./configure --disable-wayland
Поскольку я не использую Wayland — отключаю зависимость от него при сборке, если же он вам актуален — мне вас жаль придется поставить дополнительные библиотеки:
Добавляем описанный выше блок в файл src/xfpm-inhibit.c и наконец запускаем сборку:
make
Если сборка завершится успешно, в каталоге src будет готовый бинарник с патчем, проверить который можно так:
pkill -f xfce4-power-manager ./src/xfce4-power-manager --debug
Дальше открываем в Chrome любую страницу с видео и смотрим выдаваемые сообщения:
Разумеется, после такого патча вам придется вручную включать и отключать режим презентации (Presentation mode) при просмотре длинных роликов в Хроме, зато процесс будет полностью контролируемым.
Также подобным образом можно обламывать рога и другим приложениям, дерзнувшими шатать управление питанием.