转自: http://huandu.me/2010/02/11/595/

Firefox插件可实现强大功能,但其中麻烦事情不少。写这个实用指南首先是为了方便自己记忆,免得以后再次栽倒一些坑里面,如果能帮助其他人,则是更好。这个指南不是为了手把手教读者开发插件,而是作为一个FAQ,解决各种诡异问题

Firefox拥有众多的扩展(Extension),开发扩展也非常容易,不过有一些事情还是无法用扩展解决,需要访问操作系统的底层功能,这就需要写插件(plugins)。例如flash就是一个插件而不是扩展。

Mozilla提供了一系列的教程和文档,虽然很不详尽,众多重要的API语焉不详,但至少是一个好的开始。

最需要阅读的是plugins API和使用入门。这是一个相当长的文档,如果看完所有的内容会花费大量的时间而且还会很晕,这里列一些重点供参考。

完成以上这些内容以后差不多就已经可以实现自己的插件了,一般而言,参照着例子来做开发不会有什么问题,只是有不少细节需要留意。

Firefox plugins开发的众多奇怪的约定(假设plugins已经被正确安装)

有些约定非常奇怪,不要问我为什么,天晓得开发firefox的牛人们怎么想的。

在Windows下,plugins必须满足以下条件才能被firefox检测到:

  • 插件的名字必须是np*.dll,也就是必须以np开头,.dll结尾
  • 插件dll资源的语言必须为LANG_ENGLISH,code page必须为1252。在rc文件里是这么写的:

    LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
    #pragma code_page(1252)
  • 插件dll的VERSION_INFO里面必须包含以下值:

    VALUE "MIMEType", "application/x-your-mimetype"

    这个MIME就是<object>标签引用插件的唯一凭证。

在Linux下,plugins必须满足以下条件才能被检测到:

  • 插件的名字必须是lib*plugin.so,即以lib开头,plugin.so结尾
  • 插件必须实现NP_GetMIMEDescription和NP_GetPluginVersion,并返回合适MIME字符串。注意,这个字符串并不是普通的MIME,是有特殊规则的,详见前面这个链接的内容。
  • 插件so不要静态链接gtk、opensll、pthread、z等系统库,这会在不同linux平台上因为符号表的问题遇到各种运行时错误

特别需要说明的是,NP_GetPluginVersion、NP_GetEntryPoints等关键函数没有任何官方文档介绍它们,只能根据例子来猜,反正没事就别改它们的实现,copy例子中的代码就好。

firefox插件开发注意事项

写firefox插件的一个基本习惯是,经常编译代码并运行它,保证你的插件还能工作。只要firefox无法加载dll/so,或者加载出现任何错误,都会悄无声息的忽略这个插件。时常关注一下about:plugins,看看插件是不是还在这个列表里。

firefox插件从窗口模式上可分为windowlesswindowed两种。其中,windowless模式的文档较多较全,是firefox比较推荐的模式,坑比较少,这里就不多说了。windowed模式则相反,需要好好说说。

无论在Windows还是Linux上,windowed的插件都拥有独立于浏览器页面的窗口。firefox会通过插件的NPP_SetWindow来告诉插件当前窗口的情况。

关于windowed插件有两个诡异问题需要注意:

  • Windows平台下,插件窗口默认会响应WM_CTLCOLOREDIT、WM_CTLCOLORLISTBOX、
    WM_CTLCOLORBTN、WM_CTLCOLORSTATIC消息,并设置一个默认的背景色。这本来没问题,但在Windows
    XP下,这个颜色居然永远是黑色,而不是默认系统背景色(通常是白色)。最好subclass这个窗口并且拦截这些消息,不要让firefox去处理它
    们。对于插件来说,firefox处理这些消息只是帮倒忙而已。至于firefox还帮了哪些倒忙,可以去源码widget/src/windows
    /nsWindows.cpp的nsWindow::ProcessMessage()去围观。
  • Linux平台下,NPP_SetWindow传入的NPWindow指针中虽然有一个ws_info成员,这个成员里面也确实有一个display变量指向X Window的Display结构,但绝对不要真正使用它,否则可能会导致firefox直接退出,据说这可能是firefox的一个bug。

测试firefox插件小技巧,测试方面的高手可以无视

测试插件前建议先在firefox里面创建一个新的profile(帐号)。这样可以创造一个最干净的开发环境,避免被其他扩展/插件干扰。

默认的profile名叫default,在命令行里输入firefox -p default就可以使用这个profile。如果只是输入firefox -p,会弹出一个对话框用于选择profile。这个命令在Windows和Linux下都可使用。

无论是哪个平台,调试插件的方法都很类似。

Windows下可以用VC以调试方式启动firefox,载入插件时调试器会自动载入对应的符号,捕捉发生的异常或者设断点都很方便。

Linux下直接用gdb就好,细节应该不用多说。有一点需要注意,系统默认安装的firefox命令(默认放在/usr/bin/firefox)是一个shell脚本,真正的可执行文件名字需要打开这个脚本自行查找。

实现firefox插件的基本功能

firefox为插件提供的接口十分原始,很多功能默认没有实现,下面提供了一些思路和方法。

      • 让插件接受焦点:默认情况下,<object>标签不能获得焦点,必须指定tabindex。
      • 在插件中使用tab键跳到下一个element:没有好办法,必须自己手动将焦点还给浏览器窗口(Linux下不必如此),然后自己用NPN_*系列函数找到应该获得focus的DOM element,然后调用这个element的focus()方法。
      • 隐藏和显示插件:直接设置<object>标签的style.display = “none”即可,但这里有个严重的副作用,firefox会调用插件的NS_PluginShutdown,销毁这个插件。如果不期望造成这种效果,要 么别用这种方式隐藏插件,要么把插件状态保存在js里,再次显示的时候把状态设回去。
      • 触发DOM事件:firefox没有提供任何便利的方法触发DOM事件,要在插件中做到这点,必须自己模拟js触发DOM事件的过程。例如,对于HTML事件,假设self是DOM element,js会这么做。

        evt = document.createEvent("KeyboardEvent");
        evt.initKeyEvent(
        "blur", // in DOMString typeArg,
        false, // in boolean canBubbleArg,
        false); // in boolean cancelableArg,
        self.dispatchEvent(evt);

        对应的C代码就是
void FireHTMLEvent(NPP npp, const string & name)
{
NPVariant result;
NPObject *window;
NPVariant vDoc; NPN_GetValue(npp, NPNVWindowNPObject, &window); // 也许页面已经跳转了……
if (!window) {
return;
} NPIdentifier sDocument = NPN_GetStringIdentifier("document");
NPN_GetProperty(npp, window, sDocument, &vDoc);
NPN_ReleaseObject(window); // evt = document.createEvent("KeyboardEvent");
NPVariant evt;
NPObject* npDoc = NPVARIANT_TO_OBJECT(vDoc);
NPIdentifier createEvent = NPN_GetStringIdentifier("createEvent");
NPVariant eventArgs[];
STRINGZ_TO_NPVARIANT("HTMLEvents", eventArgs[]);
NPN_Invoke(npp, npDoc, createEvent, eventArgs, , &evt);
NPN_ReleaseObject(npDoc); // evt.initKeyEvent(
// "blur", // in DOMString typeArg,
// false, // in boolean canBubbleArg,
// false); // in boolean cancelableArg,
NPObject * npEvt = NPVARIANT_TO_OBJECT(evt);
NPIdentifier initKeyEvent = NPN_GetStringIdentifier("initEvent");
NPVariant initArgs[];
STRINGZ_TO_NPVARIANT(name.c_str(), initArgs[]);
BOOLEAN_TO_NPVARIANT(false, initArgs[]);
BOOLEAN_TO_NPVARIANT(false, initArgs[]);
NPN_Invoke(npp, npEvt, initKeyEvent, initArgs, , &result);
NPN_ReleaseVariantValue(&result); // this.dispatchEvent(evt);
NPObject * self;
NPN_GetValue(npp, NPNVPluginElementNPObject, &self);
NPIdentifier dispatchEvent = NPN_GetStringIdentifier("dispatchEvent");
NPVariant dispatchArgs[];
dispatchArgs[] = evt;
NPN_Invoke(npp, self, dispatchEvent, dispatchArgs, , &result);
NPN_ReleaseVariantValue(&result);
NPN_ReleaseObject(npEvt); NPN_ReleaseObject(self);
}

[转载]Firefox插件(plugins)开发实用指南的更多相关文章

  1. 如何显示Firefox插件(Plugins)的完整路径并删除

    在Firefox里面,插件firefox只提供禁用选项,无法直接卸载. 要卸载插件,可以按照下面的步骤: 1.在地址栏内,输入 about:config,回车:在过滤器那一栏输入 plugin.exp ...

  2. 《软件自动化测试开发-Java和Python测试开发实用指南》出版了

    1.关于书中下载链接的问题:出现404,页面不存在 解答:大小写要区分,l和1不能弄错了 2.关于勘误,出现极个别漏子少字错字 解答:后续版本会改进,目前能理解就好了 ---------------- ...

  3. 使用 ADD-ON SDK 开发 基于 Html JQuery 和 CSS 的 firefox 插件入门教程1: 创建一个简单的 Add-on

    [本文转载自http://sixpoint.me/942/implementing-simple-addon/] 实现一个简单的插件 教程的这个部分带你使用 SDK 来实现, 运行并打包一个插件. 这 ...

  4. Web前端开发实用的Chrome插件

    Web前端开发实用的Chrome插件 越来越多的前端开发人员喜欢在Chrome里开发调试代码,Chrome有许多优秀的插件可以帮助前端开发人员极大的提高工作效率.尤其Chrome本身是可以登录的,登录 ...

  5. Windows 常用工具 & 开发工具 & Chrome插件 & Firefox 插件 & 办公软件

    常用工具 1.FastStone 8.0 2.印象笔记 3.Chrome 4.Beyond Compare 5.Everything 6.有道词典 7.文本编辑软件 EditPlus UltraEdi ...

  6. FireFox 浏览器插件/扩展开发学习

    2014-11-08 内容存档在evernote,笔记名"FireFox 浏览器插件/扩展开发学习"

  7. webdriver实用指南python版本(1)-安装开发环境

    webdriver实用指南是本人编写的系列丛书,包括ruby版.python版和java版.在线版是免费的,之前是放在我的github上,但是很多同学总不记得地址,现在转到我的博客上,方便大家阅读. ...

  8. 【干货】Chrome插件(扩展)开发全攻略(不点进来看看你肯定后悔)

    写在前面 我花了将近一个多月的时间断断续续写下这篇博文,并精心写下完整demo,写博客的辛苦大家懂的,所以转载务必保留出处.本文所有涉及到的大部分代码均在这个demo里面:https://github ...

  9. 【干货】Chrome插件(扩展)开发全攻略

    写在前面 我花了将近一个多月的时间断断续续写下这篇博文,并精心写下完整demo,写博客的辛苦大家懂的,所以转载务必保留出处.本文所有涉及到的大部分代码均在这个demo里面:https://github ...

随机推荐

  1. Redis安装与配置Redis安装与配置

    今天在使用Redis的时候遇到了一些问题,这个问题的解决,发现很多人使用Redis的时候没有一点安全意识.所以又重温了一下Redis,觉得应该写一下Redis的安全和配置. Redis安装与配置Red ...

  2. 【BZOJ3243】【NOI2013】向量内积(矩阵,数论)

    [BZOJ3243][NOI2013]向量内积(矩阵,数论) 题面 BZOJ 题解 这题好神仙. 首先\(60\)分直接是送的.加点随机之类的可以多得点分. 考虑正解. 我们先考虑一下暴力. 我们把\ ...

  3. HikariPool-1 - Connection is not available, request timed out after XXXXms.

    hikaripool-0-连接不可用,请求在30000ms之后超时.意思是池等待30000ms的免费连接,但是您的应用程序没有返回任何连接. 原因一:连接泄漏(在从池中借用之后连接没有关闭).解决方法 ...

  4. [JSOI2008]Blue Mary的战役地图——全网唯一一篇dp题解

    全网唯一一篇dp题解 网上貌似全部都是哈希+二分(反正我是大概baidu了翻了翻)(还有人暴力AC了的..) 哈希还是相对于dp还是比较麻烦的. 而且正确性还有可能被卡(当然这个题不会) 而且还容易写 ...

  5. 改变 jq中 data-id 的值

    if (_this.hasClass('default_btn_is')){ _this.removeClass('default_btn_is'); _this.addClass('default_ ...

  6. OpenCV---图像加载与保存

    一:获取图像的信息 什么是图像: 结构化存储的数据信息 图像属性: -通道数目 -高与宽 -像素数据 -位图深度 import cv2 as cv def get_image_info(image): ...

  7. Jenkins使用教程之创建job

    第一部分:常规设置(general) 1.点击新建,进入新建项目页面 2.输入项目名称,选择构建一个自由风格的软件项目(里面可以自己自由进行配置,使用更加灵活),点击ok 3.项目名称与描述 4.gi ...

  8. gcd的性质+分块 Bzoj 4028

    4028: [HEOI2015]公约数数列 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 865  Solved: 311[Submit][Statu ...

  9. POJ 1113 Wall 凸包 裸

    LINK 题意:给出一个简单几何,问与其边距离长为L的几何图形的周长. 思路:求一个几何图形的最小外接几何,就是求凸包,距离为L相当于再多增加上一个圆的周长(因为只有四个角).看了黑书使用graham ...

  10. IDEA 启动时,报“淇℃伅”的字符

    IDEA 启动时,报“淇℃伅”的字符,如下: 解决办法: 修改tomcat安装目录下的config/logging.properties文件,找到java.util.logging.ConsoleHa ...