browser.storage

说明

使用 chrome.storage API 存储、检索和跟踪用户数据的更改。

权限

storage

如需使用 Storage API,请在扩展程序清单中声明 "storage" 权限。例如:

{
  "name": "My extension",
  ...
  "permissions": [
    "storage"
  ],
  ...
}

示例

以下示例演示了 local、sync 和 session 存储区域:

示例(本地)

await browser.storage.local.set({ key: value });
console.log("Value is set");
const result = await browser.storage.local.get(["key"]);
console.log("Value is " + result.key);

示例(同步)

await browser.storage.sync.set({ key: value });
console.log("Value is set");
const result = await browser.storage.sync.get(["key"]);
console.log("Value is " + result.key);

示例(会话)

await browser.storage.session.set({ key: value });
console.log("Value is set");
const result = await browser.storage.session.get(["key"]);
console.log("Value is " + result.key);

如需查看 Storage API 的其他演示,请浏览以下任一示例:

概念和用法

Storage API 提供了一种特定于扩展程序的方式来保留用户数据和状态。它类似于 Web 平台的存储 API(IndexedDB 和 Storage),但旨在满足扩展程序的存储需求。以下是一些关键功能:

  • 所有扩展程序上下文(包括扩展程序 Service Worker 和内容脚本)都可以访问 Storage API。
  • 可序列化的 JSON 值会存储为对象属性。
  • Storage API 是异步的,支持批量读写操作。
  • 即使用户清除缓存和浏览记录,这些数据也会保留。
  • 即使使用拆分无痕模式,存储的设置也会保留。
  • 包含一个专供企业政策使用的只读受管理存储区域。

扩展程序可以使用 Web 存储 API 吗?

虽然扩展程序可以在某些上下文(弹出式窗口和其他 HTML 页面)中使用 Storage 接口(可从 window.localStorage 访问),但我们不建议这样做,原因如下:

  • 扩展程序 Service Worker 无法使用 Web Storage API。
  • 内容脚本与托管网页共享存储空间。
  • 当用户清除浏览记录时,使用 Web Storage API 保存的数据会丢失。

如需从 Service Worker 将数据从 Web 存储空间 API 移至扩展程序存储空间 API,请执行以下操作:

  1. 准备屏幕外文档 HTML 页面和脚本文件。脚本文件应包含转换例程和 onMessage 处理程序。
  2. 在扩展程序 Service Worker 中,检查 browser.storage 是否有您的数据。
  3. 如果未找到您的数据,请致电 createDocument()。
  4. 返回的 Promise 解析后,调用 sendMessage() 以启动转换例程。
  5. 在屏幕外文档的 onMessage 处理程序中,调用转换例程。

Web 存储 API 在扩展程序中的运作方式也存在一些细微差别。如需了解详情,请参阅存储和 Cookie 一文。

存储空间和限制

Storage API 具有以下用量限额:

  • 存储数据会产生性能开销,并且该 API 设有存储空间配额。规划您要存储的数据,以便维护存储空间。
  • 存储空间可能需要一些时间才能完成。请合理安排代码结构,以便将这段时间考虑在内。

如需详细了解存储区域限制以及超出限制后会出现什么情况,请参阅 sync、local 和 session 的配额信息。

存储区域

Storage API 分为以下存储区域:

局部

数据会存储在本地,并在扩展程序被移除时一并清除。存储空间上限为 10 MB(在 Chrome 113 及更早版本中为 5 MB),但可以通过请求 "unlimitedStorage" 权限来提高。我们建议使用 storage.local 存储大量数据。默认情况下,它会向内容脚本公开,但您可以通过调用 browser.storage.local.setAccessLevel() 来更改此行为。

代管

对于通过政策安装的扩展程序,托管式存储空间是只读的。它由系统管理员使用开发者定义的架构和企业政策进行管理。政策与选项类似,但由系统管理员(而非用户)配置。这样,您就可以为组织中的所有用户预先配置该扩展程序。

默认情况下,storage.managed 会向内容脚本公开,但可以通过调用 browser.storage.managed.setAccessLevel() 来更改此行为。如需了解政策,请参阅面向管理员的文档。如需详细了解 managed 存储区域,请参阅存储区域清单。

会话

会话存储空间会在扩展程序加载时将数据保存在内存中。如果扩展程序被停用、重新加载、更新,以及浏览器重启,存储空间就会被清除。默认情况下,它不会向内容脚本公开,但可以通过调用 browser.storage.session.setAccessLevel() 来更改此行为。存储空间上限为 10 MB(在 Chrome 111 及更早版本中为 1 MB)。

storage.session 接口是我们建议 Service Worker 使用的多个接口之一。

同步

如果用户启用同步功能,则数据会与用户登录的每个 Chrome 浏览器同步。如果停用,其行为将类似于 storage.local。当浏览器处于离线状态时,Chrome 会将数据存储在本地,并在恢复在线状态后继续同步。配额限制约为 100 KB,每项 8 KB。

我们建议使用 storage.sync,以便在同步的浏览器中保留用户设置。如果您要处理敏感用户数据,请改用 storage.session。默认情况下,storage.sync 会向内容脚本公开,但可以通过调用 browser.storage.sync.setAccessLevel() 来更改此行为。

方法和事件

所有存储区域都实现了 StorageArea 接口。

get()

借助 get() 方法,您可以从 StorageArea 中读取一个或多个键。

getBytesInUse()

借助 getBytesInUse() 方法,您可以查看 StorageArea 使用的配额。

getKeys()

借助 getKeys() 方法,您可以获取存储在 StorageArea 中的所有密钥。

remove()

您可以使用 remove() 方法从 StorageArea 中移除内容。

set()

您可以使用 set() 方法在 StorageArea 中设置项。

setAccessLevel()

借助 setAccessLevel() 方法,您可以控制对 StorageArea 的访问权限。

clear()

借助 clear() 方法,您可以清除 StorageArea 中的所有数据。

onChanged

借助 onChanged 事件,您可以监控 StorageArea 的变化。

使用场景

以下部分演示了 Storage API 的常见应用场景。

响应存储空间更新

如需跟踪对存储空间所做的更改,请向其 onChanged 事件添加监听器。当存储空间发生任何变化时,该事件就会触发。示例代码会监听以下更改:

background.js:

browser.storage.onChanged.addListener((changes, namespace) => {
  for (let [key, { oldValue, newValue }] of Object.entries(changes)) {
    console.log(
      `Storage key "${key}" in namespace "${namespace}" changed.`,
      `Old value was "${oldValue}", new value is "${newValue}".`
    );
  }
});

我们还可以进一步拓展这一思路。在此示例中,我们有一个选项页面,可让用户切换“调试模式”(此处未显示实现)。选项页面会立即将新设置保存到 storage.sync,而 Service Worker 会使用 storage.onChanged 尽快应用该设置。

options.html:

<!-- type="module" allows you to use top level await -->
<script defer src="options.js" type="module"></script>
<form id="optionsForm">
  <label for="debug">
    <input type="checkbox" name="debug" id="debug">
    Enable debug mode
  </label>
</form>

options.js:

// In-page cache of the user's options
const options = {};
const optionsForm = document.getElementById("optionsForm");

// Immediately persist options changes
optionsForm.debug.addEventListener("change", (event) => {
  options.debug = event.target.checked;
  browser.storage.sync.set({ options });
});

// Initialize the form with the user's option settings
const data = await browser.storage.sync.get("options");
Object.assign(options, data.options);
optionsForm.debug.checked = Boolean(options.debug);

background.js:

function setDebugMode() { /* ... */ }

// Watch for changes to the user's options & apply them
browser.storage.onChanged.addListener((changes, area) => {
  if (area === 'sync' && changes.options?.newValue) {
    const debugMode = Boolean(changes.options.newValue.debug);
    console.log('enable debug mode?', debugMode);
    setDebugMode(debugMode);
  }
});

从存储空间异步预加载

由于 Service Worker 并非始终运行,因此 Manifest V3 扩展程序有时需要在执行事件处理脚本之前从存储空间异步加载数据。为此,以下代码段使用了一个异步 action.onClicked 事件处理脚本,该脚本会等待 storageCache 全局变量填充完毕,然后再执行其逻辑。

background.js:

// Where we will expose all the data we retrieve from storage.sync.
const storageCache = { count: 0 };
// Asynchronously retrieve data from storage.sync, then cache it.
const initStorageCache = browser.storage.sync.get().then((items) => {
  // Copy the data retrieved from storage into storageCache.
  Object.assign(storageCache, items);
});

browser.action.onClicked.addListener(async (tab) => {
  try {
    await initStorageCache;
  } catch (e) {
    // Handle error that occurred during storage initialization.
  }

  // Normal action handler logic.
  storageCache.count++;
  storageCache.lastTabId = tab.id;
  browser.storage.sync.set(storageCache);
});

开发者工具

您可以在开发者工具中查看和修改使用该 API 存储的数据。如需了解详情,请参阅开发者工具文档中的查看和修改扩展程序存储空间页面。

类型

AccessLevel

Chrome 102 及更高版本 browser.*(自 Chrome 148 起)

存储区域的访问权限级别。

枚举

"TRUSTED_CONTEXTS"
指定源自扩展程序本身的上下文。

"TRUSTED_AND_UNTRUSTED_CONTEXTS"
指定源自扩展程序外部的上下文。

StorageChange

属性

  • newValue

    any 可选

    该项的新值(如果有)。

  • oldValue

    any 可选

    该项的旧值(如果有)。

属性

local

local 存储区中的内容仅存储在每台机器的本地。

类型

StorageArea 和对象

属性

  • QUOTA_BYTES

    10485760

    本地存储空间中可存储的数据量上限(以字节为单位),通过每个值的 JSON 字符串化加上每个键的长度来衡量。如果扩展程序具有 unlimitedStorage 权限,系统将忽略此值。如果更新会导致超出此限制,则会立即失败,并在使用回调时设置 runtime.lastError,或在使用 async/await 时返回被拒绝的 Promise。

managed

managed 存储区域中的内容由网域管理员配置的企业政策设置,对扩展程序而言是只读的;尝试修改此命名空间会导致错误。如需了解如何配置政策,请参阅存储区域清单。

类型

session

Chrome 102 及更高版本 browser.*(自 Chrome 148 起) MV3 及更高版本

session 存储区域中的内容会存储在内存中,不会持久保存到磁盘。

类型

StorageArea 和对象

属性

  • QUOTA_BYTES

    10485760

    可通过估算每个值和键的动态分配内存用量来衡量可存储在内存中的数据量上限(以字节为单位)。如果更新会导致超出此限制,则会立即失败,并在使用回调时或 Promise 被拒绝时设置 runtime.lastError。

sync

sync 存储区域中的内容会通过 Chrome 同步功能进行同步。

类型

StorageArea 和对象

属性

  • MAX_ITEMS

    512

    同步存储区中可存储的最大项数。如果更新会导致超出此限制,则会立即失败,并在使用回调时或 Promise 被拒绝时设置 runtime.lastError。

  • MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE

    1000000

    已弃用

    storage.sync API 不再有持续写入操作配额。

  • MAX_WRITE_OPERATIONS_PER_HOUR

    1800

    每小时可执行的 set、remove 或 clear 操作的数量上限。即每 2 秒 1 次,低于短期内较高的每分钟写入次数上限。

    如果更新会导致超出此限制,则会立即失败,并在使用回调时或 Promise 被拒绝时设置 runtime.lastError。

  • MAX_WRITE_OPERATIONS_PER_MINUTE

    120

    每分钟可执行的 set、remove 或 clear 操作数上限。此限制为每秒 2 次,在较短的时间内提供比每小时写入次数更高的吞吐量。

    如果更新会导致超出此限制,则会立即失败,并在使用回调时或 Promise 被拒绝时设置 runtime.lastError。

  • QUOTA_BYTES

    102400

    同步存储空间中可存储的数据总量上限(以字节为单位),通过每个值的 JSON 字符串化加上每个键的长度来衡量。如果更新会导致超出此限制,则会立即失败,并在使用回调时或 Promise 被拒绝时设置 runtime.lastError。

  • QUOTA_BYTES_PER_ITEM

    8192

    同步存储区中每个单独项的大小上限(以字节为单位),通过其值的 JSON 字符串化加上其键长度来衡量。如果更新包含大于此限制的项,则会立即失败,并在使用回调时或 Promise 被拒绝时设置 runtime.lastError。

事件

onChanged

browser.storage.onChanged.addListener(
  callback: function,
)

当一个或多个内容发生更改时触发。

参数

  • callback

    函数

    callback 参数如下所示:

    (changes: object, areaName: string) => void

    • 更改

      对象

    • areaName

      字符串