插件主要用于HTML页面中增强HTML页面可以支持的资源类型,在HTML页面中最重要的一个特性就是可以利用脚本语言来实现与用户的交互,之前的文章也提及过相关的议题,不过在交流过程中还是发现好多开发者对于这个主题有不太明白的地方,这里再次详细介绍一下在插件中如何与JS进行交互。
那么浏览器是如何完成将插件转换为JS能够识别的对象的呢?我们发现,在NPP_GetValue的实现中有:
也就是说,浏览器会调用NPP_GetValue (instance, NPPVpluginScriptableNPObject, value)并将来获取插件的scriptable对象。进一步看看plugin是如何获取scriptable对象的:
对象存在时用NPN_RetainObject来获取对象,对象不存在时用NPN_CreateObject来创建一个对象。
当我们在JS中设置/获取属性或者调用方法时,都会在这个scriptable对象中操作,在使用结束时(CPlugin的析构函数中)使用NPN_ReleaseObject(m_pScriptableObject);来释放这个对象。
简单解释一下对象是如何创建的(一般情况下我们可以不知道,只需要按照demo中的代码使用就可以了,如果只想知道如何实现与JS的交互请跳至下一部分),看看MDN上相关说明:
本文的例子代码可以下载:无boost需安装CMake、原来的scriptable demo。
插件对象
可以在JS中使用document.getElementsByTagName或者document.getElementById来获取页面中已经存在的插件对象,还可以在JS中使用document.createElement("object");来动态创建对象,并为该对象设置type属性,接着将创建的这个对象添加到页面中,这样就动态创建了一个插件对象。如下JS函数可以根据传入的mimetype创建一个插件对象(chrome、firefox测试有效,其他未测试):function newNPObject(mimetype)
{
var obj = document.createElement("object");
obj.type = mimetype;
document.body.appendChild(obj);
return obj;
}
那么浏览器是如何完成将插件转换为JS能够识别的对象的呢?我们发现,在NPP_GetValue的实现中有:
if (variable==NPPVpluginScriptableNPObject)
{
*(NPObject **)value = plugin->GetScriptableObject();
}
也就是说,浏览器会调用NPP_GetValue (instance, NPPVpluginScriptableNPObject, value)并将来获取插件的scriptable对象。进一步看看plugin是如何获取scriptable对象的:
NPObject* CPlugin::GetScriptableObject()
{
if (!m_pScriptableObject) {
m_pScriptableObject = NPN_CreateObject(m_pNPInstance, &CScriptObject::nsScriptObjectClass);
}
if (m_pScriptableObject) {
NPN_RetainObject(m_pScriptableObject);
}
return m_pScriptableObject;
}
对象存在时用NPN_RetainObject来获取对象,对象不存在时用NPN_CreateObject来创建一个对象。
当我们在JS中设置/获取属性或者调用方法时,都会在这个scriptable对象中操作,在使用结束时(CPlugin的析构函数中)使用NPN_ReleaseObject(m_pScriptableObject);来释放这个对象。
简单解释一下对象是如何创建的(一般情况下我们可以不知道,只需要按照demo中的代码使用就可以了,如果只想知道如何实现与JS的交互请跳至下一部分),看看MDN上相关说明:
NPObject *NPN_CreateObject(NPP npp, NPClass *aClass);
The function has the following parameters:
npp
The NPP indicating which plugin wants to instantiate the object.
aClass
The class to instantiate an object of.
第一个参数很好搞定,第二个参数比较费解,创建时传入的&CScriptObject::nsScriptObjectClass实际上是基类nsScriptObjectBase的NPClass变量,结合说明可以知道,NPN_CreateObject是根据所传入的NPClass类创建一个NPObject并返回这个对象的指针。NPN_CreateObject中调用NPClass类的NPAllocateFunctionPtr成员来为NPObject分配内存,看到NPClass的NPAllocateFunctionPtr成员是nsScriptObjectBase::_Allocate函数,该函数则是调用nsScriptObjectBase::AllocateScriptPluginObject来实现的,AllocateScriptPluginObject的实现在Plugincpp中,可以看到其实现代码就是return (NPObject*)new CScriptObject(npp);也就是创建一个新的CScriptObject对象,这里绕过来绕过去这