找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2169

积分

0

好友

302

主题
发表于 前天 06:42 | 查看: 7| 回复: 0

Chrome浏览器插件开发指的是创建能够在谷歌浏览器中运行的扩展程序,它们能为用户提供额外的功能与定制化体验。这类插件通常由 HTML、CSS和JavaScript 构成,这对于前端开发者而言非常友好。开发者可以利用这些技术为浏览器增添新功能、修改现有功能或与网页进行交互。

要开发一个Chrome插件,通常需要创建一个包含 清单文件(manifest.json)、后台脚本(background script)、内容脚本(content script) 等项目结构的文件。其中,清单文件是插件的核心配置文件,用于声明插件的名称、版本、描述、权限等元信息。后台脚本负责处理插件的后台逻辑,而内容脚本则用于在特定网页的上下文中执行JavaScript代码。

Chrome插件能实现的功能多种多样,例如添加新的工具栏按钮、修改网页内容、捕获用户输入、与远程服务器通信等。开发者可以通过丰富的Chrome插件API来访问浏览器的各项功能与数据,以满足个性化的开发需求。

下图概括了Chrome插件开发涉及的主要模块及其功能:
Chrome插件开发思维导图

基础配置

开发Chrome插件,最重要的文件是 manifest.json

{
  "name": "Getting Started Example", // 插件名称
  "description": "Build an Extension!", // 插件描述
  "version": "1.0", // 版本
  "manifest_version": 3, // 指定插件版本,这个很重要,不同版本可用的API不同
  "background": {
    "service_worker": "background.js" // 指定background脚本的路径
  },
  "action": {
    "default_popup": "popup.html", // 指定popup页面的路径
    "default_icon": { // 指定插件图标,支持多种尺寸
      "16": "/images/icon16.png",
      "32": "/images/icon32.png",
      "48": "/images/icon48.png",
      "128": "/images/icon128.png"
    }
  },
  "icons": { // 指定插件的应用图标
    "16": "/images/icon16.png",
    "32": "/images/icon32.png",
    "48": "/images/icon48.png",
    "128": "/images/icon128.png"
  },
  "permissions": [], // 声明插件所需的API权限
  "options_page": "options.html", // 插件选项页
  "content_scripts": [ // 配置内容脚本
    {
      "js": ["content.js"], // content脚本路径
      "css":["content.css"], // content脚本的css
      "matches": ["<all_urls>"] // 脚本注入的URL匹配规则,`<all_urls>`表示匹配所有网址
    }
  ]
}

配置项解析:

  • name: 插件名称。
  • manifest_version: 插件使用的清单文件版本,当前最新版为3(Manifest V3)。
  • version: 插件自身的版本号,与发布更新相关。
  • action: 配置工具栏图标的交互行为。
    • default_icon: 设置显示的图标。
    • default_popup: 设置点击图标时弹出的页面(popup.html)。
    • default_title: 鼠标悬停时显示的提示文本。
  • permissions: 声明插件需要的API权限,例如 tabs 权限用于监听浏览器标签页事件。
  • background: 配置后台脚本(Service Worker)。
    • service_worker: 指定后台脚本文件。
  • options_page: 插件的设置页面。
  • content_scripts: 配置注入到网页中的脚本和样式。

打开popup弹窗页面

通过设置 action 中的 default_popup 属性,可以创建一个点击插件图标即弹出的页面。

首先,配置 manifest.json

{
  "name": "Hello world",
  "description": "show 'hello world'!",
  "version": "1.0",
  "manifest_version": 3,
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "/images/icon16.png",
      "32": "/images/icon32.png",
      "48": "/images/icon48.png",
      "128": "/images/icon128.png"
    }
  },
  "permissions":["tabs", "storage", "activeTab", "idle"],
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "js": ["content.js"],
      "css":["content.css"],
      "matches": ["<all_urls>"]
    }
  ]
}

创建popup.html

这是一个标准的HTML文件,可以引入CSS和JavaScript。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>显示出hello world</title>
  <link rel="stylesheet" type="text/css" href="popup.css">
</head>
<body>
  <h1>显示出hello world</h1>
  <button id="clickBtn">点击按钮</button>
  <script src="popup.js"></script>
</body>
</html>

配套的CSS和JavaScript示例:

/* popup.css */
body {
  width: 600px;
  height: 300px;
}
h1 {
  background-color: antiquewhite;
  font-weight: 100;
}
// popup.js
console.log(document.getElementById('clickBtn'));
document.getElementById('clickBtn').addEventListener('click', function () {
  console.log('clicked');
});

点击插件图标

配置并加载插件后,点击浏览器工具栏上的插件图标,即可看到如下弹窗:
Popup弹窗页面效果截图

调试popup.js的方法

调试弹出页面的脚本有两种常见方式:

  1. 在打开的弹窗内部点击右键,选择“检查”。
  2. 直接在浏览器工具栏的插件图标上点击右键,选择“审查弹出内容”。
    右键审查popup内容方法截图
    通过插件图标右键菜单审查弹出内容

通过background打开独立页面

基于 backgroundservice_worker,我们可以打开一个独立的后台脚本。这个脚本在插件安装时初始化执行一次,之后在浏览器运行期间持续存在于后台,适合用于存储全局状态或处理长期任务。

示例 background.js 代码,用于在点击插件图标时打开一个新标签页:

chrome.action.onClicked.addListener(function () {
  chrome.tabs.create({
    url: chrome.runtime.getURL('newPage.html')
  });
});

对应的 manifest.json 配置需要移除 action 中的 default_popup 配置:

{
  "name": "newPage",
  "description": "Demonstrates the chrome.tabs API and the chrome.windows API...",
  "version": "0.1",
  "permissions": ["tabs"],
  "background": {
    "service_worker": "service-worker.js"
  },
  "action": {
    "default_title": "Show tab inspector"
  },
  "manifest_version": 3
}

通过 chrome.runtime.getURL() 可以获取扩展程序内部资源的绝对URL。在 newPage.js 中,你可以使用 chrome.tabschrome.windows API。

你还可以在插件安装后立即打开一个独立页面:

chrome.runtime.onInstalled.addListener(async () => {
  chrome.tabs.create({
    url: chrome.runtime.getURL('newPage.html'),
  });
});

content内容脚本

内容脚本(content-scripts)是在网页上下文中运行的文件。它能够通过标准的DOM API读取和修改浏览器当前访问网页的详细信息,并将信息传递回其父级扩展程序。内容脚本在访问Chrome API方面有一定限制,它可以直接访问:

  • i18n
  • storage
  • runtime (部分API: connect, getManifest, getURL, id, onConnect, onMessage, sendMessage)

content.js 运行在一个独立的、隔离的环境中,不会与宿主页面的脚本或其他插件的内容脚本发生冲突。有两种方式可以注入内容脚本。

在配置中设置

manifest.jsoncontent_scripts 字段中静态声明:

"content_scripts": [
  {
    "js": ["content.js"],
    "css":["content.css"],
    "matches": ["<all_urls>"]
  }
]

除了 jscss,还可以配置:

  • run_at: 脚本注入时机,可选值:
    • document_idle (默认):DOM加载完成后,浏览器选择合适时机注入。
    • document_start:在CSS加载完成之后,DOM和脚本构建之前注入。
    • document_end:DOM加载完成后立即注入。
  • exclude_matches: 排除不需要注入的URL地址,与 matches 作用相反。

动态配置注入

在特定时刻(如用户点击按钮)动态注入脚本。这需要在 popup.jsbackground.js 中执行。

// 执行一段代码
chrome.tabs.executeScript(tabs[0].id, {
  code: 'document.body.style.backgroundColor = "red";',
});

// 或者注入整个脚本文件
chrome.tabs.executeScript(tabs[0].id, {
  file: "content.js",
});

利用content制作一个弹窗工具

设想一个场景:你需要向朋友道歉,希望她浏览任何网页时都能看到你的道歉信。利用内容脚本,可以轻松实现这个有点“顽皮”的功能。

我们创建一个弹窗,显示道歉信息并提供两个按钮:
道歉弹窗效果示意图

点击“已消气”按钮,弹窗关闭;点击“不原谅”,弹窗会随机改变位置继续显示。

content.js 内容如下:

let newDiv = document.createElement('div');
newDiv.innerHTML = `<div id="wrapper">
  <h3>小仙女~消消气</h3>
  <div><button id="cancel">已消气</button>
  <button id="reject">不原谅</button></div>
</div>`;
newDiv.id = 'newDiv';
document.body.appendChild(newDiv);

const cancelBtn = document.querySelector('#cancel');
const rejectBtn = document.querySelector('#reject');

cancelBtn.onclick = function() {
  document.body.removeChild(newDiv);
  chrome.storage.sync.set({ state: 'cancel' }, (data) => {
  });
}

rejectBtn.onclick = function() {
  newDiv.style.bottom = Math.random() * 200 + 10 + "px";
  newDiv.style.right = Math.random() * 800 + 10 + "px";
}

content.css 样式如下:

#newDiv {
  font-size: 36px;
  color: burlywood;
  position: fixed;
  bottom: 20px;
  right: 0;
  width: 300px;
  height: 200px;
  background-color: rgb(237, 229, 216);
  text-align: center;
  z-index: 9999;
}

打开option页面

options页是插件的设置页面,有两个入口:

  1. 在浏览器扩展程序管理页面,找到对应插件,点击“详细信息”中的“扩展程序选项”。
    扩展程序选项入口截图
  2. 在浏览器工具栏的插件图标上点击右键,选择“选项”。
    插件图标右键菜单中的选项入口

option.html 是一个普通的HTML页面:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>插件的option配置</title>
</head>
<body>
  <h3>插件的option配置</h3>
</body>
</html>

同样,这个页面也可以引入自己的CSS和JavaScript文件。

替换浏览器默认页面

override功能允许你替换浏览器的默认页面,可以替换新建标签页(newtab)、历史记录页(history)和书签管理器页(bookmarks)。

manifest.json 中配置:

{
  "chrome_url_overrides": {
    "newtab": "newtab.html",
    "history": "history.html",
    "bookmarks": "bookmarks.html"
  }
}

创建一个简单的 newtab.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h1>new tab</h1>
</body>
</html>

插件更新后,打开新的标签页,就会出现自定义的页面。首次替换时,浏览器会询问用户是否确认更改。
浏览器询问是否更改默认页面的提示

很多流行插件(如掘金插件)都利用此功能提供自定义的新标签页,这本身就是一次有趣的前端 & 移动开发实践。

页面之间进行数据通信

Chrome插件各组件(content script, background, popup)之间经常需要通信。下图清晰地展示了它们之间的短连接通信方式:
Chrome插件content, background, popup通信示意图

如需发送单条消息并(可选地)接收响应,可以调用 runtime.sendMessage()tabs.sendMessage()

content脚本发送消息

chrome.runtime.sendMessage 通常用于从内容脚本向扩展程序的其他部分发送消息。

(async () => {
  const response = await chrome.runtime.sendMessage({greeting: "hello"});
  // 在此处理响应
  console.log(response);
})();

其他页面向content脚本发送消息

从Service Worker、popup或其他扩展页面向内容脚本发送消息,需要指定目标标签页ID。

(async () => {
  const [tab] = await chrome.tabs.query({active: true, lastFocusedWindow: true});
  const response = await chrome.tabs.sendMessage(tab.id, {greeting: "hello"});
  // 在此处理响应
  console.log(response);
})();

使用onMessage接收消息

在扩展程序的所有脚本(background, content, popup)中,都可以用相同的方式监听消息。

chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    console.log(sender.tab ?
                "from a content script:" + sender.tab.url :
                "from the extension");
    if (request.greeting === "hello")
      sendResponse({farewell: "goodbye"});
  }
);

添加右键菜单

创建菜单

首先在 manifest.json 中声明 contextMenus 权限:

{
  "permissions": ["contextMenus"]
}

然后在 background.js 中创建菜单:

// 创建单选菜单项,仅在图片上显示
let menu1 = chrome.contextMenus.create({
  type: 'radio', // 类型可以是 normal, checkbox, radio
  title: 'click me',
  id: "myMenu1Id",
  contexts:['image'] // 指定触发上下文,如图片、选中文字等
});

// 创建普通菜单项,在所有上下文中显示
let menu2 = chrome.contextMenus.create({
  type: 'normal',
  title: 'click me222',
  id: "myMenu222Id",
  contexts:['all']
});

// 创建带占位符的菜单,用于搜索选中文本
let menu3 = chrome.contextMenus.create({
  id: 'baidusearch1',
  title: '使用百度搜索:%s', // %s 会被替换为选中的文本
  contexts: ['selection'],
});

// 删除特定菜单
chrome.contextMenus.remove('myMenu222Id');
// 删除所有自定义菜单
// chrome.contextMenus.removeAll();

// 绑定菜单点击事件
chrome.contextMenus.onClicked.addListener(function(info, tab){
  if(info.menuItemId == 'myMenu222Id'){
    console.log('xxx')
  }
})

绑定点击事件并发送网络请求

首先,需要在 manifest.json 中配置网络请求权限:

{
  "host_permissions": ["http://*/*", "https://*/*"]
}

然后,在 background.js 中完善右键菜单的创建与事件处理逻辑。例如,创建一个分组的右键菜单,并处理点击事件,包括发起网络请求和创建搜索标签页。

// 创建右键菜单项
chrome.runtime.onInstalled.addListener(function () {
  // 创建一个父级菜单项和子项
  let parent = chrome.contextMenus.create({
    title: '操作数据分组',
    id: 'parent',
  });
  chrome.contextMenus.create({title: '分组1', parentId: parent, id: 'group1'});
  chrome.contextMenus.create({title: '分组2', parentId: parent, id: 'group2'});
  chrome.contextMenus.create({title: '获取远程数据', parentId: parent, id: 'fetch'});

  // 创建单选按钮菜单项
  chrome.contextMenus.create({title: '创建单选按钮1', type: 'radio', id: 'radio1'});
  // 创建复选框菜单项
  chrome.contextMenus.create({title: '可以多选的复选框1', type: 'checkbox', id: 'checkbox'});
  // 创建搜索菜单(选中文字时出现)
  chrome.contextMenus.create({
    id: 'baidusearch1',
    title: '使用百度搜索:%s',
    contexts: ['selection'],
  });
});

// 处理菜单点击事件
chrome.contextMenus.onClicked.addListener(function (info, tab) {
  // 处理分组点击
  if (info.menuItemId === 'group1') {
    console.log('分组文字1', info);
  }
  // 处理“获取远程数据”点击
  if (info.menuItemId === 'fetch') {
    console.log('fetch 获取数据');
    const res = fetch('http://localhost:8080/api', {
      method: 'GET',
      headers: {'Content-Type': 'application/json'},
    }).then((res) => {
      console.log(res, '获取到接口数据');
      // 将数据存储到storage
      chrome.storage.sync.set({ color: 'red' }, function (err, data) {
        console.log('store success!');
      });
    });
  }
  // 处理百度搜索
  if (info.menuItemId === 'baidusearch1') {
    chrome.tabs.create({
      url: 'https://www.baidu.com/s?ie=utf-8&wd=' + encodeURI(info.selectionText),
    });
  }
});

最终效果如下图所示,右键菜单包含了分组、单选、多选等多种形式的项目:
自定义右键菜单分组效果截图
自定义右键菜单详细选项截图
当在网页上选中一段文字后,右键菜单会出现“使用百度搜索:选中文字”的选项:
选中文字后出现的搜索右键菜单

缓存与数据存储

Chrome插件提供了 chrome.storage API 用于持久化存储数据。首先需要在 manifest.json 中声明权限:

{
  "permissions": ["storage"]
}

存储数据:

chrome.storage.sync.set({color: 'red'}, function(){
  console.log('background js storage set data ok!')
})

获取数据(第二个参数是获取不到数据时的默认值):

chrome.storage.sync.get({color: 'yellow'}, function(data){
  console.log('获取到的颜色是:', data.color);
})

tabs管理页签

要操作浏览器的标签页,需要 tabs 权限:

{
  "permissions": ["tabs"]
}

常用操作示例:

// 查询所有标签页
chrome.tabs.query({}, function(tabs){
  console.log(tabs)
})

// 获取当前激活的标签页
function getCurrentTab(){
  let [tab] = chrome.tabs.query({active: true, lastFocusedWindow: true});
  return tab;
}

notifications消息通知

Chrome提供了 chrome.notifications API 来推送桌面通知。首先配置权限:

{
  "permissions": [
    "notifications"
  ]
}

background.js 中创建通知:

chrome.notifications.create(null, {
  type: "basic",
  iconUrl: "drink.png",
  title: "喝水小助手",
  message: "看到此消息的人可以和我一起来喝一杯水",
});

devtools开发扩展工具

开发者工具扩展可以让你在Chrome DevTools中新增自定义面板。首先在 manifest.json 中指定一个开发工具页面:

{
  "devtools_page": "devtools.html"
}

devtools.html 内容通常很简单,只用于引入脚本:

<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
  <script type="text/javascript" src="./devtools.js"></script>
</body>
</html>

devtools.js 中,你可以创建自定义面板和侧边栏:

// 创建扩展面板
chrome.devtools.panels.create(
  "DevPanel", // 面板显示名称
  "panel.png", // 图标(通常不显示)
  "Panel.html", // 面板内容页面
  function (panel) {
    console.log("自定义面板创建成功!");
  }
);

// 创建自定义侧边栏
chrome.devtools.panels.elements.createSidebarPane(
  "Sidebar",
  function (sidebar) {
    sidebar.setPage("sidebar.html");
  }
);

然后,你需要创建对应的 Panel.htmlsidebar.html 页面来定义自定义工具界面。

通过学习以上核心模块和API,你已经掌握了Chrome插件开发的基础。从修改网页内容、添加UI交互,到处理后台任务、管理浏览器状态,插件的可能性非常丰富。这不仅是提升个人效率的工具,也是深入理解浏览器工作原理和现代Web技术的绝佳途径。如果你想与更多开发者交流此类前端框架/工程化实践经验,欢迎到 云栈社区 分享你的作品或探讨问题。




上一篇:Java实现AgentScope智能体自主规划:会议室预订与邮件通知自动化
下一篇:从入门劝退到生产利器:Rust学习曲线为何陡峭却值得投入
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-14 16:01 , Processed in 0.507188 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表