5

I am trying to code a chrome extension, and I have a background.html with this code:

var x = "test";

function tabChanged(id, info, tab){
    if(info.status == 'complete'){
        chrome.tabs.executeScript(id, {code:"try{alert(x);}catch(e){alert(e);}"}, null);
    }
}

chrome.tabs.onUpdated.addListener(tabChanged);
chrome.tabs.getAllInWindow(null,function(tabs){
    for(var index=0; index < tabs.length; index++){
        chrome.tabs.executeScript(tabs[index].id, {code:"try{alert(x);}catch(e){alert(e);}"}, null);
    }
});

But variable "x" is always undefined inside executeScript.

How can I get/set x from executeScript? Without using messaging.

3 Answers 3

3

Content scripts executes in context of web page. See Content Scripts section in Chrome docs for more information.

If you want to pass string variable from background page to chrome.tabs.executeScript you must do something like this:

var x = "test";
chrome.tabs.executeScript(id, {code:"var x = '"+x+"'; try{alert(x);}catch(e){alert(e);}"},null);

If you want to modify variable, you have only one way - messaging:

var x = 1;
console.log('x=' + x);

chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
    console.log(request);
    if(request.command == 'setVar') {
        window[request.name] = request.data;
    }
});

chrome.browserAction.onClicked.addListener(function() {
    var code = "chrome.extension.sendRequest({command: 'setVar', name: 'x', data: 2});";
    chrome.tabs.executeScript(null, {code:code});
    window.setTimeout(function(){console.log('x=' + x);}, 1000);
});
Sign up to request clarification or add additional context in comments.

3 Comments

Do you have any sample on how to modify the variable?
Well you said is the only way so yes.
Check it, but i think it's better to create content script and communicate with background page from it.
0

For chrome Chrome 92+, you can use args

chrome.tabs.query({active: true, currentWindow: true}).then(([tab])=>{
  const para = "Hello world!!!"
  chrome.scripting.executeScript({
    target: {tabId: tab.id},
    function: (args) => {
      alert(args)
    },
    args: [para]
  })
})

or you can use the chrome.storage

{
  "manifest_version": 3,
  "permissions": [
    "storage",
    "activeTab",
    "scripting"
  ]
}
chrome.storage.sync.set({msg: "hello world"})
chrome.tabs.query({active: true, currentWindow: true}).then(([tab])=>{
  chrome.scripting.executeScript({
    target: {tabId: tab.id},
    function: () => {
      chrome.storage.sync.get(['msg'], ({msg})=> {
        console.log(`${msg}`)
        alert(`Command: ${msg}`)
      })
    }
  })
})

Update for pass functions in args is OK?

You can't

Neither Storage nor Args, they both can't accept the function parameter.

Example:

const myObj = {
  msg: "Hi",
  myNum: 1,
  myFunc: ()=>{return "hi"},
  myFunc2: function() {return ""}
}

chrome.storage.sync.set({
  msg: "my storage msg",
  myObj,
})

chrome.tabs.query({active: true, currentWindow: true}).then(([tab])=>{
  chrome.scripting.executeScript({
    target: {tabId: tab.id},
    function: (para1, para2MyObj) => {
      console.log(para1) // Hello
      console.log(JSON.stringify(para2MyObj)) // {"msg":"Hi","myNum":1} // myFunc, myFunc2 are missing. You can't get the variable if its type is function.
      chrome.storage.sync.get(['msg', "myObj"], ({msg, myObj})=> {
        console.log(`${msg}`) // "my storage msg"
        console.log(JSON.stringify(myObj)) // {"msg":"Hi","myNum":1}
        alert(`Command: ${msg}`)
      })
    },
    args: ["Hello", myObj]
  })
})

3 Comments

can we pass functions in args like args: [function1, function2] and expect functions working there?
Hi @xjlin0, I updated my answer hope it will be helpful for you.
Thanks, I ended up writing those functions as well as my main function in a separated js file, and include that js file by files: ['filename.js'] under executeScript instead of function: mainFunction.
-1

The reason your variable is undefined is because you are referencing your variable inside of a string so you can just simply do this:

var yourVar = "your variable"
   //define your variable
chrome.tabs.executeScript({code: 'Your code here' + yourVar + ';}'})
   //then format it like this ({code: "Your code as a string" + your variable + "code"})

and if you want to change the variable later than just do the same thing but with your new variable, it's pretty straight forward

1 Comment

I don't see how that would solve the issue even remotely, and for the same reason the problem exists in the first place. When you use chrome.tabs.executeScript anything in ({code: }) is run in the page and if you simply use a variable it will check the current website for the variable not your script so my work around was to create a string with my variable then eval that so its is no longer a variable but rather part of the string which is then run

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.