9

Ok, so what I want is to override a method that already exists inside a tab, what I'm going to use is the default alert function. Override it inside the JS function would be very easy. just add

window.alert = function(){ 
   //Do Something
}

but the problem is that when I try to use chrome.tabs.executeScript("window.alert = function() { };"); it doesn't work. I tried to do this manually by using the Console from Chrome in the tab that I wanted to override the function, I typed that override function in the log and pressed enter, and done, the alert function was overridden, but I can't do this via Chrome Extension.

When you add executeScript, it seems like it creates a Javascript apart from the one inside the tab DOM, because I can create functions with the name of a function that already exists inside the tab DOM.

Is there a way to make executeScript to write the script inside of the tab DOM, so it can actually override any function that was written by the .js file the page generated?

Thanks!

Grego
  • 2,220
  • 9
  • 43
  • 64
  • Are you sure that the functionality is separate from the DOM? Maybe try a setTimer or setInterval to see if that is the case. Maybe the executeScript is executing before the DOM scripts. – PJH Aug 23 '12 at 16:15
  • I tried that. I made a setInterval for in every 500 milliseconds it overrides the alert function and nothing, it's not about which time it interprets, it is really separate from the page DOM, we can't even invoke existing functions in the page. All we have access is our script, the one we generated by executeScript, and the HTML. executeScript can't run functions of the page generated javascript. – Grego Aug 23 '12 at 16:21

1 Answers1

22

Functions don't exist as part of the DOM; instead, they exist within an execution environment that includes the DOM. Content scripts (including scripts run with executeScript) and actual web pages share the same DOM, but have separate execution environments. So calling window.alert = function() {} only rewrites window.alert within your content script's execution environment, not in the actual page's one.

The typical way to reach the execution environment of the actual page is to inject a <script> tag into the DOM. This can be done in several ways. One method is to white-list a script in web_accessible_resource, and insert the <script> element referring to this script in the document. The required absolute URL can be obtained via chrome.extension.getURL.

var s = document.createElement("script");
s.src = chrome.extension.getURL("script_in_extension.js");
(document.head||document.documentElement).appendChild(s);

Make sure that the script is configured to "run_at": "document_start", so that the overwrite takes place before any of the page's functions are loaded.

Note: Your action can easily be undone by the page:

window.alert = function(){ /*...*/ }; // Your overwrite
delete window.alert;                  // Run from the page/console/...
window.alert('Test?');                // Displays alert box.

If it's critical that the overwritten function cannot be removed, use Object.defineProperty to define an immutable method. For more details, see Stop a function from execute with Chrome extension.

Shaya Ulman
  • 1,299
  • 1
  • 12
  • 24
apsillers
  • 112,806
  • 17
  • 235
  • 239
  • I've edited your answer to remove incorrect information, and add extra information. Check if you agree with it. – Rob W Aug 24 '12 at 08:25
  • @RobW `defineProperty` is a very good note (but should it read "`replace the property`", or am I not quite following you?). I didn't mention the `run_at` property since they OP only asked about using `executeScript`, but it's definitely useful and relevant in almost all cases. Looks good, thanks. – apsillers Aug 24 '12 at 12:54
  • @RobW @apsillers, Re "..overwrite.."; you'll also need to `async=false` if you're using `src=`. ¶ In any case, I've got little faith that its guaranteed to run at the start, even while the docs write that its before [any other script is run](https://archive.is/bjgXQ#selection-5609.45-5609.68). Does someone have a link to that portion of source code? Also, aside from there's . – Pacerier Oct 12 '17 at 17:42
  • @RobW, @apsillers, Ok just tested and it works so far for the manifest one but **it doesn't work** for both executescriptcode and executescriptfile. I tested https://jsfiddle.net/qrate8aq/ with ftp `ftp://speedtest.tele2.net`, http `www.w3fools.com`, https `https://en.wikipedia.org/wiki/Main_Page`. Same 3 links for https://jsfiddle.net/f9bL5os6/ and https://jsfiddle.net/hofppzau/ – Pacerier Oct 12 '17 at 18:47
  • Refby https://stackoverflow.com/questions/19191679/chrome-extension-inject-js-before-page-load/19192010#comment80380207_19192010 – Pacerier Oct 12 '17 at 18:55
  • Just tried the "Note: Your action can easily be undone by the page:" code; delete window.alert; window.alert("test"); in FF and Chrome and it gives an error - alert not defined/not a function ( possibly behaviour changed since original post ) – Bob Aug 26 '19 at 20:32