文档章节

基于NPAPI接口的windows平台安全控件开发(二)

季牧云
 季牧云
发布于 2015/03/20 15:41
字数 1354
阅读 125
收藏 1

    通过前一篇博客,已经实现了基本的功能和图形界面  。本篇主要介绍如何实现插件与JS交互。交互功能主要是通过NPObject对象来实现的。

   上面提到我们重写了NPP_GetValue函数,使NPP_GetValue去调用CPlugin中的GetScriptObject,而不是按默认流程调用GetValue(其实无所谓,改个名称而已)。所以,当插件加载完成后,浏览器会调用NPP_GetValue并将variable参数设置为NPPVpluginScriptableNPObject来查询浏览器是否支持与脚本语言的交互功能,如果插件支持交互功能,则NPP_GetValue会返回一个NPOject对象给浏览器,此时浏览器就可以通过这个NPObject对象与插件建立联系。所以在CPlugin::GetScriptObject函数中,我们要实现NPObject对象。实现如下:

NPObject *CPlugin::GetScriptableObject()
{
    if (!m_pScriptableObject) {  
    m_pScriptableObject = NPN_CreateObject(m_pNPInstance,GET_NPOBJECT_CLASS(CScriptObject));
    }  
    if (m_pScriptableObject) {  
    NPN_RetainObject(m_pScriptableObject);  
    }  
    return m_pScriptableObject; 
}

当存在NPObject对象时,直接使用NPN_RetainObject获取并返回。若不存在NPObject对象时,使用NPN_CreateObject创建一个NPObject对象。GET_NPOBJECT_CLASS宏定义如下:

#define DECLARE_NPOBJECT_CLASS_WITH_BASE(_class, ctor)                        \
static NPClass s##_class##_NPClass = {                                        \
NP_CLASS_STRUCT_VERSION_CTOR,                                             \
ctor,                                                                       \
ScriptablePluginObjectBase::_deallocate,                                    \
ScriptablePluginObjectBase::_invalidate,                                    \
ScriptablePluginObjectBase::_hasMethod,                                     \
ScriptablePluginObjectBase::_invoke,                                        \
ScriptablePluginObjectBase::_invokeDefault,                                 \
ScriptablePluginObjectBase::_hasProperty,                                   \
ScriptablePluginObjectBase::_getProperty,                                   \
ScriptablePluginObjectBase::_setProperty,                                   \
ScriptablePluginObjectBase::_removeProperty,                                \
ScriptablePluginObjectBase::_enumerate,                                     \
ScriptablePluginObjectBase::_construct                                      \
}

宏中的ScriptablePluginObjectBase定义如下:

class ScriptablePluginObjectBase : public NPObject
{
public:
ScriptablePluginObjectBase(NPP npp)
: mNpp(npp)
{
}
virtual ~ScriptablePluginObjectBase()
{
}
// Virtual NPObject hooks called through this base class. Override
// as you see fit.
//virtual NPObject *allocate(NPP npp, NPClass *aClass){}
virtual void invalidate();
virtual bool hasMethod(NPIdentifier name);
virtual bool invoke(NPIdentifier name, const NPVariant *args,uint32_t argCount, NPVariant *result);
virtual bool invokeDefault(const NPVariant *args, uint32_t argCount,NPVariant *result);
virtual bool hasProperty(NPIdentifier name);
virtual bool getProperty(NPIdentifier name, NPVariant *result);
virtual bool setProperty(NPIdentifier name, const NPVariant *value);
virtual bool removeProperty(NPIdentifier name);
virtual bool enumerate(NPIdentifier **identifier, uint32_t *count);
virtual bool construct(const NPVariant *args, uint32_t argCount,NPVariant *result);
public:
static NPObject *_allocate(NPP npp, NPClass *aClass);
static void _deallocate(NPObject *npobj);
static void _invalidate(NPObject *npobj);
static bool _hasMethod(NPObject *npobj, NPIdentifier name);
static bool _invoke(NPObject *npobj, NPIdentifier name,const NPVariant *args, uint32_t argCount,NPVariant *result);
static bool _invokeDefault(NPObject *npobj, const NPVariant *args,uint32_t argCount, NPVariant *result);
static bool _hasProperty(NPObject * npobj, NPIdentifier name);
static bool _getProperty(NPObject *npobj, NPIdentifier name,NPVariant *result);
static bool _setProperty(NPObject *npobj, NPIdentifier name,const NPVariant *value);
static bool _removeProperty(NPObject *npobj, NPIdentifier name);
static bool _enumerate(NPObject *npobj, NPIdentifier **identifier,uint32_t *count);
static bool _construct(NPObject *npobj, const NPVariant *args,uint32_t argCount, NPVariant *result);
static NPObject *AllocateCScriptObject(NPP npp, NPClass *aClass);
protected:
NPP mNpp;
};

该类需要继承自NPObject,因为插件需要给浏览器返回一个NPObject对象。随后再定一个类CScriptObject。

class CScriptObject:
public ScriptablePluginObjectBase
{
public:
NPUTF8 *utf8_chars1,*utf8_chars2,*utf8_chars3,*utf8_chars4;//缓冲区
static NPObject *sWindowObj;
static NPIdentifier s_idGetPasswd;
static NPIdentifier s_idGetMacAddress;
static NPIdentifier s_idGetHardwareInfo;
static NPIdentifier s_idSetEditSize;
static NPIdentifier s_idGetVersion;
//int result_size;
//NPString str1;
//NPUTF8 utf8_chars1[INVOKE_STRING_LENGTH];
CScriptObject(NPP npp);
~CScriptObject();
virtual bool hasProperty(NPIdentifier name);
virtual bool hasMethod(NPIdentifier name);
virtual bool getProperty(NPIdentifier name, NPVariant *result);
virtual bool setProperty(NPIdentifier name, const NPVariant *value);
virtual bool invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);
virtual bool invokeDefault(const NPVariant *args, uint32_t argCount, NPVariant *result);
virtual bool enumerate(NPIdentifier **identifier, uint32_t *count);
virtual bool construct(const NPVariant *args, uint32_t argCount,NPVariant *result);
};

CScriptObject对象继承ScriptablePluginObjectBase类,随后就是实现CScriptObject中的虚函数,以下为部分实现:

CScriptObject::CScriptObject(NPP npp):ScriptablePluginObjectBase(npp)
{
    s_idGetPasswd = NPN_GetStringIdentifier("GetPasswd");
    s_idGetMacAddress = NPN_GetStringIdentifier("GetMacAddress");
    s_idGetHardwareInfo = NPN_GetStringIdentifier("GetHardwareInfo");
    s_idSetEditSize = NPN_GetStringIdentifier("SetEditSize");
    s_idGetVersion = NPN_GetStringIdentifier("GetVersion");
    utf8_chars1 = static_cast<NPUTF8 *>(NPN_MemAlloc(INVOKE_STRING_LENGTH));
    utf8_chars2 = static_cast<NPUTF8 *>(NPN_MemAlloc(INVOKE_STRING_LENGTH));
    utf8_chars3 = static_cast<NPUTF8 *>(NPN_MemAlloc(INVOKE_STRING_LENGTH));
    utf8_chars4 = static_cast<NPUTF8 *>(NPN_MemAlloc(INVOKE_STRING_LENGTH));
}
CScriptObject::~CScriptObject()
{
    //NPN_MemAlloc分配的内存不需要手动释放,浏览器会自动释放
    //NPN_MemFree(utf8_chars1);
    //NPN_MemFree(utf8_chars2);
    //NPN_MemFree(utf8_chars3);
    //MessageBox(NULL,"CScriptobject delete","Plugin GetMacAddress",MB_ICONERROR|MB_OK);
}
bool CScriptObject::hasMethod(NPIdentifier name)
{
    //MessageBox(NULL,"HashMethod Successful","HashMethod",MB_ICONERROR|MB_OK);
    return  name == s_idGetPasswd || name == s_idGetMacAddress || name == s_idGetHardwareInfo || name == s_idSetEditSize || name == s_idGetVersion;
}
bool CScriptObject::hasProperty(NPIdentifier name)
{
    //return name == s_idSetEditSize;
    return false;
}
bool CScriptObject::getProperty(NPIdentifier name, NPVariant *result)
{
    return false;
}
bool CScriptObject::setProperty(NPIdentifier name, const NPVariant *value)
{
    return false;
}
bool CScriptObject::invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result)
{
    char *tmp;
    CPlugin* plugin = (CPlugin*) mNpp->pdata;
    if (name == s_idGetPasswd)
    {
        tmp = plugin->myedit->GetVal();
        //*result = NPVARIANT_TO_STRING(tmp);
        memset(utf8_chars1,'\0',INVOKE_STRING_LENGTH);
        strcpy(utf8_chars1,tmp);
        //STRINGZ_TO_NPVARIANT(utf8_chars1,*result);
        //INT32_TO_NPVARIANT(10,*result);
        result->type = NPVariantType_String;
        NPString  str1 = {utf8_chars1, uint32_t(strlen(utf8_chars1)) };
        //str1.UTF8Characters = utf8_chars1;
        //str1.UTF8Length = uint32_t(strlen(utf8_chars1));
        result->value.stringValue = str1;
        return true;
    }
    if(name == s_idGetMacAddress){
        tmp = plugin->myedit->GetMacAddress();
        memset(utf8_chars2,'\0',INVOKE_STRING_LENGTH);
        strcpy(utf8_chars2,tmp);
        //STRINGZ_TO_NPVARIANT(utf8_chars2,*result);
        result->type = NPVariantType_String;
        NPString str2 = { utf8_chars2, uint32_t(strlen(utf8_chars2)) };
        result->value.stringValue = str2;
        return true;
    }
    if(name == s_idGetHardwareInfo){
        tmp = plugin->myedit->GetHardwareInfo();
        memset(utf8_chars3,'\0',INVOKE_STRING_LENGTH);
        strcpy(utf8_chars3,tmp);
        //STRINGZ_TO_NPVARIANT(utf8_chars3,*result);
        result->type = NPVariantType_String;
        NPString str3 = { utf8_chars3, uint32_t(strlen(utf8_chars3)) };
        result->value.stringValue = str3;
        return true;
    }
    if(name == s_idSetEditSize){
        //plugin->myedit->SetEditSize();
        if(args[0].type == NPVariantType_Int32 && args[1].type == NPVariantType_Int32){
            plugin->myedit->SetEditSize(NPVARIANT_TO_INT32(args[0]),NPVARIANT_TO_INT32(args[1]));
        }else if (args[0].type == NPVariantType_Double && args[1].type == NPVariantType_Double){
            plugin->myedit->SetEditSize((int)NPVARIANT_TO_DOUBLE(args[0]),(int)NPVARIANT_TO_DOUBLE(args[1]));
        }
        //INT32_TO_NPVARIANT(result_size,*result);
        return true;
}
    if(name == s_idGetVersion){
        tmp = plugin->myedit->GetVersion();
        memset(utf8_chars4,'\0',INVOKE_STRING_LENGTH);
        strcpy(utf8_chars4,tmp);
        result->type = NPVariantType_String;
        NPString str4 = { utf8_chars4, uint32_t(strlen(utf8_chars4)) };
        result->value.stringValue = str4;
        return true;
    }
    return false;
}

其中最主要的是hasMethod和invoke两个函数。当浏览器中JS调用某个插件函数A时,浏览器会通过NPObject调用hasMethod函数,以判断插件是否提供函数A的调用,若插件存在函数A(即hasMethod返回true),随后浏览器将调用invoke函数。故,在hasMethod函数中,我们将插件对外提供的函数在此处列出。

return  name == s_idGetPasswd || name == s_idGetMacAddress || name == s_idGetHardwareInfo || name == s_idSetEditSize || name == s_idGetVersion;

其中s_idGetPasswd等变量在CScriptObject进行了相应的初始化,以关联具体函数名。

CScriptObject::CScriptObject(NPP npp):ScriptablePluginObjectBase(npp)
{
    s_idGetPasswd = NPN_GetStringIdentifier("GetPasswd");
    s_idGetMacAddress = NPN_GetStringIdentifier("GetMacAddress");
    s_idGetHardwareInfo = NPN_GetStringIdentifier("GetHardwareInfo");
    s_idSetEditSize = NPN_GetStringIdentifier("SetEditSize");
    s_idGetVersion = NPN_GetStringIdentifier("GetVersion");
    ........
}

当通过hasMethod返回true之后,浏览器讲会调用invoke函数,在invoke函数中,通过判断name参数,确定浏览器需要具体调用插件中的哪个函数,随后调用该函数即可,具体可参照invoke实现代码。插件提供的各种函数在CYKedit中详细定义。

© 著作权归作者所有

季牧云
粉丝 20
博文 25
码字总数 18661
作品 0
浦东
其他
私信 提问
加载中

评论(1)

W
Waikell
写的很好,望楼主继续,最核心的还没有出现2
Adobe Flash Player - imsoft.cnblogs

Adobe Flash Player是一个跨平台、基于浏览器的应用程序。运行时,它可以跨屏幕和浏览器原汁原味地查看具有表现力的应用程序、内容和视频。Flash Player实现了移动屏幕上的高性能优化,设计为...

imzdx
2015/01/15
0
0
EasyPlayer windows RTSP播放器OCX插件使用说明

鉴于大家对于EasyPlayer插件的使用还不太熟悉,特此写一篇插件的使用文档,供大家参考;EasyPlayer插件有两种,一种是基于IE的ActiveX控件,一种是基于FireFox(也支持多浏览器)的npAPI插件...

xiejiashu
2017/12/11
0
0
精简小巧的 Chromium 内核控件 - miniblink

miniblink是一款精简小巧的浏览器控件,基于chromium精简而成,是市面上最小巧的chromium内核控件没有之一。 它仅10余M大小,只需一个dll,几个纯C接口即可轻松调起,并嵌入到任何软件内使用...

龙泉寺扫地僧
2019/02/13
1.2W
24
Flash Player 24 For Linux

2012年 Adobe 决定停止更新 Linux 平台上的 NPAPI 版 Flash 播放器,以后只提供安全更新。在四年时间里 Linux 版的 Flash 播放器版本号一直停留在 11.2。但在今年8月,Adobe 改变了这一决定,...

linux小陶
2016/12/28
15
0
Adobe 发布 Linux 下的 Flash Player 24

2012 年 Adobe 决定停止更新 Linux 平台上的 NPAPI 版 Flash 播放器,以后只提供安全更新。在四年时间里 Linux 版的 Flash 播放器版本号一直停留在 11.2。但在今年8月,Adobe 改变了这一决定...

局长
2016/12/20
4.4K
27

没有更多内容

加载失败,请刷新页面

加载更多

“>”(大于号)CSS选择器是什么意思?

例如: div > p.some_class { /* Some declarations */} >符号到底是什么意思? #1楼 html <div> <p class="some_class">lohrem text (it will be of red color )</p> <div> <p class="......

javail
33分钟前
47
0
mysql中int(11)的列大小是多少?

mysql中int(11)的列大小是多少? 以及可以在此列中存储的最大值? #1楼 mysql中int(11)的列大小是多少? (11) int数据类型的此属性与列的大小无关。 它只是整数数据类型的显示宽度。 从11....

技术盛宴
今天
40
0
聊聊artemis消息的推拉模式

序 本文主要研究一下artemis消息的推拉模式 拉模式 receive activemq-artemis-2.11.0/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQMessageConsumer.......

go4it
今天
73
0
vue 全局前置守卫引起死循环的原因与解决方法

我们经常会用到全局前置守卫,如判断用户有没有登陆过,如果登陆过就直接跳到目的页面,如果没有登陆过,就跳转到登陆页。 先看官网对全局前置守卫的介绍 使用 router.beforeEach 注册一个全...

tianyawhl
今天
39
0
使用生成器模拟时间分片

对于cpu密集型任务, 时间分片可以有效减少页面卡顿, 不过对于纯计算型任务还是推荐使用worker在后台做计算 效果图, 计算密集型任务被分到每次只执行16ms, 每次执行完毕留给浏览器时间去响应事...

阿豪boy
今天
65
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部