如何做到1个月内快速开发并发布易信web版截屏插件

勿忘初心2018-10-26 10:05

此文已由作者严跃杰授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。


需求分析

主要参考微信网页版

和网易邮箱插件

考虑到操作方便性,保留截图窗口右下角的鼠标操作按钮,暂不开发画图和文字功能。

 

分析插件需要完成主要工作如下

1、  鼠标点击网页截屏按钮,网页调用插件开放js接口生成全屏窗口覆盖整个桌面,窗口背景为暗色的原桌面图片。

2、  鼠标在窗口任意位置按下左键拖动,在窗口上绘制一块亮色的选择区块。

3、  鼠标左键抬起后,右下角出现按钮框或者更改左上角提示。

4、  鼠标左键选中选择区块后,可拖动该区块;鼠标选中区块边缘后拖动可更改区块大小。

5、  鼠标双击该区块或按右下角确定按钮后生成区块的内存位图。

6、  将该内存位图转换为png图片。

7、  将改png图片通过https接口上传,并获取远端可访问地址。

8、  通过回调接口通知web页面该图片地址

  

选择合适的框架

网易邮箱插件使用的是gears框架

框架大而全较为复杂,学习成本高。

google已经停止对gears的开发

 

firebreath是一个专门的插件框架

domo和文档较全,学习成本相对较低。

通过firebreath主页的文档

http://www.firebreath.org/display/documentation/FireBreath+Home

可以快速掌握如何创建一个插件,包括项目创建,编译生成,部署及测试。

 

找到合适资源并进行修改及裁剪

1.       截屏实现原理比较简单,但是从头写还是比较费时间的。从网上找到一个带源码的截屏应用http://www.cppblog.com/shly/archive/2011/10/07/157704.html, 运行起来后是这样的, 初步能满足要求。

我们对代码稍作修改,并打包成静态库,以便调用。

2.       Bmp转png功能,需要libpng,zlib,boost(firebreath内有),引用了邮箱助手内转换代码。

3.       https图片上传。

基于libcurl实现https上传,但是libcurl默认是不支持ssl,因此先后编译openssl和libcurl,使其支持https。

编译openssl生成静态库libeay32.lib, ssleay32.lib,参考

http://blog.163.com/xiaoting_hu/blog/static/50464772201310415042524/

编译libcurl生成静态库libcurl.lib, 参考

http://blog.csdn.net/haiyan_qi/article/details/23608037

注意编译libcurl时要在预处理器定义中加入

BUILDING_LIBCURL

USE_OPENSSL

USE_SSLEAY

 

最后创建一个上传文件的项目,并按照libcurl文档说明完成上传功能开发,最后打包成静态库以便调用。注意因为该项目要引用libcurl静态库,预处理器定义中加入CURL_STATICLIB,否则会报错。

 

开发

1.       把上述资源组织起来,项目文件夹结构如下:

2.       把外部项目加入firebreath中我们自己创建的插件项目内有两种方式

1)         用vs打开插件解决方案后,直接在添加其他引用项目,习惯用vs的人一般都会这么干,但是这里不推荐这么做。原因是如果需要更新插件版本,我们需要重新执行cmake生成插件项目和解决方案,这会导致通过vs做的配置丢失,需要重新配置。

2)         在cmake文件中添加引用项目(推荐)

 

生成项目结构如下,把BmpToPng/HttpUpload/PrintScreen等这些项目加载到解决方案中,主要是为了方便对这些功能模块进行开发和调试。

完成对各功能模块开发和验证后,将其配置到YiXinPlugin插件项目。接下来就是jsapi的开发,能够让jsapi正确调用上述功能模块提供的外部接口,以完成需求分析中所描述到的功能。

 

3.       代码类图结构如下:

绿色表示Firebreath/atl接口类;

淡蓝色表示firebreath为插件项目扩展的接口类,这里定义了所有对外开放jsapi,也是实现插件所有的功能入口;

黄色是需要自己实现的功能模块。

 

测试并修正问题

1.       IE/chrome浏览器页面调用jsapi后,可以完成截图和上传功能,但是上传过程中浏览器无法响应用户操作

分析:IE/chrome会在ui线程中调用firebreath jsapi, 该api会调用CaptureScreenAPP::printscreen和HttpUpload::upload函数,这两个函数都会阻塞该api接口返回,导致浏览器ui线程无响应。由于在CaptureScreenAPP::printscreen阶段,浏览器被截屏窗口覆盖,所以这时掩盖了浏览器无法响应用户输入的问题,但一旦截屏完成截屏窗口随即销毁,线程进入HttpUpload::upload阶段,明显发现该问题。解决方法:创建独立线程运行HttpUpload::upload,解决上传阶段浏览器无影响的问题。

2.       Firefox奔溃问题

问题描述:firefox通过页面调用jsapi后,插件创建了截屏窗口,但是鼠标点击该窗口无反应,几秒钟后firefox提示插件无响应,随后奔溃。IE和chrome没有问题。

分析:问题原因同问题1,估计是浏览器实现的差异导致该该问题,修改为CaptureScreenAPP::printscreen也放到独立线程中运行,这个更改保证了jsapi即时返回。但也引出下面第三个问题。

 

3.       截屏窗口出现时被浏览器窗口挡住问题

该问题在IE/Chrome/Firefox同时出现,如下

点击页面按钮调用插件提供的jsapi后,浏览器始终保持为顶层窗口,截屏窗口被浏览器窗口覆盖。

分析:CaptureScreenAPP::printscreen在独立线程中运行,该函数中创建窗口父窗口被设置为NULL,因此在调用SetWindowPos将窗口设置为HWND_TOPMOST,无法将截屏窗口设置到浏览器窗口前。

解决方法:将截屏窗口父窗口设置为浏览器窗口。

 

4.       插件在IE下运行,第一次出现截屏窗口是,alt+tab导致窗口切换的问题

问题描述:经过问题三的修改,发现在IE下,第一次点击截屏按钮,IE浏览器窗口仍然保持在截屏窗口前,而且alt+tab可以切换到其他窗口。Chrome/firefox没有问题。

解决方案:

在截屏窗口显示前,调用SetForegroundWindow(g_MainDlg.m_hWnd);将截屏窗口设置为前置窗口,这能解决第一次截屏窗口出现时被IE覆盖的问题。但无法解决alt+tab切换问题;通过截获截屏窗口的MSG_WM_KILLFOCUS事件,在截屏窗口失去焦点时调用SetWindowPos设置为前置窗口,保证不被切换到其他窗口。

 

如何发布

Firebreath可以生成msi,也可以通过配置为各浏览器生成cab,crx,xpi格式插件,当然你也可以自己创建。

IE发布

在IE发布cab需要对cab进行数字签名,如下介绍了如何生成自己证书及签名,如果需要对外发布,则需要购买正是CA证书。

http://hiyyp1234.blog.163.com/blog/static/67786373201261891538299/

 

chrome发布,如何生成crx

创建一个manifest.json文件,格式参考如下

https://developer.chrome.com/extensions/manifest

我们插件manifest.json文件如下

{
  "manifest_version": 2,
  "name": "YiXinPlugin",
  "description": "YiXinPlugin by NetEase",
  "version": "1.0",
  "permissions": [
    "https://web.yixin.im/",
         "http://10.240.155.226/"
  ],
  "plugins": [
    { "path": "npYiXinPlugin.dll", "public": true}
  ]
}

将生成的.dll文件和上述manifest.json放到同一个文件夹下,打开chrome://externsion页面,选中开发者模式后点击打包扩展程序,如下


 

然后对话框选中文件夹,打包后生成.crx和.pem两个文件。保留好.pem,下次打升级包时需要用到。

 

由于安全问题google限制了用户私自分发crx,强制要求将extension提交到web app store才能让用户web页面上进行下载安装。有两个方案:

1. 按照google要求将extension发布到web app store.流程如下 (更新:该方法不可用)

https://developer.chrome.com/webstore/publish

备注:google目前已限制基于npapi插件,不允许其发布到web app store. 详细请参见

http://blog.chromium.org/2013/09/saying-goodbye-to-our-old-friend-npapi.html

2. 私自发布的crx可以让用户在chrome://extension页面进行安装,google目前未对此作限制。

 

Firefox发布,如何生成xpi插件

详细打包流程参考

https://developer.mozilla.org/en-US/docs/Building_an_Extension

最简要的打包一个npapi插件扩展如下:

创建如下一个目录结构:

yixinplubin_firefox
|--plugins
                   |-- npYiXinPlugin.dll
|-- install.rdf

Intall.rdf内容如下

<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> 
  <Description about="urn:mozilla:install-manifest"> 
    <em:id>helloween@myplugin.org</em:id> 
    <em:name>yixinplugin</em:name> 
    <em:version>1.0.0.1</em:version> 
    <em:targetApplication> 
    <Description> 
      <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> 
      <em:minVersion>4.0</em:minVersion> 
      <em:maxVersion>30.0</em:maxVersion> 
    </Description> 
    </em:targetApplication> 
    <em:unpack>true</em:unpack> 
  </Description> 
</RDF>

 

然后将plugins和install.rdf压缩至.zip,将压缩包后缀更改为.xpi即可。

Xpi同样需要数字签名,否则安装会出告警。签名方法参考如下:

https://developer.mozilla.org/en-US/docs/Signing_a_XPI



网易云免费体验馆,0成本体验20+款云产品! 

更多网易技术、产品、运营经验分享请点击


相关文章:
【推荐】 中文脏话识别的解决方案
【推荐】 react技术栈实践(2)
【推荐】 Hive中文注释乱码解决方案