Chrome extension set to `run_at` `document_start` is running too fast?

Chrome extension Content scripts (run from a manifest.json) that are run at document_start, do fire before document.readyStateDoc has reached interactive -- which is the earliest you want to start messing with most page elements.

However, you can inject most <script> nodes right away if you wish. Just not to document.head or document.body because they don't exist yet.
Append to documentElement instead. For example:

var s = document.createElement ("script");
s.src = "http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js";
s.async = false;
document.documentElement.appendChild (s);

Or

var s = document.createElement ("script");
s.src = chrome.extension.getURL ("MyPwnCode.js");
s.async = false;
document.documentElement.appendChild (s);

If you are adding or modifying other DOM elements, in a script running at document_start, wait until the DOMContentLoaded event like so:

document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);

function fireContentLoadedEvent () {
    console.log ("DOMContentLoaded");
    // PUT YOUR CODE HERE.
    //document.body.textContent = "Changed this!";
}

Your problem is that, when using "run_at": "document_start", the only element that is granted to exist in the DOM is the <html> element. If you want to avoid errors relative to page load, like trying to access some element that hasn't been created yet, you'll have to either:

  • Make your script run at "document_idle" or "document_end". Although "document_end" still doesn't grant you that all the elements and resources of the page have been fully loaded (but the DOM has already been parsed), the "document_idle" keyword will give you the certainty that the DOM has been parsed and all the elements and resources have been loaded properly before your script runs.

  • Or, instead, you can continue using "document_start" wrapping your code inside a "DOMContentLoaded" listener, which will make it run when the DOM has completely finished loading and parsing, similarly to "document_idle". Here's an example:

    document.addEventListener("DOMContentLoaded", function() {
        // Run your code here...
    });