commit a090ed22b28dd460661f97529378a73aa97009f7 Author: Mike Perry mikeperry-git@fscked.org Date: Fri Apr 15 00:51:04 2011 -0700
Move JS hooks to new JS1.8.5 hooking support.
The new JS1.8.5 hooking method appear more stable than the old ways, but they're not perfect... --- src/chrome/content/jshooks4.js | 264 +++++++++++++++++++++++++++++++++++++++ src/chrome/content/torbutton.js | 9 ++- 2 files changed, 272 insertions(+), 1 deletions(-)
diff --git a/src/chrome/content/jshooks4.js b/src/chrome/content/jshooks4.js new file mode 100644 index 0000000..60a4e1c --- /dev/null +++ b/src/chrome/content/jshooks4.js @@ -0,0 +1,264 @@ +window.__HookObjects = function() { + if (typeof(window.__tb_hooks_ran) === "boolean") { + return false; + } + + // No pref for this.. Should be mostly harmless.. + if(true) { + // Wrap in anonymous function to protect scr variables just in case. + (function () { + var origHeight = window.innerHeight; + var origWidth = window.innerWidth; + + Object.defineProperty(window.__proto__, "innerWidth", + {get: function() { return Math.round(origWidth/50.0)*50;}, + configurable: false}); + Object.defineProperty(window.__proto__, "innerHeight", + {get: function() { return Math.round(origHeight/50.0)*50;}, + configurable: false}); + Object.defineProperty(window.__proto__, "outerWidth", + {get: function() { return Math.round(origWidth/50.0)*50;}, + configurable: false}); + Object.defineProperty(window.__proto__, "outerHeight", + {get: function() { return Math.round(origHeight/50.0)*50;}, + configurable: false}); + Object.defineProperty(window.__proto__, "screenX", + {get: function() { return 0;}, + configurable: false}); + Object.defineProperty(window.__proto__, "screenY", + {get: function() { return 0;}, + configurable: false}); + Object.defineProperty(window.__proto__, "pageXOffset", + {get: function() { return 0;}, + configurable: false}); + Object.defineProperty(window.__proto__, "pageYOffset", + {get: function() { return 0;}, + configurable: false}); + + // We can't define individual getters/setters for window.screen + // for some reason. works in html but not in these hooks.. No idea why + + var scr = new Object(); + var origScr = window.screen; + scr.__defineGetter__("height", function() { return window.innerHeight; }); + scr.__defineGetter__("width", function() { return window.innerWidth; }); + + scr.__defineGetter__("availTop", function() { return 0;}); + scr.__defineGetter__("availLeft", function() { return 0;}); + + scr.__defineGetter__("top", function() { return 0;}); + scr.__defineGetter__("left", function() { return 0;}); + + scr.__defineGetter__("availHeight", function() { return window.innerHeight;}); + scr.__defineGetter__("availWidth", function() { return window.innerWidth;}); + + scr.__defineGetter__("colorDepth", function() { return origScr.colorDepth;}); + scr.__defineGetter__("pixelDepth", function() { return origScr.pixelDepth;}); + + scr.__defineGetter__("availTop", function() { return 0;}); + scr.__defineGetter__("availLeft", function() { return 0;}); + + Object.defineProperty(window.__proto__, "screen", + {get: function() { return scr;}, + configurable: false}); + + })(); + + } + + if(window.__tb_hook_date == true) { // don't feel like indenting this + // XXX: events should not have timeStamp, unless they are of type MozBeforePaint? + + /* Timezone fix for http://gemal.dk/browserspy/css.html */ + var reparseDate = function(d, str) { + /* Rules: + * - If they specify a timezone, it is converted to local + * time. All getter fucntions then convert properly to + * UTC. No mod needed. + * - If they specify UTC timezone, then it is converted + * to local time. All getter functions then convert back. + * No mod needed. + * - If they specify NO timezone, it is local time. + * The UTC conversion then reveals the offset. Fix. + */ + + /* Step 1: Remove everything inside ()'s (they are "comments") */ + var s = str.toLowerCase(); + var re = new RegExp('\(.*\)', "gm"); + s = s.replace(re, ""); + + /* Step 2: Look for +/-. If found, do nothing */ + if(s.indexOf("+") == -1 && s.indexOf("-") == -1) { + /* Step 3: Look for timezone string from + * http://lxr.mozilla.org/seamonkey/source/js/src/jsdate.c + */ + if(s.indexOf(" gmt") == -1 && s.indexOf(" ut") == -1 && + s.indexOf(" est") == -1 && s.indexOf(" edt") == -1 && + s.indexOf(" cst") == -1 && s.indexOf(" cdt") == -1 && + s.indexOf(" mst") == -1 && s.indexOf(" mdt") == -1 && + s.indexOf(" pst") == -1 && s.indexOf(" pdt")) { + /* No timezone specified. Adjust. */ + d.setTime(d.getTime()-(d.getTimezoneOffset()*60000)); + } + } + } + + // XXX: Each origin should have its own unique offset from the real date + // XXX: Subsequent calls to the ms timer should be monotonically increasing, but randomized + + var origDate = window.Date; + var newDate = function() { + /* DO NOT make 'd' a member! EvilCode will use it! */ + var d; + var a = arguments; + /* apply doesn't seem to work for constructors :( */ + if(arguments.length == 0) d=new origDate(); + if(arguments.length == 1) d=new origDate(a[0]); + if(arguments.length == 3) d=new origDate(a[0],a[1],a[2]); + if(arguments.length == 4) d=new origDate(a[0],a[1],a[2],a[3]); + if(arguments.length == 5) d=new origDate(a[0],a[1],a[2],a[3],a[4]); + if(arguments.length == 6) d=new origDate(a[0],a[1],a[2],a[3],a[4],a[5]); + if(arguments.length == 7) d=new origDate(a[0],a[1],a[2],a[3],a[4],a[5],a[6]); + if(arguments.length > 7) d=new origDate(); + + if(arguments.length > 0) { + if((arguments.length == 1) && typeof(a[0]) == "string") { + reparseDate(d,a[0]); + } else if(arguments.length > 1) { + /* Numerical value. No timezone given, adjust. */ + d.setTime(d.getTime()-(d.getTimezoneOffset()*60000)); + } + } + + // XXX: the native valueOf seems to sometimes return toString and + // sometimes return getTime depending on context (which we can't detect) + // It seems as though we can't win here.. + window.Date.prototype.valueOf=function(){return d.getTime()}; + window.Date.prototype.getTime=function(){return d.getTime();} /* UTC already */ + window.Date.prototype.getFullYear=function(){return d.getUTCFullYear();} + window.Date.prototype.getYear=function() {return d.getYear();} + window.Date.prototype.getMonth=function(){return d.getUTCMonth();} + window.Date.prototype.getDate=function() {return d.getUTCDate();} + window.Date.prototype.getDay=function() {return d.getUTCDay();} + window.Date.prototype.getHours=function(){return d.getUTCHours();} + window.Date.prototype.getMinutes=function(){return d.getUTCMinutes();} + window.Date.prototype.getSeconds=function(){return d.getUTCSeconds();} + window.Date.prototype.getMilliseconds=function(){return d.getUTCMilliseconds();} + window.Date.prototype.getTimezoneOffset=function(){return 0;} + + window.Date.prototype.setTime = + function(x) {return d.setTime(x);} + window.Date.prototype.setFullYear=function(x){return d.setUTCFullYear(x);} + window.Date.prototype.setYear=function(x){return d.setYear(x);} + window.Date.prototype.setMonth=function(x){return d.setUTCMonth(x);} + window.Date.prototype.setDate=function(x){return d.setUTCDate(x);} + window.Date.prototype.setDay=function(x){return d.setUTCDay(x);} + window.Date.prototype.setHours=function(x){return d.setUTCHours(x);} + window.Date.prototype.setMinutes=function(x){return d.setUTCMinutes(x);} + window.Date.prototype.setSeconds=function(x){return d.setUTCSeconds(x);} + window.Date.prototype.setMilliseconds= + function(x) {return d.setUTCMilliseconds(x);} + + window.Date.prototype.getUTCFullYear=function(){return d.getUTCFullYear();} + window.Date.prototype.getUTCMonth=function(){return d.getUTCMonth();} + window.Date.prototype.getUTCDate=function() {return d.getUTCDate();} + window.Date.prototype.getUTCDay=function() {return d.getUTCDay();} + window.Date.prototype.getUTCHours=function(){return d.getUTCHours();} + window.Date.prototype.getUTCMinutes=function(){return d.getUTCMinutes();} + window.Date.prototype.getUTCSeconds=function(){return d.getUTCSeconds();} + window.Date.prototype.getUTCMilliseconds= + function(){return d.getUTCMilliseconds();} + + window.Date.prototype.setUTCFullYear=function(x){return d.setUTCFullYear(x);} + window.Date.prototype.setUTCMonth=function(x){return d.setUTCMonth(x);} + window.Date.prototype.setUTCDate=function(x){return d.setUTCDate(x);} + window.Date.prototype.setUTCDay=function(x){return d.setUTCDay(x);} + window.Date.prototype.setUTCHours=function(x){return d.setUTCHours(x);} + window.Date.prototype.setUTCMinutes=function(x){return d.setUTCMinutes(x);} + window.Date.prototype.setUTCSeconds=function(x){return d.setUTCSeconds(x);} + window.Date.prototype.setUTCMilliseconds= + function(x) {return d.setUTCMilliseconds(x);} + + window.Date.prototype.toUTCString=function(){return d.toUTCString();} + window.Date.prototype.toGMTString=function(){return d.toGMTString();} + window.Date.prototype.toString=function(){return d.toUTCString();} + window.Date.prototype.toLocaleString=function(){return d.toUTCString();} + + /* Fuck 'em if they can't take a joke: */ + window.Date.prototype.toLocaleTimeString=function(){return d.toUTCString();} + window.Date.prototype.toLocaleDateString=function(){return d.toUTCString();} + window.Date.prototype.toDateString=function(){return d.toUTCString();} + window.Date.prototype.toTimeString=function(){return d.toUTCString();} + + /* Hack to solve the problem of multiple date objects + * all sharing the same lexically scoped d every time a new one is + * created. This hack creates a fresh new prototype reference for + * the next object to use with a different d binding. + * It doesn't break stuff because at the start of this function, + * the interpreter grabbed a reference to Date.prototype. During + * this function we modified Date.prototype to create the new methods + * with the lexically scoped d reference. + */ + + // valueOf gets called for implicit string conversion?? + window.Date.prototype = window.eval(window.Object.prototype.toSource()); + return d.toUTCString(); + } + + // Need to do this madness so that we use the window's notion of Function + // for the constructor. If this is not done, then changes to Function + // and Object in the real window are not propogated to Date (for example, + // to extend the Date class with extra functions via a generic inheritance + // framework added onto Object - this is done by livejournal and others) + var newWrappedDate = window.eval("function() { return newDate(); }"); + + newWrappedDate.parse=function(s) { + var d = new origDate(s); + if(typeof(s) == "string") reparseDate(d, s); + return d.getTime(); + } + + newWrappedDate.now=function(){return origDate.now();} + newWrappedDate.UTC=function(){return origDate.apply(origDate, arguments); } + + // d = new Date(); + // d.__proto__ === Date.prototype + // d.constructor === Date + // d.__proto__ === d.constructor.prototype + // Date.prototype.__proto__ === Date.prototype.constructor.prototype + // window.__proto__ === Window.prototypea + + Object.defineProperty(window.__proto__, "Date", + {get: function() { return newWrappedDate;}, + configurable: false}); + + } // window.__tb_hook_date == true + + //Object.defineProperty(window.Components.__proto__, "lookupMethod", + // {get: function() { return function (a,b) { return function() { return a[b]; }; };}, + // configurable: false}); + + return true; +} + +if (typeof(window.__HookObjects) != "undefined") { + var res = 23; + + if(!window.__HookObjects()) { + res = 13; + } + + window.__HookObjects = undefined; + delete window['__HookObjects']; + delete window['__CheckFlag']; + delete window['__tb_set_uagent']; + delete window['__tb_oscpu']; + delete window['__tb_platform']; + delete window['__tb_productSub']; + + window.__tb_hooks_ran = true; + + res; // Secret result code. +} else { + 42; +} diff --git a/src/chrome/content/torbutton.js b/src/chrome/content/torbutton.js index 676c311..9f5c5fe 100644 --- a/src/chrome/content/torbutton.js +++ b/src/chrome/content/torbutton.js @@ -3431,6 +3431,7 @@ function torbutton_do_startup() } var tor_enabled = torbutton_check_status();
+ // XXX: There is a timer at startup. this is not enough.. if(m_tb_ff35 && m_tb_prefs.getBoolPref("extensions.torbutton.disable_livemarks")) { var livemarks = Cc["@mozilla.org/browser/livemark-service;2"]. @@ -3668,8 +3669,14 @@ function torbutton_init_jshooks() { torbutton_log(2, "torbutton_init_jshooks()"); var nsio = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService); - var chan = nsio.newChannel("chrome://torbutton/content/jshooks.js", + var chan = null; + if (m_tb_ff4) { + chan = nsio.newChannel("chrome://torbutton/content/jshooks4.js", null, null); + } else { + chan = nsio.newChannel("chrome://torbutton/content/jshooks.js", + null, null); + } var istream = Components.classes["@mozilla.org/scriptableinputstream;1"]. createInstance(Components.interfaces.nsIScriptableInputStream);
tor-commits@lists.torproject.org