2009-12-19 10 views
8

Ich bin ein Web-Browser-Plugin zu schreiben (NPAPI.)Generieren asynchroner Javascript Ereignisse aus Browser-Plugin (NPAPI)

Mein Plugin startet einen Worker-Thread, und wie die Arbeiter fortschreitet, würde ich gerne wieder Ereignisse passieren zu Javascript. Aufgrund des NPAPI-Threadingmodells ist es jedoch nicht zulässig, dass der Arbeitsthread direkt in NPAPI zurückruft, sodass der Arbeitsthread JavaScript nicht aufrufen kann.

Eine Lösung hierfür ist die NPN_PluginThreadAsyncCall-Funktion. Aber das ist eine relativ neue Funktion. Zum Beispiel wird es nur von Firefox 3 an unterstützt.

Gibt es eine Möglichkeit, asynchrone Ereignislieferung/Javascript-Ausführung von einem NPAPI-Plugin zu erhalten, ohne NPN_PluginThreadAsyncCall zu verwenden? Was haben Personen gemacht, bevor diese Funktion hinzugefügt wurde?

Antwort

5

Die Antwort ist ja ... und nein ...

Wenn Sie ältere Browser unterstützen müssen (pre firefox 3), können Sie die NPN_PluginThreadAsyncCall selbst funktionieren implementieren. In Windows können Sie das tun, indem Sie eine Datenstruktur erstellen, die den Funktionszeiger und den void * opaque-Zeiger enthält, und dann eine benutzerdefinierte Nachricht mit einem Zeiger auf Ihre Datenstruktur als LPARAM an das Hauptfenster senden.

Das Hauptfenster WINPPROC wird auf dem UI-Thread ausgeführt, der der Thread ist, der mit Javascript kommunizieren kann. Wenn Sie diese Nachricht in Ihrem WINPROC erhalten, müssen Sie die LPARAM einfach zurück auf den Zeiger werfen, die Methode mit den undurchsichtigen Daten aufrufen und dann die Datenstruktur freigeben.

Auf dem Mac können Sie eine ähnliche Funktion mit einer Warteschlange zum Speichern der Ereignisse und dann mit dem NULL-Ereignis (das von Mac OS bei jedem Tick gesendet wird) überprüfen, um festzustellen, ob etwas darin enthalten ist. Wenn das der Fall ist, knallen Sie es ab, rufen Sie die Methode auf, geben Sie sie frei und machen Sie weiter.

Es gibt wahrscheinlich einen Weg, es auch auf Linux zu tun, aber ich weiß nicht, was es ist.

Sie finden ein Beispiel für die Windows-Version in firebreath project.

Die Handhabung der WinProc Nachricht in dieser Datei ist: https://github.com/firebreath/FireBreath/blob/master/src/PluginWindow/Win/PluginWindowWin.cpp

Die Veranstaltung und Datenstruktur in der Header-Datei definiert sind: https://github.com/firebreath/FireBreath/blob/master/src/PluginWindow/Win/PluginWindowWin.h

und das Verfahren für dieses Ereignis Brennen ist hier:

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)); 
} 
+1

Vielen Dank! Es ist äußerst hilfreich zu wissen, dass der Ereignis-Loop-Thread der Plattform-GUI für NPAPI-Aufrufe sicher ist. Und ich werde Firebreath auf jeden Fall ausprobieren. FWIW, auf Mac, wenn Sie sich auf Cocoa verlassen können, ist eine einfache Möglichkeit, Code auf dem GUI-Thread auszuführen, die NSObject-Methode performSelectorOnMainThread. – Geoff

+0

Ja, ich denke, jemand hat mir von performSelectorOnMainThread erzählt, aber ich musste es bisher nicht verwenden. Der Prozentsatz der Benutzer, die noch auf Firefox 2 sind, ist heutzutage so klein, dass ich mich entschieden habe, es nicht mehr zu unterstützen. Mit FireBreath könnten wir Unterstützung hinzufügen, wenn jemand es dringend genug (oder sie könnte), aber ich brauche es nicht für irgendwelche meiner Sachen. =] Es gibt einige wirklich nette Features, die erst mit firefox 2 implementiert wurden; NPN_Enumerate und NPN_Construct, zum Beispiel. Außerdem hat firefox 2 einen bekannten Fehler, dass Plugins, die in HKCU in Windows registriert sind, nicht sehen können, also muss man Admin sein. – taxilian