简体   繁体   中英

How do I pass messages back from content scripts in iframes?

I am viewing a webpage that has an iframe embedded in it. I need to collect information from my extensions browser action on both the web page and all embedded iframes. I have the following code:

manifest

{
  "manifest_version": 2,
  ...
  "content_scripts": [
    {
      "all_frames": true,
      "js": [ "contentscript.js" ],
      "matches": [ "http://*/*", "https://*/*", "file:///*" ],
      "run_at": "document_start"
    }
  ],
  ...
}

browser action popup

chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
    chrome.tabs.sendMessage(tabs[0].id,{command: 'collectPageDetails'},function (details) {
        console.log('got details');
    });
});

content script

chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
    if (msg.command === 'collectPageDetails') {
        console.log('getting page details');
        sendResponse({ details: 'something' });
        return true;
    }
});

The behavior I am seeing here is that the message is received by both the main page and the iframe. I can verify this by seeing two instances of getting page details logged in the page console.

However, I am only getting one response back to the browser action ( got details only logged once in the browser action), which seems to only come from the main page and not the embedded iframe.

How do I communicate back from the iframe embedded within the page via messaging? I am expecting two callbacks to occur from my browser action in function (details) { } .

The sendRespnse() function from chrome.runtime.onMessage can be used at most once to send a single response to a message. This does not mean that it can be used once per frame, but once in total. When describing the sendResponse function, the Chrome documentation says [emphasis mine]:

Function to call ( at most once ) when you have a response. The argument should be any JSON-ifiable object. If you have more than one onMessage listener in the same document, then only one may send a response.

Thus, you will need to use some other method of sending a message to the background script. This will usually be a chrome.runtime.sendMessage() (content scripts) paired with a chrome.runtime.onMessage listener in your background script. You will need to establish some format for the message which defines what the message is for your background script. For instance, you could do something like:

content scripts:

chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
    if(msg.command === 'collectPageDetails') {
        console.log('getting page details');
        chrome.runtime.sendMessage({type:'collectPageDetailsResponse',details:'something'});
    }
});

background script:

chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
    if(msg && msg.type === 'collectPageDetailsResponse') {
        //Received a details response.
        let tabId = sender.tab.id;
        let frameId = sender.tab.frameId;
        console.log('got details:', msg.details, ' From tabId:',tabId, ' frameId:',frameId);
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM