If the onload
event of the iframe
with a data:
URI fires, the browser supports data:
URIs. Otherwise, the browser doesn't support data:
URIs.
The example code also checks if scripting is allowed from a data:
URI by sending a message from the iframe
to the parent window.
Working code
var iframeDataURISupport = { checked: false, supported: false, scriptingSupported: false };
function iframesSupportDataURIs(callback) {
if (!iframeDataURISupport.checked) {
var iframe = document.createElement('iframe'), alreadyCalled = false, done = function () {
if (!alreadyCalled) {
alreadyCalled = true;
document.body.removeChild(iframe);
console.log(iframeDataURISupport);
callback && callback(iframeDataURISupport);
}
}, previousMessageHandler = window.onmessage, dataURI = 'data:text/html,<' + 'script>window.parent.postMessage("data: URIs supported", "*");<' + '/script>';
window.onmessage = function (e) {
if (e.data === 'data: URIs supported') {
window.onmessage = previousMessageHandler;
iframeDataURISupport.supported = true;
iframeDataURISupport.scriptingSupported = true;
done();
} else {
window.onmessage.apply(this, arguments);
}
};
iframe.src = dataURI;
iframe.setAttribute('style', 'display: inline-block; width: 0; height: 0; overflow: hidden; border: 0 none; padding: 0; margin: 0;'.replace(/;/g, ' !important;'));
iframe.onload = function (e) {
if (iframe.src === dataURI) {
iframeDataURISupport.supported = true;
setTimeout(done, 100);
} else done();
};
document.body.appendChild(iframe);
setTimeout(done, 500);
} else {
setTimeout(function () {
callback && callback(iframeDataURISupport);
}, 5);
}
};
Usage
iframesSupportDataURIs(function (details) {
alert('This browser ' + (details.supported ? 'supports' : 'does not support') + ' data: URIs. It ' + (details.scriptingSupported ? 'also supports' : 'does not support') + ' scripting from data: URIs');
});
If you want more advanced control, you can call it like this:
iframeDataURISupport.checked ? functionName(iframeDataURISupport) : iframesSupportDataURIs(functionName);
Demo
Play with it on JSFiddle.
this.contentWindow.document
will throw on success. IE fires the load event even though nothing is loaded, so a simply try/catch will tell you if the browser supports data uri in a frame. – Wilberwilberforce