You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome扩展内容脚本无法访问全局window对象问题求助

问题:Chrome扩展内容脚本无法访问window.phantom.solana对象?

我开发了一款Chrome扩展,能在Twitter每条推文上添加按钮,点击按钮需要调用window.phantom.solana.connect()函数。直接在浏览器控制台执行这个函数能正常运行,但在内容脚本里调用时,window对象的上下文和控制台不一样,找不到phantom.solana属性。我已经尝试过事件通信、web_accessible_resources等方法,还是没解决,请问怎么在扩展里访问到和控制台相同的window对象?

提供的代码

manifest.json

{
"manifest_version": 3,
"name": "react-boilerplate",
"description": "react-boilerplate for chrome extension",
"version": "1.0.0",
"action": {
"default_title": "React Boilerplate"
},
"permissions": ["tabs", "bookmarks", "storage", "identity", "scripting"],
"icons": {
"16": "icon.png",
"48": "icon.png",
"128": "icon.png"
},
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["https://*.twitter.com/*"],
"js": ["contentScript.js"]
}
],
"web_accessible_resources": [
{
"resources": ["web_accessible_resources.js"],
"matches": ["<all_urls>"],
"extension_ids": ["bfnaelmomeimhlpmgjnjophhpkkoljpa"]
}
]
}

内容脚本代码

import React from "react";
import { createRoot } from "react-dom/client";
import "../assets/tailwind.css";
import ContentScript from "./contentScript";

function init() {
const appContainer = document.createElement("div");
if (!appContainer) {
throw new Error("Cannot find app container");
}

const root = createRoot(appContainer);
const articleList = window.document.querySelectorAll("article");
root.render(<ContentScript />);

for (const element of articleList) {
var btn = document.createElement("button");

    btn.appendChild(document.createTextNode("Bonk tweet"));
    btn.style.color = "white";
    btn.addEventListener("click", function () {
      // this function should catch the window object
      chrome.runtime.sendMessage(
        { greetings: "Bonk tweet" },
        function (response) {
          console.log(response.farewell);
          // don't have access to window.phantom.solana
          console.log(this);
          console.log(window);
        }
      );
    });
    
    element.appendChild(btn);

}
}
setTimeout(init, 4000);

解决方案

核心原因是Chrome扩展的内容脚本运行在隔离环境,和网页自身的JS上下文完全隔离,所以无法直接访问网页注入的window.phantom对象。需要通过「注入网页脚本+跨上下文消息通信」的方式解决:

1. 修改manifest.json

调整web_accessible_resources配置,移除不必要的extension_ids限制,确保脚本能被Twitter网页访问:

"web_accessible_resources": [
  {
    "resources": ["page-script.js"],
    "matches": ["https://*.twitter.com/*"]
  }
]

2. 创建网页注入脚本page-script.js

这个脚本会运行在网页的原生上下文,能直接访问window.phantom.solana,负责处理钱包连接逻辑并传递结果:

// 监听来自内容脚本的消息
window.addEventListener('message', (event) => {
  if (event.source !== window || event.data.type !== 'CONNECT_PHANTOM') return;
  
  // 调用Phantom钱包连接方法
  window.phantom.solana.connect()
    .then((resp) => {
      window.postMessage({
        type: 'PHANTOM_CONNECT_RESULT',
        data: resp
      }, '*');
    })
    .catch((err) => {
      window.postMessage({
        type: 'PHANTOM_CONNECT_ERROR',
        error: err.message
      }, '*');
    });
});

3. 修改内容脚本contentScript.js

  • 先注入网页脚本到Twitter页面;
  • 按钮点击时通过postMessage触发网页脚本的连接逻辑;
  • 监听网页脚本返回的结果:
import React from "react";
import { createRoot } from "react-dom/client";
import "../assets/tailwind.css";
import ContentScript from "./contentScript";

function init() {
  // 注入网页脚本到页面上下文
  const script = document.createElement('script');
  script.src = chrome.runtime.getURL('page-script.js');
  script.onload = () => script.remove();
  document.head.appendChild(script);

  const appContainer = document.createElement("div");
  if (!appContainer) {
    throw new Error("Cannot find app container");
  }

  const root = createRoot(appContainer);
  const articleList = window.document.querySelectorAll("article");
  root.render(<ContentScript />);

  // 监听网页脚本返回的连接结果
  window.addEventListener('message', (event) => {
    if (event.source !== window) return;
    switch(event.data.type) {
      case 'PHANTOM_CONNECT_RESULT':
        console.log('Phantom连接成功:', event.data.data);
        break;
      case 'PHANTOM_CONNECT_ERROR':
        console.error('Phantom连接失败:', event.data.error);
        break;
    }
  });

  for (const element of articleList) {
    const btn = document.createElement("button");
    btn.appendChild(document.createTextNode("Bonk tweet"));
    btn.style.color = "white";
    btn.addEventListener("click", function () {
      // 向网页脚本发送连接指令
      window.postMessage({ type: 'CONNECT_PHANTOM' }, '*');
    });
    element.appendChild(btn);
  }
}
setTimeout(init, 4000);

注意事项

  • 消息通信要通过type字段做校验,避免和其他脚本的消息冲突;
  • 确保page-script.js在扩展打包目录中,路径和manifest.json配置一致;
  • Manifest V3中禁止内容脚本直接修改网页window对象,必须通过这种跨上下文消息传递的方式实现。

内容的提问来源于stack exchange,提问作者Miloš Arsić

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 20:35:16