You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Chrome扩展:如何从Content Script向Popup发送消息?

How to Send Messages from Content Script to Popup Script in Chrome Extension?

Got it, let's work through fixing this issue and getting your Content Script → Popup messaging working. First, let's break down why you're hitting that error, then walk through the correct implementation step by step.

The Root Cause of Your Error

You mentioned getting Uncaught TypeError: Cannot read property 'query' of undefined in your Content Script. That's because Content Scripts don't have access to the chrome.tabs API—Chrome restricts which APIs are available in Content Scripts, and chrome.tabs is only accessible in background scripts or the Popup itself.

Another critical point: the Popup only exists when it's open (when the user clicks the extension icon to show it). If it's closed, there's no active listener to receive your message.

Correct Implementation

We'll use chrome.runtime.sendMessage() from the Content Script to send messages, and have the Popup listen for these messages with chrome.runtime.onMessage.addListener(). Here's how to adjust your code:

1. Updated Content Script (content.js)

Let's add a trigger (like a button on the web page) to send messages to the Popup. We'll use chrome.runtime.sendMessage instead of trying to access chrome.tabs:

// Add a test button to the page (optional, for demo purposes)
const sendToPopupBtn = document.createElement('button');
sendToPopupBtn.textContent = 'Send Message to Popup';
sendToPopupBtn.style.position = 'fixed';
sendToPopupBtn.style.top = '20px';
sendToPopupBtn.style.right = '20px';
document.body.appendChild(sendToPopupBtn);

sendToPopupBtn.addEventListener('click', () => {
  // Send a structured message to the extension runtime
  chrome.runtime.sendMessage(
    {
      type: 'FROM_CONTENT',
      content: 'Hello from the Content Script!'
    },
    (response) => {
      // Handle cases where the Popup is closed
      if (response) {
        console.log('Popup replied:', response);
      } else {
        console.log('Popup is closed—no response received');
      }
    }
  );
});

// Keep your existing listener for Popup → Content messages
chrome.runtime.onMessage.addListener(gotMessage);
function gotMessage(message) {
  console.log('Received from Popup:', message);
}

2. Updated Popup Script (popup.js)

Now the Popup will listen for incoming messages from the Content Script, plus keep your existing Popup → Content functionality:

// Listen for messages from Content Script
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === 'FROM_CONTENT') {
    console.log('Message from Content Script:', message.content);
    // Optional: send a response back to the Content Script
    sendResponse({ reply: 'Hi from the Popup!' });
  }
});

// Your existing Popup → Content Script code (unchanged)
let counter = 0;
document.getElementById("userInput").addEventListener("click", () => {
  counter++;
  const params = { active: true, currentWindow: true };
  chrome.tabs.query(params, (tabs) => {
    chrome.tabs.sendMessage(tabs[0].id, counter);
  });
});

3. Your index.html Remains Mostly the Same

Just ensure the test button for Popup → Content is present:

<!DOCTYPE html>
<html>
<body>
  <h2>Hello there!</h2>
  <button id="userInput">Click me! (Send to Content)</button>
</body>
<script src="popup.js"></script>
</html>

Key Tips

  • Popup Availability: If the Popup is closed, chrome.runtime.sendMessage won't trigger the listener, and the callback will get undefined as a response. You can handle this gracefully (like we did with the log message).
  • Long-Lived Connections: For persistent, real-time communication (not just one-off messages), use chrome.runtime.connect() to create a Port between the Content Script and Popup. This is useful for continuous updates.
  • Permissions: Ensure your manifest.json has the necessary permissions—for basic messaging, "permissions": ["activeTab"] works if your Content Script runs on the active tab, or <all_urls> if it runs on all sites.

内容的提问来源于stack exchange,提问作者Petr Jelínek

火山引擎 最新活动