1

Since extensions can not access unsafeWindow, like Firefox can, to hook into DOM scripts am I looking for other ideas so I come to SO for help!

How about using some code to inject into DOM and sending the intercepted response to a background page, which then does some initial processing before calling a content script for final processing. When done, it answers to the background with a modified response, or the original (it depends), and the background page sends the response back to DOM which handles it to the DOM script response function.
There is just one problem with this, a background page cant communicate with the DOM.

I did a small test with injecting some code, where I output something to the console and an alert. The result wasnt good, as the alert fired but the console was empty - not even an error, which makes me wonder - what console received the output ?

function injectCode(fn){ // Executing an anonymous script
     var script = document.createElement('script');
     script.type = 'application/javascript';
     script.textContent = '(' + fn + ')();';
     document.documentElement.appendChild(script); // run the script
     document.documentElement.removeChild(script); // clean up
  }
var code = function(){
  console.log('dom',window);
  alert('code injected');
}
injectCode(code);

I also tried addEventListener, with DOMAttrModified DOMSubtreeModified DOMNodeInserted, on DOM elements that change when the DOM ajax response is fully parsed but all failed to fire.

Am I trying to do the impossible, by any means ?

Kim
  • 2,747
  • 7
  • 41
  • 50

1 Answers1

0

Before continuing, make sure that you know the differences between the script contexts in an extension.

To inject a script from the background page, you have to execute a Content script, which on his turn injects the script as mentioned in your question / here.

Examples (using chrome.tabs.executeScript):

// null = current active tab
// Simple code, background:
chrome.tabs.executeScript(null, {
   code: [
    'var s = document.createElement("script");',
    's.textContent = "console.log(window);";',
    '(document.head||document.documentElement).appendChild(s);',
    's.parentNode.removeChild(s);'
   ].join('\n')
});

I can imagine that this method is not doable for a big chuck of code. For a set of pre-defined scripts, you can then use two scripts: the code itself, and a helper script:

// config.js
var fn_code = function() {
    console.log(window); ....
};
// helper.js
var s = document.createElement('script');
s.textContent = '(' + fn_code + ')();';
(document.head||document.documentElement).appendChild(s);
s.parentNode.removeChild(s);

// Background:
chrome.tabs.executeScript(null, {file: 'config.js'}, function() {
    chrome.tabs.executeScript(null, {file: 'helper.js'});
});

Note: I did not directly link to "config.js", because that complicates the use when using manifest version 2, see "web_accessible_resources".


The previous method only shows how to execute code in one direction (background -> page). If there's a need to activate a background's function from the injected script, you have to define and listen to a custom event handler. See this answer + demo.


Because the code is injected, thus runs in the scope of the page, you have to check the console at the page.

When chrome.tabs.executeScript fails to execute the Content script (eg. because the extension does not have the permission to access a certain page), an error is logged at the console in the background page. This console can be accessed by following these steps.

Community
  • 1
  • 1
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • I am injecting code via a content script and I did have the console for the DOM page open. Could you explain how this helps me? If I inject a rewritten function of DOM script ajax response function, then it would be cut off from the extension and I would have to use something like this http://code.google.com/chrome/extensions/content_scripts.html#host-page-communication which kinda defeats the purpose of intercepting the ajax response. Parsing the DOM seems like the better solution. – Kim May 06 '12 at 10:45
  • @Kim The post answers the highlighted question regarding the console. Your question makes use of an injected script (you did **not** mention where this script was used, by the way). If this answer does not match your expectations, please edit the question to be more clear. Currently, your question's post does not even match the title. – Rob W May 06 '12 at 10:49
  • I think the title matches just fine. Your answer focuses more on how to inject code into DOM, which I know as you can see from the code included in my question. I need to 'hook' into a DOM scripts ajax response handler while still communicating with my extension. Your answer doesnt cover this. – Kim May 06 '12 at 17:17
  • @Kim That is covered in the section below `"web_accessible_resources"`. – Rob W May 06 '12 at 17:18