There is a webpage i am making a greasmonkey script for. This page has several iframes. I have found out that they are the problem, however i do not know how to solve the issue.
At first my script creates a small div box with the button. By pressing a button script analyzes webpage contents and calls alert on certain conditions.
Javascript console in Firefox already shouts to me that access was denied for document because my script is using document.getElementByID to find the top document's body, where the div box is being appended to.
This is easily avoidable problem as then script fails and gets stuck in iframes, yet it still continues on the main page as it does give the access to document.
The problem araises when i try to use alert in my function. Seems like iframes take over my script and kills it with the Permission denied to access property 'alert'.
How do i tell browser/script or whatever, that i only want my script to run on main document and i do not want to be bothered by iframes?I installed NO-script addon, allowed the primary domain and blocked the secondary domain (that loads inside iframes) and all the alert messages go normal. But, i can't ask my users to install noscript enable/disable specific domains and my script should be working fine. I need to find solution which would work with all the iframes enabled.
Hope it didn't sound confusing.
Thank you for any help.
RE:
How do i tell browser/script or whatever, that i only want my script to run on main document and i do not want to be bothered by iframes?I installed NO-script addon, allowed the primary domain and blocked the secondary domain (that loads inside iframes) and all the alert messages go normal.
First, adjust your include and exclude directives to ignore the iframes as much as possible. EG:
// #include http://example.com/normal/*
// #include http://example.com/extra/*
// #exclude http://example.com/extra/in_iframe/*
Next, add these 2 lines as the first lines of code after the Metadata Block:
if (window.top != window.self) //-- Don't run on frames or iframes
return;
That will stop the GM script from running on iframes.
Related
I am writing a script that has to enter an iframe in order to interact with certain inputs. In this case, the inputs are credit card related.
In Chrome head mode, the script runs perfectly fine. In Chrome headless mode, I always get this error: "Content of the iframe in which the test is currently operating did not load.".
I haven't had this problem in other scripts, so I'm assuming it's because these fields are credit card (payment) related, but I'm not finding anything online that confirm my suspisions.
Can anyone confirm or provide insight and is there a workaround (without changing elements)?
Thank you,
Is the iframe content ready at this moment? You can check it by making a screenshot of the whole page via the await t.takeScreenshot() command or the takeOnFails option. If the iframe content on the screenshot looks fine and the cause of the error is unclear, try one of the following workarounds:
add some waiting timeouts: await t.wait(timeout)
implement a ClientFunction that will check if the iframe content is ready. Here is an example of this approach: https://stackoverflow.com/a/10444444
I have an ad that displays within an iframe on a given publisher site around every 1000 loads or so. I have no control over the host site but I need a way to see the ad live as users will see it. I'm trying to figure out a javascript solution that will load the page, search for the name of my company to see if my ad loaded (the company name is the id of a div tag that loads the iframe) and then either stop there if it finds it, or reload the page if not.
I had it sort of working by running a script in the console that got the innerHTML of the document body, searched for a keyword and then reloaded the page if the keyword wasn't found.
Two problems though.
It could only find keywords outside of the iframe.
It didn't search the content of the iframe (where the actual keyword that would identify my particular ad sits) even if I set a delay or did onload.
Secondly, for every page refresh, the script would be cleared from the console.
I know this is beginner stuff but I would love any pointers to the correct way to tackle this problem.
Thanks so much for the help thus far (also, I upvoted everyone but don't think I have the necessary cred for it to show up publicly)
Here's where I got. I created a chrome plugin with the following manifest.json:
{
"manifest_version": 2,
"name": "Ad Refresh",
"version": "1.0",
"permissions": [
"activeTab",
"tabs"
],
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["jquery.min.js", "contentscript.js"],
"all_frames": true
}
]
}
I have the content-scripts running on all urls but will restrict it once I get things running properly.
For contentscript.js that gets injected and runs in each frame, I have:
setTimeout(function(){
$("[title='3rd party ad content']").attr("id", "dfp"); // "3rd party ad content" is the title of all iframes that could potentially contain my ad and is the only identifying attribute across all iframe instances. I stick an id on there so it's easier to grab with getElementById. It only gets the first instance though, need to figure out how to loop through all.
var company = document.getElementById('dfp');
if (company == null) {
console.log("no hit");
} else {
console.log(company);
}
}, 5000);
I'm not worried about reloading the page, I'm just stuck on getting access within the iframe.
I am unable to directly grab any element within the actual content of the iframe with jquery $ or getElementById etc. However, if I run getElementId on the iframe itself and console.log it, it includes all the HTML inside the iframe:
http://i.stack.imgur.com/dfuYt.png
I tried getting the innerHTML of the iframe element so that I'd have it as a string and could search for it, but all it returns is the iframe element tags, none of the inner content. I don't know if any of that makes sense but I appear to be over my head at this point.
Ok, last addition. My ad runs a script that I can see under "Sources" in inspector. So I thought "Why not run
var scripts = document.getElementsByTagName('script'); to get an array of all the scripts that were loaded on the page? Then I could just search the array to see if my script and hence my ad had loaded and we'd be golden." Unfortunately though, it doesn't include my script in the array, even when it's loaded and is visible in "Sources" and accurately includes a random Stripe script that's also loading from within an iframe. Bummer...
Use .load event of the jQuery to know whether iFrame is loaded and then read the innerHTML of the iframe body
Try this:
$('#ID_OF_THE_IFRAME').load(function() {
var iFrameContent = $('body', this.contentWindow.document).html();
console.log(iFrameContent);
});
Fiddle
JS:
var company = document.getElementById('myframe1').contentWindow.document.getElementById('company');
if (company == null) {
//reload
console.log("reload");
} else {
//continue
console.log(company);
}
It sounds like the iframe containing the ad is loaded from a different domain than the main page, is that right? That would explain why your JavaScript code running in the main page (or in the console, same thing) can't access DOM elements inside the iframe. Browser cross-domain security prevents that kind of access: the iframe is treated just like a separate browser window or tab.
If the main page and the iframe were both loaded from the same domain, then you could use contentWindow as a couple of answers have described. But that won't work across domains.
So, what can you do?
You're building a tool for your own use or the use of your colleagues - not something you need to publish on a website for the rest of the world to use, right?
This gives you a couple of other options. First, you could simply disable cross-domain browser security. In Chrome, you can do that as described here:
Disable same origin policy in Chrome
Beware: Don't do any "normal" browsing in a Chrome session running in this mode, only your special testing. But if you do run Chrome in this mode, then you'll be able to access iframe DOM elements via contentWindow and contentWindow.document as described in the other answers.
If that doesn't do the trick, or if you don't want to have to start a special Chrome session for this, another approach would be to write a Chrome extension. This would allow you to write code to access DOM elements in both the iframe and the main window using techniques like these:
access iframe content from a chrome's extension content script
Chrome extension to remove DOM elements inside iframes
Or you could write a Firefox extension if you prefer - similar capabilities are available in both.
Recently I came across a website that sells adds ( http://buysellads.com/ ) on a friends computer with Adblock enabled and the site seems to detect the browser add-on and it disables the CSS and JS.
I have been trying to read their code, but I can not seem to find the line that makes this happen. I know there are ways to detect and give the user a message to disable the plugin, but I find this way to be more clever.
I appreciate if somebody knows or finds the code that triggers and executes.
Bonus question: How would this work with a cache plugin like W3 Total Cache for Wordpress? I make this question because I wonder how the website would look after the person whitelisted the page and the site refreshes. In theory it should display the CSS and JS because Adblock is not found, but I am not sure if cache plugins would break that and display the site as it looked before without any CSS or JS.
Thanks in advance.
I don't know how this particular site does it, but one possibility is to add/load the JS and CSS files via an ad serving system that is blocked by Adblock (load the style and script tags in an ad placement).
Depending on how Adblock works, it could be enough to host the files on a subdomain like ads.your-domain.com or banner.your-domain.com.
You could then set display=none with inline style on a wrapper containing the whole page, and display=block on an element outside the wrapper, containing the message to the user. The CSS file loaded via an ad serving system could then change the display properties of the two elements (so the users without Adblock gets the content of the page and not the message).
I can't seem to reload the parent page from within an iframe even though the domain for my iframe and the parent page appear to be the same. The IFRAME was created dynamically, rather than in the HTML page source, so could that be the problem?
The iframe I'm working with is here http://www.avaline.com/ R3000_3 once you log in.
You may use user:test2#gmail.com
pass: test03
Once logged in, hit the "order sample" button, and then hit "here" where it says "Your Third Party Shipper Numbers (To enter one, click here.)".
I tried using javascript statements window.top.location.reload(),window.parent.location.reload(),window.parent.location.href=window.parent.location.href but none of those worked in FF 3.6 so I didn't move on to the other browsers although I am shooting for a cross-browser solution.
I put the one-line javascript statements inside setTimeout("statement",2000) so people could read the content of the iframe before the redirect happens, but that shouldn't affect the execution of the statements...
I wish I could test and debug the statements with the Firebug console from within the Iframe.
Your script tag is:
<script type="test/javascript">
That might be the problem :-)
If changing that to "text/javascript" doesn't fix the issue, try changing the query string slightly:
window.top.location.search = window.top.location.search + '&dc=' + (new Date).getTime();
This is a very urgent problem and I'd be forever indebted to anyone who can lend some insight.
I'm going to be deploying a widget (called the "ISM") to a third-party site. That site uses the document.domain JavaScript property to relax cross-domain restrictions (e.g., setting document.domain in "a.example.com" and "b.example.com" to both "example.com" so they can access each other's DOMs).
This causes problems with my script in Internet Explorer due to the way that I construct an <iframe> that is used to display my widget's HTML content. In Internet Explorer, using document.domain on a page, and then creating an <iframe> with JavaScript, will cause you to be immediately "locked out" of the <iframe> - i.e., you can create it, but it's not created in the correct document.domain, so you're not able to access its DOM due to security restrictions. This isn't a problem in any other browser.
To see what I'm talking about, load this page in IE:
http://troy.onespot.com/static/3263/stage1.html
You should see a JavaScript error: "Access is denied."
To get around this, I'm setting the dynamically created <iframe>'s "src" attribute to load a static HTML file that's hosted in the same domain (different subdomain), and setting its document.domain property to the appropriate value:
http://troy.onespot.com/static/3263/stage2.html
That gets around the security issue, and lets me write the document I originally wanted to write to the <iframe>:
http://troy.onespot.com/static/3263/stage3.html
With that document in place, my widget does some polling to our server to get some HTML content that I want to insert into another <iframe>, which will be visible to visitors of the parent page. I've roughly simulated that here (using static content, not actually contacting our server):
http://troy.onespot.com/static/3263/stage4.html
Here comes the problem. When I get that HTML content and insert it into the second <iframe>, I now face an unusual issue with a broken "Back" button. This happens in Firefox 3.0 and all version of IE (possibly other browsers), though it does not happen in some browsers I've tested (Firefox 3.5, Safari, Chrome). See this page:
http://troy.onespot.com/static/3263/stage5.html
If you click the "Google" link, all seems fine. But, when navigating back to the previous page (that has the latter test script), another JavaScript error is introduced: "Permission denied." This does not terminate the script, and does not appear to have any ill effects, other than the fact that I assume it's connected to the broken "Back" button functionality, which is a very big problem - the one I'm desperately trying to solve. I'm at a loss to debug this error since its call stack starts and stops in the jQuery script.
You can also encounter this error - with more serious symptoms - by going to the last link above (stage5.html - clear your browser cache first). Click the "Stage 5 (Again)" link, then, after that page has loaded, click the "Back" button.
The "Back" button is completely broken! You can't go anywhere except to another URL.
This is the problem that I need to solve as soon as possible. Any insights or help would be extremely appreciated!
I can't deviate from this method too much, so outside-the-box suggestions are definitely welcome, but I may not be able to use them due to the constraints of the widget's specifications. I would prefer to understand why the "Back" button is breaking and how to fix it, along with the "Permission denied" error related to jQuery.
It's really hard to try out fixes for this because of the multiple domains. One thing I've heard is that IE treats a blank src or "about:blank" as a different domain, but it treats 'javascript:""' as the same domain. Have you experimented with changing stage one to set the iframe src to things like:
iframe.src = 'javascript:""'
Or:
iframe.src = 'javascript:parent.getFrameHTML()'
Part of the problem seems to be that IE (at least IE 7) adds two entries to the history named "Domain" when I click on the "Stage 5 Again" link. When you use the little drop-down arrow next to the Back button you'll see the history of pages allowing you to step back more than one step. I see the previous two entries are listed as "Domain" and clicking either of those brings me to the same page. The fourth spot (after Current Page, Domain, Domain) is the correct "ISM Back Button" link to the original stage5.html page.
So the problem isn't exactly that the back button doesn't work, but just that the entries in the history are added and so the back button takes you to the wrong place. I don't have an answer as to why those "Domain" entries are being added to the history, but hopefully this helps point you in a useful direction.
Good luck!