从扩展访问网页的“window”/DOM/HTML

Accessing `window`/DOM/HTML of the webpage from the extension

提问人:Steven 提问时间:12/26/2010 最后编辑:wOxxOmSteven 更新时间:9/12/2023 访问量:76656

问:

我正在编写一个 Chrome 扩展程序,并尝试在弹出 .html 文件中单击按钮后立即覆盖当前网页。<div>

当我从弹出窗口 .html 中访问该方法时,它会覆盖弹出窗口,而不是当前网页。document.body.insertBefore<div>

我是否必须在 background.html 和 popup.html 之间使用消息传递才能访问网页的 DOM?我想在popup.html中做所有事情,如果可能的话,也使用jQuery。

谷歌浏览器 扩展程序

评论


答:

138赞 Mohamed Mansour 12/26/2010 #1

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

解决方案:使用内容脚本访问网页或与其内容进行交互。

  • 内容脚本在网页中执行,而不是在扩展中执行。
  • 默认情况下,内容脚本是隔离的,请参阅如何在页面上下文(又名 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 与上述内容的区别:

评论

0赞 Alex 11/29/2022
在哪里可以找到脚本?contentScript.js
2赞 wOxxOm 1/6/2023
你自己创建它。
12赞 wOxxOm 4/23/2021 #2

使用编程注入添加该 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