Skip to content

[提案] 将安装后的返回操作改为由标签页侧上下文执行 #1588

Description

@cyfung1031

涉及模块

  • src/app/service/service_worker/script.ts
  • Service Worker 与标签页侧执行上下文之间的通信
  • 用户脚本安装完成后的页面返回流程

当前实现

ScriptService.listenerScriptInstall() 会拦截用户脚本安装地址并打开 ScriptCat 的安装页面。

openInstallPageByUrl() 完成或失败后,当前代码都会在 finally 中调用 chrome.scripting.executeScript(),向原标签页注入一个函数并执行:

history.back();

因此,当前安装流程为了完成一次“返回上一页”操作,需要由 Service Worker 主动向目标标签页注入并执行代码。

本 issue 只针对上述安装后返回流程,不涉及 ScriptCat 用于执行用户脚本的 ExecScript 类,也不讨论完整的用户脚本运行时设计。

问题说明

需要避免一种容易引起误解的表述:

Firefox 不允许扩展使用 scripting.executeScript()

这并不准确。Firefox 支持 scripting.executeScript();当前调用本身也不应被描述为一个已确认的 Firefox 阻塞问题。

本 issue 真正要处理的是执行职责和上下文边界:

  • history.back() 属于标签页页面历史操作;
  • 目前该操作由 Service Worker 通过一次性脚本注入触发;
  • 这使安装流程额外依赖 Service Worker 对另一个执行上下文的直接代码执行;
  • 对于这样一个固定且明确的页面动作,更清晰的模型是由标签页侧上下文预先拥有对应逻辑,并在收到请求后自行执行。

因此,本 issue 的目标不是因为 Firefox 禁用了某个 API,也不是要全面移除项目中的 executeScript(),而是消除这一处仅为触发 history.back() 而存在的一次性跨上下文代码注入。

Rob Wu 的观点

原始 issue 所引用的 Rob Wu 意见,其核心可概括为:

不应把模型设计成“上下文 A 直接把代码放到上下文 B 中执行”;更合适的方式是“上下文 A 向上下文 B 发送请求,再由上下文 B 执行自己拥有的代码”。

这里需要明确:

  • 上述内容是对 Rob Wu 架构意见的概括,不是 Mozilla API 文档的逐字规范;
  • 它表达的是推荐的执行职责划分和消息通信模式;
  • 它不能被解释成 Firefox 已禁止所有 scripting.executeScript() 调用。

本 issue 采用这一观点,是因为 history.back() 本来就是一个由标签页侧上下文执行更自然的固定操作,而不是因为当前 API 在 Firefox 中必然不可用。

官方资料

这些资料用于说明 API 能力和标准的跨上下文通信方式,不应被引用为“Firefox 禁止 executeScript()”的依据。

目标

将用户脚本安装完成后的“返回上一页”职责移交给合适的标签页侧上下文。

重构后:

  • Service Worker 不再为了执行 history.back() / history.go(-1) 而向标签页动态注入函数;
  • 页面返回动作由标签页侧预先存在的代码自行执行;
  • Service Worker 如需触发该动作,应通过 ScriptCat 现有的消息通信机制发送明确请求;
  • Chrome 中现有安装体验保持不变;
  • 同时减少后续 Firefox 适配和执行上下文重构中的一处不必要依赖。

范围

  • 替换 ScriptService.listenerScriptInstall() 中用于执行 history.back()chrome.scripting.executeScript() 调用;
  • 保持当前行为:无论 openInstallPageByUrl() 成功还是失败,安装页交接结束后都应尝试返回原页面;
  • 复用项目已有的消息通信和执行上下文边界;
  • 只修改完成该职责迁移所必需的代码和测试。

具体实现由贡献者在梳理现有 content、scripting 和消息通道后决定,本 issue 不预设完整方案。

非目标

  • 不声称 Firefox 不支持 scripting.executeScript()
  • 不要求移除项目中所有 executeScript() 用法;
  • 不重构完整的用户脚本安装流程;
  • 不修改 ExecScript 用户脚本运行时;
  • 不在本 issue 中完成全部 Firefox 支持;
  • 不通过在 Firefox 中隐藏或删除返回功能来规避问题;
  • 不进行与该职责无关的模块清理。

验收标准

  • 安装后的返回流程不再使用 chrome.scripting.executeScript() 执行 history.back()history.go(-1)
  • 页面历史操作由合适的标签页侧上下文自行完成;
  • 跨上下文触发通过 ScriptCat 已有的消息机制完成;
  • openInstallPageByUrl() 成功和失败时均保持当前返回行为;
  • 每次安装页交接只触发一次返回操作;
  • 支持的 .user.js 安装入口不得出现行为回归;
  • 不得以 Firefox 专用跳过逻辑代替本次职责迁移。

测试要求

  • 覆盖 openInstallPageByUrl() resolve 和 reject 两条路径,因为当前返回行为位于 finally 中;
  • 验证新的消息或调用只触发一次页面返回;
  • 验证该职责不再调用 chrome.scripting.executeScript()
  • 测试名称遵循仓库现有的中文 BDD 风格;
  • 提交 PR 前运行相关单元测试、pnpm typecheck 和仓库 lint 检查。

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalTechnical proposal or design discussiontechnicalTechnical implementation, architecture, or refactoring topic

    Type

    Fields

    No fields configured for Task.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions