"Access Is Denied" JavaScript Error When Trying to Access the Document Object of a Programmatically-Created <Iframe> (Ie-Only)

Access is denied JavaScript error when trying to access the document object of a programmatically-created iframe (IE-only)

if the document.domain property is set in the parent page, Internet Explorer gives me an "Access is denied"

Sigh. Yeah, it's an IE issue (bug? difficult to say as there is no documented standard for this kind of unpleasantness). When you create a srcless iframe it receives a document.domain from the parent document's location.host instead of its document.domain. At that point you've pretty much lost as you can't change it.

A horrendous workaround is to set src to a javascript: URL (urgh!):

 iframe.src= "javascript:'<html><body><p>Hello<\/p><script>do things;<\/script>'";

But for some reason, such a document is unable to set its own document.domain from script in IE (good old “unspecified error”), so you can't use that to regain a bridge between the parent(*). You could use it to write the whole document HTML, assuming the widget doesn't need to talk to its parent document once it's instantiated.

However iframe JavaScript URLs don't work in Safari, so you'd still need some kind of browser-sniffing to choose which method to use.

*: For some other reason, you can, in IE, set document.domain from a second document, document.written by the first document. So this works:

if (isIE)
iframe.src= "javascript:'<script>window.onload=function(){document.write(\\'<script>document.domain=\\\""+document.domain+"\\\";<\\\\/script>\\');document.close();};<\/script>'";

At this point the hideousness level is too high for me, I'm out. I'd do the external HTML like David said.

jquery - iframe access denied in IE on some pages

Issue is due to IE not inheriting the parent document.domain.

Unfortunately, once you get into this murky area, it took some specific hacks to get this to work properly.

Basically doing a check for if document.domain is being explicitly set and the browser is IE.

Full updated plugin:

https://github.com/jasonday/printThis

(function ($) {
var opt;
$.fn.printThis = function (options) {
opt = $.extend({}, $.fn.printThis.defaults, options);
var $element = this instanceof jQuery ? this : $(this);

var strFrameName = "printThis-" + (new Date()).getTime();

if(window.location.hostname !== document.domain && navigator.userAgent.match(/msie/i)){
// Ugly IE hacks due to IE not inheriting document.domain from parent
// checks if document.domain is set by comparing the host name against document.domain
var iframeSrc = "javascript:document.write(\"<head><script>document.domain=\\\"" + document.domain + "\\\";</script></head><body></body>\")";
var printI= document.createElement('iframe');
printI.name = "printIframe";
printI.id = strFrameName;
printI.className = "MSIE";
document.body.appendChild(printI);
printI.src = iframeSrc;

} else {
// other browsers inherit document.domain, and IE works if document.domain is not explicitly set
var $frame = $("<iframe id='" + strFrameName +"' name='printIframe' />");
$frame.appendTo("body");
}

var $iframe = $("#" + strFrameName);

// show frame if in debug mode
if (!opt.debug) $iframe.css({
position: "absolute",
width: "0px",
height: "0px",
left: "-600px",
top: "-600px"
});

// $iframe.ready() and $iframe.load were inconsistent between browsers
setTimeout ( function () {

var $doc = $iframe.contents();

// import page stylesheets
if (opt.importCSS) $("link[rel=stylesheet]").each(function () {
var href = $(this).attr("href");
if (href) {
var media = $(this).attr("media") || "all";
$doc.find("head").append("<link type='text/css' rel='stylesheet' href='" + href + "' media='" + media + "'>")
}
});

//add title to iframe
if (opt.pageTitle) $doc.find("head").append("<title>" + opt.pageTitle + "</title>");

// import additional stylesheet
if (opt.loadCSS) $doc.find("head").append("<link type='text/css' rel='stylesheet' href='" + opt.loadCSS + "'>");

// grab $.selector as container
if (opt.printContainer) $doc.find("body").append($element.outer());

// otherwise just print interior elements of container
else $element.each(function () {
$doc.find("body").append($(this).html())
});

if($iframe.hasClass("MSIE")){
// check if the iframe was created with the ugly hack
// and perform another ugly hack out of neccessity
window.frames["printIframe"].focus();
setTimeout(function () {
$doc.find("head").append("<script> window.print(); </script>");
}, 500 );
} else {
// proper method
$iframe[0].contentWindow.focus();
$iframe[0].contentWindow.print();
}

//remove iframe after print
if (!opt.debug) {
setTimeout(function () {
$iframe.remove();
}, 1000);
}

}, 333 );

};

// defaults
$.fn.printThis.defaults = {
debug: false, // show the iframe for debugging
importCSS: true, // import parent page css
printContainer: true, // print outer container/$.selector
loadCSS: "", // load an additional css file
pageTitle: "" // add title to print page
};

// $.selector container
jQuery.fn.outer = function () {
return $($("<div></div>").html(this.clone())).html()
}
})(jQuery);

Access is denied error on accessing iframe document object

Solved it by myself!

The problem was, that even though the correct response was being sent (verified with Fiddler), it was being sent with an HTTP 500 error code (instead of 200).

So it turns out, that if a response is sent with an error code, IE replaces the content of the iframe with an error message loaded from the disk (res://ieframe.dll/http_500.htm), and that causes the cross-domain access denied error.

Error: Permission denied to access property '$' - iFrame

You need to set both domains to the same top level domain in JavaScript:

A page may change its own origin with some limitations. A script can set the value of document.domain to a subset of the current domain. If it does so, the shorter domain is used for subsequent origin checks.

So if you have static.example.com and news.example.com you should include this JavaScript to run before you try any cross-frame access:

document.domain = 'example.com';

You will need to run this code in both windows.



Related Topics



Leave a reply



Submit