I am developing a system that allows userwritten javascript in widgets. To keep things secure, I plan to sandbox these widgets in iframes. Of course, for the sandboxing to be effective the iframe must have a different domain than the parent document.
I would really love to be able to dynamically generate the iframe with code similar to this:
template = '<html><body><script>/* user code */</script></body></html>'
src = 'javascript: document.write("' + template + '")'
widget = $('<iframe>').attr('src', src)
$('#container').append(widget)
...and then have the resulting iframe be treated as cross-domain from the parent window. Is this possible, and if so, how would it be done?
Ok, I think I get what you need but it's a bit tricky. You want to create an
<iframe>
and populate it with the user Javascript client-side but still have the client sandboxed?This is fairly non-standard. Usually the contents of the
<iframe>
are generated server side. But here it goes.First some background: documents can not access the content of any document that is not from the same domain (including sub-domain) and port. But they can change their own security domain using the
document.domain
property. So what you need to do is lighten up the security then tighten it back up again for the user script to run.So you can't do it the way you specified because if you create an
<iframe>
with a Javascriptsrc
thedocument.domain
will match the parent frame. This means that the widget will have full access to everything.So here's how you can do it:
home.example.com
andwidgets.example.com
.widgets.example.com
and make sure it calls this javascript:document.domain = "example.com";
document.domain
to the same value.widgets.example.com
into it.myFrame.contentWindow.foo = "template";
document.domain
on the main window back tohome.example.com
so that the<iframe>
s will no longer have access to the parent frameThat last part is the tricky part. You can't just embed the code because if it runs automatically it will run before you can change the domain of the home document back, which will be a security issue. So instead you need to set it to a temporary variable inside the frame then somehow trigger the frame to replace its own contents with that template but only after everything is locked down. The easiest and most compatible way would be to trigger it on resize and then just change the width or height of the frame.
Now, alternatively, if the widget was populated server-side:
widgets.example.com
home.example.com
But I assume that you have reasons for doing it all client-side.
The logical next topics: communicating between the frames and auto-sizing. But those are for another day.
Did I answer your question? I hope so because this was a lot of typing and I won't mind the reputation points if you vote up and accept my answer! ;)