提问人:Steven 提问时间:12/26/2010 最后编辑:wOxxOmSteven 更新时间:9/12/2023 访问量:76656
从扩展访问网页的“window”/DOM/HTML
Accessing `window`/DOM/HTML of the webpage from the extension
问:
我正在编写一个 Chrome 扩展程序,并尝试在弹出 .html 文件中单击按钮后立即覆盖当前网页。<div>
当我从弹出窗口 .html 中访问该方法时,它会覆盖弹出窗口,而不是当前网页。document.body.insertBefore
<div>
我是否必须在 background.html 和 popup.html 之间使用消息传递才能访问网页的 DOM?我想在popup.html中做所有事情,如果可能的话,也使用jQuery。
答:
问题:扩展页面(弹出窗口、选项、MV2 中的背景页面等)与网页是分开的,它们有自己的 DOM、、、和 URL。document
window
chrome-extension://
- 请注意,Service Worker 根本没有任何 DOM/document/window。
- 若要检查扩展的每个上下文,请使用其自己的 devtools。
解决方案:使用内容脚本访问网页或与其内容进行交互。
- 内容脚本在网页中执行,而不是在扩展中执行。
- 默认情况下,内容脚本是隔离的,请参阅如何在页面上下文(又名 MAIN 世界)中运行代码。
- 请勿在扩展页面中加载内容脚本。
方法 1.声明
manifest.json:
"content_scripts": [{
"matches": ["*://*.example.com/*"],
"js": ["contentScript.js"]
}],
当页面加载时,它将运行一次。发生这种情况后,请使用 消息传递 。
警告!它不能发送 DOM 元素、Map、Set、ArrayBuffer、类、函数等。它只能发送与 JSON 兼容的简单对象和类型,因此您需要手动提取所需的数据并将其作为简单数组或对象传递。
方法 2.编程
清单V3:
在扩展脚本(如弹出窗口)中使用 chrome.scripting.executeScript 按需将内容脚本/函数注入选项卡。
此方法的结果是内容脚本中的最后一个表达式,因此可用于提取数据。数据必须与 JSON 兼容,请参阅上面的警告。
manifest.json中要求:
permissions
"scripting"
-命令的;“activeTab”
- 理想场景,适用于对用户操作的响应(通常单击工具栏中的扩展图标)。安装扩展时不显示任何权限警告。
如果理想情况是不可能的,请在manifest.json中添加允许的站点:
host_permissions
"*://*.example.com/"
以及您想要的任何其他网站。"<all_urls>"
或者,由于主机权限广泛,这些会将您的扩展程序置于 Chrome 网上应用店的超慢审核队列中。"*://*/"
ManifestV2 与上述内容的区别:
- 使用 chrome.tabs.executeScript。
- 在 中指定站点。
permissions
评论
contentScript.js
使用编程注入添加该 div 的扩展弹出脚本的一些示例。
清单V3
不要忘记在manifest.json中添加权限,有关详细信息,请参阅其他答案。
简单调用:
(async () => { const [tab] = await chrome.tabs.query({active: true, currentWindow: true}); const [{result}] = await chrome.scripting.executeScript({ target: {tabId: tab.id}, func: () => document.querySelector('foo')?.textContent, }); document.body.textContent = result; })();
简单调用 2:
(async () => { const [tab] = await chrome.tabs.query({active: true, currentWindow: true}); await chrome.scripting.executeScript({ target: {tabId: tab.id}, func: inContent1, }); })(); // executeScript runs this code inside the tab function inContent1() { const el = document.createElement('div'); el.style.cssText = 'position:fixed; top:0; left:0; right:0; background:red'; el.textContent = 'DIV'; document.body.appendChild(el); }
注意:在 Chrome 91 或更早版本中应该是 .
func:
function:
使用参数调用并接收结果
需要 Chrome 92 因为它实现了。
args
示例 1:
res = await chrome.scripting.executeScript({ target: {tabId: tab.id}, func: (a, b) => { return [window[a], window[b]]; }, args: ['foo', 'bar'], });
示例 2:
(async () => { const [tab] = await chrome.tabs.query({active: true, currentWindow: true}); let res; try { res = await chrome.scripting.executeScript({ target: {tabId: tab.id}, func: inContent2, args: [{ foo: 'bar' }], // arguments must be JSON-serializable }); } catch (e) { console.warn(e.message || e); return; } // res[0] contains results for the main page of the tab document.body.textContent = JSON.stringify(res[0].result); })(); // executeScript runs this code inside the tab function inContent2(params) { const el = document.createElement('div'); el.style.cssText = 'position:fixed; top:0; left:0; right:0; background:red'; el.textContent = params.foo; document.body.appendChild(el); return { success: true, html: document.body.innerHTML, }; }
清单V2
简单调用:
// uses inContent1 from ManifestV3 example above chrome.tabs.executeScript({ code: `(${ inContent1 })()` });
使用参数调用并接收结果:
// uses inContent2 from ManifestV3 example above chrome.tabs.executeScript({ code: `(${ inContent2 })(${ JSON.stringify({ foo: 'bar' }) })` }, ([result] = []) => { if (!chrome.runtime.lastError) { console.log(result); // shown in devtools of the popup window } });
此示例使用函数代码自动转换为字符串,这里的好处是 IDE 可以应用语法突出显示和 linting。明显的缺点是浏览器浪费时间来解析代码,但通常小于 1 毫秒,因此可以忽略不计。
inContent
评论