В этой статье мы рассмотрим разработку расширения для Firefox, с помощью addon sdk, а также разберём ключевые моменты разработки: установка sdk(jpm), инициализация проекта, тестирование, компиляция и публикация нашего расширения на addons.mozila.org, на примере всё того же скриншотера…

Должен сразу оговориться, что расширение поддерживается только linux системами и разработана на linux.
И так, с начала мы должны установить пакет jpm в нашу систему, для этого устанавливаем nodejs и npm (если нету):
После установки node.js и npm устанавливаем jpm с помощью команды:
Эта команда установит нам jpm в глобальную область, его так же можно установить локально опустив ключ --global.
Далее нам необходимо создать директорию, для будущего расширения. Давайте назовём его habrscreen:
И инициализируем в этой директории расширение, для этого нам надо перейти в папку и выполнить команду инициализации:
После выполнения данной команды, в директории создаётся скелет будущего приложения.
habrscreen
— index.js
— package.json
— test
— test-index.js
Рассмотрим конфигурацию нашего addon package.json:
Что здесь может быть интересного? это тот же манифест только в формате json. Да это так тот же манифест с указанием версии, описанием и имени addons. А так же мы в нём определили настройки нашего модуля пока их будет 4:
1. client id — id клиента yandex oauth
2. get OAuth token — кнопка при клике переходим на яндекс и получаем токен авторизации
3. oauth token — собственно поле для ввода токена
4. autocopy to clipboard — флаг который автоматического копирования ссылки на скриншот в буфер обмена.
После определения настроек нам необходимо подумать о кнопке, при нажатие на которую будет запускаться наш скриншотер. Для этого открываем index.js на редактирование и описываем в нём эту кнопку:
Код довольно прост, для начала мы импортируем, нужные нам, компоненты sdk, и создаём объект кнопки. Нам необходимо создать папку data в ней директорию image, в последнею скопировать заранее заготовленные картинки кнопки, картинка должна быть 3-х размеров 64, 32, 16… Готово, картинки загружены, настройка создана. Попробуем запустить:
После выполнения команды запустится firefox с нашим модулем, мы увидим результат это кнопочка с права в верху, и настройка addon.
Обработаем логику кнопки getOauth в настройках расширения, для этого необходимо обработать событие генерируемое кнопкой:
И так по нажатию на кнопку, браузер откроет новую в кладку с яндекс аутентификацией, где мы можем согласиться с разрешениями и получить токен, который скопируем в поле токена в настройках.
Далее, обработаем нажатие кнопки 'make screen' выше, мы указали что обработчиком служит функция makeScreen:
Это функция тривиальна она запускает пакет, с помощью которого делается скриншот выделенной области. Далее запускается функция uploadToYandex с параметром имени файла скриншота.
Эта функция производит запрос с помощью класса Request к api диска. К сожалению не удалось реализовать запрос методом put, он есть в объекте но параметр content принимает либо объект, либо строку и по этому бинарные данные превращаются в строку тела запроса, что приводит к выгрузке битых файлов. Мне пришлось написать свой putRequest с помощью XMLHttpRequest, если кто знает как реализовать с помощью Request пишите в комментариях. Я буду благодарен если кто то поможет привести код к общему знаменателю.
Здесь тоже всё просто, мы открываем файл и создаём поток, который, собственно, и передаём в тело запроса. По документации «диска» мы должны всегда отправлять «Content-Type:application/binary» так и делаем. Всё наш запрос ушол, последним запросом мы публикуем файл publicateFile:
Эта функция отправляет на yandex запрос на публикацию, который возвращает ссылку, для следующего запроса, подтверждения. Второй запрос возвращает объект с информацией о файле, в котором есть ссылка на файл public_url. Если всё успешно открываем вкладку браузера со скриншотом, и в зависимости от настроек, копируем с��ылку в буфер обмена…
Когда всё готово и проверена работоспособность расширения нам необходимо собрать его в фаил xpi для этого вводим команду:
Далее проходим регистрацию на addons.mozilla.org и заполняем форму для отправки расширения на модерацию здесь developer hub.

И на этом мы закончим наше приложение скриншотер разработано и опубликовано в addons.mozilla.org…
» Как всегда, делюсь ссылкой на полный код github.com: firefox-sdk-addons
» Вот и наша, ссылка на расширение habrahabr-screenshoter
Всем спасибо за внимание, и всего доброго.

Должен сразу оговориться, что расширение поддерживается только linux системами и разработана на linux.
И так, с начала мы должны установить пакет jpm в нашу систему, для этого устанавливаем nodejs и npm (если нету):
$ sudo apt-get install nodejs nodejs-legacy npm
После установки node.js и npm устанавливаем jpm с помощью команды:
$ sudo npm install jpm --global
Эта команда установит нам jpm в глобальную область, его так же можно установить локально опустив ключ --global.
Далее нам необходимо создать директорию, для будущего расширения. Давайте назовём его habrscreen:
$ mkdir ~/habrscreen
И инициализируем в этой директории расширение, для этого нам надо перейти в папку и выполнить команду инициализации:
$ cd ~/habrscreen $ jpm init
После выполнения данной команды, в директории создаётся скелет будущего приложения.
habrscreen
— index.js
— package.json
— test
— test-index.js
Рассмотрим конфигурацию нашего addon package.json:
{ "title": "habrahabr screenshoter", "name": "habrscreen", "version": "0.0.1", "description": "This add-on for make screenshot and upload to yandex disk", "main": "index.js", "author": "Roman", "engines": { "firefox": ">=38.0a1" }, "license": "MIT", "keywords": [ "jetpack" ], "preferences": [ { "name": "hClientId", "title": "client id", "description": "client id", "type": "string", "value": "8fc231e60575439fafcdb3b9281778a3" }, { "type": "control", "label": "get oAuth token", "name" : "getYaToken", "title": "Token" }, { "description": "oauth token", "name": "oauthKey", "type": "string", "title": "oauth token" }, { "description": "automaticaly copy to clipboard", "title": "autocopy to clipboard", "name":"autoCopy", "type":"bool", "value":true } ] }
Что здесь может быть интересного? это тот же манифест только в формате json. Да это так тот же манифест с указанием версии, описанием и имени addons. А так же мы в нём определили настройки нашего модуля пока их будет 4:
1. client id — id клиента yandex oauth
2. get OAuth token — кнопка при клике переходим на яндекс и получаем токен авторизации
3. oauth token — собственно поле для ввода токена
4. autocopy to clipboard — флаг который автоматического копирования ссылки на скриншот в буфер обмена.
После определения настроек нам необходимо подумать о кнопке, при нажатие на которую будет запускаться наш скриншотер. Для этого открываем index.js на редактирование и описываем в нём эту кнопку:
var ui = require('sdk/ui'); var {ActionButton} = require('sdk/ui/button/action'); var button = ui.ActionButton({ id: "mozilla-link", label: "Make screenshot", icon: { "16": "./image/camera16.png", "32": "./image/camera32.png", "64": "./image/camera64.png" }, onClick: makeScreen });
Код довольно прост, для начала мы импортируем, нужные нам, компоненты sdk, и создаём объект кнопки. Нам необходимо создать папку data в ней директорию image, в последнею скопировать заранее заготовленные картинки кнопки, картинка должна быть 3-х размеров 64, 32, 16… Готово, картинки загружены, настройка создана. Попробуем запустить:
$ jpm run
После выполнения команды запустится firefox с нашим модулем, мы увидим результат это кнопочка с права в верху, и настройка addon.
Обработаем логику кнопки getOauth в настройках расширения, для этого необходимо обработать событие генерируемое кнопкой:
var sp = require("sdk/simple-prefs"); sp.on("getYaToken", function () { tabs.open('https://oauth.yandex.ru/authorize' + '?response_type=token' + '&client_id=' + require('sdk/simple-prefs').prefs['hClientId']); });
И так по нажатию на кнопку, браузер откроет новую в кладку с яндекс аутентификацией, где мы можем согласиться с разрешениями и получить токен, который скопируем в поле токена в настройках.
Далее, обработаем нажатие кнопки 'make screen' выше, мы указали что обработчиком служит функция makeScreen:
/** * click to button screenshot * @param state */ function makeScreen(state) { var date = new Date(); var fileScreen = date.getTime().toString() + '_screen.png'; var args = ["-s", "/tmp/" + fileScreen]; system( '/usr/bin/scrot', args ); uploadToYandex(fileScreen); }
Это функция тривиальна она запускает пакет, с помощью которого делается скриншот выделенной области. Далее запускается функция uploadToYandex с параметром имени файла скриншота.
/** * upload screenshot to yandex * @param name */ function uploadToYandex(name) { var Request = require('sdk/request').Request; const fileIO = require("sdk/io/file"); Request({ url: "https://cloud-api.yandex.net/v1/disk/resources/upload?path=" + name, headers: getHeaders(), onComplete: function (response) { var result = JSON.parse(response.text); if (result.method == "PUT") { putRequest(result.href, '/tmp/' + name); // publicate file publicateFile(name); } } }).get(); }
Эта функция производит запрос с помощью класса Request к api диска. К сожалению не удалось реализовать запрос методом put, он есть в объекте но параметр content принимает либо объект, либо строку и по этому бинарные данные превращаются в строку тела запроса, что приводит к выгрузке битых файлов. Мне пришлось написать свой putRequest с помощью XMLHttpRequest, если кто знает как реализовать с помощью Request пишите в комментариях. Я буду благодарен если кто то поможет привести код к общему знаменателю.
/** * put request to yandex api * @param url * @param file */ function putRequest(url, file) { const {Cc, Ci} = require("chrome"); // Make a stream from a file. var stream = Cc["@mozilla.org/network/file-input-stream;1"] .createInstance(Ci.nsIFileInputStream); var fileIo = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); fileIo.initWithPath(file); stream.init(fileIo, 0x04 | 0x08, 0644, 0x04); // file is an nsIFile instance var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] .createInstance(Ci.nsIXMLHttpRequest); req.open('PUT', url, false); req.setRequestHeader('Content-Type', "application/binary"); req.send(stream); }
Здесь тоже всё просто, мы открываем файл и создаём поток, который, собственно, и передаём в тело запроса. По документации «диска» мы должны всегда отправлять «Content-Type:application/binary» так и делаем. Всё наш запрос ушол, последним запросом мы публикуем файл publicateFile:
/** * publicate file on yandex disk * @param name */ function publicateFile(name) { var Request = require('sdk/request').Request; var result; Request({ url: "https://cloud-api.yandex.net/v1/disk/resources/publish?path=" + name, headers: getHeaders(), onComplete: function (responsePublic) { result = JSON.parse(responsePublic.text); if (result.method == "GET") { Request({ url: result.href, headers: getHeaders(), onComplete: function (resp) { result = JSON.parse(resp.text); if (require('sdk/simple-prefs').prefs['autoCopy']) { var clipboard = require("sdk/clipboard"); clipboard.set(result.public_url); } tabs.open(result.public_url); } }).get(); } } }).put(); }
Эта функция отправляет на yandex запрос на публикацию, который возвращает ссылку, для следующего запроса, подтверждения. Второй запрос возвращает объект с информацией о файле, в котором есть ссылка на файл public_url. Если всё успешно открываем вкладку браузера со скриншотом, и в зависимости от настроек, копируем с��ылку в буфер обмена…
Когда всё готово и проверена работоспособность расширения нам необходимо собрать его в фаил xpi для этого вводим команду:
$ jpm xpi
Далее проходим регистрацию на addons.mozilla.org и заполняем форму для отправки расширения на модерацию здесь developer hub.

И на этом мы закончим наше приложение скриншотер разработано и опубликовано в addons.mozilla.org…
» Как всегда, делюсь ссылкой на полный код github.com: firefox-sdk-addons
» Вот и наша, ссылка на расширение habrahabr-screenshoter
Всем спасибо за внимание, и всего доброго.
