Skip to content

feat: 添加 Native Messaging 桥接,支持 CLI 和 AI Agent 控制扩展#1143

Open
LeiShi1313 wants to merge 21 commits intopt-plugins:masterfrom
LeiShi1313:master
Open

feat: 添加 Native Messaging 桥接,支持 CLI 和 AI Agent 控制扩展#1143
LeiShi1313 wants to merge 21 commits intopt-plugins:masterfrom
LeiShi1313:master

Conversation

@LeiShi1313
Copy link
Copy Markdown
Collaborator

@LeiShi1313 LeiShi1313 commented Mar 30, 2026

为 PT-Depiler 添加 Chrome Native Messaging 支持,使终端工具和 AI Agent
能够通过命令行与浏览器扩展通信,复用扩展已有的登录态、站点定义和下载器配置。

改动内容

  • 新增 src/entries/background/utils/nativeMessaging.ts(约 130 行)
    • 通过 chrome.runtime.connectNative() 连接本地 Native Messaging Host
    • 启动时发送 hello 握手,携带浏览器实例标识
    • 维护方法白名单,仅代理安全的、面向外部的 sendMessage() 方法
    • 支持断线重连(指数退避),未安装 Host 时静默跳过,不影响现有功能
  • 修改 src/entries/background/main.ts — 添加一行 import
  • 修改 vite.config.ts — 添加 nativeMessaging 权限
  • 修改 src/entries/offscreen/utils/search.ts — 修复 configStorage 未初始化时的空指针问题

配套 CLI 工具

配合本 PR,我开发了 https://github.com/LeiShi1313/ptd-cli (Rust 编写,跨平台支持
Linux/macOS/Windows),可以在终端中完成以下操作:

跨站搜索种子

ptd search "阿凡达"

搜索指定站点

ptd search "avatar" --site chdbits --site btschool

将搜索结果推送到下载器

ptd download 0 --downloader <下载器ID>

查看站点用户数据(做种数、上传量、魔力值等)

ptd user-info current chdbits

查看所有站点的历史数据

ptd user-info history chdbits

管理下载器

ptd downloader status <下载器ID>

管理辅种任务

ptd keep-upload list

AI Agent 集成

本 PR 最大的意义在于:任何 AI Agent 都可以通过 ptd-cli 用自然语言控制 PT-Depiler 扩展。

例如,用户可以在 OpenClaw/Claude Code/Codex 或其他 AI 编码助手中直接说:

▎ "帮我在所有站点搜索 4K 版本的《流浪地球2》,找到体积最小的那个,推送到 qBittorrent"

AI Agent 会自动调用 ptd search、分析结果、选择最优种子、调用 ptd download 完成整个流程。

这使得 PT-Depiler 从一个浏览器扩展进化为一个可编程的、可被 AI 驱动的 PT 站点管理平台。

安全性

  • 方法白名单机制:仅暴露搜索、下载、用户信息查询等安全方法,不暴露 cookie、存储写入等敏感操作
  • 通信完全走本地 Native Messaging 通道,不涉及网络暴露
  • 未安装 Native Host 时扩展行为完全不变,零影响

对现有功能的影响

  • 无 — 不修改 ProtocolMap、offscreen handler、站点定义或下载器逻辑
  • 未安装 ptd-cli 的用户不会感知到任何变化

目前 https://github.com/LeiShi1313/ptd-cli 在我的个人仓库下开发。如果本 PR 被接受,我很乐意将 ptd-cli 项目转移到
https://github.com/pt-plugins 组织下,作为 PT-Depiler 的官方 CLI 工具统一维护。

Summary by Sourcery

Add a Chrome Native Messaging bridge to allow external CLI or agents to call a safe subset of PT-Depiler background APIs while keeping existing extension behavior unchanged when the native host is absent.

New Features:

  • Introduce a background native messaging bridge that proxies a whitelisted set of extension methods to a local native host for CLI and agent integration.

Bug Fixes:

  • Guard access to search configuration in the offscreen search utility to avoid null or undefined access errors when config storage is not initialized.

Build:

  • Request the browser nativeMessaging permission in the extension build configuration to enable the new bridge.

- New nativeMessaging.ts bridge in background script that connects to
  a native host via chrome.runtime.connectNative(), sends a hello
  handshake with instance identity, and proxies an allowlisted set of
  methods through the existing sendMessage() system
- Add nativeMessaging permission to manifest
- Fix null-safety in search handler for uninitialized config storage
- Prevent reconnect loop when native host is not installed
Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've reviewed this pull request using the Sourcery rules engine

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Mar 30, 2026

Reviewer's Guide

Adds a Chrome Native Messaging bridge from the background script to a local native host, enabling CLI/AI Agent control of the extension while keeping behavior unchanged when the host is absent, and includes a small search null-safety fix and a manifest permission update.

Sequence diagram for CLI/AI Agent request via Native Messaging bridge

sequenceDiagram
  actor User
  participant AIAgent
  participant CLI as ptd_cli
  participant Host as NativeMessagingHost
  participant BG as BackgroundScript
  participant Offscreen as OffscreenSearch
  participant Site as PT_Site

  User->>AIAgent: Natural language request
  AIAgent->>CLI: Invoke ptd command
  CLI->>Host: JSON request {id, method, params}
  Host->>BG: Native message request

  Note over BG: On startup, BG connectsNative and sends hello {instanceId, browser, extensionId, version, capabilities}

  BG->>BG: Validate method in ALLOWED_METHODS
  alt Method allowed
    BG->>Offscreen: setupOffscreenDocument
    Offscreen->>Site: Perform search/download/user_info etc
    Site-->>Offscreen: Result
    Offscreen-->>BG: Result
    BG->>Host: Response {type: response, id, result}
    Host->>CLI: Response
    CLI->>AIAgent: Parsed result
    AIAgent->>User: Answer and follow up actions
  else Method not allowed
    BG->>Host: Response {error: METHOD_NOT_ALLOWED}
    Host->>CLI: Error
  end
Loading

Class diagram for Native Messaging bridge module

classDiagram
  class NativeMessagingBridge {
    <<module>>
    +string NATIVE_HOST_NAME
    +string INSTANCE_ID_KEY
    +number RECONNECT_BASE_MS
    +number RECONNECT_MAX_MS
    +Set~string~ ALLOWED_METHODS
    +string[] FATAL_ERRORS
    +number reconnectAttempt
    +Promise~string~ getOrCreateInstanceId()
    +void connect()
  }

  class BackgroundMain {
    <<module>>
    +NativeMessagingBridge import
  }

  class OffscreenSearch {
    <<module>>
    +onMessage_getSiteSearchResult()
    +configStorage_optional_access
  }

  NativeMessagingBridge --> BackgroundMain : used_by
  BackgroundMain --> OffscreenSearch : sendMessage_calls
Loading

File-Level Changes

Change Details Files
Introduce a background native-messaging bridge that exposes a whitelisted subset of extension methods to a local native host for CLI/AI integration.
  • Create a Native Messaging connector that calls chrome.runtime.connectNative with a fixed host name and manages the runtime Port lifecycle.
  • Implement an initial hello handshake that sends a stable instance id, browser type, extension id, version, and capability flags to the native host.
  • Persist and reuse a random UUID instance id in chrome.storage.local to distinguish browser instances across restarts.
  • Whitelist allowed sendMessage methods and reject all other requested methods with a structured error response.
  • On incoming native requests, ensure the offscreen document is set up, forward the call to sendMessage with the provided params, and respond with either result or an error.
  • Implement disconnect handling with detection of fatal host errors (host missing/forbidden/exited) vs transient errors, and perform bounded exponential backoff reconnects only for transient errors.
  • Fail gracefully when connectNative throws (host not installed) by logging a debug message and leaving the rest of the extension behavior unchanged.
src/entries/background/utils/nativeMessaging.ts
Wire the native-messaging bridge into the background entry and grant required browser permission.
  • Import the nativeMessaging bridge module from the background main entry so that the connection is established when the background script runs.
  • Add the nativeMessaging permission to the extension permissions list in Vite config so the bridge can use chrome.runtime.connectNative.
src/entries/background/main.ts
vite.config.ts
Harden search logic against uninitialized configuration storage in the offscreen search utility.
  • Guard access to configStorage.searchEntity.autoDetectOfficialGroupFromTitle using optional chaining to avoid null/undefined dereferences when configStorage is not yet initialized.
src/entries/offscreen/utils/search.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@Rhilip
Copy link
Copy Markdown
Collaborator

Rhilip commented Mar 30, 2026

很有意思的玩法,也符合目前 AI+CLI 的大趋势。。

几点想法,供mr前参考:

  1. 建议使用 optional_permissions 来声明权限。虽然无论在 permissions 中还是在 optional_permissions 中申请权限,chrome商店那边都会让我们补充隐私权说明。但我觉得毕竟需要用户安装额外的cli工具来实现沟通,而且 mobile 环境中也不可能有相应的调用可能,因此不在基础权限中声明而是在可选权限中申请更为合理。
image
  1. 建议在 Settings 下面增加一个页面,用于调用 chrome.permissions.request 进行权限授权,启用、停止监听,插件侧连接性测试,进一步的也可以作为操作说明以及更为细粒度的method控制。

  2. 因为引入了新的权限,建议 bump version 下(虽然我0.0.5规划的内容还没有完成,但是没有关系哒~

@hui-shao
Copy link
Copy Markdown
Collaborator

Replace auto-connect-on-import with a full lifecycle manager:
- Checks chrome.permissions.contains before connecting
- Adds ptd_native_bridge_enabled storage flag (default true) for user control
- Explicit state machine: no-permission → disabled → connecting → connected → retrying → error
- Differentiates intentional vs unexpected disconnects (no retry vs backoff)
- Listens for chrome.permissions.onAdded/onRemoved for reactive updates
- Exposes nativeBridgeGetStatus, nativeBridgeSetEnabled, nativeBridgeReconnect message handlers
- Treats "host not found" / "forbidden" as fatal; "host exited" as recoverable with backoff
State should remain "connecting" after port creation until the first
valid message exchange confirms the host is responsive. The previous
code immediately set state to "connected" before any handshake
completed, giving a false positive in the UI.
…result

- Add MAX_RECONNECT_ATTEMPTS (10) to prevent infinite reconnect loops
  on unclassified permanent failures. After exhausting retries, state
  transitions to "error" requiring explicit user action to retry.
- Test Connection now polls for up to 5s after triggering reconnect,
  waiting for the async connection to settle before showing the result.
The native host daemon does not send an acknowledgment after receiving
the hello. Transition to connected after successful postMessage of the
hello handshake — if the host is absent, onDisconnect will correct the
state to error.
Firefox uses 'ptd install --browser firefox' without extension ID.
Chrome-family uses '--browser chrome --extension-id <id>'.
@LeiShi1313
Copy link
Copy Markdown
Collaborator Author

  • Native bridge 现在是optional permission
  • Setting页面增加了Native Bridge的选项
    Mac/Linux测试通过了,Windows的权限控制好像有点问题,明早起来我再看看

@LeiShi1313
Copy link
Copy Markdown
Collaborator Author

我蠢了,同时装了2个扩展所以通讯出问题了。起来再测下Edge,FireFox就差不多了

@socketcat
Copy link
Copy Markdown
Collaborator

感谢你的 PR,但是我对该 PR 的部分描述有一些疑惑:

这使得 PT-Depiler 从一个浏览器扩展进化为一个可编程的、可被 AI 驱动的 PT 站点管理平台。

我对 “可被 AI 驱动” 这个说辞持保留意见,不过我可以理解为此 PR 的核心意图是让 ptd 能通过 CLI 被外部程序(包括 AI Agent)调用,从而实现一定程度的自动化。但是社区内已有成熟的自动化抓取程序(*arr 生态),它们无需 OpenClaw / 外部脚本 即可编写自定义配置进行精确的自动化资源抓取。

相比之下,我认为一个需要下载额外 cli、自己编写脚本,甚至需要借助 AI Agent 的自动化方案的 配置复杂度成本 是高于现有生态的。我担心这可能会成为大多数 ptd 用户的一个伪需求。

如果本 PR 被接受,我很乐意将 ptd-cli 项目转移到 https://github.com/pt-plugins 组织下,作为 PT-Depiler 的官方 CLI 工具统一维护。

感谢你愿意把整个项目贡献出来,但是 ptd-cli 作为一个技术栈不同的外部程序,现有维护者对其的维护能力有限,我认为并不适合将其立即作为官方 CLI,目前这个 PR 把该 CLI 和扩展的功能绑定得比较紧,间接增加了扩展的维护成本。
 
我个人的意见是,可以先将该 PR 合并到一个 feature branch 里,等后续功能成熟、社区有真实反馈后再并入主线(如果当前维护节奏允许的话)。

以上仅为我个人看法,如有考虑不周的地方,欢迎指正和继续讨论。

@LeiShi1313
Copy link
Copy Markdown
Collaborator Author

@socketcat AI Agent对于个人用户来说,最大的便利不是自动化,是人机交互的革新,这次变革肯定不会亚于智能手机对人生活的改变。看看下面几个例子就能明白了
CleanShot 2026-03-31 at 08 05 12@2x
CleanShot 2026-03-31 at 08 14 46@2x
CleanShot 2026-03-31 at 08 18 30@2x

即使从自动化角度来说这种程度的智能和以前那种靠字符串拼接和靠豆瓣/imdb id做的匹配也完全不是一回事。配合OpenClaw的定时功能,用户可以很方便地追剧,追热剧,发两条消息就全搞定了。
当然这种能力也不是PTD的专属,你说的*arr、movepilot等也完全也可以cli化接入AI做到类似的功能。我自己早就已经直接把浏览器cli化给我常用的几个站点做了cli化,不靠PTD也可以让AI帮我下电影。但是PTD的优势是已经做了大部分PT站点的聚合和下载器的接入,一个接入点就可以把全链路打通,*arr生态因为把很多脏活干了,这些活现在AI都可以干,反而会比较尴尬。
有关接入成本和是否合并主线的考虑,我是这么想的:

  1. 这个功能在PTD插件上只体现在多了一个Native Bridge的开关,权限默认不开,对不需要的用户完全没有影响,对本体功能也没有任何侵入,所有调用的方法插件本身就支持,现在只是开放给外部程序了
  2. 关于ptd-cli的接入,对于已经搭好OpenClaw或者就是使用Claude Code/Codex的用户,所谓接入也可以让AI完全托管,只需要给ta ptd-cli的仓库地址,AI会自己阅读README,找到release的bianry下载,用户只需要后续把extension id告诉AI即可。复杂度仅存在在配置OpenClaw这种Agent上,如果是Claude Code/Codex则完全没有难度,一切都可以直接靠聊天实现
  3. 关于维护,整套代码都是AI vibe的,核心大概20分钟不到就走通了。AI coding是大势所趋,已经不太需要考虑人是不是有能力维护了,实在有顾虑,10分钟左右AI应该就能写出ts的实现,我是考虑到跨平台所以选择了Rust。我本人对Vue和Rust一窍不通 :)

@socketcat
Copy link
Copy Markdown
Collaborator

不知道怎么说,但我觉得你说的可能是有道理。PT 对每个人来说,意义不同。我不会尝试为某个人的用法做任何辩解,因为那是徒劳。我在乎的是,我在开发者之前,首先是用户,而我相信大多数用户在乎的不是潮流,而是安逸。而可控性是安全感的关键一环。如果你不认同,你可以选择无视,我不会阻挠。如果你认同,你可以试着重新思考一下。 差不多就这些

@Rhilip Rhilip self-assigned this Mar 31, 2026
if (__BROWSER__ === "firefox") {
return "ptd install --browser firefox";
}
return `ptd install --browser chrome --extension-id ${extensionId}`;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

提示命令只有 chrome ,如果 Chromium / Edge 的注册方法不同,需要额外增加浏览器类型判断(比如根据UA信息)

Comment on lines +17 to +25
type BridgeState = "no-permission" | "disabled" | "connecting" | "connected" | "retrying" | "error";

interface BridgeStatus {
permissionGranted: boolean;
enabled: boolean;
state: BridgeState;
connected: boolean;
lastError?: string;
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这块类型定义再 background/utils/nativeMessaging.ts , messages.ts 和 vue 模板等地方中重复声明了,都抽象出来,放在 shared/common 目录下,并在 shared/types.ts 中增加代理转发

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

getDownloaderList(): Array<{ id: string; name: string; type: string; enabled: boolean; address: string }>;

// 2.9 Native messaging bridge control
nativeBridgeGetStatus(): {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这些返回类型都抽象出来

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

加了BridgeStatus

];

/** Methods the bridge will proxy to sendMessage(). Everything else is rejected. */
const ALLOWED_METHODS = new Set([
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CLI 能够使用的 sendMessage methods 有必要进一步细分吗?比如按 site, search, download, userInfo, keepUpload 这种大类?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这现阶段应该问题不大,还没有那么多方法到让人困惑的地步

id,
name: nameMap[id] ?? "",
url: config.url ?? "",
offline: config.isOffline ?? false,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isOffline 并不一定能完全表示站点无法使用。 ISiteMetadata 定义中还声明了一个 isDead 的参数,在 offscreen 中可以通过 getDefinedSiteMetadata 方法获取到

  const siteMetaData = await getDefinedSiteMetadata(siteId);
  const isDeadSite = siteMetaData.isDead ?? false;

  const siteOffline = (isDeadSite || config.isOffline) ?? false;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

加上了

const nameMap = metadata?.siteNameMap ?? {};
return Object.entries(sites).map(([id, config]) => ({
id,
name: nameMap[id] ?? "",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果nameMap中没有,先回落到 config.merge?.name 如果这里还没有,建议使用 id,或者和下面一样从 siteMetaData 中拿,而不是取空字符串。即

{
   name: nameMap[id] ?? config.merge?.name ?? id 
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

改了


function getStatus() {
return {
permissionGranted,
Copy link
Copy Markdown
Collaborator

@Rhilip Rhilip Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

此处的 permissionGranted 建议动态获取,因为下面的 onAdded 以及 onRemoved 在重复授权的情况下不会触发,在极端条件下会导致已授权的在设置页面仍然显示未授权(需要reload插件解决)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

return id;
}

function getStatus() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

建议再增加一个 port 的状态,检查是不是为 null

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

加了

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a Chrome/Firefox Native Messaging bridge so an external CLI/agent can communicate with the extension’s background APIs (reusing existing login state, site definitions, and downloader config), plus a small offscreen null-guard fix and an options UI entry to manage the bridge permission/status.

Changes:

  • Add a background Native Messaging bridge with reconnect logic and a method whitelist.
  • Add options UI + i18n strings for granting/revoking nativeMessaging permission and viewing bridge status.
  • Add lightweight list endpoints (getSiteList, getDownloaderList) and fix a null access in offscreen search.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
vite.config.ts Declares nativeMessaging as an optional permission for both Chrome/Firefox builds.
src/locales/zh_CN.json Adds Settings tab label + Native Bridge UI translations (zh-CN).
src/locales/en.json Adds Settings tab label + Native Bridge UI translations (EN).
src/entries/options/views/Settings/SetBase/NativeBridgeWindow.vue New settings panel to request/revoke permission, toggle bridge, and test connection.
src/entries/options/views/Settings/SetBase/Index.vue Hides the global “Save” button for tabs that opt out (used by Native Bridge page).
src/entries/options/plugins/router.ts Adds the native-bridge settings route and redirects /settings/set-base.
src/entries/offscreen/utils/site.ts Adds getSiteList message handler for CLI discovery.
src/entries/offscreen/utils/download.ts Adds getDownloaderList message handler for CLI discovery.
src/entries/offscreen/utils/search.ts Guards configStorage access to prevent null/undefined crashes.
src/entries/messages.ts Extends ProtocolMap with list endpoints + native bridge control endpoints.
src/entries/background/utils/nativeMessaging.ts New Native Messaging bridge implementation (connect/handshake, whitelist proxying, reconnect, status/control handlers).
src/entries/background/main.ts Loads the new native messaging module in background startup.
package.json Bumps extension version to 0.0.6.

- Extract BridgeState/BridgeStatus to shared/types/common/nativeBridge.ts
- Dynamic permission check via chrome.permissions.contains() in getStatus()
- Port race safety: capture currentPort in connect(), guard all listeners
- Hello handshake error handling with try/catch and .catch()
- Validate boolean input in nativeBridgeSetEnabled
- Remove getExtStorage/getLogger from bridge allowlist (security)
- getSiteList: include isDead from site metadata, fallback name to id
- getDownloaderList: remove address field (may contain credentials)
- Browser detection via UA for setup command (chrome/chromium/edge/firefox)
@Rhilip
Copy link
Copy Markdown
Collaborator

Rhilip commented Apr 1, 2026

还要加点隐私权相关的说明。

privacy-statement.md 和 设置页面 NativeBridgeWindow.vue 中要加一下如果用户授权并启用 Native Message 功能后,允许相关实现的通过xxxx获取信息。

image image

…statement

- Restore address field in getDownloaderList per reviewer request
- Add Native Messaging privacy disclosure to privacy-statement.md (section 四)
- Add privacy notice in NativeBridgeWindow.vue info section
- i18n keys for privacy text in both en.json and zh_CN.json
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants