Переход в пространство имен браузера

Начиная с Chrome 148, все API расширений Chrome доступны в пространстве имен browser в дополнение к существующему пространству имен chrome . Например, browser.tabs.create({}) и chrome.tabs.create({}) эквивалентны.

Пространство имен доступно везде, где можно вызывать API расширений, включая скрипты контента, сервис-воркеры и документы, находящиеся вне экрана. Оно указывает на те же объекты API, что и chrome , поэтому chrome.tabs === browser.tabs .

Пространство имен browser прекращает свою работу в рамках WebExtensions Community Group (WECG) , сообщества W3C, где производители браузеров сотрудничают над общими стандартами расширений. Пространство имен chrome не исчезнет; оба пространства имен продолжат свою работу.

Решите, следует ли использовать пространство имен браузера.

Если вы используете webextension-polyfill , перед внесением каких-либо изменений перейдите к разделу «Примечание для пользователей полифилов» — решение для вас будет другим.

Если вы создаёте новое расширение, установите minimum_chrome_version равным "148" и используйте browser без ограничений; на этом можно прекратить чтение. Остальная часть этого раздела предназначена для существующих расширений, которые решают, как их использовать.

Проверьте, какие версии Chrome используют ваши пользователи.

Если у вас уже есть расширение, проверьте, какие версии Chrome используют ваши пользователи, прежде чем переключаться на новую версию. Chrome обновляется автоматически, но некоторые пользователи отключают обновления, а другие используют старые устройства, на которых не работает последняя версия. Подтвердите это с помощью собственных аналитических данных. Если у вас еще не настроена аналитика, см. раздел «Мониторинг производительности вашего расширения с помощью Google Analytics 4», чтобы начать работу.

Оттуда выберите путь:

Принять безоговорочно

Укажите параметр minimum_chrome_version в вашем манифесте и используйте browser безусловно — проверка во время выполнения не требуется:

{
  "minimum_chrome_version": "148"
}

При повышении параметра minimum_chrome_version используйте поэтапное развертывание. Если что-то пойдет не так, вы сможете откатить расширение в Chrome Web Store.

Используйте защиту во время выполнения.

Добавьте следующий фрагмент кода в начало кода запуска вашего расширения, прежде чем где-либо еще ссылаться на browser :

if (!globalThis.browser) {
  globalThis.browser = chrome;
  // Consider firing an analytics event here to measure how often
  // your users hit this fallback path.
}

Это делает browser псевдонимом для chrome в более ранних версиях, поэтому остальная часть вашего кода может использовать browser безусловно.

Примечание для пользователей полифилов

Если ваше расширение использует webextension-polyfill , оно становится бесполезным в Chrome 148 и более поздних версиях. Полифил пропускает обертывание, если browser уже определен, предполагая, что хост-браузер уже предоставил API.

Предыдущая попытка включить пространство имен в Chrome 136 была отменена по этой причине: с новым определением browser полифил перестал его оборачивать, но browser.runtime.onMessage в Chrome еще не поддерживал обработчики событий, возвращающие промисы, которые предоставлял полифил. Расширения, использующие этот шаблон, перестали работать. Chrome 148 включает пространство имен и нативные обработчики событий onMessage , возвращающие промисы, вместе, чтобы избежать этого пробела.

Вы сможете удалить зависимость от полифилла после того, как ваши пользователи перейдут на Chrome 148.

Другие функции

Асинхронные ответы в runtime.sendMessage

В Chrome 148 обработчики runtime.onMessage могут напрямую возвращать Promise для отправки асинхронного ответа. Это работает независимо от того, вызываете ли вы его с помощью chrome.* или browser.* .

Ранее единственным способом асинхронного ответа было возвращение слушателем значения true и последующий вызов функции sendResponse :

// Old pattern - requires returning true to keep the channel open
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  fetch('https://example.com')
    .then(response => sendResponse({ statusCode: response.status }));

  return true; // keeps the message channel open for the async response
});

Теперь вы можете напрямую возвращать Promise (или использовать async функцию):

// New pattern - return a promise or use async/await
browser.runtime.onMessage.addListener(async (message, sender) => {
  const response = await fetch('https://example.com');
  return { statusCode: response.status };
});

Принцип return true по-прежнему работает, поэтому существующий код менять не нужно.