2008-11-28 23 views

Respuesta

815

Los navegadores pueden bloquear el acceso a window.top debido a same origin policy. Los errores de IE también tienen lugar. Aquí está el código de trabajo:

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

top y self son ambos window objetos (junto con parent), por lo que se está viendo si la ventana es la ventana superior.

+3

Esto parece funcionar bien en Firefox. ¿Funciona en otros navegadores también? – akshat

+5

Tener una página con un iframe dentro de un iframe, para probar el iframe de mi hijo si mi iframe primario estaba incrustado en la página, lo usé if (parent === top) – sglessard

+7

@sglessard Si la página secundaria y parent son de dominios diferentes entonces Firefox se quejará por la Política de Same Origin (www.w3.org/Security/wiki/Same_Origin_Policy) y el código no funcionará –

25

RoBorg es correcto, pero quería agregar una nota al margen.

En IE7/IE8 cuando Microsoft agregó pestañas a su navegador, rompieron una cosa que causará estragos en su JS si no tiene cuidado.

Imagínese este diseño de página:

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

ahora en el marco de "baz" hace clic en un enlace (sin objetivo, cargas en el marco de "baz") que trabaja muy bien.

Si la página que se carga, vamos a llamarla special.html, usa JS para verificar si "it" tiene un marco principal llamado "bar", devolverá verdadero (esperado).

Ahora digamos que la página special.html cuando carga, comprueba el marco padre (por la existencia y su nombre, y si es "barra" se vuelven a cargar en sí en el marco de la barra. Ej

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

hasta aquí todo bien. Ahora viene el fallo.

permite decir en lugar de hacer clic en el enlace original como normal, y la carga de la página special.html en el "Baz" marco, medio-clic o eligió ábralo en una nueva pestaña.

Cuando esa nueva pestaña se carga (sin ningún cuadro principal).) ¡IE introducirá un bucle infinito de carga de página! porque IE "copia sobre" la estructura de marco en JavaScript de modo que la nueva pestaña TIENE un padre y ese padre TIENE el nombre "barra".

La buena noticia, es que la comprobación:

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

en que la nueva ficha de vuelta verdad, y por lo tanto se puede probar esta situación extraña.

+0

¿Se ha solucionado el error mientras tanto? No puedo reproducirlo en IE8. Siempre obtengo el 'window.parent' correcto. – user123444555621

+1

No estoy seguro - Ejecutaré mi suite de pruebas contra IE9 y abajo nuevamente y publicaré una actualización. – scunliffe

+8

@scunliffe - ¿Alguna actualización? – Nick

1

Como usted pregunta en el contexto de una aplicación de Facebook, es posible que desee considerar detectar esto en el servidor cuando se realiza la solicitud inicial. Facebook pasará un montón de datos de cadena de consulta, incluida la clave fb_sig_user si se llama desde un iframe.

Dado que probablemente necesite verificar y utilizar esta información de todos modos en su aplicación, utilícela para determinar el contexto apropiado para representar.

1

Utilice esta función de Javascript como ejemplo de cómo lograr esto.

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; 
} 
15

La respuesta aceptada no funcionó para mí dentro de la escritura de contenido de una extensión de Firefox 6.0 (Addon-SDK 1.0): Firefox ejecuta la secuencia de comandos contenidos en cada uno: la ventana de nivel superior y en todos los marcos flotantes.

Dentro de la escritura de contenido consigo los siguientes resultados:

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

Lo extraño de esta salida es que es siempre el mismo, independientemente de si el código se ejecuta dentro de una la ventana de nivel superior de marco flotante o.

Por otro lado, Google Chrome parece ejecutar mi script de contenido solo una vez dentro de la ventana de nivel superior, por lo que lo anterior no funcionaría en absoluto.

Lo que finalmente trabajó para mí en un script contenido en ambos navegadores es la siguiente:

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

Sin iframes Esto imprime 0:0, en una ventana de nivel superior que contiene un cuadro que imprime 1:1, y en el único iframe de un documento imprime 0:1.

Esto permite a mi extensión determinar en ambos navegadores si hay algún iframes presente, y adicionalmente en Firefox si se ejecuta dentro de uno de los iframes.

+0

Pruebe 'document.defaultView.self === document.defaultView.top' o' window! == window.top'. En el script de contenido del SDK complementario de Firefox, el objeto 'self' global es un objeto utilizado para comunicarse con el script principal. –

-1

Es una antigua pieza de código que he usado un par de veces:

if (parent.location.href == self.location.href) { 
    window.location.href = 'https://www.facebook.com/pagename?v=app_1357902468'; 
} 
+6

Debido a la lectura de XSS, no se permite la ubicación principal. –

+0

Para agregar a Eneko Alonso: esto funciona '(parent.location == self.location)' –

+0

@piotr_cz, funciona solo si la política del mismo origen permite el acceso a 'parent.location'. De lo contrario, se lanza una excepción – Dan

5

estoy usando esto:

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

¿Por qué haces esto: '.indexOf (" HTMLIFrameElement ")'? – Luke

+0

.indexOf ('foobarbaz')> -1 es una forma de comprobar si hay "coincidencia de subcadena" (es decir, ¿se puede encontrar 'foobarbaz' en algún lugar dentro de la cadena?), Pero sin usar expresiones regulares. Es lógicamente equivalente a .match (/ foobarbaz /). Se usa para :-) trabajar en un rango más amplio de navegadores, y todavía se puede usar por hábito o por el rendimiento de la maquinaria de expresión regular. –

-3
if (window.frames.length != parent.frames.length) { page loaded in iframe } 

Pero sólo si el número de marcos flotantes difiere en su página y página que lo están cargando en iframe. No nos iframe en tu sitio para tener garantía del 100% del resultado de este código

+0

No es una solución muy elegante para determinar si la ventana está dentro de un iframe o no, y tampoco hay garantía de que pueda leer desde parent.frames. – Percy

-3

escribir este JavaScript en cada página

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

entonces se redirige automáticamente a la página principal.

+3

Su redirección funcionará cuando no esté si el marco. Entonces no podría navegar en su sitio. En segundo lugar, existen técnicas para evitar el redireccionamiento desde la página principal. –

0

Si desea saber si el usuario está accediendo a su aplicación desde la pestaña de la página de Facebook o el lienzo, compruebe la Solicitud firmada. Si no lo obtiene, probablemente el usuario no esté accediendo desde Facebook. Para asegurarse de confirmar la estructura de los campos signed_request y el contenido de los campos.

Con el php-SDK se puede obtener la solicitud firmada así:

$signed_request = $facebook->getSignedRequest(); 

Puede leer más sobre solicitud firmada aquí:

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

y aquí:

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

61

window.frameElement Devuelve el elemento (como <iframe> o <objeto>) en el que está incrustada la ventana, o nulo si la ventana está en el nivel superior. Así código de identificación parece

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

This is standard and rather new method. Funciona exactamente en Chrome y Firefox. No puedo recomendarlo como una solución universal, pero debería mencionarse aquí, creo.

+1

Nota: intentar leer 'frameElement' arrojará una excepción SecurityError en iframes de origen cruzado, de acuerdo con [W3C] (https://www.w3.org/TR/html5/browsers.html#dom-frameelement) ([WHATWG ] (https://html.spec.whatwg.org/multipage/browsers.html#dom-frameelement) dice que debería devolver nulo en su lugar). Así que es posible que desee envolverlo en una declaración 'try ... catch'. – Oriol

+0

'Este es un método [...] bastante nuevo' <- a través de su enlace, dice IE5.5. Probé en IE9, parece funcionar bien. – Neolisk

+1

esto realmente no funciona – user151496

1
if(typeof(parent) == 'undefined') { 
    console.log('Not Iframe'); 
} 
else { 
    console.log('iframe'); 
} 
+0

Estos no son trabajos en opera mini 11 – Serg

+0

en cromo en el contexto de la ventana principal 'window.parent === window' es verdadero. Entonces tu respuesta es incorrecta. Y esta comparación podría usarse para verificar (al menos en Chrome, no lo probó en otros navegadores). – MarkosyanArtur

1

No estoy seguro de cómo funciona este ejemplo para los más viejos navegadores web pero yo lo uso para IE, Firefox y Chrome sin y número:

var iFrameDetection = (window === window.parent) ? false : true; 
+3

O simplemente '! (Ventana === window.parent)' – CalculatorFeline

Cuestiones relacionadas