PK !>¶ÖI• • chrome.manifestcontent InboxInfluence content/
overlay chrome://browser/content/browser.xul chrome://InboxInfluence/content/script-compiler-overlay.xul
PK !>j! çQ Q content/prefman.jsfunction InboxInfluence_PrefManager() {
var startPoint="InboxInfluence.";
var pref=Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefService).
getBranch(startPoint);
var observers={};
// whether a preference exists
this.exists=function(prefName) {
return pref.getPrefType(prefName) != 0;
}
// returns the named preference, or defaultValue if it does not exist
this.getValue=function(prefName, defaultValue) {
var prefType=pref.getPrefType(prefName);
// underlying preferences object throws an exception if pref doesn't exist
if (prefType==pref.PREF_INVALID) {
return defaultValue;
}
switch (prefType) {
case pref.PREF_STRING: return pref.getCharPref(prefName);
case pref.PREF_BOOL: return pref.getBoolPref(prefName);
case pref.PREF_INT: return pref.getIntPref(prefName);
}
}
// sets the named preference to the specified value. values must be strings,
// booleans, or integers.
this.setValue=function(prefName, value) {
var prefType=typeof(value);
switch (prefType) {
case "string":
case "boolean":
break;
case "number":
if (value % 1 != 0) {
throw new Error("Cannot set preference to non integral number");
}
break;
default:
throw new Error("Cannot set preference with datatype: " + prefType);
}
// underlying preferences object throws an exception if new pref has a
// different type than old one. i think we should not do this, so delete
// old pref first if this is the case.
if (this.exists(prefName) && prefType != typeof(this.getValue(prefName))) {
this.remove(prefName);
}
// set new value using correct method
switch (prefType) {
case "string": pref.setCharPref(prefName, value); break;
case "boolean": pref.setBoolPref(prefName, value); break;
case "number": pref.setIntPref(prefName, Math.floor(value)); break;
}
}
// deletes the named preference or subtree
this.remove=function(prefName) {
pref.deleteBranch(prefName);
}
// call a function whenever the named preference subtree changes
this.watch=function(prefName, watcher) {
// construct an observer
var observer={
observe:function(subject, topic, prefName) {
watcher(prefName);
}
};
// store the observer in case we need to remove it later
observers[watcher]=observer;
pref.QueryInterface(Components.interfaces.nsIPrefBranchInternal).
addObserver(prefName, observer, false);
}
// stop watching
this.unwatch=function(prefName, watcher) {
if (observers[watcher]) {
pref.QueryInterface(Components.interfaces.nsIPrefBranchInternal)
.removeObserver(prefName, observers[watcher]);
}
}
}
PK !>yo„§ § # content/script-compiler-overlay.xul
PK !>fÒp» » content/script-compiler.jsvar InboxInfluence_gmCompiler={
// getUrlContents adapted from Greasemonkey Compiler
// http://www.letitblog.com/code/python/greasemonkey.py.txt
// used under GPL permission
//
// most everything else below based heavily off of Greasemonkey
// http://greasemonkey.devjavu.com/
// used under GPL permission
getUrlContents: function(aUrl){
var ioService=Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var scriptableStream=Components
.classes["@mozilla.org/scriptableinputstream;1"]
.getService(Components.interfaces.nsIScriptableInputStream);
var unicodeConverter=Components
.classes["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
unicodeConverter.charset="UTF-8";
var channel=ioService.newChannel(aUrl, "UTF-8", null);
var input=channel.open();
scriptableStream.init(input);
var str=scriptableStream.read(input.available());
scriptableStream.close();
input.close();
try {
return unicodeConverter.ConvertToUnicode(str);
} catch (e) {
return str;
}
},
isGreasemonkeyable: function(url) {
var scheme=Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService)
.extractScheme(url);
return (
(scheme == "http" || scheme == "https" || scheme == "file") &&
!/hiddenWindow\.html$/.test(url)
);
},
contentLoad: function(e) {
var unsafeWin=e.target.defaultView;
if (unsafeWin.wrappedJSObject) unsafeWin=unsafeWin.wrappedJSObject;
var unsafeLoc=new XPCNativeWrapper(unsafeWin, "location").location;
var href=new XPCNativeWrapper(unsafeLoc, "href").href;
if (
InboxInfluence_gmCompiler.isGreasemonkeyable(href)
&& ( /http:\/\/mail.google.com\/mail.*/.test(href) || /https:\/\/mail.google.com\/mail.*/.test(href) || /http:\/\/mail.google.com\/a\/.*/.test(href) || /https:\/\/mail.google.com\/a\/.*/.test(href) )
&& true
) {
var script=InboxInfluence_gmCompiler.getUrlContents(
'chrome://InboxInfluence/content/InboxInfluence.js'
);
InboxInfluence_gmCompiler.injectScript(script, href, unsafeWin);
}
},
injectScript: function(script, url, unsafeContentWin) {
var sandbox, script, logger, storage, xmlhttpRequester;
var safeWin=new XPCNativeWrapper(unsafeContentWin);
sandbox=new Components.utils.Sandbox(safeWin);
var storage=new InboxInfluence_ScriptStorage();
xmlhttpRequester=new InboxInfluence_xmlhttpRequester(
unsafeContentWin, window//appSvc.hiddenDOMWindow
);
sandbox.window=safeWin;
sandbox.document=sandbox.window.document;
sandbox.unsafeWindow=unsafeContentWin;
// patch missing properties on xpcnw
sandbox.XPathResult=Components.interfaces.nsIDOMXPathResult;
// add our own APIs
sandbox.GM_addStyle=function(css) { InboxInfluence_gmCompiler.addStyle(sandbox.document, css) };
sandbox.GM_setValue=InboxInfluence_gmCompiler.hitch(storage, "setValue");
sandbox.GM_getValue=InboxInfluence_gmCompiler.hitch(storage, "getValue");
sandbox.GM_openInTab=InboxInfluence_gmCompiler.hitch(this, "openInTab", unsafeContentWin);
sandbox.GM_xmlhttpRequest=InboxInfluence_gmCompiler.hitch(
xmlhttpRequester, "contentStartRequest"
);
//unsupported
sandbox.GM_registerMenuCommand=function(){};
sandbox.GM_log=function(){};
sandbox.GM_getResourceURL=function(){};
sandbox.GM_getResourceText=function(){};
sandbox.__proto__=sandbox.window;
try {
this.evalInSandbox(
"(function(){"+script+"})()",
url,
sandbox);
} catch (e) {
var e2=new Error(typeof e=="string" ? e : e.message);
e2.fileName=script.filename;
e2.lineNumber=0;
//GM_logError(e2);
alert(e2);
}
},
evalInSandbox: function(code, codebase, sandbox) {
if (Components.utils && Components.utils.Sandbox) {
// DP beta+
Components.utils.evalInSandbox(code, sandbox);
} else if (Components.utils && Components.utils.evalInSandbox) {
// DP alphas
Components.utils.evalInSandbox(code, codebase, sandbox);
} else if (Sandbox) {
// 1.0.x
evalInSandbox(code, sandbox, codebase);
} else {
throw new Error("Could not create sandbox.");
}
},
openInTab: function(unsafeContentWin, url) {
var tabBrowser = getBrowser(), browser, isMyWindow = false;
for (var i = 0; browser = tabBrowser.browsers[i]; i++)
if (browser.contentWindow == unsafeContentWin) {
isMyWindow = true;
break;
}
if (!isMyWindow) return;
var loadInBackground, sendReferrer, referrer = null;
loadInBackground = tabBrowser.mPrefs.getBoolPref("browser.tabs.loadInBackground");
sendReferrer = tabBrowser.mPrefs.getIntPref("network.http.sendRefererHeader");
if (sendReferrer) {
var ios = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
referrer = ios.newURI(content.document.location.href, null, null);
}
tabBrowser.loadOneTab(url, referrer, null, null, loadInBackground);
},
hitch: function(obj, meth) {
var unsafeTop = new XPCNativeWrapper(unsafeContentWin, "top").top;
for (var i = 0; i < this.browserWindows.length; i++) {
this.browserWindows[i].openInTab(unsafeTop, url);
}
},
apiLeakCheck: function(allowedCaller) {
var stack=Components.stack;
var leaked=false;
do {
if (2==stack.language) {
if ('chrome'!=stack.filename.substr(0, 6) &&
allowedCaller!=stack.filename
) {
leaked=true;
break;
}
}
stack=stack.caller;
} while (stack);
return leaked;
},
hitch: function(obj, meth) {
if (!obj[meth]) {
throw "method '" + meth + "' does not exist on object '" + obj + "'";
}
var hitchCaller=Components.stack.caller.filename;
var staticArgs = Array.prototype.splice.call(arguments, 2, arguments.length);
return function() {
if (InboxInfluence_gmCompiler.apiLeakCheck(hitchCaller)) {
return;
}
// make a copy of staticArgs (don't modify it because it gets reused for
// every invocation).
var args = staticArgs.concat();
// add all the new arguments
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
// invoke the original function with the correct this obj and the combined
// list of static and dynamic arguments.
return obj[meth].apply(obj, args);
};
},
addStyle:function(doc, css) {
var head, style;
head = doc.getElementsByTagName('head')[0];
if (!head) { return; }
style = doc.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
},
onLoad: function() {
var appcontent=window.document.getElementById("appcontent");
if (appcontent && !appcontent.greased_InboxInfluence_gmCompiler) {
appcontent.greased_InboxInfluence_gmCompiler=true;
appcontent.addEventListener("DOMContentLoaded", InboxInfluence_gmCompiler.contentLoad, false);
}
},
onUnLoad: function() {
//remove now unnecessary listeners
window.removeEventListener('load', InboxInfluence_gmCompiler.onLoad, false);
window.removeEventListener('unload', InboxInfluence_gmCompiler.onUnLoad, false);
window.document.getElementById("appcontent")
.removeEventListener("DOMContentLoaded", InboxInfluence_gmCompiler.contentLoad, false);
},
}; //object InboxInfluence_gmCompiler
function InboxInfluence_ScriptStorage() {
this.prefMan=new InboxInfluence_PrefManager();
}
InboxInfluence_ScriptStorage.prototype.setValue = function(name, val) {
this.prefMan.setValue(name, val);
}
InboxInfluence_ScriptStorage.prototype.getValue = function(name, defVal) {
return this.prefMan.getValue(name, defVal);
}
window.addEventListener('load', InboxInfluence_gmCompiler.onLoad, false);
window.addEventListener('unload', InboxInfluence_gmCompiler.onUnLoad, false);
PK !>
úÙõ¡ ¡ content/xmlhttprequester.jsfunction InboxInfluence_xmlhttpRequester(unsafeContentWin, chromeWindow) {
this.unsafeContentWin = unsafeContentWin;
this.chromeWindow = chromeWindow;
}
// this function gets called by user scripts in content security scope to
// start a cross-domain xmlhttp request.
//
// details should look like:
// {method,url,onload,onerror,onreadystatechange,headers,data}
// headers should be in the form {name:value,name:value,etc}
// can't support mimetype because i think it's only used for forcing
// text/xml and we can't support that
InboxInfluence_xmlhttpRequester.prototype.contentStartRequest = function(details) {
// important to store this locally so that content cannot trick us up with
// a fancy getter that checks the number of times it has been accessed,
// returning a dangerous URL the time that we actually use it.
var url = details.url;
// make sure that we have an actual string so that we can't be fooled with
// tricky toString() implementations.
if (typeof url != "string") {
throw new Error("Invalid url: url must be of type string");
}
var ioService=Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var scheme = ioService.extractScheme(url);
// This is important - without it, GM_xmlhttpRequest can be used to get
// access to things like files and chrome. Careful.
switch (scheme) {
case "http":
case "https":
case "ftp":
this.chromeWindow.setTimeout(
InboxInfluence_gmCompiler.hitch(this, "chromeStartRequest", url, details), 0);
break;
default:
throw new Error("Invalid url: " + url);
}
}
// this function is intended to be called in chrome's security context, so
// that it can access other domains without security warning
InboxInfluence_xmlhttpRequester.prototype.chromeStartRequest=function(safeUrl, details) {
var req = new this.chromeWindow.XMLHttpRequest();
this.setupRequestEvent(this.unsafeContentWin, req, "onload", details);
this.setupRequestEvent(this.unsafeContentWin, req, "onerror", details);
this.setupRequestEvent(this.unsafeContentWin, req, "onreadystatechange", details);
req.open(details.method, safeUrl);
if (details.headers) {
for (var prop in details.headers) {
req.setRequestHeader(prop, details.headers[prop]);
}
}
req.send(details.data);
}
// arranges for the specified 'event' on xmlhttprequest 'req' to call the
// method by the same name which is a property of 'details' in the content
// window's security context.
InboxInfluence_xmlhttpRequester.prototype.setupRequestEvent =
function(unsafeContentWin, req, event, details) {
if (details[event]) {
req[event] = function() {
var responseState = {
// can't support responseXML because security won't
// let the browser call properties on it
responseText:req.responseText,
readyState:req.readyState,
responseHeaders:(req.readyState==4?req.getAllResponseHeaders():''),
status:(req.readyState==4?req.status:0),
statusText:(req.readyState==4?req.statusText:'')
}
// Pop back onto browser thread and call event handler.
// Have to use nested function here instead of GM_hitch because
// otherwise details[event].apply can point to window.setTimeout, which
// can be abused to get increased priveledges.
new XPCNativeWrapper(unsafeContentWin, "setTimeout()")
.setTimeout(function(){details[event](responseState);}, 0);
}
}
}
PK !>‰R©e‚ ‚ install.rdf
oxtail@sunlightfoundation.com
Inbox Influence
0.4.4
Sunlight Foundation's Gmail extension to add political influence information to your inbox.
Sunlight user script compiler, adapted from Greasemonkey Compiler by Anthony Lieuallen
http://arantius.com/
https://inbox.influenceexplorer.com
https://inbox.influenceexplorer.com/update.rdf
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0g1J8cDferyxJWrsjZGPu0lgs16p1vBNMgtU5u8A4EQJzU0YX8B2elVjsWSoPBlKPgYepWWaDjMWhanLj/tK3T/b7lnR3p781jH4be9bBQ1+AJZ1GXnm+zRxKxN5HbepmJqnmDL0FpZ+aPhIaGmqPWRt7lQeXMXZjmOdzuI2sVwIDAQAB
{ec8030f7-c20a-464f-9b0e-13a3a9e97384}
1.5
12.0.*
PK !>Û% Å Å content/InboxInfluence.jsvar doc = document;
var oxtailInterval = setInterval(function() {
var frame = doc.getElementById('canvas_frame');
if (frame && frame.contentDocument) {
var document = frame.contentDocument;
if (document.getElementsByClassName('w-as0').length) {
clearInterval(oxtailInterval);
var submit = document.getElementById('oxtail-submit');
if (!submit) {
var searchTable = document.querySelectorAll('.no .nn .oy8Mbf')[0];
var userArea = document.createElement('td');
searchTable.childNodes[0].appendChild(userArea);
userArea.innerHTML = userArea.innerHTML + '';
}
var loader = document.createElement('script');
loader.setAttribute('type', 'text/javascript');
loader.src = 'data:text/javascript;charset=utf-8,' + encodeURIComponent("var submit \u003D document.getElementById(\u0027oxtail\u002Dsubmit\u0027)\u003B\u000Aif (submit) {\u000A var initialOffset \u003D window.globalStorage \u003D\u003D\u003D undefined ? 0 : \u002D17\u003B\u000A var submitImg \u003D document.getElementById(\u0027oxtail\u002Dsubmit\u002Dimg\u0027)\u003B\u000A \u000A submitImg.style.top \u003D initialOffset + \u0027px\u0027\u003B\u000A \u000A submit.onmouseover \u003D function() {\u000A submitImg.style.clip \u003D \u0027rect(34px,166px,68px,0px)\u0027\u003B\u000A submitImg.style.top \u003D (initialOffset \u002D 34) + \u0027px\u0027\u003B\u000A }\u003B\u000A submit.onmouseout \u003D function() {\u000A submitImg.style.clip \u003D \u0027rect(0px,166px,34px,0px)\u0027\u003B\u000A submitImg.style.top \u003D initialOffset + \u0027px\u0027\u003B\u000A }\u003B\u000A \u000A submit.onclick \u003D (function() {\u000A if (window.poligraftParser) {\u000A window.poligraftParser.fetchData()\u003B\u000A } else {\u000A var s \u003D document.createElement(\u0027script\u0027)\u003B\u000A s.setAttribute(\u0027src\u0027, \u0027https://inbox.influenceexplorer.com/oxtail.js\u0027)\u003B\u000A s.setAttribute(\u0027type\u0027, \u0027text/javascript\u0027)\u003B\u000A submit.parentNode.appendChild(s)\u003B\u000A document.defaultView.window.poligraftEnabled \u003D true\u003B\u000A }\u000A })\u003B\u000A submit.removeAttribute(\u0027disabled\u0027)\u003B\u000A}\u000A\u000Aif (window.poligraftParser) {\u000A window.poligraftParser.loadPage()\u003B\u000A}\u000A");
document.getElementsByTagName('head')[0].appendChild(loader);
}
}
}, 250);
PK !>¶ÖI• • chrome.manifestPK !>j! çQ Q Â content/prefman.jsPK !>yo„§ § # C
content/script-compiler-overlay.xulPK !>fÒp» » + content/script-compiler.jsPK !>
úÙõ¡ ¡ 0 content/xmlhttprequester.jsPK !>‰R©e‚ ‚ ø> install.rdfPK !>Û% Å Å £D content/InboxInfluence.jsPK ß ŸP