Ste*_*ven 63 google-chrome google-chrome-extension
我正在编写Chrome扩展程序,并<div>在popup.html文件中单击按钮后尝试覆盖当前网页.
当我document.body.insertBefore从popup.html中访问该方法时,它会覆盖<div>弹出窗口而不是当前网页.   
我是否必须在background.html和popup.html之间使用消息传递才能访问网页的DOM?我想在popup.html中做所有事情,并且如果可能的话也使用jQuery.
Moh*_*our 105
如Chrome扩展程序概述中所述:体系结构(必读):
如果您的扩展需要与网页交互,那么它需要一个内容脚本.内容脚本是一些JavaScript,它在已加载到浏览器中的页面的上下文中执行.将内容脚本视为该加载页面的一部分,而不是作为其打包的扩展(其父扩展)的一部分.
browserAction弹出窗口是您单击浏览器工具栏中的图标时看到的页面,它是带有chrome-extension://URL 的HTML页面,因此当您访问其DOM时,您正在影响弹出窗口.这同样适用于扩展的背景/选项页面.
要访问/操作网页DOM,您有两种方法:
chrome.tabs.sendMessage()从你的后台/弹出页面到注入的内容脚本的chrome.runtime.onMessage监听器,它将sendResponse根据文档在网页上执行操作并通过回调传输结果(注意:只支持JSON可用的对象,如数字,字符串,数组,简单对象,这意味着不是DOM元素,不是类,不是函数).如果内容脚本需要启动与扩展页面的通信,它应该使用chrome.runtime.sendMessage().
或者使用Tabs API注入内容脚本:
chrome.tabs.executeScript(tabId, details, callback)
所需的权限:"tabs","https://www.example.com/*"
(或"<all_urls>"及其变种类似"*://*/*","http://*/*","https://*/*")
在显式用户激活的情况下,更好的选择是使用"activeTab"权限而不是"tabs"并且"<all_urls>"因为它可以作为许多用途的替代"<all_urls>",但在安装期间不显示警告消息.
.executeScript()可以与回调函数一起使用,该函数接收注入的内容脚本中的最后一个计算表达式的数组,每个帧中的一个元素在注册表中注入.Chrome 在内部使用JSON.parse()和JSON.stringify()结果,从而将支持的类型限制为普通对象和简单的可字符串值,如数字/字符串或其数组.
因此它不适用于DOM元素,函数,自定义属性,getter/setter:您需要手动映射/提取所需数据并将其传递到一个简单的数组/对象中.
内容脚本在称为孤立世界的特殊环境中执行.他们可以访问注入页面的DOM,但不能访问页面创建的任何JavaScript变量或函数.它将每个内容脚本视为在其运行的页面上没有执行其他JavaScript.反过来也是如此:页面上运行的JavaScript无法调用任何函数或访问内容脚本定义的任何变量.
仍然可以更深入地访问网页JavaScript变量/函数.
作为第二种方法的示例,让我们在单击浏览器操作时显示div.
我们将chrome.tabs.executeScript()在browserAction单击处理程序中使用内容脚本文件(或文字代码字符串,如果它很小,请参阅方法的文档)到该页面的DOM.
var someVar = {text: 'test', foo: 1, bar: false};
chrome.tabs.executeScript({
    code: '(' + function(params) {
        document.body.insertAdjacentHTML('beforeend',
            '<div style="all:unset; position:fixed; left:0; top:0; right:0; bottom:0;' +
                'background-color:rgba(0,255,0,0.3)">' + params.text + '</div>'
        );
        return {success: true, html: document.body.innerHTML};
    } + ')(' + JSON.stringify(someVar) + ');'
}, function(results) {
    console.log(results[0]);
});
如您所见,我们使用了函数代码的自动字符串转换,以便能够将注入的代码编写为具有语法高亮和linting的普通JavaScript.显而易见的缺点是浏览器浪费时间来解析代码,但通常它不到1毫秒,因此可以忽略不计.
wOx*_*xOm 13
使用编程注入来添加该 div 的扩展弹出脚本的一些示例。
不要忘记在 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,
  };
}
简单的调用:
// 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
  }
});
此示例使用inContent函数代码自动转换为字符串,这样做的好处是 IDE 可以应用语法高亮和 linting。明显的缺点是浏览器会浪费时间来解析代码,但通常不到 1 毫秒,因此可以忽略不计。
| 归档时间: | 
 | 
| 查看次数: | 50018 次 | 
| 最近记录: |