Разработка дополнений FireFox

Семинар «Разработка дополнений FireFox» является частью обучающих материалов кафедры веб-технологий.

Дополнения к FireFox распространяются в виде файлов с расширением xpi. Эти файлы являются zip-архивами. Внутри архива могут находиться javascript, xul, css-файлы и даже jar-архивы. В большинстве случаев файлы структурированы в директории, имеющие стандартные названия. В общем, с точки зрения человека, всё довольно понятно и доступно. Давайте попробуем создать простое расширение. Пусть это будет кнопка, которую мы могли бы разместить на произвольной панели инструментов FireFox и по нажатию на неё должно появляться всплывающее окно.

Но мы не будем делать так, как делается в большинстве подобных руководств: сначала сделать описание файлов, а потом дать ссылку на архив. Мы сначала настроимся на работу, скачаем и установим шаблонный проект, а уже потом будем разбираться, что там к чему.

Подготовка рабочего пространства

править

Итак, для начала создадим отдельный FireFox профиль, который не жалко сломать. Для этого закрываем FireFox, нажимаем Win+R и вводим команду

firefox -P

Откроется окно для выбора профиля. Нажимаем кнопку создания профиля и указываем папку для создания нового профиля. Предпочтительно создать папку так, чтобы она была легко доступна, например:

D:\my_experiments\firefox

Далее скачиваем и устанавливаем шаблонный проект helloworld.xpi. На панели управления должна появиться кнопка, по нажатию которой отображается приветствие 'Hello, World!'.

После установки внутри директории

D:\my_experiments\firefox\extensions

появится папка с названием

helloworld@ru.wikiversity.org.xpi

с ней-то мы и будем работать в дальнейшем.

Содержимое пакета helloworld.xpi

править

content\overlay.xul

править
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="chrome://helloworld/skin/overlay.css" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://helloworld/locale/overlay.dtd">
<overlay id="helloworld-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    <toolbarpalette  id="BrowserToolbarPalette">
        <toolbarbutton  id="helloButton" label="&helloworld;" oncommand="alert('Hello, World!');"/>
    </toolbarpalette>
</overlay>

Это корневой файл, он говорит, что кнопка вообще должна быть и должна быть добавлена по умолчанию на панель инструментов BrowserToolbarPalette. Этот код написан на языке XUL.

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

locale\en-US\overlay.dtd

править
<!ENTITY helloworld "Hello World!">

Это просто справочник текстовых констант.

В этой папке содержатся изображение для кнопки и файл со стилями

chrome.manifest

править
content	helloworld	content/
overlay	chrome://browser/content/browser.xul	chrome://helloworld/content/overlay.xul

locale	helloworld	en-US	locale/en-US/

skin	helloworld	classic/1.0	skin/
style	chrome://global/content/customizeToolbar.xul	chrome://helloworld/skin/overlay.css

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

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>helloworld@ru.wikiversity.org</em:id>
    <em:name>Hello World extension for Firefox</em:name>
    <em:version>1.0</em:version>
    <em:description>Demo Hello World extension.</em:description>
    <em:creator>Wikiversity student</em:creator>
    <em:unpack>true</em:unpack> <!-- чтобы архив распаковался при установке -->

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

  </Description>
</RDF>

В соответствии с этим файлом происходит установка дополнения (или не происходит в случае слишком старых или слишком новых версий). 8.0.* - тут указывается максимальная версия Firefox, с которой может работать расширение. Поэтому следует изменить это значение на то, для с какой версией планируется работа расширения.

Инструменты

править

Для разработки потребуется программистский текстовый редактор. Чтобы изменения содержимого файлов вступили в силу, требуется перегружать FireFox. Это неудобно, т.к. перегружать приходится часто. Поэтому нужно установить дополнение Extension Developer. После установки на панель управления FF нужно вытащить кнопку 'Reload all Chrome'.

Процесс разработки будет выглядеть так: редактируем файлы в текстовом редакторе, сохраняем, жмём на 'Reload all Chrome', проверяем.

Внутри XUL могут содержаться скрипты (внутри тега script) или подключаться из отдельных файлов.

<script>
function showHello(){
    alert('hello!');
}
</script>
...
<toolbarbutton  id="helloButton" label="&helloworld;" oncommand="showHello();"/>

Поскольку про JS есть отдельный курс, то про стандартные возможности здесь говорить не будем.

В JavaScript-е могут быть использованы компоненты XPCOM.

Работа с файлами

править

Чтение

править
function read(path) {
     try {
          netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
     } catch (e) {
          alert("Permission to read file was denied.");
     }
     var file = Components.classes["@mozilla.org/file/local;1"]
          .createInstance(Components.interfaces.nsILocalFile);
     file.initWithPath( path );
     if ( file.exists() == false ) {
          alert("File does not exist");
     }
     var is = Components.classes["@mozilla.org/network/file-input-stream;1"]
          .createInstance( Components.interfaces.nsIFileInputStream );
     is.init( file,0x01, 00004, null);
     var sis = Components.classes["@mozilla.org/scriptableinputstream;1"]
          .createInstance( Components.interfaces.nsIScriptableInputStream );
     sis.init( is );
     return sis.read( sis.available() );
}
alert(read("D:\\1.txt"));

Следует обратить внимание, что путь файла должен чётко соответствовать системе: в Windows используются обратные слэши, в Linux - прямые.

Окно для выбора файла

править

Окно для выбора файла на чтение:

	fp = Components.classes["@mozilla.org/filepicker;1"]
	    .createInstance(Components.interfaces.nsIFilePicker);
	fp.init(window, "File Open Dialog", fp.modeOpen);
	fp.show();

С точки зрения рантайма окно отображается синхронно (приостанавливает работу js). После выбора файла соответствующий дескриптор будет доступен в fp.file.

Окно для сохранения файла:

fp.init( window, "File Save Dialog", fp.modeSave );

Таймер

править
<script>
var event = {
  notify: function(timer) {
    alert("Будильник!!!");
  }
}
var timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
timer.initWithCallback(event,3000, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
</script>

Разработка библиотек XPCOM

править

Внутри JavaScript-а могут быть использованы компоненты XPCOM. Для того, чтобы разрабатывать библиотеки XPCOM нужно скачать XULRunner-SDK.

После распаковки архива нужно прописать путь к бинарным файлам в PATH.

IDL - расшифровывается как язык описания интерфейсов (interface description language). XPIDL - это Mozilla Cross-platform IDL. Интерфейсы, видимо, следует понимать как программные интерфейсы, а не GUI.

Рассмотрим пример:

#include "nsISupports.idl"
[scriptable, uuid(00000000-0000-0000-0000-000000000000)]
interface IMyComponent : nsISupports
{
  long Add(in long a, in long b);
};

Этот текст надо положить в файл с названием IMyComponent.idl и можно компилировать его в .xpt из командной строки:

xpidl.exe -m typelib -w -v -I D:\my_path_to\xulrunner-sdk\idl -e IMyComponent.xpt IMyComponent.idl

См. также

править