Chrome扩展:如何在background.js中访问window对象?
需求背景
在微软开发环境中,所有自定义控件均从服务器拉取并通过iframe渲染。开发者修改控件后,必须上传更新后的HTML、完成发布再刷新页面才能查看效果,流程繁琐低效。我们计划开发一款Chrome扩展,拦截向微软服务器发送的控件请求,转而返回本地服务器(通常部署在localhost)上的内容,让开发者可以直接在本地修改Web资源并实时预览。
当前实现与遇到的问题
我已经编写了两段请求拦截的代码,大部分功能符合预期,但遇到核心问题:在background.js中无法访问window对象,这是Chrome扩展安全政策的限制导致的。
代码片段1:返回Blob生成的内容
chrome.webRequest.onBeforeRequest.addListener( (details) => { // 检查请求URL是否匹配目标地址 if (details.url.includes("webresources/gc_relatedproductcontrol")) { var myblob = new Blob(["<html><body>Hello</body></html>"], { type: 'text/html' }); let url = URL.createObjectURL(myblob); return { redirectUrl: url }; } }, { urls: ["<all_urls>"], types: ["xmlhttprequest", "main_frame", "sub_frame", "stylesheet", "script", "image", "object", "xmlhttprequest", "other"] }, ["blocking"] );
代码片段2:重定向到本地服务器
chrome.webRequest.onBeforeRequest.addListener( (details) => { // 检查请求URL是否匹配目标地址 if (details.url.includes("webresources/gc_relatedproductcontrol")) { return { redirectUrl: "http://locahost:3000/gc_relatedproductcontrol.html" }; } }, { urls: ["<all_urls>"], types: ["xmlhttprequest", "main_frame", "sub_frame", "stylesheet", "script", "image", "object", "xmlhttprequest", "other"] }, ["blocking"] );
解决方案思路
Chrome扩展的background脚本运行在独立的后台上下文,没有DOM环境,因此无法直接访问window对象。如果需要操作页面DOM或获取页面相关的window属性,你需要通过以下方式实现:
使用内容脚本(Content Script):内容脚本注入到目标页面的上下文,可以直接访问页面的
window对象和DOM。你可以在background脚本中监听请求拦截后,向目标页面发送消息,触发内容脚本执行相关操作;或者让内容脚本主动与background脚本通信,传递所需的window相关信息。通过
chrome.runtime.sendMessage/onMessage实现通信:- 在content.js中监听来自background的消息,获取
window相关数据后回传给background。 - 示例流程:
- background脚本拦截请求后,发送消息到当前标签页的内容脚本。
- 内容脚本接收到消息后,获取
window对象的所需属性,再发送回background。 - background脚本根据返回的数据调整拦截逻辑或重定向行为。
- 在content.js中监听来自background的消息,获取
注意权限配置:在manifest.json中需要声明
activeTab、scripting(用于注入内容脚本)以及webRequest、webRequestBlocking等必要权限,确保扩展能正常运行。
比如,如果你需要获取页面的window.location信息来调整重定向逻辑,可以这样做:
- 在manifest.json中添加权限:
{ "permissions": ["webRequest", "webRequestBlocking", "<all_urls>", "scripting", "activeTab"] }
- 在background脚本中发送消息并等待响应:
chrome.webRequest.onBeforeRequest.addListener( async (details) => { if (details.url.includes("webresources/gc_relatedproductcontrol")) { // 获取当前标签页的内容脚本返回的window信息 const [tab] = await chrome.tabs.query({active: true, currentWindow: true}); const response = await chrome.tabs.sendMessage(tab.id, {action: "getWindowInfo"}); // 根据返回的信息调整重定向逻辑,比如结合window.origin const localUrl = `http://localhost:3000/gc_relatedproductcontrol.html?origin=${response.origin}`; return { redirectUrl: localUrl }; } }, { urls: ["<all_urls>"], types: ["sub_frame"] }, ["blocking"] );
- 在content.js中监听消息并返回window信息:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.action === "getWindowInfo") { sendResponse({ origin: window.origin, // 其他你需要的window属性 }); } });
另外,注意代码片段2中的拼写错误:locahost应该改为localhost,否则无法正确指向本地服务器。
内容的提问来源于stack exchange,提问作者Avinash Pathak

