From 0cd183613f5dacc85676109c3a5c6930e3632fae Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Mon, 1 Dec 2014 02:19:34 -0500 Subject: [PATCH] Fix for Firefox 34 Passing sandboxes between translators became difficult. This change loads all translators in the same sandbox, using the same ugly hack as in the connectors to get us close enough to being able to load translators into separate scopes for things to work. Conflicts: chrome/content/zotero/xpcom/translation/translate.js --- .../zotero/xpcom/translation/translate.js | 30 +++++----- .../xpcom/translation/translate_firefox.js | 55 +++++++++++++++++-- 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/chrome/content/zotero/xpcom/translation/translate.js b/chrome/content/zotero/xpcom/translation/translate.js index c521fc3093..4cbb049793 100644 --- a/chrome/content/zotero/xpcom/translation/translate.js +++ b/chrome/content/zotero/xpcom/translation/translate.js @@ -240,7 +240,7 @@ Zotero.Translate.Sandbox = { if(!Zotero.isBookmarklet) arg = JSON.parse(JSON.stringify(arg)); return translation.setSearch(arg); }; - safeTranslator.setDocument = function(arg) { return translation.setDocument(arg) }; + safeTranslator.setDocument = function(arg) { return translation.setDocument(new XPCNativeWrapper(arg)) }; var errorHandlerSet = false; safeTranslator.setHandler = function(arg1, arg2) { if(arg1 === "error") errorHandlerSet = true; @@ -249,14 +249,6 @@ Zotero.Translate.Sandbox = { try { item = item.wrappedJSObject ? item.wrappedJSObject : item; if(arg1 == "itemDone") { - var sbZotero = translate._sandboxManager.sandbox.Zotero; - if(sbZotero.wrappedJSObject) sbZotero = sbZotero.wrappedJSObject; - if(Zotero.isFx && !Zotero.isBookmarklet - && (translate instanceof Zotero.Translate.Web - || translate instanceof Zotero.Translate.Search)) { - // Necessary to get around object wrappers in Firefox - item = translate._sandboxManager._copyObject(item); - } item.complete = translate._sandboxZotero.Item.prototype.complete; } arg2(obj, item); @@ -346,7 +338,6 @@ Zotero.Translate.Sandbox = { if(!Zotero.Utilities.isEmpty(sandbox.exports)) { sandbox.exports.Zotero = sandbox.Zotero; sandbox = sandbox.exports; - if(Zotero.isFx && sandbox.wrappedJSObject) sandbox = sandbox.wrappedJSObject; } else { translate._debug("COMPAT WARNING: "+translation.translator[0].label+" does "+ "not export any properties. Only detect"+translation._entryFunctionSuffix+ @@ -389,10 +380,11 @@ Zotero.Translate.Sandbox = { if(Zotero.isFx && Zotero.platformMajorVersion >= 33) { for(var i in safeTranslator) { if (typeof(safeTranslator[i]) === "function") { - var func = safeTranslator[i]; - safeTranslator[i] = translate._sandboxManager._makeContentForwarder(function() { - func.apply(safeTranslator, this.args.wrappedJSObject); - }); + safeTranslator[i] = translate._sandboxManager._makeContentForwarder(function(func) { + return function() { + func.apply(safeTranslator, this.args.wrappedJSObject); + } + }(safeTranslator[i])); } } } @@ -442,7 +434,7 @@ Zotero.Translate.Sandbox = { */ "selectItems":function(translate, items, callback) { function transferObject(obj) { - return Zotero.isFx ? translate._sandboxManager._copyObject(obj) : obj; + return Zotero.isFx ? translate._sandboxManager.copyObject(obj) : obj; } if(Zotero.Utilities.isEmpty(items)) { @@ -1502,7 +1494,11 @@ Zotero.Translate.Base.prototype = { */ "_generateSandbox":function() { Zotero.debug("Translate: Binding sandbox to "+(typeof this._sandboxLocation == "object" ? this._sandboxLocation.document.location : this._sandboxLocation), 4); - this._sandboxManager = new Zotero.Translate.SandboxManager(this._sandboxLocation); + if (this._parentTranslator && this._parentTranslator._sandboxManager.newChild) { + this._sandboxManager = this._parentTranslator._sandboxManager.newChild(); + } else { + this._sandboxManager = new Zotero.Translate.SandboxManager(this._sandboxLocation); + } const createArrays = "['creators', 'notes', 'tags', 'seeAlso', 'attachments']"; var src = "var Zotero = {};"+ "Zotero.Item = function (itemType) {"+ @@ -2274,7 +2270,7 @@ Zotero.Translate.Search.prototype.complete = function(returnValue, error) { */ Zotero.Translate.Search.prototype._getParameters = function() { if(Zotero.isFx) { - return [this._sandboxManager._copyObject(this.search)]; + return [this._sandboxManager.copyObject(this.search)]; } return [this.search]; }; diff --git a/chrome/content/zotero/xpcom/translation/translate_firefox.js b/chrome/content/zotero/xpcom/translation/translate_firefox.js index b2de56159f..c3f69cfdf0 100644 --- a/chrome/content/zotero/xpcom/translation/translate_firefox.js +++ b/chrome/content/zotero/xpcom/translation/translate_firefox.js @@ -471,13 +471,13 @@ Zotero.Translate.SandboxManager.prototype = { } } if(passAsFirstArgument) args.unshift(passAsFirstArgument); - return me._copyObject(object[localKey].apply(object, args)); + return me.copyObject(object[localKey].apply(object, args)); }); } else { attachTo[localKey] = function() { var args = Array.prototype.slice.apply(arguments); if(passAsFirstArgument) args.unshift(passAsFirstArgument); - return me._copyObject(object[localKey].apply(object, args)); + return me.copyObject(object[localKey].apply(object, args)); }; } } else { @@ -514,7 +514,7 @@ Zotero.Translate.SandboxManager.prototype = { * @param {Object} obj * @return {Object} */ - "_copyObject":function(obj, wm) { + "copyObject":function(obj, wm) { if(!this._canCopy(obj)) return obj; if(!wm) wm = new WeakMap(); var obj2 = (obj.constructor.name === "Array" ? this.sandbox.Array() : this.sandbox.Object()); @@ -526,7 +526,7 @@ Zotero.Translate.SandboxManager.prototype = { if(this._canCopy(prop1)) { var prop2 = wm.get(prop1); if(prop2 === undefined) { - prop2 = this._copyObject(prop1, wm); + prop2 = this.copyObject(prop1, wm); wm.set(prop1, prop2); } wobj2[i] = prop2; @@ -535,6 +535,53 @@ Zotero.Translate.SandboxManager.prototype = { } } return obj2; + }, + + "newChild":function() { + return new Zotero.Translate.ChildSandboxManager(this); + } +} + +Zotero.Translate.ChildSandboxManager = function(parent) { + this._wrappedSandbox = new parent.sandbox.Object(); + this._wrappedSandbox.Zotero = new parent.sandbox.Object(); + this.sandbox = this._wrappedSandbox.wrappedJSObject; + this._parent = parent; +} +Zotero.Translate.ChildSandboxManager.prototype = { + "eval":function(code, functions, path) { + // eval in sandbox scope + if(functions) { + for(var i = 0; i < functions.length; i++) { + delete this.sandbox[functions[i]]; + } + } + this._parent.sandbox._withSandbox = this._wrappedSandbox; + Components.utils.evalInSandbox("with(_withSandbox){"+code+"};", this._parent.sandbox, "1.8", path, 1); + if(functions) { + for(var i = 0; i < functions.length; i++) { + try { + this._wrappedSandbox[functions[i]] = Components.utils.evalInSandbox(functions[i], this._parent.sandbox); + } catch(e) {} + } + } + this._parent.sandbox._withSandbox = undefined; + }, + "importObject":function(object, passAsFirstArgument, attachTo) { + if(!attachTo) attachTo = this.sandbox.Zotero; + // Zotero.debug(object); + // Zotero.debug(attachTo); + this._parent.importObject(object, passAsFirstArgument, attachTo); + // Zotero.debug(attachTo); + }, + "copyObject":function(obj) { + return this._parent.copyObject(obj); + }, + "newChild":function() { + return this._parent.newChild(); + }, + "_makeContentForwarder":function(f) { + return this._parent._makeContentForwarder(f); } }