插件实现机制
1. 插件运行机制
1.1 运行环境
项目本身是使用的capacitor开发的,而capacitor是基于Android的webview,所有运行环境就是浏览器环境,但为了一定的安全考虑(比如页面不被破坏)插件在受限的环境中执行,只有部分 JavaScript 全局对象可用。safeRunContext
通过代理 window
对象,仅允许访问 Set
、Map
、fetch
等安全 API,避免插件访问敏感数据。
ts
//只有定义的才可在插件中访问
const whitelist = {
Set: true,
Map: true,
navigator: true,
console: true,
fetch: true,
XMLHttpRequest: true,
FormData: true,
DOMParser: true,
Promise: true,
String: true,
Array: true,
unescape: true,
decodeURI: true,
decodeURIComponent: true,
encodeURI: true,
encodeURIComponent: true,
URL: true,
Blob: true,
JSON: true,
eval: true,
Object: true,
}
5.2 安全执行
插件代码通过 safeRunScript
运行,该函数使用 Function
创建新的作用域,并在 with (IConfig.safeWindow)
内部执行插件代码,确保代码只能访问白名单内的变量。
5.3 依赖注入
插件通过 fnOption.require
引入系统提供的功能,fnOption.module
访问插件的导出内容,fnOption.env
读取系统环境变量。 由于运行环境本质是浏览器环境,那么在使用fetch请求时会存在部分请求头无法设置的问题,所有项目提供了require来使用一些系统函数来处理,插件中可直接使用以下代码,如:
ts
//使用的是CapacitorHttp,具体可参考CapacitorHttp的文档
const Http = require("http");
//代理图片地址,返回图片base64
const proxyImg = require('proxyImg')
这里是全部的require函数:
ts
{
http: CapacitorHttp,
CryptoJS: CryptoJS,
analysis: analysis,
proxyImg: proxyImg
},
5.4 生命周期
插件在被加载或软件启动时,会自动执行插件函数的函数体,并将插件的模块导出(module.exports)作为插件的实例。
插件实例和插件中的数据会在软件的生命周期内持续存在,直至软件或者插件被卸载。