ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

GeoLibre Chrome 扩展「Open data in GeoLibre」深度解析:最小权限设计、数据链接发现与 Chrome Web Store 上架实践

GeoLibre Chrome 扩展「Open data in GeoLibre」深度解析:最小权限设计、数据链接发现与 Chrome Web Store 上架实践 GeoLibre Chrome 扩展「Open data in GeoLibre」深度解析最小权限设计、数据链接发现与 Chrome Web Store 上架实践【免费下载链接】GeoLibreA lightweight, cloud-native GIS platform for visualizing, exploring, and analyzing geospatial data. It runs in the web browser, on the desktop, on mobile, and inside Jupyter notebooks.项目地址: https://gitcode.com/GitHub_Trending/ge/GeoLibre本文以 GeoLibre 仓库中 STORE_LISTING.md 这份 Chrome Web Store 上架清单为主体完整梳理扩展的命名、描述文案、分类与权限声明并结合 scanner.mjs、service-scanner.mjs、url-builder.mjs 等源码与 chrome-extension.test.ts 测试用例说明这些文案背后的实际实现——链接如何被识别、地图服务如何被还原、深链如何被构建——以及从源码到可发布 ZIP 的完整打包流程。读完本文你既能理解一份“可直接粘贴进商店后台”的权限说明为何这样写也能掌握该扩展的本地加载、打包与验证方式。扩展定位把数据目录页变成地图的发射台商店清单为该扩展定义的身份如下均为 STORE_LISTING.md 原文内容的逐条对应名称NameOpen data in GeoLibre摘要SummaryFind geospatial datasets and map services on a webpage and open them in GeoLibre.在网页中发现地理空间数据集与地图服务并在 GeoLibre 中打开它们。分类CategoryDeveloper Tools语言LanguageEnglish详细描述部分说明了它的工作方式把数据集目录、文档页面和项目网站变成交互地图的“发射台”。点击扩展图标后用户可以在当前页面中找到受支持的数据链接、按矢量/栅格类型过滤、勾选所需文件然后一起在 GeoLibre 中打开。清单宣称的能力边界可以归纳为三类静态文件链接GeoJSON、GeoParquet、PMTiles、Cloud-Optimized GeoTIFFCOG以及包含 GeoJSON 的 ZIP 压缩包结构化元数据与既有链接读取 schema.org 下载元数据、识别既有的 GeoLibre 深链、把匹配的 GeoLibre 样式文件与数据集配对并在虚拟化的 Source Cooperative 仓库页面上恢复完整的文件清单交互式地图服务识别当前页面已经发出的 WMS、WMTS、WFS、OGC API Features、ArcGIS Feature Service、XYZ/TMS 与矢量瓦片请求。这些能力与 manifest.json 中的字段一一对应name为 Open data in GeoLibredescription为 Find geospatial datasets and services used by the current page and open them in GeoLibre.当前版本0.3.1minimum_chrome_version为 106。整个扩展由 7 个运行时文件构成manifest、popup.html/css/mjs、scanner.mjs、service-scanner.mjs、url-builder.mjs加 4 个图标这一点在打包脚本 package-chrome-extension.mjs 的runtimeFiles列表中可以得到确认。商店权限声明为何只需要 activeTab 和 scriptingSTORE_LISTING.md 中最核心的部分是逐字段可直接粘贴进 Chrome Web Store 后台 Privacy 页签的权限论证Permission justification。清单明确给出了一条维护规则这些文字块必须与manifest.json保持同步manifest 中新增的每一项权限都必须在这里和商店后台有对应的论证否则该版本会被拒审。截至 0.3.0manifest 只请求activeTab和scripting因此 storage、webRequest 与 host 权限的说明字段不再出现。manifest.json 的实际内容印证了这一声明——permissions数组中只有两项且没有任何host_permissions字段permissions: [activeTab, scripting],activeTab 的论证清单为activeTab给出的原文论证是该权限仅在用户点击扩展工具栏图标后授予对当前页面的临时访问权。扩展利用该访问权读取页面链接与结构化元数据从中挑出 GeoJSON、GeoParquet、PMTiles、COG、含 GeoJSON 的 ZIP 等地理空间数据集列入弹窗供用户选择。用户离开或刷新页面后访问即结束任何其它时刻都不会读取页面内容。从源码看这一承诺对应的执行路径在 popup.mjs 的inspectPage()中弹窗打开时先chrome.tabs.query({ active: true, currentWindow: true })拿到当前标签页再用chrome.scripting.executeScript把 scanDocumentForDatasets 注入页面执行。没有任何后台 service worker也没有任何监听器——扩展的全部行为都发生在“图标被点击”这个时刻之后。scripting 的论证清单为scripting给出的论证是用户打开弹窗时该权限把两个打包在扩展内的函数注入活动标签页。第一个函数读取页面链接与元数据以发现数据集文件第二个函数读回页面已经发出的请求地址以便识别页面地图所使用的服务——因为地图是从 JavaScript 发起这些请求的它们从来不是文档中的链接。两个函数都包含在扩展包内不涉及任何远程代码每次调用只运行一次并把结果返回给弹窗。对应到源码第二个函数正是 collectRequestedUrls它调用performance.getEntriesByType(resource)读回每个文档自己维护的 Resource Timing 缓冲只保留 http/https 条目。popup.mjs中第二次executeScript使用allFrames: true从顶层框架及所有同源子框架各取一次再汇总交给collectServiceCandidates归类。注释里特别说明Chrome 对跨源框架的注入按帧拒绝因此可达的同源框架仍会返回各自的缓冲。明确“不请求”什么清单同样用一整节说明扩展不请求什么没有 host 权限、没有监听网络请求的权限、没有存储权限、没有后台运行不请求浏览历史、下载记录、Cookie、活动标签之外的标签页或远程代码。商店问卷中关于远程代码的问题应回答“No, I am not using remote code”——因为它运行的每一个脚本都随包分发。这一点在 manifest 的 CSP 中得到代码级佐证content_security_policy: { extension_pages: script-src self; object-src self }script-src self在策略层面封死了远程脚本注入的可能与清单声明互相咬合。配套的可发布隐私政策源文件在 PRIVACY.md商店提交前需要把该政策托管到一个公开 URL 上这一要求也写在 README.md 的打包章节中。数据链接发现清单承诺在源码里的落点清单宣称的“受支持链接”清单——GeoJSON、GeoParquet、PMTiles、COG、ZIP、schema.org 元数据、既有 GeoLibre 链接、样式配对、Source Cooperative 完整文件清单——在 scanner.mjs 的scanDocumentForDatasets()中有完整的逐条实现。分类规则扩展名、线索与置信度核心函数classify(url, hint)按优先级判定格式并给出 1–3 的置信度判定条件格式类型置信度路径以.geojson结尾或线索含 geojson / geojson / feature collectionGeoJSON矢量3.geoparquet/.parquet结尾或线索含 geoparquet / parquetGeoParquet矢量3.pmtiles结尾或线索含 pmtilesPMTiles矢量3.tif/.tiff/.cog结尾或线索含 geotiff / cloud optimized / cogGeoTIFF栅格3.zip结尾或线索含 application/zip、geojsonzip 组合ZIP矢量2.json结尾且线索含 geo/spatial/vector/dataset 等词JSON矢量1注意其中的一个关键防误报设计当 URL 明显是网页.html等页面扩展名或尾斜杠目录式路径且链接文本“复读”了 slug 中的词时同样的词汇只描述页面本身而不是数据此时线索判定被禁用。chrome-extension.test.ts 中专门有一个用例验证这一点文档站链接 “Add a GeoJSON line” 指向/examples/add-a-geojson-line/这类 HTML 页面不会被误报为数据集。扫描面锚点、资源链接、数据属性与 JSON-LDscanDocumentForDatasets的扫描面覆盖了清单与 README 描述的四个来源a[href]与link[href]线索取自type、rel、download、title属性与链接文本的拼接[data-url]、[data-href]、source[src]三类元素对应清单中“selected data attributes”所有script[typeapplication/ldjson]块递归遍历其中对象的contentUrl与downloadUrl字段线索取自encodingFormat、fileFormat、name、description对应“schema.org JSON-LD”Source Cooperative 仓库页的 Next.js 内嵌清单下文单列。去重与合并策略是以规范化后的 URL 为键高置信度候选覆盖低置信度候选若已有候选没有样式而新候选带来样式则补挂样式而不替换数据集。样式配对与既有深链解包清单提到“pairs matching GeoLibre style files”实现上所有…style.json/…geolibre.style.json结尾的链接被单独收集进styleLinks最后按“去掉扩展名后的文件主干”与数据集做匹配——roads.geojson与roads.style.json或roads.geolibre.style.json互为配对测试用例pairs a neighboring style by filename stem验证了这一行为。“understands existing GeoLibre links”对应另一段逻辑若链接本身是geolibre.app域名下带data查询参数的深链扩展会解包其中的每一对data/style参数并递归加入候选使它们能与页面上其它链接组合后再一起打开。站点特化Source Cooperative 与 Hugging Face清单中“discovers the complete file inventory on virtualized Source Cooperative repository pages”的实现值得细看Source Coop 的仓库列表页做了虚拟滚动DOM 中只有可见行是锚点但其 Next.js 载荷self.__next_f.push脚本块里仍嵌有当前目录的完整对象清单。扫描器从这些脚本中提取每个path:...,type:file条目拼接到公开数据主机data.source.coop下从而把不可见的文件也变成可选数据集并与页面上已可见的 page/download 重复链接去重规范化到同一data.source.coop主机是去重的前提测试用例reads Source Cooperatives complete virtualized inventory...覆盖了这一行为包括把形似文件格式的/products?tagscloud optimised geotiff导航链接排除在外。此外还有一个未在清单摘要中点名、但同属“链接规范化”的实现Hugging Face Hub 的同一文件可从 blob/raw/blame/edit/delete/commits/resolve 等七条路由链接到而只有resolve路由会 302 到能供地图数据源读取字节的 CDN 地址。扫描器按路由在路径中的位置而非第一个匹配段解析仓库路径把七条路由折叠成一条resolveURL并去掉行锚点以免一个文件被拆成两条候选——对应测试collapses every Hugging Face file route onto the direct resolve URL等三、四个用例。交互式服务识别读回请求而非监听网络清单承诺识别“当前页面已经发出”的七类服务请求。README 与源码共同说明了这套机制的完整逻辑与边界这也是商店文案中“runs no network watcher”声明的技术基础。原理Resource Timing 缓冲地图从 JavaScript 拉取瓦片与服务文档这些 URL 从不出现在文档链接里。扩展读的是performance.getEntriesByType(resource)——每个文档为自身加载记录在案的资源时序缓冲——从顶层框架与所有同源子框架分别收集。service-scanner.mjs 的classifyServiceRequest()把这些 URL 归一成 GeoLibre 可打开的服务候选WMS / WMTS / WFS按service与request参数识别如 WMS 的 GetCapabilities/GetMap/GetFeatureInfo。端点还原时会剥掉 OGC 操作参数bbox、layers、styles、tilematrixset等一长串白名单但保留token之类的签名参数WMTS GetTile 特例把TileMatrix/TileCol/TileRow三个数值参数还原为{z}/{x}/{y}占位符生成可直接渲染的瓦片模板——比裸端点更有价值因为模板已经携带了层名、矩阵集与格式ArcGIS Feature Service正则匹配…/FeatureServer[/N]路径并保留子图层索引N——因为只给裸FeatureServer时 GeoLibre 会回退到服务的第一个要素层对页面正在显示其它层的站点会静默画错层OGC API Features/collections/id/items路径足以独立成立裸/collections则必须伴随 OGCf格式参数才算数商店站点恰好也有/collections这种普通路由测试用例recognizes OGC API Features and ArcGIS feature service requests明确验证/collections?page2之类不被误判瓦片 URL/…/6/17/25.png形式的坐标路径被折叠为{z}/{x}/{y}模板并按坐标合法性校验如column 2^zoom以避开日期组织的资产目录/uploads/2024/03/15.png这类路径在测试中被明确排除.pbf/.mvt判为矢量瓦片其余图片格式判为 XYZ/TMS 栅格瓦片。随服务一起携带的“层”与“样式”清单说这些服务“the current page has already made”README 进一步解释了为什么结果还要携带额外字段光有一个端点通常不足以加层所以每个结果还带上页面向该服务请求的层——WMS 的LAYERS值、WFS 的typeName、WMTS 的层名以及矢量瓦片集所加载的同源样式文档。这些以serviceLayer与serviceStyle参数进入 GeoLibre落入对应表单字段使 Add Data 对话框以“可立即提交”的状态打开而不是落在一个图层字段为空的端点上。由于一个端点可服务多个层结果按层列出如WMS service: topp:states而不是按 URL 合并——测试keeps two layers of one service apart despite their shared endpoint验证同一 WMS 端点的roads与rivers两层各自独立保留。三个设计边界README 明示的取舍Worker 请求不可见MapLibre 等渲染器从 web worker 里拉矢量瓦片worker 的时序记录在自己的时间线上文档缓冲里看不到。此类瓦片集从主线程确实获取的元数据恢复优先 TileJSON按文件名tile.json、tiles.json、tilejson.json识别再退而求其次用样式文档——GeoLibre 可以从样式单独解析出层。样式只在它的来源上没发现任何瓦片集时才作为独立候选提供。由于从不读取响应体描述栅格瓦片的 TileJSON 与矢量瓦片无法区分、会按矢量提供——这种误报无法成为图层Add Data 提交时会解析文档并在解析不出源层时拒绝而在这里读响应体需要跨源抓取恰恰需要本设计要规避的 host 权限缓冲有限Resource Timing 每个文档默认只保留 250 条记录且满后停止记录。很繁忙的页面可能丢掉后加入的服务提高上限需要document_start注入脚本与宽泛 host 权限因此该上限被明确接受。对应地候选总数在collectServiceCandidates中被MAX_SERVICE_CANDIDATES 100封顶且封顶时先扣普通服务、为样式回退候选保留名额测试keeps room for a style fallback on a page that fills the cap验证了这一点跨源框架不可达activeTab只授予标签页主框架的来源Chrome 不会把该授权延伸到他源框架allFrames: true因此只能覆盖顶层与其同源框架跨源框架注入被逐帧拒绝可达框架仍返回缓冲。完全运行在跨源 iframe 里的地图对扫描不可见弹窗会报“无服务”而不是报错——要触达它需要该来源的 host 权限即本设计刻意回避的常驻访问。深链构建从勾选到 GeoLibre 表单用户勾选条目后url-builder.mjs 的buildGeoLibreUrl()负责把选择翻译成一个 GeoLibre 深链基础地址为 GeoLibre Web 入口见文件顶部常量。其参数协议如下数据集可多选每个数据集追加一个data参数若任一数据集带样式则按位置一一对应地追加style参数无样式的条目以空串占位保证位置对齐。地图服务限单选七类服务的格式名被映射为add参数值——XYZ / TMS→xyz、WMS→wms、WMTS→wmts、WFS→wfs、OGC API→ogc-features、ArcGIS Feature Service→arcgis、Vector tiles→ogc-vector-tiles——并追加serviceUrl请求携带的层与样式分别进serviceLayer与serviceStyle。该函数内置一组显式校验全部有对应测试tests/chrome-extension.test.ts的 URL builder 描述块空选择抛错 “Select at least one dataset.”两个以上服务同选抛错 “Open one map service at a time.”服务与其它数据混选抛错 “A map service cannot be opened together with other data.”服务走add…入口文件走data入口两者在 GeoLibre 侧是不同入口点;任何非 http/https 的 URL包括file://与清单中提到的blob:临时链接抛出 “GeoLibre can only open HTTP or HTTPS …”——这与商店描述中 “Temporaryblob:links cannot be transferred” 的边界声明完全一致服务 URL 与其样式 URL 相同时只给serviceStyle而不重复serviceUrl避免 GeoLibre 把样式文档再当 TileJSON 解析一次而失败。传输边界CORS、签名参数与会话凭证商店详细描述与 PRIVACY.md 共同界定了数据流边界这部分内容应视为对部署方的直接约束CORS 前置条件数据集服务器必须允许浏览器跨源访问CORS否则 GeoLibre 端抓取会失败完整 URL 原样转发完整的 HTTP(S) URL包括签名查询参数、URL 内嵌的访问令牌被逐字放入深链查询串因此清单提醒不要把包含你不愿发送给 GeoLibre 的信息的 URL 选进去会话凭证不转发Cookie 与其它浏览器会话凭证不会随选择转发依赖 Cookie 或会话认证的链接可能失效blob: 不可迁移临时blob:链接与浏览器内部链接无法传输对应 url-builder 的协议校验;扩展本身不抓取数据集GeoLibre 直接向上游服务器请求数据扩展从不持久化任何 URL——列表只存在于弹窗打开期间关闭即丢弃。本地开发与商店打包本地加载开发态按 README.md 的步骤打开chrome://extensions启用Developer mode选择Load unpacked指向extensions/geolibre-chrome目录。之后的一切发生在点击工具栏图标之后扫描文档链接、读回各可达框架的 Resource Timing 缓冲除activeTab与scripting外不持有任何权限没有后台 service worker不存储任何东西。README 还附了一张手工验证矩阵可作为验收标准针对 WMS、WMTS、WFS、OGC API Features、ArcGIS Feature Service、XYZ 栅格瓦片、同源 iframe 中的矢量瓦片七类真实第三方地图示例页逐一确认扩展列出预期服务且选中后打开的 Add Data 对话框字段已填好——“对话框打开但必填字段为空”被定义为 bug 而非预期步骤。打包为商店上传 ZIP在仓库根目录执行npm run build:chrome-extension该脚本由 scripts/package-chrome-extension.mjs 实现读取 manifest 版本号按runtimeFiles清单收集 7 个运行时文件与 4 个图标用fflate以最大压缩级别、固定 mtime1980-01-01打成确定性 ZIP输出到dist/geolibre-chrome-version.zip如dist/geolibre-chrome-0.3.1.zip。固定 mtime 保证同一版本重复打包得到逐字节一致的归档便于审计与分发。回归验证整个识别与构建逻辑由 tests/chrome-extension.test.ts 以 node:test 覆盖共四个描述块scanner / URL builder / service request scanner / request history用例包括JSON-LD 无扩展名下载端点、文档链接措辞防误报、Source Coop 虚拟化清单恢复与规范化、Hugging Face 七路由折叠、WMTS GetTile 模板还原、同一端点多层去重、250 条缓冲下的样式回退保位、100 条候选封顶等——商店文案中承诺的每一项行为基本都能在该文件中找到可执行的断言。小结STORE_LISTING.md 表面上是一份上架文案实质是 GeoLibre Chrome 扩展的契约文件它声明的能力发现文件链接、识别七类服务、只读当前页、不存储、无后台、它论证的权限仅activeTabscripting且与 manifest 同步维护、它声明的边界CORS、签名参数转发、会话凭证不转发、blob: 不可迁移都能在 manifest.json、scanner.mjs、service-scanner.mjs、url-builder.mjs 与 chrome-extension.test.ts 中找到逐条对应的实现与断言。对维护者而言清单与 manifest 的同步规则新增权限即需补写两处论证否则拒审是该文件最重要的一条操作规范对使用者而言理解“读回请求而非监听网络”这一机制就理解了它在能力覆盖worker 瓦片、跨源 iframe、250 条缓冲上限上的全部边界所在。【免费下载链接】GeoLibreA lightweight, cloud-native GIS platform for visualizing, exploring, and analyzing geospatial data. It runs in the web browser, on the desktop, on mobile, and inside Jupyter notebooks.项目地址: https://gitcode.com/GitHub_Trending/ge/GeoLibre创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表