Несовместимости с Chrome
Расширения, созданные с использованием API WebExtension, предназначены для совместимости с расширениями Chrome и Opera. По возможности, расширения, написанные для этих браузеров, должны работать в Firefox с минимальными изменениями.
Однако существуют значительные различия между Chrome, Firefox и Edge. В частности:
- Поддержка JavaScript-API различается в разных браузерах. Подробнее см. Поддержка JavaScript-API в разных браузерах.
- Поддержка
manifest.jsonключей различается в разных браузерах. Подробнее см. раздел "Совместимость с браузерами" на страницеmanifest.json. - JavaScript-API:
-
В Firefox: к JavaScript-API обращаются в пространстве имен
browser. -
В Chrome и Edge: к JavaScript-API обращаются в пространстве имен
chrome. (см. ошибку Chrome 798169)
-
В Firefox: к JavaScript-API обращаются в пространстве имен
- Асинхронные API:
- В Firefox: асинхронные API реализованы с использованием промисов.
- В Chrome и Edge: асинхронные API реализованы с использованием обратных вызовов. (см. ошибку Chrome 328932)
В остальной части этой страницы подведены итоги этим и другим несовместимостям.
JavaScript-API
Пространство имен chrome.* и browser.*
-
В Firefox: эквивалентные API доступны через пространство имен
browser.browser.browserAction.setIcon({path: "path/to/icon.png"});
-
В Chrome: расширения обращаются к привилегированным JavaScript-API в пространстве имен
chrome.chrome.browserAction.setIcon({path: "path/to/icon.png"});
Обратные вызовы и промисы
-
В Firefox: асинхронные API используют промисы для возврата значений вместо этого.
function logCookie(c) { console.log(c); } function logError(e) { console.error(e); } let setCookie = browser.cookies.set( {url: "https://developer.mozilla.org/"} ); setCookie.then(logCookie, logError);
-
В Chrome: асинхронные API используют обратные вызовы для возврата значений и
runtime.lastErrorдля передачи ошибок.function logCookie(c) { if (chrome.runtime.lastError) { console.error(chrome.runtime.lastError); } else { console.log(c); } } chrome.cookies.set( {url: "https://developer.mozilla.org/"}, logCookie );
Firefox поддерживает оба пространства имен chrome и browser
Для облегчения переноса реализация WebExtensions в Firefox поддерживает chrome, используя обратные вызовы, а также browser, используя промисы. Это означает, что многие расширения Chrome будут работать в Firefox без каких-либо изменений.
Примечание: Однако это не является частью стандарта WebExtensions и может не поддерживаться всеми совместимыми браузерами.
Если вы хотите написать свое расширение, чтобы использовать browser и промисы, то Firefox также предоставляет полифил, который позволит ему работать в Chrome: https://github.com/mozilla/webextension-polyfill.
Частично поддерживаемые API
Страница Поддержка JavaScript-API в разных браузерах содержит таблицы совместимости для всех API, которые частично поддерживаются в Firefox. В случаях, когда есть замечания относительно поддержки того или иного элемента API, это указано в этих таблицах с звездочкой «*», а в справочной странице по элементу API поясняются эти замечания.
Эти таблицы сгенерированы из данных о совместимости, хранящихся в файлах JSON в GitHub.
В остальной части этого раздела описываются проблемы совместимости, которые еще не отражены в таблицах.
API уведомлений
Для notifications.create(), с type "basic":
-
В Firefox:
iconUrlявляется необязательным. -
В Chrome:
iconUrlявляется обязательным.
Когда пользователь нажимает на уведомление:
- В Firefox: уведомление удаляется немедленно.
- В Chrome: это не так.
Если вы вызываете notifications.create() более одного раза подряд:
-
В Firefox: в Firefox уведомления могут вообще не отображаться. Ожидание для последующих вызовов до начала выполнения обратного вызова
chrome.notifications.create()не является достаточным временем ожидания для предотвращения этого.
API прокси
API прокси Firefox proxy имел совершенно иную структуру по сравнению с API прокси Chrome.
- В Firefox: расширение может зарегистрировать файл PAC.
- В Chrome: расширение может зарегистрировать файл PAC, но также может определить явные правила проксирования.
Поскольку этот API несовместим с API прокси Chrome proxy, API прокси Firefox доступен только через пространство имен browser.
API вкладок
При использовании tabs.executeScript() или tabs.insertCSS():
- В Firefox: передаваемые относительные URL интерпретируются относительно текущего URL страницы.
- В Chrome: эти URL интерпретируются относительно базового URL расширения.
Для кросс-браузерной работы можно указать путь в виде абсолютного URL, начинающегося с корня расширения, например:
/path/to/script.js
При запросе вкладок по URL tabs.query():
-
В Firefox: расширения должны иметь разрешение
"tabs". -
В Chrome: расширениям не нужно разрешение
"tabs", но в результаты будут включены только вкладки, URL которых соответствуют разрешениям хоста расширения.
При вызове tabs.remove():
-
В Firefox: промис
tabs.remove()выполняется после событияbeforeunload. -
В Chrome: обратный вызов не ожидает события
beforeunload.
API webrequest
-
В Firefox:
- Перенаправление запросов возможно только если исходный URL использует схему
http:илиhttps:. - Разрешение
activeTabне позволяет перехватывать сетевые запросы в текущей вкладке. (См. ошибку 1617479) - События не генерируются для системных запросов (например, обновление расширений или предложения в строке поиска).
-
С Firefox 57: Firefox делает исключение для расширений, которым необходимо перехватывать
webRequest.onAuthRequiredдля авторизации прокси. См. документацию поwebRequest.onAuthRequired.
-
С Firefox 57: Firefox делает исключение для расширений, которым необходимо перехватывать
- Если расширение хочет перенаправить публичный (например, HTTPS) URL на страницу расширения, файл manifest расширения должен содержать ключ
web_accessible_resourcesс URL страницы расширения.-
Примечание: Любой веб-сайт может затем ссылаться или перенаправлять на этот URL, и расширения должны рассматривать любой ввод (например, данные POST) как поступающий от ненадежного источника, как и обычная веб-страница.
-
- Некоторые API
browser.webRequest.*позволяют возвращать промисы, которые разрешаютсяwebRequest.BlockingResponseасинхронно.
- Перенаправление запросов возможно только если исходный URL использует схему
-
В Chrome: только
webRequest.onAuthRequiredподдерживает асинхронноеwebRequest.BlockingResponse, используя'asyncBlocking'.
API окон
-
В Firefox: вызовы
onFocusChangedAPIwindowsбудут срабатывать несколько раз при изменении фокуса.
Неподдерживаемые API
API declarativeContent
-
В Firefox: API declarativeContent Chrome ещё не реализован. Кроме того, Firefox не будет поддерживать API
declarativeContent.RequestContentScript(который редко используется и недоступен в стабильных версиях Chrome).
Разные несовместимости
URL в CSS
- В Firefox: URL в инжектированных файлах CSS разрешаются относительно самого файла CSS.
- В Chrome: URL в инжектированных файлах CSS разрешаются относительно страницы, в которую они инжектированы.
Поддержка диалоговых окон в страницах фона
web_accessible_resources
-
В Firefox: Ресурсам присваивается случайный UUID, который меняется для каждой инстанции Firefox:
moz-extension://«random-UUID»/«path». Эта случайность может помешать вам выполнить некоторые действия, такие как добавление URL вашего конкретного расширения в политику CSP другого домена. -
В Chrome: Когда ресурс перечислен в
web_accessible_resources, он доступен какchrome-extension://«your-extension-id»/«path». Идентификатор расширения фиксирован для данного расширения.
Свойство манифеста "key"
-
В Firefox: Поскольку Firefox использует случайные UUID для
web_accessible_resources, это свойство не поддерживается. -
В Chrome: При работе с нераспакованным расширением манифест может содержать
"key"свойство для привязки идентификатора расширения к различным машинам. Это в основном полезно при работе сweb_accessible_resources.
Запросы HTTP(S) скриптов содержимого
- В Firefox: Когда скрипт содержимого выполняет запрос HTTP(S), вы обязательно должны указать абсолютные URL.
-
В Chrome: Когда скрипт содержимого выполняет запрос (например, используя
fetch()) к относительному URL (например,/api), он будет отправлен вhttps://example.com/api.
Окружение скрипта содержимого
-
В Firefox: Глобальное пространство имен скрипта содержимого не строго равно
window(Firefox bug 1208775). Более конкретно, глобальное пространство имен (globalThis) состоит из стандартных возможностей JavaScript, как обычно, плюсwindowв качестве прототипа глобального пространства имен. Большинство API DOM наследуются от страницы черезwindow, через Xray vision для защиты скрипта содержимого от изменений со стороны веб-страницы. Скрипты содержимого могут сталкиваться с объектами JavaScript из собственного глобального пространства имен или с заворачиваемыми через Xray версиями со страницы веб-сайта. -
В Chrome: Глобальное пространство имен
window, а доступные API DOM, как правило, независимы от веб-страницы (кроме совместного использования базового DOM). Скрипты содержимого не могут напрямую получить доступ к объектам JavaScript со страницы веб-сайта.
Выполнение кода на веб-странице из скрипта содержимого
-
В Firefox:
evalвыполняет код в контексте скрипта содержимого, аwindow.evalвыполняет код в контексте страницы. См. Использованиеevalв скриптах содержимого. -
В Chrome:
evalиwindow.evalвсегда выполняет код в контексте скрипта содержимого, а не в контексте страницы.
Обмен переменными между скриптами содержимого
-
В Firefox: Вы не можете обмениваться переменными между скриптами содержимого, присваивая их
this.{variableName}в одном скрипте, а затем пытаясь получить доступ к ним с помощьюwindow.{variableName}в другом. Это ограничение, созданное песочницей Firefox. Это ограничение может быть устранено, см. Firefox bug 1208775.
Жизненный цикл скрипта содержимого во время навигации
- В Firefox: Скрипты содержимого остаются инжектированными на веб-странице после того, как пользователь перешел на другую страницу, однако свойства объекта window уничтожаются. Например, если скрипт содержимого установит
window.prop1 = "prop", а пользователь затем перейдет на другую страницу и вернется на страницуwindow.prop1, тоwindow.prop1будет undefined. Эта проблема отслеживается в Firefox bug 1525400. Чтобы смоделировать поведение Chrome, отслеживайте события pageshow и pagehide. Затем смоделируйте инъекцию или уничтожение скрипта содержимого. - В Chrome: Скрипты содержимого уничтожаются, когда пользователь переходит на другую веб-страницу. Если пользователь затем возвращается на страницу через историю, нажав кнопку "Назад", скрипт содержимого снова инжектируется на веб-страницу.
Поведение масштабирования "per-tab"
- В Firefox: Уровень масштабирования сохраняется при переходе между страницами и навигации в рамках вкладки.
- В Chrome: Изменения масштабирования сбрасываются при навигации; навигация по вкладке всегда загружает страницы с их факторами масштабирования по происхождению.
Ключи manifest.json
Основная страница manifest.json содержит таблицу, описывающую поддержку браузеров для manifest.json ключей. В случаях, когда есть оговорки относительно поддержки определенного ключа, это указывается в таблице звездочкой "*" и на странице справки по ключу подробно объясняются эти оговорки.
Эти таблицы сгенерированы из данных совместимости, хранящихся в виде JSON-файлов на GitHub.
Нативное сообщение
Аргументы месседжинга на основе соединений
В Linux и macOS: Chrome передает один аргумент в приложение, который является происхождением расширения, которое его запустило, в формате: chrome-extension://«extensionID/» (требуется конечный слэш). Это позволяет приложению идентифицировать расширение.
В Windows: Chrome передает два аргумента:
- Происхождение расширения
- Дескриптор окна Chrome, которое запустило приложение
Разрешенные расширения
-
В Firefox: Ключ манифеста называется
allowed_extensions. -
В Chrome: Ключ манифеста называется
allowed_origins.
Расположение манифеста приложения
- В Chrome: Манифест приложения ожидается в другом месте. См. Расположение хоста нативного сообщения в документации Chrome.
Сохранение приложения
-
В Firefox: Когда соединение нативного месседжинга закрывается, Firefox убивает дочерние процессы, если они не отвязались. В Windows браузер помещает процесс приложения в объект задания и убивает задание. Если приложение запускает другие процессы и хочет, чтобы они оставались открытыми после закрытия родительского приложения, приложение должно использовать
CreateProcess, а неShellExecute, чтобы запустить дополнительный процесс со флагомCREATE_BREAKAWAY_FROM_JOB.
Алгоритм клонирования данных
Некоторые расширенные API позволяют расширению отправлять данные из одной части расширения в другую, такие как runtime.sendMessage(), tabs.sendMessage(), runtime.onMessage, метод postMessage() объекта runtime.port и tabs.executeScript().
- В Firefox: Используется алгоритм структурного клонирования.
- В Chrome: Используется алгоритм сериализации JSON. В будущем может быть переключен на алгоритм структурного клонирования (задача 248548).
Алгоритм структурного клонирования поддерживает больше типов, чем алгоритм сериализации JSON. Заметным исключением являются (DOM) объекты с методом toJSON. DOM-объекты по умолчанию не клонируются и не сериализуются в JSON, но с помощью метода toJSON(), их можно сериализовать в JSON (но всё равно не клонировать с помощью алгоритма структурного клонирования). Примерами JSON-сериализуемых объектов, которые не поддерживают структурное клонирование, являются экземпляры URL и PerformanceEntry.
Расширения, которые полагаются на метод toJSON() алгоритма сериализации JSON, могут использовать JSON.stringify(), за которым следует JSON.parse(), чтобы гарантировать обмен сообщением, так как разобранное значение JSON всегда структурно клонируемо.
© 2005–2023 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Chrome_incompatibilities