Pull to refresh

Создание плагина для браузера с помощью NPAPI

Reading time6 min
Views25K
NPAPI это набор API, позволяющий создавать плагины для Firefox, Chrome, Safari, Opera. В этой статье я хочу дать первоначальные сведения о создании плагина на базе NPAPI. Будет приведен пример плагина под Windows, но и разработчикам на Mac и Unix статья будет полезной, т.к. описывает общий подход к созданию плагинов, использующих NPAPI.

NPAPI плагин это модуль, который «цепляется» к браузеру и отвечает за обработку определенного content type (например application/x-shockwave-flash).

О том как появился и менялся NPAPI вы можете прочитать на странице в Wikipedia
Полное описание API можно получить на странице Gecko_Plugin_API_Reference

Для начала необходимо скачать XULRunner в состав которого входят заголовочные файлы, необходимые для создания плагина (include\plugin). Если вы работаете в Visual Studio — не забудьте добавить путь к файлам Include в VC++ Directories (пункт меню Tools -> Options -> Projects and Solutions -> VC++ Directories).

Плагин представляет из себя модуль, экспортирующий следующие функции:

NP_GetEntryPoints – вызывается при загрузке плагина. С помощью данной функции браузер получает указатели на другие функции, содержащиеся в плагине, необходимые браузеру для работы с плагином.
NP_Initialize – вызывается при инициализации плагина. При вызове браузер передает указатели на свои функции, которые могут понадобиться плагину.
NP_Shutdown – вызывается при завершении работы плагина.

Порядок вызова NP_GetEntryPoints и NP_Initialize может меняться в зависимости от браузера. В часности Chrome сначала вызывает NP_GetEntryPoints, затем NP_Initialize.

Давайте рассмотрим эти функции более продобно.

NP_GetEntryPoints

Прототип:

NPError WINAPI NP_GetEntryPoints(NPPluginFuncs* pFuncs)

В качестве аргументов передается указатель на структуру NPPluginFuncs

typedef struct _NPPluginFuncs {
// Размер структуры
uint16_t size;
// Версия
uint16_t version;
// Вызывается при создании нового экземпляра плагина
NPP_NewProcPtr newp;
// Вызывается при удалении экземпляра плагина
NPP_DestroyProcPtr destroy;
// Вызывается когда браузер хочет сообщить плагину о том,
// что окно (в котором находится объект, созданный плагином) создано,
// закрыто, изменило позицию или размер.

NPP_SetWindowProcPtr setwindow;
// Вызывается для уведомления плагина о создании нового потока данных.
NPP_NewStreamProcPtr newstream;
// Вызывается для уведомления плагина о закрытии или удалении потока данных.
NPP_DestroyStreamProcPtr destroystream;
// Вызывается для того, чтобы сообщить плагину полный путь
// к локальному файлу связанного с потоком данных.

NPP_StreamAsFileProcPtr asfile;
// Вызывается для определения максимального размера данных,
// которые готов обработать плагин.

NPP_WriteReadyProcPtr writeready;
// Вызывается для передачи данных плагину.
NPP_WriteProcPtr write;
// Вызывается когда пользователь запрашивает печать страницы,
// содержащей плагин.

NPP_PrintProcPtr print;
// Вызывается для обработки событий.
NPP_HandleEventProcPtr event;
// Вызывается после завершения URL запроса.
NPP_URLNotifyProcPtr urlnotify;
// Устаревшее, более не используется.
void* javaClass;
// Вызывается для запроса от плагина различной информации.
NPP_GetValueProcPtr getvalue;
// Вызывается для передачи плагину различной информации.
NPP_SetValueProcPtr setvalue;
} NPPluginFuncs;

Структура помимо размера (uint16_t size) и версии (uint16_t version) содержит указатели на функции, реализованные плагином. Немного забегая вперед скажу, что NPP_ это префикс функций реализуемых плагином, дальше мы встретим функии начинающиеся с NPN_ — эти функции реализуются браузером. Вроде бы мелочь, но данное знание помогает лучше понять жизненный цикл плагина.

Не все из выше перечисленных функций могут использоваться плагином, я не нашел нигде информации о том, корректно ли присваивать не используемым функциям NULL, поэтому создал функции-заглушки, которые ничего не делают, а только возвращают значение означающее успешность вызова NPERR_NO_ERROR. Например для NPP_DestroyStreamProcPtr:

static NPError StubDestroyStream(NPP instance, NPStream *stream, NPReason reason)
{
return NPERR_NO_ERROR;
}

NP_Initialize

Прототип для Windows:

NPError WINAPI NP_Initialize(NPNetscapeFuncs *aNPNFuncs)

Прототип для Unix:

NPError NP_Initialize(NPNetscapeFuncs *aNPNFuncs, NPPluginFuncs *aNPPFuncs)

Вызывается при инициализации плагина. Функция должна вызываться браузером только один раз, до создания первого экземпляра плагина.

В качестве аргументов передается указатель на структуру NPNetscapeFuncs

typedef struct _NPNetscapeFuncs {
// Размер структуры
uint16_t size;
// Версия
uint16_t version;
// Выполнение GET запроса
NPN_GetURLProcPtr geturl;
// Выполнение POST запроса
NPN_PostURLProcPtr posturl;
// Получение блока данных из потока
NPN_RequestReadProcPtr requestread;
// Создание нового потока данных
NPN_NewStreamProcPtr newstream;
// Запись данных в поток
NPN_WriteProcPtr write;
// Удаление и закрытия потока данных
NPN_DestroyStreamProcPtr destroystream;
// Отображение сообщения в строке состояния браузера
NPN_StatusProcPtr status;
// Получение строки "user agent"
NPN_UserAgentProcPtr uagent;
// Выделение памяти в адресном пространстве браузера
NPN_MemAllocProcPtr memalloc;
// Освобождение памяти в адресном пространстве браузера
NPN_MemFreeProcPtr memfree;
// Освобождение указанного диапазона памяти
NPN_MemFlushProcPtr memflush;
// Перезагрузка всех плагинов
NPN_ReloadPluginsProcPtr reloadplugins;
NPN_GetJavaEnvProcPtr getJavaEnv;
NPN_GetJavaPeerProcPtr getJavaPeer;
// Создание нового GET запроса с возможностью получать уведомления о ходе его выполнения
NPN_GetURLNotifyProcPtr geturlnotify;
// Создание нового POST запроса с возможностью получать уведомления о ходе его выполнения
NPN_PostURLNotifyProcPtr posturlnotify;
// Запрос информации от браузера
NPN_GetValueProcPtr getvalue;
// Передача информации браузеру
NPN_SetValueProcPtr setvalue;
// Запрос на повторную отрисовку области рисования
NPN_InvalidateRectProcPtr invalidaterect;
// Запрос на повторную отрисовку указанной области
NPN_InvalidateRegionProcPtr invalidateregion;
// Отправка сообщения на отрисовку плагину, не имеющему окна
NPN_ForceRedrawProcPtr forceredraw;
// Создание идентификатора из строки
NPN_GetStringIdentifierProcPtr getstringidentifier;
// Создание массива идентификаторов из массива строк
NPN_GetStringIdentifiersProcPtr getstringidentifiers;
// Создание идентификатора из числа
NPN_GetIntIdentifierProcPtr getintidentifier;
// Проверка явялется ли идентификатор строкой
NPN_IdentifierIsStringProcPtr identifierisstring;
// Преобразование идентификатора в строку
NPN_UTF8FromIdentifierProcPtr utf8fromidentifier;
// Преобразование идентификатора в число
NPN_IntFromIdentifierProcPtr intfromidentifier;
// Создание нового объекта
NPN_CreateObjectProcPtr createobject;
// Уменьшение на единицу количества ссылок на объект
NPN_RetainObjectProcPtr retainobject;
// Освобождение объекта
NPN_ReleaseObjectProcPtr releaseobject;
// Вызов метода указанного объекта
NPN_InvokeProcPtr invoke;
// Вызов метода по умолчанию для указанного объекта
NPN_InvokeDefaultProcPtr invokeDefault;
// Выполнение скрипта в контексте указанного объекта
NPN_EvaluateProcPtr evaluate;
// Получение свойства указанного объекта
NPN_GetPropertyProcPtr getproperty;
// Задание значения для свойства указанного объекта
NPN_SetPropertyProcPtr setproperty;
// Удаление свойства
NPN_RemovePropertyProcPtr removeproperty;
// Определение наличия свойства
NPN_HasPropertyProcPtr hasproperty;
// Определение наличия метода
NPN_HasMethodProcPtr hasmethod;
// Освобождение памяти, выделенной под значение NPVariant
NPN_ReleaseVariantValueProcPtr releasevariantvalue;
// С помощью данной функции плагин может уведомить браузер об ошибке
NPN_SetExceptionProcPtr setexception;
NPN_PushPopupsEnabledStateProcPtr pushpopupsenabledstate;
NPN_PopPopupsEnabledStateProcPtr poppopupsenabledstate;
// Получение списка имен свойств и методов указанного объекта
NPN_EnumerateProcPtr enumerate;
// Асинхронный вызов указанной функции в контексте потока плагина
NPN_PluginThreadAsyncCallProcPtr pluginthreadasynccall;
// Создание нового объекта
NPN_ConstructProcPtr construct;
NPN_GetValueForURLPtr getvalueforurl;
NPN_SetValueForURLPtr setvalueforurl;
NPN_GetAuthenticationInfoPtr getauthenticationinfo;
} NPNetscapeFuncs;

NP_Shutdown

Прототип для Windows:

void WINAPI NP_Shutdown(void);

Прототип для Unix:

void NP_Shutdown(void);

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

Для создания плагина необходимо создать DLL, реализовать перечисленные экспортируемые функции и можно начинать эксперементировать. Одно важное замечание — плагин не будет загружаться браузером, если в его информации о версии отсутствует строка MIMEType, определяющая content type, обрабатываемый плагином. В файле ресурсов она выглядит так:

VALUE "MIMEType", "application/minimize-to-tray-extension"

Без этой строки Chrome не хотел загружать плагин, а я долго не мог понять, почему не происходит вызова DllMain, не говоря уже о других экспортируемых функция.

Чтобы избавить себя от реализации всех функций, которые должен иметь плагин, в качестве отправной точки вы можете взять исходники моего проекта расширения для Google Chrome Minimize to tray
Tags:
Hubs:
Total votes 34: ↑33 and ↓1+32
Comments12

Articles