使用上下文身份

许多人需要或希望使用多个身份在网络上进行交互。他们可能有用于工作和个人电子邮件的在线账户。他们可能会在访问在线购物之前退出社交媒体账户,以确保购物网站上的任何跟踪脚本无法获取其社交媒体活动。用户通常会使用一个标准的私密浏览器窗口或两个不同的浏览器来满足这些需求。

为了满足这一需求,Firefox 提供了一项名为“上下文身份”、“容器标签页”或“账户容器”的功能。此功能允许为用户希望在其浏览器中使用的每个身份创建 cookie 容器(存储)。标签页可以与其中一个身份相关联,从而将 cookie 与浏览器中其他身份的 cookie 分开。其实际效果是,例如,用户可以拥有一个个人身份和一个工作身份。然后,他们可以,例如,在一个标签页中使用个人身份登录他们的个人网页邮件,在另一个标签页中使用工作身份登录他们的工作网页邮件。

有关此功能的更多背景信息,请参阅

用于处理上下文身份的 API

根据您的扩展的性质,您可能需要管理上下文身份、将您的扩展操作的对象与上下文身份相关联,或两者兼有。

管理上下文身份

要管理上下文身份,您需要使用 contextualIdentities API。此 API 允许您添加、查询、更新和删除上下文身份。当您创建上下文身份时,它会被赋予一个唯一的 cookieStoreId。您可以使用此 ID 来处理与上下文身份相关的实体。

使用 cookieStoreId

几个扩展 API 在对象中包含 cookieStoreId,以允许扩展将这些对象与特定的上下文身份相关联。

Permissions

要使用 contextualIdentities API,您必须在您的 manifest.json 文件中包含“contextualIdentities” 权限

如果 API 允许修改 cookie,您需要“cookies”权限。例如,在 tabs.query 中使用 cookieStoreId 不需要“cookies”API,因为读取属性不会影响容器中的 cookie。但是,使用 tabs.create 需要该权限,因为打开的标签页可以读取和修改容器中的 cookie。

示例详解

示例扩展 contextual-identities 提供了一个带有弹出窗口的工具栏按钮,该弹出窗口列出了浏览器中的身份。对于每个身份,扩展都提供了使用其 cookie 容器创建标签页或移除其所有标签页的选项。

这是一个关于该扩展的简短视频

manifest.json

manifest.json 文件的一些主要功能是

  • 权限请求

    json
      "permissions": [
          "contextualIdentities",
          "cookies"
      ],
    
  • 工具栏按钮(browserAction)的规范,该按钮提供对扩展功能的访问

    json
      "browser_action": {
        "default_title": "Contextual Identities",
        "default_popup": "context.html",
        "default_icon": {
          "128": "identity.svg"
        }
    

context.html

工具栏按钮上的弹出窗口提供了扩展的用户界面。 context.html 实现此弹出窗口,但它只是一个外壳,context.js 脚本将在此外壳中写入上下文身份列表及其相关选项。

html
<body>
  <div class="panel">
    <div id="identity-list"></div>
  </div>
  <script src="context.js"></script>
</body>

context.js

该扩展的所有功能都通过 context.js 实现,每当工具栏弹出窗口显示时都会调用它。

脚本首先从 context.html 获取 'identity-list' <div>。然后检查上下文身份功能是否在浏览器中打开。如果未打开,则会将有关如何激活该功能的信息添加到弹出窗口中。

Firefox 安装时上下文身份功能是关闭的。当安装使用 contextualIdentities API 的扩展时,它会被打开。但是,用户也可以在首选项页面(about:preferences)上通过一个选项将其关闭,因此需要进行检查。

脚本现在使用 contextualIdentities.query 来确定浏览器中是否定义了任何上下文身份。如果没有,则会将一条消息添加到弹出窗口中,脚本将停止。

js
const div = document.getElementById("identity-list");
if (browser.contextualIdentities === undefined) {
  div.innerText =
    "browser.contextualIdentities not available. Check that the privacy.userContext.enabled pref is set to true, and reload the add-on.";
} else {
  browser.contextualIdentities.query({}).then((identities) => {
    if (!identities.length) {
      div.innerText = "No identities returned from the API.";
      return;
    }
    for (const identity of identities) {
      const row = document.createElement("div");
      const span = document.createElement("span");
      span.className = "identity";
      span.innerText = identity.name;
      span.style = `color: ${identity.color}`;
      console.log(identity);
      row.appendChild(span);
      createOptions(row, identity);
      div.appendChild(row);
    }
  });
}

如果存在上下文身份(Firefox 带有四个默认身份),脚本会循环遍历每个身份,将其名称(以其选定的颜色样式显示)添加到 <div> 元素中。然后 createOptions() 函数将“创建”或“关闭所有”的选项添加到 <div> 中,然后再将其添加到弹出窗口。

js
function createOptions(node, identity) {
  for (const option of ["Create", "Close All"]) {
    const a = document.createElement("a");
    a.href = "#";
    a.innerText = option;
    a.dataset.action = option.toLowerCase().replace(" ", "-");
    a.dataset.identity = identity.cookieStoreId;
    a.addEventListener("click", eventHandler);
    node.appendChild(a);
  }
}

脚本现在等待用户在弹出窗口中选择一个选项。

如果用户点击为某个身份创建标签页的选项,则会使用 tabs.create 通过传递该身份的 cookie 存储 ID 来打开一个标签页。

如果用户选择关闭该身份的所有标签页的选项,脚本将执行一次 tabs.query 来获取使用该身份的 cookie 存储的所有标签页。然后脚本将此标签页列表传递给 tabs.remove

js
function eventHandler(event) {
  if (event.target.dataset.action === "create") {
    browser.tabs.create({
      url: "about:blank",
      cookieStoreId: event.target.dataset.identity,
    });
  }

  if (event.target.dataset.action === "close-all") {
    browser.tabs
      .query({
        cookieStoreId: event.target.dataset.identity,
      })
      .then((tabs) => {
        browser.tabs.remove(tabs.map((i) => i.id));
      });
  }
  event.preventDefault();
}

了解更多

如果您想了解有关 contextualIdentities API 的更多信息,请查看