Как стать автором
Обновить

Разработка расширения для firefox, или мой первый опыт, на примере скриншотера

Время на прочтение7 мин
Количество просмотров18K
После написания статьи Системные скрипты на php для linux, пишем скриншотер, у меня появилась идея «А почему бы, не написать расширение которое завязать на мой скрипт, с возможностью автоматической выгрузки на яндекс диск.»… Почитав документацию о разработке расширений я решил всё же начать писать.

image

Вот это маленькая кнопочка и скриншот на яндекс диске, результат прототипа расширения, написаного за пару часов. О процессе его создание под катом…

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

Расширение которое я разработал имеет следующую файловую структуру:

Структура
-chrome.manifest
-install.rdf
--content
----browserOverlay.js
----browserOverlay.xul
----options.xul
--skin
----browserOverlay.css

Сейчас нас интересуют файлы: chrome.manifest и install.rdf. chrome.manifest содержит в себе описание структуры проекта:

chrome.manifest
content   xulphpsrc                content/
skin      xulphpsrc  classic/1.0   skin/

overlay chrome://browser/content/browser.xul  chrome://xulphpsrc/content/browserOverlay.xul

Первые две строки хром манифеста содержат: тип данных, название пакета, путь к файлам пакета.

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

Файл install.rdf это манифест установки, который содержит информацию об добавляемом расширение:

install.rdf
<?xml version="1.0"?>

<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:em="http://www.mozilla.org/2004/em-rdf#">

  <Description about="urn:mozilla:install-manifest">
    <em:id>phpsrc@phpsrc.ru</em:id>
    <em:name>xulphpsrc</em:name>
    <em:description>PHP screenshoter extensions!</em:description>
    <em:version>0.1</em:version>
    <em:optionsURL>chrome://xulphpsrc/content/options.xul</em:optionsURL>
    <em:creator>Naumov</em:creator>
    <em:type>2</em:type>

    <!-- Mozilla Firefox -->
    <em:targetApplication>
      <Description>
        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
        <em:minVersion>4.0</em:minVersion>
        <em:maxVersion>10.*</em:maxVersion>
      </Description>
    </em:targetApplication>
  </Description>
</RDF>

Как вы видите. Он содержит в себе идентификатор, имя приложения, версию, создателя, тип приложения, URL панели настройки и д.р. информацию.

Я не думаю что стоит заострять внимание на этом файле, так как всё вполне очевидно. Мы можем только разобрать одну опцию optionsURL, это url который ведёт к настройкам расширения, настройки в свою очередь описываются файлом options.xul:

options.xul
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>

<prefwindow id="xulphpsrc-prefs"
            title="phpsrc api yandex settings"
            xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

    <prefpane id="phpsrc_api_set" label="PHPsrc setting api yandex">
        <preferences>
            <preference id="phpsrc_login" name="extensions.xulphpsrc.login" type="string"/>
        </preferences>

        <preferences>
            <preference id="phpsrc_pass" name="extensions.xulphpsrc.pass" type="string"/>
        </preferences>

        <hbox align="center">
            <label control="phpsrc_login_label" value="Яндекс логин: "/>
            <textbox preference="phpsrc_login" id="phpsrc_login_label" maxlength="40"/>

            <label control="phpsrc_pass_label" value="Яндекс пароль: "/>
            <textbox preference="phpsrc_pass" id="phpsrc_pass_label" maxlength="40"/>
        </hbox>
    </prefpane>
</prefwindow>

В этом файле, мы описали всего 2-ва поля логин и пароль. Обратите внимание на имена «extensions.xulphpsrc.login» и «extensions.xulphpsrc.pass» они содержат как бы древовидную структуру, и их будет удобнее получать из общей массы записей, да и есть, некая гарантия уникальности ключей…

Далее рассмотрим фаил browserOverlay.xul:

browserOverlay.xul
<?xml version="1.0"?>

<?xml-stylesheet type="text/css" href="chrome://global/skin/" ?>
<?xml-stylesheet type="text/css"
  href="chrome://xulphpsrc/skin/browserOverlay.css" ?>

<overlay id="xulphpsrc-browser-overlay"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

  <script type="application/x-javascript"
    src="chrome://xulphpsrc/content/browserOverlay.js" />

  <toolbar>
    <hbox>
    <toolbarbutton id="xulphpsrc-button" class="button-screen"
                   label="Скриншот" tooltiptext="Скриншот"
                   oncommand="XULPHPsrcChrome.BrowserOverlay.makeScreen(event);"/>
    </hbox>
  </toolbar>
</overlay>

Что он делает? он подключает два файла browserOverlay.css, browserOverlay.js и создаёт toolbar и единственную кнопку на нём «Скриншот»:



Вся логика приложения заложена в browserOverlay.js

browserOverlay.js
/**
 * XULPHPsrcChrome namespace.
 */
if ("undefined" == typeof(XULPHPsrcChrome)) {
    var XULPHPsrcChrome = {};
}

/**
 * Controls the browser overlay.
 */
XULPHPsrcChrome.BrowserOverlay = {
    /**
     * craete screen shot by rect
     * @param aEvent
     */
    makeScreen: function (aEvent) {
        var date = new Date();
        var fileScreen = date.getTime().toString() + '_screen.png';

        var args = ["-s", "/tmp/" + fileScreen];

        this.systemRequest(
            '/usr/bin/scrot',
            args
        );

        this.uploadToYandex(fileScreen);
    },

    /**
     * analog php system
     * @param shell
     * @param args
     */
    systemRequest: function (shell, args) {
        var file = Components.classes["@mozilla.org/file/local;1"]
            .createInstance(Components.interfaces.nsIFile);

        file.initWithPath(shell);

        var process = Components.classes["@mozilla.org/process/util;1"]
            .createInstance(Components.interfaces.nsIProcess);
        process.init(file);

        process.run(true, args, args.length);
    },

    /**
     * upload screen to yandex
     * @param name
     */
    uploadToYandex: function (name) {
        var xml = '<propertyupdate xmlns="DAV:"><set><prop><public_url xmlns="urn:yandex:disk:meta">true</public_url></prop></set></propertyupdate>';
        var auth = this.getPreference().login + ':' + this.getPreference().pass;

        this.systemRequest('/usr/bin/curl', [
            '-s',
            '--user', auth,
            '-T', '/tmp/' + name,
            '-X', 'PUT',
            'https://webdav.yandex.ru'
        ]);

        this.systemRequest('/usr/bin/curl', [
            '-s',
            '--user', auth,
            '-d', xml,
            '-X', 'PROPPATCH',
            'https://webdav.yandex.ru/' + name
        ]);

        alert("Скриншот сохранён");
    },

    /**
     * get system configuration
     * @returns {{login: *, pass: *}}
     */
    getPreference: function () {
        var prefs = Components.classes["@mozilla.org/preferences-service;1"]
            .getService(Components.interfaces.nsIPrefService);
        var myPrefs = prefs.getBranch("extensions.xulphpsrc.");

        return {
            login: myPrefs.getCharPref('login'),
            pass: myPrefs.getCharPref('pass')
        }
    }
};

Данный фаил мы разберём чуть подробнее хотя он тривиален и выполняет всего 2-ва действия: делает скриншот, и загружает его на yandex disk. Скриншот он делает с помощью вызова системной утилиты crot, и згружает результат с помощью curl. Обработчик «клика» на кнопку «скриншот» мы поставили метод makeScreen:

    /**
     * craete screen shot by rect
     * @param aEvent
     */
    makeScreen: function (aEvent) {
        var date = new Date();
        var fileScreen = date.getTime().toString() + '_screen.png';

        var args = ["-s", "/tmp/" + fileScreen];

        this.systemRequest(
            '/usr/bin/scrot',
            args
        );

        this.uploadToYandex(fileScreen);
    },

Это точка входа в приложение, здесь формируется имя будущего скриншота и происходит вызов, linux программы, scrot. Мы выбираем мышкой область экрана и делаем снимок, после этого программа переходит в следующий метод uploadToYandex, и передаёт имя файла для загрузки.

    /**
     * upload screen to yandex
     * @param name
     */
    uploadToYandex: function (name) {
        var xml = '<propertyupdate xmlns="DAV:"><set><prop><public_url xmlns="urn:yandex:disk:meta">true</public_url></prop></set></propertyupdate>';
        var auth = this.getPreference().login + ':' + this.getPreference().pass;

        this.systemRequest('/usr/bin/curl', [
            '-s',
            '--user', auth,
            '-T', '/tmp/' + name,
            '-X', 'PUT',
            'https://webdav.yandex.ru'
        ]);

        this.systemRequest('/usr/bin/curl', [
            '-s',
            '--user', auth,
            '-d', xml,
            '-X', 'PROPPATCH',
            'https://webdav.yandex.ru/' + name
        ]);

        alert("Скриншот сохранён");
    },

В этом методе, как вы видите нет ни чего экстраординарного, он делает 2-ва запроса с помощью curl в yandex.disk, один загружает созданный файл, другой его публикуют. Спасибо lexore за коментарий. В конце концов, мы получаем уведомление что скриншот сохранён.

Ну вот теперь у нас есть расширение как его установить? Для разработки мы можем, просто, создать файл под именем приложения в папке:

~/.mozilla/firefox/[id].[user]/extensions/

Где id — идентификатор, [user] — пользователь firefox к примеру у меня получилось так:

~/.mozilla/firefox/pta4nm6g.default/extensions/phpsrc@phpsrc.ru

И содержащий путь до директории с файлами расширения:~/extensions/phpsrc/ (к примеру у меня такой).

Последним штрихом, нам необходимо отключить проверку подписи расширений в firefox. Для этого необходимо перейти по адресу about:config найти опцию xpinstall.signatures.required и выставить значение false.



Перезагружаем firefox и всё готово… Настройка расширения, заходим в дополнения и ищем своё расширение, нажимаем на кнопочку настроить, вводим логин и пароль от yandex'a и готово, теперь можно нажать кнопочку и сделать скриншот…

Выводы: Я в первый раз писал расширение для firefox, и времени у меня больше на написание статьи ушло. Это первая версия приложения в дальнейшем есть планы развиваться в направление, использования php в этой сфере. Все скриншоты сделаны разработанным расширением. Всем спасибо за внимание, всего хорошего…

UPD: Репозитарий на github
Теги:
Хабы:
Всего голосов 34: ↑26 и ↓8+18
Комментарии32

Публикации

Ближайшие события