2013-03-08 12 views
5

Zuerst geht etwas Hintergrund über das, was ich mit Firebreath mache.Ein Feueratem JSAPI wird in firefox nicht erkannt

  1. Ich entwickle ein Rendering-Viewer-Plugin im Browser mit Firebreath.
  2. Ich definiere zwei MIME-Typ in meinem Plugin, eine ist für den Haupt-Viewer, und die andere ist für 2D-Draufsicht.
  3. Auf jeder Seite ist nur ein Hauptviewer zulässig, kann jedoch mehrere 2D-Draufsichten enthalten. Und sie alle teilen das gleiche Modelldokument, das im Hauptviewer geöffnet wurde.
  4. Also, nach der Instanziierung der 2D-Draufsicht, muss ich das Dokument-Objekt (ein Feueratem JSAPI) an die 2D-Draufsicht übergeben.

Dann übernehmen die Haupt-Viewer und eine Draufsicht sind beide geladen, wie ‚mainviewer‘ genannt und ‚Planview‘, und ich werde das Dokument planen Betrachter wie unten,

planview.attach(mainviewer.doc); 
(the signature is "bool attach(const FB::JSObjectPtr& myDoc)" and 
The mainviewer.doc is just a firebreath JSAPI) 

Die AUSGABE attch ist dass in Firefox kann die vergangen JSObject nicht

FB::JSAPIPtr jsAPI = myDoc->getJSAPI(); // THIS WILL RETURN **NULL**. 
m_main_doc = FB::ptr_cast<LcFbViewerDocumentAPI>(jsAPI); // Cast to my document API. 

Dieses Problem geschieht nur durch den Aufruf als JSAPI erkannt werden, wenn der Host-Browser Firefox, IE/Chrome funktioniert gut ist.

Also, was ist mit dem übergebenen JSAPI bei der Verwendung von Firefox passiert?

Antwort

4

Wie sich herausstellt, wickeln die meisten Browser (einschließlich FireFox) NPObjects ein, bevor sie an einen anderen Funktionsaufruf übergeben werden. Aus diesem Grund können Sie die zugrunde liegende C++ - Klasse, die Sie ursprünglich an den Browser übergeben haben, nicht abrufen. Da FireBreath nicht zum echten NPJavascriptObject (dem NPObject, das FireBreath zum Umbrechen von JSAPI-Objekten für den Browser verwendet) gelangt, kann es auch nicht zum ursprünglichen JSAPI-Objekt gelangen.

Sie können eine statische ID für jede Instanz Ihres JSAPI-Objekts erstellen. Sie können dann die instance_id als JSAPI-Eigenschaft verfügbar machen und dann eine globale std :: map erstellen, mit der Sie eine Map speichern können, die Sie an Ihrem Objekt abrufen können.

// in the class def 
static int counter; 
int instance_id; 

// In the .cpp file 
int MyPluginAPI::counter(0); 

std::map<int, FB::JSAPIWeakPtr> apiMap; 
FB::JSAPIPtr getJSAPIObjectById(int id) { 
    std::map<int, FB::JSAPIWeakPtr> fnd = apiMap.find(id); 
    if (fnd != apiMap.end()) { 
     return fnd.second->lock(); // it's a weak pointer, lock to get the shared_ptr 
    } else { 
     return FB::JSAPIPtr(); // Alternately throw an exception 
    } 
} 

MyPluginAPI::MyPluginAPI() { 
    instance_id = counter++; 
    // Note that you can't get at the shared_ptr in the constructor, 
    // so you'll have to call an init function after creating the JSAPI object 

    registerProperty("instance_id", 
       make_property(this, 
        &FBTestPluginAPI::get_instId)); 
} 

int MyPluginAPI::get_instId() { return instance_id; } 

void MyPluginAPI::init() { 
    apiMap[instance_id] = shared_from_this(); 
} 

Dies würde schließlich natürlich eine geringe Menge an Speicher verlieren, wenn Sie die Karte nicht immer gehen durch und abgelaufene schwach PTRs räumen, aber es sollte Sie geben, was Sie brauchen. Wenn Sie ein Objekt erhalten, das ein JSAPIPtr-Objekt sein soll, können Sie es als JSObjectPtr erwarten.

void doSomethingWithAnAPI(const FB::JSObjectPtr& obj) { 
    if (obj) { 
     int id = obj->GetProperty("instance_id"); 
     FB::JSAPIPtr ptr = getJSAPIObjectById(id); 
     if (ptr) { 
      // Hurray! We have the object 
     } 
    } 
} 

Ich habe den obigen Code nicht getestet, aber es sollte ziemlich nah sein.

+1

Danke Taxilian, das ist genau das, was ich brauche. –

+1

Übrigens, Firebreath ist wirklich ein großartiger Rahmen, der mich auf die Funktionsentwicklung anstatt auf pluginspezifische Dinge beschränkt. –