# SDK 开发入门

> 启动独立的 Chrovia 浏览器实例，创建 Provision 扩展，并调用第一个内核 JavaScript API。

Source: https://console.getchrovia.com/zh/docs/sdk-getting-started

Chrovia SDK 是带有扩展配置和 JavaScript API 的 Chromium 浏览器运行时。`chrovia` 对象由浏览器内置提供，不是需要在网站或 Node.js 应用中导入的 npm 包。

你的应用负责启动浏览器、准备实例文件。**Chrovia License** 授权能力，**Extended Preferences** 配置实例，**Provision 扩展**运行需要内核特权 API 的浏览器端逻辑。

## 1. 准备浏览器和 License

先按照[下载和安装试用 License](https://console.getchrovia.com/zh/docs/trial-license)获取浏览器压缩包和已签发的 License。本例需要勾选 **Extended Preferences**（`extendedPrefs`）。保留随浏览器附带的 **Chrovia Infra** 扩展，它负责需要在线授权的许可证的联网流程。

完整解压浏览器。不要修改已签名的 License 来增加能力，应重新申请包含所需能力的 License。

## 2. 选择实例目录

为测试实例创建独立目录，将已签发的许可证放入其中，文件名必须为 `Chrovia License`，不带扩展名：

```text
sdk-profile/
  Chrovia License
```

启动时通过 `--user-data-dir` 传入该目录的绝对路径。目录会保存这个实例的浏览器数据，包括 Cookie 和已保存的密码。不同的独立实例应使用不同目录。

浏览器优先读取用户数据目录中的 `Chrovia License`。只有该文件不存在时，才使用 Provision 根目录中的同名文件。用户数据目录中存在但无效的 License 不会回退到 Provision 副本。

如果 License 包含 `signedExtendedPrefs`，启动前还需要放入正确签名的 `Extended Preferences` 文件。如果只是测试不需要签名的配置，请申请不包含该能力的 License，不要从已签发的文件中自行删除它。详见 [Extended Preferences](https://console.getchrovia.com/zh/docs/sdk-extended-preferences)。

## 3. 添加 Provision 扩展

标准 Chrovia 发行包的 Provision 根目录，在 Windows 上是可执行文件旁的 `Chrovia` 文件夹，在 macOS 上是 `Chrovia.app/Contents/Chrovia`。自定义品牌发行包可能使用不同的目录名。

在 `Extensions` 下新增目录，保留原有文件和扩展：

```text
Chrovia/
  manifest.json
  Extensions/
    chrovia-infra/
    sdk-example/
      manifest.json
      background.js
```

根目录的 `manifest.json` 是发行包元数据。`sdk-example` 内的 `manifest.json` 才是 Chrome 扩展清单，内容如下：

```json
{
  "manifest_version": 3,
  "name": "SDK Example",
  "version": "1.0.0",
  "background": {
    "service_worker": "background.js"
  }
}
```

创建 `background.js`：

```js
const prefs = globalThis.chrovia?.prefs;

async function runExample() {
  if (!prefs) {
    console.error('SDK Example: extendedPrefs is unavailable');
    return;
  }

  await prefs.set('sdk_example.message', 'Hello from Chrovia SDK');
  console.log(await prefs.get('sdk_example.message'));
}

runExample().catch(console.error);
```

不需要在 Chrome 扩展清单中添加名为 `extendedPrefs` 的权限：它是 **License 能力**，不是扩展权限。标准 `chrome.*` API 和扩展中的网络请求仍需遵守各自的清单权限要求。

浏览器启动时自动加载 `Extensions` 直接子目录中的插件。更新插件时保持目录名不变，不需要点击**加载已解压的扩展程序**。

## 4. 启动并调试

更换文件或启动参数后，先完全退出测试实例，再重新启动。请按实际安装位置调整路径。

### Windows PowerShell

```powershell
& 'C:\SDK\Chrome-bin\chrovia.exe' --user-data-dir='C:\SDK\sdk-profile' --show-component-extension-options
```

### macOS 终端

```sh
./Chrovia.app/Contents/MacOS/Chrovia \
  --user-data-dir="$HOME/chrovia-sdk-profile" \
  --show-component-extension-options
```

打开 `chrome://extensions`，启用**开发者模式**，找到 **SDK Example** 并检查其 **Service Worker**。在该控制台运行：

```js
await chrovia.prefs.get('sdk_example.message')
```

预期返回 `Hello from Chrovia SDK`。上述调试参数用于显示组件扩展，正常运行不需要。请勿使用已通过 License 和配置禁用 DevTools 的实例进行本教程的调试。

## 代码运行位置很重要

默认只有 **Provision 扩展的 Service Worker** 能使用 `chrovia`，普通网页、扩展弹出窗口和扩展标签页都不能直接访问。弹出窗口应通过 `chrome.runtime.sendMessage` 请求自己的 Service Worker 执行具体操作。

`unrestrictedApi` 能力可以将 API 开放到页面上下文，但不会同时授予各个 API 的能力。本例不需要它。即使拥有 `unrestrictedApi`，`passwords` API 仍只对 Provision Service Worker 开放。

Service Worker 空闲时可能停止，之后再启动。应在每次脚本执行时注册监听和拦截逻辑，不要只放在 `chrome.runtime.onInstalled` 中。不要依赖全局变量跨越 Worker 重启保存状态。

## 开发循环与排查

1. 修改扩展，将构建后的 JavaScript 复制到实际启动的浏览器所使用的 Provision 目录。
2. 完全退出该浏览器实例，然后重新启动。
3. 检查扩展的 Service Worker，而不是网页或弹出窗口的控制台。

如果没有 `chrovia`，检查执行上下文和 Provision 位置。如果仅 `chrovia.prefs` 不存在，检查 License 是否包含 `extendedPrefs`。如果 API 存在但读取返回 `undefined`，检查键名、已安装的 License 和 Extended Preferences 签名。API 对象存在不代表在线租约授权一定正常。

可以从[下载页面](https://console.getchrovia.com/zh/download)获取 Chrovia Studio，运行各项能力的演示。有些 Studio 页面演示会申请 `unrestrictedApi`，不要将这种页面访问方式误认为 SDK 的默认集成方式。

接下来阅读 [SDK 文档与能力索引](https://console.getchrovia.com/zh/docs/sdk-capabilities)，其中包含 License、租约、EP、Provision、插件安装及各项能力的独立指南。
