Compatibility fixes for shared connector code (#1082)

Safari does not support generators yet. Removes coroutines
and removes the requirement for bluebird, which should
improve script injection performance.
This commit is contained in:
Adomas Ven 2016-09-06 02:49:23 +03:00 committed by Dan Stillman
parent f68ee60524
commit 5859dd6956
6 changed files with 79 additions and 50 deletions

View file

@ -84,7 +84,7 @@ Zotero.Connector_Types = new function() {
return ZOTERO_CONFIG.BOOKMARKLET_URL+"images/"+icon; return ZOTERO_CONFIG.BOOKMARKLET_URL+"images/"+icon;
} else if(Zotero.isFx) { } else if(Zotero.isFx) {
return "chrome://zotero/skin/"+icon; return "chrome://zotero/skin/"+icon;
} else if(Zotero.isChrome) { } else if(Zotero.isBrowserExt) {
return chrome.extension.getURL("images/"+icon); return chrome.extension.getURL("images/"+icon);
} else if(Zotero.isSafari) { } else if(Zotero.isSafari) {
return safari.extension.baseURI+"images/"+icon; return safari.extension.baseURI+"images/"+icon;

View file

@ -240,7 +240,7 @@ Zotero.Connector = new function() {
this.callMethod("saveItems", data, callback, tab); this.callMethod("saveItems", data, callback, tab);
return; return;
} else if(Zotero.isChrome && !Zotero.isBookmarklet) { } else if(Zotero.isBrowserExt && !Zotero.isBookmarklet) {
var self = this; var self = this;
chrome.cookies.getAll({url: tab.url}, function(cookies) { chrome.cookies.getAll({url: tab.url}, function(cookies) {
var cookieHeader = ''; var cookieHeader = '';

View file

@ -544,7 +544,7 @@ Zotero.Translate.ItemSaver.prototype = {
} }
attachment.md5 = hash; attachment.md5 = hash;
if(Zotero.isChrome && !Zotero.isBookmarklet) { if(Zotero.isBrowserExt && !Zotero.isBookmarklet) {
// In Chrome, we don't use messaging for Zotero.API.uploadAttachment, since // In Chrome, we don't use messaging for Zotero.API.uploadAttachment, since
// we can't pass ArrayBuffers to the background page // we can't pass ArrayBuffers to the background page
Zotero.API.uploadAttachment(attachment, attachmentCallback.bind(this, attachment)); Zotero.API.uploadAttachment(attachment, attachmentCallback.bind(this, attachment));

View file

@ -42,7 +42,7 @@ Zotero.Translators = new function() {
this.init = function(translators) { this.init = function(translators) {
if(!translators) { if(!translators) {
translators = []; translators = [];
if((Zotero.isChrome || Zotero.isSafari) && localStorage["translatorMetadata"]) { if((Zotero.isBrowserExt || Zotero.isSafari) && localStorage["translatorMetadata"]) {
try { try {
translators = JSON.parse(localStorage["translatorMetadata"]); translators = JSON.parse(localStorage["translatorMetadata"]);
if(typeof translators !== "object") { if(typeof translators !== "object") {
@ -196,7 +196,7 @@ Zotero.Translators = new function() {
if(j === 0) { if(j === 0) {
converterFunctions.push(null); converterFunctions.push(null);
} else if(Zotero.isChrome || Zotero.isSafari) { } else if(Zotero.isBrowserExt || Zotero.isSafari) {
// in Chrome/Safari, the converterFunction needs to be passed as JSON, so // in Chrome/Safari, the converterFunction needs to be passed as JSON, so
// just push an array with the proper and proxyHosts // just push an array with the proper and proxyHosts
converterFunctions.push([properHosts[j-1], proxyHosts[j-1]]); converterFunctions.push([properHosts[j-1], proxyHosts[j-1]]);
@ -303,7 +303,7 @@ Zotero.Translators = new function() {
} }
// Store // Store
if(Zotero.isChrome || Zotero.isSafari) { if (Zotero.isBrowserExt || Zotero.isSafari) {
var serialized = JSON.stringify(serializedTranslators); var serialized = JSON.stringify(serializedTranslators);
localStorage["translatorMetadata"] = serialized; localStorage["translatorMetadata"] = serialized;
Zotero.debug("Translators: Saved updated translator list ("+serialized.length+" characters)"); Zotero.debug("Translators: Saved updated translator list ("+serialized.length+" characters)");
@ -374,7 +374,8 @@ Zotero.Translators.CodeGetter.prototype.getCodeFor = function(i) {
const TRANSLATOR_REQUIRED_PROPERTIES = ["translatorID", "translatorType", "label", "creator", "target", const TRANSLATOR_REQUIRED_PROPERTIES = ["translatorID", "translatorType", "label", "creator", "target",
"priority", "lastUpdated"]; "priority", "lastUpdated"];
var TRANSLATOR_PASSING_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES.concat(["browserSupport", "code", "runMode"]); var TRANSLATOR_PASSING_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES
.concat(["browserSupport", "code", "runMode", "itemType"]);
var TRANSLATOR_SAVE_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES.concat(["browserSupport"]); var TRANSLATOR_SAVE_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES.concat(["browserSupport"]);
/** /**
* @class Represents an individual translator * @class Represents an individual translator

View file

@ -373,7 +373,12 @@ Zotero.Translate.Sandbox = {
var translator = translation.translator[0]; var translator = translation.translator[0];
translator = typeof translator === "object" ? translator : Zotero.Translators.get(translator); translator = typeof translator === "object" ? translator : Zotero.Translators.get(translator);
translation._loadTranslator(translator) // Zotero.Translators.get returns a value in the client and a promise in connectors
// so we normalize the value to a promise here
Zotero.Promise.resolve(translator)
.then(function(translator) {
return translation._loadTranslator(translator)
})
.then(function() { .then(function() {
if(Zotero.isFx && !Zotero.isBookmarklet) { if(Zotero.isFx && !Zotero.isBookmarklet) {
// do same origin check // do same origin check
@ -400,7 +405,7 @@ Zotero.Translate.Sandbox = {
}) })
.then(function () { .then(function () {
setDefaultHandlers(translate, translation); setDefaultHandlers(translate, translation);
sandbox = translation._sandboxManager.sandbox; var sandbox = translation._sandboxManager.sandbox;
if(!Zotero.Utilities.isEmpty(sandbox.exports)) { if(!Zotero.Utilities.isEmpty(sandbox.exports)) {
sandbox.exports.Zotero = sandbox.Zotero; sandbox.exports.Zotero = sandbox.Zotero;
sandbox = sandbox.exports; sandbox = sandbox.exports;
@ -679,7 +684,7 @@ Zotero.Translate.Sandbox = {
// refuse to save very long tags // refuse to save very long tags
if(item.tags) { if(item.tags) {
for(var i=0; i<item.tags.length; i++) { for(var i=0; i<item.tags.length; i++) {
var tag = item.tags[i]; var tag = item.tags[i],
tagString = typeof tag === "string" ? tag : tagString = typeof tag === "string" ? tag :
typeof tag === "object" ? (tag.tag || tag.name) : null; typeof tag === "object" ? (tag.tag || tag.name) : null;
if(tagString && tagString.length > 255) { if(tagString && tagString.length > 255) {
@ -1111,7 +1116,9 @@ Zotero.Translate.Base.prototype = {
// if detection returns immediately, return found translators // if detection returns immediately, return found translators
var me = this; var me = this;
return potentialTranslators.spread(function(allPotentialTranslators, properToProxyFunctions) { return potentialTranslators.then(function(result) {
var allPotentialTranslators = result[0];
var properToProxyFunctions = result[1];
me._potentialTranslators = []; me._potentialTranslators = [];
me._foundTranslators = []; me._foundTranslators = [];
@ -1266,25 +1273,35 @@ Zotero.Translate.Base.prototype = {
/** /**
* Called when translator has been retrieved and loaded * Called when translator has been retrieved and loaded
*/ */
"_translateTranslatorLoaded": Zotero.Promise.coroutine(function* () { "_translateTranslatorLoaded": Zotero.Promise.method(function() {
// set display options to default if they don't exist // set display options to default if they don't exist
if(!this._displayOptions) this._displayOptions = this._translatorInfo.displayOptions || {}; if(!this._displayOptions) this._displayOptions = this._translatorInfo.displayOptions || {};
yield this._prepareTranslation(); var loadPromise = this._prepareTranslation();
if (this.noWait) {
Zotero.debug("Translate: Beginning translation with "+this.translator[0].label); if (!loadPromise.isResolved()) {
throw new Error("Load promise is not resolved in noWait mode");
this.incrementAsyncProcesses("Zotero.Translate#translate()"); }
rest.apply(this, arguments);
// translate } else {
try { return loadPromise.then(() => rest.apply(this, arguments))
Function.prototype.apply.call(this._sandboxManager.sandbox["do"+this._entryFunctionSuffix], null, this._getParameters());
} catch(e) {
this.complete(false, e);
return false;
} }
this.decrementAsyncProcesses("Zotero.Translate#translate()"); function rest() {
Zotero.debug("Translate: Beginning translation with " + this.translator[0].label);
this.incrementAsyncProcesses("Zotero.Translate#translate()");
// translate
try {
Function.prototype.apply.call(this._sandboxManager.sandbox["do" + this._entryFunctionSuffix], null, this._getParameters());
} catch (e) {
this.complete(false, e);
return false;
}
this.decrementAsyncProcesses("Zotero.Translate#translate()");
}
}), }),
/** /**
@ -1596,13 +1613,12 @@ Zotero.Translate.Base.prototype = {
let lab = this._potentialTranslators[0].label; let lab = this._potentialTranslators[0].label;
this._loadTranslator(this._potentialTranslators[0]) this._loadTranslator(this._potentialTranslators[0])
.bind(this)
.then(function() { .then(function() {
return this._detectTranslatorLoaded(); return this._detectTranslatorLoaded();
}) }.bind(this))
.catch(function (e) { .catch(function (e) {
this.complete(false, e); this.complete(false, e);
}); }.bind(this));
}, },
/** /**
@ -2309,7 +2325,7 @@ Zotero.Translate.Export.prototype.getTranslators = function() {
/** /**
* Does the actual export, after code has been loaded and parsed * Does the actual export, after code has been loaded and parsed
*/ */
Zotero.Translate.Export.prototype._prepareTranslation = Zotero.Promise.coroutine(function* () { Zotero.Translate.Export.prototype._prepareTranslation = Zotero.Promise.method(function () {
this._progress = undefined; this._progress = undefined;
// initialize ItemGetter // initialize ItemGetter
@ -2320,6 +2336,7 @@ Zotero.Translate.Export.prototype._prepareTranslation = Zotero.Promise.coroutine
var configOptions = this._translatorInfo.configOptions || {}, var configOptions = this._translatorInfo.configOptions || {},
getCollections = configOptions.getCollections || false; getCollections = configOptions.getCollections || false;
var loadPromise = Zotero.Promise.resolve();
switch (this._export.type) { switch (this._export.type) {
case 'collection': case 'collection':
this._itemGetter.setCollection(this._export.collection, getCollections); this._itemGetter.setCollection(this._export.collection, getCollections);
@ -2328,7 +2345,7 @@ Zotero.Translate.Export.prototype._prepareTranslation = Zotero.Promise.coroutine
this._itemGetter.setItems(this._export.items); this._itemGetter.setItems(this._export.items);
break; break;
case 'library': case 'library':
yield this._itemGetter.setAll(this._export.id, getCollections); loadPromise = this._itemGetter.setAll(this._export.id, getCollections);
break; break;
default: default:
throw new Error('No export set up'); throw new Error('No export set up');
@ -2336,27 +2353,38 @@ Zotero.Translate.Export.prototype._prepareTranslation = Zotero.Promise.coroutine
} }
delete this._export; delete this._export;
// export file data, if requested if (this.noWait) {
if(this._displayOptions["exportFileData"]) { if (!loadPromise.isResolved()) {
this.location = this._itemGetter.exportFiles(this.location, this.translator[0].target); throw new Error("Load promise is not resolved in noWait mode");
} }
rest.apply(this, arguments);
// initialize IO
// this is currently hackish since we pass null callbacks to the init function (they have
// callbacks to be consistent with import, but they are synchronous, so we ignore them)
if(!this.location) {
this._io = new Zotero.Translate.IO.String(null, this.path ? this.path : "", this._sandboxManager);
this._io.init(configOptions["dataMode"], function() {});
} else if(!Zotero.Translate.IO.Write) {
throw new Error("Writing to files is not supported in this build of Zotero.");
} else { } else {
this._io = new Zotero.Translate.IO.Write(this.location); return loadPromise.then(() => rest.apply(this, arguments))
this._io.init(configOptions["dataMode"],
this._displayOptions["exportCharset"] ? this._displayOptions["exportCharset"] : null,
function() {});
} }
this._sandboxManager.importObject(this._io); function rest() {
// export file data, if requested
if(this._displayOptions["exportFileData"]) {
this.location = this._itemGetter.exportFiles(this.location, this.translator[0].target);
}
// initialize IO
// this is currently hackish since we pass null callbacks to the init function (they have
// callbacks to be consistent with import, but they are synchronous, so we ignore them)
if(!this.location) {
this._io = new Zotero.Translate.IO.String(null, this.path ? this.path : "", this._sandboxManager);
this._io.init(configOptions["dataMode"], function() {});
} else if(!Zotero.Translate.IO.Write) {
throw new Error("Writing to files is not supported in this build of Zotero.");
} else {
this._io = new Zotero.Translate.IO.Write(this.location);
this._io.init(configOptions["dataMode"],
this._displayOptions["exportCharset"] ? this._displayOptions["exportCharset"] : null,
function() {});
}
this._sandboxManager.importObject(this._io);
}
}); });
/** /**

View file

@ -29,10 +29,10 @@ var TRANSLATOR_REQUIRED_PROPERTIES = ["translatorID", "translatorType", "label",
// Properties that are preserved if present // Properties that are preserved if present
var TRANSLATOR_OPTIONAL_PROPERTIES = ["browserSupport", "minVersion", "maxVersion", var TRANSLATOR_OPTIONAL_PROPERTIES = ["browserSupport", "minVersion", "maxVersion",
"inRepository", "configOptions", "displayOptions", "inRepository", "configOptions", "displayOptions",
"hiddenPrefs"]; "hiddenPrefs", "itemType"];
// Properties that are passed from background to inject page in connector // Properties that are passed from background to inject page in connector
var TRANSLATOR_PASSING_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES. var TRANSLATOR_PASSING_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES.
concat(["browserSupport", "code", "runMode"]); concat(["browserSupport", "code", "runMode", "itemType"]);
// Properties that are saved in connector if set but not required // Properties that are saved in connector if set but not required
var TRANSLATOR_SAVE_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES.concat(["browserSupport"]); var TRANSLATOR_SAVE_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES.concat(["browserSupport"]);