5

I'm trying to inject a remote script as the content script in Chrome extension, but I feel like I'm running into the murky (at least to me) area of Chrome execution environment.

I want to use jQuery's $.getScript for that (and other) purposes.

Here's the injection code (brilliantly suggested here):

// inject jQuery
chrome.tabs.executeScript(null, { file: "js/jquery.js" }, function() {
   // inject remote script with jQuery
   chrome.tabs.executeScript(null, { code: '$.getScript("https://mysite.com/myremotescript.js", function(){ })' });
});

Here's the remote script myremotescript.js - it's simple:

$("body").css("backgroundColor", "green");

The error is: "$ is not defined"

The $ referred in the error seems to be that of the myremotescript.js function, because it works if myremotescript.js is changed to:

document.body.style.backgroundColor = "green";

It appears that it's not only $ that is not defined. If I change myremotescript.js to:

function Do(){
    document.body.style.backgroundColor = "green";
}

and then execute Do() from the callback of $.getScript:

chrome.tabs.executeScript(null, {
    code: '$.getScript("https://mysite.com/myremotescript.js", function(){ Do(); })' 
});

The error is then: "Do is not defined"

Any ideas/explanation/suggestions?

EDIT: SOLUTION: Following @Rob-W answer, it worked. The only quirk that I needed to add to get $.get() not to error out was to mark the data type as "text". Also, I didn't need to do eval, since executeScript can accept code-as-text:

$.get("https://mysite.com/myremotescript.js", null, null, "text")
    .done(function(remoteCode){
        chrome.tabs.executeScript(null, { code: remoteCode }, function(){
            chrome.tabs.executeScript(null, { code: "Do();" });
    });
})
Community
  • 1
  • 1
New Dev
  • 48,427
  • 12
  • 87
  • 129

1 Answers1

1

$.getScript defaults to injecting a <script> element to load scripts from a different origin. Consequently, the code runs in the context of the page, not the content script (see also).

If you really want to use jQuery to get the script, replace

$.getScript("https://mysite.com/myremotescript.js", function(){ });

with the following (eval is used as a callback, thus it evaluates the response of the request)

$.get("https://mysite.com/myremotescript.js", eval);

While this works, I recommend to cache the script's response body. Then, your extension will not break if the network connection drops. And, more importantly, the user will not get a useless request for every page load. I've fleshed out this concept before, see this answer.

Community
  • 1
  • 1
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • Thanks Rob. It appears that because I do a cross-domain xhr with `$.get()` it requires me to add permissions with a match pattern (for some reason `$.getScript()` did not require it). Is this, in fact, true? Does it add a special warning to the user during extension installation? – New Dev Aug 11 '13 at 20:58
  • Just "Can access all data on example.com". See https://developer.chrome.com/extensions/permission_warnings.html – Rob W Aug 11 '13 at 21:59
  • Yeah... that's kinda crappy, for the user confusion part, if for nothing else. Couldn't I just overcome this by doing `$.getScript` in the background/page, then retrieve the `innerHtml` of the ` – New Dev Aug 12 '13 at 00:53
  • Ah no, I take it back.... it adds a – New Dev Aug 12 '13 at 01:42