-
Notifications
You must be signed in to change notification settings - Fork 0
Description
背景
当前 Nolo 只支持基于 urlFilter 的拦截规则,并统一生成 redirect -> blocked.html 的 DNR 动态规则。它还不能表达“在一个更大的路径范围内拦截,但对其中某个子路径放行”的需求。
典型场景:
- 想拦截
github.com/xxx/下的大部分内容 - 但允许访问
github.com/xxx/yyy及其下级路径
当前代码现状:
rule-utils.js的buildDynamicRules()只生成redirect规则background.js的状态模型只围绕blockedSites工作popup.js只支持新增 / 启停 / 删除“拦截规则”,没有“放行例外”概念
目标
- 支持“父路径拦截、子路径放行”的规则表达能力
- 保持当前基于 DNR 的实现路线,不引入请求拦截型后台代理
- 尽量复用现有 popup / background / rule-utils 架构
- 不新增超出当前需求的新高风险权限
非目标
- 这一期不做复杂的可视化规则树编辑器
- 这一期不做同步到云端、多设备同步
- 这一期不做站点模板市场或预设规则仓库
技术调研结论
1. DNR 原生支持 allow 规则
Chrome 官方 DNR 文档明确支持以下动作:
blockredirectallowallowAllRequestsupgradeSchememodifyHeaders
其中 allow 的语义是:如果请求命中 allow 规则,则该请求不会被当前扩展拦截。
2. 同一扩展内的规则优先级满足“高优先级 allow 覆盖低优先级 redirect”
官方文档说明:
- 先按开发者设置的
priority排序 - 同优先级下按动作优先级排序:
allowallowAllRequestsblockupgradeSchemeredirect
因此,实现路径例外的核心方式是:
- 用较高优先级的
allow规则放行子路径 - 用较低优先级的
redirect规则拦截父路径
3. 这个需求大多数情况下不需要 regexFilter,urlFilter 就够用
GitHub 这类路径场景可以先用 urlFilter 完成:
- block:
||github.com/xxx/ - allow:
||github.com/xxx/yyy^
这里的 ^ 是 DNR urlFilter 的分隔符/结尾匹配符,可以避免把 github.com/xxx/yyyzzz 误判为放行目标。
这意味着首期实现可以不引入 regex 编辑复杂度,就先满足主要需求。
4. regexFilter 仍然值得保留为后续高级能力
虽然首期不必依赖 regex,但更复杂的路径约束、排除规则、精确匹配仍然会受益于 regexFilter。Chrome 官方也支持 regexFilter,并提供:
- RE2 语法
isRegexSupported()校验能力- 每类 regex 规则最多 1000 条的限制
结论:
- MVP 可先做
urlFilter + allow regexFilter作为第二阶段高级能力更合适
5. 当前权限足够,不需要为 allow 规则额外加权限
当前 manifest 已包含:
declarativeNetRequeststoragewebNavigationhost_permissions: ["<all_urls>"]
基于官方文档,allow 规则可以直接在现有 DNR 能力内使用,因此本需求不需要新增新的核心权限。
6. 开发期验证可以结合 DNR 调试 API
Chrome 官方提供:
testMatchOutcome()getMatchedRules()onRuleMatchedDebug
这些能力主要用于 unpacked extension 调试,适合开发阶段验证“allow 是否真的压过 redirect”。
需求定义
用户故事
- 用户可以新增一条“拦截规则”
- 用户可以新增一条“放行规则”
- 当某个请求同时命中“放行规则”和“拦截规则”时,应优先放行
- 用户可以通过规则组合表达:
- 拦截
github.com/xxx/下的大多数页面 - 放行
github.com/xxx/yyy与其下级路径
- 拦截
- popup 中可以清楚区分规则类型,避免误操作
验收示例
给定以下两条规则:
- allow:
||github.com/xxx/yyy^ - block/redirect:
||github.com/xxx/
预期行为:
https://github.com/xxx/aaa-> 被拦截https://github.com/xxx/yyy-> 放行https://github.com/xxx/yyy/issues-> 放行https://github.com/xxx/yyyzzz-> 不应因为 allow 规则被误放行https://github.com/other/repo-> 不受影响
推荐技术方案
方案选型
推荐先做“通用规则动作扩展”,而不是直接做“嵌套例外 UI”。
原因:
- 更贴近 DNR 原生模型
- 与当前代码结构更兼容
- 后续要支持 regexFilter / block / allow 时更容易扩展
- 首期实现成本更低
规则模型升级
建议将当前单一拦截规则模型升级为通用规则模型,建议字段如下:
{
id: number;
action: "redirect" | "allow";
patternType: "urlFilter" | "regexFilter";
pattern: string;
enabled: boolean;
}说明:
redirect继续表示“拦截并跳转到 blocked.html”allow表示“放行,不拦截”patternType让首期与后续阶段共用同一数据模型- 首期 UI 可以只开放
urlFilter,但底层数据结构提前兼容regexFilter
状态与存储
建议把当前 blockedSites 演进为更语义化的 rules。
如果要最小改动,也可以短期保留原存储键名,但对象结构需扩展出 action 和 patternType。长期更推荐统一重命名为 rules,减少概念歧义。
DNR 生成策略
建议在 buildDynamicRules() 中按动作类型生成不同 DNR action:
redirect->blocked.html?ruleId=<id>allow->{ type: "allow" }
建议显式设置优先级:
allow规则:priority = 100redirect规则:priority = 10
这样即使未来出现更多规则组合,也能稳定表达“放行优先于拦截”。
匹配策略
首期推荐:
- 默认使用
urlFilter - 路径例外通过更具体的 allow 规则表达
例如:
- allow:
||github.com/xxx/yyy^ - redirect:
||github.com/xxx/
第二阶段再考虑开放 regexFilter:
- 在保存前通过
chrome.declarativeNetRequest.isRegexSupported()校验 - 对不支持的 regex 给出明确报错
UI / UX 方案
popup 需要新增“规则类型”概念,建议最小实现为:
- 新增一个动作选择控件:
拦截/放行 - 规则列表中展示动作标签,例如:
拦截放行
- 保留当前启停、删除交互
- 保持输入框仍面向高级用户,继续接受 DNR 规则表达式
建议不要在第一期就做可视化“父规则 + 子例外”树状编辑器,先让底层能力上线。
blocked 页面影响
blocked 页面只服务于 redirect 规则。
因此:
allow规则不需要 blocked 页展示GET_SITE_BY_RULE_ID/CONSUME_BLOCKED_REQUEST逻辑可以继续服务于 redirect 规则- 只需保证 blocked 页在读取规则时能处理“当前 ruleId 对应的是 redirect 规则”这一前提
风险与注意事项
-
存储迁移风险
- 如果要把
blockedSites重命名为rules,需要决定是否做迁移 - 如果当前 main 已有用户,建议设计一次性迁移逻辑
- 如果要把
-
规则冲突风险
- 用户可以创建过宽的 allow 规则,导致部分拦截失效
- 需要在 UI 文案和排序逻辑上让优先级模型足够清晰
-
regex 复杂度风险
- regexFilter 有 1000 条上限和复杂度限制
- 所以不建议把 regex 当作首期主路径
-
测试误判风险
- 仅靠单元测试不够,仍需浏览器内手动验证真实 DNR 行为
具体实施规划
Phase 1: 规则模型与 DNR 基础能力
- 扩展规则数据结构,支持
action和patternType - 调整
normalizeState()/serializeState()/ 去重逻辑 - 调整
buildDynamicRules(),支持输出allow和redirect - 为 allow / redirect 设置显式优先级
- 扩展
background.js的新增 / 更新 / 删除消息处理
Phase 2: Popup 交互
- 在 popup 中增加规则动作选择器(拦截 / 放行)
- 在规则列表中展示规则类型标签
- 优化状态提示文案,使“放行优先级高于拦截”可理解
- 保持当前启停 / 删除交互不退化
Phase 3: 验证与测试
- 扩展
rule-utils.test.js,覆盖 mixed allow + redirect 规则生成 - 补充状态规范化 / 去重 / 相等性测试
- 增加手动验证用例:GitHub 父路径拦截 + 子路径放行
- 在 unpacked extension 下用
testMatchOutcome()/getMatchedRules()辅助验证
Phase 4: 高级能力(可选后续 issue)
- 开放
regexFilter作为高级匹配方式 - 在 background 中接入
isRegexSupported()保存前校验 - 评估是否提供“例外规则模板”或“嵌套例外 UI”
建议的首批落地范围(MVP)
建议本 issue 先完成以下闭环:
- 支持
allow+redirect - 仅要求
urlFilter - popup 可创建 / 管理两类规则
- 用明确优先级满足“父路径拦截、子路径放行”
这已经足以满足最核心的 GitHub 场景,而且能以最低复杂度验证产品方向。
参考资料
- Chrome DNR API: https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest
- Chrome DNR 规则评估 / allow 优先级: https://developer.chrome.com/extensions/declarativeNetRequest
- Chrome 权限说明: https://developer.chrome.com/docs/extensions/reference/permissions-list