Basically, if you have a script that works in firefox, the chance is quite large that you'll be able to convert it to a chrome script.
There are a few things that just won't work. Most notably:
- @require (to add a static file along with your script) doesn't work. See http://www.chromium.org/developers/desi ... er-scripts for the latest support.
- Unsafewindow gives access to the javascript of the page. There is no way to get access to that through chrome, only HTML-elements and firing events on those elements.
- There is no way to do cross-side requests (normally). Greasemonkey allows this usually, because every request is seen as fetching a new page, and not as 1 page requesting another page.
The basics are just to remove every use of the previous 3 points. The 2nd point was the hardest for me, but it is considered to be bad practice even in Greasemonkey itself, so it had to be done anyway.
But then, there are still some methods in greasemonkey that might not be implemented in chrome, most noticably the getValue and setValue-methods.
The best way to solve this is to add those functions and do something similar if they don't exist already. This is the piece of script I use at the moment:
- Code: Select all
if((typeof GM_getValue == 'undefined') || (GM_getValue('a', 'b') == undefined)) {
var namespace = "BOB.";
GM_addStyle = function(css) {
var style = document.createElement('style');
style.textContent = css;
document.getElementsByTagName('head')[0].appendChild(style);
}
GM_deleteValue = function(name) {
localStorage.removeItem(namespace + name);
}
GM_getValue = function(name, defaultValue) {
var value = localStorage.getItem(namespace + name);
if (!value)
return defaultValue;
var type = value[0];
value = value.slice(1);
switch (type) {
case 'b':
return value == 'true';
case 'n':
return Number(value);
default:
return value;
}
}
GM_listValues = function() {
var i, name ,result = [];
for (i = 0; i < localStorage.length; i++) {
name = localStorage.key(i);
if (name.indexOf(namespace) == 0) {
result.push(name.slice(namespace.length));
}
}
return result;
}
GM_xmlhttpRequest=function(obj) {
var request=new XMLHttpRequest();
request.onreadystatechange=function() {
if(obj.onreadystatechange) {
obj.onreadystatechange(request);
};
if(request.readyState==4 && obj.onload) {
obj.onload(request);
}
}
request.onerror=function() {
if(obj.onerror) {
obj.onerror(request);
}
}
try {
request.open(obj.method,obj.url,true);
} catch(e) {
if(obj.onerror) {
obj.onerror( {readyState:4,responseHeaders:'',responseText:'',responseXML:'',status:403,statusText:'Forbidden'} );
};
return request;
}
if(obj.headers) {
for(var name in obj.headers) {
request.setRequestHeader(name,obj.headers[name]);
}
}
request.send(obj.data);
return request;
}
GM_setValue = function(name, value) {
value = (typeof value)[0] + value;
localStorage.setItem(namespace + name, value);
}
unsafeWindow = window;
}
(Most of this code was found in a userscripts-thread btw, I made some small adjustments)
For storage, it uses the localStorage that used to be part of HTML5, and is implemented in the newer browsers. There is one caveat for that: those values get set per website, so http://www.conquerclub.com has 1 localStorage, and this could cause name collisions if multiple scripts try to save the same name. So the variable namespace defines a namespace now that should be different for every script, which should make it less likely to have naming collisions.
Most difficult thing at the moment is the mimicing of the GM_xmlhttpRequest. I don't know if it is possible to get around not being able to get a site, but for now I only need it for checking whether a new version is available, and I can live with that not working for chrome at the moment.