🐛 修复 popup「当前页运行脚本」误报:过滤不可运行页面并恢复 iframe 脚本显示 (#1687) - #1689
Open
CodFrm wants to merge 8 commits into
Open
Conversation
popup「当前页运行脚本」原本只按顶层网址做 pattern 匹配,带来两类失真: 1. iframe 内运行的脚本整条消失。#1666 为了让「排除本站」后该行立即消失, 删掉了 #1511 加的「运行过但未匹配」合并,代价是 @match 只命中 iframe 的 脚本连同它在 iframe 注册的 GM 菜单都不再出现。现改为「本 tab 跑过 ∧ 仍匹配 某个子 frame」——排除本站后脚本对所有 frame 都不再匹配,仍会立即消失。 仅匹配子 frame 的行标记 matchesTopFrame=false,UI 据此隐藏按顶层 host 生成规则的站点范围操作(否则会写出 *://settings/* 这类垃圾规则)。 2. chrome:// 等脚本猫触及不到的页面上照样列出脚本。新增页面状态判定: 协议/商店名单给出准确原因,「本 tab 有没有 content script 报到」作为 运行时证据兜住白名单漏掉的情况(企业策略等)。file:// 的权限查询只用于 给未注入的情况一个更准确的原因,不反过来否定已注入的事实。 黑名单页并入同一状态——它同样不会注入,此前却照常列脚本。 GetPopupDataRes.isBlacklist 相应替换为 pageStatus。 e2e/popup-matching-regressions.spec.ts 原先用不授予 userScripts 权限的 fixture,脚本从未真正注入,验证的只是 pattern 命中这一层(即本 issue 的假象 在测试套件里的镜像)。改用带权限与 .test host 解析的 fixture + 本地 mock 页。
商店域是浏览器相关的:Edge 商店在 Chrome 里就是普通网页,Chrome 商店在 Firefox 里也一样。原实现把商店域并进 getPageAccessKind 的硬名单、优先于 注入证据判定,会在「别家浏览器」上误报脚本不能运行——而它其实在跑。 改为与 file:// 权限查询同一处理:只用来给「已确认没注入」的页面一个更准确 的原因,不反过来否定已注入的事实。顺带补上 microsoftedge.microsoft.com/addons。
This comment was marked as outdated.
This comment was marked as outdated.
This reverts commit 67270db.
This comment was marked as outdated.
This comment was marked as outdated.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checklist / 检查清单
Description / 描述
popup「当前页运行脚本」原本只按顶层网址的 pattern 匹配产生,导致列出的并不是实际在跑的脚本。#1687 报的两个症状同源:
1. iframe 内运行的脚本整条消失(beta.2 回归)
#1666 为了让「排除本站」后该行立即消失,删掉了 #1511 加的「运行过但未匹配」合并。代价是
@match只命中 iframe 的脚本、连同它在 iframe 里注册的 GM 菜单,都不再出现在 popup(右键菜单和角标却仍有,三个界面口径不一致)。改为 「本 tab 跑过 ∧ 现在仍匹配某个子 frame」,而不是简单恢复无条件合并:排除本站后脚本对所有 frame 都不再匹配,该行照样立即消失,#1666 的契约不变。只在存在「跑过但顶层没匹配」的记录时才去查
chrome.webNavigation.getAllFrames,常见页面零额外开销。仅匹配子 frame 的行标记
matchesTopFrame=false,UI 据此隐藏站点范围操作——那些规则按顶层 host 生成,对它不成立,点下去会写出*://settings/*这类垃圾规则。2. 脚本猫触及不到的页面照样列出脚本
新增页面状态判定,非
ok时不列脚本、改为说明原因(后台脚本区不受影响):restrictedchrome:/// 扩展页 /about:/devtools:…),或已确认没注入的扩展商店页blacklistfile-access-deniedfile://且未开启文件访问not-injected判据是实测选出来的:
chrome://settings/上getAllFrames照常返回 frames,当不了可达性判据;而「本 tab 有没有 content script 报到」是精确的运行时证据(scriptcat-scripting注册在<all_urls>+allFrames,src/scripting.ts无条件调pageLoad())。因此用两条正交信号:名单给准确原因,报到兜住名单漏掉的(企业策略等)。顺序有意为之:协议层面的受限(
chrome://、扩展页等,跨浏览器确定)与黑名单先判;其余一律以报到为准;两项与浏览器相关的判据——扩展商店域和file://权限查询——放在注入证据之后,只用来给已确认没注入的页面一个更准确的原因,绝不反过来否定已注入的事实。这一点对商店域尤其要紧:各浏览器只保护自家商店,
microsoftedge.microsoft.com/addons在 Chrome 里就是普通网页,chromewebstore.google.com在 Firefox 里也一样。硬名单会误伤那些页面上正常运行的脚本;放在注入证据之后则两种浏览器都对。四家商店都已覆盖(Chrome / Chrome 旧域 / Edge / Firefox)。报到标记(新 session key
tabLoaded:<tabId>)存 origin 而非完整网址:SPA 换页不失效,跳到另一个 origin 自然失效。黑名单页并入同一状态——它本来就不会注入(
runtime.ts命中黑名单直接return null),此前却照常列脚本。GetPopupDataRes.isBlacklist相应替换为pageStatus。附带:修正一处测试假前提
e2e/popup-matching-regressions.spec.ts原先用e2e/fixtures.ts的简单 fixture,而它不授予 userScripts 权限(注释即写明「不需要 userScripts 的测试使用」)。探针证实:它goto("https://example.com/")后页面 console 为空、tabScript:/tabLoaded:皆无——脚本从未真正注入,这三条 e2e 一直只验证 pattern 命中那一层,正是本 issue 的假象在测试套件里的镜像。已改用带 userScripts 权限与.testhost 解析的 fixture + 本地 mock 页面,三条重新全绿,且现在建立在真实注入之上。测试
修复前后各观测一次(真实 Chrome):iframe 场景修复前 popup 清单
[],修复后拿到完整行runNumByIframe:1、matchesTopFrame:false,以及 iframe 内注册的菜单(frameId:8)。可达性:同一次运行里
chrome://settings/→pageStatus:"restricted"、scripts:[];普通页 →"ok"、脚本正常列出(用的就是 issue 正文的@match http*://*/*)。扩展商店(真实外网,跑在 Chrome 上):
chromewebstore.google.com主 frame 脚本没跑 →restricted、scripts:[];microsoftedge.microsoft.com/addons主 frame 脚本跑了 →ok、scripts:["allsite-probe#1"]。两侧都与「商店判定排在注入证据之后」一致。全量 e2e
62 passed;全量单测343 文件 / 4252 条;pnpm run lint全 0。新增单测:
page_access.test.ts32 条纯函数、popup 服务层 10 条状态判定(含 SPA 换页、跨 origin、商店页与file://的跨浏览器误报防护)、popup 子 frame 合并 6 条、popup UI 4 态文案 + iframe 行隐藏站点操作。Screenshots / 截图
popup 在
chrome://settings/与普通页(含跨 host iframe)下的真实渲染,明暗双主题各一组,由
e2e/scratch/iframe-popup/capture-shots.spec.ts生成(scratch 目录 gitignored):chrome://settings/):橙色说明条「浏览器不允许扩展在此页面运行脚本」,当前页清单(0/0)、无任何脚本行。(2/2),allsite-probe(命中顶层)与iframe-only-probe(只匹配 iframe)都在,两者分别在顶层 / iframe 注册的 GM 菜单
demo-menu/iframe-menu也都列出可点 —— 同时是缺陷 B 的渲染证据。(0/0)(脚本确实注入不了)。(1/1)正常列出脚本 —— 这一组就是「硬名单会误伤」的反证。截 popup 有个坑:它必须开在
focused:false的独立窗口里,否则 popup 自己就是lastFocusedWindow的active tab,
getCurrentTab()拿不到目标页;视口要固定 360px,否则 popup.html 会按 #686 的移动端媒体查询铺满。已知限制
restricted,没拦就有报到 →ok,两种都不误伤;两条单测钉住了这个顺序。runtime_blocked_hosts拦下的页面无法探测具体原因,落到not-injected(文案为「刷新页面后生效」)。file://那条只给文案、不给跳转按钮:Chrome 是chrome://extensions/?id=、Firefox 是about:addons,跨浏览器引导不统一。url_matcher.ts里*:///http*://匹配任意协议(与 Chrome/TM 的*= http|https 不同)未在本 PR 处理。做完可达性判定后它在 popup 上不可见,但仍影响file://的真实注入行为,建议单独跟进。