瀏覽器和js交互、NPAPI之NPRuntime開發

NPAPI 原本是由 Netscape 所制定的一組單純的 C Plugin API,起初是無法支持 Scriptability;於是到了 2004 年底,各家 Browser ( IE , Opera, Mozilla 等) 都同意支持NPRuntime 延伸 API 以支持 Scriptability,所以目前若是想寫 Plugin則應該以 NPRuntime API 才能跨不同的 Browsers。
先介紹下瀏覽器的生命週期。
這裏寫圖片描述
1.瀏覽器搜索加載DLL文件。

2.瀏覽器調用NP_GetEntryPoints, NP_Initialize()來初始化瀏覽器和插件的函數映射表。

i.調用瀏覽器端的 NP_Initialize,將函數傳給插件的函數表。

ii.插件將定義好的函數通過NP_GetEntryPoints,傳遞到NPPluginFuncs中,讓瀏覽器可以調用。

3.瀏覽器調用插件的NPP_GetValue,得到插件的對象,若支持js交互,則通過NPPVpluginScriptableNPObject來判斷創建m_pScriptableObject對象。

4.瀏覽器通過HTML中的MIMTYPE,調用插件的NP_New來創建插件實例。然後對插件進行業務處理。

5.瀏覽器關閉頁面時,調用插件的NPP_Destory來銷燬插件實例。

6.瀏覽器關閉時,調用NP_shutdown關閉所有的資源。

以上就是瀏覽器插件的生命週期。

下面來看下NPRuntime的執行過程。

瀏覽器調用插件的方法的順序,基本上爲: NP_GetEntryPoints 、 NP_Initialize 、 NPP_New 、 NPP_SetWindow 、 NPP_GetValue 。在 NPP_New 中,我們需要創建插件對象的實例, NPP_SetWindow 中,瀏覽器會傳入插件窗口的信息,最後一個 NPP_GetValue ,是瀏覽器來獲取一些插件信息的。 NPP_GetValue 函數的結構是這樣的:

NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value);

· instance 包含着插件對象實例;

· variable 表示瀏覽器要獲取的信息的類型 ;

· value 表示返回給瀏覽器的值

i.瀏覽器會傳入NPPVpluginScriptableNPObject(作爲variable參數)來查詢插件是否支持Scriptable功能(即和腳本語言交互的功能)

ii.可以利用NPN_CreateObject方法來創建一個NPObject對象,並且作爲value返回給瀏覽器。

iii.瀏覽器就通過這個NPObject對象和我們的插件建立了連接。

V.當頁面上Javascript調用了我們插件對象的某個方法時,瀏覽器會調用該NPObject對象的HasMethod方法來查詢是否支持這個方法,

VI.如果支持,則會調用NPObject對象的Invoke方法,傳入方法名、參數等信息。

VII.這樣,我們就可以讓網頁上的腳本語言來執行我們編寫的函數了。

VIII.在Windows上,我們編寫的函數就如同編寫普通的應用程序一樣,可以使用很多Windows API來完成許多複雜的工作。

如下圖。
這裏寫圖片描述

其中NPRuntime插件對象如下圖:
這裏寫圖片描述
插件和js交互時,js調用插件的屬性和方法,調用getProperty,hasMethod,invoke方法即可。

如何定義一個方法(或屬性)?
1、添加一個方法(或屬性)很簡單,先定義一個靜態NPIdentifier類型的變量,例如:

static NPIdentifier s_idSetArgs;

2、在插件對象構造函數中,使用NPN_GetStringIdentifier方法來設置該方法的名稱,例如:

s_idSetArgs = NPN_GetStringIdentifier(“SetArgs”);

其中,SetArgs就是我們提供給腳本語言調用的方法名稱。

3、在ScriptablePluginObject的HasMethod方法中,判斷傳入的方法名:

bool ScriptablePluginObject::HasMethod(NPIdentifier name)
{
    char *pProp = NPN_UTF8FromIdentifier(name);
  //Check which Properties are available
    if( !strcmp( "Add", pProp ) )
    {
    return true;
    }
    if(name == s_idSetArgs)
    {
        printf("method name = SetArgs\n");
        return true;
    }
    return false;
}

4.在Plugin的Invoke方法中,判斷如果傳入的方法名稱等於我們定義的方法名,則做你想要做得事情:

bool
ScriptablePluginObject::Invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result)
{
  //kk  
  char *pFunc = NPN_UTF8FromIdentifier(name);

  if( !strcmp( "Add", pFunc ) )
  {
    int sum = 0;

    for( unsigned int i = 0; i < argCount; i++ )
    {
      if( args[i].type == NPVariantType_Int32 )
      {
        sum += args[i].value.intValue;
      }
      else if( args[i].type == NPVariantType_String )
      {
        CNPString s(args[i].value.stringValue);
        sum += atoi( s );
      }
      else 
        return false;//an error happenend

    }
    //value for GUI output
    sprintf( m_szTextGui, "Sum = %ld", sum );
    //triggering
    ::InvalidateRect( m_hWnd, 0, true );
    //nice and handy little helpers, there are more of it 
    INT32_TO_NPVARIANT( sum,*result);
    return true;
  }
        return false;
}

在HTML中調用方法如下。

<embed type="application/npruntime" width=600 height=200 id="plugin">

JS調用Add方法如下:

function Add()
{
  try
  { 
    //if( CheckBrowser() ) return;
    var a1 = document.getElementById("f1").value;
    var a2 = document.getElementById("f2").value;
    alert("test");
    var res = PLUGIN.Add(a1,a2);//we can also add numbers and strings (because of the plugin implementation)
    alert( "Plugin Added result is: " + res );
  }
  catch (err) { alert(err); }
}

這裏就可以JS和瀏覽器插件進行交互了。

轉自:http://www.tuicool.com/articles/uERf6ja

發佈了14 篇原創文章 · 獲贊 4 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章