Сейчас вы снова убедитесь, что знание языка С сопоставимо с навыками самообороны, поскольку в современном мире мега-корпораций и победившего киберпанка на простых пользователей всем и давно наплевать.

Картина "Хром шатает батарею цифрового Ильича".
Картина "Хром шатает батарею цифрового Ильича".

Отдыхаем хорошо

Как и все нормальные люди, я временами смотрю фильмы, сериалы и длинные видео на ноутбуке и чтобы тот случайно не ушел в сон во время просмотра — включаю на нем «режим презентации».

Поскольку за последние годы все кино переместилось в веб, большую часть времени теперь используется не программа-видеоплеер, а обычный браузер Chrome/Chromium.

После одного из обновлений, стал замечать, что браузер-то оборзел научился самостоятельно перехватывать засыпание ноутбука, блокировку экрана и запуск скринсейвера во время просмотра видео, без всяких «режимов презентации».

Затем такое поведение появилось и на обычных сайтах — без видимого видео или аудио-контента.

Без каких-либо сообщений, запросов и подтверждений на подобные действия.

Затем ноутбук впервые разрядился в ноль, будучи оставленным с открытой страницей какого-то левого сайта, ни suspend ни hibernate внезапно не сработали.

После пятой по счету подставы с перехватом управления, автор окончально огорчился с такой наглости, достал любимый топор компилятор и стал изучать проблему в деталях.

Изучение проблемы

Первым делом я полез в поисковик, убедиться что проблема — не результат осеннего обострения или моего специфического окружения, в котором половина системы это разнообразные компиляторы и средства разработки, а другая — горы исходного кода.

Оказалось что сия дичь действительно массовая и хорошо известная:

Разумеется тут не про порно, человек просто собирал ядро из исходников. "Sensitive situation".
Разумеется тут не про порно, человек просто собирал ядро из исходников. "Sensitive situation".

Хотя в статье речь пойдет о Xfce, аналогичным обазом ведут себя все «большие» окружения — KDE, Gnome, Cinnamon и так далее:

Отдельная «шутка юмора» — попытка втащить поддержку такого поведения в.. Sway:

Monitor dbus and inhibit swayidle when Firefox or Chromium request it

Хотя любители тайловых менеджеров — особая раса сверхлюдей, понять мотивы которых обывателю не дано, так что не буду даже пытаться.

Разумеется по этой проблеме есть давно заведенный тикет в трекере, с длиннющей перепиской, с приложенными дампами памяти и техническими деталями, открытый уже 11 лет:

Как видите тут стоит низкий приоритет и не назначен ответственный, ниже станет понятно почему.
Как видите тут стоит низкий приоритет и не назначен ответственный, ниже станет понятно почему.

Помимо означенного тикета в публичном трекере Ubuntu, где тусуются в основном простые пользователи, нашелся еще один, не менее эпичный тикет в трекере самого Chromium, висящий там аж с 2013 года:

Если прокрутить в самый низ страницы, можно заметить статус «Fixed» и битую ссылку на коммит (поскольку трекер переехал), суть которого — легализация специального API для управления блокировкой экрана и засыпанием.. прямо из кода на странице!

Примерно такого:

// 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:

Ни один из этих сервисов не поддается интерпретации обывателем.
Ни один из этих сервисов не поддается интерпретации обывателем.

У замечательного 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, но все последствия — на вас и вашей совести.

Мы же пойдем немного другим, менее радикальным путем.

Менеджер управления питанием Xfce

Этой командой можно посмотреть список запущенных перехватчиков:

systemd-inhibit --list

В моей системе (Linux Manjaro) вывод выглядит следующим образом:

Обратите внимание, что самого браузера Chrome в списке нет, зато есть xfce4-power-manager — менеджер управления питанием из Xfce, который принимает входящие запросы на перехват и решает что делать дальше.

Остальные сервисы обрабатывают только события засыпания (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 ("Chrome уходи!");  
	return TRUE;  
}

Для не знающих и не владеющих:

метод strstr проверяет на входжение слова «chrom» в названии дерзкого приложения, которое отправило запрос на перехват управления питанием, если оно там есть — происходит немедленный выход из этого метода, а запрос игнорируется.

Вот так, всего лишь 4 строчки на С, вставленные в нужном месте, сразу после проверки на пустоту обламывают рога оборзевшему браузеру, созданному мировой корпорацией, которая решила, что «мы знаем как лучше».

Так это выглядит в действии после наложения моего «кровавого» патча:

В этот знаменательный день браузер Chrome.. пошел лесом.
В этот знаменательный день браузер Chrome.. пошел лесом.

Сборка

Теперь поговорим о печальном — о сборке всего этого цирка с конями.

Проект 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)

      • Same version for gmodule-2.0, gobject-2.0, gthread-2.0, gio-2.0 and gdbus

    • gdk-pixbuf-2.0 >= 2.42.8

    • gobject-introspection >= 1.72

    • gtk-layer-shell 0.7.0

    • pkgconfig

Это не весь список, тут внизу страницы находится специальная таблица с описанием зависимостей между компонентами Xfce, часть из которых также придется установить.

Таков путь джедая, что поделать.

Распаковываем скачанный архив с исходниками и запускаем скрипт configure:

tar xvjf ~/Downloads/xfce4-power-manager-4.20.0.tar.bz2 
cd fce4-power-manager-4.20.0
./configure --disable-wayland

Поскольку автор не использует Wayland — тут отключена зависимость от него при сборке, но если вам оно актуально, придется установить дополнительные библиотеки:

  • wayland 1.20

  • wayland-protocols 1.25

Добавляем описанный выше блок в файл src/xfpm-inhibit.c и наконец запускаем сборку:

make

Если сборка завершится успешно, в каталоге src будет готовый бинарник с патчем, проверить который можно так:

pkill -f xfce4-power-manager
./src/xfce4-power-manager --debug

Дальше открываем в Chrome любую страницу с видео и смотрим выдаваемые сообщения:

Победа.
Победа.

Разумеется, после такого патча вам придется вручную включать и отключать режим презентации (Presentation mode) при просмотре длинных роликов в браузере, зато процесс будет полностью контролируемым.

Также подобным образом можно «обламывать рога» и другим интересным приложениям, дерзнувшим покуситься на управление питанием — с недавних пор за подобным неблаговидным делом был замечен и Firefox.

Эпилог

Грустно наблюдать (в который уж раз), как некогда хороший софт, по мере роста популярности скатывается в полное УГ отрицание пользовательского опыта и начинает считать своих пользователей полными идиотами:

неотключаемые опции, неизменяемое поведение и просто наглая ложь — все это стало, к великому сожалению, постоянными спутниками самого популярного браузера на планете.

И лишь владение языком С и навыки системного программирования все еще позволяют ставить на место оборзевшие программы — изучайте же инженерное дело настоящим образом!

В одной из следующих статей расскажу о патчах для самого браузера Chrome: «как убрать detach вкладок при таскании», «как вернуть пустую страницу для новой вкладки» и многое другое — следите за анонсами на нашем канале.

Менее цензурный оригинал статьи как обычно в нашем блоге.

Комментарии (9)


  1. CoolCmd
    30.11.2025 20:33

    а не проще сделать простенькое расширение браузера (одна строка js), меняющее navigator.wakeLock.request на заглушку? бонус: расширение будет работать не только в chrome, но и в firefox и safari.


    1. alex0x08 Автор
      30.11.2025 20:33

      Это системная функция браузера, не факт что сработает.

      Ну и Хром такой не один, как только в systemd сделали дырку для управления питанием — понеслось, теперь и плееры и видеоредакторы и калькуляторы лезут блокировать засыпание.


      1. CoolCmd
        30.11.2025 20:33

        Это системная функция браузера, не факт что сработает.

        js на страницах блокировать сон не сможет, вы же этого хотите. можно указать отдельные сайты.

        сам браузер блокировать сможет, например во время просмотра видео.


    1. aborouhin
      30.11.2025 20:33

      В Firefox оно, вроде, штатно отключается через about:config (dom.screenwakelock.enabled и media.video-wakelock, не вникал детально, в чём разница в этих двух параметрах)

      А по поводу того, как проще - тогда уж надо бы PR в XFCE оформлять, который добавляет настройку "Allow apps to request wakelock", лучше ещё и с выбором приложений, которым можно или нельзя. Иначе пересобирать со своим патчем при каждом обновлении будет, хм... утомительно.


      1. alex0x08 Автор
        30.11.2025 20:33

        Это еще один невозможный с точки зрения технических специалистов PR, уже проходили с открытием диалога.


  1. DSolodukhin
    30.11.2025 20:33

    А можно раскрыть, в чем проблема? Вы хотите, чтобы комп засыпал, пока вы кино смотрите?


    1. alex0x08 Автор
      30.11.2025 20:33

      Проблема в том, что "дырку для кино" стали использовать все подряд, например чтобы сделать блокирование перехода в спящий режим все время пока открыта страница сайта.

      В качестве "фишки".

      Соотвественно теперь возможно такое, что если оставляете включенным ноутбук с открытым сайтом в браузере, он легко может и не заснуть, полностью разрядив батарею.


      1. DSolodukhin
        30.11.2025 20:33

        Да, интересно, не сталкивался сам, если честно.

        А не смотрели, что приходит в reason? Может там можно различть как-то когда сам браузер запрашивает или это шаловливые ручки сайтописателя?


        1. alex0x08 Автор
          30.11.2025 20:33

          На скриншотах же видно сообщение "Playing audio", так что оно достаточно общее, хотя и обязательное (судя по коду).

          На самом деле сам факт программной инициации из JS столь системного действа как управление питанием - лишь половина проблемы, есть и вторая:

          задумайтесь, что произойдет если браузер отправит сообщение через dbus на запрос перехвата и оно будет принято, а затем браузер упадет.

          спойлер:

          блокировка засыпания останется висеть и убрать ее не получится, тк таймаут обрабатывается на стороне браузера, но не в менеджере питания.

          Цирк короче.