Search code examples
google-chrome-extensionchrome-extension-manifest-v3

Chrome Extension: How to communicate with Content.js from a newly opened Window?


I have created a new window in chrome.action.onClicked.addListener as given below.

On clicking of "Check" button in newly opened window I need to connect to content.js and print some message in the console of window. I dont know where it is going wrong! I am using Manifest version 3.

content.js

chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
   
    if(msg.color === "#00FF00"){
      document.body.style.backgroundColor = "green";
      sendResponse({ status: "done" });
    }
});

background.js

var urlRegex = /^(https?:\/\/)?[a-z0-9-]*\.?[a-z0-9-]+\.[a-z0-9-]+(\/[^<>]*)?$/;

chrome.action.onClicked.addListener(function(tab) {
    /*...check the URL of the active tab against our pattern and... */
        if (urlRegex.test(tab.url)) {
            /* ...if it matches, send a message specifying a callback too */
            chrome.windows.create({
                tabId: tab.id,
                type:"popup",
                url:"popup.html",
                focused:true
            });
    }
});

popup.html

<html>
    <head>
      <script defer src="popup.js"></script>
    </head>
    <body>
      <h3>Test Extension Page</h3>
      <input type="button" id="sendMessage" value="Check"/>
    </body>
</html>

popup.js

let sendMessageButton = document.getElementById("sendMessage");
console.log(document.URL);
console.log(sendMessageButton.value);

function getTitle()
{
    return document.title;
}

sendMessageButton.onclick = function() {
  
  chrome.tabs.query({ active: true, currentWindow: true }, function(tabs){
    var tab = tabs[0];
    chrome.scripting.executeScript(
      {
        target: {tabId:tab.id},
        func: getTitle,
      },
      () => {
        // This executes only after your content script executes
        chrome.tabs.sendMessage(
          tab.id,
          { color: "#00FF00" },
          function (response) {
            console.log(response.status);
          }
        );
      });   
    });  
};

Error in console of newly opened window.

Unchecked runtime.lastError: Cannot access contents of url "chrome-extension://jjaaoafdfmabdajdckiacompibnnmnlh/popup.html". Extension manifest must request permission to access this host.

Error handling response: TypeError: Cannot read properties of undefined (reading 'status') at chrome-extension://jjaaoafdfmabdajdckiacompibnnmnlh/popup.js:25:34
    
Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.

Solution

  • The problem is that the window you create becomes active and hence it becomes the result of chrome.tabs.query in your code, meaning that executeScript runs inside your own extension page, which can't work as this method is only for web sites.

    The solution is to pass the tab id as URL parameter.

    // background.js

    chrome.action.onClicked.addListener(tab => {
      chrome.windows.create({
        type: 'popup',
        url: 'popup.html?' + new URLSearchParams({
          tabId: tab.id,
          title: tab.title,
        }),
      });
    });
    

    // popup.js

    const params = new URLSearchParams(location.search);
    const tabId = +params.get('tabId');
    let title = params.get('title'); // initial title
    
    document.getElementById('sendMessage').onclick = async function () {
      title = (await chrome.tabs.get(tabId)).title;
      let res = await chrome.tabs.sendMessage(tabId, { color: "#00FF00" });
    };