Created
September 27, 2010 05:01
-
-
Save johan/598628 to your computer and use it in GitHub Desktop.
Lets a GM script safely read variables from the content scope (untested)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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