Chrome extension: inserting a javascript tag and calling a function

I have a chrome extension that uses a content script in order to dynamically insert a script tag referencing an external javascript file. The code I use is:

var html_doc = document.getElementsByTagName('head')[0]; 
var _js = document.createElement('script');  
_js.setAttribute('type', 'text/javascript'); 
_js.setAttribute('id', 'chr_js'); 
_js.setAttribute('src', 'http://unixpapa.com/js/dyna1.js'); 
if(!document.getElementById('chr_js')) 
html_doc.appendChild(_js);

The external Javascript contains the following code:

  • is there a way to launch a php script and get the status?
  • Different backgrounds for different time of day?
  • Supplementary properties/settings for JavaScript:window.print() to enable Backgrounds by default
  • How to stop npm script running in background automatically
  • css background repeating when div height reset
  • How to Inherit grandparent CSS not parent?
  • function lfunc(){
      alert('RUNNING loaded function');
    }
    alert('LAST LINE of script');
    

    When I load a page in a tab the “LAST LINE of script” message appears, showing that the script tag is correctly inserted in the DOM.

    My extension also has a button (i.e., a browser_action). Now, I would like this button to call lfunc() defined above whenever it is clicked. Unfortunately, my code simply doesn’t work.

    I use the following code in the background.html page to process the onClick event of my button:

    <script>
    chrome.browserAction.onClicked.addListener(function(tab) {
      chrome.tabs.executeScript(null, 
        {code: "try {lfunc()} catch (e) {alert(e);}"});
      }); // it should call lfunc()
    </script>
    

    The permissions in the manifest.json file are:

    "permissions": [
    "tabs", "http://*/*", "https://*/*"  ]
    

    Instead of getting the “RUNNING loaded function” message I get the error message “ReferenceError: lfunc is not defined“.

    What am I doing wrong?

  • Random body background-image
  • How to change HTML background with JavaScript Function?
  • jquery - stretch background image to fill document rather than window?
  • Repeating a section of an image in CSS
  • Changing background color of text box input not working when empty
  • A way to fade in the background on load?
  • 3 Solutions collect form web for “Chrome extension: inserting a javascript tag and calling a function”

    You can execute the external JS file (by injecting it into the DOM (document in the extension)). The external JS file also has access to the local DOM.

    Not possible is communciation between those two:

    • User-added Javascript (so non-native) can’t be accessed by the extension:
      The extension’s JS doesn’t have access to the page’s jQuery object, but it does have access to its document.body.
    • The user-added Javascript (the page’s JS or your added external JS) doesn’t have access to the extension:
      From the page, you can’t access chrome API’s, like bookmarks, tabs, browser action etc.

    This is done very much intentionally for security reasons.

    What I was talking about (sendRequest and onRequest) is communication between ‘content script’ and extension script/background pages. In your case irrelevant =) Sorry.

    answers

    > I cannot call specific functions within the external JS file from the extension because of the lack of communication capabilities between the two

    That’s right.

    > All I can do is make my extension inject the external JS file into the DOM. This will execute whatever is there to be executed in the external JS file

    That’s right. The ext JS can contain immediate actions and timers etc, like a normally loaded JS (in the webpage itself) would.

    > The code launching granularity from the extension is at external JS level, not at JS function level

    What do you mean by JS function level? The extension JS?

    PS
    chrome.tabs.executeScript is not quite as cool as you’d think. Basically what it does is execute a script in the page’s context (like content_scripts). It has, however, the same limits as content_scripts: it can reach the DOM and native JS functionality, bot not user added JS. An example:

    // Inside a `background_page`:
    chrome.tabs.executeScript(null, {
        "code": "document.body.removeChild(document.body.firstChild);"
    });
    

    This works, because only access to the page’s (always existing) DOM is required. The following won’t work (assuming jQuery was included in the webpage itself):

    // Still inside a `background_page`:
    chrome.tabs.executeScript(null, {
        "code": "jQuery('input').remove();"
    });
    

    This won’t work, because jQuery is a foreign, non-native, user-added JS object that’s inaccessible to the extension (both background_page and content_scripts).
    I don’t really understand the reason for this last limitation, but it’s all about sandboxing and security in Chrome =) Which is a good thing I guess…

    BTW
    I think the solution to your problem is quite simple… You can make the browser_action inject external JS into the page’s DOM. That’s enough, right? The external JS contains logic AND the actual function call. Better solution all around, because the external JS is only loaded when the browser_action (button) is pushed/triggered. One very slight downside: a very short delay (= downloading the external JS after pushing the browser_action).

    Might I suggest again: put all your extension JS into the extension. This will allow offline functionality and never require a(nother) connection to a third party server.

    Replace alert('It doesn't work'); with alert(e);

    This should give you a better idea of what the error is. Please post the error.

    i needed to invoke a function that was inside one of the pages scripts…

    location = 'javascript:callToTheFunction(param,param,..)' did it.  
    

    i’m talking from a content