web-dev-qa-db-fra.com

Comment identifier si une page Web est en cours de chargement dans une iframe ou directement dans la fenêtre du navigateur?

J'écris une application facebook basée sur l'iframe. Maintenant, je veux utiliser la même page HTML pour rendre le site Web normal ainsi que la page de canevas au sein de Facebook. Je souhaite savoir si je peux déterminer si la page a été chargée dans l'iframe ou directement dans le navigateur.

538
akshat

Les navigateurs peuvent bloquer l’accès à window.top en raison de même règle d’origine . IE bugs ont également lieu. Voici le code de travail:

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

top et self sont tous deux des objets window (avec parent), ce qui vous permet de voir si votre fenêtre est la fenêtre supérieure.

1004
Greg

Dans une iframe de même origine que le parent, la méthode window.frameElement renvoie l'élément (par exemple, iframe ou object) dans laquelle la fenêtre est incorporée. Sinon, si vous naviguez dans un contexte de niveau supérieur ou si les cadres parent et enfant ont des origines différentes, le résultat sera évalué à null.

_window.frameElement
  ? 'embedded in iframe or object'
  : 'not embedded or cross-Origin'
_

Ceci est un HTML Standard avec un support de base dans tous les navigateurs modernes.

78

RoBorg est correct, mais je voulais ajouter une note de côté.

Dans IE7/IE8, lorsque Microsoft a ajouté Tabs à son navigateur, ils ont cassé une chose qui pourrait causer des dégâts avec votre JS si vous ne faites pas attention.

Imaginez cette mise en page:

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

Maintenant dans le cadre "baz" vous cliquez sur un lien (pas de cible, charge dans le "baz" cadre) cela fonctionne bien.

Si la page qui est chargée, appelons-la special.html, utilise JS pour vérifier si "it" a un cadre parent nommé "bar", il retournera true (attendu).

Supposons maintenant que la page special.html, lorsqu’elle est chargée, vérifie le cadre parent (son existence, son nom et, s’il s’agit de "barre", elle se recharge elle-même dans le cadre.).

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

Jusqu'ici tout va bien. Maintenant vient le bug.

Disons qu'au lieu de cliquer sur le lien d'origine comme d'habitude et de charger la page special.html dans le cadre "baz", vous avez cliqué dessus ou choisi de l'ouvrir dans un nouvel onglet.

Lorsque ce nouvel onglet charge ( sans aucun cadre parent!! ) IE entrera dans une boucle sans fin de chargement de la page! parce que IE "copie" la structure de la structure en JavaScript de telle sorte que le nouvel onglet ait un parent et que ce parent porte le nom "bar".

La bonne nouvelle, c'est que vérifier:

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

dans ce nouvel onglet renvoie vrai, et vous pouvez donc tester cette condition étrange.

26
scunliffe

La réponse acceptée ne fonctionnait pas pour moi dans le script de contenu d'une extension de Firefox 6.0 (Addon-SDK 1.0): Firefox exécute le script de contenu dans chaque fenêtre: la fenêtre de niveau supérieur et dans tous les iframes.

Dans le script de contenu, j'obtiens les résultats suivants:

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

La chose étrange à propos de cette sortie est qu'elle est toujours la même, que le code soit exécuté dans une iframe ou dans la fenêtre de niveau supérieur.

D'autre part, Google Chrome semble exécuter mon script de contenu une seule fois dans la fenêtre de niveau supérieur, de sorte que ce qui précède ne fonctionne pas du tout.

Ce qui a finalement fonctionné pour moi dans un script de contenu dans les deux navigateurs est le suivant:

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

Sans iframes, ceci imprime 0:0, dans une fenêtre de niveau supérieur contenant une image, il imprime 1:1, et dans la seule iframe d'un document, il imprime 0:1.

Cela permet à mon extension de déterminer dans les deux navigateurs s'il y a des iframes présents, ainsi que dans Firefox si elle est exécutée dans l'un des iframes.

18
magnoz

Je ne suis pas sûr de savoir comment cet exemple fonctionne pour les anciens navigateurs Web, mais je l'utilise pour IE, Firefox et Chrome sans et dans lequel:

var iFrameDetection = (window === window.parent) ? false : true;
10
portal TheAnGeLs

J'utilise ceci:

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

Meilleur pour l'instant Script de rupture de cadre de navigateur hérité

Les autres solutions n'ont pas fonctionné pour moi. Celui-ci fonctionne sur tous les navigateurs:

Un moyen de se défendre contre le détournement de clic consiste à inclure un script "saut de cadre" dans chaque page qui ne doit pas être encadrée. La méthodologie suivante empêchera l’encadrement d’une page Web, même dans les navigateurs existants, qui ne prennent pas en charge l’en-tête X-Frame-Options.

Dans l'élément document HEAD, ajoutez les éléments suivants:

<style id="antiClickjack">body{display:none !important;}</style>

Tout d'abord, appliquez un ID à l'élément de style lui-même:

<script type="text/javascript">
   if (self === top) {
       var antiClickjack = document.getElementById("antiClickjack");
       antiClickjack.parentNode.removeChild(antiClickjack);
   } else {
       top.location = self.location;
   }
</script>

De cette façon, tout peut être dans le document HEAD et vous n'avez besoin que d'une seule méthode/balise dans votre API.

Référence: https://www.codemagi.com/blog/post/194

2
Albert Olivé

Utilisez cette fonction javascript comme exemple pour y parvenir.

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;
}
2
Rolf

En fait, j'avais l'habitude de vérifier window.parent et cela fonctionnait pour moi, mais dernièrement, window est un objet cyclique et a toujours une clé parente, iframe ou no iframe.

Comme les commentaires suggèrent difficile de comparer avec les travaux window.parent. Pas sûr que cela fonctionne si iframe est exactement la même page Web que le parent.

window === window.parent;
1
Jabran Saeed

Étant donné que vous posez la question dans le contexte d'une application facebook, vous pouvez envisager de le détecter sur le serveur lors de la demande initiale. Facebook transmettra un tas de données de chaîne de requête, y compris la clé fb_sig_user, si elle est appelée à partir d'un iframe.

Étant donné que vous devez probablement vérifier et utiliser ces données dans votre application, utilisez-les pour déterminer le contexte approprié à afficher.

1
HectorMac

Cela a fini par être la solution la plus simple pour moi.

    <p id="demofsdfsdfs"></p>

<script>

if(window.self !== window.top) {

//run this code if in an iframe
document.getElementById("demofsdfsdfs").innerHTML = "in frame";

}else{

//run code if not in an iframe
document.getElementById("demofsdfsdfs").innerHTML = "no frame";
}

</script>
0
Alex Roseland