在现代浏览器扩展开发中,如何高效地管理历史记录、优化下载体验,以及构建灵活的数据存储方案,已经成为开发者们关注的焦点。今天,我们将深入探讨 Chrome 提供的 历史浏览记录 API、下载管理 API 和 存储管理 API,并通过一个实用项目带你快速上手这些功能,让你的插件不仅智能,还贴心。
历史浏览记录
基础功能
- 数据查询:使用
chrome.history.search
方法,根据关键词和时间范围搜索用户的浏览历史记录。
chrome.history.search({ text: '', startTime: Date.now() - 7 * 24 * 60 * 60 * 1000 }, (results) => {
console.log(results); // 输出最近 7 天的历史记录
});
- 访问详情:借助
chrome.history.getVisits
方法,获取特定页面的访问时间和来源信息。
chrome.history.getVisits({ url: 'https://example.com' }, (details) => {
console.log(details); // 输出访问时间和跳转来源
});
- 隐私保护
- 删除单个 URL 的历史记录:
chrome.history.deleteUrl({ url: 'https://example.com' }, () => {
console.log('URL 已删除');
});
- 清空所有历史记录:
chrome.history.deleteAll(() => {
console.log('所有历史记录已清空');
});
进阶内容
完整 API 函数列表:
-
chrome.history.search
:用于按条件检索历史记录。
参数:
-
text
:匹配的关键词。 -
startTime
和endTime
:搜索时间范围。 -
maxResults
:返回结果的最大数量。
-
-
chrome.history.getVisits
获取指定 URL 的访问记录详情,包括访问时间、来源等。 -
chrome.history.deleteUrl
:删除指定 URL 的历史记录。 -
chrome.history.deleteRange
:删除指定时间范围内的历史记录。
例子如下:
chrome.history.deleteRange(
{ startTime: Date.now() - 24 * 60 * 60 * 1000, endTime: Date.now() },
() => console.log('最近一天的历史记录已删除')
);
虽然 chrome.history
没有监听新增或删除历史记录的直接事件,但你可以通过配合其他 API,例如 chrome.tabs.onUpdated
,间接获取用户浏览行为:
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (changeInfo.url) {
console.log(`用户访问了新页面: ${changeInfo.url}`);
}
});
除此以外,我们还可以配合搜索条件,构建复杂过滤功能。例如,只查询访问量高于一定次数的记录:
chrome.history.search({ text: '', startTime: Date.now() - 30 * 24 * 60 * 60 * 1000 }, (results) => {
const frequentVisits = results.filter((item) => item.visitCount > 5);
console.log(frequentVisits);
});
下载管理
浏览器的下载管理功能跟历史记录的 API 非常相似,大部分的能力和应用都是相通的。
基础功能
-
下载查询::使用
chrome.downloads.search
进行下载记录的查询,支持按时间、文件类型等条件筛选。
chrome.downloads.search({ query: '', startTime: Date.now() - 7 * 24 * 60 * 60 * 1000 }, (results) => {
console.log(results); // 输出最近一周的下载记录
});
- 任务管理::控制下载任务,例如暂停、取消某个下载任务。
- 暂停下载:
chrome.downloads.pause(downloadId, () => {
console.log('下载任务已暂停');
});
- 取消下载:
chrome.downloads.cancel(downloadId, () => {
console.log('下载任务已取消');
});
记录清理:使用 chrome.downloads.erase
清除过期或特定时间段的下载记录。
chrome.downloads.erase({ startTime: Date.now() - 30 * 24 * 60 * 60 * 1000 }, () => {
console.log('30天前的下载记录已清除');
});
实际应用
- 自动分类助手:插件根据文件类型自动将下载的内容分类保存到不同的文件夹,比如文档、图片、视频等。
- 任务监控工具:提供实时的下载任务进度提醒,并在完成后自动触发文件操作。
代码示例:
chrome.downloads.search({}, function(downloads) {
const categorized = downloads.reduce((acc, item) => {
const ext = item.filename.split('.').pop();
acc[ext] = acc[ext] || [];
acc[ext].push(item);
return acc;
}, {});
console.log('分类后的下载记录:', categorized);
});
存储管理
Chrome 存储 API 提供了强大的支持,用于插件中数据的持久化和跨设备同步。它确保用户的设置和数据能够在不同设备间保持一致,同时支持实时监听功能,方便插件及时响应数据变化,提升用户体验和数据管理的效率。
核心功能
-
本地存储:
chrome.storage.local
提供持久化存储功能,用于存储与扩展功能相关的数据,支持离线访问。chrome.storage.local.set({ key: 'value' }, function() { console.log('数据已存储至本地'); });
-
跨设备同步:
chrome.storage.sync
实现扩展配置的云端同步,确保数据在不同设备间保持一致。chrome.storage.sync.set({ key: 'value' }, function() { console.log('数据已同步到云端'); });
-
实时监听:
chrome.storage.onChanged
监听存储数据的变化,一旦有变化,可以触发响应动作。chrome.storage.onChanged.addListener((changes, areaName) => { console.log('存储数据已变化:', changes, areaName); });
实际应用场景
-
偏好设置管理器:存储用户个性化设置,例如主题、语言、清理规则等,方便用户跨设备同步和管理。
- 数据持久化工具::用户工作记录或任务状态在不同设备间保持一致,提升跨设备使用体验。
个人设置
以上 3 个 API 我主要用来清理历史记录和下载记录的。通过自己设定的一些策略来完成个性化需求的实现。
下面是我定义的几个相关的方法:
// 删除历史记录
function deleteHistory(page) {
chrome.browsingData.removeHistory({
url: page.url
}, function () {
if (chrome.runtime.lastError) {
console.error(`delete Error history:`, chrome.runtime.lastError);
} else {
console.log("delete page:", page.url);
}
});
// chrome.history.deleteUrl({url: page.url});
chrome.history.deleteUrl({url: page.url}, function () {
if (chrome.runtime.lastError) {
// console.error(`delete Error history:`, chrome.runtime.lastError);
} else {
console.log("delete page:", page.url);
}
});
}
function deleteDownlaods() {
chrome.downloads.search({}, (downloads) => {
downloads.forEach((download) => {
// 只删除已完成的下载记录
if (download.state === 'complete') {
chrome.downloads.erase({id: download.id}, () => {
// chrome.downloads.removeFile(download.id, () => {
if (chrome.runtime.lastError) {
if (chrome.runtime.lastError.message !== "Download file already deleted") {
console.error("Error removing download:", chrome.runtime.lastError.message);
}
} else {
console.log(`Removed download: ${download.id}`);
}
});
} else {
console.log(`Skipping download: ${download.id} (state: ${download.state})`);
}
});
});
}
// 监听历史记录变化
chrome.history.onVisitRemoved.addListener(function (removed) {
console.log("Removed visit:", removed);
});
function clearHistoryRecord() {
const endTime = Date.now() - (5 * 24 * 60 * 60 * 1000);
chrome.history.deleteRange({
startTime: 0,//含义是删除所有历史记录
endTime: endTime//删除5天前的历史记录
}, function () {
console.log(`Deleted history older than 5 days`);
});
}
其实一个比较复杂的就是删除最近的历史记录的方法,主要区分了一些常用网站的域名:
function clearRecentRecord() {
console.info("clear recent record");
// start = Date.now() - 1000 * 60 * 60 * 12;// 12 小时前
end = Date.now() - 1000 * 60 * 10;// 10 分钟前
chrome.history.search({
text: "",
startTime: 0,//含义是删除所有历史记录,0表示从1970年1月1日开始
endTime: end,
maxResults: 1200
}, function (data) {
let domainMap = {};
let countMap = {};
console.info("history data:", data.length);
for (let i = 0; i < data.length; i++) {
page = data[i];
let domain = page.url.split('/')[2];
let countUrl = domain;
const parts = domain.split('.');
if (parts.length > 2) {
countUrl = parts.slice(-2).join('.');// 只取域名后两部分,-2表示倒数第二个,join表示拼接
}
if (shouldDeletePage(domain)) {
console.info("should delete page:", domain);
deleteHistory(page);
continue;
}
if (delete2Domain.includes(countUrl)) {
deleteHistory(page);
continue;
}
// console.info("page:", page);
// console.log("url:", domain, page.url); if (!domainMap[domain]) {// 如果不存在,则初始化为1
domainMap[domain] = 1;
} else {
domainMap[domain]++;// 记录域名出现的次数
}
if (!countMap[countUrl]) {// 如果不存在,则初始化为1
countMap[countUrl] = 1;
} else {
countMap[countUrl]++;// 记录url出现的次数
}
if (keep2Domains.includes(countUrl)) {
if (domainMap[domain] > 5) {
deleteHistory(page);
}
} else {
if (countMap[countUrl] > 1) {
deleteHistory(page);
}
}
}
console.info("map:", domainMap);
});
}
使用定时任务来定时执行,这个放在下期内容分享,专门分享一下定时任务的处理方式。
FunTester 原创精华