将脚本注入到当前活动的标签页中

点击扩展程序工具栏图标,简化当前网页的样式。

概览

本教程将构建一个扩展程序,用于简化 Chrome 扩展程序和 Chrome 应用商店文档页面的样式,以便用户更轻松地阅读。

在本指南中,我们将介绍如何执行以下操作:

  • 将扩展程序服务 worker 用作事件协调者。
  • 通过 "activeTab" 权限保护用户隐私。
  • 在用户点击扩展程序工具栏图标时运行代码。
  • 使用 Scripting API 插入和移除样式表。
  • 使用键盘快捷键执行代码。

前期准备

本指南假定您具备基本的 Web 开发经验。我们建议您查看 Hello World,了解扩展程序开发工作流程。

构建扩展程序

首先,创建一个名为 focus-mode 的新目录,用于存放扩展程序的文件。如果您愿意,可以从 GitHub 下载完整源代码。

第 1 步:添加扩展程序数据和图标

创建一个名为 manifest.json 的文件,并添加以下代码。

{
  "manifest_version": 3,
  "name": "Focus Mode",
  "description": "Enable focus mode on Chrome's official Extensions and Chrome Web Store documentation.",
  "version": "1.0",
  "icons": {
    "16": "images/icon-16.png",
    "32": "images/icon-32.png",
    "48": "images/icon-48.png",
    "128": "images/icon-128.png"
  }
}

如需详细了解这些清单键,请参阅“在每个标签页上运行脚本”教程,其中详细介绍了扩展程序的metadata图标

创建一个 images 文件夹,然后将下载的图标下载到该文件夹中。

第 2 步:初始化扩展程序

扩展程序可以使用扩展程序的服务工作器在后台监控浏览器事件。Service Worker 是一种特殊的 JavaScript 环境,用于处理事件,并在不需要时终止。

首先,在 manifest.json 文件中注册 Service Worker:

{
  ...
  "background": {
    "service_worker": "background.js"
  },
  ...
}

创建一个名为 background.js 的文件,并添加以下代码:

chrome.runtime.onInstalled.addListener(() => {
  chrome.action.setBadgeText({
    text: "OFF",
  });
});

我们的服务工件将监听的第一个事件是 runtime.onInstalled()。借助此方法,扩展程序可以在安装时设置初始状态或完成一些任务。扩展程序可以使用 Storage APIIndexedDB 存储应用状态。不过,在本例中,由于我们只处理两种状态,因此将使用操作的标记文本本身来跟踪扩展程序是处于“开启”还是“关闭”状态。

第 3 步:启用扩展程序操作

扩展程序操作用于控制扩展程序的工具栏图标。因此,每当用户点击扩展程序图标时,扩展程序都会运行一些代码(如本例所示)或显示弹出式窗口。添加以下代码以在 manifest.json 文件中声明扩展程序操作:

{
  ...
  "action": {
    "default_icon": {
      "16": "images/icon-16.png",
      "32": "images/icon-32.png",
      "48": "images/icon-48.png",
      "128": "images/icon-128.png"
    }
  },
  ...
}

使用 activeTab 权限保护用户隐私

activeTab 权限可授予扩展程序在有效标签页上临时执行代码的权限。它还允许访问当前标签页的敏感属性

当用户调用扩展程序时,系统会启用此权限。在这种情况下,用户通过点击扩展程序操作来调用扩展程序。

💡? 在我的扩展程序中,哪些其他用户互动会启用 activeTab 权限?

  • 按键盘快捷键组合。
  • 选择上下文菜单项。
  • 接受 Omnibox 中的建议。
  • 打开扩展程序弹出式窗口。

借助 "activeTab" 权限,用户可以有目的地选择在聚焦的标签页上运行扩展程序;这样一来,就可以保护用户的隐私。另一个好处是,它不会触发权限警告

如需使用 "activeTab" 权限,请将其添加到清单的权限数组中:

{
  ...
  "permissions": ["activeTab"],
  ...
}

第 4 步:跟踪当前标签页的状态

用户点击扩展程序操作后,该扩展程序会检查网址是否与文档页面匹配。接下来,它会检查当前标签页的状态并设置下一个状态。将以下代码添加到 background.js

const extensions = 'https://developer.chrome.com/docs/extensions';
const webstore = 'https://developer.chrome.com/docs/webstore';

chrome.action.onClicked.addListener(async (tab) => {
  if (tab.url.startsWith(extensions) || tab.url.startsWith(webstore)) {
    // Retrieve the action badge to check if the extension is 'ON' or 'OFF'
    const prevState = await chrome.action.getBadgeText({ tabId: tab.id });
    // Next state will always be the opposite
    const nextState = prevState === 'ON' ? 'OFF' : 'ON';

    // Set the action badge to the next state
    await chrome.action.setBadgeText({
      tabId: tab.id,
      text: nextState,
    });
  }
});

第 5 步:添加或移除样式表

现在,我们来更改页面的布局。创建一个名为 focus-mode.css 的文件,并添加以下代码:

* {
  display: none !important;
}

html,
body,
*:has(article),
article,
article * {
  display: revert !important;
}

[role='navigation'] {
  display: none !important;
}

article {
  margin: auto;
  max-width: 700px;
}

使用 Scripting API 插入或移除样式表。首先,在清单中声明 "scripting" 权限:

{
  ...
  "permissions": ["activeTab", "scripting"],
  ...
}

最后,在 background.js 中添加以下代码以更改页面的布局:

  ...
    if (nextState === "ON") {
      // Insert the CSS file when the user turns the extension on
      await chrome.scripting.insertCSS({
        files: ["focus-mode.css"],
        target: { tabId: tab.id },
      });
    } else if (nextState === "OFF") {
      // Remove the CSS file when the user turns the extension off
      await chrome.scripting.removeCSS({
        files: ["focus-mode.css"],
        target: { tabId: tab.id },
      });
    }
  }
});

💡? 我可以使用 Scripting API 注入代码,而不是样式表吗?

可以。您可以使用 scripting.executeScript() 注入 JavaScript。

可选:分配键盘快捷键

为方便起见,我们添加了一个快捷方式,以便更轻松地启用或停用专注模式。将 "commands" 键添加到清单中。

{
  ...
  "commands": {
    "_execute_action": {
      "suggested_key": {
        "default": "Ctrl+B",
        "mac": "Command+B"
      }
    }
  }
}

"_execute_action" 按键会运行与 action.onClicked() 事件相同的代码,因此无需额外的代码。

测试是否生效

验证项目的文件结构是否如下所示:

专注模式文件夹的内容:manifest.json、background.js、focus-mode.css 和 images 文件夹。

在本地加载扩展程序

如需在开发者模式下加载未封装的扩展程序,请按照 Hello World 中的步骤操作。

在文档页面上测试扩展程序

首先,打开以下任一页面:

然后,点击相应扩展程序操作。如果您设置了键盘快捷键,可以按 Ctrl + BCmd + B 对其进行测试。

它应如下所示:

专注模式扩展功能处于关闭状态
关闭专注模式延长时间

更改为:

专注模式扩展功能处于开启状态
启用专注模式延长

🎯? 可能的改进

根据您今天学到的内容,尝试完成以下任一操作:

  • 改进 CSS 样式表。
  • 分配其他键盘快捷键。
  • 更改您喜爱的博客或文档网站的布局。

继续构建。

恭喜您完成本教程 🎉?。请继续学习本系列的其他教程,提升您的技能:

扩展程序 学习内容
阅读时间 自动在特定网页中插入元素。
标签页管理器 创建用于管理浏览器标签页的弹出式窗口。

继续探索

希望您能享受构建此 Chrome 扩展程序的乐趣,并期待您继续学习扩展程序开发。我们建议您学习以下课程:

  • 开发者指南中还提供了数十个指向与高级扩展程序开发相关的文档的链接。
  • 除了开放网络上提供的 API 之外,扩展程序还可以使用强大的 API。 Chrome API 文档详细介绍了每个 API。