Browser Extension v3 开发常见需求

extension
Created 9/17/2022
Updated 4/17/2023

Browser Extension v3 开发常见需求

标签页

参考

Chrome 提供以 chrome.tabs 为前缀的 API,它们是与标签页相关方法

这些方法一般会返回一个标签对象 Tab,它包含以下常用的属性

  • active 属性:布尔值,该标签是否为(其所在的窗口中的)当前激活的标签页
  • audible(可选)属性:布尔值,标签页是否在过去几秒内产生了声音(如果有声音播放,会在该标签页的右侧显示一个扬声器图标 🔈)
  • mutedInfo(可选)属性:对象,标签页是否被静音了以及静音的理由
  • favIconUrl(可选)属性:字符串,标签页所显示的网址的 favicon 图标 URL。如果要访问该属性,需要在扩展出现的配置清单 manifest.json 的配置项 permissions 中声明 tabs 权限。如果标签页正在加载网页时,该属性值可能是一个空字符串
  • groupId 属性:数值,标签页所属的标签组
  • width(可选)属性:数值,标签页的宽度,单位是像素 px
  • height(可选)属性:数值,标签页的高度,单位是像素 px
  • id(可选)属性:数值,在浏览器窗口中,每一个标签页的 ID 都是独特唯一的,但有些情况下,例如使用 sessions API 查询标签页时,标签对象并会分配到一个 ID 值
  • incognito 属性:布尔值,标签页是否在隐身模式中
  • index 属性:数值,标签页在浏览器窗口中的位置,索引从 0 开始
  • title(可选)属性:字符串,标签页所显示网页的标题。如果要访问该属性,需要在扩展出现的配置清单 manifest.json 的配置项 permissions 中声明 tabs 权限。
  • url(可选)属性:字符串,标签页所显示网页的 URL。需要在扩展出现的配置清单 manifest.json 的配置项 permissions 中声明 tabs 权限。
提示

在开发与标签页相关的扩展程序时,一般还会使用 bookmarks 书签相关的 API

在 Manifest V3 版本的扩展程序中,Chrome 新增了以 chrome.tabGroups 为前缀的 API,它们是与标签组相关的方法

这些方法一般会返回一个标签组对象 TabGroup,它包含以下常用属性

  • collapsed 属性:布尔值,标签组折叠或展开
  • color 属性:字符串,标签组所标记的颜色,可以是 greyblueredyellowgreenpinkpurplecyan 这 8 个值之一
  • id 属性:数值,标签组的 ID 唯一标识符
  • title(可选)属性:字符串,标签组的名称
  • windowId 属性:数值,标签组所在的浏览器窗口的 ID 唯一标识符

创建一个新标签页

使用方法 chrome.tabs.create(createProperties: object) 创建一个新标签,它是一个异步函数,立即返回的是一个 Promise,最终返回的是所创建的标签对象 Tab

该方法接受一个与标签相关的配置对象作为入参,该对象常用属性如下:

  • active 布尔值(可选),新建的标签是否作为当前激活标签页
  • index 数值(可选),新建标签在当前窗口中的所有标签页的次序,索引从 0 开始
  • url 字符串(可选),新建标签页后访问给定的 URL
  • windowId 数值(可选),在指定的窗口中新建标签页,默认是在当前激活的窗口中打开
js
// 借助 Chrome 提供的 API,封装一个新建标签页的方法
// 它接收一个参数 active,用以控制是否将新建的标签页作为当前激活的标签页
const createNewTab = async (active = true) => {
  const newTab = await chrome.tabs.create({
    active,
  });
  return newTab;
};

获取当前激活的标签页

使用方法 chrome.tabs.query(queryInfo: object) 获取符合(查询)条件的所有标签页,它是一个异步函数,立即返回的是一个 Promise,最终返回的是所有符合条件的标签对象 Tab 数组

js
// 借助 Chrome 提供的 API,封装一个获取当前激活的标签页的方法
const getActiveTab = async () => {
  // 匹配条件是 currentWindow 当前窗口的 active 激活的标签页
  // 该方法返回的是一个数组
  // 但是激活的标签页只有一个,因此可以使用解构获取该数组唯一的一个元素
  const [tab] = await chrome.tabs.query({
    active: true,
    currentWindow: true,
  });
  return tab;
};

获取所有标签组

使用方法 chrome.tabGroups.query(queryInfo: object) 获取符合(查询)条件的所有标签组,它是一个异步函数,立即返回的是一个 Promise,最终返回的是所有符合条件的标签组对象 TabGroup 数组

js
// 借助 Chrome 提供的 API,封装一个获取当前窗口中所有标签组的方法
const getAllTabGroups = async () => {
  const tabGroups = await chrome.tabGroups.query({
    // 通过 Chrome 内置对象的属性 chrome.windows.WINDOW_ID_CURRENT 获取当前窗口的 ID 唯一标识符
    windowId: chrome.windows.WINDOW_ID_CURRENT,
  });
  return tabGroups;
};

在标签组中创建标签页

使用方法 chrome.tabs.group(options: object) 将给定的(一个或多个)标签添加到指定标签组中,它是一个异步函数,立即返回的是一个 Promise,最终返回的是该标签组 TabGroup 的 ID 唯一标识符。

该方法接受一个配置对象作为入参,该对象常用属性如下:

  • createProperties 该(可选)属性的值是一个对象,该对象只包含一个(可选)属性 windowId,以指定需要在哪一个窗口新建一个标签组,默认在当前窗口新建标签组
    注意

    如果在配置对象中指定了另一个属性 groupId,则忽略该属性

  • groupId 数值(可选),指定将标签添加到哪一个标签组中,如果指定的标签组并不存在,就会创建一个新的标签组
  • tabIds 数值或数组,通过标签的 ID 指定某个标签,或一系列标签
提示

通过以上方法新建标签组时,并不能指定标签组的颜色和标题,可以采用以下方式「曲线救国」

先通过上述方法创建一个默认的新标签组(颜色是灰色 gray,默认名称为空)

再使用方法 chrome.tabGroups.update(groupId: number, updateProperties: object) 更新标签组的属性,该方法接收两个入参:

  • 第一个参数是标签组 ID,用以指定需要修改哪一个标签组
  • 第二个参数是一个对象用以设置所需更新的内容,可以包含以下属性:
    • collapsed 布尔值(可选),标签组折叠或展开
    • color 字符串,标签组所标记的颜色,可以是 greyblueredyellowgreenpinkpurplecyan 这 8 个值之一
    • title 字符串(可选),标签组的名称
js
// 借助 Chrome 提供的 API,封装一个将指定标签添加到标签组的方法
// 该方法接收两个参数,第一个参数是所需移动到标签组内的标签页的 ID,第二个参数是该标签组的一些属性(颜色和名称)
const createTabInGroup = async (tabId, group) => {
  // 先使用给定的标签 ID 创建一个新的标签组
  const groupId = await chrome.tabs.group({
    tabIds: tabId,
  });
  // 再更新该标签组的颜色和名称
  await chrome.tabGroups.update(groupId, {
    color: group.color,
    title: group.title,
  });

  return groupId;
};

书签

参考

书签是指将网址收藏在浏览器的收藏夹中,便于日后再访问。

可以通过点击浏览器地址栏右侧的星型图标 ⭐ 将当前网页收藏起来

bookmark
bookmark

在地址栏输入 chrome://bookmarks/ 打开书签管理器,可以对书签进行批量操作管理。

提示

如果开发书签相关的扩展程序,还可以考虑 Override Pages 覆写书签管理页面,以提供更多样的功能

在浏览器中,众多的书签是以树型数据结构进行存储管理的,该数据结构中的基本单位是节点 BookmarkTreeNode,它有两种类型:

  • 书签 bookmark,它是叶子节点,即其下没有再细分的子节点
  • 文件夹 folder,也称作组 group,在其下可以包含子节点

Chrome 提供以 chrome.bookmarks 为前缀的 API,它们是与书签相关方法

提示

在使用相关 API 时需要在扩展出现的配置清单 manifest.json 的配置项 permissions 中声明 bookmarks 权限

这些方法里一般返回一个书签节点对象 BookmarkTreeNode,它包含以下常用的属性:

  • children(可选)属性:数组,一个包含了子节点的数组(当节点是书签时就没有该属性)
  • dateAdded(可选)属性:数值,节点创建的时间,以毫秒为计算单位,可以通过方法 new Date(dateAdded) 获取 JS Date 对象
  • dateGroupModified (可选)属性:数值,如果节点是文件夹时,该数值表示文件夹内容修改的最后时间点
  • id 属性:字符串,它是节点的唯一标识符,在浏览器的书签「树」中每一个节点的 ID 都是唯一的
  • index(可选)属性:数值,该节点在其父文件夹中的排序,索引从 0 开始
  • parentId(可选)属性:字符串,表示父级文件夹的唯一标识符(当节点是根文件夹时,没有该属性)
  • url(可选)属性:字符串,当节点是书签时具有该属性,点击该书签会导航到指定的网页地址

打开书签

使用方法 chrome.bookmarks.get(idOrIdList: string | string[]) 获取特定的书签节点,或多个书签节点组成的数组,它是一个异步函数,立即返回的是一个 Promise,最终返回的是相应的书签节点 BookmarkTreeNode(或数组)

js
// 借助 Chrome 提供的 API,封装一个打开书签的方法
// 该方法接收三个参数
// * 第一个参数是所需打开的书签节点的 ID 值
// * 第二个参数是打开的模式,可以是 new 或 current,分别是指在新建标签页打开书签,或在当前标签页打开书签
// * 第三个参数是对于新增标签页的情况,是否将该标签页设置为当前激活标签页
const openBookmark = (nodeId, mode = 'new', active = true) => new Promise((resolve, reject) => {
    // 根据节点 ID 获取书签
    chrome.bookmarks.get(nodeId)
    .then(async (nodes) => {
      const { url } = nodes[0];
      // 根据参数判断以哪一个标签页打开书签
      let tab;
      if (mode === 'new') {
        // open on new tab
        tab = await createNewTab(active);
      } else if (mode === 'current') {
        // open on current active tab
        tab = await getActiveTab();
      }
      // 通过更新标签页的属性 URL 的方式打开书签
      await chrome.tabs.update(tab.id, {
        url,
      });
      resolve(tab);
    });
});

const createNewTab = async (active = true) => {
  const newTab = await chrome.tabs.create({
    active,
  });
  return newTab;
};

const getActiveTab = async () => {
  // 匹配条件是 currentWindow 当前窗口的 active 激活的标签页
  // 由于该方法返回的是一个数组,但是激活的标签页只有一个,因此可以使用解构获取该数组唯一的一个元素
  const [tab] = await chrome.tabs.query({
    active: true,
    currentWindow: true,
  });
  return tab;
};

创建书签

使用方法 chrome.bookmarks.create(bookmark: CreateDetails) 创建一个书签节点,它可以是一个书签或一个文件夹(如果入参的配置对象省略了属性 url 或该属性值为 NULL),它是一个异步函数,立即返回的是一个 Promise,最终返回的是书签节点 BookmarkTreeNode

该方法接受一个配置对象作为入参,该对象常用属性如下:

  • index(可选)属性:数值,指定新增的书签节点在其父节点中的排序
  • parentId(可选)属性:字符串,指定新增的书签是在哪一个父节点之下,默认是以 📁 Other bookmarks 「其他书签」文件夹作为父节点
  • title(可选)属性:字符串,书签节点的名称
  • url(可选)属性:字符串,书签节点的网址(如果新增的节点是文件夹时,省略该属性)

由于书签以树型数据结构进行存储管理,因此创建书签节点时,需要向上述方法传递配置对象,指定新增的节点是在哪一个父节点之下的

js
// 在文件夹 bookmarkBar 之下,新增一个名为 new folder 书签节点,它是一个文件夹
chrome.bookmarks.create({
  'parentId': bookmarkBar.id,
  'title': 'new folder'
}).then(folder => {
  console.log("added folder: " + newFolder.title);
})

// 新增一个书签,名称为 Google
chrome.bookmarks.create({
  'parentId': FolderId,
  'title': 'Google',
  'url': 'https://www.google.com.hk/',
});

Copyright © 2024 Ben

Theme BlogiNote

Icons from Icônes