2

I'd like to edit the content of an iframe through a chrome extension but am unable to because contentWindow/contentDocument of the iframe returns undefined. Been looking around for an answer and as I've understood it it's easily fixed if the iframe exists on the page from the beginning, but it doesn't. The iframe in question is the gmail compose text area which is in the form of an iframe, and it's added to the DOM dynamically. Is there any way to do this through a chrome extension?

Edit: I'm sorry. Rob W Made me realize the contentDocument indeed can be accessed. What I'm trying to do here is add some extra functionality in Gmail, having a button in the toolbar that adds some html in the compose window. I now have the button partially working, it adds the html but It doesn't do it at the caret like its supposed to since I can't access contentWindow in order to do this:

range = iWindow.getSelection().getRangeAt(0);
node = range.createContextualFragment(html);
range.insertNode(node);

Any solution to this?

Clox
  • 1,923
  • 5
  • 28
  • 43

1 Answers1

3

contentWindow is not accessible in Chrome extensions.
contentDocument, on the other hand, correctly returns the document within a frame, provided that the iframe is at the same origin, which is the case for Gmail.

Here's an example for Gmail. For simplicity, I assumed that there's only one editor in the document.

var poller = setInterval(function() {
    var editor = document.querySelector('iframe.editable');
    if (editor && editor.contentDocument && !editor.__rwHandled) {
        editor.__rwHandled = true; // Run once for an editor instance
        var textNode = document.createTextNode('It works!');
        editor.contentDocument.body.appendChild(textNode);
    }
}, 200);

Whenever you want to stop the poller, just use clearInterval(poller);. Make sure that the methods you for detection are inexpensive. Eg: querying for a DOM node is OK, opening new windows isn't.

Community
  • 1
  • 1
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • Thanks for the answer. I've made an edit to my question. I'm sorry, I'm sure it's because I'm not experienced enough with this but I wasn't really able to understand your answer. I did try a lot, and I did try to add contentscript in the iframe using executeScript but I really wasn't able to get it working at all. Sorry, and I appreciate the help so far. – Clox Dec 04 '12 at 19:29
  • @Clox That's because your code really needs access to the window object, for using `window.getSelection();`. [Inject a script](http://stackoverflow.com/questions/9515704/building-a-chrome-extension-inject-code-in-a-page-using-a-content-script/9517879#9517879) which does what you want. If you want to communicate between the page and the content script, set up a custom event or [use `postMessage`](http://stackoverflow.com/a/13271692/938089?accessing-iframe-from-chrome-extension). – Rob W Dec 04 '12 at 21:48
  • 1
    It appears iframes in Gmail don't always load from the same origin; if you mouseover a sender in the main email list view, you get a small box (what they apparently call a hovercard). This box is created by an iframe loading from: https://apis.google.com/u/0/_/streamwidgets/hovercard?origin=https%3A%2F%2Fmail.google.com... - you can affect these iframes with "all_frames": true http://stackoverflow.com/questions/6641729/in-chrome-extension-content-scripts-cant-affect-inside-the-iframe?rq=1 – Chris Moschini Dec 27 '12 at 00:23