firefox插件开发 tab-url-tools-firefox(用于快速保存和恢复工作状态)
·
新建文件夹(如 tab-url-tools-firefox),在其中创建以下 3 个文件:
manifest.json(Firefox 专属配置)
{
"manifest_version": 3,
"name": "标签页网址提取",
"version": "1.0.0",
"description": "一键获取浏览器所有打开标签页的网址",
"permissions": ["tabs"],
"action": {
"default_title": "查看所有标签页网址",
"default_popup": "popup.html"
},
"browser_specific_settings": {
"gecko": {
"id": "tab-url-tool@example.local",
"strict_min_version": "109.0"
}
}
}
说明:browser_specific_settings.gecko.id 是 Firefox 强制要求的扩展唯一标识,格式为邮箱样式可自定义;strict_min_version 表示最低支持 Firefox 109(首个完整支持 MV3 的正式版本)。
popup.html(界面文件)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style>
body {
width: 420px;
margin: 0;
padding: 12px 16px;
font-family: system-ui, -apple-system, sans-serif;
font-size: 13px;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
padding-bottom: 8px;
border-bottom: 1px solid #eee;
}
.title {
font-weight: 600;
font-size: 14px;
}
.copy-btn {
padding: 4px 10px;
border: 1px solid #d0d7de;
border-radius: 4px;
background: #f6f8fa;
cursor: pointer;
font-size: 12px;
}
.copy-btn:hover {
background: #eaeef2;
}
.url-list {
max-height: 360px;
overflow-y: auto;
margin: 0;
padding: 0;
list-style: none;
}
.url-item {
padding: 6px 0;
border-bottom: 1px solid #f5f5f5;
word-break: break-all;
line-height: 1.4;
color: #24292f;
}
.url-item:last-child {
border-bottom: none;
}
.count {
color: #656d76;
font-size: 12px;
font-weight: normal;
}
</style>
</head>
<body>
<div class="header">
<span class="title">全部标签页网址 <span class="count" id="count"></span></span>
<button class="copy-btn" id="copyBtn">复制全部</button>
</div>
<ul class="url-list" id="urlList"></ul>
<script src="popup.js"></script>
</body>
</html>
popup.js(Firefox 原生 Promise 写法)
Firefox 的 browser.* API 原生返回 Promise,使用 async/await 写法更简洁:
const urlList = document.getElementById('urlList');
const countEl = document.getElementById('count');
const copyBtn = document.getElementById('copyBtn');
let allUrls = [];
// 页面加载后获取所有标签页
document.addEventListener('DOMContentLoaded', async () => {
const tabs = await browser.tabs.query({});
allUrls = tabs.map(tab => tab.url);
countEl.textContent = `(共 ${tabs.length} 个)`;
// 渲染列表
tabs.forEach((tab, index) => {
const li = document.createElement('li');
li.className = 'url-item';
li.textContent = `${index + 1}. ${tab.url}`;
urlList.appendChild(li);
});
});
// 一键复制全部网址
copyBtn.addEventListener('click', async () => {
const text = allUrls.join('\n');
try {
await navigator.clipboard.writeText(text);
copyBtn.textContent = '已复制';
setTimeout(() => {
copyBtn.textContent = '复制全部';
}, 1500);
} catch (err) {
alert('复制失败,请手动选择复制');
}
});
安装
打开 Firefox,地址栏输入 about:debugging#/runtime/this-firefox 回车,进入扩展调试页面
点击页面中的临时加载附加组件按钮
在文件选择窗口中,找到扩展文件夹,选中里面的 manifest.json 文件(注意:Firefox 是选文件,不是选文件夹,和 Chrome 不同),确认即可
安装成功后,工具栏会出现扩展图标,点击即可使用
⚠️ 注意事项:
以上方式安装的是临时扩展,Firefox 完全关闭重启后会自动失效,适合测试使用
如需永久安装,可将扩展提交到 Firefox 附加组件商店签名,或使用 Firefox 开发者版 / 夜间版,在 about:config 中设置 xpinstall.signatures.required 为 false 后安装未签名扩展
如果加入日期和title提取
manifest.json 无需改动,tabs 权限本身支持读取标签页标题,我们只需要修改 popup.html 和 popup.js,新增当前提取日期时间和网页标题的展示与复制。以下代码同时兼容 Firefox 和 Chrome/Edge。
- popup.html(更新后)
调整了布局,顶部显示提取时间和标签页总数,每个标签页分开展示标题和网址,层级更清晰:
popup.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style>
body {
width: 450px;
margin: 0;
padding: 12px 16px;
font-family: system-ui, -apple-system, sans-serif;
font-size: 13px;
}
.header {
margin-bottom: 10px;
padding-bottom: 8px;
border-bottom: 1px solid #eee;
}
.header-top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 6px;
}
.title {
font-weight: 600;
font-size: 14px;
}
.meta {
color: #656d76;
font-size: 12px;
}
.copy-btn {
padding: 4px 10px;
border: 1px solid #d0d7de;
border-radius: 4px;
background: #f6f8fa;
cursor: pointer;
font-size: 12px;
}
.copy-btn:hover {
background: #eaeef2;
}
.url-list {
max-height: 380px;
overflow-y: auto;
margin: 0;
padding: 0;
list-style: none;
}
.url-item {
padding: 8px 0;
border-bottom: 1px solid #f5f5f5;
line-height: 1.4;
}
.url-item:last-child {
border-bottom: none;
}
.tab-title {
font-weight: 500;
color: #1f2328;
margin-bottom: 3px;
word-break: break-all;
}
.tab-url {
color: #656d76;
font-size: 12px;
word-break: break-all;
}
</style>
</head>
<body>
<div class="header">
<div class="header-top">
<span class="title">标签页信息汇总</span>
<button class="copy-btn" id="copyBtn">复制全部</button>
</div>
<div class="meta">
提取时间:<span id="extractTime"></span>
<span> · 共 <span id="count"></span> 个标签页</span>
</div>
</div>
<ul class="url-list" id="urlList"></ul>
<script src="popup.js"></script>
</body>
</html>
popup.js
const urlList = document.getElementById('urlList');
const countEl = document.getElementById('count');
const timeEl = document.getElementById('extractTime');
const copyBtn = document.getElementById('copyBtn');
// 自动兼容 Firefox / Chrome
const api = typeof browser !== 'undefined' ? browser : chrome;
// 格式化日期时间为 YYYY-MM-DD HH:mm:ss
function formatDateTime(date) {
const y = date.getFullYear();
const m = String(date.getMonth() + 1).padStart(2, '0');
const d = String(date.getDate()).padStart(2, '0');
const h = String(date.getHours()).padStart(2, '0');
const min = String(date.getMinutes()).padStart(2, '0');
const s = String(date.getSeconds()).padStart(2, '0');
return `${y}-${m}-${d} ${h}:${min}:${s}`;
}
// 页面加载后获取数据并渲染
document.addEventListener('DOMContentLoaded', async () => {
const now = new Date();
const extractTime = formatDateTime(now);
timeEl.textContent = extractTime;
// 获取所有标签页
const tabs = await api.tabs.query({});
countEl.textContent = tabs.length;
// 渲染列表
tabs.forEach((tab, index) => {
const li = document.createElement('li');
li.className = 'url-item';
const titleDiv = document.createElement('div');
titleDiv.className = 'tab-title';
titleDiv.textContent = `${index + 1}. ${tab.title || '无标题'}`;
const urlDiv = document.createElement('div');
urlDiv.className = 'tab-url';
urlDiv.textContent = tab.url;
li.appendChild(titleDiv);
li.appendChild(urlDiv);
urlList.appendChild(li);
});
});
// 一键复制全部信息
copyBtn.addEventListener('click', async () => {
const tabs = await api.tabs.query({});
const lines = [];
lines.push(`提取时间:${timeEl.textContent}`);
lines.push('------------------------------');
tabs.forEach((tab, index) => {
lines.push(`${index + 1}. ${tab.title || '无标题'}`);
lines.push(tab.url);
lines.push(''); // 空行分隔
});
const text = lines.join('\n');
try {
await navigator.clipboard.writeText(text);
copyBtn.textContent = '已复制';
setTimeout(() => {
copyBtn.textContent = '复制全部';
}, 1500);
} catch (err) {
alert('复制失败,请手动选择复制');
}
});
manifest.json
{
"manifest_version": 3,
"name": "标签页信息提取",
"version": "1.1.0",
"description": "一键获取所有标签页的标题、网址与提取时间",
"permissions": ["tabs"],
"action": {
"default_title": "查看标签页信息",
"default_popup": "popup.html"
},
"browser_specific_settings": {
"gecko": {
"id": "tab-url-tool@example.local",
"strict_min_version": "109.0"
}
}
}
效果说明
弹窗顶部会显示本次提取的精确日期时间(年 - 月 - 日 时:分: 秒)和标签页总数
每个标签页先显示网页标题,下方显示对应网址,层级清晰
点击「复制全部」会把提取时间、所有标签页的标题 + 网址按格式复制,粘贴到笔记 / 文档中直接可用
加载中、无标题的页面会自动显示「无标题」兜底,不会报错
更多推荐


所有评论(0)