Android浏览器插件小结(三)

接上一节的内容,但初始化插件以后(NP_Initialize),WebKit将实例化插件,调用

NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
        char* argn[], char* argv[], NPSavedData* saved);

所以上一节提到的NP前缀,我认为可以理解成类函数,而NPP前缀相当于实例函数了,这里的NPP,就可以看成是this指针,或者C里面的叫法Handle了,看NPP的定义

typedef struct _NPP
{
    void*    pdata;            /* plug-in private data */
    void*    ndata;            /* netscape private data */
} NPP_t;

typedef NPP_t*    NPP;

也证实了这一点,对于它就是简单的使用它的pdata来传递参数吧


先来看看NPP_New里面的实现

instance->pdata = browser->createobject (instance, getPluginClass());

其中browser是前面初始化的时候传过来的浏览器接口,利用它来实例化插件,getPluginClass是干嘛的?

这里的getpluginClass返回NPClass指针,其中定义了插件的一系列函数指针(又是函数指针。。。。),下面是一个实现的例子:

static NPClass pluginClass = {
    NP_CLASS_STRUCT_VERSION,
    pluginAllocate,
    pluginDeallocate,
    pluginInvalidate,
    pluginHasMethod,
    pluginInvoke,
    pluginInvokeDefault,
    pluginHasProperty,
    pluginGetProperty,
    pluginSetProperty,
    pluginRemoveProperty,
    pluginEnumerate
};
这些函数指针应该是预先定义好的,顺序,个数都要保证,由于以前开发过相关的这部分内容,我知道这些是浏览器用来操作NPObject的接口,任意一个js对象,调用它的属性或者方法,最终都是调用到对应的NPObject中来的,这样来看,这个NPObject代表了对应的一个js的对象,我们这里就是对应了MIME那个节点


浏览器知道了这个NPObject的接口,就直接利用pluginAllocate建立这个NPObject,回调。。。又是回调,插件的地位很低的,告诉别人怎么样调用自己,但啥时候被调不是自己说了算的


实际中,我们创建了一个PluginObject,这个相当于是插件这边的Handle,里面保存了很多东东:

typedef struct PluginObject {
    NPObject header;
    NPP npp;
    NPWindow* window;

    PluginType pluginType;
    SubPlugin* activePlugin;

} PluginObject;
其中,NPObject,NPP在pluginAllocate中赋值:

static NPObject *pluginAllocate(NPP npp, NPClass *theClass)
{
    PluginObject *newInstance = (PluginObject*) malloc(sizeof(PluginObject));
    newInstance->header._class = theClass;
    newInstance->header.referenceCount = 1;

    if (!identifiersInitialized) {
        identifiersInitialized = true;
        initializeIdentifiers();
    }

    newInstance->npp = npp;

    return &newInstance->header;
}

这里可以看到,NPObject就是NPClass的封装,代表了js的对象本质就是一组函数


NPWindow在哪里赋值的?还记得NPP_SetWindow吧,这个应该是在插件视图创建好以后调用的


嗯,还没有完,继续NPP_New,看看这3个参数

int16 argc,char* argn[], char* argv[]
类似main函数的参数,argn和argv分别代表节点的属性名和属性值,我对HTML不是很熟,不知道是不是叫这个,还是对照测试用的HTML文件来解释好一些:

<object type="application/x-testbrowserplugin" height=200 width=400 id="sample">
<param name="DrawingModel" value="Surface" />
<param name="PluginType" value="Paint" />
</object>
OK,这里的argc == 2,argn[0] == "DrawingModel",argn[1] == "Surface",这样大家应该就明白了

浏览器通过HTML中插件的参数,调用NPP_New初始化插件,得到SubPlugin和PluginType


这里的SubPlugin代表真正的插件实例的接口,定义如下:

class SubPlugin {
public:
    SubPlugin(NPP inst) : m_inst(inst) {}
    virtual ~SubPlugin() {}
    virtual int16 handleEvent(const ANPEvent* evt) = 0;
    virtual bool supportsDrawingModel(ANPDrawingModel) = 0;

    int getPluginWidth();
    int getPluginHeight();

    NPP inst() const { return m_inst; }

private:
    NPP m_inst;
};

class SurfaceSubPlugin : public SubPlugin {
public:
    SurfaceSubPlugin(NPP inst) : SubPlugin(inst) { m_context = NULL; }
    virtual ~SurfaceSubPlugin() {}
    virtual jobject getSurface() = 0;
    virtual bool supportsDrawingModel(ANPDrawingModel);

    void setContext(jobject context);

    jobject m_context;
};
SubPlugin,提供处理事件接口,SurfaceSubPlugin继承SubPlugin,增加了Context,用作jni相关的调用


实际中,我们继承SurfaceSubPlugin,实现这些纯虚函数,创建我们自己的插件,而HandleEvent的事件就是前面讲到了的在NPP_HandleEvent中传入的


OK,到现在为止,初始化的工作做完了,基本的调用逻辑,框架也搭好了,可以开始具体的插件实现了






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值