首页 > 解决方案 > Chrome 扩展中的 Web3js 脚本注入

问题描述

我知道对于 Chrome 扩展脚本注入的一般情况,已经有人问过这个问题。我正在询问我的特定 Web3js 用例,看看是否有人有更好的想法,这样我就不需要注入了。


我正在尝试从 Chrome 扩展程序签署以太坊交易。为此,我正在使用 Web3.js。但是,我需要访问 window 变量来实例化 web3。就像是:

    if (window.ethereum) {
      // current web3 providers
      window.web3 = new Web3(window.ethereum);
      await window.ethereum.enable();
    } else if (window.web3) {
      // fallback for older web3 providers
      window.web3 = new Web3(window.web3.currentProvider);
    } else {
      // no web3 provider, user needs to install one in their browser
      window.alert('No injected web3 provider detected');
    }

由于 Chrome 扩展的 content_scripts 无法访问浏览器的窗口,我不得不同时注入 web3js 代码和使用它的脚本,如下所示:

// inject script.js into the page.
var s = document.createElement('script');
s.src = chrome.runtime.getURL('js/script.js');
s.onload = function() {
    this.remove();
};
var w = document.createElement('script');
w.src = chrome.runtime.getURL('third-party/web3.min.js');
w.onload = function() {
    this.remove();
};
(document.head || document.documentElement).appendChild(w).appendChild(s);

这工作正常。但是,大多数主要网页都有一个 CSP 来阻止 unsafe-inlines 和 unsafe-evals,这两种方法都发生在这种方法中。因此,我的扩展仅适用于没有此 CSP 的网页。

谁能想到一种更好的方法来实现我想要实现的目标,或者至少是一种绕过 CSP 的方法?

标签: javascriptgoogle-chrome-extensionethereumweb3js

解决方案


有几种解决方案:

  • 使用 chrome.webRequest.onHeadersReceived 事件剥离/修改站点的 CSP 标头,请参阅此示例(它用于不同的标头,因此您将更改名称)。

  • 修改库,使其不使用 eval

  • 在通过web_accessible_resources公开的 iframe 中运行库。该 iframe 将是一个类似于弹出/选项页面的扩展页面,您可以在 manifest.json 中应用您自己的 CSP,更多信息

    因此,内容脚本不会添加third-party/web3.min.js,而是会添加一个 iframe:

    var iframe = document.createElement('iframe');
    iframe.src = chrome.runtime.getURL('iframe.html');
    document.documentElement.appendChild(iframe);
    

    iframe.html:

    <script src="iframe.js"></script>
    <script src="third-party/web3.min.js"></script>
    

    消息传递会有些复杂。您的页面脚本 (script.js) 可以使用CustomEvent 消息与内容脚本进行通信,而内容脚本又可以使用 chrome.runtime 消息与 iframe 进行通信,例如。或者,直接使用externally_connectablesender.tab.id消息传递,以便页面脚本(和网页本身)可以将消息发送到任何扩展脚本(iframe 脚本也会看到它并通过与通过 chrome.xml 获得的自己的标签 ID进行比较来决定是否应该处理它。 tabs.getCurrent)。


推荐阅读