3

I'm trying to inject a function into a webpage via Chrome extension content script by:

function inject(code) {
    var actualCode = '(' + code + ')();';
    var script = document.createElement('script');
    script.textContent = actualCode;
    (document.head||document.documentElement).appendChild(script);
    script.parentNode.removeChild(script);
}

var myObj = person;  // myObj/person is passed in from elsewhere
var fn = function() {
    alert(myObj.name);
};
inject(fn); // myObj undefined

My issue is, since fn is a function expression, I can't pass in myObj.personName. So my question is, how can I construct a function expression that includes a variable? Do I do some sort of string concatenation instead?

I also tried to pass the object to the function, as follows:

function inject(code, myObj) {
    var actualCode = '(' + code + ')(' + myObj +');';
    ...

But this did not work, and caused a "Uncaught SyntaxError: Unexpected identifier" error.

Related: Insert code into the page context using a content script

4
  • 1
    "since fn is a function expression, I can't pass in myObj.personName" - Why not? You can do this: (function(param){...})(paramValue); (so you should be able to modify your code to make something like that happen). Commented Dec 11, 2012 at 22:28
  • It depends on the scope. If myObj is declared in the same scope as inject, it should work. Commented Dec 11, 2012 at 22:29
  • @nnnnnn I tried doing something like that. If I do var fn = (function(p){...})(param); it'll execute the function instead of passing the actual function expression. I also tried doing something like function inject(func, myObj) { var code = '(' + func + ')(' + myObj + ');'; ... }, but that absolutely did not work, lol, it threw Uncaught SyntaxError: Unexpected identifier Commented Dec 11, 2012 at 22:41
  • @bfavaretto Unfortunately, it's not defined in the same scope as inject. Everything is wrapped in a event listener function and myObj is passed from the event itself. Commented Dec 11, 2012 at 22:47

3 Answers 3

3

Your approach was almost correct. The problem is that the following

var code = '(' + func + ')(' + myObj + ');'   // results in
var code = '(function(){})([object Object])'

To solve this, just use JSON.stringify:

var code = '(' + func + ')(' + JSON.stringify(myObj) + ');';
Sign up to request clarification or add additional context in comments.

1 Comment

I've updated the answer at "Building a Chrome Extension - Inject code in a page using a Content script", and added a section at the end which explains this method with more details.
1

Try:

var actualCode = new Function( code )();

1 Comment

It takes a string: new Function( 'return 1+2' )() //=> 3
1

You can post messages in and back between event listeners using window.postMessage.

Inject code like this into the page

window.addEventListener('message', function messageInvoker(e) {
    if (e.data.extKey !== 'myKey') return; // some kind of check so you only worry about your own extension
    window[e.data.fn].apply(window, e.data.params);
}, false);

And from your extension,

window.postMessage({extKey: 'myKey', fn: 'userFunction', params: ['a','b','c']}, '*');

2 Comments

The documentation on the Developer site is a little confusing. Can the messages posted from the embedding page to the extension access the page's execution environment variables?
You can pass transferable objects (read self contained) and most data types, i.e. String, Number etc. also ArrayBuffer. If your object references another object or the environment it was in I'm not sure what happens.

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.