Skip to content

Instantly share code, notes, and snippets.

@johan
Created September 27, 2010 05:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save johan/598628 to your computer and use it in GitHub Desktop.
Save johan/598628 to your computer and use it in GitHub Desktop.
Lets a GM script safely read variables from the content scope (untested)
// Query page javascript for the identifier "name", and call callback(value),
// when found, or undefined, if not found or some error occurred. This works
// only for values that can be JSON serialized -- numbers, strings, booleans,
// null, or nested structures like Arrays and Objects that only contain above
// mentioned types of data.
function queryContentVar(name, callback) {
// makes a random 20-char lowercase id
function random() {
var rand = '';
while (rand.length < 20)
rand += String.fromCharCode(97 + Math.random() * 26 | 0);
return rand;
}
// Creates a mostly anonymous <meta> tag in the <head> section, giving it a
// secret id we'll use for messaging back and forth with content space, and
// fires pageInit() in the page scope (to listen and respond to queries from
// us about variables) and registers reply() for answers from it at this end.
function privInit() {
var node = document.createElement('meta'), secret,
head = document.getElementsByTagName('head')[0];
node.id = secret = random();
node.addEventListener(id, reply, false);
head.appendChild(node);
location.href = 'javascript:('+ pageInit +')('+ JSON.stringify(secret) +')';
return node;
}
// Grabs the meta tag, anonymizes it and listens for incoming queries from us.
function pageInit(secret) {
// Replaces given <meta content="variable.name"> with <meta content="value">
// (after JSON encoding it) and then alerts the caller to grab the response.
function reply() {
var name = node.getAttribute('content'),
mesg = document.createEvent('Events'),
val;
try {
val = eval(node.getAttribute('content'));
val = JSON.stringify(val);
} catch(e) { val = ''; }
node.setAttribute('content', val);
mesg.initEvent(secret, true, false);
node.dispatchEvent(mesg);
}
var node = document.getElementById(secret);
node.addEventListener(secret + '?', reply, false);
node.removeAttribute('id');
}
var self = queryContentVar,
node = self.node = self.node || privInit(),
id = self.secret = self.secret || node.id,
mesg = document.createEvent('Events');
mesg.initEvent(secret + '?', true, false);
node.setAttribute('content', name);
self.callback = callback;
node.dispatchEvent(mesg);
// Picks up the response from content space, decodes it, passes it on to given
// response callback and resets everything (just in case) to handle new calls.
function reply() {
var cb = self.callback,
is = node.getAttribute('content');
if (cb) cb(is === '' ? undefined : JSON.parse(is));
node.removeAttribute('name');
delete self.callback;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment