Несколько изолированных рабочих пространств в одном окне Chrome: как это устроено

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

Почему несколько окон — это ещё не несколько аккаунтов, вошедших одновременно

Начнём с того, что придётся разобрать: окно не является единицей изоляции. Десять окон в одном профиле делят одно хранилище cookie, один localStorage и один HTTP-кэш — сайт видит одну сессию. У режима инкогнито хранилище действительно отдельное, но оно одно и умирает вместе с окном, так что на десять аккаунтов его не хватит. Настоящая единица — контейнер сессии: собственный набор cookie, собственное пространство имён хранилища и устойчивая карта принадлежности. В Chrome нет API контейнеров — исключение составляет contextualIdentities в Firefox, — поэтому расширение строит его само на уровне сессии: запоминает, какая вкладка к какому контейнеру относится, и распределяет запросы и хранилище страницы по этой карте. CrispLogin устроен именно так: контейнер — это запись принадлежности, которую ведёт расширение, а не примитив Chrome. Единица изоляции — сессия, а не процесс.

Слой первый: почему cookie не смешиваются

Аккаунты не смешиваются благодаря виртуальной банке cookie и перезаписи заголовка запроса на уровне вкладки. Каждый контейнер держит внутри расширения собственные записи cookie. Перед отправкой запроса session rule из declarativeNetRequest сопоставляет вкладку через condition.tabIds и целиком выставляет заголовок cookie в значение этого контейнера; когда приходит ответ, webRequest наблюдает Set-Cookie и записывает его в нужную банку. Банка обязана сериализовать cookie в порядке длины пути, а затем времени создания, иначе заголовок не совпадёт с тем, что отправил бы сам браузер.

Чаще всего упускают время жизни: tabIds работает только в session rule, а session rule очищаются при закрытии браузера и при обновлении расширения. Значит, правила нужно переустанавливать при каждом запуске; если этого не делать, симптом будет такой: «после перезапуска все рабочие пространства — один и тот же аккаунт». Хранилище страницы — вторая плоскость: document.cookie читает настоящее хранилище cookie, а у localStorage одно пространство имён, поэтому скрипт в MAIN world должен проксировать чтение и запись по контейнерам. Это изоляция прикладного уровня: она разделяет два аккаунта на одном сайте, но отпечатка ядра не касается.

Слой второй: как прокси следует за рабочим пространством

В Chrome нет API «прокси для вкладки». chrome.proxy.settings действует на весь профиль, а FindProxyForURL(url, host) в PAC-скрипте никогда не получает tabId; declarativeNetRequest умеет переписывать заголовки и перенаправлять, но действия «выбрать вышестоящий прокси» у него нет. Поэтому расширение может лишь вести карту «рабочее пространство → выход» и переписывать эту общую конфигурацию, когда меняется активная вкладка.

PAC умеет разделять по домену, но на входе у него URL, а не вкладка: один и тот же сайт в двух рабочих пространствах получит от PAC один ответ. Поэтому «десять рабочих пространств, каждое со своим туннелем» в расширении не существует; гарантировано только «чьё пространство сейчас на переднем плане — того и выход». Отсюда же заметное переподключение при переключении: конфигурация прокси меняется, и уже установленные соединения пересоздаются. Граница: этот слой меняет IP выхода и путь запроса, но не отпечаток TCP/TLS (JA3/JA4); WebRTC можно ограничить через chrome.privacy.network.webRTCIPHandlingPolicy, отключив UDP вне прокси, но это политика всего браузера, а не отдельного пространства.

Слой третий: переживает ли привязка закрытие вкладки и перезапуск

Фон MV3 — это service worker: 30 секунд без событий, и он завершается, унося с собой переменные уровня модуля и любой Map в замыкании. Поэтому «какая вкладка к какому пространству относится» нельзя держать в памяти: это уходит в chrome.storage.session. Эта область живёт в памяти, пока расширение загружено, переживает переработку воркера и очищается при перезапуске браузера. Учтите: по умолчанию она не открыта для content script; если стороне страницы нужно читать привязку, придётся явно вызвать setAccessLevel.

Так данные делятся на два вида: привязки времени выполнения — в session, а всё, что должно пережить перезапуск (список пространств, конфигурация прокси, индекс снимков), — в storage.local. Причинная связь прямая: раз привязка лежит в session, а не в переменной, после пробуждения расширение по-прежнему знает, кому принадлежит каждая вкладка, и не выливает cookie одного пространства на страницу другого. Если держать её только в памяти, в момент засыпания воркера следующему запросу некого будет опросить — это проявляется дублями групп и снимками, попавшими в чужой контейнер.

Слой четвёртый: что хранит снимок сайта и что он восстанавливает

Снимок отвечает на другой вопрос — переносимость состояния входа, а не изоляция во время работы. В этом списке он четвёртый, но частью самой изоляции не является. Он сериализует cookie одного сайта внутри одного контейнера вместе с хранилищем этого сайта, а при восстановлении выливает их обратно в пространство имён этого контейнера. Эти вещи ортогональны: изоляция не даёт двум пространствам мешать друг другу, пока оба существуют; снимок избавляет от повторного входа. Гранулярность — сайт, а не браузер: два сайта в одном контейнере — две независимые записи.

Поэтому снимок обязан принадлежать контейнеру: вылить состояние A в B — значит слить два аккаунта в один. Не менее важно сказать, чего он не делает: он восстанавливает состояние сессии прикладного уровня, а не отпечаток ядра, и не обещает обойти риск-контроль платформы или проверку устройства. Применение: Внутренняя ссылка: снимки сайтов на практике.

Чем это отличается от нескольких профилей

Несколько профилей в Chrome — это физическое разделение на уровне корневого каталога хранилища: у каждого профиля своё хранилище cookie, своё хранилище, свои расширения и свой кэш, поэтому изоляция полная. Цена проявляется по четырём осям: память — у каждого профиля свой сетевой контекст и свои процессы отрисовки, так что три профиля это примерно тройной постоянный расход; процессы — деревья независимы; окна — один профиль это одно окно, и переключение означает смену окна; отпечаток — профили делят одно ядро и одну машину, поэтому UA, Canvas и шрифты по умолчанию идентичны. Есть и более тихая цена: закладки, расширения и история не разделяются, и после третьего профиля всё начинает расходиться.

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

Границы возможностей: какие слои расширение закрывает, а какие нет

Всё сказанное выше, сжатое в одну таблицу. Читать её нужно с вопросом «что проверяет платформа»: для сессии и выхода — средний столбец, для согласованности отпечатка — правый. И ещё раз: расширение делает изоляцию уровня сессии, это не тот же класс, что антидетект-браузер; считать его «более лёгким антидетектом» — значит неверно оценить риск.

Границы изоляции сессий средствами расширения (на ноябрь 2026 года)
СлойЧто расширение закрываетЧто недоступно или чего это стоит
Cookie и состояние входаРазделены по контейнерам, сериализуются в снимокЯдро не знает контейнеров; заголовки переписываются, и при потере правил аккаунты смешиваются
Хранилище страницыlocalStorage и IndexedDB можно префиксовать или проксировать по контейнерамService worker, SharedWorker и другие отдельные контексты требуют собственного покрытия
IP выходаПривязан к пространству; сменился передний план — сменился выходОдновременно доступен только один выход; параллельных туннелей нет
WebRTCUDP вне прокси можно отключить (политика всего браузера)Не на уровне пространства; медиапути всё ещё могут обходить прокси
Отпечаток TLSНичегоJA3/JA4 определяются ядром и сетевым стеком
Canvas / WebGL / AudioНичегоОтрисовка происходит в ядре; API для перезаписи нет
Перечисление шрифтовНичегоТолько патчи JS на странице, и они обнаружимы
HTTP-кэшНичегоКэш общий для профиля и разделяется между контейнерами

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

Частые вопросы

Изоляция cookie в расширении — это то же самое, что Partitioned Cookie в Chrome?

Нет. Partitioned Cookie привязаны к сайту верхнего уровня, поэтому у сайта одна банка на страницу верхнего уровня; partitionKey в API cookies — всего лишь ключ для чтения и записи таких cookie, и его единственный компонент — topLevelSite, придумать новые разделы им нельзя. Банка рабочего пространства разделена по контейнерам, один сайт может иметь их сколько угодно, и учёт ведёт расширение. Первое — приватностное разделение в браузере, второе — абстракция сессии на уровне расширения.

Сохранится ли состояние рабочего пространства после закрытия вкладки?

Три случая. Вкладка исчезла — привязка уходит вместе с ней. Определения пространства (имя, прокси, индекс снимков) относятся к данным, которые должны переживать перезапуск, и обычно лежат в storage.local. Состояние входа восстановимо только если сохранён снимок; иначе придётся входить заново. Содержимое storage.session очищается при закрытии браузера, не считайте его постоянным хранилищем.

Влияет ли подход с одним окном на производительность браузера?

Прирост идёт от вкладок, а не от изоляции. Второй браузер не запускается, ядро не копируется; накладные расходы — сопоставление правил и перезапись заголовков, постоянная величина на запрос. Настоящая цена — в числе вкладок и самих страницах: при двадцати пространствах тормозит отрисовка, а не слой изоляции.

Могут ли два рабочих пространства одновременно использовать разные IP выхода?

Нет. Конфигурация прокси задаётся на профиль, и расширение может переписать её только при смене вкладки, поэтому в каждый момент свой выход использует лишь пространство на переднем плане; фоновые либо блокируются правилами, либо идут напрямую. Для настоящих параллельных туннелей нужен клиент с собственным сетевым стеком.

Источники и последнее обновление

Там, где статья касается поведения API, действует официальная документация. Границы возможностей расширения меняются вместе с версиями Chrome — проверяйте перед внедрением.

Последнее обновление: 11 ноября 2026 года. Здесь описан общий путь реализации для этого класса расширений; какие именно API и где хранит данные конкретный продукт, может отличаться, и внутреннее устройство определяется его собственной документацией.