Опубликован: 10.12.2007 | Доступ: свободный | Студентов: 822 / 20 | Оценка: 5.00 / 5.00 | Длительность: 58:33:00
Лекция 5:

Скрипты

5.5.4. XPCOM и XPConnect

Стандарты DOM предоставляют интерфейсы, которые делают содержимое доступным из скриптов. Похожим образом XPConnect и XPCOM предоставляют интерфейсы, которые делают доступными из скриптов составные части самой платформы Mozilla.

XPCOM - полностью внутренняя часть платформы Mozilla. XPConnect - соединительное звено, превращающее XPCOM-объекты и их интерфейсы в объекты базового ПО для JavaScript. В "Объекты XPCOM" , "Объекты XPCOM", подробно описывается работа с этой системой с точки зрения приложения. В текущей лекции дается только обзор этих двух технологий.

С точки зрения программиста приложения, система XPCOM в основном представляется объектом window.Components (см. рисунок 5.1). Свойства этого объекта classes и interfaces - списки всех доступных идентификаторов контрактов XPCOM-объектов и имена их интерфейсов. Свойство manager - менеджер XPCOM-компонентов. Свойство results - список всех исключений, которые могут быть выброшены, и значений результатов, которые могут возвращаться. Результаты - 32-битные числа.

Теоретически эти списки могут динамически меняться, но в стандартной платформе этого не происходит. Стандартная платформа регистрирует все доступные компоненты во время запуска, и большая часть этой избыточной регистрации проводится во время первого запуска платформы. Набор зарегистрированных компонентов может быть пересмотрен при запуске инструмента regxpcom (в Microsoft Windows - regxpcom.exe). Эта маленькая программа устанавливается вместе со стандартной платформой и необходима только при создании или установке новых XPCOM- объектов (например, целых модулей, а не просто объектов; см. "Объекты XPCOM" , "Объекты XPCOM").

С точки зрения программиста приложений, система XPConnect, делающая написанные на C/C++ компоненты доступными из JavaScript, почти невидима. Чтобы выполнить свою задачу, система XPConnect опирается на набор библиотек типов (с расширениями .xpt), которые хранятся в подкаталоге components каталога установки платформы. XPConnect также предоставляет доступ из скриптов к модулям браузера, интерфейсам DOM, Java и Java-аплетам. Хотя эти вещи и кажутся не связанными с XPCOM, в конце концов они все оказываются XPCOM-компонентами.

Все XPCOM-компоненты, предоставляющие более одного XPCOM- интерфейса, должны реализовывать интерфейс nsISupports. Этот интерфейс предоставляет метод QueryInterface(), с помощью которого можно находить другие поддерживаемые объектом интерфейсы.

5.5.4.1 Поиск XPCOM-компонентов

Платформа Mozilla очень велика, и многие ее части разбиты на составные блоки, каждый из которых является XPCOM-объектом с какими-то собственными уникальными характеристиками. Не вся Mozilla разделена на такие блоки; в ней все еще есть анонимные куски, скрытые внутри платформы.

Существует, по крайней мере, тысяча XPCOM-компонентов, каждый из которых предоставляет один или несколько интерфейсов. Это огромное число компонентов и этот набор эквивалентны очень большой библиотеке классов. Такое количество компонентов создает трудности для новичков. На первый взгляд, доступные функции Mozilla кажутся никак не связанными между собой, однако это не так. Просто все необходимые знания за один присест получить не удастся, а структура предмета неочевидна. Поиск документации по всем компонентам Mozilla также непрост. По две страницы на компонент - итого две тысячи страниц. Когда-нибудь такая книга, может, и будет написана, но пока ее еще нет.

Чтобы найти подходящий компонент, придется приложить усилия. То, что нам в конце концов нужно - объект, который можно использовать для решения конкретной задачи. Не ко всем объектам необходимо обращаться напрямую через XPCOM-интерфейсы. Многие объекты существуют в других формах. Перед погружением в XPCOM задайте себе вопрос: может ли нужный вам объект появиться в одной из этих форм?

  • Стандартный объект JavaScript (например, Date или Math ). Если да, загляните в стандарт ECMAScript.
  • Как часть DOM. Если объект связан с любой частью XML-документа, он описывается стандартами W3C DOM.
  • Как часть BOM. Из книги о JavaScript для web-страниц можно узнать, является ли какой-то объект стандартной частью скриптов для HTML. В введении в AOM в этой лекции также сообщается, что есть и стандартные объекты XUL, доступные из скриптов.
  • XBL-связь. Почти у всех объектов, которым соответствует какой-то XUL-тег, есть и XBL-связка. Определения связок можно найти в архиве toolkit.jar в chrome.
  • Как служба нестатического объекта. Некоторые объекты существуют отдельно от DOM, но, тем не менее, доступны для непосредственной работы с ними (например, Image и Option в HTML, XMLHttpRequest и SOAPService в HTML и XUL).

Если же не остается ничего, кроме как искать XPCOM-объект, то вот что следует делать. Объекты создаются из XPCOM-интерфейсов и XPCOM-компонентов, реализующих эти интерфейсы. У интерфейсов есть имена; у компонентов есть идентификаторы контракта (они же и их имена). Для поиска этой информации подойдет любая из следующих стратегий:

  • в индексе в конце этой книги найти ключевое слово, соответствующее области задачи. На протяжении книги рекомендуются многие пары "компонент-интерфейс";
  • загрузить краткое описание лекций этого курса с сайта (http://www.nigelmcfarlane.com) и поискать в них;
  • загрузить наборы XPIDL-определений с сайта этой книги (http://www.nigelmcfarlane.com) или из исходных текстов на mozilla.org и поискать в них;
  • исследовать chrome-приложения, которые поставляются вместе с классической Mozilla. Этот код содержит множество оттестированных и проверенных примеров;
  • искать в ресурсах организации mozilla.org, например, на сайтах, в конференциях, задавать вопросы в IRC. На четко сформулированные вопросы в этих сообществах часто дают подробные ответы.

Из всех этих стратегий наиболее результативными будут чтение этой книги и загрузка копии XPIDL-файлов и других кратких описаний.

Наконец, имена почти всех (но не всех) полезных интерфейсов начинается с префикса:

nsI

а идентификаторы контракта всех компонентов начинаются с префикса:

@mozilla.org/

После того, как вы найдете пару из нужных вам интерфейса и компонента, требуется создать объект. Делается это так.

5.5.4.2. Работа с XPCOM-компонентами

Вот простой пример использования XPCOM-компонента. В языке Perl есть ключевое слово require, позволяющее одному скрипту на Perl загрузить содержимое другого скрипта. В JavaScript нет аналога этой инструкции, но в Mozilla для этого можно использовать компоненты. Посмотрим на пример в листинге 5.7.

var comp_name = "@mozilla.org/moz/jssubscript-loader;1";
var comp_obj = Components.classes[comp_name];
var if_obj = Components.interfaces.mozIJSSubScriptLoader;
var final_obj = comp_obj.createInstance(if_obj);
final_obj.loadSubScript("file:///tmp/extras.js");
Листинг 5.7. Включение скриптов JavaScript с помощью XPCOM-компонента Mozilla

Этот скрипт эквивалентен использованию eval() с содержимым файла /tmp/extras.js как аргумента.

Для создания объекта необходимы две вещи: имя компонента ( строка, comp_name ) и интерфейс, который можно использовать ( имя свойства, if_obj ). После получения объекта ( final_obj ) можно задействовать его методы. В нашем случае метод loadSubScript() импортирует содержимое файла extras.js, как если бы оно было строкой, обрабатываемой eval().

Характерный для многих компонентов Mozilla комментарий в XPIDL-определении mozIJSSubScriptLoader объясняет, что загружаемый файл JavaScript должен быть расположен на локальном компьютере. Краткие и рассредоточенные пояснения обычны для компонентов Mozilla.

5.5.4.3. Другие варианты создания объектов

В листинге 5.7 для создания объекта использовался метод createInstance(). Это одна из основных альтернатив. Другая - метод getService(). Он используется, когда данный XPCOM-компонент реализован так, чтобы предоставлять только единственный экземпляр объекта (одиночный объект). Такие объекты могут содержать статическую или глобальную информацию, которую нельзя синхронизировать между различными экземплярами объекта. В листинге 5.7 строку с createInstance() можно заменить на следующую:

var final_obj = comp_obj.getService(if_obj);

Как определить, какой из методов следует использовать? Если идентификатор контракта или имя интерфейса содержат слово "service" (в любом регистре), пользуйтесь getService(), иначе - createInstance().

Эти методы можно вызывать и без аргументов. В этом случае у создаваемого или возвращаемого объекта есть интерфейс nsISupports. Затем с помощью данного интерфейса можно получить любой другой нужный интерфейс. Чтобы проиллюстрировать эту ситуацию, мы можем изменить листинг 5.7:

var anon_obj = comp_obj.createInstance();
var final_obj = anon_obj.QueryInterface(if_obj);

Если нужно создать несколько однотипных объектов, можно сначала создать конструктор, а потом с его помощью сгенерировать отдельные объекты. Следующий код заменяет первые четыре строчки листинга 5.7:

var Includer = Components.Constructor(
  "@mozilla.org/moz/jssubscript-loader;1",
  "mozIJSSubScriptLoader",
  null
);
var final_obj = new Includer();
// var another_obj = new Includer()

Обратите внимание, что в этом случае имя интерфейса представляет собой строку. Третий аргумент метода Constructor() - необязательная строка. Если она есть, она означает имя метода, который будет вызван как метод инициализации при создании экземпляра объекта. Все аргументы, переданные конструктору объекта Includer(), будут передаваться этому методу инициализации.

Наконец, можно создавать объекты с XPCOM-интерфейсами прямо в JavaScript. Это можно делать только для простых интерфейсов, для которых не предусмотрена какая-либо особая обработка. Продолжая вариации на тему листинга 5.7, мы можем создать объект, используя код листинга 5.8.

var final_obj = {
  // интерфейс nsISupports
  QueryInterface : function(iid) {
  var Ci = Components.interfaces;
  if ( !iid.equals(Ci.nsISupports) &&
  !iid.equals(Ci.mozIJsSubSCriptLoader )
  throw Components.results.NS_ERROR_NO_INTERFACE;
  return this;
},
// интерфейс mozIJSSubScriptLoader
loadSubScript : function (url) {
  // здесь идет код для запуска скрипта
  return;
}
};
Листинг 5.8. Создание JavaScript-объекта с XPCOM-интерфейсом

Этот объект поддерживает и интерфейс nsISupports, и mozIJsSub-ScriptLoader. Если бы мы могли быть уверены, что для этого объекта никогда не будет вызван метод QueryInterface(), мы могли бы не использовать часть объекта с nsISupports. Конечно, с этим объектом связана одна большая проблема: как правильно реализовать второй интерфейс? Эта реализация будет содержать длинный код, открывающий файл в файловой системе, читающий его содержимое, передавая его eval(). Для этого можно использовать уже существующую реализацию объекта. Такое создание объектов вручную иногда очень полезно. Чаще всего оно бывает необходимо при создании возвращаемых объектов для разных отслеживающих функций, см. "События" , "События".

Метод createInstance() сам реализуется интерфейсом nsIComponentManager ; getService() реализуется интерфейсом nsIServiceManager.

5.5.4.4. Модули и DOM

К модулям браузера можно обращаться из скриптов, начиная с третьих версий браузеров. В то время Netscape расширила версию 1.1 стандарта модулей NPAPI, чтобы сделать его доступным из скриптов, и для работы с ним были написаны сотни модулей. Mozilla до сих пор поддерживает этот стандарт, но чтобы все работало без заминок, нужны последние версии и платформы, и модулей (особенно это касается Macromedia's Flash).

Для модулей существуют наборы XPIDL-интерфейсов. С их помощью отдельными модулями можно управлять прямо из JavaScript. По-прежнему самый простой способ работать с модулями - пользоваться HTML-тегами <embed> (не рекомендуется) или <object> (рекомендуется) и массивом plugins DOM 0. Обсуждение комбинирования HTML и XUL можно найти в "Окна и панели" , "Окна и панели".

Наборы интерфейсов, доступных в скриптах, также существуют в стандартах DOM, так что интерфейсы DOM можно получить и с помощью объекта Components. Однако это не имеет особого смысла, так как такие интерфейсы автоматически доступны для объекта window, а также для всех DOM-объектов, созданных и полученных с помощью данного объекта.

5.5.4.5. Java

Браузеры поддерживают доступ к Java-апплетам из скриптов, начиная с третьих версий; Mozilla также поддерживает эту функциональность. Архитектура, используемая для этого в платформе 1.x, отличается от архитектуры в Netscape Communicator 4.x, но совместима с ней, так что проблем у авторов скриптов быть не должно.

В Netscape Communicator 4.x браузер полностью зависел от модели защиты Java 1.1. Чтобы браузер мог принять какое-то решение относительно защиты, нужно было послать запрос Java с целью проверить специальную библиотеку классов, предоставляемую Netscape. Java и JavaScript были связаны с помощью технологии LiveConnect.

В Mozilla этой зависимости от Java больше нет. Netscape отвечает за свою защиту сам. Java не требуется и она уже не интегрирована в такой степени в платформу. LiveConnect в его первоначальном смысле не существует; есть только XPConnect. Интеграция, предоставляемая LiveConnect, все еще существует, но она находится ниже XPCOM под слоями кода. Явная поддержка Java в Mozilla теперь состоит из набора XPCOM-интерфейсов, как и многое другое, а поддержка Java по статусу считается близкой к модулям. Функциональность LiveConnect по-прежнему проявляется, когда создаются интерфейсы объектов Java и JavaScript для доступа к ним из "неродного" языка.

Mozilla предоставляет две технологии для адаптации Java. Первая - OJI (Open Java Inteface, открытый интерфейс к Java). Это программный интерфейс, напоминающий интерфейс NPAPI (для модулей), который предназначен для работы с платформой Java любого производителя. XPCOM-интерфейсы предоставляют доступ к OJI. Вторая технология - эмулятор LiveConnect для обратной совместимости. Это тоже XPCOM-интерфейс, определенный в интерфейсе nsIJRILLiveConnectPlugin. Этот эмулятор обрабатывает C/C++-запросы Mozilla, которые раньше отправлялись Netscape 4.x виртуальной машиной Java.

Как и в случае с модулями, по-прежнему простейший способ использовать Java внутри Mozilla - теги <applet> или <object> в HTML-файле. Опять же, о том, как смешивать HTML и XUL, рассказано в "Окна и панели" , "Окна и панели".

Некоторые программисты, пришедшие в web-программирование, уже обладают знанием Java. Если у вас есть сложная Java-среда, которую предстоит интегрировать с Mozilla, будьте осторожны. С одной стороны, самые простые и очевидные взаимодействия между JavaScript и Java будут работать прекрасно. С другой стороны, JavaScript, Java и Mozilla - очень сложные системы, и идеальное их взаимодействие на любом уровне - глобальная цель. В случае более сложных взаимодействий по-прежнему возникают проблемы, и рекомендуется внимательно изучить ошибки, связанные с Java в базе данных ошибок, Bugzilla.

Лучше всего остановиться на реализации Java от Sun Microsystems и затем пользоваться только версией 1.4 или более поздней. Чтобы свести к минимуму вероятность нетривиальных ошибок, рекомендуется пользоваться последними версиями Mozilla.

За исключением некоторых замечаний в "Окна и панели" , "Окна и панели", в этом курсе разговор о Java завершен.