Previous Entry Share Next Entry
Custom DOM object for FireFox
and_cesbo
Задача: доработать фаерфокс - добавить DOM объект.
Зачем надо: для идентификации девайса на котором работает фаерфокс (например идентификация платёжного терминала ну или другого девайса). При входе на сервер открывается страничка с ява-скриптом который использует методы DOM-объекта для передачи данных от девайса на сервер.
Проблема: документация очень хреновая... та что есть очень кривая.

Ну, для начала надо скачать исходники фаерфокса :-) взять можно тут: ftp.mozilla.org/pub/mozilla.org/firefox/releases/latest/source/
DOM объект в виде исходного кода состоит из двух частей:
1. "Интерфейс" - *.idl файл в котором описываются переменные и методы объекта.
2. Исходный код - в общем тут уже пишется, что должен делать при вызове методов и переменных

Допустим наш объект будет называться BoxAPI.

Файл интерфейса размещаем в ./content/base/public/:
nsIBoxAPI.idl
#include "nsISupports.idl" 
 
[scriptable, uuid(748d3f42-3b0b-4fbd-8d0e-1e22ddd5d95a)]
interface nsIBoxAPI : nsISupports
{
  readonly attribute long date;
};


nsISupports.idl - это главный интерфейс для всех интерфейсов.
uuid(748d3f42-3b0b-4fbd-8d0e-1e22ddd5d95a) - уникальный идентификатор, чтобы его получить, выполните команду uuidgen (в линуксе).
readonly attribute long date; - цифровая переменная в объекте BoxAPI (только для чтения)(начинаться должен с маленькой буквы). тут подробная информация про IDL

Исходники DOM объекта я разместил в ./content/base/src/ два файла:
nsBoxAPI.h
#ifndef nsBoxAPI_h 
#define nsBoxAPI_h 
 
#include "nsIBoxAPI.h" 
 
class nsBoxAPI : public nsIBoxAPI
{
public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSIBOXAPI
  nsBoxAPI();
private:
  ~nsBoxAPI();
};
 
#endif // nsBoxAPI_h


nsBoxAPI.cpp
#include "nsBoxAPI.h" 
#include "nsDOMClassInfo.h" // for QueryInterface define's 
 
nsBoxAPI::nsBoxAPI(){}
 
nsBoxAPI::~nsBoxAPI(){}
 
// QueryInterface implementation for nsBoxAPI
NS_INTERFACE_MAP_BEGIN(nsBoxAPI)
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBoxAPI)
  NS_INTERFACE_MAP_ENTRY(nsIBoxAPI)
  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BoxAPI)
NS_INTERFACE_MAP_END
 
NS_IMPL_ADDREF(nsBoxAPI)
NS_IMPL_RELEASE(nsBoxAPI)
 
/* readonly attribute long date; */
NS_IMETHODIMP
nsBoxAPI::GetDate(PRInt32 *aDate)
{
  *aDate = 1984;
  return NS_OK;
}


Правим файлы Makefile.in в этих двух каталогах.
1. ./content/base/public/Makefile.in : В переменную XPIDLSRCS перед $(NULL) добавляем nsIBoxAPI.idl
2. ./content/base/src/Makefile.in : В переменную CPPSRCS перед $(NULL) добавляем nsBoxAPI.cpp

Теперь созданный объект надо приписать в общую кучу объектов. Для этого надо поправить несколько файлов:
1. ./dom/base/nsDOMClassInfoID.h : в этом файле в enum nsDOMClassInfoID.h, в конце, перед eDOMClassInfoIDCount, надо добавить eDOMClassInfo_BoxAPI_id,
2. ./dom/base/nsDOMClassInfo.cpp : тут изменений надо сделать побольше (для инициализации объекта):
2.1. добавить в общую кучу include :
#include "nsIBoxAPI.h"
(этот файл при компиляции генерируется автоматически из nsIBoxAPI.idl)
2.2. в структуру sClassInfoData (в самый конец) добавить
NS_DEFINE_CLASSINFO_DATA(BoxAPI, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS)

2.3. в функцию nsDOMClassInfo::Init() почти самый конец, где кончаются объявление DOM_CLASSINFO_MAP (у меня это строка 3727), добавляем:
  DOM_CLASSINFO_MAP_BEGIN(BoxAPI, nsIBoxAPI)
    DOM_CLASSINFO_MAP_ENTRY(nsIBoxAPI)
  DOM_CLASSINFO_MAP_END


Если сейчас откомпилировать проект то alert(BoxAPI) будет выдавать "[Object BoxAPI]"

3. ./dom/interfaces/base/domstubs.idl, в конец добавляем
interface nsIBoxAPI;

4. ./dom/interfaces/base/nsIDOMWindowInternal.idl, где-нибудь в начале класса-интерфейса добавляем:
readonly attribute nsIBoxAPI boxapi;

5. ./dom/base/nsGlobalWindow.h
5.1. добавляем
#include "nsBoxAPI.h"
(после всех includ-ов)
5.2. в protected класса nsGlobalWindow, добавляем
nsRefPtr<nsBoxAPI> mBoxAPI;
(чтобы класс nsBoxAPI не создавать заново при каждом обращении.
6. ./dom/base/nsGlobalWindow.cpp добавляем где-нибудь в районе строки 2600 важную функцию (она привязывает в скрипте слово boxapi к классу nsBoxAPI):
NS_IMETHODIMP
nsGlobalWindow::GetBoxapi(nsIBoxAPI** aBoxAPI)
{
  FORWARD_TO_OUTER(GetBoxapi, (aBoxAPI), NS_ERROR_NOT_INITIALIZED);
  *aBoxAPI = nsnull;
  if(!mBoxAPI) {
    mBoxAPI = new nsBoxAPI();
    if(!mBoxAPI) return NS_ERROR_OUT_OF_MEMORY;
  }
  NS_IF_ADDREF(*aBoxAPI = mBoxAPI);
  return NS_OK;
}


В общем всё, теперь можно добавлять только объявление методов/переменных в интерфейсе nsIBoxAPI.idl и описывать их в nsBoxAPI.cpp

компилировать лучше в отдельном каталоге: mkdir ../ff-build; cd ../ff-build
../mozilla-{версия исходников}/configure --prefix={куда поставить} --enable-application=browser --disable-crashreporter --disable-necko-wifi
make -j8

?

Log in

No account? Create an account