Как обновить код

Обновления, не связанные с другими проблемами

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

Замените tabs.executeScript() на scripting.executeScript()

В Manifest V3 executeScript() переходит из API tabs в API scripting. Для этого нужно изменить разрешения в файле манифеста и код.

Для метода executeScript() вам потребуется:

  • Разрешение "scripting".
  • Разрешения хоста или разрешение "activeTab".

Метод scripting.executeScript() похож на то, как это работало с tabs.executeScript(). Однако между версиями есть несколько отличий.

  • Если старый метод мог принимать только один файл, то новый может принимать массив файлов.
  • Также вместо объекта InjectDetails передается объект ScriptInjection. Между ними есть несколько различий. Например, tabId теперь передается как элемент ScriptInjection.target, а не как аргумент метода.

Пример ниже показывает, как это сделать.

Manifest V2
async function getCurrentTab() {/* ... */}
let tab = await getCurrentTab();

browser.tabs.executeScript(
  tab.id,
  {
    file: 'content-script.js'
  }
);

В файле фонового скрипта.

Manifest V3
async function getCurrentTab()
let tab = await getCurrentTab();

browser.scripting.executeScript({
  target: {tabId: tab.id},
  files: ['content-script.js']
});

В файле service worker расширения.

Замените tabs.insertCSS() и tabs.removeCSS() на scripting.insertCSS() и scripting.removeCSS().

В Manifest V3 insertCSS() и removeCSS() переходят из API tabs в scripting API. Для этого необходимо изменить разрешения в файле манифеста и код.

  • Разрешение "scripting".
  • Разрешения хоста или разрешение "activeTab".

Функции API scripting похожи на функции tabs. Однако между версиями есть несколько отличий.

  • При вызове этих методов вы передаете объект CSSInjection вместо InjectDetails.
  • Теперь tabId передается как элемент CSSInjection.target, а не как аргумент метода.

В примере ниже показано, как это сделать для insertCSS(). Процедура для removeCSS() такая же.

Manifest V2
browser.tabs.insertCSS(tabId, injectDetails, () => {
  // callback code
});

В файле фонового скрипта.

Manifest V3
const insertPromise = await browser.scripting.insertCSS({
  files: ["style.css"],
  target: { tabId: tab.id }
});
// Remaining code. 

В файле service worker расширения.

Замена действий в браузере и на странице действиями

В Manifest V2 действия браузера и действия на странице были разными понятиями. Хотя они начинали с разных ролей, со временем различия между ними уменьшились. В Manifest V3 эти концепции объединены в Action API. Для этого нужно внести изменения в код manifest.json и расширения, которые отличаются от того, что вы бы добавили в фоновый скрипт Manifest V2.

Действия в Manifest V3 больше всего похожи на действия браузера, однако API action не предоставляет hide() и show(), как это делал pageAction. Если вам по-прежнему нужны действия на странице, вы можете эмулировать их с помощью декларативного контента или вызвать enable() или disable() с идентификатором вкладки.

Замените browser_action и page_action на action

В manifest.json замените поля "browser_action" и "page_action" полем "action". Ознакомьтесь с информацией о поле "action".

Manifest V2
{
  ...
  "page_action": { ... },
  "browser_action": {
    "default_popup": "popup.html"
   }
  ...
}
Manifest V3
{
  ...
  "action": {
    "default_popup": "popup.html"
  }

  ...
}

Замените API browserAction и pageAction на API action

Если в Manifest V2 вы использовали API browserAction и pageAction, теперь вам нужно использовать API action.

Manifest V2
browser.browserAction.onClicked.addListener(tab => { ... });
browser.pageAction.onClicked.addListener(tab => { ... });
Manifest V3
browser.action.onClicked.addListener(tab => { ... });

Замените обратные вызовы промисами

В Manifest V3 многие методы API расширений возвращают промисы. Promise – это прокси-сервер или плейсхолдер для значения, возвращаемого асинхронным методом. Если вы никогда не использовали Promises, вы можете прочитать о них на MDN. На этой странице описано, что нужно знать, чтобы использовать их в расширении Chrome.

Для обратной совместимости многие методы продолжают поддерживать обратные вызовы после добавления поддержки обещаний. Обратите внимание, что вы не можете использовать оба параметра в одном вызове функции. Если вы передадите обратный вызов, функция не вернет обещание. Если вы хотите, чтобы обещание было возвращено, не передавайте обратный вызов. Для некоторых функций API, например прослушивателей событий, по-прежнему будут требоваться обратные вызовы. Чтобы узнать, поддерживает ли метод промисы, найдите в документации по API пометку Promise.

Чтобы перейти от обратного вызова к объекту Promise, удалите обратный вызов и обработайте возвращенный объект Promise. Пример ниже взят из примера необязательных разрешений, в частности newtab.js. В версии с обратным вызовом показано, как будет выглядеть вызов request() с обратным вызовом. Обратите внимание, что версию с промисом можно переписать с помощью async и await.

Обратный звонок
browser.permissions.request(newPerms, (granted) => {
  if (granted) {
    console.log('granted');
  } else {
    console.log('not granted');
  }
});
Promise
const newPerms = { permissions: ['topSites'] };
browser.permissions.request(newPerms)
.then((granted) => {
  if (granted) {
    console.log('granted');
  } else {
    console.log('not granted');
  }
});

Замените функции, которые ожидают фоновый контекст Manifest V2

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

  • browser.runtime.getBackgroundPage()
  • browser.extension.getBackgroundPage()
  • browser.extension.getExtensionTabs()

Скрипты расширения должны использовать передачу сообщений для связи между сервис-воркером и другими частями расширения. Сейчас это можно сделать с помощью sendMessage() и реализации browser.runtime.onMessage в сервис-воркере расширения. В долгосрочной перспективе вам следует заменить эти вызовы на postMessage() и обработчик событий сообщений сервисного работника.

Замените неподдерживаемые API

В Manifest V3 нужно изменить методы и свойства, перечисленные ниже.

Метод или свойство Manifest V2 Заменить на
browser.extension.connect() browser.runtime.connect()
browser.extension.connectNative() browser.runtime.connectNative()
browser.extension.getExtensionTabs() browser.extension.getViews()
browser.extension.getURL() browser.runtime.getURL()
browser.extension.lastError Если методы возвращают объекты Promise, используйте promise.catch().
browser.extension.onConnect browser.runtime.onConnect
browser.extension.onConnectExternal browser.runtime.onConnectExternal
browser.extension.onMessage browser.runtime.onMessage
browser.extension.onRequest browser.runtime.onMessage
browser.extension.onRequestExternal browser.runtime.onMessageExternal
browser.extension.sendMessage() browser.runtime.sendMessage()
browser.extension.sendNativeMessage() browser.runtime.sendNativeMessage()
browser.extension.sendRequest() browser.runtime.sendMessage()
browser.runtime.onSuspend (фоновые скрипты) Не поддерживается в сервисных рабочих процессах расширений. Вместо этого используйте событие документа beforeunload.
browser.tabs.getAllInWindow() browser.tabs.query()
browser.tabs.getSelected() browser.tabs.query()
browser.tabs.onActiveChanged browser.tabs.onActivated
browser.tabs.onHighlightChanged browser.tabs.onHighlighted
browser.tabs.onSelectionChanged browser.tabs.onActivated
browser.tabs.sendRequest() browser.runtime.sendMessage()
browser.tabs.Tab.selected browser.tabs.Tab.highlighted