Опубликован: 10.12.2007 | Уровень: специалист | Доступ: платный
Лекция 17:

Система распространения и установки - XPInstall

< Лекция 16 || Лекция 17: 12345678910

17.4. Практика: комплектуем Notetaker

В данном разделе "Практика" мы должны упаковать уже работающее приложение Notetaker в XPI-файл и установить его, используя XPInstall. Теоретически, наше приложение должно действовать прямо с удаленного web-сервера, но смешивать локальный контент для приложения с оверлеями, расположенными на web-сервере, бессмысленно. На практике это может даже не работать. Так что займемся установкой приложения, загружаемого с удаленного сервера.

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

  • Определить все имена для приложения.
  • Определить содержание документов релиза.
  • Определить контент финального приложения.
  • Создать страничку загрузки, инсталляционные скрипты и файлы поддержки.
  • Создать финальный файл XPI.

Приступим.

17.4.1. Подготовка к релизу

Сначала подберем подходящее имя.

Текстовое имя. Выберем "NoteTaker Web Notes". Рекламу прибережем для web-странички, предлагающей приложение пользователю.

Имя пакета. На протяжении книги мы использовали слово "notetaker", пусть так и будет. Тут более 8 символов, что является ограничением для стареньких компьютеров с Microsoft Windows, смиримся с этой небольшой потерей.

Имя приложения в регистре. Это "/Nigel McFarlane/NoteTaker". Если бы наше приложение взяли в главную ветку разработки браузера Mozilla, то имя могло бы быть просто "NoteTaker", что дополнялось бы строкой наподобие "/mozilla.org/Browser/". В этом случае полное имя могло бы быть "/mozilla.org/Browser/NoteTaker". Однако пока такого не случилось.

Номер версии. Нашему приложению не хватало тестирования в реальных условиях, но оно, вроде бы, работает. Назовем его версию 0.9. В полной нотации 0.9.0.0. Можно придумать еще множество усовершенствований и модификаций, но пусть они относятся к версии 1.0

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

Исходники. Все, что обсуждалось в этой книге, и есть основа данного релиза приложения. Я сохранял копии значимого кода в каждой лекции в специальной поддиректории лекции, и делал инкрементальную резервную копию каждый день и полную копию еженедельно и ежемесячно. Поскольку я заканчиваю сегодня, данная копия содержит все необходимое. Моими исходниками будут исходные файлы этой книги (вариант 1, последняя авторская правка), плюс финальный устанавливаемый XPI-файл, плюс данные бекапа bac-up?. Это бекап хранит также и тестовые файлы и тестовые данные, что очень удобно.

Воздействие. Воздействие приложения NoteTaker невелико. Это лишь три вещи: иерархия папок в директории chrome; регистры Mozilla; последнее - файл notetaker.rdf в текущем профиле пользователя.

Требования. Требования к данному программному обеспечению состоят из нескольких частей. Из-за того, что мы недавно включили объекты XPCOM (file-based streams), нам потребуется платформа Mozilla версии не ниже 1.4, финальный релиз, как минимум. Тестировалось приложение с классическим браузером, не с браузером Mozilla. Приложение переносимо, так что платформа значения не имеет. В ее переносимости есть, однако, некоторые ограничения, которые мы пока не обнаружили. Единственное требование - версия платформы и наличие набора стандартных приложений. Еще нужно заметить, что последующие версии платформы не будут автоматически поддерживаться.

Это все требования со стороны логистики.

17.4.2. Создание файлов поддержки и скриптов

Релиз приложения NoteTaker 0.9 требует кода до и после собственно кода приложения.

Мы включим файл README.txt для разработчиков, которые имеют дело с исходными текстами. Мы напишем его, основываясь на информации из последней рассмотренной темы.

Нам нужен файл contents.rdf для директории notetaker/contents и два регистра. Мы используем один, созданный в "Верстка с XUL" , "Верстка XUL", и включим улучшения, сделанные в "Оверлеи и Chrome" , "Оверлеи и chrome".

Мы хотим показать простейший пример поддержки локалей. Для этого нам нужно иметь файлы contents.rdf и DTD для некоторой локали. Мы используем файл contents.rdf из "Статическое содержимое" , "Статический контент", и создадим простейший файл DTD - ничего не выполняющий.

Нам нужно также дать простейший пример установки скина. Для этого нам нужны файл contents.rdf и файл CSS демонстрационного скина (темы). Мы используем contents.rdf из "Первые элементы управления и темы" , "Первые виджеты и Темы", и создадим простейшую стилевую таблицу, также ничего не выполняющую.

Наконец, нам нужно обеспечить установку. Это задача для одного HTML-файла и двух скриптов. Утилита NoteTaker маленькая и целиком основана на платформе и приложении "классический браузер". Мы надеемся, что скрипты будут простые, а не сложные.

Поскольку файл HTML должен показываться любым браузером, ему лучше быть в высшей степени переносимым, наподобие того, что показан в листинге 17.4.

<html> 
  <head> 
    <script src="deploy.js"/> 
  <body> 
    <h1>NoteTaker Download</h1> 
    <p>The NoteTaker tool adds Web Notes to 
     your Mozilla-based Web browser. Web Notes are placed on 
     top of displayed Web pages. They hold information that you 
     record for your own purposes. 
    </p> 
    <p>Only the Classic Browser, version 1.4, is supported. 
     It is part of the established Mozilla Web application suite. 
     The standalone Mozilla Browser is not yet supported. 
    </p> 
    <p>Download here: <a href="notetaker.xpi" 
      onclick="download(event)">NoteTaker tool 0.9</a> 
    </p> 
  </body> 
</html>
Листинг 17.4. Web-страница для загрузки утилиты NoteTaker.

Функция deploy() следует наброску, сделанному в листинге 17.1. В данном случае полный скрипт показан в листинге 17.5. Пуленепробиваемое определение браузера - довольно тягостное дело, здесь мы ограничимся лишь наиболее значимыми альтернативами.

function download(e) { 
  if ( ! deploy() ) 
    alert("NoteTaker 0.9 requires Classic Mozilla 1.4"); 
    e.preventDefault(); 
} 
function is_moz_browser() { 
  return ( 
    window.navigator && 
    window.navigator.userAgent && 
    window.navigator.userAgent.search(/^Mozilla\/5\.0/) != -1 ); 
} 
function is_target() { 
  var agent = window.navigator.userAgent; 
  return ( 
    agent.search(/rv:1\.4/) != -1 && // matches 
    agent.search(/Phoenix/) == -1 && // no match 
    agent.search(/Firebird/) == -1 // no match ); 
} 
function is_app_version_ok() { 
  var it = window.InstallTrigger;
  var result = it.compareVersion( 
    "Nigel McFarlane/NoteTaker", "0.9.0.0"); 
  return ( result == it.NOT_FOUND || 
    Math.abs(result) <= it.REL_DIFF ); 
} 
function deploy() { 
  if ( !is_moz_browser() ) { 
    return false; 
} 
if ( !window.InstallTrigger.enabled() { 
  return false; 
} 
if ( !is_target() ) { 
  return false; 
} 
if ( !is_app_version_ok() } { 
  return false; 
} 
var xpi_container = { 
  "NoteTaker Web Notes" : "notetaker.xpi" 
}; 
with (window.InstallTrigger) 
  install(xpi_container, null); 
  return true; 
}
Листинг 17.5. Триггер-скрипт для комплекта NoteTaker.

Здесь нам не требуются никакие параметры, так что эта часть скелета скрипта из Листинга 17.1 не используется. Если пользователь попробует установить NoteTaker не на ту платформу или не на то приложение, мы ему пожалуемся. Здесь нет обработчика событий для функции install(), поскольку мы ничего не можем сделать, если ситуация зайдет в тупик. В большой организации мы можем создать еще одну HTML-страницу, где пользователь может заполнить форму для сообщений об ошибках. А мы положимся на скрипт install.js, который будет содержать полезную диагностику.

Три функции проверок просты. Каждый браузер, чей userAgent начинается с "Mozilla/5.0" может быть браузером mozilla.org. Если userAgent содержит "Firebird" или "Phoenix", это отдельный браузер Mozilla, а не классический браузер, который мы поддерживаем. Тест is_app_version_ok() позволяет установить версию 0.9.1.0 поверх 0.9.0.0. Это даст некоторую гарантию защиты от разработчика, считающего, что отступить назад в номере релиза достаточно безопасно. Это может потребоваться, если в новой версии окажется больше ошибок, чем ожидалось.

Заключительная часть системы установки - скрипт install.js. Листинг 17.6 показывает основную часть этого скрипта, основанного на скрипте, приведенном в листинге 17.2

var TEXT_NAME = "NoteTaker Web Notes"; 
var REG_NAME = "/Nigel McFarlane/NoteTaker"; 
var VERSION = "0.9.0.0"; 
var rv = SUCCESS;

function prepare() { 
  initInstall(TEXT_NAME, REG_NAME, VERSION);

  if ( schedule_files() != SUCCESS ) return getLastError(); 
  if ( register_chrome() != SUCCESS) return getLastError(); 
  return SUCCESS; 
} 
rv = prepare(); 
if (rv == SUCCESS) { performInstall(); 
} else { 
  alert("Installation failed. (Error = " + rv + ")" ); 
  cancelInstall(rv); 
}
Листинг 17.6. Скрипт install.js для утилиты NoteTaker.

Так же, как и в случае триггер-скрипта, install.js упрощен по сравнению со скелетом, приведенным в листинге 17.2. Параметров для проверки нет. Мы предполагаем, что скрипт должен лишь загрузить приложение, если проверяемые условия выполняются. Поскольку NoteTaker - это дополнение к браузеру, у нас нет элементов десктопного меню или пиктограмм. NoteTaker - столь маленькая утилита, что и проверка доступного места на диске бессмысленна. А поскольку утилита написана целиком на JavaScript, у нас нет ни внешних бинарников, ни библиотек, которые требовалось бы обрабатывать. Все, что нам нужно, это корректно разместить содержание файла .XPI и сообщить платформе о существовании нового содержимого в chrome.

Чтобы выполнить эти шаги, нам нужно знать содержание XPI. Заглянем вперед, в раздел "Финальный комплект", и увидим, что содержимое XPI:

install.js 
notetaker.jar 
extras/README.txt 
extras/notetaker.rdf

Собственно приложение располагается в архиве notetaker.jar. Файлы в виртуальной директории extras вряд ли когда-нибудь будут использоваться в работе. Файл README.txt предназначен для того, чтобы любознательные программисты нашли его там и прочитали; файл notetaker.rdf - начальная копия базы данных записей пользователя. Ее нужно скопировать в профиль текущего пользователя.

Листинг 17.7 показывает две функции, отсутствующие в листинге 17.6. Они выполняют необходимые манипуляции с файлами XPI и регистром chrome.

function schedule_files() { 
  addFile(TEXT_NAME, VERSION, "notetaker.jar", 
    getFolder("Chrome"), "notetaker.jar", true); 
  addFile(TEXT_NAME, VERSION, "extras/notetaker.rdf", 
    getFolder("Profile"), "notetaker.rdf", true);

  return SUCCESS; 
} 
function register_chrome() { 
  var jar_root = getFolder("Chrome", "notetaker.jar"); 
  registerChrome(PACKAGE | DELAYED_CHROME, 
   jar_root, "content/notetaker/"); 
  registerChrome(SKIN | DELAYED_CHROME, 
   jar_root, "skin/modern/notetaker/"); 
  registerChrome(LOCALE | DELAYED_CHROME, 
   jar_root, "locale/en-US/notetaker/"); 
  return SUCCESS; 
}
Листинг 17.7. Копирование файлов и регистрация в chrome в скрипте install.js.

Вызов второй функции addFile() показывает, как можно сравнить путь к любому файлу в файле XPI с любым путем локальной файловой системы. Вызов getFolder() в функции register_chrome() показывает, как корень иерархии папок в файле JAR может быть возвращен как объект. И schedule_files(), и register_chrome() выполняются без обращения к файлу notetaker.xpi. Их вызовы addFile() и registerChrome() выполняются позже, когда стартует функция performInstall().

Это все, что есть в скрипте install.js

17.4.3. Финальный комплект

Теперь мы получили или создали все необходимые нам файлы, и можем, наконец, собрать финальный XPI файл. Он должен содержать как минимум файл install.js (поскольку наше приложение - нечто большее, чем просто скин или локаль), так что начнем с создания zip-архива, содержащего этот файл.

Главным содержанием файла XPI являются коды нашей утилиты NoteTaker. Аккуратный и эффективный способ все организовать - завести единственный архив JAR в директории chrome. Он быстро прочитается на диске, поскольку маленький. Вдобавок, так будет легче манипулировать пакетами, если их число велико. Мы так и сделаем, и поместим его внутрь инсталляционного архива XPI. К сожалению, при работе с JAR-архивами придется основательно потрудиться, по двум причинам.

На протяжении книги мы строили утилиту NoteTaker как набор отдельных файлов и поддеревьев, доступных по адресу resource:/chrome/notetaker. Если бы мы распространяли пакет, организованный именно таким образом, достаточно было бы просто сжать рабочую папку NoteTaker утилитой ZIP и добавить файл install.js. Однако JAR-архивы имеют обратную структуру директорий, чтобы обеспечить быстрый доступ к содержанию. Имеющийся у нас пакет NoteTaker совсем не похож на иерархию директорий, требуемую архивом JAR:

Пакет в chrome <---> JAR архив

notetaker/content  <---> content/notetaker
notetaker/locale/en-US <---> locale/en-US/notetaker 
notetaker/skin/modern <---> skin/moder/notetaker

Единственное решение - сделать копию исходных файлов из chrome в какую-то временную папку и переорганизовать их так, как требуется для JAR-архивов. На систематической основе это делается с помощью Perl, WSH, или shell-скриптом, автоматизирующим процесс реорганизации. Вторую иерархию можно теперь сжать утилитой zip, это и будет файл JAR.

Вторая трудность с JAR-файлами состоит в том, что в больших архивах имеет значение порядок файлов. Наиболее критичные с точки зрения времени доступа файлы должны быть расположены ближе к началу архива, чтобы их легче было найти. Чтобы это сделать, поместите файлы в требуемую JAR-архивом иерархию папок, как раньше. Создайте текстовый файл, перечисляющий все файлы в нужном порядке, и создайте архив на основании этого списка, используя утилиту pkzip (Microsoft Windows) или zip(1) (UNIX). Можно корректно создавать файл JAR и добавляя файлы в архив вручную по одному в нужном порядке, но это утомительно.

На Рисунке 17.9 показан JAR-файл пакета NoteTaker, имеющий некоторый простейший порядок. Content-часть пакета расположена первой, поскольку она используется чаще всего. Фактически, скины и локали в пакете - лишь заглушки, иллюстрирующие, где должны быть помещены подобные вещи. Для столь маленького приложения соблюдать определенный порядок в архиве, вероятно, большого смысла не имеет.

Теперь у нас есть два файла для финального XPI: install.js и notetaker.jar. К ним мы можем добавить файл README и начальный файл notetaker.rdf. Финальный файл XPI (в котором порядок следования файлов не имеет значения, если нет цифровой подписи) показан на рисунке 17.10.

Больше ничего не требуется, кроме как разместить нашу HTML-страничку со ссылкой на файл XPI на web-сайте. На этом мы завершаем пример разработки утилиты NoteTaker.

Архив JAR, содержащий пакет NoteTaker.

Рис. 17.9. Архив JAR, содержащий пакет NoteTaker.
Архив XPI, содержащий полный дистрибутив NoteTaker.

Рис. 17.10. Архив XPI, содержащий полный дистрибутив NoteTaker.
< Лекция 16 || Лекция 17: 12345678910
Дмитрий Гуменюк
Дмитрий Гуменюк
Россия, Звенигород
Konstantin Grishko
Konstantin Grishko
Россия, Москва, Московский финансово-промышленный университет "Синергия", Москва