Устройство расширений для браузера Firefox (WebExtensions)

Для людей, работа которых связана с использованием сети Интернет, расширения браузера могут быть очень полезными инструментами. С помощью них можно избавить пользователя от повторения одних и тех же действий и лучше организовать рабочий процесс. Можно составить набор инструментов из уже существующих расширений, но этого бывает недостаточно.

Тому, кто разбирается в веб-разработке, будет несложно создать новое расширение для браузера. Сейчас большинство самых популярных браузеров поддерживает стандартную систему разработки, которая использует в основном только JavaScript, HTML и CSS, — WebExtensions.

Человеку, который никогда раньше не создавал дополнение для браузера на основе WebExtensions, может быть тяжело сразу понять, из каких основных частей оно должно состоять и что может делать. В сети Интернет есть много информации об этой системе, но для того, чтобы создать для себя общую картину, придётся потратить много времени. Эта статья поможет быстро разобраться в устройстве системы WebExtensions и покажет, как лучше ориентироваться в документации к её API. Здесь описывается расширение для браузера Firefox, поэтому почти вся информация, используемая в статье, взята с сайта MDN. Но статья будет полезна и тем, кто хочет создать расширение для других браузеров, поддерживающих WebExtensions, — в первую очередь для Google Chrome и Chromium.

Здесь рассматривается создание расширений только для настольных компьютеров. Если нужно создать расширение для мобильного браузера Chrome или Firefox, эта статья тоже может быть чем-то полезной, но основную часть информации придётся найти и изучить самостоятельно.


Вступление


Что нужно, чтобы начать

А нужно вот что:


  • Браузер Firefox — лучше всего версии 60 или выше. Во всей статье подразумевается, что используется именно такой браузер, если не сказано другое. Но можно вместо этого использовать Google Chrome или Chromium.
  • Знания в HTML и CSS, достаточные для создания хотя бы несложных веб-страниц.
  • Знания Javascript. Не обязательно в совершенстве знать последний стандарт ECMA, но как работать с Promise нужно знать.
  • Знания английского языка, достаточные для чтения документации к API. Информации, переведённой на русский язык, на эту тему мало (на момент написания статьи), и иногда она может быть неполной. Но всё-таки лучше попробуйте переключать язык на «английских» страницах MDN — может быть, там уже есть перевод на русский язык.
  • Иногда при создании расширения могут пригодиться знания языка Python или платформы Node.js.
  • И, конечно же, нужно желание научиться чему-то новому и написать своё расширение для браузера.


О браузерах

Firefox до версии 60 хуже поддерживал WebExtensions — там не были реализованы многие полезные функции. Но вообще более-менее сносно Firefox поддерживает эту систему начиная с версии 52.

В Google Chrome или Chromium расширения на основе WebExtensions всегда работают хорошо, ведь эта система изначально была сделана как их часть. У них, собственно, другие браузеры и позаимствовали эту систему. У API для браузера Firefox есть существенные отличия, о которых можно узнать из статьи Building a cross-browser extension. Она может помочь и для того, чтобы сделать расширение, которое подойдёт как для Firefox, так и для Chrome.

Независимо от того, для какого браузера создаётся расширение, может пригодиться информация об API расширений Chrome.


Об использовании других браузеров

Многие из популярных браузеров работают на том же «движке», что и Google Chrome. Это и Яндекс-Браузер, и Opera, и Microsoft Edge. Поэтому и механизм расширений у всех этих браузеров очень похож на тот, что используется в Chrome. Отличия в API WebExtensions у этих браузеров от браузера Chrome, конечно, есть, но обычно их меньше, чем у Firefox.

Для Яндекс-Браузера на момент написания статьи рекомендовалось использовать расширения из каталога для браузера Opera. Значит, скорее всего, API для расширений у двух этих браузеров если и различаются, то мало. Поэтому, если будет нужно создать расширение для Яндекс-Браузера или Opera, обязательно просмотрите API для браузера Opera.

Если нужно сделать расширение для Edge, тогда смотрите список его средств API на сайте Microsoft.



Первый взгляд на расширение

Для начала поверхностно рассмотрим, что такое расширение и каковы его основные возможности. Большинство ссылок в этом разделе ведут к более подробному описанию в этой же статье, поэтому раздел можно использовать как своеобразное оглавление. Но учтите, что ссылки будут даны не в том порядке, в котором идут главы статьи.

Расширение — это набор скриптов. Самый главный из них — manifest.json. В некоторых случаях расширение может состоять вообще только из этого файла — такое может быть у расширения-темы, которое только изменяет стиль оформления окна браузера. В файле-манифесте содержится вся информация о расширении, а также о том, что и когда нужно запускать, что расширению разрешено делать, к каким ресурсам оно само даёт доступ, и некоторые настройки браузера. Остальное — скрипты Javascript, HTML, CSS, а также данные для них (например, файлы изображений).

Если совсем коротко, вот что может делать расширение:


  • Добавить элементы управления в браузер. Это могут быть кнопки в панели инструментов браузера, похожие на те, что вызывают меню Настройки или Добавить страницу в закладки. Можно добавить и всплывающие меню, которые появляются при нажатии на них. А ещё можно добавить боковую панель браузера.
  • Добавить в содержимое загруженной веб-страницы свои скрипты и файлы стилей.
  • Добавить фоновый скрипт, который будет работать всё время, пока работает браузер. С помощью него, например, можно координировать действия всех остальных скриптов в расширении.
  • Добавить горячие клавиши, при нажатии которых выполняются определённые действия.
  • Добавить свои опции в контекстное меню браузера, которое появляется при клике правой кнопкой мыши в окне браузера.
  • Добавить страницу опций, показывающую описание расширения и органы управления для изменения его настроек в Менеджере Дополнений браузера.
  • Добавить внешнюю программу или скрипт, которая будет работать прямо в операционной системе, а не в браузере. Браузер будет запускать эту программу и обмениваться с ней сообщениями. Можно даже подключить к расширению обычную программу, используя свою программу-переходник.
  • Использовать ещё много разных функций браузера в своём расширении.

Скрипты расширения делятся на группы, у каждой из которых — свои программная среда и время жизни. Эти группы называются контекстами выполнения. У каждого всплывающего меню, а также у фонового скрипта и у скриптов, добавленных в веб-страницу, и у других подобных частей расширения — свои отдельные контексты выполнения.

Скрипты разных контекстов выполнения могут общаться друг с другом с помощью механизмов сообщений — например, передавая информацию о нужных событиях.

По умолчанию расширению доступны только «безопасные» возможности, то есть только часть API WebExtensions. Чтобы использовать больше средств API, нужно дать расширению разрешения на доступ к ним.

Дополнительно можно почитать эти статьи:


Описание системы WebExtensions

Теперь рассмотрим основные понятия и особенности, связанные с созданием расширения в системе WebExtensions, с которыми придётся часто сталкиваться и в данной статье, и при чтении документации на MDN. Почти все ссылки этого раздела тоже ведут к разным местам текущей статьи.


API WebExtensions: точка входа

Любому скрипту расширения доступен глобальный объект, который содержит все свойства и функции API WebExtensions, доступные в этом скрипте. В расширениях для браузера Firefox он называется browser, а для Google Chrome — chrome. Но главный, родительский объект для скриптов расширения — это всегда window, — как и у скриптов обычных страниц веб-сайтов.

Таким образом, каждому скрипту расширения всегда доступно два глобальных объекта. Один из них — это объект window. Другой объект — точка входа в API WebExtensions, в нашем случае — browser. Этот объект не является частью window и существует параллельно ему. Всё это значит, что любые объекты и функции, определённые в скрипте глобально, — как обычно, будут частью объекта window, и для доступа к ним не обязательно каждый раз писать »window.» перед их именем. А для доступа к средствам API WebExtensions нужно каждый раз добавлять »browser.» перед именем объекта или функции. Например, просматривая документацию к WebExtensions на сайте MDN, можно заметить, что через объект runtime.id можно узнать идентификатор расширения. Если посмотреть его подробное описание, синтаксис для доступа к нему —

var myAddonId = browser.runtime.id;

Состав объекта browser может отличаться как в разных скриптах, так и в разных расширениях. Это зависит от того, к какой части API WebExtensions разрешён доступ всему расширению, и в каком контексте выполнения работает скрипт.


Контексты выполнения

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


Подключенная внешняя программа в данном разделе не рассматривается

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


Каждому контексту выполнения доступна DOM своего отдельного документа. Да-да, каждой части расширения соответствует некоторая HTML-страница, даже если она никому не видна, и даже если никто не добавлял в расширение соответствующий HTML-файл! И, конечно, у всех скриптов одного и того же контекста выполнения — общие глобальные объекты window и browser.

Все контексты выполнения можно разделить на две группы. В первую группу входит всего один вид контекстов — контексты содержимого веб-страниц. В каждом из них работает набор скриптов, добавленных нашим расширением к загруженной с сервера веб-странице. То есть каждой вкладке браузера, в которую наше расширение добавило скрипты, соответствует один такой контекст выполнения. Во вторую группу входят все остальные, привилегированные контексты. В них работают те части расширения, которые добавляют функционал к самой программе браузера. Например, всплывающее меню, боковая панель, фоновый скрипт (или «фоновая страница») — работают в таких контекстах.


Привилегированные контексты выполнения

У привилегированных контекстов выполнения есть такие особенности:


  • Им доступен весь API WebExtensions, к которому разрешён доступ в файле манифеста. Именно поэтому в документации на сайте MDN они всегда называются привилегированными.
  • Содержимое любого из этих контекстов можно создать или в виде HTML-документа, к которому могут быть подключены файлы CSS и JavaScript, или как набор одних только файлов JavaScript. Во многих случаях HTML-документ подходит лучше. Например, содержимое добавленного в браузер всплывающего меню или боковой панели удобнее создавать тем же способом, что и обычные веб-страницы. Внимание: не используйте в таком HTML-файле код JavaScript, который находится непосредственно в элементе ! Иначе браузер может выдавать ошибки и будет тяжело сразу понять, откуда они взялись.
  • У скриптов этих контекстов нет прямого доступа к содержимому веб-страницы, открытой во вкладке браузера. Объект window такого контекста даёт доступ только к его собственному HTML-документу.
  • Любой привилегированный скрипт может добавлять JavaScript в контекст содержимого веб-страницы, открытой в любой вкладке или окне браузера. Для этого расширению обычно нужно дать одно из подходящих разрешений на доступ. Если нужно добавить скрипт во вкладку браузера, где открыт файл HTML, входящий в состав данного расширения, то разрешение не нужно. Подробнее об этом — в разделе о скриптах содержимого.


Контексты содержимого (не привилегированные)

Контекст содержимого веб-страницы отличается такими особенностями:


  • Ему доступна только небольшая часть API WebExtensions, поэтому такие контексты называют не привилегированными.
  • Скрипты содержимого добавляются к уже существующей загруженной в браузер веб-странице. Поэтому их контекст выполнения нельзя создать с помощью файла HTML — он заменил бы собой загруженную веб-страницу. Можно добавить только JavaScript и CSS.
  • Все скрипты такого контекста имеют доступ к DOM страницы, к которой они добавлены — как обычно, с помощью API объекта window. И время жизни этих скриптов почти совпадает со временем жизни «родных» скриптов веб-страницы. Тем не менее в описании рабочего окружения скриптов содержимого сказано, что их контекст выполнения не тот же самый, что у настоящих скриптов веб-страницы. Это значит, что у настоящей веб-страницы один объект window, а у добавленных к ней скриптов — другой.

Из последней особенности в списке видно, что можно выделить ещё один вид контекстов выполнения — назовём его контекстом подлинной страницы веб-сайта. Он тесно связан с контекстом содержимого расширения браузера, но, несмотря на это, не является частью расширения.


Время жизни

Каждому контексту выполнения отведено своё время жизни. Вернее, это время жизни его программного окружения: объекта window вместе с его HTML-документом и объекта browser. Например, время жизни всплывающего меню — пока видно это меню, а время жизни скриптов содержимого — от загрузки веб-страницы в браузер (или от момента, когда эти скрипты добавили) и до закрытия вкладки или начала загрузки следующей страницы. Время жизни отдельных контекстов выполнения будет указано в разделах о соответствующих частях расширения.


Взаимодействие между контекстами выполнения

Об уже упомянутых механизмах сообщений, которые используются для взаимодействия между контекстами выполнения, мы поговорим позже.


Структура папки проекта

Я советую не создавать файлы расширения прямо в корневой папке проекта, а сделать там несколько папок: одну — собственно, для файлов расширения («Extension»), ещё одну — для файлов, описывающих дизайн («Design»), и ещё одну — для внешней программы, если она нужна («Native»). Можно ещё добавить папку «Build», чтобы складывать туда готовые к публикации файлы-архивы. А внутри папки расширения для тех контекстов выполнения, которым соответствует более одного файла, лучше создать отдельные папки. В папке расширения файлы, которые не являются скриптами, тоже обычно раскладывают по папкам: например, для иконок обычно создают папку «icons», а файлы локализации обязательно должны быть в папке »_locales» (если расширение поддерживает несколько языков). В итоге папка проекта может выглядеть так:

My_project
|--Design
|  |--concept.md
|
|--Build
|  |--my_extension-1.0.0.zip
|
|--Native
|  |--native_program.py
|  |--native_program_manifest.json
|  |--run.bat
|  |--install.sh
|  |--install.bat
|
|--Extension
   |--manifest.json
   |--background.js
   |--content.js
   |--browser_popup
   |  |--menu.html
   |  |--menu.css
   |  |--menu.js
   |
   |--icons
      |--my_extension.svg


Манифест расширения

При установке и запуске расширения браузер читает файл manifest.json, который должен находиться в корневой папке расширения. Из этого манифеста он получает всю информацию о расширении и о том, как с ним работать. Этот файл должен быть в формате JSON. В него можно добавлять строчные комментарии в стиле JavaScript, что может быть полезным.


Манифест может быть единственным файлом в расширении

Файл-манифест не только обязателен для любого расширения. Он может быть и единственным файлом в расширении. Например, можно сделать расширение, при установке которого изменяется тема оформления браузера, используя только один файл манифеста. Смотрите документацию к элементу манифеста theme.


Документацию к файлу манифеста смотрите в статье о manifest.json на MDN.


Основные элементы манифеста

Файл манифеста лучше всего начинать с общего описания расширения, а именно — с трёх обязательных элементов:


  • manifest_version — в этом элементе всегда должно быть число 2.
  • name — строка, полное название расширения.
  • version — версия расширения в виде строки.

На всякий случай можно добавить ещё и сокращённое имя расширения — с помощью элемента short_name. Оно будет показываться там, где места для полного имени не хватает.

Следующим лучше добавить краткое описание расширения — с помощью элемента description


Информация об авторе

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


  • author — имя автора. Обычно здесь указывают короткое имя, по которому будут узнавать разработчика, или полные имя и фамилию, или название организации.
  • homepage_url — URL-адрес домашней страницы расширения. Обычно здесь указывают адрес веб-страницы на личном сайте автора, посвящённой расширению, или целого сайта о расширении, или адрес проекта на GitHub.

Вместо этих двух элементов можно использовать один элемент-группу developer. Он делает то же самое, только выглядит немного иначе.


Идентификатор расширения, поддерживаемые версии браузера

Теперь можно добавить элемент browser_specific_settings.


Во многих расширениях он называется по-старому — applications

В старых браузерах Firefox — до версии 48 — этот элемент был обязательным, и до версии 42 он назывался applications. Сейчас можно использовать как browser_specific_settings, так и applications, но многие расширения используют applications. Возможно так получилось потому, что эти расширения написаны уже давно и несколько раз их адаптировали для браузера новой версии, а это имя изменять было необязательно. А может и потому, что имя applications часто встречается в примерах расширений на MDN.


Этот элемент необязателен и поддерживается только браузером Firefox, но часто бывает полезным. С помощью него можно указать диапазон версий браузера, в которых расширение может работать, а также ID расширения. Если в расширении используется внешняя программа (которую мы рассмотрим позже) или взаимодействие с другими расширениями, то этот ID должен быть известен и лучше указать его вручную. А если ID знать не нужно, можно вообще не беспокоиться о его существовании. Тогда просто не указывайте его, и он будет присвоен расширению автоматически — когда будет нужен.


Как выбрать ID расширения

По стандарту идентификатором может быть или GUID или строка текста, похожая на адрес e-mail. Не пытайтесь генерировать GUID — это непрактично и бесполезно. Лучше использовать строку вида название_расширения@организация.org. Конечно, буквы здесь можно использовать только латинские. Вместо названия сайта организации можно использовать что угодно: или название личного сайта, или имя пользователя и сайт какого-нибудь сервиса или блога, на котором Вы зарегистрированы. На самом деле ID расширения нужен только для того, чтобы гарантированно отличить его от других расширений, и он почти никому не будет виден. Поэтому здесь не обязательно указывать настоящее название сайта или адрес e-mail. Например, если название расширения — my_extension, имя автора расширения — user, а личного сайта или сайта организации нет, то ID может быть одним из таких:

my_extension@user.habr.com
my_extension@user.github.com
my_extension@user.addons.mozilla.org


Иконка-логотип

Ещё нужно добавить иконку-логотип, по которой будут узнавать наше расширение. Она будет видна везде, где расширение должно быть обозначено: в Менеджере Дополнений (меню браузераДополненияРасширения) и в списке расширений на сайте, где оно будет опубликовано для общего использования. Для этого в манифест нужно добавить элемент icons.

В документации на MDN сказано, что стандартный размер иконки для Менеджера Дополнений — 48×48 пикселов, но на момент написания статьи намного чаще используется размер 32×32. А ещё желательно добавить иконки размером в два раза больше — для экранов с большим разрешением, таких как Retina display в устройствах от фирмы Apple. Таким образом, чтобы иконка всегда хорошо отображалась, нужно добавить изображения таких размеров: 32×32, 64×64, 48×48 и 96×96 пикселов.

Рекомендуется использовать изображения в формате PNG или SVG. Даже если использовать один и тот же файл SVG для разных размеров иконки, лучше определить его в манифесте несколько раз — для разных размеров. Кстати, браузер Google Chrome не поддерживает файлы SVG в качестве иконок.


Пример начала файла манифеста

Вот пример начала файла manifest.json. Название и описание расширения выдуманы, на самом деле такого расширения нет.

{
  // Это значение всегда должно быть числом 2
  "manifest_version": 2,

  // Название расширения
  "name": "Habr article editor",
  "short_name": "Habr Editor",

  // Версия
  "version": "1.0.0",

  // Краткое описание расширения
  "description": "Enhances editor of articles on habr.com site to support Markdown Extra",

  // Имя автора — никнейм или полное
  "author": "Aleksandr Solovyov",

  // Адрес домашней страницы расширения, обычно — специальный сайт
  // или страница на GitHub
  "homepage_url": "https://github.com/alexandersolovyov/habr_editor",


  // Идентификатор расширения и совместимые версии браузера Firefox
  "browser_specific_settings": {
    "gecko": {
      "id": "habr_editor@alexandersolovyov.github.com",
      "strict_min_version": "52.0"
    }
  },

  // Иконка-логотип
  "icons": {
    "32": "icons/habr_editor.svg",
    "64": "icons/habr_editor.svg",
    "48": "icons/habr_editor.svg",
    "96": "icons/habr_editor.svg"
  },

  ...
}

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


Разрешения на доступ к API

В целях безопасности, по умолчанию расширению доступен не весь API WebExtensions. Для того, чтобы открыть доступ к «небезопасным» средствам API, в файле-манифесте расширения нужно объявить соответствующие разрешения на доступ.

Такие разрешения добавляют с помощью элемента permissions в манифесте расширения. Если объявлены такие разрешения, при установке расширения пользователь увидит всплывающее окно, где будут перечислены дополнительные возможности, которые требует расширение, и вопрос, можно ли дать разрешение на доступ к ним. Если пользователь посчитает, что расширение требует слишком много возможностей и поэтому может быть опасным, он ответит «Не разрешать», и установка расширения будет отменена.

Некоторые разрешения лучше запросить позже, во время выполнения расширения. Например, пользователя может насторожить, что расширение при установке требует доступ к данным о его месте расположения. Лучше, чтобы расширение спросило разрешение в тот момент, когда эти данные будут использоваться. Для таких случаев используется элемент манифеста optional_permissions. Количество разрешений, доступных при его использовании, немного меньше, чем у элемента permissions. Зато каждое из разрешений в этом списке будет запрашиваться только прямо перед использованием соответствующего средства API.

Список разрешений в манифесте представляет собой массив — как для элемента permissions, так и для optional_permissions. Разрешение на доступ к каждому из средств API даётся при добавлении специального ключевого слова в этот массив. Многие из этих слов совпадают с названиями средств API, к которым они дают доступ. Информацию о том, к каким возможностям можно открыть доступ, можно получить из списка ключевых слов для элемента permissions, а также из списка для элемента optional_permissions. Внимание: не забудьте посмотреть на таблицу совместимости с браузерами внизу этих страниц — она точнее показывает, какие ключевые слова можно использовать в действительности! Подробно узнать о средствах API, названных в этих списках, можно из описания всех средств API WebExtensions. Если в списке средств API не получается найти то, что нужно — просто добавляйте в расширение нужный функционал, читая документацию о соответствующих средствах API, и увидите, какие разрешения нужно добавить.


Разрешения для доступа к содержимому веб-страниц

Изначально доступ скриптов расширения к содержимому веб-страниц немного ограничен. Чтобы снять ограничения, нужно дать разрешение на доступ к определённым сайтам (host permissions) или к активной вкладке браузера (activeTab). В зависимости от целей, лучше выбрать один из этих видов разрешений.

Разрешение activeTab относительно безобидно. Оно даёт дополнительные полномочия для работы с активной вкладкой браузера, при этом не открывая слишком большой доступ к веб-сайту. Когда объявлено это разрешение, в активную вкладку можно добавлять скрипты содержимого из любых привилегированных скриптов, а также получать доступ к её адресу URL, заголовку и файлу иконки. Подобного эффекта можно добиться, если одновременно использовать разрешения и tabs, но тогда полномочия расширения зачастую будут больше, чем нужно.

Разрешения host permissions более потенциально опасны. В списке разрешений они обычно представлены как шаблоны адреса URL и дают расширению практически полный доступ к веб-сайтам, чей адрес URL совпадает с одним из этих шаблонов. К разрешённым таким образом сайтам можно добавлять скрипты содержимого из любых привилегированных скриптов, отправлять запросы AJAX из любого скрипта содержимого — даже из тех, которые были добавлены к странице другого сайта, а также читать и изменять данные HTTP-запросов и файлов cookie. Разрешение тоже относится к host permissions. Оно даёт доступ ко всем сайтам сразу, поэтому его лучше использовать только в крайних случаях.


Страница настроек расширения (options page)

Не забудьте добавить в расширение страницу настроек, которая ещё называется страницей опций — особенно если расширение будет опубликовано для использования другими людьми. Когда пользователь установит расширение, откроет меню браузера и в нём выберет ДополненияРасширения (Менеджер Дополнений), он увидит список установленных расширений. В этом списке, при нажатии на кнопку (или ссылку, или пункт всплывающего меню) Настройки расширения, будет показана страница опций. На ней обычно дают краткую информацию о расширении, краткую инструкцию по использованию или ссылку на страницу помощи и, конечно же, меню настроек расширения. Если нужны примеры — можно установить какое-нибудь расширение и посмотреть его страницу опций.

Эту страницу создают таким же образом, как и обычную веб-страницу: файл HTML, к которому подключены CSS и JavaScript.

HTML-файл страницы опций подключают к расширению в файле манифеста с помощью элемента options_ui. Обычно страница опций открывается прямо в Менеджере Дополнений, в специально отведённом месте. Если нужно, чтобы эта страница открывалась в отдельной вкладке, добавьте "open_in_tab": true в свойства элемента options_ui.

Страница опций работает в отдельном контексте выполнения, который, конечно же, является привилегированным. Время жизни скриптов этой страницы — пока она открыта.

Более подробное описание страницы опций есть в статье Options page.

Для хранения настроек расширения используйте storage API.


Об опции «Подробности» в Мереджере Дополнений

Можно заметить, что в Менеджере Дополнений браузера у каждого расширения есть опция Подробности. В старых версиях Firefox (приблизительно до 68) она, как правило, открывала ту же самую страницу опций. В более свежих версиях браузера опция Подробности открывает вкладку с общей информацией о расширении. Причём краткое описание расширения берётся не из файла-манифеста расширения или из какого-то другого файла. Его нужно написать при регистрации расширения на сайте расширений Firefox.



Фоновый скрипт

Очень часто расширению нужен фоновый скрипт. Он работает всё время, пока работает браузер — при условии, что расширение установлено и включено.

Можно создать один или более таких файлов JavaScript, или целую фоновую HTML-страницу с подключёнными к ней скриптами (и даже файлами CSS!). Эти файлы добавляются в расширение с помощью элемента background файла манифеста. Конечно, фоновая страница никогда не будет видна пользователю, а её элементы DOM нельзя полноценно использовать в других контекстах выполнения. Поэтому польза от фонового файла HTML небольшая.


Не стоит использовать фоновую HTML-страницу как библиотеку

Файл HTML в качестве фоновой страницы может быть полезен для того, чтобы вынести список используемых в расширении фоновых скриптов в отдельный файл. Использовать фоновую страницу в качестве библиотек функций и HTML-элементов — обычно, плохая идея.

В API WebExtensions есть одна любопытная функция — browser.runtime.getBackgroundPage (). Она наталкивает на мысль, что фоновую страницу можно использовать как библиотеку элементов DOM или функций JavaScript. Но, во-первых, она ненадёжна: если она используется в скрипте всплывающего меню, и пользователь открыл веб-страницу в приватном режиме, функция возвращает пустое значение. Во-вторых, она вообще не работает в скриптах содержимого — в единственном месте, где действительно пригодилась бы библиотека HTML-элементов.

С помощью механизма сообщений WebExtensions тоже нельзя передать HTML-элементы и функции. Конечно, можно передавать HTML в виде текста, но тогда для превращения этой строки обратно в элемент DOM придётся создать специальную функцию или использовать дополнительные библиотеки (смотрите ответ на StackOverflow). Чаще всего для всплывающих меню и боковых панелей такая HTML-библиотека не нужна, а для скриптов, добавленных в страницу, есть способы добавить отдельный файл HTML.

Если нужно добавить в расширение библиотеки функций, лучше используйте элемент user_scripts манифеста расширения, который появился в Firefox с версии 68. Или подключайте нужные файлы JavaScript к каждому контексту выполнения.


Фоновый скрипт можно использовать для координации действий скриптов других контекстов выполнения: например, получать сообщения о событиях от одних контекстов выполнения и давать команды скриптам других контекстов. Механизм сообщений WebExtensions мы рассмотрим позже. В фоновом скрипте можно хранить данные о состоянии программы — флаги и параметры, которые изменяются во время работы расширения и могут быть сброшены в начальное состояние каждый раз при перезагрузке браузера. В этом случае обратите внимание на значение persistent элемента background в файле манифеста — установите его значение в true. А бывает и так, что все основные действия выполняются в фоновом скрипте, и он является чуть ли ни единственным файлом JavaScript в расширении.


Добавление элементов управления в браузер

Вот в какие места вкладки браузера можно добавить элементы управления:


Окно браузера с указателями на элементы управления

  1. В верхней панели инструментов браузера Firefox, справа, между строкой адреса (или поиска) и кнопкой Открыть Меню, обычно есть кнопки управления, среди которых могут быть Просмотр истории, Показать закладки и другие. Можно добавить рядом с ними свою кнопку. Для этого в файл манифеста нужно добавить элемент browser_action. Эту кнопку можно использовать для вызова всплывающего меню, которое можно создать подобно веб-странице — с помощью HTML, CSS и JavaScript. Как и другие всплывающие меню браузера, оно будет закрываться при нажатии мышкой за его пределами. Если всплывающее меню не нужно — добавьте в фоновый скрипт обработчик события нажатия на кнопку с помощью функции .addListener() объекта-события browser.browserAction.onClicked. Чтобы получить больше информации о кнопке в панели инструментов — смотрите Toolbar Buttton на MDN
  2. Точно таким же образом можно добавить кнопку в строке для ввода URL в панели инструментов браузера. Для этого используется другой элемент файла манифеста — page_action. Эта кнопка тоже может открывать всплывающее окно. Если кнопка не должна вызывать окно, обработчик в фоновом скрипте добавляется для события browser.pageAction.onClicked. Больше информации о кнопке в строке адреса — на странице Address bar button.
  3. У браузера Firefox есть встроенные боковые панели, которые можно открыть с помощью кнопки Показать боковые панели в панели инструментов браузера или через меню окна браузера Вид → Боковая панель. Можно создать свою боковую панель, добавив в файл манифеста элемент sidebar_action. Эта панель откроется автоматически после установки расширения — так браузер показывает, что оно использует боковую панель. Правда, её нельзя будет открывать автоматически с помощью скриптов расширения — как и встроенные боковые панели. Зато можно назначить горячие клавиши (подробнее о которых — позже), чтобы пользователь мог быстро её открыть. Как и всплывающее меню,

    © Habrahabr.ru