Is run_at page_start in manifest.json really working?

You can define to load a page at a certain time of building DOM using run_at: for example with parameter page_start. this isn’t working either. it seems to me that either the script is being run asynchronous, or there is some other reason for this not to be working:

aall=document.getElementsByTagName("*");
for (var i=0, max=aall.length; i < max; i++) {
aall[i].addEventListener=function(a,b,c){ console.log(“Log”); return false; };
}
console.log(“Log”); is never being called, even though an event has been added to the element using addEventListener in the test html file. My current solution for this is an own firefox fork that overwrites the functions in the javascript engine, which is kind of overdosed.

You didn’t say what you actually want to do. Do you want to overwrite Element.prototype.addEventListener (from the web pages perspective)?

If so, you should read this:

And also you should overwrite Element.prototype.addEventListener, not cover up every individual elements .addEventListener property.

1 Like

Hello,
thanks for your imput. that’s exactly what i’m trying to do. Element.prototype.addEventListener failed, too. But i’m gonna check again to get sure. The reason is that i want to be able to block external scripts or scripts from the page itself from adding blacklisted events.
so injecting javascript that will get executed before anything else gets executed would be great.
i’m using a content script, run_at is only for content scripts, as far as i know.

Regards,
Dennis

okay, update. this one seems to be working:

var actualCode = ‘Element.prototype.addEventListener=function(a,b,c){alert(a);}’;
document.documentElement.setAttribute(‘onreset’, actualCode);
document.documentElement.dispatchEvent(new CustomEvent(‘reset’));
document.documentElement.removeAttribute(‘onreset’)

so run_at is working correctly.
the problem is, that inline events can be blocked, so i’m still looking for a better possibility.

You Reely ned to read and understand the article I linked above, especially the things about Xray vision.


Regarding your actual aim, overwriting the addEventListener function is not the best way to achieve it. You should instead attach a capturing listener on the document and call .stopImmidiatePropagation on it.

it’s working perfectly now using
var actualCode = ‘Element.prototype._addEventListener=Element.prototype.addEventListener;Element.prototype.addEventListener=function(a,b,c){if(a!=“mouseenter”){this._addEventListener(a,b,c);}};’;

your input lead my on the right track, allthough i allready knew the page you were linking to - thanks alot for your help!

Injecting inline code (which is what you are doing) won’t work on pages with a reasonably strong CSP.

You can try it out on for example https://github.com/. Your actualCode won’t run there.

event.stopImmidiatePropagation() doesn’t have that limitation.

fixed it using:
var script = document.createElement(‘script’);
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.remove();

That is generally a cleaner way to inject scripts, but is rejected by CSPs all the same. If the page has a CSP with doesn’t explicitly allow script-src 'unsafe-inline' (or 'unsafe-eval') you will not be able to inject code into the page at all.

When using the old method, i do get csp errors in the developers console. with the new version, there don’t seem to be errors.

That does not necessarily mean that your code was executed. Firefox likes to keep errors like that to itself.

it has to be injected somehow because at run_at document_start, the dom tree hasn’t loaded yet. the description in the MDN API documentation sounds like the script being loaded asynchronously with run_at document_end.
event.stopImmediateProgragation can only be applyed to existing DOM elements, afaik.

I’m not quite sure what you mean. You call .stopImmediateProgragation() on events when they occur, so of course an event target exists at that time. But you can attach your capturing listener that does the cancelling earlier. For most events you can put it on the window, for some few event types you need to use the document. Either way you can attach the listener before the first element is present, and it will affect all elements that are later added to the DOM.

i don’t have access to the elements from the content script.

What do you mean? accessing the DOM is the primary purpose of content scripts. Why do you say you can’t access them?


it shows you when content scripts are being loaded using run_at

btw: i tryed several methods by now. script injection was the first that really worked.

aall=document.getElementsByTagName("*");
for (var i=0, max=aall.length; i < max; i++) {
aall[i].addEventListener=function(a,b,c){ console.log(“Log”); return false; };
}
console.log(“Log”); is never being called
also, when using jquery and stopImmediatePropagation or overwriting addEventListener, it doesn’t work.

another thing: why should adding code to the objects representing the page be a problem? it’s not inline scripting, and unsafe-inline shouldn’t concern it.

That is to be expected. Due to the Xray vision, the .addEventListener function called by the page scripts is a different one (that does the exact same thing).

why should adding code to the objects representing the page be a problem? it’s not inline scripting, and unsafe-inline shouldn’t concern it.

if you are adding script tags with code to the page, that is an inline script and the CSP will prevent it’s execution. It duesn’t matter where the code string came from.

also, when using jquery and stopImmediatePropagation […], it doesn’t work.

You can’t use jQuery for this. You need to use .addEventListener and set useCaptureto true. jQuery doesn’t support that. If you attach your listener like that, it can call .stopImmediatePropagation().

sure it’s possible with jquery.
that’s simply not true, xray vision is concerning content and background script communication, it’s not inline scripting, and so on.
i’m out of this conversation.
thank you again for your help, annyway.