2013-03-08 2 views
5

먼저 Firebreath로 무엇을하고 있는지에 대한 배경 정보를 제공합니다.firebreath JSAPI는 파이어 폭스에서 인식되지 않습니다

  1. firebreath를 사용하여 브라우저에서 렌더링 뷰어 플러그인을 개발 중입니다.
  2. 내 플러그인에서 두 개의 MIME 유형을 정의합니다. 하나는 기본 뷰어 용이고 다른 하나는 2D 평면보기 용입니다.
  3. 각 페이지에서 하나의 기본 뷰어 만 허용되지만 여러 개의 2D 평면 뷰를 가질 수 있습니다. 그리고 그들은 모두 메인 뷰어에서 열리는 동일한 모델 문서를 공유합니다.
  4. 그래서 2D 평면 뷰를 인스턴스화 한 후 문서 객체 (firebreath JSAPI)를 평면 뷰에 전달해야합니다.

그런 다음 모두 'mainviewer'와 'planview'로 명명로드 주 뷰어 및 계획보기를 가정, 나는이 문제가

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

, 아래 뷰어를 도모하기 위해 문서를 attch합니다 파이어 폭스에서, 전달의 JSObject가

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

를 호출하여 JSAPI로 인식 할 수없는 호스트 브라우저가 파이어 폭스, IE/크롬 잘 작동 때이 문제는 발생합니다.

그럼 파이어 폭스를 사용할 때 전달 된 JSAPI는 어떻게 되었을까요?

답변

4

대부분의 브라우저 (FireFox 포함)는 NPObject를 다른 함수 호출로 전달하기 전에 래핑합니다. 이 때문에 원래 브라우저에 전달한 기본 C++ 클래스를 사용할 수 없습니다. FireBreath는 실제 NPJavascriptObject (FireBreath가 브라우저에 제공하기 위해 JSAPI 객체를 래핑하기 위해 사용하는 NPObject)에 도달 할 수 없으므로 원래 JSAPI 객체에도 도달 할 수 없습니다.

JSAPI 객체의 각 인스턴스에 대한 정적 ID를 만드는 것이 좋습니다. 그런 다음 instance_id를 JSAPI 속성으로 노출 한 다음 개체에 도달 할 수 있도록지도를 저장하는 데 사용할 수있는 전역 std :: map을 만들 수 있습니다.

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

적지도를 통해 이동 및 만료 약한 ptrs을 취소하지 않으면 물론 이것은 결국 적은 양의 메모리를 누출 것이다, 그러나 당신이 필요로하는 무엇을 제공해야합니다. JSAPIPtr 객체 여야하는 객체를 얻으면 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 
     } 
    } 
} 

위의 코드는 테스트하지 않았지만 매우 비슷해야합니다.

+1

택시 기사에게 감사합니다. 이것은 내가 필요한 것입니다. –

+1

그건 그렇고, Firebreath는 정말 플러그인을 쓰는 대신에 기능 개발을 할 수있게 해주는 위대한 프레임 워크입니다. –