
Security News
TypeScript is Porting Its Compiler to Go for 10x Faster Builds
TypeScript is porting its compiler to Go, delivering 10x faster builds, lower memory usage, and improved editor performance for a smoother developer experience.
chrome-extension-tools
Advanced tools
浏览器插件
你可以使用该工作流库,来实现复杂业务流程的自动化,定义多层级任务流程,基于每个任务的执行结果来动态调整后续的任务执行,支持任务的重试和重新执行等功能。
该工作流是需要编写代码来实现相关的业务流程,它只提供流程等相关的基础功能。
以 sidePanel 为中心,根据工作流的配置要求,定义相关的业务流程配置,给到 sidePanel 和 contentScript。由 sidePanel 开始启动工作流,background 作为 sidePanel 和 contentScript 之间的通信桥梁。
+---------------+
| configures | -+
+---------------+ |
| |
| |
v |
+---------------+ |
+> | contentScript | |
| +---------------+ |
| | |
| | |
| v v
| +--------------------+
+- | sidePanel |
+--------------------+
| ^
| |
v |
+---------------+ |
| background | -+
+---------------+
浏览器的消息通信由三个部分组成:
每个浏览器插件,只会各有一个 service 和 sidePanel,会有多个 content script,所以关于 content script 的通信,都需要带上对应的 tabId,保证 background(sidePanel) 可以给指定的 content script 发消息。
这块消息通信的复杂度并不高,为了方便和更适配我的写法,所以我自己重新封装了消息通信的功能。
// send
const result = await sendMsgByCS(messageId, data, { destination: CetDestination.BG , tabId?: ...})
// receive
onMsgInBg(messageId, (data, params) => {
return xx
})
export interface CetMessageCallbackParams {
tabId?: number
option: CetDestinationOption
messageId: string
}
export interface CetMessageSendResult<T = unknown> {
data: T
tabId?: number
messageId: string
success: boolean
msg?: string
}
Background 发给 content script 需要带上 tabId 才能指定发给谁:
import { sendMsgByBG, CetDestination } from 'chrome-extension-tools'
const res = await sendMsgByBG('test1', { ... }, { tabId: tabId, destination: CetDestination.cs })
import { sendMsgByBG, CetDestination } from 'chrome-extension-tools'
const res = await sendMsgByBG('test1', { ... }, { destination: CetDestination.sp })
import { sendMsgBySP, CetDestination } from 'chrome-extension-tools'
const res = await sendMsgBySP('toBg', { ... }, { destination: CetDestination.BG });
Side panel 发给 content script 需要带上 tabId 才能指定发给谁:
import { sendMsgBySP, CetDestination, EVENTS } from 'chrome-extension-tools'
const { data } = await sendMsgBySP(EVENTS.SP2BG_GET_CURRENT_TAB, undefined, { destination: CetDestination.BG });
const res = await sendMsgBySP('test1', { ... }, { estination: CetDestination.CS, tabId: tabId })
content script 监听:
import { onMsgInCS } from 'chrome-extension-tools'
onMsgInCS('test1', async (res) => {
console.log('test1', res)
return 'ok'
})
content script 发送给 background,可以不带 tabId
import { sendMsgByCS } from 'chrome-extension-tools'
const res = await sendMsgByCS('test2', { name: 'task1' }, { destination: CetDestination.BG })
content script 发给 side panel:
import { CetDestination, sendMsgBySP } from 'chrome-extension-tools'
const { data } = await sendMsgByCS('test3', undefined, { destination: CetDestination.SP })
side panel 监听:
import { CetDestination, onMsgInSP } from 'chrome-extension-tools'
onMsgInCS('test3', async (res) => {
console.log('test3', res)
return 'ok'
})
通过改写 xhr 和 fetch,来获取请求数据。
第一,新增一个新的 background 文件,backgroudn/intercept-reqeust.ts:
import { initInterceptRequest } from 'chrome-extension-tools'
initInterceptRequest()
第二,修改 vite 构建配置:
{
build: {
// ...
lib: {
entry: [
r('src/background/main.ts'),
r('src/background/intercept-request.ts'),
],
name: packageJson.name,
formats: ['es'],
},
rollupOptions: {
output: {
manualChunks: undefined,
entryFileNames: (chunk) => {
if (chunk.name === 'main')
return 'index.mjs'
else
return 'intercept-request.mjs'
},
extend: true,
},
},
},
}
这样 background 区域就会构建两个入口文件。
在 background 引入 injectInterceptRequest
方法,并且在 tabs 事件中,选择一个合适的时机注入代码:
import { injectInterceptRequest } from 'chrome-extension-tools'
const targetDomains = [
'https://xxx.com/*',
]
const checkDomains = [
'https://xxx.com',
]
function injectInterceptRequestBg() {
injectInterceptRequest('./dist/background/intercept-request.mjs', targetDomains)
}
function checkAndInjectDomain(url?: string) {
if (checkDomains.some(v => (url || '').includes(v))) {
injectInterceptRequestBg()
}
}
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
curTabId = tabId
// 检查页面是否完成加载
if (changeInfo.status === 'complete') {
// 注入脚本
checkAndInjectDomain(tab.url)
}
})
这样在 background 的配置已经完成,我们还需要在 content script 去接受脚本捕获的接口数据。
在这个库中已经配置好相关的初始化工作:
// content script
import { initContentScript } from 'chrome-extension-tools'
initContentScript()
收到数据,会通过消息通知发给 background 和 side panel:
// initContentScript code:
const res = serializeJSON(event.data.data.response)
const item = {
url: event.data.data.url,
response: res,
requestType: event.data.data.requestType,
id: generateTenDigitRandom(),
}
sendMsgByCS(EVENTS.CS2SP_GET_REQUEST, item, { destination: CetDestination.SP })
sendMsgByCS(EVENTS.CS2BG_GET_REQUEST, item, { destination: CetDestination.BG })
这种捕获方式,如果是第一次访问页面,脚本虽然注入了,但捕获不了数据,需要刷新一次页面才行。
日志模块提供了一个统一的日志记录系统,支持多级别日志、日志缓存、跨进程同步等功能。
组件库内已经默认初始化一个 logger,它会收集内置的消息通知:
import { CetLogger, CetLogLevel } from 'chrome-extension-tools'
export const cetLogger = new CetLogger({
isCS: true,
isSP: true,
isSyncToBG: true,
isSyncToSP: true,
level: CetLogLevel.DEBUG,
})
import { CetLogger, CetLogLevel } from 'chrome-extension-tools'
// 获取日志实例
const logger = CetLogger.getInstance({
level: CetLogLevel.DEBUG,
prefix: '[My Extension]',
maxCacheSize: 1000
})
// 记录不同级别的日志
logger.debug('调试信息')
logger.info('普通信息')
logger.warn('警告信息')
logger.error('错误信息')
选项名 | 类型 | 默认值 | 描述 |
---|---|---|---|
level | LogLevel | INFO | 日志级别,可选值:DEBUG、INFO、WARN、ERROR |
timestamp | boolean | true | 是否显示时间戳 |
prefix | string | '[Chrome Extension]' | 日志前缀 |
color | boolean | true | 是否使用颜色输出 |
maxCacheSize | number | 5000 | 最大缓存日志数量 |
isSyncToBG | boolean | false | 是否同步到后台进程 |
isSyncToSP | boolean | false | 是否同步到弹出窗口 |
isCS | boolean | false | 是否为内容脚本 |
isShowInConsole | boolean | false | 是否在 console.log 显示日志 |
日志模块支持日志缓存功能,可以通过以下方法操作缓存:
// 获取所有缓存的日志
const allLogs = logger.getLogs()
// 获取指定级别的日志
const errorLogs = logger.getLogsByLevel(LogLevel.ERROR)
// 清空日志缓存
logger.clearLogs()
// 获取当前缓存大小
const cacheSize = logger.getCacheSize()
支持将 content script 或 sidepanel 的日志同步到 sidepanel 或 background
// content script 将日志同步到 background 和 sidepanel
const logger = CetLogger.getInstance({
isCS: true,
isSyncToBG: true,
isSyncToSP: true,
})
// side panel 将日志同步到 background
const logger = CetLogger.getInstance({
isSP: true,
isSyncToBG: true,
})
可以通过 setOptions
方法动态修改日志配置:
logger.setOptions({
level: LogLevel.WARN,
timestamp: false
})
FAQs
We found that chrome-extension-tools demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
TypeScript is porting its compiler to Go, delivering 10x faster builds, lower memory usage, and improved editor performance for a smoother developer experience.
Research
Security News
The Socket Research Team has discovered six new malicious npm packages linked to North Korea’s Lazarus Group, designed to steal credentials and deploy backdoors.
Security News
Socket CEO Feross Aboukhadijeh discusses the open web, open source security, and how Socket tackles software supply chain attacks on The Pair Program podcast.