I am building a bookmarklet for various sites that functions basically like this:
User navigates to foo.com (an external site not on my control)
User clicks a bookmarklet on his browsers that grabs some information from foo.com and displays it on a form in bar.com inside an iframe
User submits the form inside bar.com which is inside foo.com
The iframe dissapears
The problem is getting the iFrame to remove itself. Since I can't access a function inside a parent domain in another domain I cannot create a custom function parent.removeIFrame() or even do a window.top.location.reload(). I tried many techniques but all of them fail because of cross domain scriptings.
The way I solved it was to change the top.location.href to a custom page I built at bar.com/back.html in which all it does is simply to send a single "history.back()" command that bounces the user on the original page. Althought creative, I don't think it's very elegant solution. Is there a better way?
You can try fragment identifier for cross domain messaging. There is a YUI library for it: http://www.julienlecomte.net/blog/2007/11/31/
When you injected the JS code to create the form on the site's page you can have it poll (js outside of the newly created iframe) your server to know when to remove the iframe. You can use all kinds of methods of doing this including jsonp, long polling, post message, fragment identifiers, etc. You do not need to load a big library for this - the smaller the better for bookmarklets.
Related
I'm designing some "add-on" to certain websites, which should be embedded in them as an iframe. Inside this iframe there is a clickable button aimed at changing the iframe's position within the parent website.
Since things are done in coordination with the parent website, I am able to add some code there as well. However it seems I am not able to do neither of the following (one of them should suffice):
From the iframe, access data within the parent.document, in order to move the iframe to the desired position.
From the parent website, access data within the iframe, in order to check when the button is clicked.
Both typically produce an error: "Blocked a frame with origin XXX from accessing a frame with origin YYY. Protocols, domains, and ports must match".
Any advice (preferably with code sample) is appreciated.
After doing lots of searching around, I came across this:
http://www.codeproject.com/Tips/585663/Communication-with-Cross-Domain-IFrame-A-Cross-Bro
I actually tested the method (using my own short piece of code) and it seemed to work on Chrome, Firefox and IE. Now I'm gonna try the "real" implementation...
From what I understand based on the information you've provided in your question, cross domain scripting is not possible. What you would need to do is provide a script that the parent-level website can paste into their template/html and run from their domain, similar to how Google does with their analytics system.
As an alternative, try turning your iframe content instead, into a div loaded with the response from a service call made from the parent domain to the iframe domain. You would most likely need to create an API that a requesting site can use. Simply call that URI with whatever parameters you would use when referencing the page you wanted to load in the iframe, and have the script that you run on the parent website handle all the DOM alterations you want to achieve.
I want know if you can guide to users for a series of steps that imply visit different web pages using actions inside a Bookmarklet. What I want is a kind of Wizard or automated actions cross web pages.
Afraid not. What you're describing would actually be very dangerous. If there were any malicious code in the bookmarklet, it would have access to every site you are logged into, email, amazon etc. Some pseudocode for an attack could look like this:
window.location = "www.gmail.com";
ajax.post("www.gmail.com/deleteAllMail");
window.location = "www.amazon.com";
ajax.post("www.amazon.com/buyReallyExpensiveStuff");
You partially can, if you open the new pages inside an iframe. However, you won't be able to modifying the content of the webpages anymore, but just modifying the url of the iframe, and going through different websites (like a kind of slideshow).
Notice that if you're the owner of the pages, you can use postMessage to interact with them, even if they're in different domains.
Or, you could do a "tunneling" on server side, and inject each team you got the page back with the JS you need.
But probably the cleanest approach if you're not the owner of the pages is just create a simple restartless add-on for the browsers you want to support.
I'm working on a site that allows administrators to upload arbitrary SWFs and embed them on the page. Administrators are in theory trusted, but I still want to protect against potentially malicious administrators or misguided administrators from harming the site.
A part of the functionality of the site is that the SWFs can communicate to the containing browser page when it's finished and for the page to react.
Now, I can think of two ways to do this:
Use ExternalInterface.addCallback to create a global callback named something like isComplete that does logic and returns true or false depending on whether the Flash app is in a completed state. Then, just do something like setTimeout to just call that function repeatedly. I don't think this would require me to open up allowscriptaccess to the movie.
Embed the movie with allowscriptaccess and have the movie call something like ExternalInterface.call('done') when it's finished. This option seems like it requires me to open up allowscriptaccess, which is a potential threat since I can't control the SWFs that would be embedded with this directive.
Is there a solution I'm missing that doesn't involve doing the infinite loop and also doesn't require me to open up a security risk?
Instead of embedding your SWFs directly in the main page, embed them in a separate page that's hosted on a subdomain (or some other domain). Then, display that subpage via an <iframe> in your main page. This way, you'll have a cross-domain <iframe>. Go ahead and give the SWF allowscriptaccess permissions. Then, communicate via postMessage (or a cross-browser simulation script) with the iframe. This way, the SWF can do anything they want to the page, but there's only one controlled "tunnel" to the main page.
I'm just looking for clarification on this.
Say I have a small web form, a 'widget' if you will, that gets data, does some client side verification on it or other AJAX-y nonsense, and on clicking a button would direct to another page.
If I wanted this to be an 'embeddable' component, so other people could stick this on their sites, am I limited to basically encapsulating it within an iframe?
And are there any limitations on what I can and can't do in that iframe?
For example, the button that would take you to another page - this would load the content in the iframe? So it would need to exist outwith the iframe?
And finally, if the button the user clicked were to take them to an https page to verify credit-card details, are there any specific security no-nos that would stop this happening?
EDIT: For an example of what I'm on about, think about embedding either googlemaps or multimap on a page.
EDIT EDIT: Okay, I think I get it.
There are Two ways.
One - embed in an IFrame, but this is limited.
Two - create a Javascript API, and ask the consumer to link to this. But this is a lot more complex for both the consumer and the creator.
Have I got that right?
Thanks
Duncan
There's plus points for both methods. I for one, wouldn't use another person's Javascript on my page unless I was absolutely certain I could trust the source. It's not hard to make a malicious script that submits the values of all input boxes on a page. If you don't need access to the contents of the page, then using an iframe would be the best option.
Buttons and links can be "told" to navigate the top or parent frame using the target attribute, like so:
This is a link
<form action="http://some.url/with/a/page" target="_parent"><button type="submit">This is a button</button></form>
In this situation, since you're navigating away from the hosting page, the same-origin-policy wouldn't apply.
In similar situations, widgets are generally iframes placed on your page. iGoogle and Windows Live Gadgets (to my knowlege) are hosted in iframes, and for very good reason - security.
If you are using AJAX I assume you have a server written in C# or Java or some OO language.
It doesn't really matter what language only the syntax will vary.
Either way I would advise against the iFrame methods.
It will open up way way too many holes or problems like Http with Https (or vice-versa) in an iFrame will show a mixed content warning.
So what do you do?
Do a server-side call to the remote site
Parse the response appropriately on the server
Return via AJAX what you need
Display returned content to the user
You know how to do the AJAX just add a server-side call to the remote site.
Java:
URL url = new URL("http://www.WEBSITE.com");
URLConnection conn = url.openConnection();
or
C#:
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://www.WEBSITE.com");
WebResponse res = req.GetResponse();
I think you want to get away from using inline frames if possible. Although they are sometimes useful, they can cause issues with navigation and bookmarking. Generally, if you can do it some other way than an iframe, that is the better method.
Given that you make an AJAX reference, a Javascript pointer would probably be the best bet i.e. embed what you need to do in script tags. Note that this is how Google embed things such as Google Analytics and Google Ads. It also has the benefit of also being pullable from a url hosted by you, thus you can update the code and 'voila' it is active in all the web pages that use this. (Google usually use version numbers as well so they don't switch everyone when they make changes).
Re the credit card scenario, Javascript is bound by the 'same origin policy'. For a clarification, see http://en.wikipedia.org/wiki/Same_origin_policy
Added: Google Maps works in the same way and with some caveats such as a user/site key that explicitly identify who is using the code.
Look into using something like jQuery, create a "plugin" for your component, just one way, and just a thought but if you want to share the component with other folks to use this is one of the things that can be done.
Suppose I have a page that I am writing a javascript plugin for on the domain first.com. The javascript plugin injects an iframe pointing to a login page (of domain second.com) into the first.com page and displays it as a popup so that the user can login.
Is there anyway for me to hide/close the iframe after the user logs in with it? I can inject any javascript necessary into the first.com page and I control both the client and server side code on the login page within the iframe.
The main issue is that the iframe cannot access it's parent window to hide itself and the parent window cannot see any changes made in the contents of the iframe because of the same origin policy. Is there anyway around this or should I just lose the iframe idea and instead open a new window?
If the developer of second.com can be convinced to load an iframe in their login page, which loads a page at first.com, the the inner iframe can call javascript on the outer, since they are both from first.com. You can pass parameters in this way too, through the url of the inner iframe. An example here.
I think the issue you're running into is the browser stopping the cross-domain communication from happening. There is a way to sign your javascript but it is pretty much breaking the browser security model and isn't suggested unless absolutely necessary.
Is there any way that the login form is based on URL submition? You could create a simple sign in form and use AJAX to get your response back to ensure a successful login. This solution depends on having a RESTful login and again, I'm not sure about the implementation of your second.com.
If you're wondering about how to use the ajax to submit a form, I'd check this out (it is in jQuery but it applies to just about any framework.) View the source on that and see if that could work in your situation.