Screen Capture API: контроль пользователя и приватность
Используйте getDisplayMedia с явным выбором, видимыми индикаторами, отзывом и ограничениями приватности для экрана, окна и вкладки.
BotBrowser Team
Нужна структурированная документация по теме Платформа?
Эта статья относится к редакционной библиотеке. Для пошаговой настройки, справки и постоянных обновлений переходите сразу в соответствующий раздел docs.
BotBrowser может повторить разрешённый сценарий getDisplayMedia() в заявленном профиле, но не может выбрать экран пользователя, скрыть индикаторы браузера или сделать захваченные пиксели приватными для страницы-получателя. Здесь рассматриваются границы управления и приватности, отличные от виртуальной камеры и границ разрешений Document Picture-in-Picture.
TL;DR
Доступ к Screen Capture API требует выбора пользователя. Запрашивайте его из видимого действия, объясняйте, что будет передано, останавливайте каждый трек после задачи и считайте поток чувствительными данными. getDisplayMedia() не является тихим скриншотом, бессрочным разрешением или доказательством приватности поверхности.
Contents
- Контракт захвата
- Матрица тестов с учётом приватности
- Отзыв и безопасное завершение
- Отличия от соседних медиа-API
- Что контролирует BotBrowser
- Практический итог
Контракт захвата
Приложение должно вызывать navigator.mediaDevices.getDisplayMedia() после действия пользователя, например клика, пока действует временная активация пользователя. Вызов из таймера или фонового сообщения может завершиться InvalidStateError. Браузер показывает выбор монитора, окна или вкладки; код не может тихо выбрать поверхность. Возвращённый MediaStream содержит треки, жизненный цикл которых должен быть видимым.
Выбор поверхности является границей управления, а не сигналом личности. NotAllowedError может означать отмену, политику или решение браузера. Записывайте только результат, нужный для восстановления интерфейса, а не полный объект возможностей, имя экрана, текст документа или постоянную метку.
Захваченные пиксели остаются данными приложения. Не отправляйте поток только потому, что захват удался. Применяйте контроль доступа, сроки хранения, редактирование и согласие как для камеры или микрофона. Индикатор браузера сообщает о передаче, но не делает назначение доверенным.
Матрица тестов с учётом приватности
Используйте синтетические данные и новый профиль для каждой строки. Явно фиксируйте действие, источник, ограничения и остановку.
| Строка | Сценарий | Ожидаемое наблюдение | Смысл приватности |
|---|---|---|---|
| A | Нажать «Поделиться» и отменить выбор | Promise отклоняется ограниченной ошибкой | Выбор отклонён; поверхность не выдана |
| B | Выбрать синтетическую вкладку | Есть видеотрек и видимый UI передачи | Пиксели вкладки становятся данными страницы |
| C | Вызвать track.stop() из «Стоп» | Трек завершается, UI возвращается в простой режим | Приложение намеренно завершило захват |
| D | Закрыть вкладку или отозвать в браузере | Приходит ended или поток неактивен | Пользователь или браузер отозвали доступ |
| E | Запросить без активации | Запрос отклоняется | Фоновый скрипт не начинает захват молча |
Компактный результат: {"browser":"Chrome 155","mode":"headed","surface":"synthetic-tab","result":"started","stopped":true,"capturedBytes":null}. Оставляйте capturedBytes равным null, если нет отдельной управляемой измерительной задачи. Публичный артефакт должен доказывать жизненный цикл, а не хранить экран.
Отзыв и безопасное завершение
Добавьте слушатели ended к каждому треку и видимую кнопку «Стоп». UI браузера, навигация, закрытие вкладки или политика также могут завершить поток. Очистите ссылки, удалите превью и верните фокус исходному элементу. Скрытие превью не останавливает источник.
Если используется рекордер, закройте его до освобождения потока и считайте dataavailable чувствительным выводом. Предпочитайте короткие фрагменты, документированное хранение и синтетические фикстуры. Не пишите в журнал кадры, OCR, данные аккаунта или полные имена экранов.
Отличия от соседних медиа-API
Медиаустройства и приватность виртуальной камеры посвящены enumerateDevices(), разрешениям камеры и микрофона и границе списка виртуальных устройств. Screen Capture не перечисляет экран как постоянное устройство и не выбирает его тихо: он показывает новый выбор и возвращает поток экрана.
Границы разрешений Document Picture-in-Picture создают управляемое браузером same-origin окно. Они не раскрывают пиксели другой поверхности. Screen Capture передаёт выбранные пиксели в MediaStream, поэтому минимизация и отзыв критичны.
Не объединяйте эти API в одно разрешение «медиа». У каждого свои жест, посредничество браузера, ошибка и проверка приватности. Успешное Picture-in-Picture ничего не говорит о захвате экрана, а виртуальная камера не доказывает выбор монитора.
Что контролирует BotBrowser
BotBrowser может повторить видимую кнопку на синтетической странице с заявленной версией браузера и новым профилем. Он проверяет отмену, тестовую вкладку, track.stop() и ended. Он не выбирает реальный экран человека, не обходит выбор, не скрывает индикаторы и не обещает одинаковое поведение на каждой ОС.
Практический итог
Контракт имеет четыре наблюдаемых якоря: getDisplayMedia(), MediaStreamTrack.readyState, ended и track.stop(). Записывайте displaySurface, значение Permissions-Policy для iframe и версию браузера. Отклонённый запрос не возвращает MediaStream; запущенный запрос сохраняет видеотрек live до stop() или ended.
Встроенная проверка должна разделять ветви политики. Список по умолчанию для display-capture равен self, поэтому iframe того же источника может получить доступ; iframe другого источника требует явного делегирования с указанием партнёра, например display-capture=(self) example.test. Не предполагайте, что отсутствие делегирования всегда означает отказ: храните источник, объявленную политику, активацию и состояние трека в отдельных строках.
Жизненный цикл для поддержки
Запись для поддержки нужно начинать до открытия выбора. Укажите видимый элемент управления, источник страницы, версию браузера, семейство ОС и временный ли профиль. Сформулируйте ожидаемый результат обычными словами: пользователь выбирает синтетическую вкладку, страница получает видеотрек, индикатор остаётся видимым, а кнопка «Стоп» завершает трек. Это позволяет поддержке разбирать сообщение «демонстрация экрана не работает» без запроса содержимого экрана.
Первая отрицательная ветвь: отмена. Пользователь может открыть выбор и решить ничего не передавать. Считайте это нормальным исходом, сохраните исходную задачу и кратко объясните результат; не открывайте выбор повторно автоматически. Повторные запросы превращают осознанный отказ в навязчивые подсказки. Для агрегированных метрик с описанной целью достаточно ограниченного результата cancelled.
Вторая отрицательная ветвь: отсутствие активации. Страница, открытая из закладки, таймера или фонового сообщения, не должна запускать выбор без текущего жеста пользователя. Проверьте этот путь на синтетической странице и запишите категорию отказа. Не исправляйте его имитацией клика или расширением разрешений: предложите видимую кнопку, объясняющую действие.
Положительный путь также должен иметь конечное состояние. Предпросмотр может быть виден, пока поток активен, но его скрытие не останавливает источник. Храните треки в одном объекте-владельце, вызывайте stop() для каждого намеренно созданного видео- и аудиотрека и обновляйте подпись элемента управления. Если браузер завершил трек первым, обработчик ended должен выполнить тот же путь очистки, чтобы интерфейс не утверждал, что передача продолжается.
Минимизируйте данные, пересекающие границу.
Захват может включать личные сообщения, страницы аккаунта, уведомления и посторонние окна. Безопаснее всего использовать простую синтетическую страницу с крупной надписью «тестовая поверхность» и без данных аккаунта. В реальном продукте объясните выбранную поверхность непосредственно перед выбором и ограничьте получатель текущей задачей. Обрезайте, скрывайте или размывайте содержимое только когда пользователь понимает эффект: скрытый предпросмотр не удаляет пиксели из потока.
Не отправляйте в аналитику сериализованный MediaStream, название экрана, полный объект возможностей или необработанные кадры. Для большинства вопросов надёжности достаточно коротких событий requested, cancelled, started, stopped и ended. Если запись необходима, используйте отдельный путь данных с контролем доступа, сроком хранения и ответственным за удаление. В публичных примерах используйте синтетические значения, а поля содержимого оставляйте null.
Безопасно сравнивайте изменения браузера.
После обновления повторите тот же синтетический сценарий, прежде чем менять код приложения. Сохраняйте одинаковыми источник, способ активации, запрошенную поверхность, жизненный цикл профиля и действие остановки. Сравнивайте первое изменившееся поле: появление выбора, создание потока, состояние трека, индикатор или очистку. Одного ярлыка «успех/ошибка» недостаточно, чтобы найти изменившуюся границу.
Запуски с видимым интерфейсом и автоматизация могут различаться из-за конфигурации дисплея, политики или времени активации. Указывайте эти переменные в заголовке результата и не превращайте наблюдение одного runner в общее утверждение об ОС. BotBrowser помогает повторить заявленный контекст, но браузер владеет выбором, а пользователь принимает решение.
Краткая проверка приватности.
Перед выпуском ответьте на пять вопросов: виден ли элемент управления и доступен ли он с клавиатуры? Уточняет ли текст, что выбрано: вкладка, окно или монитор? Сохраняет ли отмена задачу? Останавливает ли каждый выход треки и удаляет ли предпросмотры? Исключают ли журналы кадры, имена экранов, идентификаторы аккаунтов и посторонние поля профиля? Такая проверка помещается в pull request и предотвращает случайное хранение захватов.
Та же проверка нужна службе поддержки. Запрашивайте версию браузера, видимый результат, первую строку матрицы, которая не прошла, и факт отмены пользователем или завершения браузером. Не просите запись экрана клиента, если вопрос решается синтетическим воспроизведением. Если частное доказательство неизбежно, соберите минимум по ограниченному каналу и удалите его по документированному графику.
Детали реализации, защищающие пользователей.
Храните запись поддержки одной ограниченной строкой: displaySurface, сборка браузера, источник активации и первое конечное состояние. Отделяйте результат запроса от его причины: отказ политики не доказывает отсутствие поддержки захвата, а трек live не доказывает безопасность хранения пикселей.
Размещайте запрос рядом с объясняющей его кнопкой. Надпись «Поделиться тестовой вкладкой» информативнее общего «Начать», особенно если рядом есть камера и микрофон. Объясните возможные цели и то, что браузер покажет выбор; не обещайте ограничить всё содержимое выбранной вкладки. Пользователь отвечает за содержимое поверхности, приложение отвечает за полученный MediaStream.
Предпросмотр должен иметь ясный статус и доступную с клавиатуры кнопку «Стоп». Статус «Передаётся выбранная тестовая вкладка» лучше, чем индикатор, различимый только цветом. После завершения трека объявите изменение и восстановите задачу. Отделяйте состояние записи от состояния передачи: поток может быть виден без записи, а запись может остановиться при активном предпросмотре. Событие ended является конкретным якорем жизненного цикла.
Политика разрешений (заголовок Permissions-Policy) влияет на встроенный сценарий. iframe может не иметь права запросить захват, хотя верхняя страница его имеет. Проверяйте встроенный и верхний случаи отдельными строками, записывайте объявленную политику и объясняйте отказ внутри страницы. Не просите ослабить политику всего сайта ради прохождения фикстуры: это отдельное продуктовое и защитное решение с ответственным владельцем; записывайте значение политики рядом с датой.
Для получателя также нужен ограниченный контракт. Если поток передаётся через peer connection, укажите отправляемые треки, момент их удаления и уведомление удалённой стороны о завершении. При локальном отображении держите элемент предпросмотра у того же владельца, что и треки. Удалённое соединение не оправдывает хранение кадров после нажатия «Стоп»: в этот момент приложение освобождает локальные ссылки и завершает задачу.
Для автоматической проверки используйте страницу с известным рисунком и тестовой меткой, а не рабочий стол или аккаунт клиента. Runner может проверить наличие видеотрека, ненулевые размеры выбранной синтетической вкладки и состояние ended после остановки. Для проверки жизненного цикла не нужно изучать пиксели. Записывайте readyState, track.kind и время остановки, не сохраняя изображения.
При отказе браузера сохраните исходное действие и предложите поддерживаемый вариант: загрузку, статичный экспорт или объяснение на странице. Запасной путь не должен молча переключаться на камеру или микрофон: у каждого источника свои ожидания, и необъяснённая смена является нарушением приватности.
Повторяйте матрицу при изменении выбора браузера, политики разрешений, добавлении рекордера или удалённого транспорта. Храните дату и сборку рядом с результатом; при изменении укажите первую затронутую строку и следующего владельца. Не расширяйте вывод от синтетической вкладки на все экраны, окна, аккаунты и ОС.
Читайте результат без чрезмерных выводов.
Контракт MediaStream служит конкретной опорой решения поддержки. Запущенный поток доказывает, что заявленный браузер и сценарий пользователя создали поток для этой синтетической поверхности. Он не доказывает доступность другой поверхности, одинаковый результат для другого источника или безопасность хранения содержимого. Остановленный трек доказывает очистку этого трека, но не стирает копии, записанные где-то ещё. ended доказывает, что приложение увидело завершение, но не его причину.
Держите действие, наблюдаемый результат и ограничение рядом в заметках о выпуске и переводах. Так не смешиваются соседние API: виртуальная камера описывает медиадустройство, Document Picture-in-Picture означает дополнительное окно презентации, а Screen Capture означает выбранный пользователем поток дисплея. У каждого свой контракт управления и приватности.
Публичные источники
Эта статья входит в руководство: Поверхности веб-платформы: карта проверки
Похожие статьи
Document Picture-in-Picture: границы разрешений и окон
ОтпечаткиПеречень MediaDevices и приватность виртуальных камер
ПлатформаPermissions Policy, возможности браузера и приватность
ПлатформаIdle Detection API: контроль, разрешения и приватность
ПлатформаWeb Share API: границы разрешений и безопасные запасные варианты
ПлатформаПоддержка функции браузером не равна качеству функции
Переведите BotBrowser из исследований в продакшн
Используйте эти руководства, чтобы понять модель, а затем перейти к кроссплатформенной валидации, изолированным контекстам и масштабируемому браузерному развертыванию.