За обновлениями можно следить в telegram-канале https://t.me/quasiart

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

Формат NEX

Opera поддерживает расширения в формате NEX (Navigator Extension). Все файлы и каталоги расширения упакованы в zip-файл со специальным заголовком и имеющим расширение .nex. Ввиду того, что Chromium имеет ту же основу, Opera поддерживает большинство расширений для Chromium. Список API, поддерживаемых Opera: https://dev.opera.com/extensions/apis/.

API из проекта Chromium, поддерживаемые в NEX-расширениях (например, вкладки) доступны в chrome.\*, а специфичные для Opera (например, для экспресс-панели) доступны в объекте opr.\*.

Стоит заметить, что Opera поддерживает расширения в CRX-формате, если Opera поддерживает используемые в нём API.

Если охота просмотреть код расширения, его можно переименовать, изменив расширение на zip, и распаковать.

Виды расширений

Существует несколько видов расширений для Opera.

1. Расширения, подразумевающие действия браузера (и действия страницы)

You can use Browser Actions or Page Actions to put UI elements in the browser window. Browser Actions are used to put UI elements in the top right side of the browser next to the address bar. This is different from Page Actions which are used to place a UI element inside the address bar.

Page actions are used to put a UI element specific to just a page or a limited set of pages fitting a certain criteria. If you would like the UI element to be there for all pages, then you should use Browser Actions for that purpose. The UI elements you can use are buttons, badges and popups. To know more on how to create and use these in extensions, please read the article on creating buttons, badges and popups.

Note: There can only be a maximum of 6 extensions installed at a time in the toolbar using browser actions, and only up to 4 which are based on page actions.

2. Расширения контекстного меню

Как следует из названия, они расширяют контекстное меню страницы, вызываемое нажатием право кнопки мыши. Подробнее о создании расширения для контекстного меню: https://dev.opera.com/extensions/context-menus/.

3. Расширения экспресс-панели

Создание расширения для экспресс-панели доступно только для Opera (NEX). Подробнее о том, как создать расширение для экспресс-панели.

4. Расширения без интерфейса

Возможно создание расширения, не имеющего интерфейса.

Примером является расширение, обрабатывающее ввод с клавиатуры и, например, открывающее вкладку с сайтом.

Составные части расширения

Манифест

Манифест является обязательной частью любого расширения. Этот файл содержит основную информацию о расширении, как то: название расширения, его автора, разрешения, версию и пр. Если файл манифеста содержит ошибку, расширение просто не запустится. Подробнее о манифесте можно прочесть здесь.

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

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

Можно использовать HTML-страницу и вставить внутрь JavaScript-код внутри блока <script>, но лучше просто использовать .js-файл и указать его в манифесте. Браузер автоматически сгенерирует соответствующую страницу для него. Например,

"background": { "scripts": ["background.js"] }

Для того, чтобы указать страницу событий, в манифесте нужно установить false для поля persistent:

"background": {
	"scripts": ["eventPage.js"],
	"persistent": false
}

Фоновый скрипт очень важен при работе с пользовательским интерфейсом. Любой участок кода, создающий элементы пользовательского интерфейса, должен быть определён здесь. 

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

Страницы событий загружаются в следующих случаях:

  • Во время установки, перезапуска, запуска или обновления до новой версии.
  • Когда возникает событие, которое прослушивалось страницей событий.
  • Когда другая часть расширения (например, всплывающее окно) вызывают их (например, используя runtime.getBackgroundPage).

  • Когда другая часть расширения посылает сообщение (используя runtime.sendMessage() или долгоживущие соединения. Подробнее можно узнать в этой статье).

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

Скрипт содержимого

If you want to make any change to the web page itself, then you need to use a content script. The content script has access to the DOM of the web page, but access to variables and functions is confined to only itself. For example, content scripts cannot access variables defined in the web page, or even in other content scripts.

The content script does not have direct access to the variables and functions in the background scripts too. The same applies for access to API functions. However, you can use message passing to communicate between various parts of the extensions, be it background scripts or popups. So, you could call your functions in the background script and then communicate to the content script to do a certain task involving the host page’s DOM.

Более подробно описано в этой статье.

Страница всплывающего окна

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

Страница настроек

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

"options_page": "options_page.html"

Для хранения пользовательских настроек можно использовать локальное хранилище.

Иконки и другие ресурсы

Обычно расширению требуется иконка. Иконка 128x128 используется для страницы расширений и во время установки, 48x48 — для страницы управления расширениями, 16x16 — как favicon для страницы расширения, а 19x19 — для панели расширений. Помимо иконок можно хранить изображения, шрифты и пр. Всё это может быть расположено внутри расширения в произвольном месте.

Структура файлов и каталогов

Структура файлов и каталогов расширения
Структура файлов и каталогов расширения

На данном рисунке представлена структура файлов типичного расширения.

Разрешения и привилегии

Необходимость разрешений

В манифесте перечислены API браузера, доступ к которым разрешён для расширения.

Разделение привилегий

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

Скрипты содержимого работают в изолированном режиме

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

Политика безопасности содержимого

Политика безопасности содержимого определена в манифесте, например, таким образом:

"content_security_policy": "[WRITE YOUR POLICY STRING HERE]"

Запрет функций eval и иже с ними

Такие функции как eval и прочие (перечислено ниже) отключены, так как они могут быть использованы в XSS-атаках. Проще говоря, не используйте следующие функции:

  • eval()
  • setTimeout()
  • setInterval()
  • new Function(String)

Внедрённый JavaScript не будет работать

Внедрённый код на JavaScript также может быть использован в XSS-атаках, поэтому он тоже отключён. Это значит, что запрещены обработчики событий (например <a onclick="…").

Разрешена загрузка только локальных ресурсов

Разрешена загрузка скриптов и ресурсов только из пакета расширения:

<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>

Скрипт выше не будет загружен, поэтому требуется разместить его внутри расширения и подключать примерно так:

<script src="scripts/jquery-1.9.1.min.js"></script>

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

Всё

Спасибо за внимание.

Кстати, вот пример полезного расширения, к которому я приложил руку: github.com/bartholomej/modx-manager-switch .