使用FireBreath寫瀏覽器插件(二)

二. Firebreath的實際應用

    去年我在給公司開發PC上Widget引擎,這個Widget引擎上面運行WebApp應用,界面和應用邏輯使用HTML+CSS+Javascript實現,而網頁無法實現的功能則由CAR實現(CAR是與COM類似的技術,不過支持反射和AOP編程)。在這個引擎上開發的第一款應用是:類似於91手機助手的Android PC套件,整個PC套件的UI部分全部用HTML+CSS+Javascript實現,沒有使用任何原生的控件(例如button),而JS無法完成的功能(例如獲取聯繫人,安裝apk包)則由CAR實現,然後在js中調用CAR。


    其實擴展js功能,還有一種方法是使用現在網站常用的web service:在程序中實現一個http server,然後在http server中實現JS無法完成的功能,例如PC套件裏面的獲取聯繫人,最後再使用Ajax去調用。但爲什麼不選用這種方法呢?主要是基於如下幾點原因:

1. 管理同步調用非常麻煩

2. js得處理參數轉換

3. webservice除了本進程可以調用外,其他應用可以調用,安全認證比較麻煩

4. http無狀態,長時間執行的操作得用一些特殊方式處理

5.  保持長連接也挺麻煩,回調機制的實現比較難辦

6.  對象的生命週期管理難以與js的垃圾回收同步

7.  與本地UI交互困難。例如由於網頁只能打開特定的對話框,如果應用要打開特定對話框(例如選取文件夾),webservice實現比較麻煩 。

    在我看來,C++裏面的對象對JS而言,就應該和JS裏面的原生對象(例如Date)是一樣的,可以new對象,可以和原來一樣地調用C++對象裏面的方法,可以註冊事件和觸發事件,可以被垃圾回收。基於這個原則,並利用CAR的反射和事件回調機制,可以將CAR實現C++類動態注入到JS引擎中,使得JS可以輕鬆地調用C++對象。舉個例子:

    先寫一個接口描述文件HelloWorld.car:

module
{
    interface IHelloRef {
        test([in] Int32 n, [out] AStringBuf<32> ret);
   }
    //回調函數
    callbacks JHelloRef {
        onTestCallback();
    }

    class CHelloRef {
        interface IHelloRef;
        constructor([in] Int32 abc);
    }
}


    然後用emake編譯HelloWorld.car可以生成相關的.h和.cpp文件,修改cpp文件爲如下:

#include "CHelloRef.h"
#include "_CHelloRef.cpp"
#include <stdio.h>
#include <windows.h>
ECode CHelloRef::test(
    /* [in] */ Int32 n,  * [out] */AStringBuf* ret)
{
    printf("hello world\n");
    //觸發回調
    Callback::onTestCallback();
    ret->Copy("hello world");
    ret->Append(n);
    //睡眠3秒後返回結果
    ::Sleep(3000);
    return NOERROR;
}
ECode CHelloRef::constructor(Int32 abc)
{
    return NOERROR;
}


    在js中可以這麼調用:

var hello = new HelloWorld.CHelloRef(1234);
hello.onTestCallback = function(){
       window.alert('onTestCallback ’);
};
//調用test將觸發onTestCallback,test的執行將耗時3秒以上,js引擎也會“卡死”3秒以上
var ret= hello.test(11);
//ret等於hello world11
alert(ret);
//異步調用,下面的js代碼可以繼續執行,而不至於js引擎卡死,結果返回時調用function
hello.test(32, function(ec, ret){
    //ret等於hello world32
    alert(ret);
});


    最初我是採用在Webkit外殼上注入CAR的方式,但後面想在IE內核上跑應用時發現還得實現一遍注入,因爲瀏覽器之間用的JS引擎接口不一樣。即使是Webkit,也有多個JS引擎,例如V8和SquirrelFish,我不可能每個js引擎都實現一遍。但瀏覽器主要由兩種插件體系:NPAPI(chrome裏面加入了Pepper Plugin API )和ActiveX,一個體系下插件的接口是一致的,因此使用插件方式只需要編寫兩種方式的注入,有了Firebreath之後更簡單,只需要實現一致方式的注入就可以在各個瀏覽器上跑了。下面是在chrome裏面跑pc套件的截圖:


    圖上的url(http://moyang.org/pcwidget/widgets/application/com.kortide.app.pcSuite/jdy.html )裏面運行的是一個測試版,還有一些缺點(例如圖片沒有按需加載,第一次使用需要等待圖片加載完)。IE裏面排版還有點問題(萬惡的CSS瀏覽器兼容),推薦在chrome或firefox裏面運行。有android手機的可以試試,好久沒弄這個了,跑不起來我可不負責^_^。

    雖然插件是一種比較方便的方式,但在手機上通過插件來擴展並不是一種好的方式,而且插件在效率上確實有點損耗,所以應該儘量在瀏覽器外殼或js引擎裏面注入,這樣Webapp運行起來纔有好的用戶體驗。插件將各個js引擎的API進行了統一,有優點也有缺點,屬於一種窮人的解決方案。

好了,閒話講完了,後面將接着介紹如何通過Firebreath寫插件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章