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

Chrome扩展Manifest V3:MAIN世界脚本如何传递数据至本地世界

解决Manifest V3中MAIN世界脚本向扩展本地世界传递数据的方案

针对你遇到的MAIN世界脚本无法调用chrome.runtime.sendMessage的问题,这里提供两种可行的实现方案:


方案一:DOM自定义事件桥接 + Service Worker中转

通过MAIN世界脚本触发自定义DOM事件,隔离世界脚本监听后转发至Service Worker,再由Popup从Service Worker获取数据。

1. 配置Manifest.json

添加MAIN世界和隔离世界的Content Script,以及Service Worker声明:

{
  "manifest_version": 3,
  "name": "Yandex Music Discord RPC",
  "version": "1.0",
  "content_scripts": [
    // MAIN世界脚本:获取歌曲数据
    {
      "matches": ["https://music.yandex.ru/*"],
      "js": ["main-world-script.js"],
      "world": "MAIN"
    },
    // 隔离世界脚本:转发数据至Service Worker
    {
      "matches": ["https://music.yandex.ru/*"],
      "js": ["isolate-world-script.js"]
    }
  ],
  "background": {
    "service_worker": "background.js"
  },
  "permissions": ["storage"],
  "host_permissions": ["https://music.yandex.ru/*"]
}

2. MAIN世界脚本(main-world-script.js)

定时获取歌曲数据,通过自定义DOM事件传递至隔离世界:

// 每秒获取一次当前播放歌曲
setInterval(() => {
  try {
    const track = externalAPI.getCurrentTrack();
    if (track) {
      // 触发跨世界可监听的自定义事件
      const updateEvent = new CustomEvent('yandex-track-updated', {
        detail: track,
        bubbles: true,
        composed: true
      });
      document.dispatchEvent(updateEvent);
    }
  } catch (err) {
    console.error("获取歌曲数据失败:", err);
  }
}, 1000);

3. 隔离世界脚本(isolate-world-script.js)

监听自定义事件,将数据转发至Service Worker:

document.addEventListener('yandex-track-updated', (e) => {
  const trackData = e.detail;
  // 调用扩展API发送数据至Service Worker
  chrome.runtime.sendMessage({
    type: "TRACK_UPDATE",
    data: trackData
  });
});

4. Service Worker(background.js)

存储实时歌曲数据,供Popup请求:

let currentTrack = null;

// 接收Content Script发来的歌曲数据
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  if (msg.type === "TRACK_UPDATE") {
    currentTrack = msg.data;
  }
});

// 响应Popup的数据请求
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  if (msg.type === "GET_CURRENT_TRACK") {
    sendResponse(currentTrack);
  }
});

5. Popup.js 获取数据并处理Discord RPC

document.addEventListener('DOMContentLoaded', () => {
  // 请求当前歌曲数据
  chrome.runtime.sendMessage({ type: "GET_CURRENT_TRACK" }, (track) => {
    if (track) {
      // 这里编写Discord RPC逻辑
      console.log("当前播放:", `${track.title} - ${track.artists.map(a => a.name).join(', ')}`);
      // 示例:discordRpc.setActivity({ details: track.title, state: track.artists[0].name });
    }
  });

  // 监听实时更新(可选)
  chrome.runtime.onMessage.addListener((msg) => {
    if (msg.type === "TRACK_UPDATE") {
      // 实时更新Discord状态
      console.log("歌曲更新:", msg.data.title);
    }
  });
});

方案二:Popup直接调用MAIN世界接口

如果不需要实时监听,可在Popup打开时通过chrome.scripting.executeScript直接在MAIN世界执行代码获取数据。

1. 更新Manifest.json权限

添加scripting和activeTab权限:

{
  "permissions": ["scripting", "activeTab"],
  // 其他配置...
}

2. Popup.js 直接获取数据

document.addEventListener('DOMContentLoaded', async () => {
  try {
    // 获取当前激活的标签页
    const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true });
    // 在MAIN世界执行代码获取歌曲
    const [result] = await chrome.scripting.executeScript({
      target: { tabId: activeTab.id },
      func: () => externalAPI.getCurrentTrack(),
      world: "MAIN"
    });

    const track = result.result;
    if (track) {
      // 处理Discord RPC逻辑
      console.log("当前歌曲:", track);
    }
  } catch (err) {
    console.error("获取歌曲失败:", err);
  }
});

内容的提问来源于stack exchange,提问作者Ильдар Гранкин

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 11:07:06