两万+字数:从0到1带你开发 Chrome 浏览器 Manifest V3 版本插件

2024-01-17 17:20

本文主要是介绍两万+字数:从0到1带你开发 Chrome 浏览器 Manifest V3 版本插件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述

Chrome 插件

一、什么是 Chrome 浏览器插件?

Chrome 浏览器插件可通过自定义界面、观察浏览器事件和修改网络来提升浏览体验。

二、Chrome 浏览器插件是如何构建的?

使用 Web 技术开构建 Chrome 插件:HTML、CSS、JS

三、Chrome 浏览器插件可以做什么?

1. 设计界面

大多数扩展程序都需要某种类型的用户互动才能正常运行。扩展程序平台提供了多种方式来向扩展程序添加互动。这些方法包括从 Chrome 工具栏、侧边栏、上下文菜单等触发的弹出式窗口:

  1. 侧边栏(Side panel
  2. 操作项(Action
  3. 菜单项(Menus

2. 控制浏览器

借助 Chrome 的扩展程序 API,可以改变浏览器的工作方式:

  1. 覆盖 Chrome 页面和设置项:Manifest.json 配置 chrome_settings_overrides
  2. 扩展开发者工具:Manifest.json 配置 devtools_page
  3. 显示通知:chrome.notifications API
  4. 管理历史记录:chrome.history API
  5. 控制标签页和窗口:chrome.tabs、chrome.tabGroupschrome.windowsAPI
  6. 键盘快捷键:chrome.commands API
  7. 身份认证:chrome.identity API
  8. 管理插件:chrome.management API
  9. 提供建议:chrome.omnibox API
  10. 更新 Chrome 设置:chrome.proxy API
  11. 下载管理:chrome.downloads API
  12. 书签:chrome.bookmarks API

3. 控制网络

可以通过注入脚本、拦截网络请求以及使用 Web API 与网页进行交互,来控制和修改 Web

  1. 注入 JSCSS 文件
  2. 访问当前 Tab
  3. 控制 Web 请求
  4. 录音和屏幕截图
  5. 修改网站设置

四、Chrome 插件术语

1. 清单(Manifest

Chrome 插件的清单是唯一且必须具有特定文件名的必需文件:manifest.json

该文件列出了有关该扩展程序的结构和行为的重要信息。

1.1 示例展示
{"manifest_version": 3,"name": "My Chrome Extension","version": "0.0.1","description": "My Chrome Extension Description"
}
1.2 manifest.json 文件必需的字段
  1. manifest_version:用于指定扩展程序使用的清单文件格式版本,目前是 3
  2. name:插件名称,一般情况下 hover 插件图标展示的文案也是 name
  3. version:插件版本
1.3 发布 Chrome 应用商店需要的字段
  1. description:插件描述
  2. icons:图标

image.png

  1. name
  2. version
  3. description
  4. icons

2. 操作项(Action

控制扩展程序在 Chrome 浏览器工具栏中的图标。

2.1 示例
{"manifest_version": 3,"name": "My Chrome Extension","version": "0.0.1","description": "My Chrome Extension Description","icons": {"16": "icons/icon_16.png","32": "icons/icon_32.png","48": "icons/icon_48.png","128": "icons/icon_128.png"},"action": {"default_icon": "icons/icon.png","default_title": "Popup Title","default_popup": "popup.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><style>*{padding: 0;margin: 0;}div{width: 300px;height: 300px;text-align: center;line-height: 300px;background: gray;}</style>
</head>
<body><div>popup html</div>
</body>
</html>
2.2 Action 字段

image.png

  1. default_icon:工具栏展示的图片
  2. default_titlehover 插件图标展示的文案
  3. default_popup:点击图标弹出的页面

3. 背景(Background - Service Worker

Service Worker 在后台运行并处理浏览器事件

V3 中使用 service worker 替换 background 页面

3.1 Backgroundmanifest V2 V3 版本中的不同之处
  1. V2 版本 background
{"background": {"scripts": ["backgroundContextMenus.js","backgroundOauth.js"],"persistent": false},
}
  1. V3 版本 background
{"background": {"service_worker": "service_worker.js","type": "module"}
}
3.2 示例

在上面的 Action 示例中添加以下代码

"background": {"service_worker": "service_worker.js"
}
  1. 激活 Service Worker

image.png

  1. 终止 Service Worker

image.png

3.3 终止 Service Worker
  1. 无操作 30 秒后。
  2. 单个请求的处理用时超过 5 分钟。
  3. fetch 响应的传递时间超过 30 秒时。
3.4 Service Worker DevTools

点击 Chrome Service Worker 即可弹出 DevTools
image.png
image.png

4. 内容脚本(Content scripts

在网页环境中运行 JavaScriptCSS
通过 content_scripts 进行注册。

4.1 示例
  1. 在上面的 Service Worker 示例中添加以下代码
"content_scripts": [{"matches": ["https://lkcoffee.com/"],"js": ["content_scripts.js"]}
]
  1. content_scripts.js 文件代码
console.log('this is content scripts')
4.2 页面注入
  1. 打开 https://lkcoffee.com/,并打开控制台

image.png

  1. 点击 content_scripts.js

image.png

五、开发 Chrome 插件

1. 新建项目并创建 manifest.json 文件

1.1 添加以下代码
{"manifest_version": 3,"name": "My Chrome Extension","version": "0.0.1","description": "My Chrome Extension Description"
}
1.2 在谷歌浏览器中打开管理扩展程序
  1. 第一种方式

image.png

  1. 第二种方式

image.png

  1. 第三种方式

浏览器输入:chrome://extensions/

1.3 点击【加载已解压的扩展程序】

image.png

选择刚刚创建的文件夹即可

image.png

1.4 可以看到扩展程序已经加载完成

image.png

包含名称、版本、描述、默认图标

1.5 固定插件
  1. 点击固定按钮,即可把插件固定在工具栏中

image.png

  1. 固定之后的样式

image.png

到了这一步,一个最最基础的插件已经完成了

2. 添加 action 中的 popup html 页面

以谷歌翻译模版为例

image.png

2.1 添加 action icons

创建 icons 文件夹,并添加图片

.
├── icons
│   └── icon.png
├── manifest.json
2.2 新建 popup 文件夹并创建 index.html 页面
2.2.1 同时创建 index.cssindex.js 文件

目前的目录结构

.
├── icons
│   └── icon.png
├── manifest.json
└── popup├── index.css├── index.html└── index.js
2.2.2 填充 popup 代码
  1. index.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><link rel="stylesheet" href="./index.css">
</head>
<body><div class="plugin_search"><div class="plugin_search_bar"><input id="plugin_search_inp" /><input id="plugin_search_but" type="button" value="翻译" /></div><div class="plugin_span"><span>翻译此页面</span></div></div><div class="plugin_footer"><span>© 2015 Google -</span><a target="_blank" href="https://google.com/">扩展程序选项</a><a target="_blank" href="https://translate.google.com/?source=gtx">Google 翻译</a></div>
</body>
<script src="./index.js"></script>
</html>
  1. index.css
*{padding: 0;margin: 0;list-style: none;text-decoration: none;
}
.plugin_search{margin: 15px 30px 15px 30px;
}
.plugin_search_bar{margin: 8px 0 16px 0;
}
#plugin_search_inp{font-size: 14px;margin: 2px;height: 23px;width: 70%;
}
#plugin_search_but{box-shadow: none;background-color: #4d90fe;background-image: -webkit-linear-gradient(top,#4d90fe,#4787ed);border: 1px solid #3079ed;color: #fff;border-radius: 2px;cursor: default;font-size: 11px;font-weight: bold;text-align: center;white-space: nowrap;margin-right: 16px;height: 27px;line-height: 27px;width: 54px;outline: 0px;padding: 0 8px;box-sizing: content-box;
}
.plugin_span{color: #4285f4;
}
.plugin_footer{background-color: #f0f0f0;color: #636363;font-family: 'Roboto',sans-serif;font-size: 11px;margin-top: 9px;padding: 10px;text-align: center;width: 400px;
}
.plugin_footer a{color: #4285f4;
}
  1. index.js
const plugin_search_but = document.getElementById('plugin_search_but')
const plugin_search_inp = document.getElementById('plugin_search_inp')
plugin_search_but.onclick = function () {alert('plugin_search_inp的值为:' + plugin_search_inp.value.trim())
}
2.3 Manifest.json 文件添加 action 字段
2.3.1 Manifest.json 文件内容
{"manifest_version": 3,"name": "My Chrome Extension","version": "0.0.1","description": "My Chrome Extension Description","action": {"default_icon": "icons/icon.png","default_title": "Popup Title","default_popup": "popup/index.html"}
}
2.3.2 点击扩展程序刷新按钮

image.png

可以看到小图标已经展示出来了

image.png

2.3.3 Hover 图标展示 default_title 字段

image.png

2.3.4 点击图标

可以看到我们的 htmlcss 已经生效了

image.png

2.3.5 输入框输入,并点击翻译按钮

根据我们 index.js 文件中的代码,我们可以在输入框中输入文案,并点击翻译按钮

image.png

原来这就是惊喜

2.4 Action popup 控制台

点击图标,弹出 popup 页面,右键,会有【检查】选项,点击检查按钮

image.png

到了这一步,我们可以开发一个有点击动作的插件了

3. 添加 backgroundservice worker

3.1 如果我们在 popup index.js 中添加一个 setInterval,每隔几秒弹出一个 alert
setInterval(() => {alert('哈哈哈哈,我又出来了')
}, 3000)

保存代码之后,刷新插件,点击插件图标弹出 popup 页面,就会定时弹出 alert 框了

image.png

但是,当我们点击页面某处,把插件 popup 页面隐藏的时候,就会发现 alert 弹框不会再弹出了,只有在此展现 popup 页面的时候才会重新执行

那如果我想的是不展现 popup 的时候,也执行 alert 弹框,那就需要 background

3.2 新建 background 文件夹并创建 service_worker.js 文件
  1. 先把 popup index.js 中的 alert 删除
  2. service_worker.js 中写入代码
setInterval(() => {alert('我是 background service worker 中弹出来的')
}, 3000)
  1. 目录结构
.
├── background
│   └── service_worker.js
├── icons
│   └── icon.png
├── manifest.json
└── popup├── index.css├── index.html
3.3 Manifest.json 文件中添加 background
3.3.1 在上面 action 的基础上添加代码
"background": {"service_worker": "background/service_worker.js"
}
3.3.2 点击拓展程序刷新插件
  1. 发现会有错误出现

image.png

  1. 我们先点击检查视图后面的 Service Worker 弹出控制台

image.png

  1. 可以看出报错内容

这是因为 Service Workers 在插件中主要用于后台任务、推送通知等,而不是直接与用户交互。因此,alert 这类弹窗通常无法直接在 Service Worker 中使用。

image.png

  1. 我们点击【错误】按钮,你会发现,每隔三秒会刷新当前错误页面,是因为一直在执行 service_worker.js 中的代码

image.png

  1. 但是当 30s 之后,会发现不刷新了,这个时候我们点击返回,可以看到 service worker 已经被终止了

这个时候如果继续点击 service worker 则会继续触发当前程序

image.png

3.4 既然不能用 alert,那我们就换个 notifications 用一用

借助 chrome.notifications API,可以通过模板创建内容丰富的通知,并在系统任务栏中向用户显示这些通知。

3.4.1 修改 service worker 中的代码
setInterval(() => {chrome.notifications.create({type: "basic",title: "Notifications Title",message: "Notifications message to display",iconUrl: "../icons/icon.png"},(notificationId) => {console.log('notificationId-->', notificationId)});
}, 3000)
3.4.2 刷新插件

会发现还是会报错

说是 notifications 未定义

image.png

这个时候就涉及到 manifest.json 中的另一个字段了,权限(permissions)字段,使用 Chrome.XXXAPI 绝大多数的时候都需要在 permissions 字段中添加,permissions 是一个 string[]

3.4.3 manifest.json 文件中添加 permissions 字段

添加如下代码

"permissions": ["notifications"
]
3.4.4 刷新插件,并点开 service worker 控制台

可以看到控制台中已经有通知的回调返回值了

image.png

那通知呢?

3.4.5 平台差异

平台差异:对于 Mac OS X 用户,通知的显示方式有所不同。用户看到的不是 Chrome 自己的通知,而是原生 Mac OS X 通知。

点开通知中心,即可看到通知

image.png

3.5 如果有多个 JS 需要引入怎么办?

如果还需要引入 module_1.jsmodule_2.js

3.5.1 manifest.jsonbackground 字段添加 typemodule
"background": {"service_worker": "background/service_worker.js","type": "module"
},
3.5.2 在 service_worker.jsimport 引入
import './module_1.js'
import './module_2.js'
3.5.3 刷新插件,打开 Service worker 控制台

每个 js 里面只是输出了一句话

image.png

到这一步,我们已经可以操作后台了

4. Action(popup)background(service worker) 之间的通信

点击翻译的时候,发一条信息

image.png

4.1 先打印下 popup.js 中的 Chrome 数据
plugin_search_but.onclick = function () {// alert('plugin_search_inp的值为:' + plugin_search_inp.value.trim())console.log('chrome', chrome)
}

image.png

4.2 先把 popup.js 中的点击事件修改下

改成点击之后向 Service Worker 发送消息

plugin_search_but.onclick = function () {// alert('plugin_search_inp的值为:' + plugin_search_inp.value.trim())console.log('chrome', chrome)// 向 Service Worker 发送消息chrome.runtime.sendMessage({action: 'fromPopup',message: 'Hello from Popup!'});
}
4.3 只需要在 service_worker.js 中接收消息即可

把之前的代码注释/删除即可

chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => {if (message.action === 'fromPopup') {chrome.notifications.create({type: "basic",title: "Notifications Title",message: "Notifications message to display",iconUrl: "../icons/icon.png"},(notificationId) => {console.log('notificationId-->', notificationId)});}
});
4.4 刷新插件

点击图标,弹出 popup 页面,点击翻译按钮,点击消息中心

image.png

5. 内容脚本(Content Script)注入

如果需要在某个页面中注入脚本进去,那就用到了 content_scripts

更新 content script 之后需要刷新对应的页面

5.1 新建 content 文件夹,并创建 index.js 文件
  1. 写入代码
console.log('this is content js')
console.log('document', document)
console.log('location', location)
console.log('window', window)
  1. 目录结构
.
├── background
│   ├── module_1.js
│   ├── module_2.js
│   └── service_worker.js
├── content
│   └── index.js
├── icons
│   └── icon.png
├── manifest.json
└── popup├── index.css├── index.html└── index.js
5.2 在 manifest.json 文件中添加 content_scripts
"content_scripts": [{"matches": ["https://lkcoffee.com/"],"js": ["content/index.js"]}
]

可以看出我们引入了 js 文件和匹配了域名

5.3 打开 https://lkcoffee.com/ 并打开控制台

image.png

5.4 在当前页面中插入面板框,并可拖拽

使用 jquery

  1. content 中创建 index.cssjquery.js(可在 CDN 上下载)
  2. index.css 上写入面板样式
  3. index.js 上创建 dom 和监听鼠标事件
  4. manifest.json 中引入

manifest.json 文件

"content_scripts": [{"matches": ["https://lkcoffee.com/"],"css": ["content/index.css"],"js": ["content/jquery.js", "content/index.js"]}
]

JS/CSS 注入多个时,按照数组顺序注入,所以如果 JS/CSS 有多个的话,需要注意引用关系。
index.css 文件

#cj_move_page{width: 400px; user-select: none; background: white; border: 1px solid; height: 400px; position: fixed; right: 0; bottom: 0; z-index: 1000001;
}
#cj_move_h3{text-align: center; line-height: 40px; cursor: move;
}

index.js 文件

console.log('this is content js')
console.log('document', document)
console.log('location', location)
console.log('window', window)//创建页面函数
function createPage () {const page = $('<div id="cj_move_page"></div>')const h3 = $('<h3 id="cj_move_h3">my Plugin</h3>')page.append(h3)$('body').append(page)//拖拽drag(cj_move_h3)
}
createPage()//拖拽
function drag(ele) {let oldX, oldY, newX, newYele.onmousedown = function (e) {if (!cj_move_page.style.right && !cj_move_page.style.bottom) {cj_move_page.style.right = 0cj_move_page.style.bottom = 0}oldX = e.clientXoldY = e.clientYdocument.onmousemove = function (e) {newX = e.clientXnewY = e.clientYcj_move_page.style.right = parseInt(cj_move_page.style.right) - newX + oldX + 'px'cj_move_page.style.bottom = parseInt(cj_move_page.style.bottom) - newY + oldY + 'px'oldX = newXoldY = newY}document.onmouseup = function () {document.onmousemove = nulldocument.onmouseup = null}}
}
5.5 刷新 Chrome 插件,并刷新匹配的页面

可以看到右下角有个 content 页面

image.png

到这一步我们已经可以注入自己想要的东西了

6. Contentbackground(Service Worker)通信

如果我想在 content 中点击按钮来触发消息通知要怎么做呢?

6.1 在刚才的面板页面加一个 button,再加一个 click 事件

先打印下 Chrome 数据,看看有啥

//创建页面函数
function createPage () {const page = $('<div id="cj_move_page"></div>')const h3 = $('<h3 id="cj_move_h3">My Chrome Ext Content Page</h3>')const but1 = $('<button id="cj_but1">消息通知</button>')page.append(h3)page.append(but1)$('body').append(page)$('#cj_but1').click(async (e) => {console.log('e', e, chrome)})//拖拽drag(cj_move_h3)
}
6.2 刷新插件,点击 button 触发事件

image.png

image.png

可以看到 chrome 有个 runtime,里面有 sendMessage 可以发送消息,有 onMessage 可以接收消息

6.3 在 content_scripts 里面进行消息发送

click 事件改一下,加一个消息发送

$('#cj_but1').click(async (e) => {console.log('e', e, chrome)// 发送消息chrome.runtime.sendMessage({action: "fromContent"});
})
6.4 Service_worker.js 里面进行消息接收

和上面 actionservice-worker 的通信一样,在一个 if 判断就行

if (message.action === 'fromContent') {chrome.notifications.create({type: "basic",title: "Notifications Title",message: "Notifications message to display",iconUrl: "../icons/icon.png"},(notificationId) => {console.log('notificationId-->', notificationId)});
}
6.5 刷新插件

刷新插件,点击按钮,查看消息通知

image.png

7. Action(popup)content 通信

因为 content 是注入页面的脚本,所以和 content 通信,需要获取当前 tab 信息

就需要权限(permissions

7.1 添加 tab 权限(permissions

添加权限的方式有两种

  1. permissions 中添加 tabs
"permissions": ["notifications","tabs"
],
  1. 另一种是在主机权限(host_permissions)添加匹配的域名
"host_permissions": ["https://movie.douban.com/"
]

推荐使用第二种,这种符合权限最小化

7.2 获取 tab 数据

需要在 popup js 中获取 tab 数据

const [tab] = await chrome.tabs.query({url: ["https://movie.douban.com/*"],active: true,currentWindow: true
});
console.log('tab', tab)

tab 信息

image.png

7.3 popupcontent 发送消息,content 接收消息
7.3.1 popup 中使用 chrome.tabs.sendMessage 发送消息,content 中使用 chrome.runtime.onMessage.addListener 接收消息
  1. popup 代码
const plugin_search_but = document.getElementById('plugin_search_but')
const plugin_search_inp = document.getElementById('plugin_search_inp')
plugin_search_but.onclick = async function () {// alert// alert('plugin_search_inp的值为:' + plugin_search_inp.value.trim())// console.log('chrome', chrome)// 向 Service Worker 发送消息// chrome.runtime.sendMessage({//   action: 'fromPopup',//   message: 'Hello from Popup!'// });const [tab] = await chrome.tabs.query({url: ["https://movie.douban.com/*"],active: true,currentWindow: true});console.log('tab', tab)if (tab) {// 使用 chrome.tabs.sendMessage 发送消息chrome.tabs.sendMessage(tab.id, {action: 'fromPopup2Content'})}
}
  1. content 监听代码
chrome.runtime.onMessage.addListener((e) => {console.log('e', e)
})
  1. 刷新插件,刷新页面,打开控制台,点击图标,弹出 popup,点击翻译按钮

image.png

7.3.2 popup 中使用 chrome.tabs.connect 发送消息,content 使用 chrome.runtime.onConnect.addListener 来接收消息
  1. popup 代码
if (tab) {// 使用 chrome.tabs.sendMessage 发送消息// chrome.tabs.sendMessage(tab.id, {//   action: 'fromPopup2Content'// })const connect = chrome.tabs.connect(tab.id, {name: 'fromPopup2Content'});console.log('connect', connect)connect.postMessage('这里是弹出框页面,你是谁?')connect.onMessage.addListener((mess) => {console.log(mess)})
}
  1. content 代码
// chrome.runtime.onMessage.addListener((e) => {
//   console.log('e', e)
// })chrome.runtime.onConnect.addListener((res) => {console.log('contentjs中的 chrome.runtime.onConnect:',res)if (res.name === 'fromPopup2Content') {res.onMessage.addListener(mess => {console.log('contentjs中的 res.onMessage.addListener:', mess)res.postMessage('哈哈哈,我是contentjs')})}
})
  1. 刷新插件,刷新页面,打开控制台,点击图标,弹出 popup,点击翻译按钮

content 页面的日志

image.png

popup 页面的日志

image.png

8. Fetch 请求

V3 版本已经禁止使用 XMLHttpRequest,所有的请求走的都是 fetch

8.1 我们现在 content_scripts 中的 matches 中加入豆瓣域名(www.douban.com)

用于获取数据

*: 通配符匹配

"content_scripts": [{"matches": ["https://lkcoffee.com/", "https://movie.douban.com/*"],"css": ["content/index.css"],"js": ["content/jquery.js", "content/index.js"]}
]
8.2 在刚才的 index.js 文件中加入按钮,点击的时候触发 fetch 请求

只更改了 createPage 函数,增加了 but2but3 按钮和 click 事件

//创建页面函数
function createPage () {const page = $('<div id="cj_move_page"></div>')const h3 = $('<h3 id="cj_move_h3">My Chrome Ext Content Page</h3>')const but1 = $('<button id="cj_but1">消息通知</button>')const but2 = $('<button id="cj_but2">content 加载更多</button>')const but3 = $('<button id="cj_but3">service worker 加载</button>')page.append(h3)page.append(but1)page.append(but2)page.append(but3)$('body').append(page)// 消息通知按钮事件$('#cj_but1').click(async (e) => {console.log('e', e, chrome)chrome.runtime.sendMessage({action: "fromContent"});})// content 加载更多按钮事件$('#cj_but2').click(async (e) => {const response = await fetch("https://movie.douban.com/j/tv/recommend_groups")if (!response.ok) {throw new Error('Network response was not ok')}const allData = await response.json()console.log('content index allData', allData)})// service worker 加载按钮事件$('#cj_but3').click(async (e) => {console.log('e', e, chrome)chrome.runtime.sendMessage({action: "fromContentFetch"});})//拖拽drag(cj_move_h3)
}
8.3 service_worker.js 里面进行消息监听
if (message.action === 'fromContentFetch') {const response = await fetch("https://movie.douban.com/j/tv/recommend_groups")if (!response.ok) {throw new Error('Network response was not ok')}const allData = await response.json()console.log('service worker allData', allData)
}
8.4 刷新插件并刷新匹配的豆瓣域名页

image.png

8.5 点击按钮
  1. 打开页面控制台,点击【content 加载更多】

image.png

  1. 打开 service worker 控制台,点击【service worker 加载】

image.png

到这一步,我们已经可以进行接口请求了,整体的链路已经通了

9. Cookie 获取

web 开发少不了获取 cookie

使用 chrome.cookies API 查询和修改 Cookie,并在这些 Cookie 发生更改时收到通知。

这就需要在权限(permissions)里面添加 cookies 字段以及在主机权限(host_permissions)里面添加 host

9.1 Manifest.json 文件
"permissions": ["notifications","cookies"
],
"host_permissions": ["https://*.douban.com/*","https://*.lkcoffee.com/*"
]
9.2 Popup 页面获取 cookies
const cookies = await chrome.cookies.getAll({ domain:  '.lkcoffee.com'})
console.log('popup cookies--->', cookies)
const urlCookies = await chrome.cookies.getAll({ url: 'https://leaptest03.lkcoffee.com/' })
console.log("popup urlCookies", urlCookies);
9.3 Service Worker 获取 cookies
const cookies = await chrome.cookies.getAll({ domain:  '.lkcoffee.com'})
console.log('service worker cookies--->', cookies)

image.png

9.4 Content 获取 cookies

这个直接用 document.cookie 获取即可

六、打包 Chrome 插件

1. 不需要发布 Chrome 应用商店

直接压缩包就行,安装的时候加载已解压的扩展程序即可

2. 需要发布到 Chrome 应用商店

  1. 前往 Chrome 开发者信息中心。
  2. 登录开发者帐号。
  3. 点击添加新商品按钮。
  4. 依次点击选择文件 > ZIP 文件 > 上传。

image.png

gg

七、总结

  1. 到此基本上已经可以开发一个完整流程的 Chrome 插件了,但是这篇文章只是一个基础
  2. Manifest.json 文件字段解析
  3. 权限列表(permissions)
  4. 匹配模式规则
  5. Content 脚本动态注入
  6. Chrome API
  7. V2 迁移 V3 版本

引用

  • 【Chrome-extensions】

这篇关于两万+字数:从0到1带你开发 Chrome 浏览器 Manifest V3 版本插件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/616723

相关文章

ONLYOFFICE 8.1 版本桌面编辑器测评

在现代办公环境中,办公软件的重要性不言而喻。从文档处理到电子表格分析,再到演示文稿制作,强大且高效的办公软件工具能够极大提升工作效率。ONLYOFFICE 作为一个功能全面且开源的办公软件套件,一直以来都受到广大用户的关注与喜爱。而其最新发布的 ONLYOFFICE 8.1 版本桌面编辑器,更是带来了诸多改进和新特性。本文将详细评测 ONLYOFFICE 8.1 版本桌面编辑器,探讨其在功能、用户

17.用300行代码手写初体验Spring V1.0版本

1.1.课程目标 1、了解看源码最有效的方式,先猜测后验证,不要一开始就去调试代码。 2、浓缩就是精华,用 300行最简洁的代码 提炼Spring的基本设计思想。 3、掌握Spring框架的基本脉络。 1.2.内容定位 1、 具有1年以上的SpringMVC使用经验。 2、 希望深入了解Spring源码的人群,对 Spring有一个整体的宏观感受。 3、 全程手写实现SpringM

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

自制的浏览器主页,可以是最简单的桌面应用,可以把它当成备忘录桌面应用

自制的浏览器主页,可以是最简单的桌面应用,可以把它当成备忘录桌面应用。如果你看不懂,请留言。 完整代码: <!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><ti

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa

Visual Studio中,MSBUild版本问题

假如项目规定了MSBUild版本,那么在安装完Visual Studio后,假如带的MSBUild版本与项目要求的版本不符合要求,那么可以把需要的MSBUild添加到系统中,然后即可使用。步骤如下:            假如项目需要使用V12的MSBUild,而安装的Visual Studio带的MSBUild版本为V14。 ①到MSDN下载V12 MSBUild包,把V12包解压到目录(

YOLO v3 训练速度慢的问题

一天一夜出了两个模型,仅仅迭代了200次   原因:编译之前没有将Makefile 文件里的GPU设置为1,编译的是CPU版本,必须训练慢   解决方案: make clean  vim Makefile make   再次训练 速度快了,5分钟迭代了500次

WordPress网创自动采集并发布插件

网创教程:WordPress插件网创自动采集并发布 阅读更新:随机添加文章的阅读数量,购买数量,喜欢数量。 使用插件注意事项 如果遇到404错误,请先检查并调整网站的伪静态设置,这是最常见的问题。需要定制化服务,请随时联系我。 本次更新内容 我们进行了多项更新和优化,主要包括: 界面设置:用户现在可以更便捷地设置文章分类和发布金额。代码优化:改进了采集和发布代码,提高了插件的稳定

Pycharm配置conda环境(解决新版本无法识别可执行文件问题)

引言: 很多小伙伴在下载最新版本的pycharm或者更新到最新版本后为项目配置conda环境的时候,发现文件夹目录中无法显示可执行文件(一般为python.exe),以下就是本人遇到该问题后试验和解决该问题的一些方法和思路。 一般遇到该问题的人群有两种,一种是刚入门对pycharm进行conda环境配置的小白(例如我),不熟悉相关环境配置的操作和过程,还有一种是入坑pycharm有段时间的老手

WDF驱动开发-WDF总线枚举(一)

支持在总线驱动程序中进行 PnP 和电源管理 某些设备永久插入系统,而其他设备可以在系统运行时插入和拔出电源。 总线驱动 必须识别并报告连接到其总线的设备,并且他们必须发现并报告系统中设备的到达和离开情况。 总线驱动程序标识和报告的设备称为总线的 子设备。 标识和报告子设备的过程称为 总线枚举。 在总线枚举期间,总线驱动程序会为其子 设备创建设备对象 。  总线驱动程序本质上是同时处理总线枚