Here is my code on http://my-localhost.com/iframe-test.html
<html>
<head><title>Welcome Iframe Test</title></head>
<body>
<iframe src="http://www.my-website.com/index.html" width="500" height="500"></iframe>
<script type="text/javascript">
function alertMyMessage(msg){
alert(msg);
}
</script>
</body>
</html>
Here is code on http://www.my-website.com/index.html
<html>
<head></title>Welcome to my Server</title></head>
<body>
<h1>Welcome to My Server</ht>
Click Here
</body>
</html>
When i Click the "Click Here" Link. i got following Error.
Uncaught SecurityError: Blocked a frame with origin
"http://www.my-website.com" from accessing a frame with origin
"http://my-localhost.com". Protocols, domains, and ports must match.
Please Help me to Fix this Issue, or give some other solution for this.
You cannot access the DOM of a page loaded in a frame in a different origin. This is blocked for security reasons (imagine a random website you visited opening your web mail service in a hidden iframe and you can see why).
The closest you can come, and then only if you control both websites, is to pass messages between them using the web messaging api.
In one page, write a function to handle the messages and then add it as a message event listener.
function receiveMessage(event)
{
alert(event.data);
}
addEventListener("message", receiveMessage, false);
In the other, send the message:
parent.postMessage("This is a message", "*");
See MDN for more information
You can use postMessage!
PARENT
if (window.addEventListener) {
window.addEventListener ("message", receive, false);
}
else {
if (window.attachEvent) {
window.attachEvent("onmessage",receive, false);
}
}
function receive(event){
var data = event.data;
if(typeof(window[data.func]) == "function"){
window[data.func].call(null, data.params[0]);
}
}
function alertMyMessage(msg){
alert(msg);
}
IFRAME
function send(){
window.parent.window.postMessage(
{'func':'alertMyMessage','params':['Thanks for Helping me']},
'http://www.my-website.com'
);
}
REFERENCE
https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage
Related
This question already has answers here:
How do you use window.postMessage across domains?
(3 answers)
Closed 5 years ago.
I have a simple HTML5 page with an iframe whose src attribute is initially empty string. The page renders without any JavaScript errors.
The src attribute of iframe element is only set when the window has loaded, so initially an empty iframe loads. The iframe src is being set to a page from another domain.
The problem I am facing is that the postMessage method works without throwing any errors, however the source page is not firing the message event even though it's set up before the iframe page starts loading. I am having the alert messages from iframe page show up, which means the postMessage method did not throw any errors.
Question
What am I missing when subscribing to the message event in source page?
Source page
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Cross domain iframe messaging</title>
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
<script type="text/javascript">
var iframec = null;
window.addEventListener("load", function () {
iframec = document.getElementById("iframec");
//set up event listener for iframe object so it can receive message from page shown in iframe
iframec.contentWindow.addEventListener("message", function (event) {
alert("received: " + event.data);
}, false);
//load the iframe page but after you have set up to receive messages
iframec.src = "http://www.abcx.com";
});
</script>
</head>
<body>
<form id="form1">
<div>
<h1>Testing iframe messaging in a Cross Domain scenario</h1>
<p> Trying to send a message to an iframe that comes from a page in another domain. The postMessage method does not throw an error when called from the other domain page, but it's not being received by the page having iframe element in it.</p>
<div id="divComments"></div>
<iframe src="" id="iframec" name="iframec" style="border:none;margin:0;padding:0;width:100%; "></iframe>
</div>
</form>
</body>
</html>
Iframe Page JavaScript that is not throwing any error (i.e. page at http://www.abcx.com)
<script>
$( document ).ready(function() {
alert("loaded the iframe page on another domain. Just before postMessage");
window.postMessage("Some message was sent from other domain message", "*");
alert("loaded the iframe page on another domain. Just after postMessage");
});
</script>
You're hooking up the listener on the wrong window, and using the wrong window to send the message. (This is fairly easy to get wrong. :-) )
In the main window, you want to receive message events on the main window, not the iframe, so:
window.addEventListener("message", function (event) {
// ^^^^^^^
alert("received: " + event.data);
}, false);
In the iframe, you want to send to window.parent (well, parent), not window:
parent.postMessage("Some message was sent from other domain message", "*");
// ^^^^^^
With both of those changes, the message sent by the iframe is received by the main window.
I found a similar question here
On the page you're trying to load, it should be using top.postMessage or parent.postMessage
Additionally, you should be attaching the listener to the window, not the iframe (and make sure to filter the origin, or else localhost will throw you a false positive)
This is the version of yours I was playing with:
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
<script>
var iframec = null;
window.addEventListener("load", function () {
if(!iframec){
iframec = document.getElementById("iframec");
//set up event listener for iframe object so it can receive message from page shown in iframe
window.addEventListener("message", function (event) {
if(event.origin == '[your domain here]') alert("received from " + event.origin + ": " + event.data);
}, false);
//load the iframe page but after you have set up to receive messages
iframec.src = "[iframe target url]";
}
});
</script>
And the target for the iframe:
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
<script>
$( document ).ready(function() {
alert('loaded the page. Just before postMessage');
top.postMessage("Some message was sent from appsprocure", "*");
alert("loaded the page. Just after postMessage");
});
</script>
</head>
<body><h1>Hello!</h1></body>
</html>
I am trying to send a http request to a third party API through an iframe to overcome the issue with cross origin error "origin not found in access-control-allow-origin"
The third party API does not return Origin in the response header and they don't accept JSONP http request either so I am trying to implement this using iFrame.
I am testing simple html forms to see if it works. Below I have Parent and Child html. My web application owns both Parent and Child. The parent sends a message to child
using postMessage and then child makes a GET request to the specified url and tries to post the response to parent.
When I run this, I see the response in network tab from the third party but the browser is still preventing to send it to the iFrame (child.html). Can anyone point out what I am missing here?
I think I need to target the iFrame to be same domain as the third party.
Thank you for any advice.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>postMessage Demo: Parent</title>
<script type="text/javascript">
window.onload = function () {
var receiver = document.getElementById("ifrmChild").contentWindow;
var btn = document.getElementById('send');
function sendMessage(e) {
e.preventDefault();
receiver.postMessage('https://test.computing.com/my-pay/MyPay.do?UserID=8888&Amount=100&Name=Test', '*');
}
btn.addEventListener('click', sendMessage);
function ReceiveMessage(evt) {
alert(evt.data);
}
window.addEventListener("message", ReceiveMessage, false);
}
</script>
</head>
<body>
<iframe id="ifrmChild" src="receiver.html" frameborder="0" width="500" height="200">
</iframe>
<br />
<p>
<button id="send">Send Message</button>
</p>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Child</title>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript">
window.onload = function () {
var messageEle = document.getElementById('message');
function receiveMessage(evt) {
messageEle.innerHTML = "Message Received: " + evt.data;
$.ajax({
url: evt.data,
type: 'GET',
success: function (data, textStatus, jqXHR) {
console.log(data);
evt.source.postMessage(data, "*");
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(textStatus + " " + errorThrown);
evt.source.postMessage(textStatus, "*");
}
});
}
// Setup an event listener that calls receiveMessage() when the window
// receives a new MessageEvent.
window.addEventListener('message', receiveMessage);
}
</script>
</head>
<body style="background-color: gray;">
<h1>Receiver</h1>
<div id="message"></div>
</body>
</html>
This is a security feature in iFrames not to allow hijacking if the domain doesn't allow. this Stack Overflow answer gives a good explanation...
You need control over the domain you want to embed to remove/amend its
CORS policy. It the domain has explicitely blocked Cross-Origin
requests, there's nothing you can do about it.
This is used to avoid anyone hijacking any site you want (you could
have a full screen Google in an iframe running with your ads on top on
bettergoogle.com, things like that).
Edit:
To overcome this, either you have to host the webpage with the iframe in the third party domain. or you can request the third party domain owner to enable CORS for a specific domain address (your hosting domain).
Am hoping I haven't overlooked a solution here on SO, but I have been pulling my hair out trying to figure out what I am doing wrong and hoping somebody can see what it is. Here is the configuration:
I have a page that is served on DOMAIN1.COM. For the most part is is a form with a submit button and lots of jQuery. The form can be lengthy and so a user needs to scroll down the page to input form fields. The submit button is at the bottom of this form while the output results are at the top of the form. When the user clicks the submit button he/she cannot see the results because they are off of the top of the page. What I want to do is use jQuery scrollTo() to position to the top of the page once the submit button is clicked.
The problem is that the page above (and submit button) is within an iFrame on DOMAIN2.COM and so when the submit button is clicked I have a cross domain situation that I need to overcome.
I posted a question here, but my question wasn't really accurate. The thread evolved into helpful information and pointed me to a script that uses jQuery postMessage() to communicate cross domain, but I am having a problem implementing the proposed solution. Here's my code:
DOMAIN1.COM (child):
<html>
<head>
<!-- Load jquery -->
<script type="text/javascript" src="./jquery-2.0.3.min.js"></script>
<!-- Cross-domain scripting goodness (scroll to top) -->
<script type="text/javascript" src="./jquery.ba-postmessage.js"></script>
<script type="text/javascript">
// EVENT Handler - Form Submission
$(function () {
$("#btnSubmit").bind('click', function (event) {
// Get the parent page URL as it was passed in,
// for browsers that don't support window.postMessage
var parent_url = decodeURIComponent(document.location);
window.postMessage("scrollTop", parent_url, parent);
});
});
</script>
</head>
<body>
<form>
... Lots of form fields resulting in vertical height ...
<input type="submit" id="btnSubmit" value="Submit" />
</form>
</body>
</html>
DOMAIN2.COM (parent):
<html>
<head>
<!-- Load jquery -->
<script type="text/javascript" src="./jquery-2.0.3.min.js"></script>
<!-- Cross-domain scripting goodness (scroll to top) -->
<script type="text/javascript" src="./jquery.ba-postmessage.js"></script>
<script type="text/javascript">
// Cross-domain - scroll window to top
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
if (event.data == "scrollTop") {
window.scrollTo(0, 0);
}
}
</script>
</head>
<body>
<iframe src="http://domain1.com/index.html"></iframe>
</body>
</html>
Running both pages above on the same domain provides the desired results - clicking submit scrolls the page to the top.
Running on separate domains as documented and coded above, the page does not scroll to top, my output results fail, and jQuery outputs this error message in Firebug:
DataCloneError: The object could not be cloned.
If I change the code to leave out the parent parameter in the page on DOMAIN1.COM like:
var parent_url = decodeURIComponent(document.location);
window.postMessage("scrollTop", parent_url); //, parent);
Then nothing happens at all and no errors are output. It does not appear that receiveMessage() on DOMAIN2.COM gets called at all.
Can anyone see what I might be doing wrong that prevents this code from working cross domain?
I think it very late now but for others, it may work.
You are almost there; You need to use
window.postMessage("scrollTop","#domain of parent page exact page");
Instead of your code snippet:
window.postMessage("scrollTop", parent_url, parent);
If at the time the event is scheduled to be dispatched the scheme, hostname, or port of otherWindow's document does not match that provided in targetOrigin, the event will not be sent by Dom. Read documentation here
In Parent Page use following code snippet.
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
if (event.origin !== "#domain of iframe")
return;
if (event.data == "scrollTop"){
window.scrollTo(0,0);
}
}
I have two local .html files in the same folder. One page opens a window with the other page, and attempts to call a function in the newly opened window. However, the function call fails, and I get this in the console:
Unsafe JavaScript attempt to access frame with URL file:///***/A.html from frame with URL file:///***/B.html. Domains, protocols and ports must match.
This happens on both Chrome and Webkit (Mac). Is there any way I can either: disable the cross-domain checks for the file:// protocol, or call a javascript function in a different local file?
You can use window.postMessage to do something like this:
The initial window html file:
<!DOCTYPE html>
<html>
<head>
<script>
var otherWindow;
function openOther() {
otherWindow = window.open("other.html", "otherWindow");
}
function otherFunc() {
otherWindow.postMessage("otherFunc", "*");
}
</script>
</head>
<body>
<div onclick="openOther()">Open the other window</div>
<div onclick="otherFunc()">Call the other window's function</div>
</body>
</html>
Html for the second window:
<!DOCTYPE html>
<html>
<head>
<script>
window.addEventListener("message", function(event) {
alert("The other window's function executed.");
}, false);
</script>
</head>
<body>
<div>This is the other window.</div>
</body>
</html>
Here's a good reference for window.postMessage.
I have a situation where I have web apps on two different servers, where App1 contains App2 in an IFrame. Any links in App2 can have target="_parent" attribute, which allow those links to open in the top window. However, I can't find any way to get the same behavior in Javascript. I found this page, which claims that the child frame can call javascript on the parent frame using parent.foo(), but that doesn't seem to work in IE8 or FF3.5. I found this SO question which explains how this security model works. But it seems odd that I can't do in Javascript what I can do with a simple <a> tag. Is there any workaround to this at all? I know about window.postMessage, but (as far as I know) this only works in Firefox.
Example
server1/test.html
<html>
<head>
<script type="text/javascript">
function myCallback(foo) {
alert(foo);
}
</script>
</head>
<body>
<iframe src="http://server2/test2.htm" width="400" height="150"></iframe>
</body></html>
server2/test2.html
<html><body>
<script>
function clickit() {
parent.document.location = "http://www.google.com"; //not allowed
parent.myCallback("http://www.google.com"); //not allowed
}
</script>
<p>This should be in an iFrame!</p>
<p>normal link (works)</p>
<p>javascript link</p>
</body></html>
OK I did more investigation, and it appears that postMessage works in all modern browsers, even IE (with the caveat that IE has a slightly different way of doing it). Here's how I got it to work (tested on WinXP in IE8, FF3.5, Chrome 3.0, Safari 4 beta, Opera 9.64):
server1/test.html
<html>
<head>
<script type="text/javascript">
if(navigator.appName == "Microsoft Internet Explorer")
window.attachEvent("onmessage", receiveMessage);
else
window.addEventListener("message", receiveMessage, false);
function receiveMessage(e) {
if(e.origin == "http://server2") //important for security
if(e.data.indexOf('redirect:') == 0)
document.location = e.data.substr(9);
}
</script>
</head>
<body>
<iframe src="http://server2/test2.htm" width="400" height="150"></iframe>
</body>
</html>
server2/test2.htm
<html><body>
<script>
function clickit() {
parent.postMessage('redirect:http://www.google.com', 'http://server1');
}
</script>
<p>This should be in an iFrame!</p>
<p>normal link</p>
<p>javascript link</p>
</body></html>
A simple thing you can do is:
execute following from JavaScript code of iframe page
top.location = "https://www.google.co.in/";
this will change the location of window's URL to https://www.google.co.in/.
One more thing -This strategy can also be useful when you do not want that any one can inframe your site
just write the above code in document ready part.
No, and for good reason. If you need this, then you must run all communication through one of the two servers; for example, have server1 act as as a proxy for all requests for "server2/test2.html".
If both parent and iframe are on subdomains under the same domain, you may be able to do something with the document.domain property. If both body and iframe are treated as being from the same origin, changing the location should be possible; I haven't tried this myself. Some reading here
If the frames are on the same domain, you should be able to access the parent frame. Otherwise no, it's a security issue.
The only workaround that springs to mind would be to use AJAX to update a file on each of the servers, then check the contents of the opposite file server-side. You could do the same thing using a single database, if you allow connections from external domains.
This is all kind of overkill though, when you could simply pop-up a link in the frame and tell users to click it to continue.