2013-03-08 8 views
5

Prima si fa un po 'di storia su quello che sto facendo con Firebreath.Un firebreath JSAPI non verrà riconosciuto in firefox

  1. Sto sviluppando un plug-in visualizzatore di rendering nel browser utilizzando firebreath.
  2. Definisco due tipi MIME nel mio plug-in, uno per il visualizzatore principale e l'altro per la vista in pianta 2D.
  3. In ogni pagina è consentito un solo visualizzatore principale, ma può avere più viste in pianta 2D. E tutti condividono lo stesso documento modello aperto nel visualizzatore principale.
  4. Quindi, dopo aver istanziato la vista in pianta 2D, ho bisogno di passare l'oggetto documento (un JSAPI firebreath) alla vista in pianta 2d.

Quindi, assumere la principale spettatore e piano di vista sono entrambi caricati nominato come 'mainviewer' e 'PlanView', e io attch il documento di pianificare spettatore come sotto,

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

il problema è che in Firefox, il JSObject passato non può essere riconosciuto come un JSAPI chiamando

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

Questo problema si verifica solo quando il browser host è Firefox, IE/Chrome funziona bene.

Quindi, cosa è successo al JSAPI passato quando si utilizza Firefox?

risposta

4

Come risulta, la maggior parte dei browser (incluso FireFox) esegue il wrapping di NPObjects prima di consentire loro di passare a un'altra chiamata di funzione; per questo motivo, non è possibile ottenere la classe C++ sottostante che è stata originariamente trasmessa al browser. Poiché FireBreath non può accedere al vero NPJavascriptObject (il NPObject che FireBreath usa per avvolgere oggetti JSAPI da fornire al browser) non può nemmeno raggiungere l'oggetto JSAPI originale.

Prendere in considerazione la creazione di un ID statico per ogni istanza dell'oggetto JSAPI. È quindi possibile esporre l'istanza_id come una proprietà JSAPI e quindi creare una std :: map globale che è possibile utilizzare per memorizzare una mappa per ottenere il proprio oggetto.

// 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(); 
} 

Ciò, naturalmente, alla fine fuoriuscire una piccola quantità di memoria se non mai passare attraverso la mappa e cancellare le PTR deboli scaduti, ma dovrebbe darvi quello che vi serve. Quando ottieni un oggetto che dovrebbe essere un oggetto JSAPIPtr, puoi aspettarlo come JSObjectPtr.

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 
     } 
    } 
} 

Non ho testato il codice precedente, ma dovrebbe essere piuttosto vicino.

+1

Grazie tassativo, questo è proprio quello di cui ho bisogno. –

+1

Tra l'altro, Firebreath è davvero un ottimo framework che mi permette di sviluppare lo sviluppo di funzioni invece di cose specifiche del plugin. –