0

I'm opening a tab and trying to call a function defined in it but i always get a "reference error". I send a message to the script after the script is loaded asking to run "test1" function located on the tab code.

Here is my code:

Extention code

chrome.tabs.executeScript(tab.id, {file: "script.js", runAt: "document_end"}, function(array){  
    //send message executeTest to the created tab
    chrome.tabs.sendMessage(tab.id, {msg: "executeTest"});
});

script.js

url = document.URL; 
window.addEventListener("load", doStuff, true);

function doStuff(){

    //listen for messages coming from extension
    chrome.runtime.onMessage.addListener(
        function(message, sender) {

            var msg = message.msg;
            var url = message.url;    

            switch(msg){
                case "executeTest":
                    test1();
                break;
            }
        }
    );
}  

Tab HTML

<head>
<title>Test</title>
</head>

<body>
    <script src="app.js"></script>
</body>
</html>

Tab Javascript

function test1(){
    console.log("test1 is running!");
}

I receive the message on the script but it's not possible to execute "test1()".

What am i doing wrong ?

Let_IT_roll
  • 389
  • 2
  • 6
  • 20

2 Answers2

0

chrome.tabs.sendMessage(tab.id, {msg: "executeTest"});

Quotes.

  • That was a typo ! Sorry ^^ I'm able to receive the message as i said but when "test1()" is called i get a reference error. – Let_IT_roll May 19 '14 at 15:40
0

A couple of unrelated issues here.

chrome.tabs.sendMessage(tab.id, {msg: executeTest});

executeTest is not a string, it's an (undefined) identifier. That's what throwing the error.

Correct way (ninja'd by user2570380) is to write

chrome.tabs.sendMessage(tab.id, {msg: "executeTest"});

The other problem is that you will not be able to call test1(), because content scripts live in isolated context.

To bypass it, you either need to employ messaging between the webpage and your extension, use externally_connectable, or inject some of your code into the page to trigger what you need.

Considering that you do not control the webpage, you need to inject code in the page's context. Example:

control.js

window.addEventListener("message", function(event) {
  // We only accept messages from ourselves
  if (event.source != window)
    return;

  if (event.data.source && (event.data.source == "MyExtension")) {
    switch(event.data.command){
      case "test1":
        test1();
        break;
    }
  }
}, false);

script.js

// Initialization
var s = document.createElement('script');
// TODO: add "control.js" to web_accessible_resources in manifest.json
s.src = chrome.extension.getURL('control.js');
s.onload = function() {
    this.parentNode.removeChild(this);
};
(document.head||document.documentElement).appendChild(s);

// Sending a command (make sure script initialized listener first)
window.postMessage({ source: "MyExtension", command: "test1" }, "*");
Community
  • 1
  • 1
Xan
  • 74,770
  • 16
  • 179
  • 206
  • I don't quite understand. If you're referring to injecting into the page's context, you can do it with methods described in the last link, from within `script.js`. You can simply inject `test1();` in a script tag. – Xan May 20 '14 at 12:36
  • I want to run test1() from the tab code (external code opened in a tab). – Let_IT_roll May 20 '14 at 13:09
  • Then what I said above is correct. You can inject code consisting of calling `test1()` with the method I linked to; doing so from the context of `script.js` will inject it in the page's context, where `test1` is defined. – Xan May 20 '14 at 13:10
  • Okay. I was doing it from the background page. Should i define "script.js" as a content script or there is no need ? Or can I simply use it by calling "executeScript" ? – Let_IT_roll May 20 '14 at 13:14
  • There is no need; what you inject with `chrome.tabs.executeScript` is considered a content script. – Xan May 20 '14 at 13:15
  • _It's BAD to have such discussions in comments here, but you don't have enough reputation for a chatroom._ This won't work because `test1()` is a ReferenceError, and in any case your `InjectFunc` expects a function _reference_, which would be `test1`. But that again wouldn't work: there is NO `test1` in script.js. See my edited answer for a more flexible solution using messaging. – Xan May 20 '14 at 14:28
  • I finally get it right ! I was having synchronization problems... Thanks for your help and patience :) – Let_IT_roll May 21 '14 at 19:49