如何识别一个网页是否正在加载一个iframe或直接进入浏览器窗口?

我正在写一个基于iframe的Facebook应用程序。 现在,我想使用相同的HTML页面来呈现正常的网站,以及Facebook中的canvas页面。 我想知道是否可以确定页面是否已经加载到iframe中或直接在浏览器中?

由于相同的源策略,浏览器可以阻止对window.top访问。 IE的错误也发生。 这是工作代码:

 function inIframe () { try { return window.self !== window.top; } catch (e) { return true; } } 

topself都是window对象(和parent window ),所以你会看到你的窗口是否是顶层窗口。

window.frameElement返回embedded窗口的元素(如<iframe>或<object>);如果窗口是顶层,则返回null。 所以识别代码看起来像

 if (window.frameElement) { // in frame } else { // not in frame } 

这是标准而相当新的方法。 它完全适用于Chrome和Firefox。 我不能推荐它作为通用解决scheme,但应该在这里提到我想。

RoBorg是正确的,但我想添加一个附注。

在IE7 / IE8中,当微软向他们的浏览器添加了Tabs时,如果你不小心的话,他们打破了一件会对你的JS造成破坏的东西。

想象一下这个页面布局:

 MainPage.html IframedPage1.html (named "foo") IframedPage2.html (named "bar") IframedPage3.html (named "baz") 

现在在框架“巴兹”你点击一个链接(没有目标,加载在“baz”框架)它工作正常。

如果页面被加载,我们称之为special.html,使用JS来检查“它”是否有一个名为“bar”的父框架,它将返回true(预期)。

现在让我们来说一下在加载时的special.html页面,检查父框架(是否存在和它的名字,如果是“bar”,它会自动重新加载到框架中。

 if(window.parent && window.parent.name == 'bar'){ window.parent.location = self.location; } 

到现在为止还挺好。 现在来了错误。

可以说,不是像正常一样点击原始链接,而是在“baz”框架中加载special.html页面,您中间点击了它或者select了在新的Tab中打开它。

当新标签加载( 根本没有父框架!IE将进入一个无限的页面加载循环! 因为IE在JavaScript中“复制”了框架结构,使得新的标签具有父项,并且该父项具有名称“栏”。

好消息是,检查:

 if(self == top){ //this returns true! } 

在那个新的选项卡不会返回true,因此您可以testing这个奇怪的条件。

在Firefox 6.0 Extension(Addon-SDK 1.0)的内容脚本中,接受的答案不适用于我:Firefox在每个顶层窗口和所有iframe中执行内容脚本。

在内容脚本中,我得到以下结果:

  (window !== window.top) : false (window.self !== window.top) : true 

这个输出的奇怪之处在于,无论代码是在iframe还是在顶层窗口中运行,它总是一样的。

另一方面,谷歌浏览器似乎只能在顶层窗口中执行一次我的内容脚本,所以上述方法根本不起作用。

在这两个浏览器的内容脚本中最终为我工作的是这样的:

  console.log(window.frames.length + ':' + parent.frames.length); 

如果没有内嵌框架打印0:0 ,则在包含一个框架的顶层窗口中打印1:1 ,并在文档的唯一内联框架中打印0:1

这允许我的扩展在两个浏览器中确定是否存在任何iframe,并且如果在iframe之一内运行,则在Firefox中。

我正在使用这个:

 var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1); 

由于您是在facebook应用程序的上下文中询问的,因此您可能需要考虑在初始请求发生时在服务器上检测到这一点。 如果从iframe调用的话,Facebook将传递一堆查询string数据,包括fb_sig_user键。

由于您可能需要在应用程序中检查并使用这些数据,因此可以使用它来确定要呈现的相应上下文。

以这个javascript函数为例说明如何完成这个。

 function isNoIframeOrIframeInMyHost() { // Validation: it must be loaded as the top page, or if it is loaded in an iframe // then it must be embedded in my own domain. // Info: IF top.location.href is not accessible THEN it is embedded in an iframe // and the domains are different. var myresult = true; try { var tophref = top.location.href; var tophostname = top.location.hostname.toString(); var myhref = location.href; if (tophref === myhref) { myresult = true; } else if (tophostname !== "www.yourdomain.com") { myresult = false; } } catch (error) { // error is a permission error that top.location.href is not accessible // (which means parent domain <> iframe domain)! myresult = false; } return myresult; } 

我不知道这个例子是如何工作的,但我用IE浏览器,火狐浏览器和谷歌浏览器没有问题:

 var iFrameDetection = (window === window.parent) ? false : true; 
 if(typeof(parent) == 'undefined') { console.log('Not Iframe'); } else { console.log('iframe'); } 

如果您想知道用户是否从Facebook页面选项卡或canvas检查签名请求访问您的应用程序。 如果你没有得到它,可能用户没有从Facebook访问。 确保signed_request字段结构和字段的内容。

用php-sdk你可以得到这样的签名请求:

 $signed_request = $facebook->getSignedRequest(); 

您可以在这里阅读更多关于签名请求:

https://developers.facebook.com/docs/reference/php/facebook-getSignedRequest/

和这里:

https://developers.facebook.com/docs/reference/login/signed-request/

这是我用过几次的一段古代代码:

 if (parent.location.href == self.location.href) { window.location.href = 'https://www.facebook.com/pagename?v=app_1357902468'; } 
 if (window.frames.length != parent.frames.length) { page loaded in iframe } 

但是,只有当您的页面和页面中的iframe数量不同时,才会将您加载到iframe中。 在你的页面没有iframe有这个代码的结果100%的保证

在每个页面写这个javascript

 if (self == top) { window.location = "Home.aspx"; } 

然后它会自动redirect到主页。