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.
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.
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.
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.
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.
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;
J'utilise ceci:
var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);
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
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;
}
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;
É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.
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>