I have made a script that runs with no glitch on Firefox. I'm retrieving some data from external domain in an iframe to insert them in the page by using setInterval()
I have tried to use Trixie, so that it runs in IE, but it seems that functions GM_getValue and GM_setValue were not defined.
I've added these replacement functions, based on cookies, but I can't get it to work in a cross-domain way : http://www.howtocreate.co.uk/operaStuff/userjs/aagmfunctions.js
The cookie is created, and the data stored, but it's only accessible from the iframe, not from the top document.
Here is the basic structure I used : http://www.pastie.org/1889407
In test() I have access to the value stored with GM_getValue("destination",""), but it doesn't work inside function check().
1) Is there a way to make the cookie cross-domain?
2) Are there other ways to store data in IE in a cross-domain way? (I have briefly heard of Flash objects, but it doesn't seem quite a light solution...) Other implementations of these functions (getValue and setValue) are quite hard to find.
3) I'm using Trixie, maybe it's not the best solution, any advice on what plugin I should better use, to have those functions?
Well, after trying many solutions, I finally found an answer.
I used IE7PRO, that includes functions PRO_setValue and PRO_getValue, that ended to work just fine.
My problem was that I tried to access the external domain on an iframe, which is not supported by IE7PRO apparently.
I just splitted my script into 2 user scripts : one for my domain, that check if new PRO_getValue are available, and the other one for the external domain, that saves the data. One tab for my page, one for the other and surprisingly, it worked like a charm.
It doesn't seem possible with Trixie or GM4IE, the only inconvenient is that IE7PRO is heavy, since the GM script support is just a small part of this extension.
Related
Goal: making a standalone modular JavaScript debuggin-utility (includes custom dom and event manipulation methods) to be used in the console (preferably Chrome) on any random sites of interests (with no backend access).
Usage: initially include module script directly via copy-paste to console or by creating a new script element pointing at myhomepage.com/shortandeasytoremember.js and call methods on the namespace from there on.
Problem: how to best make it persistent throughout the session on that webpage (so that I wouldn't need to reinclude it after every refresh) ?
Note: any additional browser compatibility is not required - as long as it works in the latest Chrome, it's all fine by me (but any effort in the compatibility department is always much appreciated for the sake of others). IF YOU READ THIS IN A FAR FUTURE and by then there exists a better solution than what is written down below, please take a moment to contribute with your superior knowledge.
What I currently have is an event listener on window.unload to save any state data to localStorage and a string to make it easier to reinclude the module after page reload using eval(localStorage.getItem('loadMyNS'));.
(function(ns, undefined){
'use strict';
//util methods on ns and few monkey patches for debugging ...
var store = 'if(!window.MyNS){' +
'var xyz9=document.createElement("script");' +
'xyz9.src="http://myhomepage.com/shortandeasytoremember.js";' +
'document.head.appendChild(xyz9);}';
localStorage.setItem('loadMyNS', store);
ns.save = function () {
// and use localStorage for some more data
// to be used by other methods after page reload
};
window.addEventListener('unload', ns.save, false);
}(window.MyNS = window.MyNS || {}));
(browsers with no localStorage or addEventListener may benifit from this article)
I've also concidered using the same schema with window.name instead of localStorage (as long as this still seems legid) just because writing eval(window.name) would take less typing ^^.
The trouble (one of them) I have with the "eval-script-tag-inclusion" is on the sites which block external non-https script sources. An ideal solution would be a globally accessible module which would live with state and methods included (and no initialization required after refresh) at least until I close the the window (or overwrite the ref ofc).
If that is currently absolutely not possible, a lesser solution yet still superior to my current code would suffice.
So, here is the issue.
I have something like:
// Dangerous __hostObject that makes requests bypassing
// the same-origin policy exposed from other code.
(function(){
var danger = __hostObject;
})();
delete __hostOBject;
Am I perfectly safe knowing no script can tamper or access __hostObject?
( If they can, I have an CSRF vulnerability or worse. )
Note 1: This is for a browser extension. I have better hooks than other scripts running on the page. I execute before them and I'm done before they've even loaded.
Note 2: I know this has been asked multiple times for scripts in general. I'm wondering if it's possible if I know I load before any other scripts.
Provided that the __hostObject is deletable, the code in your question is safe.
However, I assume that your real code is slightly more complicated. In that case, very careful coding is required, because the page can change built-in methods (e.g. Function.prototype.call) to get into your closure and do whatever evil things they want. I had successfully abused functionality of extension frameworks such as Kango and Crossrider via this method when I performed such a test.
Won't simply adding a breakpoint and reloading the script expose your __hostObject
I'm doing a couple of things with jQuery in an MTurk HIT, and I'm guessing one of these is the culprit. I have no need to access the surrounding document from the iframe, so if I am, I'd like to know where that's happening and how to stop it!
Otherwise, MTurk may be doing something incorrect (they use the 5-character token & to separate URL arguments in the iframe URL, for example, so they DEFINITELY do incorrect things).
Here are the snippets that might be causing the problem. All of this is from within an iframe that's embedded in the MTurk HIT** (and related) page(s):
I'm embedding my JS in a $(window).load(). As I understand it, I need to use this instead of $(document).ready() because the latter won't wait for my iframe to load. Please correct me if I'm wrong.
I'm also running a RegExp.exec on window.location.href to extract the workerId.
I apologize in advance if this is a duplicate. Indeed - after writing this, SO seems to have a made a good guess at this: Debugging "unsafe javascript attempt to access frame with URL ... ". I'll answer this question if I figure it out before you do.
It'd be great to get a good high-level reference on where to learn about this kind of thing. It doesn't fit naturally into any topic that I know - maybe learn about cross-site scripting so I can avoid it?
** If you don't know, an MTurk HIT is the unit of work for folks doing tasks on MTurk. You can see what they look like pretty quick if you navigate to http://mturk.com and view a HIT.
I've traced the code to the following chunk run within jquery from the inject.js file:
try {
isHiddenIFrame = !isTopWindow && window.frameElement && window.frameElement.style.display === "none";
} catch(e) {}
I had a similar issue running jQuery in MechanicalTurk through Chrome.
The solution for me was to download the jQuery JS files I wanted, then upload them to the secure amazon S3 service.
Then, in my HIT, I called the .js files at their new home at https://s3.amazonaws.com.
Tips on how to make code 'secure' by chrome's standards are here:
http://developer.chrome.com/extensions/contentSecurityPolicy.html
This isn't a direct answer to your question, but our lab has been successful at circumventing (read hack) this problem by asking workers click on a button inside the iframe that opens a separate pop-up window. Within the pop-up window, you're free to use jQuery and any other standard JS resources you want without triggering any of AMT's security alarms. This method has the added benefit of allowing workers to view your task in a full-sized browser window instead of AMT's tiny embedded iframes.
I want a simple and light-weighted way of making cross-domain requests to my api address (api.example.com) which is a subdomain of my main domain (example.com).
I've read A LOT about techniques and hacks to deal with XDRs and their incompatibilities with each used browser but XDR is still very complicated for me. I don't need a complete/complex solution as easyXDM, which I have implemented and worked perfectly.
So, I decided to 'enable CORS' which solved the problem for modern Webkit and Gecko browsers. But as always, there is the IE (and in this case Opera too) which is not compatible with CORS yet.
As I wanted to continue using jQuery AJAX methods, I searched for a solution that would allow XDR with jQuery methods. Then, I implemented a very nice solution by benvinegar which replaces jQuery.ajax() method and therefore all its dependent methods: https://gist.github.com/859940. His script is based on the document.domain/iframe trick.
Before calling the function proposed by Ben, I tested for CORS support with jQuery.support.cors (using jQuery 1.6.2). Everything is okay, working perfectly.
The only thing I'm not happy with the above linked script is that I need to load the jQuery library from api.example.com and I don't want that. I've made a bundle of minified javascript libraries/plugins/scripts in one file which is used by example.com; that gives me me 2 options (for using jQuery in api.example.com): load the entire bundle again or load a non-cached version of jQuery only. I don't like either.
My question is: is it possible to change the DOM of an iframe from the parent frame when both frames have the same document.domain? If so, could I clone jQuery from example.com into the child-iframe (api.example.com)? How? Or I'm just being crazy about this and there is a better solution taking in consideration what I described?
Thank you all in advance,
Leonardo.
file test.htm
<iframe name='my-iframe' src='test2.htm' onload="child();"></iframe>
<script>
function child(){
alert(window.frames['my-iframe'].my_var);
window.frames['my-iframe'].my_var = 'bye';
window.frames['my-iframe'].show_var();
}
</script>
file test2.htm
<script>
window.my_var = 'hi';
function show_var(){
alert(my_var);
}
</script>
The code above will alert 'hi' and then 'bye'
I'm thinking that the reason I can't do this is because it might be a huge security hole, but here goes...
I want to have a bookmark on my browser (FF3, preferably) that is only a snippet of javascript code. It would merely construct a URL based on the current date and then do a window.location = on that URL.
I know that I could make a page and keep it on my local machine and just refer to it that way, but I was just wondering if you could bypass that step and actually have the "location" of the bookmark really just be javascript. I could have sworn that this was possible years ago, but I can't find anything that tells me either way now.
What you want is a bookmarklet they are easy to create and should work in most major browsers.
Edit: Stack overflow seems not to allow creating bookmarklets in the context of the site, basically you can create a new bookmark and type the following in the location field
javascript:window.location='http://www.google.com/search?q='+Date()
to get a bookmarklet that searches google for the current date.
It is worthy of note that you can put that in a function wrapper as well. imranamajeed nicely illustrated that for us... but apparently I'm too new to the site to up his post. :P
so for clarity:
javascript:(function(){
location.href = location.href + "#";
})();
(the carriage returns did not affect performance in chrome and IE)
One minor catch. IE can only handle a 508 character URL in this format. If you save it in IE with a url longer than this, it will truncate without warning and thus fail.
If you need a really complex script, you'll need to use a "hosted" bookmarklet, where you have a short bookmark that injects a script tag into the page, to "call" your hosted bookmarklet.
It isn't as nice/portable, but its the only workaround.
Google Bookmark
javascript:(function(){var%20a=window,b=document,c=encodeURIComponent,d=a.open("http://www.google.com/bookmarks/mark?op=edit&output=popup&bkmk="+c(b.location)+"&title="+c(b.title),"bkmk_popup","left="+((a.screenX||a.screenLeft)+10)+",top="+((a.screenY||a.screenTop)+10)+",height=420px,width=550px,resizable=1,alwaysRaised=1");a.setTimeout(function(){d.focus()},300)})();
Well, I just created a bookmark in FF3, went back and updated it and added the following test:
javascript:alert('Wacky%20test%20yo');
Low and behold, after I saved and loaded, I was able to get my alert.
I'm sure you can work up something similar for your needs.