Same-origin policy error - html

I'd like to learn about Same-origin policy. There is a site talking about it. But there have to be sth. wrong with the first example because i got an error Illegal document.domain value
Here is the problematic code:
The parent site located at http://www.qnimate.com/parent.html:
<iframe src="http://www.blog.qnimate.com/child.html" id="myIFrame"></iframe>
<script>
window.document.domain = "www.qnimate.com";//you also need to set the parent's document.domain variable
window.document.getElementById("myIFrame").contentWindow.document.body.style.backgroundColor = "red";//this access is allowed by default
</script>
and iframe located at http://www.blog.qnimate.com/child.html:
<script>
window.document.domain = "www.qnimate.com"; //if we remove this line then the below line will not work and throw a same origin policy exception.
window.parent.document.body.style.backgroundColor = "blue";
</script>

You can only set document.domain to a superdomain of the current domain. You can remove components from the left-hand end.
The current domain is www.blog.qnimate.com so it can be set to blog.qnimate.com or qnimate.com.
You can't remove components in the middle, so you can't have www.qnimate.com.
To communicate across different origins through an iframe, use postMessage as described in this question.

Related

CSS conflict when using iFrame [duplicate]

Is it possible to change styles of a div that resides inside an iframe on the page using CSS only?
You need JavaScript. It is the same as doing it in the parent page, except you must prefix your JavaScript command with the name of the iframe.
Remember, the same origin policy applies, so you can only do this to an iframe element which is coming from your own server.
I use the Prototype framework to make it easier:
frame1.$('mydiv').style.border = '1px solid #000000'
or
frame1.$('mydiv').addClassName('withborder')
In short no.
You can not apply CSS to HTML that is loaded in an iframe, unless you have control over the page loaded in the iframe due to cross-domain resource restrictions.
Yes. Take a look at this other thread for details:
How to apply CSS to iframe?
const cssLink = document.createElement("link");
cssLink.href = "style.css";
cssLink.rel = "stylesheet";
cssLink.type = "text/css";
frames['frame1'].contentWindow.document.body.appendChild(cssLink);
// ^frame1 is the #id of the iframe: <iframe id="frame1">
You can retrieve the contents of an iframe first and then use jQuery selectors against them as usual.
$("#iframe-id").contents().find("img").attr("style","width:100%;height:100%")
$("#iframe-id").contents().find("img").addClass("fancy-zoom")
$("#iframe-id").contents().find("img").onclick(function(){ zoomit($(this)); });
Good Luck!
The quick answer is: No, sorry.
It's not possible using just CSS. You basically need to have control over the iframe content in order to style it. There are methods using javascript or your web language of choice (which I've read a little about, but am not to familiar with myself) to insert some needed styles dynamically, but you would need direct control over the iframe content, which it sounds like you do not have.
Use Jquery and wait till the source is loaded,
This is how I have achieved(Used angular interval, you can use javascript setInterval method):
var addCssToIframe = function() {
if ($('#myIframe').contents().find("head") != undefined) {
$('#myIframe')
.contents()
.find("head")
.append(
'<link rel="stylesheet" href="app/css/iframe.css" type="text/css" />');
$interval.cancel(addCssInterval);
}
};
var addCssInterval = $interval(addCssToIframe, 500, 0, false);
Combining the different solutions, this is what worked for me.
$(document).ready(function () {
$('iframe').on('load', function() {
$("iframe").contents().find("#back-link").css("display", "none");
});
});
Apparently it can be done via jQuery:
$('iframe').load( function() {
$('iframe').contents().find("head")
.append($("<style type='text/css'> .my-class{display:none;} </style>"));
});
https://stackoverflow.com/a/13959836/1625795
probably not the way you are thinking. the iframe would have to <link> in the css file too. AND you can't do it even with javascript if it's on a different domain.
Not possible from client side . A javascript error will be raised "Error: Permission denied to access property "document"" since the Iframe is not part of your domaine.
The only solution is to fetch the page from the server side code and change the needed CSS.
A sort of hack-ish way of doing things is like Eugene said. I ended up following his code and linking to my custom Css for the page. The problem for me was that, With a twitter timeline you have to do some sidestepping of twitter to override their code a smidgen. Now we have a rolling timeline with our css to it, I.E. Larger font, proper line height and making the scrollbar hidden for heights larger than their limits.
var c = document.createElement('link');
setTimeout(frames[0].document.body.appendChild(c),500); // Mileage varies by connection. Bump 500 a bit higher if necessary
Just add this and all works well:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
If the iframe comes from another server, you will have CORS ERRORS like:
Uncaught DOMException: Blocked a frame with origin "https://your-site.com" from accessing a cross-origin frame.
Only in the case you have control of both pages, you can use https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage to safely send messages like this:
On you main site(one that loads the iframe):
const iframe = document.querySelector('#frame-id');
iframe.contentWindow.postMessage(/*any variable or object here*/, 'https://iframe-site.example.com');
on the iframe site:
// Called sometime after postMessage is called
window.addEventListener("message", (event) => {
// Do we trust the sender of this message?
if (event.origin !== "http://your-main-site.com")
return;
...
...
});
Yes, it's possible although cumbersome. You would need to print/echo the HTML of the page into the body of your page then apply a CSS rule change function. Using the same examples given above, you would essentially be using a parsing method of finding the divs in the page, and then applying the CSS to it and then reprinting/echoing it out to the end user. I don't need this so I don't want to code that function into every item in the CSS of another webpage just to aphtply.
References:
Printing content of IFRAME
Accessing and printing HTML source code using PHP or JavaScript
http://www.w3schools.com/js/js_htmldom_html.asp
http://www.w3schools.com/js/js_htmldom_css.asp

How do I allow CORS requests on mediawiki?

I tried adding $wgCrossSiteAJAXdomains = array( '*' ); to LocalSettings.php, but didn't work.
I am trying to add content created by an external server. The snippet below shows how I want to show the value of a parameter (I am planning to serve more complex content that I can only build on the external server.)
I added the following code to MediaWiki:Common.js:
$.each($('.from-outside'),
function(index, element) {
element = $(element);
paramName = element.attr('param-name');
console.log('Loading ' + paramName + '...');
element.load('http://outside.domain/get_value/' + encodeURIComponent(paramName));
});
Then the following content on a template:
<html>
<div class="from-outside" param-name="param one"><i>Loading...</i></div>
</html>
I tried adding $wgCrossSiteAJAXdomains = array( '*' ); to LocalSettings.php
Please don't. That's like disabling password checks on login.
Assuming you put something more reasonable in there, this is the right way to allow CORS. Given that the rest of your question does not seem to be related to enabling CORS, it's hard to tell what's not working. (Are you maybe misunderstanding in which direction CORS works? If a script on your wiki makes a request to outside.domain, it is outside.domain that needs to allow CORS.)

iframe with srcdoc: same-page links load the parent page in the frame

Same-page links work by referencing another element that has id="sec-id" on the same page, using
for instance. A link like this is relative.
However, if I use that very same syntax in the iframe in my LaTeX.js playground, it will not just scroll to the destination element, but (re)load the whole playground page inside the ifame. (Note that I set the contents of the iframe programmatically with iframe.srcdoc = html)
Example: LaTeX.js playground, right at the end of the first section click on the link in "See also SecĀ­tion 11." in the iframe on the right side.
What could be the reason?
UPDATE: I now understand the source of the problem: the browser uses the document's base URL to make all relative URLs absolute (see <base>). The trouble starts with an iframe that has its content set with srcdoc: no unique base URL is specified, and in that case the base URL of the parent frame/document is used--the playground in my case (see the HTML Standard).
Therefore, the question becomes: is there a way to reference the srcdoc iframe in a base URL? or is it possible to make the browser not prepend the base? or to make a base URL that doesn't change the relative #sec-id URLs?
I don't know exactly how you could resolve this, I think it is because the srcdoc, you can't use the src with the content-type because the character limit, but you can convert it to a Blob and it kinda works, the style are lost though. Maybe you can use it as a starting point, based on your page:
// Get the document content
const doc = document.querySelector('iframe').srcdoc;
// Convert it to blob
const blob = new Blob([doc], {type : 'text/html'});
// Load the blob on the src attr
document.querySelector('iframe').src = URL.createObjectURL(blob);
// Remove srcdoc to allow src
document.querySelector('iframe').removeAttribute('srcdoc');
What about catching the event and scrolling to the desired anchor?
$("a").click(function(e) {
$('.iframe').animate({
scrollTop: $(e.target.attr('href')).offset().top
}, 2000);
return false;
});
For the record, it seems that my question is not possible, i.e., it is not possible to use relative same-page links in an iframe that has its content set using srcdoc. A workaround has to be used, see the other answer.

Changing content of iframe dynamicallly

I have a bit different task to do,
first, i have add an iframe tag dynamically, which i was able to do easily using the code->
function getFrame()
{
var iframeTA = document.createElement("IFRAME");
iframeTA.setAttribute("src", "iframeTakeAction.html");
iframeTA.style.width = "200px";
iframeTA.style.height = "200px";
document.getElementById("status").appendChild(iframeTA);
}
now, want i want to do is to access the elements of iframeTA (i.e. elements within the body tag of 'iframeTakeAction.html' which is the source of iframeTA),
something like this ->
iframeTA.body.getSomeElement......
Hope this kind of operation is possible, if so please put some light.
Thanks.
You should be able to access it with:
document.getElementById("TOUR IFRAME ID")
However, this only holds as long as your iframe src is a relative path on the same domain. If you change the domain then your browser will prevent you to do this.

<iframe> - How to show the whole height of referenced page?

I have an application that I would like to embed inside our companies CMS. The only way to do that (I am told), is to load it in an <iframe>.
Easy: just set height and width to 100%! Except, it doesn't work.
I did find out about setting frameborder to 0, so it at least looks like part of the site, but I'd prefer not to have an ugly scrollbar inside a page that allready has one.
Do you know of any tricks to do this?
EDIT: I think I need to clarify my question somewhat:
the company CMS displays the fluff and stuff for our whole website
most pages created through the CMS
my application isn't, but they will let me embedd it in an <iframe>
I have no control over the iframe, so any solution must work from the referenced page (according to the src attribute of the iframe tag)
the CMS displays a footer, so setting the height to 1 million pixels is not a good idea
Can I access the parent pages DOM from the referenced page? This might help, but I can see some people might not want this to be possible...
This technique seems to work (gleaned from several sources, but inspired by the link from the accepted answer:
In parent document:
<iframe id="MyIFRAME" name="MyIFRAME"
src="http://localhost/child.html"
scrolling="auto" width="100%" frameborder="0">
no iframes supported...
</iframe>
In child:
<!-- ... -->
<body>
<script type="text/javascript">
function resizeIframe() {
var docHeight;
if (typeof document.height != 'undefined') {
docHeight = document.height;
}
else if (document.compatMode && document.compatMode != 'BackCompat') {
docHeight = document.documentElement.scrollHeight;
}
else if (document.body
&& typeof document.body.scrollHeight != 'undefined') {
docHeight = document.body.scrollHeight;
}
// magic number: suppress generation of scrollbars...
docHeight += 20;
parent.document.getElementById('MyIFRAME').style.height = docHeight + "px";
}
parent.document.getElementById('MyIFRAME').onload = resizeIframe;
parent.window.onresize = resizeIframe;
</script>
</body>
BTW: This will only work if parent and child are in the same domain due to a restriction in JavaScript for security reasons...
You could either just use a scripting language to include the page into the parent page, other wise, you might want to try one of these javascript methods:
http://brondsema.net/blog/index.php/2007/06/06/100_height_iframe
http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_22840093.html
Provided that your iframe is hosted on the same server as the containing page, you can access it via javascript.
There are a number of suggested methods for setting the iframe to the full height of the contents, each with varying degrees of success - a google for this problem shows that it's quite a common one, with no real, one-size-fits-all consensus solution i'm afraid!
Several people have reported that this script does the trick, but may need some modification for your specific case (again, assuming your iframe and parent page are on the same domain).
I might be missing something here, but adding scrolling=no as an attribute to the iframe tag normally gets rid of the scrollbars.