3

In the past this used to work:

// writing
var newTab = window.open();
newTab.document.write("<html><head><title>I'm just a tab</title></head>");
newTab.document.write("<body id='hello'>With some text on it</body>");
newTab.document.write("</html>");
newTab.document.close();

// reading what was wrote
newTab.document.getElementById('hello').addEventListener("click", custom_search_function(), false);

However now when I try to execute this code, Firefox mentions a security error:

Error: SecurityError: The operation is insecure.

I searched the forum for an alternative and this works:

var textOnPage = "<html><head><title>I'm just a tab</title></head><body>";
var newTab = window.open("data:text/html;charset=UTF-8," + encodeURIComponent(textOnPage));
newTab.document.close();

But I can't access the page via getElementById

newTab.document.getElementById('hello').addEventListener("click", custom_search_function(), false);

returns:

Error: TypeError: newTab.document.getElementById(...) is null

How can I write to this new tab and then go back to read it through functions such as getElementById?

Kyle
  • 3,004
  • 15
  • 52
  • 79
  • possible duplicate of [Javascript communication between browser tabs/windows](http://stackoverflow.com/questions/4079280/javascript-communication-between-browser-tabs-windows) – nneonneo Aug 10 '13 at 01:53
  • @nneonneo That's a pretty old way to do this nowadays. The `postMessage` API is now preferred. – David-SkyMesh Aug 10 '13 at 09:51

2 Answers2

2

You're falling foul of the Single Origin Policy. When you open a new window without a URL, by definition it can't have the same domain name as the original (opener) window.

You could instead have the window.open() call open another URL on your site (mostly blank html) and as part of its body.onload event handler (or jQuery.ready()) you could set up an event handler for the message event like this:

$(document).ready(function(){
   window.addEventListener("message", receiveMessage, false);
});

function receiveMessage(evt)
{
  if (evt.origin !== "https://your-domain.here")
    return;

  // do something with evt.data
  $(document.body).append(""+evt.data);
}

In your originating window you call:

otherWindow.postMessage(message, "https://your-domain.here");

The postMessage API is now well supported across a variety of modern browsers.

You'll still not be able to directly reach in to maniuplate the content of otherWindow, but you can post messages back from otherWindow to your originating window to achieve the same effect. (e.g: put your content manipulation code in otherWindow's content and 'call' it from your originating window).

David-SkyMesh
  • 5,041
  • 1
  • 31
  • 38
2

This used to work in a variety of browsers for a long time (in my past life as a web developer I actually took advantage of this technique for web applications). It used to be that window.open pages were treated mostly like they were from the same domain as the parent page (although the behavior was always a little weird and the url in the url bar was usually about:blank).

Now the standard is to open the pages with the url origin being about:blank, and while I can understand why it made sense to simplify things and I can understand the reason this breaks the previous behavior, but the issue here is that about:blank is not a real url so the standard cross-origin rules should be different, at least in the case of window.open calls.

Is there a real security threat here from allowing windows to write to pages they have opened? I do not think so, but it is possible. In the end, I am no longer a web developer and do not care that much about these things, but I would not be surprised if other people's applications broke as well.