Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Communication between injected iframe and content script -- message passing via background page

I am injecting an iframe in a tab. Now inside the the iframe, based on user's actions, I need to show some error/warning/success notifications. However I want to display these notifications in the tab not in iframe. So I need to communicate between iframe and content script. Now these notifications are dynamic based on user's actions so I thought of message passing between iframe and content script via background page.

So what i have done is send messages from iframe to background. Now both background page and content script listens to these messages but only background page is able to receive them. On receiving messages it reflects them back to sender tab. Now content script can receive these messages as they are sent from background page.

Now I tried the same using custom events but it didn't work.

But i would like to know any other method which is more efficient than what i am doing??

EDIT : Here's the relevant code

iframe.js:

    $scope.hideFrame = function(){                                        
       sendMessageToBackground("hideFrame");
    };

     $scope.checkIfFormValid = function(){
       if(!($scope.taskName === "" || $scope.group.selectedGroup === null )){
          $scope.addTask();
        }
        else{
          sendMessageToBackground("invalidForm");
        }
     };

    function sendMessageToBackground(msg){
       chrome.runtime.sendMessage({type: msg});
    }

background.js:

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){
   switch (request.type){

                case "hideFrame":
                   chrome.tabs.sendMessage(sender.tab.id,{type:"hideFrame"});
                   break;
                case "invalidForm":
                   chrome.tabs.sendMessage(sender.tab.id,{type:"invalidForm"});
                   break;

            }      
 });

content.js:

  chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){
                switch (request.type){
                     case "invalidForm":
                         var n = noty({
                                        text        : ' Please fill all details',
                                        type        : 'error',
                                        layout      : 'topRight',
                                        timeout     :  10000,
                                        theme       : 'defaultTheme'
                                    });
                        break;

                    case "hideFrame":
                      $("#isolatedFrame").hide();
                      break;
                }      
    });

Using window.parent.postMessage(not working):

iframe.js:

 function sendMessageToContent(msg){
             // chrome.runtime.sendMessage({type: msg});
             window.parent.postMessage({ type: "fromFrame", message: msg }, "*");
            }

content.js:

window.addEventListener("message", function(event) {

  if (event.source != window)
    return;

  if (event.data.type && (event.data.type == "fromFrame")) {
    console.log("Content script received: " + event.data.message);

  }
}, false);

Also, when i add a breakpoint at window.parent.postMessage({ type: "fromFrame", message: msg }, "*"); and try to see window.parent object , inspected target is disconnected. I don't why this is happening??

like image 258
Sid Avatar asked Oct 23 '15 07:10

Sid


1 Answers

Yes, there's a more effective way to achieve it - using tabs.sendMessage.

extensions cannot send messages to content scripts using this method. To send messages to content scripts, use tabs.sendMessage. (see runtime.sendMessage document )

Here's the code.

iframe.js:

  chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
    console.log(response.farewell);
  });

content.js:

chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    console.log(sender.tab ?
                "from a content script:" + sender.tab.url :
                "from the extension");
    console.log('greeting:", request.greeting);
    sendResponse({farewell: "goodbye"});

You can also refer to https://developer.chrome.com/extensions/messaging#simple for more detail.

EDIT

Since iframe.js is a content script, you should send the message with chrome.runtime.sendMessage and without using chrome.tabs API. Otherwise, chrome.tabs will be undefined.

like image 134
ran meimei Avatar answered Sep 28 '22 06:09

ran meimei