Делаем свое расширение для Firefox. Часть IV. Background, сборка, публикация.

Делаем background

Теперь делаем специальный модуль ip_background.js, который будет выполнять всю работу нашего аддона, во время работы браузера.

Создаем файл ip_background.js и копируем из файла ip_popup.js все содержимое, кроме строк с addEventListener, т.к. слушатели событий в background будут другие. Функцию doRequest пока оставим в покое, ей займемся чуть позже.

Из функции onGot(item) удаляем строку document.getElementById("script").value = curAddr;, т.к. никаких текстовых полей в бэкграунде нет и не предвидится, менять элементы нам тут не надо.

Еще я переименовал функцию bodyLoad в listinerRun, она у нас будет одна, на все три обрабатываемых события.

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

Так, начало положена, у нас есть «болванка» нашего background-скрипта, сохраняем ее и модифицируем manifest.json

Модификация manifest.json

В manifest.json следует добавить секцию "background", где перечислить в массиве "scripts" скрипты, запускаемые браузером во время работы нашего расширения. Понадобятся два скрипта, собственно ip_background.js и библиотека JQuery jquery-3.4.1.min.js:

"background": {
    "scripts": [
      "jquery-3.4.1.min.js",
      "ip_background.js"
    ]
  }

Новый manifest.json на PasteBin

Далее под катом

Дополнительно

Внешний скрипт на PHP, который можно использовать, как замену api.myip.com (копия)
На GitHub

Скачать

Страница дополнения на mozilla.org
Исходники на GitHub
Скачать подписанный xpi с GitHub
Этот мануал в PDF + весь код в одном архиве:
С Mega.nz
С Google.Drive

Предыдущая часть
Содержание

Делаем свое расширение для Firefox. Часть III. Работа с запросами.

Работа с запросами

До того, как мы будем выполнять запросы к внешним ресурсам, надо внести изменения в manifest.json, дав соответствующее разрешение "<all_urls>" в permissions.
Все разрешения для нашего аддона:

"permissions": [
    "activeTab",
    "tabs",
    "storage",
    "<all_urls>"
  ]

Внимание! Если разрешение "<all_urls>" не дать, то при попытке обращения к внешнему ресурсу произойдет ошибка:

Запрос из постороннего источника заблокирован: Политика одного источника запрещает чтение удаленного ресурса на https://api.myip.com/. (Причина: отсутствует заголовок CORS «Access-Control-Allow-Origin»).

Почему-то ссылка на пояснение к ошибке на сайте Мозиллы ведет не совсем на то, что нужно, а в поиске, тоже неизвестно почему, информация о том, что нужно просто дать разрешение "<all_urls>" в manifest.json не всплывает. Сам еле догадался, практически методом научного тыка устранил данный глюк.

Небольшое отступление от программирования

После долгого ковыряния в отладке и интернете я решил немного отдохнуть, и дополнить дизайн расширения.

Фактически, у запроса есть три состояния:

— запрос выполняется
— запрос выполнен успешно
— запрос завершен с ошибкой

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

— запрос выполняется (1working.png)

— запрос завершен с ошибкой (2error.png)

— если запрос выполнен успешно, то будем показывать флаг страны, как и планировалось изначально. Но, на всякий случай, можно предусмотреть ситуацию, когда страну определить не удалось (с api.myip.com это вряд ли случится, но с другим скриптом, выдающим данные в том же формате может быть).

— страна неизвестна (3unknow.png)

Подключение JQuery

GET-запрос к сайту оказалось проще всего сделать с помощью библиотеки JQuery.
Скачиваем библиотеку и сохраняем ее в каталог с ip_popup.html. В самом ip_popup.html подключаем ее (перед скриптом ip_popup.js):

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

Далее под катом

Предыдущая часть
Продолжение

Делаем свое расширение для Firefox. Часть II. В которой работаем с пользовательскими настройками аддона.

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

function saveSettings()
{
	var scriptAddr = document.getElementById("script").value;
	scriptAddr = scriptAddr.trim();
	
	if (scriptAddr != "")
	{
		if (window.confirm('Save script address ' + 
                    scriptAddr + '? Are you sure?'))
		{
			browser.storage.local.set({
				server_settings: {script_addr: scriptAddr}
			});
			window.alert('Settings saved!');
		}
		else
		{
			document.getElementById("script").value = curAddr;
		}
	}
}

Что тут делается:

1. Сначала в переменную scriptAddr записывается значение текстового поля с id=script, т.е. того поля, куда можно ввести адрес скрипта.
2. Функцией trim() обрезаем начальные и конечные пробелы, вдруг их пользователь навводит.
3. Если scriptAddr не пустая строка, то запрашиваем у пользователя подтверждение сохранения функцией window.confirm() Функция выведет на экран окошко с текстом, заданным в качестве ее аргумента и кнопками «Да» и «Нет». Если нажата «Да», функция вернет true, если «Нет» — false.

Подробности: «Взаимодействие: alert, prompt, confirm»

4. Если отвечено да, то пользуемся API Firefox’а, а именно функцией browser.storage.local.set(object), которой, в данном случае, передается объект, содержащий объект server_settings, содержащий единственный параметр script_addr. Значение script_addr устанавливаем из переменной scriptAddr. Далее сообщаем пользователю, что настройки сохранены (window.alert('Settings saved!');)

Подробности и примеры работы с локальным хранилищем: StorageArea.get()

5. Если было отвечено «Нет», то восстанавливаем значение текстового поля:

document.getElementById("script").value = curAddr;

В конце js-файла, после всех функций, подключаем обработчик события (слушатель) для события «click» кнопки с id == save:

document.getElementById("save").addEventListener("click", saveSettings);

Внимание! Функции addEventListener имя функции-обработчика передается без круглых скобок

document.getElementById("save").addEventListener("click", saveSettings()); //неправильно

Если добавить скобки, то код функции saveSettings просто однократно выполнится, когда дойдет очередь до addEventListener

Да, ошибка детская, но искать потом концы довольно муторно.

Далее под катом

Начало
Продолжение

Делаем свое расширение для Firefox. Часть I. В которой мы все подготавливаем.

Преамбула

Решил я сделать одно небольшое расширение для Firefox, попутно описывая весь процесс разработки. Пишу больше для себя, чтоб легче было разобраться самому.
Что оно будет делать. Расширение будет присутствовать на панели Firefox в виде отдельной кнопки и отображать на этой кнопке флаг страны, в зависимости от того, какой у пользователя внешний IP. По нажатию на кнопку будет вываливаться всплывающее окно с опцией, которых будет одна — адрес скрипта, который выдаст нам нужные данные, и собственно, самим IP-адресом.

IP и страну будем получать с https://api.myip.com/, который выдает нужную информацию в виде JSON:

{"ip":"162.247.73.193","country":"United States","cc":"US"}

Подготовка структуры каталогов.

Создадим где-нибудь в удобном месте каталог, например, deoip, он будет корневым каталогом нашего плагина, а в нем 2 подкаталога icons и flags

Иконки и флаги стран.

Плагину требуется как минимум одна иконка 48×48 для отображения в менеджере дополнений, и желательна еще одна 96×96 пикселей. В Мозиловском примере говорится, что можно сделать иконку в формате SVG, но я не стал экспериментировать и сделал две PNG-шки.

Флаги стран, которые будут отображаться на кнопке панели, должны иметь размер 32×32 пикселя, а имена файлов соответствовать двухбуквенному ISO-коду страны. Я использовал готовые иконки из коллекций плюс еще одну иконку по умолчанию (0none.png).

manifest.json

manifest.json — это главный файл расширения, содержащий основные опции плагина.

Пока он выглядит так:

{
  "manifest_version": 2,
  "name": "External IP GeoIP",
  "description": "Display you external IP and IP country",
  "version": "0.0.1",
  "icons": {
    "48": "icons/48.png",
    "96": "icons/96.png"
  },
  "browser_action": {
    "default_icon": "flags/0none.png",
    "default_title": "External IP GeoIP"
  },
  "permissions": [
    "activeTab",
    "tabs",
    "storage"
  ]
}

Сначала идут обязательные опции manifest_version и name — имя расширения, далее дополнительные, но желательные description и version, соответственно, краткое описание и версия. В секции icons указываются пути к иконкам для менеджера дополнений (все пути должны быть относительными, относительно, собственно manifest.json). В секции browser_action описывается кнопка на панели браузера и привязанные к ней действия, пока действий у нас никаких (потом добавим выплывающее меню), а задача просто отобразить кнопку на панели. Поэтому добавляем опцию default_icon — путь к иконке по умолчанию, и всплывающую подсказку default_title (появится, если к кнопке подвести указатель мыши).
Далее интересная секция permissions. Это разрешения для нашего плагина. Я уже примерно прикинул какие разрешения нам понадобятся: доступ к вкладкам (tabs), к активной вкладке (activeTab) и хранилищу, которое используется для сохранения настроек плагина (storage).

Подготовка Firefox к тестированию плагина

Особая подготовка не требуется, но я рекомендую все-таки сделать отдельный пустой тестовый профиль. Набираем в адресной строке about:profiles, жмем Enter, попадаем на страницу профилей, создаем отдельный профиль test и жмем «Запустить еще один браузер с этим профилем»

Первый запуск

В браузере с новым профилем набираем в адресной строке about:debugging, слева выбираем «Этот Firefox«, и жмем кнопку «Загрузить временное дополнение» и выбираем наш manifest.json. Теперь идем в меню «Инструменты —> Дополнения» или набираем в адресной строке about:addons, и если все сделано правильно, то видим наше дополнение в списке дополнений, а если откроем просто пустую вкладку, то увидим и кнопку.


Делаем всплывающую панель

Продолжение