检查JS是否可以访问iframe的文档

时间:2012-08-08 20:47:11

标签: javascript jquery iframe same-origin-policy

有没有标准方法可以知道我的脚本是否可以访问iframe的文档?

我在网上找不到任何内容所以我想出了这个:

function checkifr() {
    function errHandler() {
        alert('Error. Try again later.');
    }
    var ifr = $('#ifr')[0]; //the iframe DOM element

    try {
        var d = ifr.contentWindow || ifr.contentDocument;
        if (!d) {
            errHandler();
            return false;
        }

        var b = $('#ifr').contents().find('body');
        //... manipulate iframe content

    } catch(e) {
        errHandler();
    }
}

它有效,当我尝试访问iframe的内容并最终在catch块中时,Firefox会抛出错误。 Chrome在控制台中显示Unsafe JavaScript attempt to access frame警告,但从未进入catch阻止,似乎这些尝试返回null,因此初始if (!d)负责处理。 Opera和IE的行为类似于FF。 修改:使用上面的代码,Chrome现在返回一个“空”Window对象(没有属性),不会触发if块。检查Esailija的答案,该答案适用于跨浏览器!

这是fiddle

无法针对iframe测试src的{​​{1}}。

  

合理背景这是因为此功能是我正在开发的小图像上传插件的一部分(使用window.location作为目标,因为IE< 9不支持XHR2 ),目标主要是验证连接错误/超时/等。这些错误的默认浏览器页面受同一起源警察的影响,因此这个问题的目的。我不想发送ajax调用来检查页面是否可用,因为我想验证提交请求本身。 jQuery的.load处理程序不会触发错误,jQuery的.erroriframe HTML属性不起作用。工作脚本的插图可用here,但您可以完全忽略它,只需回答以下问题。

请注意,上述块仅用于说明我无法使用onerror

的原因

我确实认为应该有一种更简单/标准的方法来检查iframe.src的“可访问性”,但我无法在网络中找到任何内容,除了半解决方案只检查{{ 1}}并且不适用于许多情况。如果我的hackish iframe / iframe.src块被认为是技术上“干净”的解决方案,那么如果找不到更好的选择,其他人可能会重复使用它。

有没有任何标准或更简单的方法或jQuery插件来检查我的脚本是否可以访问try的文档,而不会将catch的{​​{1}}与{iframe进行比较1}?如果可能,在控制台中没有iframe / src块和错误/警告。

2 个答案:

答案 0 :(得分:12)

这是另一种选择,如果没有尝试捕获,就无法真正做到。

测试http://jsfiddle.net/LHjwZ/11/

function checkIframe( ifr ) {
    var key = ( +new Date ) + "" + Math.random();

    try {
        var global = ifr.contentWindow;
        global[key] = "asd";
        return global[key] === "asd";
    }
    catch( e ) {
        return false;
    }
}

答案 1 :(得分:1)

无论访问是否抛出异常,以下是一个有用的想法:

function checkFrameAccess(ifr) {
    try {
        var doc = ifr.contentDocument || ifr.contentWindow.document;
        var origClass = doc.body.className;
        var newClass = origClass += " xxxxx";
        doc.body.className = newClass;
        var valid = doc.body.className == newClass;
        doc.body.className = origClass;
        return(valid);
    } catch(e) {
        return(false);
    }
}

如果它们抛出异常,您最终会进入异常处理程序并返回false。如果它们不抛出异常,那么您测试是否可以实际修改框架中body标签的className。如果修改有效,那么显然你可以修改它。如果没有,那么它就不允许你访问它。