Chrome 通过扩展访问网页的`window`/DOM/HTML

u2nhd7ah  于 2023-05-27  发布在  Go
关注(0)|答案(2)|浏览(230)

我正在写一个Chrome扩展程序,并试图在popup.html文件中单击按钮时将<div>覆盖在当前网页上。
当我从popup.html中访问document.body.insertBefore方法时,它会覆盖弹出窗口上的<div>,而不是当前网页。
为了访问网页的DOM,我必须在background.html和popup.html之间使用消息传递吗?我想做的一切popup.html,并使用jQuery太,如果可能的话。

gstyhher

gstyhher1#

**问题:**扩展页面(弹出、选项、MV 2中的背景页等)与网页是分开的,它们有自己的DOM、documentwindowchrome-extension:// URL。

  • 注意,service worker根本没有任何DOM/document/window。
  • 检查扩展use its own devtools的每个上下文。
    **解决方案:使用content script**访问网页或与其内容进行交互。
  • 内容脚本在网页中执行,而不是在扩展中执行。
  • 默认情况下,内容脚本是隔离的,请参阅how to run code in page context(又名MAIN world)。
  • 不要在扩展页面中加载内容脚本。

方法一。声明性

manifest.json:

"content_scripts": [{
  "matches": ["*://*.example.com/*"],
  "js": ["contentScript.js"]
}],

它将在页面加载时运行一次。在此之后,使用messaging
警告!它不能发送DOM元素、Map、Set、ArrayBuffer、类、函数等。它只能发送JSON兼容的简单对象和类型,因此您需要手动提取所需的数据并将其作为简单的数组或对象传递。

方法二。程序化

*ManifestV3

在扩展脚本中使用chrome.scripting.executeScript(比如popup),根据需要将内容脚本/函数注入到标签中。
此方法的结果是内容脚本中的最后一个表达式,因此可用于提取数据。数据必须与JSON兼容,请参阅上面的警告。
manifest.json中所需的permissions

  • "scripting"-强制性;
  • "activeTab"-理想的场景,适合响应用户操作(通常是单击工具栏中的扩展图标)。安装扩展时不显示任何权限警告。

如果理想的场景是不可能的,则将允许的站点添加到manifest.json中的host_permissions

  • "*://*.example.com/"加上你想要的任何其他网站。
  • "<all_urls>""*://*/"这些扩展程序将在Chrome网上应用商店中进入超级缓慢的审查队列,因为有广泛的主机权限。
    *V2与上述的区别:
  • 使用chrome. tabs. executeScript。
  • permissions中指定站点。
oo7oh9g9

oo7oh9g92#

一些使用编程注入来添加div的扩展弹出脚本的例子。

ManifestV3

不要忘记在manifest.json中添加权限,请参阅其他答案以获取更多信息。

*简单调用:

(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,
  };
}

ManifestV2

*简单调用:

// 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毫秒,因此可以忽略不计。

相关问题