GM_ functions in GreaseKit (GK)

79 views
Skip to first unread message

jimtut

unread,
Dec 31, 2008, 1:22:10 PM12/31/08
to GreaseKit Users
Thanks to 2 posts here, I was able to get all the GM_ functions
(GM_getValue, GM_setValue, GM_xmlhttpRequest, etc.) I needed in GK. I
combined those 2 posts into a single new script, that you can leave
enabled for every site. That way, you don't need to patch each script
that calls these!

// ==UserScript==
// @name gm_functions
// @namespace *
// @description Replicated GreaseMonkey's GM_ functions for
GreaseKit.
// @include *
// @exclude
// ==/UserScript==


if(typeof GM_getValue === "undefined") {
GM_getValue = function(name){
var nameEQ = escape("_greasekit" + name) + "=", ca =
document.cookie.split(';');
for (var i = 0, c; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) {
var value = unescape(c.substring(nameEQ.length, c.length));
//alert(name + ": " + value);
return value;
}
}
return null;
}
}

if(typeof GM_setValue === "undefined") {
GM_setValue = function( name, value, options ){
options = (options || {});
if ( options.expiresInOneYear ){
var today = new Date();
today.setFullYear(today.getFullYear()+1, today.getMonth,
today.getDay());
options.expires = today;
}
var curCookie = escape("_greasekit" + name) + "=" + escape(value)
+
((options.expires) ? "; expires=" + options.expires.toGMTString
() : "") +
((options.path) ? "; path=" + options.path : "") +
((options.domain) ? "; domain=" + options.domain : "") +
((options.secure) ? "; secure" : "");
document.cookie = curCookie;
}
}

if(typeof GM_xmlhttpRequest === "undefined") {
GM_xmlhttpRequest = function(/* object */ details) {
details.method = details.method.toUpperCase() || "GET";
if(!details.url) {
throw("GM_xmlhttpRequest requires an URL.");
return;
}
// build XMLHttpRequest object
var oXhr, aAjaxes = [];
if(typeof ActiveXObject !== "undefined") {
var oCls = ActiveXObject;
aAjaxes[aAjaxes.length] = {cls:oCls, arg:"Microsoft.XMLHTTP"};
aAjaxes[aAjaxes.length] = {cls:oCls, arg:"Msxml2.XMLHTTP"};
aAjaxes[aAjaxes.length] = {cls:oCls, arg:"Msxml2.XMLHTTP.3.0"};
}
if(typeof XMLHttpRequest !== "undefined")
aAjaxes[aAjaxes.length] = {cls:XMLHttpRequest, arg:undefined};
for(var i=aAjaxes.length; i--; )
try{
oXhr = new aAjaxes[i].cls(aAjaxes[i].arg);
if(oXhr) break;
} catch(e) {}
// run it
if(oXhr) {
if("onreadystatechange" in details)
oXhr.onreadystatechange = function()
{ details.onreadystatechange(oXhr) };
if("onload" in details)
oXhr.onload = function() { details.onload(oXhr) };
if("onerror" in details)
oXhr.onerror = function() { details.onerror(oXhr) };
oXhr.open(details.method, details.url, true);
if("headers" in details)
for(var header in details.headers)
oXhr.setRequestHeader(header, details.headers[header]);
if("data" in details)
oXhr.send(details.data);
else
oXhr.send();
}
else {
throw ("This Browser is not supported, please upgrade.");
}
}
}

if(typeof GM_addStyle === "undefined") {
function GM_addStyle(/* String */ styles) {
var oStyle = document.createElement("style");
oStyle.setAttribute("type", "text\/css");
oStyle.appendChild(document.createTextNode(styles));
document.getElementsByTagName("head")[0].appendChild(oStyle);
}
}

if(typeof GM_log === "undefined") {
function GM_log(log) {
if(console)
console.log(log);
else
alert(log);
}
}

Damiano ALBANI

unread,
Jan 8, 2009, 5:09:58 PM1/8/09
to GreaseKit Users
Hello,

On Dec 31 2008, 7:22 pm, jimtut <jim...@gmail.com> wrote:
> Thanks to 2 posts here, I was able to get all the GM_ functions
> (GM_getValue, GM_setValue, GM_xmlhttpRequest, etc.)

Hum, this GM functions replacement user script is an interesting
idea... but it doesn't seem to work here. All I get is
"ReferenceError: Can't find variable: GM_log" for instance -- even if
I make sure that my "real" script is run subsequently.

So I tried to include those replacement functions right into my own
script. But now I run into a cross-domain issue with the
GM_xmlhttpRequest implementation.
Basically, I get "Permission denied" errors when I make a
XMLHttpRequest to another domain that the page I'm on.

I thought, well, let's find another way. Like using the "invisible
iframe" trick. Alas, it wasn't more successful, with errors like
"Unsafe JavaScript attempt to access frame with URL http://www.domain1.com/search
from frame with URL http://www.domain2.com/page.html. Domains,
protocols and ports must match." when trying to retrieve the iframe
content.

Now, the only idea that I've left is the dynamic <script> method,
which is even more of a hack... and leave us far from the original
usage/goal of GreaseMonkey/GreaseKit. That is to provide an easy, no-
nonsense API :-)

Any suggestion is welcome!

Regards,

--
Damiano ALBANI

jimtut

unread,
Jan 8, 2009, 11:47:30 PM1/8/09
to GreaseKit Users
That was the error I got BEFORE I added this gm_functions user
script. Try disabling your other scripts which use GM_ functions.
Then, edit this one to throw an alert() in at the beginning & end of
the file. If this script is being loaded for every page, you should
see both those alerts on EVERY page. Try it with a page on which you
want to use your other script. Are you getting both alerts from
gmfunctions? Now, what happens when you enable your other script?
Can you post your other script and the URL @ which you're trying to
use it?

Damiano ALBANI

unread,
Jan 9, 2009, 6:13:56 AM1/9/09
to greasek...@googlegroups.com
Hello,

On Fri, Jan 9, 2009 at 5:47 AM, jimtut <jim...@gmail.com> wrote:

That was the error I got BEFORE I added this gm_functions user
script.  Try disabling your other scripts which use GM_ functions.
Then, edit this one to throw an alert() in at the beginning & end of
the file.  If this script is being loaded for every page, you should
see both those alerts on EVERY page.
`
So I added a "console.log('replacement loaded');" call at the end.
And, indeed, I can see that the replacement script does get processed on every page.
 
Try it with a page on which you
want to use your other script.  Are you getting both alerts from
gmfunctions?  Now, what happens when you enable your other script?
Can you post your other script and the URL @ which you're trying to
use it?

I wrote a simple Google test userscript:

// ==UserScript==
// @name           Google test
// @namespace      urn:google-test
// @include        http://*.google.*
// ==/UserScript==

try {
GM_xmlhttpRequest({ method: "GET",
                    url: "http://yahoo.com",
                    onload: function () { alert("yahoo loaded"); } });
} catch (e) {
  console.log(e);
}

See that I'm trying to fetch a "yahoo.com" page from a "google.com" domain.
And when I run this, Safari's error console shows:

replacement loaded
google.com

Error: permission denied
google.com

The error being due to the cross-domain XMLHttpRequest call AFAIK...

By the way, my goal is not to have an external GM replacement script because I'd like to ship a single file -- even if I have to redeclare "everything" in my own script.

Best regards,

--
Damiano ALBANI

jimtut

unread,
Jan 30, 2009, 11:12:50 AM1/30/09
to GreaseKit Users
I posted this code as a downloaded userscript at http://userscripts.org/topics/21030,
so it should be easy for folks to try out. Hope it helps others as it
helped me!

samuel365

unread,
Mar 6, 2009, 9:54:59 PM3/6/09
to GreaseKit Users
hi

had to change this lines

function GM_addStyle(/* String */ styles) {

became:

GM_addStyle = function(/* String */ styles)


and

function GM_log(log) {

became:
GM_log = function(log) {


see if it fixes the "ReferenceError: Can't find variable: GM_log"


On Jan 8, 7:09 pm, Damiano ALBANI <damiano.alb...@gmail.com> wrote:
> Hello,
>
> On Dec 31 2008, 7:22 pm, jimtut <jim...@gmail.com> wrote:
>
> > Thanks to 2 posts here, I was able to get all the GM_ functions
> > (GM_getValue, GM_setValue, GM_xmlhttpRequest, etc.)
>
> Hum, this GM functions replacement user script is an interesting
> idea... but it doesn't seem to work here. All I get is
> "ReferenceError: Can't find variable: GM_log" for instance -- even if
> I make sure that my "real" script is run subsequently.
>
> So I tried to include those replacement functions right into my own
> script. But now I run into a cross-domain issue with the
> GM_xmlhttpRequest implementation.
> Basically, I get "Permission denied" errors when I make a
> XMLHttpRequest to another domain that the page I'm on.
>
> I thought, well, let's find another way. Like using the "invisible
> iframe" trick. Alas, it wasn't more successful, with errors like
> "Unsafe JavaScript attempt to access frame with URLhttp://www.domain1.com/search
> from frame with URLhttp://www.domain2.com/page.html. Domains,

Jim Tuttle

unread,
Mar 8, 2009, 8:44:11 PM3/8/09
to greasek...@googlegroups.com
Thanks - you're right!  I've posted the new script at http://userscripts.org/scripts/review/41441.

Thanks,
Jim

mr_justin

unread,
Apr 26, 2009, 4:25:59 PM4/26/09
to GreaseKit Users
Jim, thanks for this addition to GK. Have you looked much into trying
to get Ajax requests running to other domains like GM allows? I
understand that right now we're limited by what any other browser-
level script has access to, but maybe we need to push harder to get
this support back in GK or possibly just write a new SIMBL plugin that
adds this functionality?

Most GM scripts rely on pulling down external content through
GM_xmlhttpRequest, without this feature I imagine GK is going to
stagnate.

-justin

Jim Tuttle

unread,
Apr 26, 2009, 4:50:13 PM4/26/09
to greasek...@googlegroups.com
I just pasted together functions posted around this & other forums.
I'm afraid I wouldn't have any idea how to modify this code or write a
SIMBL plugin. I think pushing GK to support this is the best plan.

Sent from my iPod

Damiano ALBANI

unread,
Apr 27, 2009, 3:07:26 AM4/27/09
to greasek...@googlegroups.com
Hello,

On Sun, Apr 26, 2009 at 22:25, mr_justin <justin...@gmail.com> wrote:

Most GM scripts rely on pulling down external content through
GM_xmlhttpRequest, without this feature I imagine GK is going to
stagnate.

As a (temporary?) workaround, I'd recommend using the JSONP technique for cross-domain GM_xmlhttpRequest.
Works fine here, though it requires cooperation with the target Webservice.

Regards,

--
Damiano ALBANI

Vincent

unread,
May 18, 2009, 4:46:50 PM5/18/09
to GreaseKit Users
Hi all,

For the last monthes i completly stop using Firefox for memory and cpu
issues...
Recently ive rediscovered the joys of GM scripts...
Then I was asking myself, why the hell GK wasnt workin on my safari 4
ßeta...
Figured that i misconfigured it, probably the GK SIMBL plugin at the
wrong location...

Then i happily tried some GM scripts, to find that most of em wasnt
working...
Figured that that damn GM_ functions was missing.
Ive digged more and more to read to finally read this thread...

Looked at the GK history, the security issue of cross domain
GM_Xmlhttprequest...

Then i've gived a look at GM and GK source codes... (i'm a developper)
I really would love to be able to give a hand to bring GK to full GM
compatibility!
Any one with any hints to resolve that GK security issues?
I mean from an objective-c/cocoa/SIMBL point of view. Kato maybe?

Please, i'm starting to love safari 4, i hate going back to firefox
just for GM.


Vincent.
(from paris, france, sorry for my english ^^)

On 27 avr, 09:07, Damiano ALBANI <damiano.alb...@gmail.com> wrote:
> Hello,
>
> On Sun, Apr 26, 2009 at 22:25, mr_justin <justinperk...@gmail.com> wrote:
>
> > Most GM scripts rely on pulling down external content through
> > GM_xmlhttpRequest, without this feature I imagine GK is going to
> > stagnate.
>
> As a (temporary?) workaround, I'd recommend using the JSONP
> technique<http://en.wikipedia.org/wiki/JSON#JSONP>for cross-domain

Justin Perkins

unread,
May 18, 2009, 5:46:57 PM5/18/09
to greasek...@googlegroups.com
I don't have any help for you, but if you get the GM_* functions
working in Safari just like they do in Firefox then I will love you!

Best of luck on your adventure.

-justin

Vincent

unread,
May 21, 2009, 7:03:38 PM5/21/09
to GreaseKit Users
Digged a lot the web on the subject to come to the conslusion that the
real deal is on Safari/WebKit side to provide a secured solution like
Firefox XPCNativeWrapper.
I understand now why GreaseKit project hasnt moved for 2 years :(
Even GreaseMetal project for Chrome has the same issue :
http://labs.cybozu.co.jp/blog/kazuhoatwork/2008/09/greasemetal_version_02_release.php
> "4:43pm added: Now that we have added support for some GM_* functions, the left ones are: GM_xmlHttpRequest, GM_getValue, and GM_setValue. The three functions require a different security model than that of ordinal web scripts (known as same domain policy)"

Btw, Chromium project is including greasemonkey support directly in
chrome...

I'll try to mail WebKit team... If anyone from Apple reading this...
Please help to make Safari better... than firefox. Safari 4 is
already, except for extensibility.
(Or please mozilla make firefox better than safari, or chrome, i don't
care, i just want a perfect browser... ;)


Vincent.

Ishan Anand

unread,
May 21, 2009, 9:29:45 PM5/21/09
to greasek...@googlegroups.com
Let us know what the webkit folks say (or even better a link to the
thread). Even if they do implement an XPCNativeWrapper wrapper
equivalent in WebKit, we'd still need Apple to expose it in their
WebView interface.

Incidentally, I ran into similar security concerns trying to port
GreaseMonkey scripts to the iPhone ( GreasePocket,
http://www.readwriteweb.com/archives/greasepocket_greasemonkey_for.php
). Without those powerful-but-hard-to-implement-securely functions
like GM_xmlHttpRequest the value proposition for GreasePocket went
down.

-Ishan

Vincent

unread,
May 22, 2009, 8:19:12 AM5/22/09
to GreaseKit Users
i'll do for sure and your feedback is also welcome,

Great project about iphone greasemonkey, even if it has no chance to
be "on appstore one day.
I guess you know you can "inject" code into MobileSafari just like
GreaseKit does using MobileSubstrate, a SIMBL iPhone equivalent...
But thats the path to jailbreak apps... (i'm an iPhone dev too)

Btw, since chrome almost support greasmonkey script and since it is
WebKit based, we might find a solution on this side.
I didnt have time to investigate on this side.

Just grabbed and compiled last revision of OSX Chromium and btw, that
looks not bad, maybe we will see some osx chrome beta in few monthes.

-Vincent.

On May 22, 3:29 am, Ishan Anand <ishan.an...@gmail.com> wrote:
> Let us know what the webkit folks say (or even better a link to the
> thread). Even if they do implement an XPCNativeWrapper wrapper
> equivalent in WebKit, we'd still need Apple to expose it in their
> WebView interface.
>
> Incidentally, I ran into similar security concerns trying to port
> GreaseMonkey scripts to the iPhone ( GreasePocket,http://www.readwriteweb.com/archives/greasepocket_greasemonkey_for.php
> ). Without those powerful-but-hard-to-implement-securely functions
> like GM_xmlHttpRequest the value proposition for GreasePocket went
> down.
>
> -Ishan
>
>
>
> On Thu, May 21, 2009 at 4:03 PM, Vincent <vgue...@gmail.com> wrote:
>
> > Digged a lot the web on the subject to come to the conslusion that the
> > real deal is on Safari/WebKit side to provide a secured solution like
> > Firefox XPCNativeWrapper.
> > I understand now why GreaseKit project hasnt moved for 2 years :(
> > Even GreaseMetal project for Chrome has the same issue :
> >http://labs.cybozu.co.jp/blog/kazuhoatwork/2008/09/greasemetal_versio...

Vincent

unread,
May 22, 2009, 9:26:29 AM5/22/09
to GreaseKit Users
Mmm bad news, same issue for chromium team...
Not supporting cross domain requests, they use standard
XMLHttpRequest :(

Ishan Anand

unread,
May 24, 2009, 2:44:06 PM5/24/09
to greasek...@googlegroups.com
Thanks. Wasn't aware of MobileSubstrate but had briefly considered I
might have to method swizzle to do it effectively (a brief scan of
MobileSubstrate indicates it was would be more complex than I
considered). In either case though, it would be a jailbreak app which
isn't a road I wanted to go down.
Reply all
Reply to author
Forward
0 new messages