35

I am writing a Chrome extension that needs to modify pages in a specific domain according to some given parameter, which needs XSS in order to be obtained, so simply using a content script seems impossible. So, I've decided to inject the script using tabs.executeScript.

Now I need to know two things: First, how can I pass parameters to the script when using executeScript? I guess I can use messages, but isn't there a more direct way to pass the parameter while injecting the script?

Second, my script uses jQuery, so I need to include jQuery somehow. It's silly, but I'm not sure how to do it. So far, I embedded jQuery in the HTML page I was writing (for example background.html).

Makyen
  • 31,849
  • 12
  • 86
  • 121
Gadi A
  • 3,449
  • 8
  • 36
  • 54
  • 1
    Related/duplicates: [Pass a parameter to a content script injected using chrome.tabs.executeScript()](//stackoverflow.com/q/17567624) and [Injecting multiple scripts through executeScript in Google Chrome](//stackoverflow.com/q/21535233) – Makyen Feb 09 '17 at 21:44
  • For future readers (the OP probably has learned this in the intervening years): Please write Questions to have only one question (or ones that are *very* closely related). This allows Answers to be more focused and the Question to be either pointed at a duplicate or be used as a duplicate-target for future questions. Having multiple questions within a Question results in the Question being less valuable to future readers. – Makyen Feb 09 '17 at 21:47

3 Answers3

59

If you don't want to use messaging then:

chrome.tabs.executeScript(tabId, {file: "jquery.js"}, function(){
    chrome.tabs.executeScript(tabId, {code: "var scriptOptions = {param1:'value1',param2:'value2'};"}, function(){
        chrome.tabs.executeScript(tabId, {file: "script.js"}, function(){
            //all injected
        });
    });
});

(jquery.js should be placed into extension folder). Script options will be available inside scriptOptions variable in the script.js.

With messaging it is just as easy:

chrome.tabs.executeScript(tabId, {file: "jquery.js"}, function(){
    chrome.tabs.executeScript(tabId, {file: "script.js"}, function(){
        chrome.tabs.sendMessage(tabId, {scriptOptions: {param1:'value1',param2:'value2'}}, function(){
            //all injected
        });
    });
});

You would need to add a request listener to script.js:

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
    var scriptOptions = message.scriptOptions;
    console.log('param1', scriptOptions.param1);
    console.log('param2', scriptOptions.param2);
    doSomething(scriptOptions.param1, scriptOptions.param2);
});
wOxxOm
  • 65,848
  • 11
  • 132
  • 136
serg
  • 109,619
  • 77
  • 317
  • 330
  • 1
    So are all `executeScript` calls putting code into the same *isolated world* in the tab? [I thought they wouldn't](http://code.google.com/chrome/extensions/content_scripts.html#execution-environment): "Isolated worlds allow each content script to make changes to its JavaScript environment without worrying about conflicting with the page or with other content scripts" – Kragen Javier Sitaker Apr 06 '11 at 15:41
  • 1
    @Kragen `executeScript` is equal to declaring a content script in the manifest. It is not executed in isolated world of a tab, it is executed in isolated world of a content script. – serg Apr 06 '11 at 15:44
  • 1
    Well, see, that's what I thought — a content-script isolated world for that tab. The thing is, if you have two content scripts in the manifest, they end up in two different isolated worlds. But here you seem to have two separate `executeScript` calls that end up in the *same* isolated world. – Kragen Javier Sitaker Apr 07 '11 at 16:20
  • @Kragen No, all content scripts (from the same extension of course) are running in the same world. No matter whether you declare them in a manifest or through `executeScript`. – serg Apr 07 '11 at 16:50
  • I ran into a similar issue, and wrote a Q&A with some code to abstract the approach mentioned above: [Injecting multiple scripts through executeScript in Google Chrome](http://stackoverflow.com/q/21535233/1149773) – Douglas Feb 03 '14 at 18:55
  • As you mentioned below first code snippet, `scriptOptions` will be available in the `script.js` but when I do the same it return 'undefined' – xkeshav Nov 07 '14 at 07:12
2

Building off the direct method above, I was able to inject code into a new tab directly from the background script on my Chrome Extension. However, be advised that the code section of the executeScript command will not simply take variables, but only a string. Therefore, after experimenting, I found we need to setup the string of commands beforehand and include the variables we want. Like this:

var sendCode = 'document.getElementsByClassName("form-control n-gram")[0].value = "' + TMObj.brand + '";';

var TMUrl = "http://website.com";
chrome.tabs.create({ url: TMUrl }, function(tab){
            chrome.tabs.executeScript(null, {code: sendCode});
      });
});

This worked well!

UltimatePeter
  • 93
  • 1
  • 1
  • 9
1

Better way to include dependencies

Add the dependant libraries (and other .js files) to the background scripts in your manifest.json by:

"background": {
  "scripts": [
    "jquery.js",
    "main.js"
]

List the dependencies before app code so that they are loaded before.

Reference: Register Background Scripts

Note: this would perform eager-loading of the scripts, instead of lazy-loading as with executeScript.

Vedant Agarwala
  • 18,146
  • 4
  • 66
  • 89