Regarding security issues it's a "somehow yes but" answer. The technique
limits the risks in that malicious code would have to be aware it's being
run from an iframe. However, since the iframe is created by the main window,
there is no cross-domain barrier and malicious code could access the main
window using the "parent" and "top" variables.
I remember I tried to set "parent" to undefined at one point. Depending on
the situation, I got a javascript error (the one that says you cannot change
the field of the object) or no error but "parent" was still accessible from
the iframe. Though I must say I was experimenting like crazy at that time
and I didn't get the iframe lifecycle right (especially the fact you need to
open the document before adding fields to the window object or else
sometimes -- notice the sometimes -- the variable were not actually
accessible from within the iframe).
Now, for the approach, it's a very very silly catch-all trick:
var iframe = $("<iframe />");
$("head").append(iframe);
var win = /* plumbery code */; // the iframe window
var doc = /* plumbery code */; // the iframe document
var done = false;
doc.open();
win.callback = function(json) {
done = true;
// cleanup
// call the success callback with json
};
win.error = function() {
if (done) return; // already treated
// cleanup
// call the error callback
};
doc.write(SEE_CODE_BELOW);
doc.close();
Where SEE_CODE_BELOW is something like:
<html>
<head>
<script type="text/javascript"
src="YOUR_SCRIPT?callbackParameter=callback"></script>
<script type="text/javascript">error()</script>
</head>
<body onload="error()" onerror="error()">
</body
</html>
This is the technique I came up with to catch errors on every browser I
tested the code on. The rest is mostly plumbery code with some
setTimeout(xxx,1) to control the execution flow (saved me a nasty crash in
Safari who doesn't appreciate when you .remove() an iframe from code the
iframe is the callee of).
I know the one letter variable policy is stupid, I was just terribly anxious
about size. I don't think this kind of plugin should be as large as 5kB like
my previous getJSON one. I tried to find an obfuscator that was solid but
couldn't. I'd love to be able to have a clean code and then a very compact
minified output.
But I agree I went a little berserk here. OK, I went crazy-berserk :P
2009/3/15 Jörn Zaefferer <[email protected]>
>
> Could the jsonp-over-iframe approach also remove some of the security
> concerns associated with jsonp? That is, what happens when a jsonp
> resource is replaced with a malicious script? Is the script restricted
> to the iframe?
>
> Having proper error handling for jsonp sounds very promising.
>
> One thing I noticed after looking at the source code: Using
> one-character variable names is something to be avoided - makes the
> code really hard to read. Couldn't quite figure out how you implement
> the error handling...
>
> Jörn
>
> On Sat, Mar 14, 2009 at 6:54 PM, Julian Aubourg
> <[email protected]> wrote:
> > I've tested it in Firefox 3.x, Chrome 1.x, IE7, Opera 9.x, Safari 3.x.
> All
> > windows versions. It uses an iframe instead of a simple script tag (wich
> > brings a separate window context, hence the added flexibility in callback
> > naming and the possibility to detect faulty requests). I'm pretty
> confident
> > it's generic enough to work in all browsers supported by jQuery (maybe
> with
> > some tweaks here and there because declaring variables in the iframe
> > window's context must be done at the proper stage in the iframe's
> lifecycle
> > -- I managed to find a common ground for the browsers I tested the plugin
> in
> > but let me tell you I battled to find it). I know I could have made
> things
> > simpler by exposing callback functions as fields of an object in the main
> > window's context ($.jsonp.callbacks for instance) but then I would have
> lost
> > the benefit of the same callback name for every call.
> > "Being able to specify a fixed jsonp callback function seems useful too
> and
> > probably not hard to add."
> > With a script tag in the main window's head, it's almost impossible
> unless
> > you have a global data structure to reroute responses and a callback
> > function code generator or expect the user to filter what response
> > corresponds to what request in his own callbacks. Keep in mind you may
> have
> > several requests running with the same callback name at once and you
> don't
> > know in which order they'll complete. It seems strange to me you seem to
> > find this callback naming thing so secondary. I can assure you that the
> > features the plugin provides in that department are as valuable as
> getting
> > an error callback properly notified.
> > Anyway, the source is MIT and for good reason ;) so don't hesitate to
> > pillage it as you see fit. All variables are one-letter for size purpose
> but
> > it 's heavily commented and should be easy to follow.
> > Now on the topic of having $.ajax() being a catch-all method for every
> > protocol on the planet, I'm not sure I buy it. I was browsing through
> > $.ajax() source code and I was quite puzzled at the number of
> conditionals
> > and tricks packed in a single function. I was almost surprised not to see
> an
> > image preloading subcase in there ;)
> > I mean, JSONP is not AJAX, unfortunately mainly due to technical
> > differencies. For instance:
> > - the dataFilter callback will never receive text simply because the
> browser
> > never has access to it in the first place, so you end up passing the
> > resulting JSON object to it,
> > - you cannot pass an xhr object to the callbacks because there's none
> hence
> > my use in $.jsonp() of an object containing the request's options and an
> > abort method. Imagine the clarity of the documentation regarding said
> > callbacks if you had to implement that into $.ajax() (not to mention how
> > bloated the code would get)
> > - you never, ever have access to HTTP headers (which would be incredibly
> > nice btw)
> > From a practical point of view, I guess most people will use $.getJSON so
> > that they don't have to deal with the intricaties of $.ajax() options
> > setting. That's in this spirit that I created $.json() (which has far
> less
> > options). It seemed the easier, safer and cleaner way to go.
> > As a side note, I'm not sure I like the idea of setting defaults through
> > $.ajaxSetup() that will be applied to XML, text, JSON, JSONP and whatever
> > new data format / protocol either. Don't get me wrong, I have a
> $.json.setup
> > method myself and I know there's a need but it seems to "all or nothing"
> to
> > me. I've just finished an add-on to $.jsonp() that will allow to make
> > "prepared" requests (a bit like SQL prepared statements). The idea is
> > basically to create pre-made functions that actually call $.jsonp() but
> with
> > default options (and a url templating engine and a nice arguments to
> request
> > data mapper). Interestingly, the technique can be applied to $.ajax() and
> > the add-on installs the hook for it too. All it needs right now is
> > documentation (I hate to release without at least an API doc and some
> > examples). Hell, here is an example taken from my test file of how it
> works,
> > I can't resist:
> > // Creating the prepared request
> > var getYouTubeUser = $.jsonp.prepared(
> > // url template
> > "http://gdata.youtube.com/feeds/api/users/{user}?callback=?",
> > // generated function parameters
> > // undefined: no default value, optional parameter
> > // null: no default value, mandatory parameter
> > {
> > "user": null,
> > },
> > // default parameters for the request
> > {
> > "data": {
> > "alt": "json-in-script"
> > },
> > "dataFilter": dataFilter
> > }
> > );
> > // Using the function
> > getYouTubeUser("julianaubourg")({
> > "success": function(json) {
> > // success code
> > },
> > "error": function(d,msg) {
> > // error code
> > }
> > });
> >
> > In conclusion, well, I think json support in $.ajax() as of today is
> enough
> > for what most people will attempt with it (that is pretty simple and
> borded
> > requests). I really think $.jsonp is more oriented toward advanced uses
> (I
> > made it because I'm working on a heavily service-consuming website at the
> > moment and thought some people would need something more advanced like I
> > did).
> > Oh yeah, and from a performance point of view, using iframes instead of
> > script tags is much more time consuming. Empirical tests I made showed
> that
> > sending a jsonp request to a local webserver (static text) using
> $.jsonp()
> > is about 2x to 10x slower than the $.ajax() method (Safari being the
> fastest
> > and Firefox the slowest). I blame it on the insane chrome activity that
> is
> > performed by most browsers when you have an iframe loading. Of course,
> it's
> > still a fraction of the time a normal request over the network will take
> but
> > it still has to be taken in consideration.
> > Regards,
> > -- Julian
> > 2009/3/14 Dave Methvin <[email protected]>
> >>
> >> > To summarize, $.jsonp() is ... an entirely new function which provides
> >> > the same options as $.ajax() does (as long as said options are
> relevant
> >> > to a jsonp request).
> >>
> >> Yeah, that's what $.ajax is trying to do with jsonp as well. At the
> >> moment I think there are some issues with jsonp through $.ajax, a
> >> combination of documentation problems and missing features that could
> >> be implemented for consistency with other $.ajax requests.
> >>
> >> On the error callback, does that solution work in all browsers? If so,
> >> it sounds like $.ajax should implement it for jsonp. Being able to
> >> specify a fixed jsonp callback function seems useful too and probably
> >> not hard to add.
> >>
> >
> >
> > >
> >
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"jQuery Development" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---