首页/新闻资讯/正文详情

chrome.history 实战:从 chrome-extensions-samples 的 Typed URL History 示例掌握“最近常访问网址“弹窗实现

发布时间:2026/9/21 3:08:56 来源:云帆数科 栏目:资讯中心
chrome.history 实战:从 chrome-extensions-samples 的 Typed URL History 示例掌握“最近常访问网址“弹窗实现
示例工程【免费下载链接】chrome-extensions-samplesChrome Extensions Samples项目地址https://gitcode.com/gh_mirrors/ch/chrome-extensions-samples点击查看免费下载导读本文基于 chrome-extensions-samples 仓库中的api-samples/history/showHistory示例扩展名 Typed URL History完整拆解如何通过chrome.historyAPI 在扩展弹窗popup中展示用户最近一周最常访问且通过地址栏手动输入的网址。读完本文你将掌握chrome.history.search()与chrome.history.getVisits()的调用方式、transition类型过滤原理、异步回调计数与 Top N 排序技巧以及 Manifest V3 下该扩展的完整配置与运行调试方法。示例概览它在解决什么问题原文档对该示例的定位非常清晰使用chrome.historyAPI在扩展弹窗中展示用户访问最多的页面。其核心机制是扩展调用chrome.history.search()抓取浏览器历史并统计每个被访问 URL 出现的次数。更具体地说这个示例不是简单罗列全部历史条目而是只统计用户通过地址栏omnibox手动输入并访问的网址并按输入次数降序排列、取前 10 条展示。这让最近常访问网址这个结果更有主动意图价值——它反映的是用户主动寻找的内容而非被动点击链接留下的足迹。从仓库目录结构看该示例由五个文件组成文件作用manifest.jsonManifest V3 扩展清单声明history权限、action 弹窗与后台 Service Workerpopup.html工具栏弹窗页面骨架包含结果容器typedUrl_divpopup.js核心逻辑历史搜索、访问统计、排序与 DOM 渲染service-worker.js后台 Service Worker仅安装时打印日志无实质业务clock.png扩展 action 的默认工具栏图标时钟造型契合历史/时间主题Manifest V3 配置剖析manifest.json 是理解整个扩展行为的入口其关键配置项如下{ name: Typed URL History, version: 1.3, description: Uses the chrome.history API to display in a popup the users most visited pages., permissions: [history], background: { service_worker: service-worker.js }, action: { default_popup: popup.html, default_icon: clock.png }, manifest_version: 3 }逐一解读permissions: [history]这是整个示例的技术前提。chrome.history属于敏感权限必须在清单中显式声明否则 API 调用会直接失败。扩展安装时 Chrome 会向用户明示读取浏览历史的授权请求这也是该 API 调用方必须承担的隐私义务。action.default_popup声明点击工具栏图标时打开的弹窗页面即 popup.html。default_icon指向clock.png作为工具栏图标展示。background.service_workerManifest V3 使用 Service Worker 取代了 MV2 的持久后台页面。本例的 service-worker.js 只在chrome.runtime.onInstalled时打印一条 Hello world! 日志说明该示例的业务逻辑完全集中在弹窗中后台仅作占位。key字段清单中还包含一段key扩展公钥。固定key可以保证扩展 ID 在不同安装环境下保持一致这在依赖固定 ID 的场景如chrome.storage数据关联、跨扩展通信中很实用对本示例而言它保证了示例的稳定加载。另外可以注意该扩展没有声明host_permissions也不需要在action中配置default_title因为它不向任何网站注入内容脚本只读取浏览器自身的历史数据。核心逻辑逐层拆解popup.jspopup.js 是整篇示例的灵魂代码量虽少却完整覆盖了chrome.history两个最常用 API 的组合使用。下面按执行顺序逐层拆解。第一步DOMContentLoaded 触发入口document.addEventListener(DOMContentLoaded, function () { buildTypedUrlList(typedUrl_div); });弹窗页面加载完成后将结果容器typedUrl_div的 id 传入buildTypedUrlList启动整条数据流水线。对应的容器定义在 popup.html 中body h2Recently Typed URLs:/h2 script srcpopup.js/script div idtypedUrl_div/div /body页面通过script srcpopup.js以经典方式加载脚本正文标题为 Recently Typed URLs:下方typedUrl_div将承载渲染出的ul列表。第二步chrome.history.search 抓取历史条目let millisecondsPerWeek 1000 * 60 * 60 * 24 * 7; let oneWeekAgo new Date().getTime() - millisecondsPerWeek; chrome.history.search( { text: , // Return every history item.... startTime: oneWeekAgo // that was accessed less than one week ago. }, function (historyItems) { ... } );两个参数的含义与源码注释一致text: 空字符串表示返回所有历史条目不做关键字过滤startTime: oneWeekAgo时间窗设为一周前至今oneWeekAgo由当前时间戳减去一周的毫秒数1000 * 60 * 60 * 24 * 7计算得出示例未显式指定maxResults与endTime因此时间窗口的上限为当前时刻返回条数采用chrome.history.search的默认上限且结果按访问时间倒序返回最近的在前。第三步getVisits 与闭包绑定 URL拿到historyItems数组后代码对每个条目调用chrome.history.getVisits()获取其全部访问记录for (let i 0; i historyItems.length; i) { let url historyItems[i].url; let processVisitsWithUrl function (url) { return function (visitItems) { processVisits(url, visitItems); }; }; chrome.history.getVisits({ url: url }, processVisitsWithUrl(url)); numRequestsOutstanding; }这里藏着一个典型的 JavaScript 异步编程细节processVisitsWithUrl(url)是一个工厂函数它通过闭包把当前循环迭代的url绑定进getVisits的回调参数中。源码注释明确说明了这一设计意图——Use a closure to bind the url into the callbacks args。如果直接在外层回调里引用循环变量url由于getVisits是异步回调所有回调共享同一个循环变量最终会读到循环结束后的值导致 URL 与统计结果错位。闭包工厂是规避该问题的标准写法。与此同时numRequestsOutstanding作为未完成回调计数器每次加一用于判定所有 URL 的访问记录是否都已返回。第四步transition 过滤与计数const processVisits function (url, visitItems) { for (let i 0, ie visitItems.length; i ie; i) { // Ignore items unless the user typed the URL. if (visitItems[i].transition ! typed) { continue; } if (!urlToCount[url]) { urlToCount[url] 0; } urlToCount[url]; } if (!--numRequestsOutstanding) { onAllVisitsProcessed(); } };这是整个示例最核心的过滤逻辑。visitItems[i].transition表示该次访问的过渡类型——即用户是通过什么方式到达这个页面的chrome.history支持的类型包括地址栏输入typed、链接点击link、刷新reload、自动书签auto_bookmark、表单提交form_submit等。示例只统计transition typed的记录其余类型一律continue跳过从而精准筛出用户主动在地址栏输入的网址。计数结果存放在urlToCount映射表中URL → 输入次数每次processVisits返回后递减计数器当--numRequestsOutstanding归零说明所有异步调用均已完成进入汇总阶段。第五步排序与 Top 10 渲染const onAllVisitsProcessed () { let urlArray []; for (let url in urlToCount) { urlArray.push(url); } urlArray.sort(function (a, b) { return urlToCount[b] - urlToCount[a]; }); buildPopupDom(divName, urlArray.slice(0, 10)); };汇总阶段先把计数映射的键URL收集为数组再按计数降序排序urlToCount[b] - urlToCount[a]最后用slice(0, 10)截取前 10 条交给buildPopupDom渲染。第六步动态构建可点击列表function onAnchorClick(event) { chrome.tabs.create({ selected: true, url: event.srcElement.href }); return false; } function buildPopupDom(divName, data) { let popupDiv document.getElementById(divName); let ul document.createElement(ul); popupDiv.appendChild(ul); for (let i 0, ie data.length; i ie; i) { let a document.createElement(a); a.href data[i]; a.appendChild(document.createTextNode(data[i])); a.addEventListener(click, onAnchorClick); let li document.createElement(li); li.appendChild(a); ul.appendChild(li); } }buildPopupDom通过 DOM API而非 innerHTML为每个 URL 创建lia结构避免注入风险点击链接时由onAnchorClick拦截默认行为改用chrome.tabs.create()在当前窗口的新标签页中打开该 URL源码使用selected: true表示打开后激活该标签页。配合 popup.html 中body { min-width: 250px; }的样式弹窗以紧凑的宽度展示最近一周被手动输入过的 Top 10 网址。后台 Service Worker 的角色service-worker.js 内容极简chrome.runtime.onInstalled.addListener(() { console.log(Hello world!); });它仅在扩展安装/更新时输出一条日志用于验证 Service Worker 生命周期正常。这也说明chrome.history的读取操作完全可以在弹窗等页面上下文中直接进行本示例无需后台常驻逻辑。若未来要扩展为后台定时统计并推送通知的场景则可在该文件中补充chrome.alarms与chrome.notifications的配合逻辑。运行与调试步骤原文档给出了完整的四步运行流程这里补充每步的验证要点克隆仓库获取本仓库代码gh_mirrors/ch/chrome-extensions-samples以未打包扩展方式加载打开 Chrome 的chrome://extensions开启开发者模式点击加载已解压的扩展程序选择api-samples/history/showHistory目录将扩展固定到浏览器工具栏加载成功后在扩展菜单中找到 Typed URL History点击图钉图标将其固定便于随时点击点击扩展图标查看结果在弹出的 Recently Typed URLs: 列表中查看最近一周被手动输入次数最多的 10 个网址。调试建议由于弹窗生命周期较短可以在popup.js中临时添加console.log观察historyItems与visitItems的结构注意弹窗关闭后控制台输出会消失建议先打开 DevTools 再操作。此外chrome://history页面可用来对照验证统计结果是否与真实历史一致。同 API 家族的另一应用History Override为了更全面理解chrome.history的能力边界仓库的 api-samples/history/historyOverride 提供了同 API 体系下的另一种应用——覆盖默认历史页。其 manifest.json 展示了关键差异{ chrome_url_overrides: { history: history.html }, permissions: [history, favicon] }安装该扩展后访问chrome://history会被替换为扩展自定义的历史页面。对比可见showHistory 通过chrome.historyAPI 主动查询历史数据属于程序化读取historyOverride 通过chrome_url_overrides接管浏览器内置页面属于界面替换两者可以组合使用在自定义历史页中同样调用chrome.history.search()来渲染更丰富的统计视图。这也提示读者chrome.history的能力不仅是读数据配合chrome_url_overrides、favicon权限用于加载站点图标等可以构建完整的个性化历史管理工具。权限、隐私与发布注意事项history是敏感权限它允许扩展读取完整的浏览历史属于隐私敏感级能力。加载示例时 Chrome 会在安装确认界面明确展示权限用途若发布到 Chrome 网上应用店开发者需要在隐私权声明中如实说明历史数据的采集与使用方式。数据仅存于本地从源码看统计结果只存在于弹窗进程内存中urlToCount局部变量不写入chrome.storage也不会上传任何网络弹窗关闭后数据即销毁——这从实现层面保证了示例的数据最小化。适度使用chrome.history频繁的全量search有一定开销示例通过最近一周 typed 过滤 Top 10 截断把处理量控制在较小范围这种先粗筛、再细算、后截断的三段式流水线值得在真实项目里复用。总结api-samples/history/showHistory是一个麻雀虽小五脏俱全的chrome.history入门示例从 manifest.json 的权限声明到 popup.js 中search→getVisits→transition过滤 → 闭包计数 → 降序排序 → Top 10 渲染的完整链路再到 popup.html 的弹窗骨架每一步都对应了可独立复用的工程技巧。搭配 historyOverride 示例对比学习读者即可从弹窗展示与页面接管两个维度全面掌握 Chrome 扩展读取与展示浏览器历史的实战方法。赞分享示例工程【免费下载链接】chrome-extensions-samplesChrome Extensions Samples项目地址https://gitcode.com/gh_mirrors/ch/chrome-extensions-samples点击查看免费下载相关推荐Chrome Apps UDP 网络访问实战基于 chrome-extensions-samples 的 UDP Echo 客户端示例解析Chrome Apps UDP 网络访问实战基于 chrome extensions samples 的 UDP Echo 客户端示例解析 本指南以 chro示例工程Wox 网址插件在启动器中快速打开 URL、管理最近访问记录的实现与使用指南Wox 网址插件在启动器中快速打开 URL、管理最近访问记录的实现与使用指南 导读 本文围绕 Wox 内置系统插件「网址插件」URL Plugin展开讲桌面应用AI 应用插件系统windows-rs 示例库实战指南从 crates/samples 掌握全部 windows-* 家族 crate 的运行与实现windows rs 示例库实战指南从 crates/samples 掌握全部 windows 家族 crate 的运行与实现 本文是 windows rs开发工具上一篇RPA-Python与pytest-mistralclient集成pytest-mistralclient测试自动化下一篇Swagger UI 在线验证实战指南3 类高频 Schema 校验错误的定位与修复创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

开源生态技术水位线:如何用周刊校准真实技术信号
开源生态技术水位线:如何用周刊校准真实技术信号

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/21 3:08:56

TL082CDR运放选型与电路设计实战指南
TL082CDR运放选型与电路设计实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/21 3:08:56

Voyager 的 Image Refinement:基于反向 Alpha 混合的 Gemini 图片水印无损去除原理与使用指南
Voyager 的 Image Refinement:基于反向 Alpha 混合的 Gemini 图片水印无损去除原理与使用指南

AI 应用前端 【免费下载链接】voyager Enhancement suite for Gemini, AI Studio, Claude & ChatGPT — plus a prompt manager for any websites, DeepSeek Harness included. / 面向 Gemini、AI Studio、Claude 与 ChatGPT 的增强套件;其中的提示词管理器可用… · 2026/9/21 3:08:56

Naive UI 创建适配主题的自定义组件:n-config-provider、n-element 与 useThemeVars 全面指南
Naive UI 创建适配主题的自定义组件:n-config-provider、n-element 与 useThemeVars 全面指南

前端UI组件 【免费下载链接】naive-ui A Vue 3 Component Library. Fairly Complete. Theme Customizable. Uses TypeScript. Fast. 项目地址: https://gitcode.com/gh_mirrors/na/naive-ui 点击查看 免费下载 Naive UI 不仅内置了数十个开箱即用的主题化组件&… · 2026/9/21 3:45:03

如何给SumatraPDF贡献代码?从构建、调试到提交PR的完整开发者指南
如何给SumatraPDF贡献代码?从构建、调试到提交PR的完整开发者指南

如何给SumatraPDF贡献代码?从构建、调试到提交PR的完整开发者指南 【免费下载链接】sumatrapdf SumatraPDF reader 项目地址: https://gitcode.com/gh_mirrors/su/sumatrapdf SumatraPDF 是一款免费的开源多格式文档阅读器(支持 PDF、EPUB、MOBI、… · 2026/9/21 3:44:02

Readest OPDS 分组轮播实现解析:基于 react-virtuoso 的虚拟化横向卡片滑轨与懒加载封面
Readest OPDS 分组轮播实现解析:基于 react-virtuoso 的虚拟化横向卡片滑轨与懒加载封面

桌面应用跨平台前端 【免费下载链接】readest Readest is a modern, feature-rich ebook reader designed for avid readers offering seamless cross-platform access, powerful tools, and an intuitive interface to elevate your reading experience. 项目地址:… · 2026/9/21 3:43:02

使用 Go 标准库 time 正确处理时间:Uber Go Style Guide 时间处理实践全解析
使用 Go 标准库 time 正确处理时间:Uber Go Style Guide 时间处理实践全解析

文档教程代码质量Lint 【免费下载链接】guide The Uber Go Style Guide. 项目地址: https://gitcode.com/gh_mirrors/gu/guide 点击查看 免费下载 导读 时间处理是 Go 开发中最容易被低估的复杂度来源——"一天有 24 小时""一小时有 60 分钟"… · 2026/9/21 3:43:02

Toonflow是什么?AI短剧工厂完整指南:2小时把小说变成成片,创作效率提升10倍
Toonflow是什么?AI短剧工厂完整指南:2小时把小说变成成片,创作效率提升10倍

Toonflow是什么?AI短剧工厂完整指南:2小时把小说变成成片,创作效率提升10倍 【免费下载链接】Toonflow-app Toonflow 是一款 AI 短剧漫剧工具,能够利用 AI 技术将小说自动转化为剧本,并结合 AI 生成的图片和视频&#… · 2026/9/21 3:42:02

Macrotrends 历史金融数据提取实战:基于 browser-harness 的四种无浏览器抓取模式
Macrotrends 历史金融数据提取实战:基于 browser-harness 的四种无浏览器抓取模式

Macrotrends 历史金融数据提取实战:基于 browser-harness 的四种无浏览器抓取模式 【免费下载链接】browser-harness Browser Harness | Self-healing harness that enables LLMs to complete any task. 项目地址: https://gitcode.com/gh_mirrors/br/browser-har… · 2026/9/21 3:42:02

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化
Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡… · 2026/9/21 0:02:39

Word表格编号全攻略:从列表编号到题注交叉引用
Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技… · 2026/9/21 0:02:39

从第一个站到第二个站:独立开发者的静态网站选型与落地实践
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&… · 2026/9/20 0:00:41

Claude Code 按智谱AI指南装完,ANTHROPIC_BASE_URL 改走 TaoToken 兼容通道行不行
Claude Code 按智谱AI指南装完,ANTHROPIC_BASE_URL 改走 TaoToken 兼容通道行不行

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/21 0:00:18

agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程
agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程

agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程 【免费下载链接】agentic-awesome-skills AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and … · 2026/9/21 0:00:18

gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析
gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析

gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析 【免费下载链接】gin-vue-admin 🚀ViteVue3Gin拥有AI辅助的基础开发平台,企业级业务AI开发解决方案,内置mcp辅助服务,内置skills管理,… · 2026/9/21 0:00:18

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码