|
|
I'm currently working on getting one of my scripts to work in Google Chrome. I thought I'd post some of my code for others that may want to do the same.
(function(){
if(document.URL.match('foo.com')){
console.log('script is running');
/******
Google Gears stuff
******/
// Copyright 2007, Google Inc.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// 3. Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Sets up google.gears.*, which is *the only* supported way to access Gears.
//
// Circumvent this file at your own risk!
//
// In the future, Gears may automatically define google.gears.* without this
// file. Gears may use these objects to transparently fix bugs and compatibility
// issues. Applications that use the code below will continue to work seamlessly
// when that happens.
// We are already defined. Hooray!
if (window.google && google.gears) {
return;
}
var factory = null;
// Firefox
if (typeof GearsFactory != 'undefined') {
factory = new GearsFactory();
}
else {
// IE
try {
factory = new ActiveXObject('Gears.Factory');
// privateSetGlobalObject is only required and supported on IE Mobile on
// WinCE.
if (factory.getBuildInfo().indexOf('ie_mobile') != -1) {
factory.privateSetGlobalObject(this);
}
}
catch (e) {
// Safari
if ((typeof navigator.mimeTypes != 'undefined') && navigator.mimeTypes["application/x-googlegears"]) {
factory = document.createElement("object");
factory.style.display = "none";
factory.width = 0;
factory.height = 0;
factory.type = "application/x-googlegears";
document.documentElement.appendChild(factory);
}
}
}
// *Do not* define any objects if Gears is not installed. This mimics the
// behavior of Gears defining the objects in the future.
if (!factory) {
return;
}
// Now set up the objects, being careful not to overwrite anything.
//
// Note: In Internet Explorer for Windows Mobile, you can't add properties to
// the window object. However, global objects are automatically added as
// properties of the window object in all browsers.
if (!window.google) {
google = {};
}
if (!google.gears) {
google.gears = {factory: factory};
}
var db = google.gears.factory.create('beta.database');
db.open('database-wlr');
db.execute('create table if not exists WLR (GMSetKey text, GMSetVal text)');
db.close();
/******
Greasemonkey API replacements
******/
function GM_setValue(sN, sV){
db.open('database-wlr');
//I cant get REPLACE or ON DUPLICATE KEY UPDATE to work properly so this will have to do for the moment.
var rs = db.execute('select GMSetKey from WLR');
var dbExec = "insert";
while (rs.isValidRow()) {
if(rs.field(0) == 'gkey'){
dbExec = "UPDATE";
break;
}
rs.next();
}
if(dbExec == "insert"){
db.execute("insert into WLR values (?, ?)", [sN, sV]);
}
else{
db.execute("UPDATE WLR SET GMSetKey='"+sN+"', GMSetVal='"+sV+"'");
}
db.close();
}
function GM_getValue(gV){
db.open('database-wlr');
var getGMV = db.execute("select GMSetVal from WLR WHERE GMSetKey = '"+gV+"' LIMIT 1").field(0);
db.close();
return getGMV; //should return undefined if it's not in the database
}
var gmstDocHead = document.getElementsByTagName('head')[0];
function GM_addStyle(s){
var gm_style = document.createElement('style');
gm_style.type="text/css";
gm_style.textContent=s;
gmstDocHead.appendChild(gm_style);
};
function GM_log(t){
console.log(t);
};
}
}
More info:
|
|
|
Awesome. Lets create a group. 1.The @include's will need to be manually added with flow statements (e.g. if(document.URL=='http://foo.com/meh'||document.URL=='http://foo.com/sneh'){...) I hate doing things manually. Here's a function to automate things a bit.
function GM_testUrl(include) {
return (new RegExp(include.replace(/(\/|\?|\.|\^|\,|\+)/g, "\\\$1").replace(/\*/g, '.*')).test(document.URL)) ? true : false;
}
if (GM_testUrl("http://*.google.com/*")) {
// Code here
}
If Chrome supports E4X I could write some code to make this even easier for us. |
|
|
function GM_testUrl(include) { return (new RegExp(include.replace(/(\/|\?|\.|\^|\,|\+)/g, "\\\$1").replace(/\*/g, '.*')).test(document.URL)) ? true : false; } is the same as function GM_testUrl(include) {
return new RegExp(include.replace(/(\/|\?|\.|\^|\,|\+)/g, "\\\$1").replace(/\*/g, ".*")).test(document.URL);
}
|
|
|
lol true haha. nice catch. I'm always forgetting types when they're not explicitly declared. Anyway, I was gonna make it handle more than one include. This function was inspired by the convertToRegExp PHP function.
function GM_testUrl(includes, excludes) {
regTest = function(url) { return new RegExp(url.replace(/(\/|\?|\.|\^|\,|\+)/g, "\\\$1").replace(/\*/g, ".*")).test(document.URL); }
if (typeof excludes != "undefined") {
if (typeof excludes == "string") excludes = [excludes];
for (exclude in excludes) if (regTest(excludes[exclude])) return false;
}
if (typeof includes == "string") includes = [includes];
for (include in includes) if (regTest(includes[include])) return true;
return false;
}
if (GM_testUrl(["http://*.google.com/*", "http://*.facebook.com/*"], "http://*.facebook.com/home.php?*")) {
// This is equal to:
// @include http://*.google.com/*
// @include http://*.facebook.com/*
// @exclude http://*.facebook.com/home.php?*
// Please note that you can either pass a string or an array for either includes or excludes
// Also note that includes is required, whereas excludes is optional
// Finally, an exclude can override and include
}
|
|
|
Sorry if this is a stupid question, but if this is for running Greasemonkey scripts in Chrome, then why do we need the bit for IE, Safari, and Firefox? |
|
|
Sizzle, welcome to the wonderful world of user agent strings:
Basically, because Chrome is based on Safari, that's necessary. On an unrelated note, if there's code to handle IE in some snippet I steal (possibly from myself) I tend to leave it in, just in case I want that same effect on a page that I host later. -Joel |
|
|
But if the userscripts are running on the client-side how the hell would Safari ever risk running them? |
|
|
You can probably remove that bit. I just copied the whole gears_init.js file. ( http://code.google.com/apis/gears/gears_init.js ) Here's a good tutorial on using google gears with GM:
|
|
|
so I take it that in chrome |
|
|
Google greasemetal. |
|
|
Seems they now support @include
|
|
|
Yansky wrote: Yeah but the don't support @exclude and they also want us to use @match, but I refuse to do that just for them. |
|
|
I am brand new to GM so take what I write with a grain of salt. Chrome 2.0.180.0 supports @include. However I cannot get cross domain XHR to work. |
![]() ![]() |
Bump. I just updated a couple of my userscripts to be chrome compatible with this snippet: //chrome compatibility; opera doesn't have localStorage
if (typeof GM_log == 'undefined') {
function GM_addStyle(css) {
var style = document.createElement('style');
style.textContent = css;
document.getElementsByTagName('head')[0].appendChild(style);
}
function GM_deleteValue(name) {
localStorage.removeItem(name);
}
function GM_getValue(name, defaultValue) {
return localStorage.getItem(name) || defaultValue;
}
function GM_log(message) {
console.log(message);
}
function GM_registerMenuCommand(name, funk) {
//todo
}
function GM_setValue(name, value) {
localStorage.setItem(name, value);
}
}
|
![]() ![]() |
aeosynth wrote:Thanks for the code. That also makes your scripts Safari compatible as well. You forgot unsafeWindow: if(typeof unsafeWindow==='undefined') {
unsafeWindow = window;
function GM_addStyle(css) {
var style = document.createElement('style');
style.textContent = css;
document.getElementsByTagName('head')[0].appendChild(style);
}
function GM_deleteValue(name) {
localStorage.removeItem(name);
}
function GM_getValue(name, defaultValue) {
return localStorage.getItem(name) || defaultValue;
}
function GM_log(message) {
console.log(message);
}
function GM_setValue(name, value) {
localStorage.setItem(name, value);
}
}
|
![]() ![]() |
Since localStorage only stores strings, I had to modify the GM_getValue wrapper:
if (typeof GM_log == 'undefined') {
unsafeWindow = window;
function GM_addStyle(css) {
var style = document.createElement('style');
style.textContent = css;
document.getElementsByTagName('head')[0].appendChild(style);
}
function GM_deleteValue(name) {
localStorage.removeItem(name);
}
function GM_getValue(name, defaultValue) {
var value = localStorage.getItem(name);
if (value == 'false')
return false;
return value || defaultValue;
}
function GM_log(message) {
console.log(message);
}
function GM_registerMenuCommand(name, funk) {
//todo
}
function GM_setValue(name, value) {
localStorage.setItem(name, value);
}
}
@sizzlemctwizzle: j/w why you're checking for strict equality. |
![]() ![]() |
Chrome doesn't support localStorage. |
![]() ![]() |
Chrome (Chromium) does support localStorage.
localStorage works fine in my dev channel Chrome, but I haven't tried it in stable (which doesn't exist for Linux yet) or unstable, so you may be right for those versions. A lot can happen in a month, though. |
![]() ![]() |
aeosynth wrote: Awesome, that's great to see. Now we just need Opera to get off it's arse and implement it and we'll have them all. :) |
![]() ![]() |
I use this: http://userscripts.org/topics/41177#posts-198077 Now we just need Opera to get off it's arse and implement it...So true... |
![]() ![]() |
aeosynth wrote:Why not? It doesn't matter either way. I'm going to use your code to implement a cross-browser version of GM_config. Your welcome to help if you want. |
![]() ![]() |
I've been playing around with the latest version of Chromium. So far scripts seem to work quite well with the new install-as-extension method. localStorage works as aeosynth mentioned. You can download the latest builds of Chrome here: http://build.chromium.org/buildbot/snapshots/ |
![]() ![]() |
So guys..... as far as I know, Chrome doesn't support accessing page variables? Pretty silly. Of course, they dub this "security". Anyone know a quick workaround? Command line switches to un-stupid this? |
![]() ![]() |
chrome doesnt have unsafeWindow ?! |
![]() ![]() |
This post has been marked as spam. Do you
or
Avindra V.G. wrote: It's weird actually; unsafeWindow does seem to be passed to the script when it is installed as an extension (Screenshot: http://img.photobucket.com/albums/v215/thegoodd... ), but I don't think it's working properly. BTW, some interesting stuff shows up when you call |




