Генерация асинхронных событий Javascript из плагина браузера (NPAPI) - PullRequest
8 голосов
/ 19 декабря 2009

Я пишу плагин для веб-браузера (NPAPI.)

Мой плагин запускает рабочий поток, и по мере продвижения рабочего я хотел бы передавать события обратно в Javascript. Но из-за модели потоков NPAPI рабочий поток не имеет права напрямую вызывать NPAPI, поэтому рабочий поток не может вызывать Javascript.

Одним из решений этой проблемы является функция NPN_PluginThreadAsyncCall. Но это относительно новая функция. Например, он поддерживается только в Firefox 3.

Есть ли способ получить доставку асинхронного события / выполнение JavaScript из плагина NPAPI без использования NPN_PluginThreadAsyncCall? Что люди делали до того, как была добавлена ​​эта функция?

1 Ответ

5 голосов
/ 20 декабря 2009

Ответ - да ... и нет ...

Если вам нужна поддержка старых браузеров (до Firefox 3), вы можете самостоятельно реализовать функцию NPN_PluginThreadAsyncCall. В Windows вы можете сделать это, создав структуру данных, которая может содержать указатель на функцию и непрозрачный указатель void *, а затем опубликовать пользовательское сообщение в главном окне с указателем на структуру данных как LPARAM.

Главное окно WINPPROC выполняется в потоке пользовательского интерфейса, который является потоком, который может общаться с Javascript. Поэтому, когда вы получаете это сообщение в своем WINPROC, вы просто приводите LPARAM обратно к указателю, вызываете метод с непрозрачными данными, а затем освобождаете структуру данных.

На Mac вы можете сделать то же самое с очередью для хранения событий, а затем с помощью события NULL (которое отправляется Mac OS при каждом тике) проверять, есть ли в нем что-либо. Если это так, отключите его, вызовите метод, освободите его и продолжайте.

Возможно, есть способ сделать это и в Linux, но я не знаю, что это такое.

Пример версии windows можно найти в проекте firebreath .

Обработка сообщения winproc находится в этом файле: https://github.com/firebreath/FireBreath/blob/master/src/PluginWindow/Win/PluginWindowWin.cpp

Событие и структура данных определены в его заголовочном файле: https://github.com/firebreath/FireBreath/blob/master/src/PluginWindow/Win/PluginWindowWin.h

И метод запуска этого события здесь:

void ActiveXBrowserHost::ScheduleAsyncCall(void (*func)(void *), void *userData)
{
    if (m_hWnd != NULL) 
        ::PostMessage(m_hWnd, WM_ASYNCTHREADINVOKE, NULL, 
            (LPARAM)new FB::WINDOWS_ASYNC_EVENT(func, userData));
}
...