1

I tried a brief example:

document.body.innerHTML= '<script>alert(123);</script>'

I was expecting an alert window, but instead, nothing happened.

Why? How can I inject something to DOM that would actually run?

My intention is to be able to replace the current content of the page with completely new content, having possibly javascript calls...

PS: my original intention is to replace current page with a new one - and these instructions are to be done inside chrome extension's content script.

Novellizator
  • 13,633
  • 9
  • 43
  • 65
  • Why would you do this instead of simply calling the `alert()`? – Curtis Aug 28 '15 at 14:50
  • I am curious as well. – THE AMAZING Aug 28 '15 at 14:51
  • 2
    That and just setting innerHTML doesn't actually do anything JS-wise, it needs to be added to the DOM – Orpheus Aug 28 '15 at 14:51
  • @Curt The original problem was to edit page within the content script inside the chrome extension. By editing a page I mean adding an interactive panel with osme javascript calls after onlick events. – Novellizator Aug 28 '15 at 14:51
  • @Novellizator An injected script and a content script are two different things in chrome extension parlance. You don't need to inject anything to interact with the DOM, a content script will suffice. – Daniel Lizik Aug 28 '15 at 14:55
  • @novellizator Well your issues is that Javascript is setting your text as a text node and java script has already executed that code procedurally. If you want to inject Javascript you need to append the header. Let me know if thats what you would like to do and i will post some code. – THE AMAZING Aug 28 '15 at 14:55
  • @Curt or, even better (a more general example). Imagine you opened some url. Now with your content script you want to completely replace a page with another custom page with functioning javascript. – Novellizator Aug 28 '15 at 14:55
  • @RichardGrant ok, let's assume I want to completely replace the original page with my new page(that has javascript). And I want this javascript to run. If you can work it out, please post the solution :) – Novellizator Aug 28 '15 at 14:59
  • Question edited, hopefully now its more clear. – Novellizator Aug 28 '15 at 15:06
  • @RichardGrant _"Javascript is setting your text as a text node"_ - So? That doesn't explain why the code isn't executed. – a better oliver Aug 28 '15 at 16:36
  • if your text is being set as a text node then that means your text is just text of a script not an actual script. does that make sense? – THE AMAZING Aug 28 '15 at 16:39

3 Answers3

0
var script = document.createElement('script');
script.type = 'text/javascript';
script.innerHTML = 'alert(123);';
document.getElementById('element').appendChild(script);

Borrowing this from an older question, but it should work. Adapt the last line to pick your element you want to throw this into.

Source

Community
  • 1
  • 1
Orpheus
  • 727
  • 1
  • 7
  • 22
  • I'm still not sure if this will work, even though its relatively similar to my answer. The fact that you are appending the body with script is what has me thinking. give me a second im going to test this. – THE AMAZING Aug 28 '15 at 15:09
  • 1
    Wow to my surprise it works. now that interests me. Dont forget you need a window onload event though because the document getElementById is not populated until after the page is finished loading. – THE AMAZING Aug 28 '15 at 15:13
0

To inject javascript you need to append the #document HTML header

Note with some older browsers like NetScape 7.0 this method is not available because appending the document head does not work.

function XXX(){
    this.linked_script = {};
    this.loadJS = function(filename, callback){
        callback = typeof callback !== 'undefined' ? callback : function(){};
        var file = document.createElement("script");
        file.setAttribute("type", "text/javascript");
        file.setAttribute("src", filename);
        file.onreadystatechange = function () {
           if(this.readyState == 'complete' || this.readyState == 'loaded') {
                that.linked_script[filename.replace(/[^a-zA-Z ]/g, "")] = file;
                callback(file);
           }
        }
        file.onload = callback;

        if (typeof file !== "undefined")
            document.getElementsByTagName("head")[0].appendChild(file);
    };
    this.removeResource = function(filename,from){
        var key = filename.replace(/[^a-zA-Z ]/g, "");
        if(key in from){
            from[key].parentNode.removeChild(from[key]);
            delete from[key];
        }
    };
}
THE AMAZING
  • 1,496
  • 2
  • 16
  • 38
0

As explained by the spec,

script elements inserted using innerHTML do not execute when they are inserted.

Note innerHTML can still run JS (so you have to sanitize untrusted text):

document.body.innerHTML = '<img src="//" onerror="alert(123)" />';

But I don't recommend it. The proper way to run a string is using the devil eval (use carefully):

eval("alert(123)");
Oriol
  • 274,082
  • 63
  • 437
  • 513