- PVSM.RU - https://www.pvsm.ru -

Chrome, Xfce и очень страшное кино

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Chrome, Xfce и очень страшное кино - 3

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

Monitor dbus and inhibit swayidle when Firefox or Chromium request it

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

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

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

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

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

Chrome, Xfce и очень страшное кино - 5

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

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

// 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 [10]:

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) [11]

Отключаемый [12], разумеется.

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

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

Можете конечно попробовать заблокировать механизм inhibit в systemd, но все последствия — на вас и вашей совести.

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

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

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

systemd-inhibit --list

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

Chrome, Xfce и очень страшное кино - 7

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

Остальные сервисы обрабатывают только события засыпания (sleep).

Так что наша цель это xfce4-power-manager , именно туда мы сейчас и залезем, для нанесения правок.

xfce4-power-manager — по большей части фоновое приложение, автоматически запускаемое при старте среды Xfce. Но в отличие от прошлого поциента [13], тут есть некоторый интерфейс и взаимодействие с пользователем, которое происходит с помощью иконки в трее:

Chrome, Xfce и очень страшное кино - 8

По нажатию правой кнопки мыши, появится меню со списком дерзких приложений, которые в данный момент перехватывают управление питанием:

Chrome, Xfce и очень страшное кино - 9

Так что ответственный за весь этот электронный беспредел был наконец четко определен.

Кровавый патчинг

Исходный код менеджера управления питанием находится в основном репозитории [14] Xfce, исправляемая версия должна совпадать с установленной локально, чтобы не словить феерические проблемы совместимости.

Автор использовал версию 4.20 [15], установленную на момент написания статьи.

Место предстоящей правки — файл xfpm-inhibit.c [16], в который вынесена вся логика по обработке перехватов (inhibit).

Нас интересует метод xfpm_inhibit_inhibit,строка 370 [17], где начинается обработка входящего запроса на перехват управления.

Код метода небольшой, поэтому привожу его целиком:

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 [18] проверяет на входжение слова «chrom» в названии дерзкого приложения, которое отправило запрос на перехват управления питанием, если оно там есть — происходит немедленный выход из этого метода, а запрос игнорируется.

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

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

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

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

Сборка

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

Проект xfce4-power-manager это уже существенная часть Xfce, чтобы собрать его из исходников и заставить работать — придется постараться.

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

Куда проще скачать готовый архив [20] со специально подготовленными исходниками релизной версии.

Напоминаю что мы патчим версию 4.20.

Во-вторых, придется установить в систему довольно много библиотек и утилит для разработки:

  • A working GNU toolchain [21]

  • 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 [22])

      • 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

Это не весь список, тут [23] внизу страницы находится специальная таблица с описанием зависимостей между компонентами 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 любую страницу с видео [24] и смотрим выдаваемые сообщения:

Победа.

Победа.

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

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

Эпилог

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

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

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

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

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

Автор: alex0x08

Источник [28]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/linux/437927

Ссылки в тексте:

[1] массовая: https://askubuntu.com/questions/1051688/how-to-stop-chrome-from-making-suspend-inhibits

[2] известная: https://unix.stackexchange.com/questions/451413/disabling-chromium-xfce-power-management-inhibition

[3] Xfce: https://xfce.org/

[4] Cinnamon: https://github.com/linuxmint/Cinnamon/issues/13219

[5] попытка: https://github.com/loops/idlehack

[6] Sway: https://github.com/madic-creates/Sway-DE

[7] тикет в трекере: https://bugs.launchpad.net/ubuntu/+source/gnome-session/+bug/1600622

[8] эпичный тикет: https://issues.chromium.org/issues/40324240#comment74

[9] специального API: https://developer.chrome.com/docs/capabilities/web-apis/wake-lock

[10] systemd: https://systemd.io/

[11] systemd-logind.daemon(8): http://www.freedesktop.org/software/systemd/man/systemd-logind.service.html

[12] Отключаемый: https://unix.stackexchange.com/questions/574481/preventing-systemd-inhibit-in-linux

[13] прошлого поциента: https://blog.0x08.ru/xfce-display-settings-dialog

[14] основном репозитории: https://gitlab.xfce.org/xfce/xfce4-power-manager/

[15] 4.20: https://gitlab.xfce.org/xfce/xfce4-power-manager/-/tree/xfce4-power-manager-4.20.0?ref_type=tags

[16] xfpm-inhibit.c: https://gitlab.xfce.org/xfce/xfce4-power-manager/-/blob/xfce4-power-manager-4.20.0/src/xfpm-inhibit.c?ref_type=tags

[17] 370: https://gitlab.xfce.org/xfce/xfce4-power-manager/-/blob/xfce4-power-manager-4.20.0/src/xfpm-inhibit.c?ref_type=tags#L370

[18] strstr: https://en.cppreference.com/w/c/string/byte/strstr

[19] проверки на пустоту: https://gitlab.xfce.org/xfce/xfce4-power-manager/-/blob/xfce4-power-manager-4.20.0/src/xfpm-inhibit.c?ref_type=tags#L379

[20] скачать готовый архив: https://archive.xfce.org/src/xfce/xfce4-power-manager/4.20/

[21] A working GNU toolchain: http://en.wikipedia.org/wiki/GNU_toolchain

[22] 4.20 dependencies: https://wiki.xfce.org/releng/4.20/roadmap#changes_in_dependencies

[23] тут: https://docs.xfce.org/xfce/building#obtaining_the_xfce_source_code

[24] страницу с видео: http://pkill%20-9%20xfce4-power-manager%20./src/xfce4-power-manager%20--debug

[25] Presentation mode: https://docs.xfce.org/xfce/xfce4-power-manager/panel-plugin

[26] нашем канале: https://t.me/alex0x09

[27] оригинал: https://blog.0x08.ru/chrome-xfce-very-scary-movie

[28] Источник: https://habr.com/ru/articles/971828/?utm_source=habrahabr&utm_medium=rss&utm_campaign=971828