Валентина Ванеева
"Slackware Linux в Томске"
2006-02-14
Любое приложение из семейства Mozilla может выполнять не только свои прямые функции, но и функции платформы, на основе которой вы можете писать свои приложения - расширения. Разработка таких приложений отличается прежде всего тем, что она весьма быстра.
Конечно, это касается только расширений относительно высокого уровня - тех, для создания которых достаточно функциональности платформы и XUL/XBL/JavaScript. Именно эти технологии мы и рассмотрим.
XUL - аббревиатура от XML User Interface Language, XML-язык описания пользовательского интерфейса. XUL используется во всех основных продуктах семейства Mozilla. Особенности этого языка определяют легкость работы с ним:
Рассмотрим пример XUL-файла:
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
<?xml-stylesheet href="chrome://helloworld/skin/hello.css" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://helloworld/locale/hello.dtd">
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&title.label;">
<vbox align="center">
<description flex="1" class="bound"/>
<button label="&close.label;" oncommand="close();"/>
</vbox>
</window>
Разберем его построчно.
<!ENTITY title.label "Hello World"> <!ENTITY close.label "Close">
Такой файл представляет собой простейшее самостоятельно окно.
Рис. 1. Снимок простейшего окна
Однако часто интерфейс расширения должен встраиваться в интерфейс основного приложения, например, при добавлении кнопки на панель инструментов, меню или пунктов меню и т. д. В таких случаях пользуются оверлеями. Оверлеи - это также XUL-файлы, но они содержат только те части интерфейса, которые должны изменить интерфейс основного приложения, при этом элементы интерфейса могут добавляться, изменяться и удаляться. Пример:
<?xml version="1.0"?>
<!DOCTYPE overlay SYSTEM "chrome://helloworld/locale/overlay.dtd">
<overlay id="helloworld-overlay"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script src="overlay.js"/>
<menupopup id="menu_HelpPopup">
<menuitem id="helloworld-hello" label="&helloworld;"
oncommand="HelloWorld.onMenuItemCommand(event);"/>
</menupopup>
</overlay>
Разберем его построчно.
Рис. 2. Добавление пункта меню с помощью оверлея
Для того чтобы оверлеи действительно заработали, их нужно зарегистрировать в chrome [1].
XUL определяет внешний вид приложения, но оно должно еще и что-то делать. Логика приложений/расширений пишется на JavaScript (хотя на самом деле можно пользоваться не только им, но интерпретатор JavaScript является частью Gecko - ядра, и это проще всего). Это достаточно простой и популярный язык, а веб-разработчикам его и вовсе не нужно будет осваивать специально. Документация по JavaScript доступна как на сайте Mozilla, так и на многих других сайтах. Это стандартизованный язык (см. набор стандартов ECMAScript).
Вот как может выглядеть файл, импортируемый нами в оверлее выше:
var HelloWorld = {
onLoad: function() {
// initialization code
this.initialized = true;
},
onMenuItemCommand: function() {
window.open("chrome://helloworld/content/hello.xul", "", "chrome");
}
};
window.addEventListener("load", function(e) { HelloWorld.onLoad(e); }, false);
При написании сценариев для расширений нужно помнить, что имена функций должны быть уникальными, либо нужно прямо указывать, для какого именно объекта вызывается функция. Причина в том, как определяется область видимости.
Во-первых, есть традицонное определение области видимости переменных - локальные и глобальные. Во-вторых, простой набор инструкций, заключенных в фигурные скобки ({}) не создает отдельной области видимости. В-третьих, допустимо использование переменных, объявленных хоть где-нибудь в данном блоке кода, например, следующий код не вызовет исключения:
function f() {
alert(x); // значение "undefined"
var x = 1;
alert(x); // значение "1"
}
Наконец, есть понятие цепочек областей видимости. Цепочка представляет собой упорядоченный список объектов. При вызове функции интерпретатор просматривает все объекты по порядку вплоть до глобального объекта (например, window) и как только находит подходящую функцию, вызывает ее. Таким образом можно пользоваться функциями, определенными в других объектах.
Кроме того, в JavaScript поддерживаются замыкания (closures), а в конструкторах для создания наследования используются прототипы, а не классы. С недавних пор в сценариях можно использовать текст в UTF-8.
XUL позволяет как определять новые элементы, отсутствующие в стандартном наборе (см. архив toolkit.jar в каталоге chrome/), так и переопределять внешний вид, содержимое и поведение стандартных. Для этого используется XBL, XML Binding Language.
Вернемся к самом первому XUL-файлу. Напомню, что там были такие строчки:
<?xml-stylesheet href="chrome://helloworld/skin/hello.css" type="text/css"?> ... <description flex="1" class="bound"/>
Обе они нужны нам в данном случае только для того, чтобы переопределить элемент description, то есть создать новую XBL-привязку.
Обычно элемент description используется примерно так:
<description>
Здесь может быть текст.
<box>Или другие элементы.</box>
</description>
Мы создадим новый класс (bound) таких элементов, который будет содержать изображение. У нас может получиться такой XBL-файл:
<?xml version="1.0"?>
<bindings xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="bound">
<content>
<xul:hbox>
<xul:image
src="chrome://helloworld/skin/penguin_group.gif"/>
</xul:hbox>
</content>
</binding>
</bindings>
Разберем его.
Подключаются привязки в CSS-файлах. Нам нужно будет написать:
description.bound {
-moz-binding: url('chrome://helloworld/skin/hello.xml#bound');
}
Кроме того, у элемента binding могут быть следующие потомки:
Также у binding есть примечательные атрибуты:
Теперь нужно собрать расширение в единое целое. Для начала расположим наши файлы в правильном порядке:
chrome/ helloworld.jar <- ZIP-архив content/ hello.xul overlay.js overlay.xul locale/ en-US/ hello.dtd overlay.dtd skin/ hello.css hello.xml penguin_group.gif chome.manifest install.rdf
Каталоги content, locale и skin могут называться и по-другому, но принято называть их именно так. Они содержат неизменную часть приложения, файлы локализации и файлы внешнего вида соответственно. Расширение также может содержать только content - просто расширять функциональность, - только locale - пакет локализации - или только skin - тема. helloworld.jar - обычный ZIP-архив.
Из chrome.manifest основное приложение сможет узнать, какие именно части содержит регистрируемое расширение. Нам нужно зарегистрировать все, включая один оверлей:
content helloworld jar:chrome/helloworld.jar!/content/ locale helloworld en-US jar:chrome/helloworld.jar!/locale/en-US/ skin helloworld classic/1.0 jar:chrome/helloworld.jar!/skin/ overlay chrome://browser/content/browser.xul chrome://helloworld/content/overlay.xul
Файл 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@mozilla.doslash.org</em:id>
<em:name>Hello World (Firefox 1.5 edition)</em:name>
<em:version>1.0.1</em:version>
<em:description>Modified classic first extension from MozillaZine KB</em:description>
<em:creator>Nickolay Ponomarev</em:creator>
<em:contributor>Put your name here</em:contributor>
<em:targetApplication>
<!-- Firefox -->
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>1.5</em:minVersion>
<em:maxVersion>1.5.0.*</em:maxVersion>
</Description>
</em:targetApplication>
</Description>
</RDF>
Теперь все содержимое каталога кладем в ZIP-архив с именем helloworld.xpi. Все!
Рис. 3. Менеджер расширений с новым расширением
На самом деле на XUL можно писать не только расширения к Firefox, Thunderbird, Seamonkey и т. д., на XUL можно писать и полноценные приложения. С 2005 г. разработчики mozilla.org предлагают пользоваться также Xulrunner, который позволяет это делать. При этом:
Есть и минусы, например, вам придется включать в свой дистрибутив сам Xulrunner, а значит, объем дистрибутива станет примерно на 13 Мб больше.
XUL-файлы вместе с необходимыми сценариями и стилями можно также загружать прямо из веба. Так можно получить полноценный интерфейс, уже знакомый и понятный пользователю. К сожалению, эта функциональность будет доступна только пользователям браузеров семейства Mozilla, что не всегда приемлемо. Зато эти браузеры сделают за вас всю самую скучную работу.
Также существует проект по интеграции XUL и JSF.
При создании некоторых приложений сложно заранее узнать, какое именно количество данных придется отображать (например, вы пишете клиент к базе данных). В этом случае можно использовать XUL-шаблоны: вы просто указываете, какие данные будут получены, как их отображать и откуда из брать. В будущем, возможно, шаблоны будут заменены на XSLT-преобразования. RDF (Resource Description Framework) - XML-формат, который используется для хранения различных данных. К сожалению, на данный момент такие источники данных - единственные, которые разработчики могут использовать сразу же. Однако уже сейчас доступно расширение mozStorage для работы с SQLite.
Расширения можно подписывать. В Firefox (начиная с версии 1.5) можно осуществлять безопасный доступ из XUL-приложений к незащищенному содержимому - веб-страницам, тогда можно быть уверенным, что нужные функции не будут замещены сценариями с веб-страницы.
XPCOM - Cross-platform Component Object Model. Как только вам перестанет хватать стандартной функциональности платформы (скажем, вы хотите реализовать поддержку нового протокола), вам придется искать или писать самостоятельно нужный XPCOM-компонент. Это уже более низкий уровень разработки, который потребует от вас знания C++, но и здесь нет ничего сложного, тем более что на сайте mozilla.org достаточно документации. Создав такой компонент, вы можете легко получить нужную функциональность в обычном JavaScript-сценарии.
Да, если вы вдруг думаете, что на XUL можно писать только расширения, вы ошибаетесь. На XUL уже написаны: несколько браузеров, почтовый клиент, HTML-редактор, календарь, IRC-клиент, Jabber-клиент, отладчик JavaScript и полноценная среда разработки - Komodo.
Англоязычные ресурсы:
Русскоязычные ресурсы:
Файлы, использующиеся в тексте:
[1] Возможное происхождение термина chrome.
From Jargon File (4.3.1, 29 Jun 2001) [jargon]:
chrome n. [from automotive slang via wargaming] Showy features added to
attract users but contributing little or nothing to the power of a
system. "The 3D icons in Motif are just chrome, but they certainly are
_pretty_ chrome!" Distinguished from {bells and whistles} by the fact
that the latter are usually added to gratify developers' own desires for
featurefulness. Often used as a term of contempt.