Я пишу плагин веб-браузера (NPAPI).
Мой плагин запускает рабочий поток, и в то время как рабочий прогрессирует, я хотел бы пасовать назад события к JavaScript. Но из-за модели потоков NPAPI, это не законно, чтобы рабочий поток перезвонил в NPAPI непосредственно, таким образом, рабочий поток не может вызвать Javascript.
Одним решением этого является функция NPN_PluginThreadAsyncCall. Но это - относительно новая функция. Например, это поддерживало только от Firefox 3 на.
Там какой-либо путь состоит в том, чтобы получить асинхронное событие выполнение delivery/javascript от плагина NPAPI, не используя NPN_PluginThreadAsyncCall? Что делали люди, прежде чем эта функция была добавлена?
Ответ - да ... и нет ...
Если вам нужна поддержка старых браузеров (до Firefox 3), вы можете реализовать функцию NPN_PluginThreadAsyncCall самостоятельно. В Windows вы можете сделать это, создав структуру данных, которая может содержать указатель на функцию и указатель void * opaque, а затем опубликовать собственное сообщение в главном окне с указателем на вашу структуру данных как LPARAM.
Главное окно WINPPROC выполняется в потоке пользовательского интерфейса, который является потоком, который может взаимодействовать с Javascript. Итак, когда вы получаете это сообщение в своем WINPROC, вы просто возвращаете LPARAM обратно к указателю, вызываете метод с непрозрачными данными, а затем освобождаете структуру данных.
На Mac вы можете сделать то же самое с очередь для хранения событий, а затем в событии NULL (которое Mac OS отправляет при каждом тике) проверьте, есть ли в нем что-нибудь. 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));
}