В связи с тем, что я столкнулась с проблемами при написании необходимой мне программы, я решила написать это руководство к действиям, своего рода “памятка” – схема последовательности действий. Я не претендую на то, что я решила проблему лучшим образом и все сделала правильно.
В начале я опишу, какая задача была передо мной поставлена, как я пыталась ее решить, а потом по шагам – как мне все же это удалось.
Итак, мне необходимо было написать приложение, которое бы подключалось к Mozilla и FF и в выбранный пользователем момент выполняло определенные действия.
Представьте, у Вас есть какая-то база (приложение написанное на Delphi или С++ или вообще с помощь MFC - в дальнейшем назовем это приложение Главным), пользователь кликает мышью по какому-то полю в Mozilla и в базу заносится информация записанная в этом поле, тип поля и так далее…плюс - информация о страничке. Основная проблема! – при этом Mozilla не получает управления, то есть – управление у Главного приложения!
И следующий шаг (более легкий): в дальнейшем, когда пользователь переключается между страничками, автоматически заполняются все поля, которые сохранены в базе.
Все примеры которые я смотрела были написаны с помощью JS… причем я не сильно понимаю – зачем делать на джаве скрипт диалоговые окна – если можно написать компоненту…. Ладно, это уже пожелание авторов…
С чего я начала: http://xul.ru/- хороший сайт – но совершенно не то, что мне надо… полазив по http://xulplanet.com/(основной помощник) и сайту Mozilla – поняла, что плагины совершенно не для меня – Плагин выполняется только для определенной странички.
Значит, надо писать расширение: взяла пример http://www.borngeek.com/firefox/tutorial/(есть и переведенный вариантhttp://www.toolbar.net.ru/1.html), помучила этот пример…
Не буду приводить здесь строгую схему создания xpi файла – так как она очень хорошо описана в этих ссылках. Но получилось у меня в результате такое:
Myhook.xpi ->> install.rdf
install.js
->> myhook.jar->>[content]->> actions.js
contents.rdf
myhook.js
myhook.xul
Myhook.xpi – это переименованный zip файл;
install.rdf и install.js взятые из примера в них только изменены - имя расширения, автор, GUID и имя jar файла.
myhook.jar – делаю с помощью батника jar.bat:
contents.rdf – измены только пути и имена;
myhook.xul – прописаны два скрипта:
<script type="application/x-javascript" src="actions.js" /> <script type="application/x-javascript" src="myhook.js" />
myhook.js (все содержимое файла)
var actions = new actions(); window.addEventListener("load", formInitialize, true); function formInitialize() { try { window.addEventListener("load", actions.doLoad,true); // перехватываем события загрузки новой страницы } catch(e) { } }
actions.js (все содержимое файла):
function actions() { this.doLoad = doLoad; function doLoad() { alert('Load page…'); } }
Вот и получилось расширение, которое каждый раз при загрузке странички выдает сообщение «Load page…». Кстати, иногда выдает и по несколько раз на страничку или бывает, что и не выдает – если загрузка никак не может закончиться…
Но это расширение не может решить проблему обмена информации с Главным приложением. Поэтому я начала искать возможность добавить какой-то элемент – способный вызвать функции главной программы.
Выход нашла в создании компоненты: http://www.iosart.com/firefox/xpcom/. Снова же описание очень хорошее, а главное все работает.
Итак, копируем пример, рассматриваем его со всех сторон и экспериментируем. Общая схема создания и добавления компоненты в Mozilla такова:
1. Скачаем [gecko-sdk]
2. Скачаем пример. Архив xpcom-sample.zip содержит такие файлы:
[url]IMyComponent.h
IMyComponent.idl
IMyComponent.xpt
MyComponent.mak
MyComponent.dsp
MyComponent.cpp
MyComponentModule.cpp[/url]
Makefile – меня не интересовал так как с проектом я работала на Visual Studio 6.0
3. Переименовываем все файлы, например, на MyNewComponent. Чтобы поменять имя проекта, откройте MyNewComponent.dsp в текстовом редакторе и замените все MyComponent на MyNewComponent, то же самое надо сделать в MyNewComponent.mak.
3. В директорию [gecko-sdk]-[idl] перекопируем IMyNewComponent.idl файл.
4. Если необходимое меняем содержимое IMyNewComponent.idl файла (перечисляем все функции, которые хотим вызывать из своего actions.js файла):
#include "nsISupports.idl" #include "nsIAccessibleDocument.idl" [scriptable, uuid([свой GUID])] interface IMyNewComponent : nsISupports { long OnLoadPage(); long SetBrWindow(in nsIAccessibleDocument window); };
5. Пишем два батника или выполняем в командной строке:
– получим IMyNewComponent.xpi файл
– получим IMyNewComponent.h файл
6. Копируем IMyNewComponent.idl и IMyNewComponent.h файлы себе в проект.
7. Добавляем в MyNewComponent.сpp тело функций описанных в IMyNewComponent.h
8. Открываем проект. Вызовем диалоговое окно Settings. В С/С++ в категории Preprocessor изменяем путь «Additional include directories» к [gecko-sdk].
9. Компилируем проект.
Установка для FF:
Добавляем в схему еще одну директорию [components]
Myhook.xpi ->> install.rdf
install.js
->> myhook.jar
[components] ->> MyNewComponent.dll
IMyNewComponent.xpi
Установка для Mozilla:
1. Переписываем MyNewComponent.dll и IMyNewComponent.xpi в директорию [components], которая находится в установленной Mozilla.
2. Выполняем regxpcom.exe
3. И удаляем xpti.dat и compreg.dat
4. Запускаем Mozilla
Теперь, когда компонента зарегистрирована, вызовем ее метод в actions.js:
function actions() { this.doLoad = doLoad; netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); const cid = "@mydomain.com/XPCOMSample/MyNewComponent;1"; obj = Components.classes[cid].createInstance(); obj = obj.QueryInterface(Components.interfaces.IMyNewComponent); function doLoad() { alert('Load page…'); } }
Конечно, можно было бы добавить метод вызова в какую-то функцию. Но тогда компонента будет инициализироваться каждый раз, а мне необходимо было постоянно обращаться к этой dll.
Теперь будем каждый раз при вызове doLoad передавать
function doLoad() { const accServiceID = '@mozilla.org/accessibilityService;1'; const accServiceIF = Components.interfaces.nsIAccessibilityService; const accService = Components.classes[accServiceID].getService(accServiceIF); var acc = accService.getAccessibleFor(window.content.document); var dom_window = acc.QueryInterface(Components.interfaces.nsIAccessibleDocument); obj.SetBrWindow(dom_window); }
Где функция SetBrWindow записывает dom_window(элемент компоненты nsIAccessibleDocument) в глобальную переменную MyNewComponent.dll g_dom_window. Теперь в нашей компоненте хранится информация об окне, а соответственно мы легко можем получить содержимое документа. Выбор компоненты nsIAccessibleDocument связан с тем, что из нее можно получить HWND окна браузера:
Но всегда ли мы имеем доступ к текущему документу? Как узнать Главному приложению, с каким именно окном нужно работать, если открыто запущенно несколько окон Mozilla? И что если в одном окне Mozilla загружено несколько страничек и пользователь переходит с одной на другую?
Добавим в myhook.js перехват еще двух событий:
function formInitialize() { try { window.addEventListener("load", actions.doLoad,true); // перехватываем события загрузки новой страницы window.addEventListener("click", actions.doClick, false); //пользователь перешел на другую страничка window.addEventListener("focus", actions.doActivate, true); //пользователь перешел на другое загруженное приложение FF или Mozilla. } catch(e) { } }
И в каждой новой функции выполняются те же действия, как и в doLoad. Теперь осталась только научить компоненту обмениваться информацией с главным приложением.
Содержание MyNewComponent.h файла:
class MyNewComponent : public IMyNewComponent { public: NS_DECL_ISUPPORTS NS_DECL_IMYNEWCOMPONENT MyNewComponent (); virtual ~ MyNewComponent(); bool InitWindow(); bool InitMemory(); };
Функции InitWindow() и InitMemory() вызываются в конструкторе класса. В InitWindow создается обычное API окно с обработчиком событий:
В InitMemory инициализируется глобальная переменная pShared. В выделенной Shared Memory будут храниться данные общие для двух приложений. То есть, когда мы из g_dom_window получим необходимую информацию, то запишем ее в структуру, на которую указывает pShared.
Теперь нам необходимо определять момент, когда Главному приложению требуется получить из странички информацию о содержании полей. Зарегистрируем новое для Window сообщение в компоненте и в Главном приложении.
Обработаем такие сообщения в WndProc:
if (message == WM_SETSHARED_DATA) PostInfo(); // выполняем функцию заполнения структуры, на которую указывает pShared, //необходимыми данными if (message == WM_CREATE) pShared->hWindowComponent = hWnd; // запоминаем в HWND созданного нами окна.
А в Главном приложении пошлем зарегистрированное сообщение WM_SETSHARED_DATA для окна созданного в компоненте:
WPARAM wParam = 0; LPARAM lParam = 0; SendMessage(pShared->hWindowComponent,WM_SETSHARED_DATA,wParam,lParam);
После этого осталось только использовать данные записанные в структуре.
На последок несколько замечаний:
1. Конечно, вместо Shared Memory можно использовать WM_COPYDATA.
2. Отлавливать событие focus надо еще и из-за того, что необходимо записывать в pShared->hWindowComponent окно из текущей длл.
3. Чтобы избежать вопросов в отношении того, что в Mozilla есть реализованный интерфейс запоминания содержания полей на страничках (по крайней мере паролей), скажу, что по ряду причин он не устраивал моих заказчиков.
4. Осталась проблема с написание Инсталляции – как сделать так, чтобы можно было не требовать у пользователя самостоятельной установки расширений?
5. Каждый раз при запуске очередного окна Mozilla создается новое окно в функции InitWindow(), которое и отвечает дальше за обмен информацией. Предыдущие созданные окна теряются. С этим вопросом еще предстоит разобраться.
Отсутствует
Aerina
Не сильно я в этом разбираюсь, но ваша работа достойна уважения
Может в Документацию разместить?
Отсутствует
Aerina
Может в Документацию разместить?
Это уже по Вашему усмотрению
Отсутствует
Дайте девушке доступ в Wiki, она это заслужила
...она старалась, чтобы я больше времени проводил в разных пионерлагерях и группах продлённого дня - кстати сказать, удивительную красоту последнего словосочетания я вижу только сейчас. (c) Виктор Пелевин
Отсутствует
Дайте девушке доступ в Wiki, она это заслужила
Я, вообще-то думал, Unghost сразу присвоил ей нужные права, после того, как "отметился" в этой теме. Вопрос, правда, в другом: захочет ли она писать (сама) в Wiki ?
Время настанет, время придет...
И лис кОнкурiентов на части порвет !!!
Отсутствует
Anton
Я, вообще-то думал, Unghost сразу присвоил ей нужные права, после того, как "отметился" в этой теме.
Гм, я просто размышлял стоит ли давать права новичку. 17 постов у человека.
Сейчас права дал.
Do not meddle in the affairs of Wizards, for they are subtle and quick to anger.
Отсутствует
Гм, я просто размышлял стоит ли давать права новичку. 17 постов у человека.
Сейчас права дал.
Постараюсь не подвести... подтвердить, что ли, оказанное доверие...
Отсутствует
Aerina, Отличная работа!
А где расширения обычно хранят свои настройки? Есть какое-то правило по этому поводу?
:::: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0
Отсутствует
А где расширения обычно хранят свои настройки? Есть какое-то правило по этому поводу?
Настройки? какие настройки Вы имеете ввиду?
Если это внутрение настройки расширения - то там где пожелает производитель ("нарисует" диалоговое окно или еще как нибудь...), а так в ФФ все что мы можем сделать с расширением - это добавить его и удалить.
Но есть кажется, если я не ошибаюсь, какие-то интерфейсы предоставляющие место для хранения настроек, информации, флагов - но это уже относится к самому процессу программировани. То есть, программист может организовать какой-то интерфейс доступа к этим настройкам для пользователя.
Отсутствует
Aerina, есть одно замечание и одно предложение:
- файл install.js отсутствует в примере http://www.borngeek.com/firefox/tutorial/, во всяком случае в архиве http://www.borngeek.com/firefox/tutorial/gbltutorial.zip его нет.
- есть предложение добавить файл файл работающего примера, хотя бы того, который при загрузке странички выдает сообщение «Load page…».
Спасибо.
Отсутствует
Aerina, есть одно замечание и одно предложение:
- файл install.js отсутствует в примере http://www.borngeek.com/firefox/tutorial/, во всяком случае в архиве http://www.borngeek.com/firefox/tutorial/gbltutorial.zip его нет.
- есть предложение добавить файл файл работающего примера, хотя бы того, который при загрузке странички выдает сообщение «Load page…».
Спасибо.
Да. согласна. Вообще install.js - мне нужен был для установки расширения в Mozilla Suite, а в FF - можно и без него. Исправлю это в статье. И когда добавлять текст в "документацию" - не забуду про пример.
Спасибо за замечание.
Отсутствует
Aerina
Makefile – меня не интересовал так как с проектом я работала на Visual Studio 6.0
Я попробовал собрать проект при помощи cygwin, но он ругается на потроха из gecko-sdk:
$ make c++ -Wall -Os -o -mno-cygwin MyComponent.so -include mozilla-config.h -DXPCOM_G LUE -I ./gecko-sdk/include -L ./gecko-sdk/lib -lxpcomglue -lnspr4 -lplds4 -fno-rtti -fno-exceptions -shared MyComponent.cpp MyComponentModule.cpp c++: MyComponent.so: No such file or directory In file included from ./gecko-sdk/include/nsISupports.h:122, from IMyComponent.h:10, from MyComponent.h:4, from MyComponent.cpp:1: ./gecko-sdk/include/nsISupportsUtils.h:207: error: an explicit specialization must be preceded by 'template <>' In file included from ./gecko-sdk/include/nsISupports.h:122, from ./gecko-sdk/include/nsIFactory.h:10, from ./gecko-sdk/include/nsIGenericFactory.h:41, from MyComponentModule.cpp:1: ./gecko-sdk/include/nsISupportsUtils.h:207: error: an explicit specialization must be preceded by 'template <>' make: *** [build] Error 1
Кому-нибудь это удавалось при помощи cygwin? Мне нужно собирать это бесплатной утилитой.
:::: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0
Отсутствует
Aerina
Постараюсь не подвести... подтвердить, что ли, оказанное доверие...
Если не побоишся, и всетаки решишь написать статью, то для этих целей рекомендую плагин WikiCode . Позволяет через контекстное меню вставлять теги wiki. Это расширение написал старейший участник этого форума, Viper. Обсуждается здесь.
Можно еще с помощью кнопок быстрого форматирования размечать текст:
Для начала стоит поиграться в Песочнице . Там можно написать чтото в Wiki формате и посмотреть как это будет выглядеть.
По мере возникновения вопросов по синтаксису, всегда можно чтото уточнить в Синтаксисе форматирования.
Ну и конечно можно почитать Правила редактирования WiKi, хотя и не обязательно .
Вообще писать чтото в Wiki не сложнее чем отвечать на форумах, это только для начала кажется сложным.
ЗЫ: Форумчане, не сочтите за оффтопик, хотел девушке помочь с Wiki.
Не сильно разбираюсь в разработке плагинов, но мое скромное имхо, за такую работу нужно девушке поставить памятник . Aerina, ты молодец!
Fx 2.0.0.8
Отсутствует
а у KML аватар из игрушки *Рыбалка 2*
KML, флеймить не нужно...
Ragnaar
Отсутствует
e-travel Спасибочки!
Постараюсь, как можно быстрее разобраться с статьей... Уже начала читать Помощь для редактирования Wiki.
Исправлю ошибки, те что уже знаю и те, что найду. И добавлю примерчик (работающий:-)))
Отсутствует
Aerina
Если не напишешь, ничего страшного. Главное не спеши .
Если писать, то наверно в раздел Инициативы для разработчиков. Можно назвать Разработка расширений для Mozilla. Или так как эта тема называется.
Отредактировано e-travel (23-03-2006 03:41:42)
Fx 2.0.0.8
Отсутствует
Aerina
Если не напишешь, ничего страшного. Главное не спеши .Если писать, то наверно в раздел Инициативы для разработчиков. Можно назвать Разработка расширений для Mozilla. Или так как эта тема называется.
Да я тоже думала в этот раздел... но наверное "Разработка расширений для Mozilla" - не очень подойдет... (так как и компонента тоже не последнюю работу выполняет...) может лучше что-то типа "Как написать приложение взаимодействующее с Mozilla?"... ? но как-то слишком тяжело звучит. или "Разработка расширения и компоненты для обмена информацией с другими приложениями".
Короче, название наверное самый тяжелый вопрос на настоящий момент. Написать расширение было легче
Отсутствует
Дайте девушке доступ в Wiki, она это заслужила wink
Это точно, потому что я не хочу туда всё это вносить, слишком долго.
Ага, хитрые какие. Cами не хочем писать, а девушку заставляем .
Мое скромное имхо, для начала в Wiki такие большие статьи писать лучше не стоит.
Лучше с чегото попроще начать. Поэтому я решил помочь. ВотЪ:
Aerina, ты там подправь оформление так, как тебе больше нравится.
Отредактировано e-travel (24-03-2006 05:06:46)
Fx 2.0.0.8
Отсутствует
Дайте девушке доступ в Wiki, она это заслужила wink
Это точно, потому что я не хочу туда всё это вносить, слишком долго.
Ага, хитрые какие. Cами не хочем писать, а девушку заставляем .
Мое скромное имхо, для начала в Wiki такие большие статьи писать лучше не стоит.Лучше с чегото попроще начать. Поэтому я решил помочь. ВотЪ:
Aerina, ты там подправь оформление так, как тебе больше нравится.
Ай, спасибо большое!
Вот это настоящая помощь!
Отсутствует
e-travel
Вот-вот я уже наконец-то занялась праведным делом!
И у меня возникло несколько вопросов:
А можно как-то добавить не страничку, а Архивчик с исходниками?.. как говорится по прозьбам трудящегося HouseF
И общеобразовательный: А как добавить новую страничку? достаточно написать имя, а потом она сама создаться при нажатии на кнопку "Редактирование"... (могу конечно попробывать в песочнице, но там же одна страничка... - не знаю следует ли еще добавлять)
Отсутствует
А... вот думала насчет названия. Хотела поменять на "Разработка приложения для работы с Mozilla", но что-то так стало жалко свое уже привычное. Но это как-то серьезней звучит.. Стоит ли менять?
Отсутствует
Aerina
Если устроишь голосование - то я за "привычное" (ну, может быть, c не большим, не принципиальным изменением).
Отредактировано ioppp (03-04-2006 21:38:35)
" ...Отметим лишь, что качество локализации программного обеспечения этого модема способно нанести человеку психическую травму, а посему настоятельно рекомендуем использовать английский интерфейс..." (c) Басир Ахмедов .
Отсутствует
Aerina
Для архивчика с исходниками есть Uploads. Или мне пришли, выложу на ftp.mozilla.ru.
Do not meddle in the affairs of Wizards, for they are subtle and quick to anger.
Отсутствует